diff options
Diffstat (limited to 'src')
156 files changed, 10360 insertions, 4018 deletions
diff --git a/src/Make_mvc.mak b/src/Make_mvc.mak index 4db2298..4d03a72 100644 --- a/src/Make_mvc.mak +++ b/src/Make_mvc.mak @@ -157,10 +157,55 @@ # you can set DEFINES on the command line, e.g., # nmake -f Make_mvc.mvc "DEFINES=-DEMACS_TAGS" +RM= del /f /q +PS= powershell.exe + +PSFLAGS= -NoLogo -NoProfile -Command + +!IF ![$(PS) $(PSFLAGS) try{Out-File -FilePath '.\major.tmp' -InputObject \ + \"MAJOR=$$(((Select-String -Pattern 'VIM_VERSION_MAJOR\s+\d{1,2}' \ + -Path '.\version.h').Line[-2..-1^]-join '').Trim())\"} \ + catch{exit 1}] +! INCLUDE .\major.tmp +! IF [$(RM) .\major.tmp] +! ENDIF +!ELSE +# Change this value for the new version +MAJOR= 9 +!ENDIF + +!IF ![$(PS) $(PSFLAGS) try{Out-File -FilePath '.\minor.tmp' -InputObject \ + \"MINOR=$$(((Select-String -Pattern 'VIM_VERSION_MINOR\s+\d{1,2}' \ + -Path '.\version.h').Line[-2..-1^]-join '').Trim())\"} \ + catch{exit 1}] +! INCLUDE .\minor.tmp +! IF [$(RM) .\minor.tmp] +! ENDIF +!ELSE +# Change this value for the new version +MINOR= 1 +!ENDIF + +!IF ![$(PS) $(PSFLAGS) try{Out-File -FilePath '.\patchlvl.tmp' -InputObject \ + \"PATCHLEVEL=$$([decimal^]((Get-Content -Path '.\version.c' \ + -TotalCount ((Select-String -Pattern 'static int included_patches' \ + -Path '.\version.c').LineNumber+3))[-1^]).Trim().TrimEnd(','))\"} \ + catch{exit 1}] +! INCLUDE .\patchlvl.tmp +! IF [$(RM) .\patchlvl.tmp] +! ENDIF +!ENDIF + + # Build on Windows NT/XP TARGETOS = WINNT +!IFDEF PATCHLEVEL +RCFLAGS= -DVIM_VERSION_PATCHLEVEL=$(PATCHLEVEL) +!ENDIF + + !if "$(VIMDLL)" == "yes" GUI = yes !endif @@ -591,7 +636,7 @@ OPTFLAG = $(OPTFLAG) /GL ! endif CFLAGS = $(CFLAGS) $(OPTFLAG) -DNDEBUG $(CPUARG) -RCFLAGS = -DNDEBUG +RCFLAGS = $(RCFLAGS) -DNDEBUG ! ifdef USE_MSVCRT CFLAGS = $(CFLAGS) /MD LIBC = msvcrt.lib @@ -607,7 +652,7 @@ VIM = vimd DEBUGINFO = /ZI ! endif CFLAGS = $(CFLAGS) -D_DEBUG -DDEBUG /Od -RCFLAGS = -D_DEBUG -DDEBUG +RCFLAGS = $(RCFLAGS) -D_DEBUG -DDEBUG # The /fixed:no is needed for Quantify. LIBC = /fixed:no ! ifdef USE_MSVCRT @@ -621,7 +666,7 @@ LIBC = $(LIBC) libcmtd.lib !endif # DEBUG # Visual Studio 2005 has 'deprecated' many of the standard CRT functions -CFLAGS_DEPR = /D_CRT_SECURE_NO_DEPRECATE /D_CRT_NONSTDC_NO_DEPRECATE +CFLAGS_DEPR = -D_CRT_SECURE_NO_DEPRECATE -D_CRT_NONSTDC_NO_DEPRECATE CFLAGS = $(CFLAGS) $(CFLAGS_DEPR) !include Make_all.mak @@ -1276,6 +1321,10 @@ $(OUTDIR): CFLAGS_INST = /nologo /O2 -DNDEBUG -DWIN32 -DWINVER=$(WINVER) -D_WIN32_WINNT=$(WINVER) $(CFLAGS_DEPR) +!IFDEF PATCHLEVEL +CFLAGS_INST= $(CFLAGS_INST) -DVIM_VERSION_PATCHLEVEL=$(PATCHLEVEL) +!ENDIF + install.exe: dosinst.c dosinst.h version.h $(CC) $(CFLAGS_INST) dosinst.c kernel32.lib shell32.lib \ user32.lib ole32.lib advapi32.lib uuid.lib \ diff --git a/src/Makefile b/src/Makefile index 33903d3..29f63dc 100644 --- a/src/Makefile +++ b/src/Makefile @@ -2341,6 +2341,7 @@ installrtbase: $(HELPSOURCE)/vim.1 $(DEST_VIM) $(VIMTARGET) $(DEST_RT) \ $(DEST_SYN) $(DEST_SYN)/modula2 $(DEST_SYN)/modula2/opt $(DEST_SYN)/shared \ $(DEST_IND) $(DEST_FTP) \ $(DEST_AUTO) $(DEST_AUTO)/dist $(DEST_AUTO)/xml $(DEST_AUTO)/zig \ + $(DEST_AUTO)/rust $(DEST_AUTO)/cargo \ $(DEST_IMPORT) $(DEST_IMPORT)/dist \ $(DEST_PLUG) $(DEST_TUTOR) $(DEST_SPELL) $(DEST_COMP) -$(SHELL) ./installman.sh install $(DEST_MAN) "" $(INSTALLMANARGS) @@ -2428,6 +2429,10 @@ installrtbase: $(HELPSOURCE)/vim.1 $(DEST_VIM) $(VIMTARGET) $(DEST_RT) \ cd $(DEST_AUTO)/xml; chmod $(HELPMOD) *.vim cd $(AUTOSOURCE)/zig; $(INSTALL_DATA) *.vim $(DEST_AUTO)/zig cd $(DEST_AUTO)/zig; chmod $(HELPMOD) *.vim + cd $(AUTOSOURCE)/cargo; $(INSTALL_DATA) *.vim $(DEST_AUTO)/cargo + cd $(DEST_AUTO)/cargo; chmod $(HELPMOD) *.vim + cd $(AUTOSOURCE)/rust; $(INSTALL_DATA) *.vim $(DEST_AUTO)/rust + cd $(DEST_AUTO)/rust; chmod $(HELPMOD) *.vim # install the standard import files cd $(IMPORTSOURCE)/dist; $(INSTALL_DATA) *.vim $(DEST_IMPORT)/dist cd $(DEST_IMPORT)/dist; chmod $(HELPMOD) *.vim @@ -2669,6 +2674,7 @@ $(DESTDIR)$(exec_prefix) $(DEST_BIN) \ $(DEST_LANG) $(DEST_KMAP) $(DEST_COMP) $(DEST_MACRO) \ $(DEST_PACK) $(DEST_TOOLS) $(DEST_TUTOR) $(DEST_SPELL) \ $(DEST_AUTO) $(DEST_AUTO)/dist $(DEST_AUTO)/xml $(DEST_AUTO)/zig \ + $(DEST_AUTO)/cargo $(DEST_AUTO)/rust \ $(DEST_IMPORT) $(DEST_IMPORT)/dist $(DEST_PLUG): $(MKDIR_P) $@ -chmod $(DIRMOD) $@ @@ -2859,10 +2865,10 @@ uninstall_runtime: -rmdir $(DEST_SYN) $(DEST_IND) -rm -rf $(DEST_FTP)/*.vim $(DEST_FTP)/README.txt $(DEST_FTP)/logtalk.dict -rm -f $(DEST_AUTO)/*.vim $(DEST_AUTO)/README.txt - -rm -f $(DEST_AUTO)/dist/*.vim $(DEST_AUTO)/xml/*.vim $(DEST_AUTO)/zig/*.vim + -rm -f $(DEST_AUTO)/dist/*.vim $(DEST_AUTO)/xml/*.vim $(DEST_AUTO)/zig/*.vim $(DEST_AUTO)/cargo/*.vim $(DEST_AUTO)/rust/*.vim -rm -f $(DEST_IMPORT)/dist/*.vim -rm -f $(DEST_PLUG)/*.vim $(DEST_PLUG)/README.txt - -rmdir $(DEST_FTP) $(DEST_AUTO)/dist $(DEST_AUTO)/xml $(DEST_AUTO)/zig $(DEST_AUTO) + -rmdir $(DEST_FTP) $(DEST_AUTO)/dist $(DEST_AUTO)/xml $(DEST_AUTO)/zig $(DEST_AUTO)/cargo $(DEST_AUTO)/rust $(DEST_AUTO) -rmdir $(DEST_IMPORT)/dist $(DEST_IMPORT) -rmdir $(DEST_PLUG) $(DEST_RT) # This will fail when other Vim versions are installed, no worries. diff --git a/src/auto/configure b/src/auto/configure index 9712104..0e0cf8e 100755 --- a/src/auto/configure +++ b/src/auto/configure @@ -15965,16 +15965,16 @@ printf "%s\n" "yes" >&6; } printf "%s\n" "no" >&6; } fi - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if msgfmt supports --no-convert" >&5 -printf %s "checking if msgfmt supports --no-convert... " >&6; } + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $MSGFMT supports --no-convert" >&5 +printf %s "checking if $MSGFMT supports --no-convert... " >&6; } if "$MSGFMT" --help | grep -q -- '--no-convert' >/dev/null; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } - MSGFMTCMD="OLD_PO_FILE_INPUT=yes msgfmt --no-convert -v" + MSGFMTCMD="OLD_PO_FILE_INPUT=yes $MSGFMT --no-convert -v" else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } - MSGFMTCMD="OLD_PO_FILE_INPUT=yes msgfmt -v" + MSGFMTCMD="OLD_PO_FILE_INPUT=yes $MSGFMT -v" fi fi diff --git a/src/autocmd.c b/src/autocmd.c index 8e43b34..bce57cb 100644 --- a/src/autocmd.c +++ b/src/autocmd.c @@ -74,152 +74,166 @@ typedef struct AutoPat char last; // last pattern for apply_autocmds() } AutoPat; -static struct event_name -{ - char *name; // event name - event_T event; // event number -} event_names[] = -{ - {"BufAdd", EVENT_BUFADD}, - {"BufCreate", EVENT_BUFADD}, - {"BufDelete", EVENT_BUFDELETE}, - {"BufEnter", EVENT_BUFENTER}, - {"BufFilePost", EVENT_BUFFILEPOST}, - {"BufFilePre", EVENT_BUFFILEPRE}, - {"BufHidden", EVENT_BUFHIDDEN}, - {"BufLeave", EVENT_BUFLEAVE}, - {"BufNew", EVENT_BUFNEW}, - {"BufNewFile", EVENT_BUFNEWFILE}, - {"BufRead", EVENT_BUFREADPOST}, - {"BufReadCmd", EVENT_BUFREADCMD}, - {"BufReadPost", EVENT_BUFREADPOST}, - {"BufReadPre", EVENT_BUFREADPRE}, - {"BufUnload", EVENT_BUFUNLOAD}, - {"BufWinEnter", EVENT_BUFWINENTER}, - {"BufWinLeave", EVENT_BUFWINLEAVE}, - {"BufWipeout", EVENT_BUFWIPEOUT}, - {"BufWrite", EVENT_BUFWRITEPRE}, - {"BufWritePost", EVENT_BUFWRITEPOST}, - {"BufWritePre", EVENT_BUFWRITEPRE}, - {"BufWriteCmd", EVENT_BUFWRITECMD}, - {"CmdlineChanged", EVENT_CMDLINECHANGED}, - {"CmdlineEnter", EVENT_CMDLINEENTER}, - {"CmdlineLeave", EVENT_CMDLINELEAVE}, - {"CmdwinEnter", EVENT_CMDWINENTER}, - {"CmdwinLeave", EVENT_CMDWINLEAVE}, - {"CmdUndefined", EVENT_CMDUNDEFINED}, - {"ColorScheme", EVENT_COLORSCHEME}, - {"ColorSchemePre", EVENT_COLORSCHEMEPRE}, - {"CompleteChanged", EVENT_COMPLETECHANGED}, - {"CompleteDone", EVENT_COMPLETEDONE}, - {"CompleteDonePre", EVENT_COMPLETEDONEPRE}, - {"CursorHold", EVENT_CURSORHOLD}, - {"CursorHoldI", EVENT_CURSORHOLDI}, - {"CursorMoved", EVENT_CURSORMOVED}, - {"CursorMovedI", EVENT_CURSORMOVEDI}, - {"DiffUpdated", EVENT_DIFFUPDATED}, - {"DirChanged", EVENT_DIRCHANGED}, - {"DirChangedPre", EVENT_DIRCHANGEDPRE}, - {"EncodingChanged", EVENT_ENCODINGCHANGED}, - {"ExitPre", EVENT_EXITPRE}, - {"FileEncoding", EVENT_ENCODINGCHANGED}, - {"FileAppendPost", EVENT_FILEAPPENDPOST}, - {"FileAppendPre", EVENT_FILEAPPENDPRE}, - {"FileAppendCmd", EVENT_FILEAPPENDCMD}, - {"FileChangedShell",EVENT_FILECHANGEDSHELL}, - {"FileChangedShellPost",EVENT_FILECHANGEDSHELLPOST}, - {"FileChangedRO", EVENT_FILECHANGEDRO}, - {"FileReadPost", EVENT_FILEREADPOST}, - {"FileReadPre", EVENT_FILEREADPRE}, - {"FileReadCmd", EVENT_FILEREADCMD}, - {"FileType", EVENT_FILETYPE}, - {"FileWritePost", EVENT_FILEWRITEPOST}, - {"FileWritePre", EVENT_FILEWRITEPRE}, - {"FileWriteCmd", EVENT_FILEWRITECMD}, - {"FilterReadPost", EVENT_FILTERREADPOST}, - {"FilterReadPre", EVENT_FILTERREADPRE}, - {"FilterWritePost", EVENT_FILTERWRITEPOST}, - {"FilterWritePre", EVENT_FILTERWRITEPRE}, - {"FocusGained", EVENT_FOCUSGAINED}, - {"FocusLost", EVENT_FOCUSLOST}, - {"FuncUndefined", EVENT_FUNCUNDEFINED}, - {"GUIEnter", EVENT_GUIENTER}, - {"GUIFailed", EVENT_GUIFAILED}, - {"InsertChange", EVENT_INSERTCHANGE}, - {"InsertEnter", EVENT_INSERTENTER}, - {"InsertLeave", EVENT_INSERTLEAVE}, - {"InsertLeavePre", EVENT_INSERTLEAVEPRE}, - {"InsertCharPre", EVENT_INSERTCHARPRE}, - {"MenuPopup", EVENT_MENUPOPUP}, - {"ModeChanged", EVENT_MODECHANGED}, - {"OptionSet", EVENT_OPTIONSET}, - {"QuickFixCmdPost", EVENT_QUICKFIXCMDPOST}, - {"QuickFixCmdPre", EVENT_QUICKFIXCMDPRE}, - {"QuitPre", EVENT_QUITPRE}, - {"RemoteReply", EVENT_REMOTEREPLY}, - {"SafeState", EVENT_SAFESTATE}, - {"SafeStateAgain", EVENT_SAFESTATEAGAIN}, - {"SessionLoadPost", EVENT_SESSIONLOADPOST}, - {"ShellCmdPost", EVENT_SHELLCMDPOST}, - {"ShellFilterPost", EVENT_SHELLFILTERPOST}, - {"SigUSR1", EVENT_SIGUSR1}, - {"SourceCmd", EVENT_SOURCECMD}, - {"SourcePre", EVENT_SOURCEPRE}, - {"SourcePost", EVENT_SOURCEPOST}, - {"SpellFileMissing",EVENT_SPELLFILEMISSING}, - {"StdinReadPost", EVENT_STDINREADPOST}, - {"StdinReadPre", EVENT_STDINREADPRE}, - {"SwapExists", EVENT_SWAPEXISTS}, - {"Syntax", EVENT_SYNTAX}, - {"TabNew", EVENT_TABNEW}, - {"TabClosed", EVENT_TABCLOSED}, - {"TabEnter", EVENT_TABENTER}, - {"TabLeave", EVENT_TABLEAVE}, - {"TermChanged", EVENT_TERMCHANGED}, - {"TerminalOpen", EVENT_TERMINALOPEN}, - {"TerminalWinOpen", EVENT_TERMINALWINOPEN}, - {"TermResponse", EVENT_TERMRESPONSE}, - {"TermResponseAll", EVENT_TERMRESPONSEALL}, - {"TextChanged", EVENT_TEXTCHANGED}, - {"TextChangedI", EVENT_TEXTCHANGEDI}, - {"TextChangedP", EVENT_TEXTCHANGEDP}, - {"TextChangedT", EVENT_TEXTCHANGEDT}, - {"User", EVENT_USER}, - {"VimEnter", EVENT_VIMENTER}, - {"VimLeave", EVENT_VIMLEAVE}, - {"VimLeavePre", EVENT_VIMLEAVEPRE}, - {"WinNewPre", EVENT_WINNEWPRE}, - {"WinNew", EVENT_WINNEW}, - {"WinClosed", EVENT_WINCLOSED}, - {"WinEnter", EVENT_WINENTER}, - {"WinLeave", EVENT_WINLEAVE}, - {"WinResized", EVENT_WINRESIZED}, - {"WinScrolled", EVENT_WINSCROLLED}, - {"VimResized", EVENT_VIMRESIZED}, - {"TextYankPost", EVENT_TEXTYANKPOST}, - {"VimSuspend", EVENT_VIMSUSPEND}, - {"VimResume", EVENT_VIMRESUME}, - {NULL, (event_T)0} +// +// special cases: +// BufNewFile and BufRead are searched for ALOT (especially at startup) +// so we pre-determine their index into the event_tab[] table for fast access. +// Keep these values in sync with event_tab[]! +#define BUFNEWFILE_INDEX 9 +#define BUFREAD_INDEX 10 + +// must be sorted by the 'value' field because it is used by bsearch()! +static keyvalue_T event_tab[] = { + KEYVALUE_ENTRY(EVENT_BUFADD, "BufAdd"), + KEYVALUE_ENTRY(EVENT_BUFADD, "BufCreate"), + KEYVALUE_ENTRY(EVENT_BUFDELETE, "BufDelete"), + KEYVALUE_ENTRY(EVENT_BUFENTER, "BufEnter"), + KEYVALUE_ENTRY(EVENT_BUFFILEPOST, "BufFilePost"), + KEYVALUE_ENTRY(EVENT_BUFFILEPRE, "BufFilePre"), + KEYVALUE_ENTRY(EVENT_BUFHIDDEN, "BufHidden"), + KEYVALUE_ENTRY(EVENT_BUFLEAVE, "BufLeave"), + KEYVALUE_ENTRY(EVENT_BUFNEW, "BufNew"), + KEYVALUE_ENTRY(EVENT_BUFNEWFILE, "BufNewFile"), // BUFNEWFILE_INDEX + KEYVALUE_ENTRY(EVENT_BUFREADPOST, "BufRead"), // BUFREAD_INDEX + KEYVALUE_ENTRY(EVENT_BUFREADCMD, "BufReadCmd"), + KEYVALUE_ENTRY(EVENT_BUFREADPOST, "BufReadPost"), + KEYVALUE_ENTRY(EVENT_BUFREADPRE, "BufReadPre"), + KEYVALUE_ENTRY(EVENT_BUFUNLOAD, "BufUnload"), + KEYVALUE_ENTRY(EVENT_BUFWINENTER, "BufWinEnter"), + KEYVALUE_ENTRY(EVENT_BUFWINLEAVE, "BufWinLeave"), + KEYVALUE_ENTRY(EVENT_BUFWIPEOUT, "BufWipeout"), + KEYVALUE_ENTRY(EVENT_BUFWRITEPRE, "BufWrite"), + KEYVALUE_ENTRY(EVENT_BUFWRITECMD, "BufWriteCmd"), + KEYVALUE_ENTRY(EVENT_BUFWRITEPOST, "BufWritePost"), + KEYVALUE_ENTRY(EVENT_BUFWRITEPRE, "BufWritePre"), + KEYVALUE_ENTRY(EVENT_CMDLINECHANGED, "CmdlineChanged"), + KEYVALUE_ENTRY(EVENT_CMDLINEENTER, "CmdlineEnter"), + KEYVALUE_ENTRY(EVENT_CMDLINELEAVE, "CmdlineLeave"), + KEYVALUE_ENTRY(EVENT_CMDUNDEFINED, "CmdUndefined"), + KEYVALUE_ENTRY(EVENT_CMDWINENTER, "CmdwinEnter"), + KEYVALUE_ENTRY(EVENT_CMDWINLEAVE, "CmdwinLeave"), + KEYVALUE_ENTRY(EVENT_COLORSCHEME, "ColorScheme"), + KEYVALUE_ENTRY(EVENT_COLORSCHEMEPRE, "ColorSchemePre"), + KEYVALUE_ENTRY(EVENT_COMPLETECHANGED, "CompleteChanged"), + KEYVALUE_ENTRY(EVENT_COMPLETEDONE, "CompleteDone"), + KEYVALUE_ENTRY(EVENT_COMPLETEDONEPRE, "CompleteDonePre"), + KEYVALUE_ENTRY(EVENT_CURSORHOLD, "CursorHold"), + KEYVALUE_ENTRY(EVENT_CURSORHOLDI, "CursorHoldI"), + KEYVALUE_ENTRY(EVENT_CURSORMOVED, "CursorMoved"), + KEYVALUE_ENTRY(EVENT_CURSORMOVEDI, "CursorMovedI"), + KEYVALUE_ENTRY(EVENT_DIFFUPDATED, "DiffUpdated"), + KEYVALUE_ENTRY(EVENT_DIRCHANGED, "DirChanged"), + KEYVALUE_ENTRY(EVENT_DIRCHANGEDPRE, "DirChangedPre"), + KEYVALUE_ENTRY(EVENT_ENCODINGCHANGED, "EncodingChanged"), + KEYVALUE_ENTRY(EVENT_EXITPRE, "ExitPre"), + KEYVALUE_ENTRY(EVENT_FILEAPPENDCMD, "FileAppendCmd"), + KEYVALUE_ENTRY(EVENT_FILEAPPENDPOST, "FileAppendPost"), + KEYVALUE_ENTRY(EVENT_FILEAPPENDPRE, "FileAppendPre"), + KEYVALUE_ENTRY(EVENT_FILECHANGEDRO, "FileChangedRO"), + KEYVALUE_ENTRY(EVENT_FILECHANGEDSHELL, "FileChangedShell"), + KEYVALUE_ENTRY(EVENT_FILECHANGEDSHELLPOST, "FileChangedShellPost"), + KEYVALUE_ENTRY(EVENT_ENCODINGCHANGED, "FileEncoding"), + KEYVALUE_ENTRY(EVENT_FILEREADCMD, "FileReadCmd"), + KEYVALUE_ENTRY(EVENT_FILEREADPOST, "FileReadPost"), + KEYVALUE_ENTRY(EVENT_FILEREADPRE, "FileReadPre"), + KEYVALUE_ENTRY(EVENT_FILETYPE, "FileType"), + KEYVALUE_ENTRY(EVENT_FILEWRITECMD, "FileWriteCmd"), + KEYVALUE_ENTRY(EVENT_FILEWRITEPOST, "FileWritePost"), + KEYVALUE_ENTRY(EVENT_FILEWRITEPRE, "FileWritePre"), + KEYVALUE_ENTRY(EVENT_FILTERREADPOST, "FilterReadPost"), + KEYVALUE_ENTRY(EVENT_FILTERREADPRE, "FilterReadPre"), + KEYVALUE_ENTRY(EVENT_FILTERWRITEPOST, "FilterWritePost"), + KEYVALUE_ENTRY(EVENT_FILTERWRITEPRE, "FilterWritePre"), + KEYVALUE_ENTRY(EVENT_FOCUSGAINED, "FocusGained"), + KEYVALUE_ENTRY(EVENT_FOCUSLOST, "FocusLost"), + KEYVALUE_ENTRY(EVENT_FUNCUNDEFINED, "FuncUndefined"), + KEYVALUE_ENTRY(EVENT_GUIENTER, "GUIEnter"), + KEYVALUE_ENTRY(EVENT_GUIFAILED, "GUIFailed"), + KEYVALUE_ENTRY(EVENT_INSERTCHANGE, "InsertChange"), + KEYVALUE_ENTRY(EVENT_INSERTCHARPRE, "InsertCharPre"), + KEYVALUE_ENTRY(EVENT_INSERTENTER, "InsertEnter"), + KEYVALUE_ENTRY(EVENT_INSERTLEAVE, "InsertLeave"), + KEYVALUE_ENTRY(EVENT_INSERTLEAVEPRE, "InsertLeavePre"), + KEYVALUE_ENTRY(EVENT_MENUPOPUP, "MenuPopup"), + KEYVALUE_ENTRY(EVENT_MODECHANGED, "ModeChanged"), + KEYVALUE_ENTRY(EVENT_OPTIONSET, "OptionSet"), + KEYVALUE_ENTRY(EVENT_QUICKFIXCMDPOST, "QuickFixCmdPost"), + KEYVALUE_ENTRY(EVENT_QUICKFIXCMDPRE, "QuickFixCmdPre"), + KEYVALUE_ENTRY(EVENT_QUITPRE, "QuitPre"), + KEYVALUE_ENTRY(EVENT_REMOTEREPLY, "RemoteReply"), + KEYVALUE_ENTRY(EVENT_SAFESTATE, "SafeState"), + KEYVALUE_ENTRY(EVENT_SAFESTATEAGAIN, "SafeStateAgain"), + KEYVALUE_ENTRY(EVENT_SESSIONLOADPOST, "SessionLoadPost"), + KEYVALUE_ENTRY(EVENT_SESSIONWRITEPOST, "SessionWritePost"), + KEYVALUE_ENTRY(EVENT_SHELLCMDPOST, "ShellCmdPost"), + KEYVALUE_ENTRY(EVENT_SHELLFILTERPOST, "ShellFilterPost"), + KEYVALUE_ENTRY(EVENT_SIGUSR1, "SigUSR1"), + KEYVALUE_ENTRY(EVENT_SOURCECMD, "SourceCmd"), + KEYVALUE_ENTRY(EVENT_SOURCEPOST, "SourcePost"), + KEYVALUE_ENTRY(EVENT_SOURCEPRE, "SourcePre"), + KEYVALUE_ENTRY(EVENT_SPELLFILEMISSING, "SpellFileMissing"), + KEYVALUE_ENTRY(EVENT_STDINREADPOST, "StdinReadPost"), + KEYVALUE_ENTRY(EVENT_STDINREADPRE, "StdinReadPre"), + KEYVALUE_ENTRY(EVENT_SWAPEXISTS, "SwapExists"), + KEYVALUE_ENTRY(EVENT_SYNTAX, "Syntax"), + KEYVALUE_ENTRY(EVENT_TABCLOSED, "TabClosed"), + KEYVALUE_ENTRY(EVENT_TABENTER, "TabEnter"), + KEYVALUE_ENTRY(EVENT_TABLEAVE, "TabLeave"), + KEYVALUE_ENTRY(EVENT_TABNEW, "TabNew"), + KEYVALUE_ENTRY(EVENT_TERMCHANGED, "TermChanged"), + KEYVALUE_ENTRY(EVENT_TERMINALOPEN, "TerminalOpen"), + KEYVALUE_ENTRY(EVENT_TERMINALWINOPEN, "TerminalWinOpen"), + KEYVALUE_ENTRY(EVENT_TERMRESPONSE, "TermResponse"), + KEYVALUE_ENTRY(EVENT_TERMRESPONSEALL, "TermResponseAll"), + KEYVALUE_ENTRY(EVENT_TEXTCHANGED, "TextChanged"), + KEYVALUE_ENTRY(EVENT_TEXTCHANGEDI, "TextChangedI"), + KEYVALUE_ENTRY(EVENT_TEXTCHANGEDP, "TextChangedP"), + KEYVALUE_ENTRY(EVENT_TEXTCHANGEDT, "TextChangedT"), + KEYVALUE_ENTRY(EVENT_TEXTYANKPOST, "TextYankPost"), + KEYVALUE_ENTRY(EVENT_USER, "User"), + KEYVALUE_ENTRY(EVENT_VIMENTER, "VimEnter"), + KEYVALUE_ENTRY(EVENT_VIMLEAVE, "VimLeave"), + KEYVALUE_ENTRY(EVENT_VIMLEAVEPRE, "VimLeavePre"), + KEYVALUE_ENTRY(EVENT_VIMRESIZED, "VimResized"), + KEYVALUE_ENTRY(EVENT_VIMRESUME, "VimResume"), + KEYVALUE_ENTRY(EVENT_VIMSUSPEND, "VimSuspend"), + KEYVALUE_ENTRY(EVENT_WINCLOSED, "WinClosed"), + KEYVALUE_ENTRY(EVENT_WINENTER, "WinEnter"), + KEYVALUE_ENTRY(EVENT_WINLEAVE, "WinLeave"), + KEYVALUE_ENTRY(EVENT_WINNEW, "WinNew"), + KEYVALUE_ENTRY(EVENT_WINNEWPRE, "WinNewPre"), + KEYVALUE_ENTRY(EVENT_WINRESIZED, "WinResized"), + KEYVALUE_ENTRY(EVENT_WINSCROLLED, "WinScrolled") }; -static AutoPat *first_autopat[NUM_EVENTS] = -{ +static AutoPat *first_autopat[NUM_EVENTS] = { + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL + NULL, NULL, NULL, NULL, NULL, NULL }; -static AutoPat *last_autopat[NUM_EVENTS] = -{ +static AutoPat *last_autopat[NUM_EVENTS] = { + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL + NULL, NULL, NULL, NULL, NULL, NULL }; #define AUGROUP_DEFAULT (-1) // default autocmd group @@ -265,6 +279,7 @@ static int current_augroup = AUGROUP_DEFAULT; static int au_need_clean = FALSE; // need to delete marked patterns +static event_T event_name2nr(char_u *start, char_u **end); static char_u *event_nr2name(event_T event); static int au_get_grouparg(char_u **argp); static int do_autocmd_event(event_T event, char_u *pat, int once, int nested, char_u *cmd, int forceit, int group, int flags); @@ -680,24 +695,35 @@ is_aucmd_win(win_T *win) event_name2nr(char_u *start, char_u **end) { char_u *p; - int i; - int len; + keyvalue_T target; + keyvalue_T *entry; + static keyvalue_T *bufnewfile = &event_tab[BUFNEWFILE_INDEX]; + static keyvalue_T *bufread = &event_tab[BUFREAD_INDEX]; // the event name ends with end of line, '|', a blank or a comma for (p = start; *p && !VIM_ISWHITE(*p) && *p != ',' && *p != '|'; ++p) ; - for (i = 0; event_names[i].name != NULL; ++i) - { - len = (int)STRLEN(event_names[i].name); - if (len == p - start && STRNICMP(event_names[i].name, start, len) == 0) - break; - } + + target.key = 0; + target.value = (char *)start; + target.length = (size_t)(p - start); + + // special cases: + // BufNewFile and BufRead are searched for ALOT (especially at startup) + // so we check for them first. + if (cmp_keyvalue_value_ni(&target, bufnewfile) == 0) + entry = bufnewfile; + else + if (cmp_keyvalue_value_ni(&target, bufread) == 0) + entry = bufread; + else + entry = (keyvalue_T *)bsearch(&target, &event_tab, ARRAY_LENGTH(event_tab), sizeof(event_tab[0]), cmp_keyvalue_value_ni); + if (*p == ',') ++p; *end = p; - if (event_names[i].name == NULL) - return NUM_EVENTS; - return event_names[i].event; + + return (entry == NULL) ? NUM_EVENTS : (event_T)entry->key; } /* @@ -707,11 +733,52 @@ event_name2nr(char_u *start, char_u **end) event_nr2name(event_T event) { int i; +#define CACHE_SIZE 12 + static int cache_tab[CACHE_SIZE]; + static int cache_last_index = -1; + + if (cache_last_index < 0) + { + for (i = 0; i < (int)ARRAY_LENGTH(cache_tab); ++i) + cache_tab[i] = -1; + cache_last_index = ARRAY_LENGTH(cache_tab) - 1; + } - for (i = 0; event_names[i].name != NULL; ++i) - if (event_names[i].event == event) - return (char_u *)event_names[i].name; - return (char_u *)"Unknown"; + // first look in the cache + // the cache is circular. to search it we start at the most recent entry + // and go backwards wrapping around when we get to index 0. + for (i = cache_last_index; cache_tab[i] >= 0; ) + { + if ((event_T)event_tab[cache_tab[i]].key == event) + return (char_u *)event_tab[cache_tab[i]].value; + + if (i == 0) + i = ARRAY_LENGTH(cache_tab) - 1; + else + --i; + + // are we back at the start? + if (i == cache_last_index) + break; + } + + // look in the event table itself + for (i = 0; i < (int)ARRAY_LENGTH(event_tab); ++i) + { + if ((event_T)event_tab[i].key == event) + { + // store the found entry in the next position in the cache, + // wrapping around when we get to the maximum index. + if (cache_last_index == ARRAY_LENGTH(cache_tab) - 1) + cache_last_index = 0; + else + ++cache_last_index; + cache_tab[cache_last_index] = i; + break; + } + } + + return (i == (int)ARRAY_LENGTH(event_tab)) ? (char_u *)"Unknown" : (char_u *)event_tab[i].value; } /* @@ -805,12 +872,14 @@ au_event_disable(char *what) { char_u *new_ei; char_u *save_ei; + size_t p_ei_len; - save_ei = vim_strsave(p_ei); + p_ei_len = STRLEN(p_ei); + save_ei = vim_strnsave(p_ei, p_ei_len); if (save_ei == NULL) return NULL; - new_ei = vim_strnsave(p_ei, STRLEN(p_ei) + STRLEN(what)); + new_ei = vim_strnsave(p_ei, p_ei_len + STRLEN(what)); if (new_ei == NULL) { vim_free(save_ei); @@ -1591,6 +1660,11 @@ aucmd_prepbuf( win_init_popup_win(auc_win, buf); + // Make sure tp_localdir and globaldir are NULL to avoid a + // chdir() in win_enter_ext(). + // win_init_popup_win() has already set w_localdir to NULL. + aco->tp_localdir = curtab->tp_localdir; + curtab->tp_localdir = NULL; aco->globaldir = globaldir; globaldir = NULL; @@ -1704,6 +1778,12 @@ win_found: vars_clear(&awp->w_vars->dv_hashtab); // free all w: variables hash_init(&awp->w_vars->dv_hashtab); // re-use the hashtab #endif + // If :lcd has been used in the autocommand window, correct current + // directory before restoring tp_localdir and globaldir. + if (awp->w_localdir != NULL) + win_fix_current_dir(); + vim_free(curtab->tp_localdir); + curtab->tp_localdir = aco->tp_localdir; vim_free(globaldir); globaldir = aco->globaldir; @@ -2257,7 +2337,7 @@ apply_autocmds_group( saveRedobuff(&save_redo); did_save_redobuff = TRUE; } - did_filetype = keep_filetype; + curbuf->b_did_filetype = curbuf->b_keep_filetype; } /* @@ -2269,7 +2349,7 @@ apply_autocmds_group( // Remember that FileType was triggered. Used for did_filetype(). if (event == EVENT_FILETYPE) - did_filetype = TRUE; + curbuf->b_did_filetype = TRUE; tail = gettail(fname); @@ -2378,7 +2458,7 @@ apply_autocmds_group( restore_search_patterns(); if (did_save_redobuff) restoreRedobuff(&save_redo); - did_filetype = FALSE; + curbuf->b_did_filetype = FALSE; while (au_pending_free_buf != NULL) { buf_T *b = au_pending_free_buf->b_next; @@ -2420,7 +2500,7 @@ BYPASS_AU: aubuflocal_remove(buf); if (retval == OK && event == EVENT_FILETYPE) - au_did_filetype = TRUE; + curbuf->b_au_did_filetype = TRUE; return retval; } @@ -2773,6 +2853,8 @@ set_context_in_autocmd( char_u * get_event_name(expand_T *xp UNUSED, int idx) { + int i; + if (idx < augroups.ga_len) // First list group names, if wanted { if (!include_groups || AUGROUP_NAME(idx) == NULL @@ -2780,7 +2862,12 @@ get_event_name(expand_T *xp UNUSED, int idx) return (char_u *)""; // skip deleted entries return AUGROUP_NAME(idx); // return a name } - return (char_u *)event_names[idx - augroups.ga_len].name; + + i = idx - augroups.ga_len; + if (i < 0 || i >= (int)ARRAY_LENGTH(event_tab)) + return NULL; + + return (char_u *)event_tab[i].value; } /* @@ -2790,7 +2877,10 @@ get_event_name(expand_T *xp UNUSED, int idx) char_u * get_event_name_no_group(expand_T *xp UNUSED, int idx) { - return (char_u *)event_names[idx].name; + if (idx < 0 || idx >= (int)ARRAY_LENGTH(event_tab)) + return NULL; + + return (char_u *)event_tab[idx].value; } @@ -3250,8 +3340,6 @@ f_autocmd_get(typval_T *argvars, typval_T *rettv) // return only the autocmds for the specified event if (dict_has_key(argvars[0].vval.v_dict, "event")) { - int i; - name = dict_get_string(argvars[0].vval.v_dict, "event", TRUE); if (name == NULL) return; @@ -3260,16 +3348,20 @@ f_autocmd_get(typval_T *argvars, typval_T *rettv) event_arg = NUM_EVENTS; else { - for (i = 0; event_names[i].name != NULL; i++) - if (STRICMP(event_names[i].name, name) == 0) - break; - if (event_names[i].name == NULL) + keyvalue_T target; + keyvalue_T *entry; + + target.key = 0; + target.value = (char *)name; + target.length = (int)STRLEN(target.value); + entry = (keyvalue_T *)bsearch(&target, &event_tab, ARRAY_LENGTH(event_tab), sizeof(event_tab[0]), cmp_keyvalue_value_ni); + if (entry == NULL) { semsg(_(e_no_such_event_str), name); vim_free(name); return; } - event_arg = event_names[i].event; + event_arg = (event_T)entry->key; } vim_free(name); } @@ -3314,7 +3406,10 @@ f_autocmd_get(typval_T *argvars, typval_T *rettv) event_dict = dict_alloc(); if (event_dict == NULL || list_append_dict(event_list, event_dict) == FAIL) + { + vim_free(pat); return; + } if (dict_add_string(event_dict, "event", event_name) == FAIL || dict_add_string(event_dict, "group", @@ -3329,7 +3424,10 @@ f_autocmd_get(typval_T *argvars, typval_T *rettv) || dict_add_bool(event_dict, "once", ac->once) == FAIL || dict_add_bool(event_dict, "nested", ac->nested) == FAIL) + { + vim_free(pat); return; + } } } } diff --git a/src/buffer.c b/src/buffer.c index 243593a..58e9718 100644 --- a/src/buffer.c +++ b/src/buffer.c @@ -225,7 +225,7 @@ open_buffer( // The autocommands in readfile() may change the buffer, but only AFTER // reading the file. set_bufref(&old_curbuf, curbuf); - modified_was_set = FALSE; + curbuf->b_modified_was_set = FALSE; // mark cursor position as being invalid curwin->w_valid = 0; @@ -322,7 +322,7 @@ open_buffer( // the changed flag. Unless in readonly mode: "ls | gview -". // When interrupted and 'cpoptions' contains 'i' set changed flag. if ((got_int && vim_strchr(p_cpo, CPO_INTMOD) != NULL) - || modified_was_set // ":set modified" used in autocmd + || curbuf->b_modified_was_set // autocmd did ":set modified" #ifdef FEAT_EVAL || (aborting() && vim_strchr(p_cpo, CPO_INTMOD) != NULL) #endif @@ -1944,7 +1944,7 @@ enter_buffer(buf_T *buf) // ":ball" used in an autocommand. If there already is a filetype we // might prefer to keep it. if (*curbuf->b_p_ft == NUL) - did_filetype = FALSE; + curbuf->b_did_filetype = FALSE; open_buffer(FALSE, NULL, 0); } diff --git a/src/change.c b/src/change.c index daf4fae..dacc06f 100644 --- a/src/change.c +++ b/src/change.c @@ -574,8 +574,7 @@ changed_common( && wp->w_topline < lnume && win_linetabsize(wp, wp->w_topline, ml_get(wp->w_topline), (colnr_T)MAXCOL) - <= wp->w_skipcol + sms_marker_overlap(wp, - win_col_off(wp) - win_col_off2(wp))))) + <= wp->w_skipcol + sms_marker_overlap(wp, -1)))) wp->w_skipcol = 0; // Check if a change in the buffer has invalidated the cached diff --git a/src/charset.c b/src/charset.c index 5ae90da..470698f 100644 --- a/src/charset.c +++ b/src/charset.c @@ -798,6 +798,45 @@ linetabsize(win_T *wp, linenr_T lnum) ml_get_buf(wp->w_buffer, lnum, FALSE), (colnr_T)MAXCOL); } +/* + * Like linetabsize(), but excludes 'above'/'after'/'right'/'below' aligned + * virtual text, while keeping inline virtual text. + */ + int +linetabsize_no_outer(win_T *wp, linenr_T lnum) +{ +#ifndef FEAT_PROP_POPUP + return linetabsize(wp, lnum); +#else + chartabsize_T cts; + char_u *line = ml_get_buf(wp->w_buffer, lnum, FALSE); + + init_chartabsize_arg(&cts, wp, lnum, 0, line, line); + + if (cts.cts_text_prop_count) + { + int write_idx = 0; + for (int read_idx = 0; read_idx < cts.cts_text_prop_count; read_idx++) + { + textprop_T *tp = &cts.cts_text_props[read_idx]; + if (tp->tp_col != MAXCOL) + { + if (read_idx != write_idx) + cts.cts_text_props[write_idx] = *tp; + write_idx++; + } + } + cts.cts_text_prop_count = write_idx; + if (cts.cts_text_prop_count == 0) + VIM_CLEAR(cts.cts_text_props); + } + + win_linetabsize_cts(&cts, (colnr_T)MAXCOL); + clear_chartabsize_arg(&cts); + return (int)cts.cts_vcol; +#endif +} + void win_linetabsize_cts(chartabsize_T *cts, colnr_T len) { @@ -1318,7 +1357,7 @@ win_lbr_chartabsize( cts->cts_bri_size = get_breakindent_win(wp, line); head_mid += cts->cts_bri_size; } - if (head_mid > 0 && wcol + size > wp->w_width) + if (head_mid > 0) { // Calculate effective window width. int prev_rem = wp->w_width - wcol; diff --git a/src/clientserver.c b/src/clientserver.c index 340add3..b19cd44 100644 --- a/src/clientserver.c +++ b/src/clientserver.c @@ -608,7 +608,7 @@ build_drop_cmd( // Call inputsave() so that a prompt for an encryption key works. ga_concat(&ga, (char_u *) - "<CR>:if exists('*inputsave')|call inputsave()|endif|"); + "<CR><C-\\><C-N>:if exists('*inputsave')|call inputsave()|endif|"); if (tabs) ga_concat(&ga, (char_u *)"tab "); ga_concat(&ga, (char_u *)"drop"); @@ -652,7 +652,13 @@ build_drop_cmd( // endif // endif ga_concat(&ga, (char_u *)":if !exists('+acd')||!&acd|if haslocaldir()|"); +#ifdef MSWIN + // in case :set shellslash is set, need to normalize the directory separators + // '/' is not valid in a filename so replacing '/' by '\\' should be safe + ga_concat(&ga, (char_u *)"cd -|lcd -|elseif getcwd()->tr('/','\\') ==# '"); +#else ga_concat(&ga, (char_u *)"cd -|lcd -|elseif getcwd() ==# '"); +#endif ga_concat(&ga, cdp); ga_concat(&ga, (char_u *)"'|cd -|endif|endif<CR>"); vim_free(cdp); diff --git a/src/configure.ac b/src/configure.ac index 6311269..f6e54b3 100644 --- a/src/configure.ac +++ b/src/configure.ac @@ -4523,13 +4523,13 @@ if test "$enable_nls" = "yes"; then AC_MSG_RESULT([no]) fi AC_SUBST(MSGFMT_DESKTOP) - AC_MSG_CHECKING([if msgfmt supports --no-convert]) + AC_MSG_CHECKING([if $MSGFMT supports --no-convert]) if "$MSGFMT" --help | grep -q -- '--no-convert' >/dev/null; then AC_MSG_RESULT([yes]) - MSGFMTCMD="OLD_PO_FILE_INPUT=yes msgfmt --no-convert -v" + MSGFMTCMD="OLD_PO_FILE_INPUT=yes $MSGFMT --no-convert -v" else AC_MSG_RESULT([no]) - MSGFMTCMD="OLD_PO_FILE_INPUT=yes msgfmt -v" + MSGFMTCMD="OLD_PO_FILE_INPUT=yes $MSGFMT -v" fi AC_SUBST(MSGFMTCMD) fi @@ -1300,12 +1300,18 @@ dict_extend_func( action = tv_get_string_chk(&argvars[2]); if (action == NULL) + { + if (is_new) + dict_unref(d1); return; + } for (i = 0; i < 3; ++i) if (STRCMP(action, av[i]) == 0) break; if (i == 3) { + if (is_new) + dict_unref(d1); semsg(_(e_invalid_argument_str), action); return; } diff --git a/src/dosinst.c b/src/dosinst.c index 35625a7..116cc8f 100644 --- a/src/dosinst.c +++ b/src/dosinst.c @@ -1663,7 +1663,7 @@ install_registry(void) uninstall_string, icon_string, version_string, - "Bram Moolenaar et al."); + "The Vim Project"); if (ERROR_SUCCESS != lRet) return FAIL; diff --git a/src/drawline.c b/src/drawline.c index a8de449..81577be 100644 --- a/src/drawline.c +++ b/src/drawline.c @@ -2072,26 +2072,34 @@ win_line( // not on the next char yet, don't start another prop --bcol; # endif - int display_text_first = FALSE; - // Add any text property that starts in this column. - // With 'nowrap' and not in the first screen line only "below" - // text prop can show. - while (text_prop_next < text_prop_count - && (text_props[text_prop_next].tp_col == MAXCOL - ? ((*ptr == NUL - && (wp->w_p_wrap - || wlv.row == startrow - || (text_props[text_prop_next].tp_flags - & TP_FLAG_ALIGN_BELOW))) - || (bcol == 0 - && (text_props[text_prop_next].tp_flags - & TP_FLAG_ALIGN_ABOVE))) - : bcol >= text_props[text_prop_next].tp_col - 1)) + while (text_prop_next < text_prop_count) { - if (text_props[text_prop_next].tp_col == MAXCOL - || bcol <= text_props[text_prop_next].tp_col - 1 - + text_props[text_prop_next].tp_len) + int active; + textprop_T *tp = &text_props[text_prop_next]; + if (tp->tp_col == MAXCOL) + { + if (bcol == 0 && (tp->tp_flags & TP_FLAG_ALIGN_ABOVE)) + active = TRUE; + else if (*ptr != NUL) + break; + else + { + // With 'nowrap' and not in the first screen line only "below" + // text prop can show. + active = wp->w_p_wrap + || wlv.row == startrow + || (tp->tp_flags & TP_FLAG_ALIGN_BELOW); + } + } + else + { + if (bcol < tp->tp_col - 1) + break; + active = bcol <= tp->tp_col - 1 + tp->tp_len; + } + + if (active) text_prop_idxs[text_props_active++] = text_prop_next; ++text_prop_next; } @@ -2109,8 +2117,7 @@ win_line( text_prop_id = 0; reset_extra_attr = FALSE; } - if (text_props_active > 0 && wlv.n_extra == 0 - && !display_text_first) + if (text_props_active > 0 && wlv.n_extra == 0) { int used_tpi = -1; int used_attr = 0; @@ -2157,8 +2164,6 @@ win_line( // skip this prop, first display the '$' after // the line or display an empty line text_prop_follows = TRUE; - if (used_tpi < 0) - display_text_first = TRUE; continue; } @@ -2172,7 +2177,6 @@ win_line( text_prop_flags = pt->pt_flags; text_prop_id = tp->tp_id; used_tpi = tpi; - display_text_first = FALSE; } } if (text_prop_id < 0 && used_tpi >= 0 @@ -2327,17 +2331,29 @@ win_line( } } else if (text_prop_next < text_prop_count - && text_props[text_prop_next].tp_col == MAXCOL && ((*ptr != NUL && ptr[mb_ptr2len(ptr)] == NUL) - || (!wp->w_p_wrap - && wlv.col == wp->w_width - 1 - && (text_props[text_prop_next].tp_flags - & TP_FLAG_ALIGN_BELOW)))) + || (!wp->w_p_wrap && wlv.col == wp->w_width - 1))) + { // When at last-but-one character and a text property // follows after it, we may need to flush the line after // displaying that character. // Or when not wrapping and at the rightmost column. - text_prop_follows = TRUE; + + int only_below_follows = !wp->w_p_wrap && wlv.col == wp->w_width - 1; + // TODO: Store "after"/"right"/"below" text properties in order + // in the buffer so only `text_props[text_prop_count - 1]` + // needs to be checked for following "below" virtual text + for (int i = text_prop_next; i < text_prop_count; ++i) + { + if (text_props[i].tp_col == MAXCOL + && (!only_below_follows + || (text_props[i].tp_flags & TP_FLAG_ALIGN_BELOW))) + { + text_prop_follows = TRUE; + break; + } + } + } } if (wlv.start_extra_for_textprop) @@ -845,9 +845,10 @@ doESCkey: did_cursorhold = FALSE; // ins_redraw() triggers TextChangedI only when no characters - // are in the typeahead buffer, so only reset curbuf->b_last_changedtick + // are in the typeahead buffer, so reset curbuf->b_last_changedtick only // if the TextChangedI was not blocked by char_avail() (e.g. using :norm!) - if (!char_avail()) + // and the TextChangedI autocommand has been triggered. + if (!char_avail() && curbuf->b_last_changedtick_i == CHANGEDTICK(curbuf)) curbuf->b_last_changedtick = CHANGEDTICK(curbuf); return (c == Ctrl_O); } @@ -3958,10 +3959,9 @@ ins_del(void) * Delete one character for ins_bs(). */ static void -ins_bs_one(colnr_T *vcolp) +ins_bs_one(void) { dec_cursor(); - getvcol(curwin, &curwin->w_cursor, vcolp, NULL, NULL); if (State & REPLACE_FLAG) { // Don't delete characters before the insert point when in @@ -4211,44 +4211,69 @@ ins_bs( && (!*inserted_space_p || arrow_used)))))) { - int ts; - colnr_T vcol; + colnr_T vcol = 0; colnr_T want_vcol; - colnr_T start_vcol; + char_u *line; + char_u *ptr; + char_u *cursor_ptr; + char_u *space_ptr; + colnr_T space_vcol = 0; + int prev_space = FALSE; + colnr_T want_col; *inserted_space_p = FALSE; - // Compute the virtual column where we want to be. Since - // 'showbreak' may get in the way, need to get the last column of - // the previous character. - getvcol(curwin, &curwin->w_cursor, &vcol, NULL, NULL); - start_vcol = vcol; - dec_cursor(); - getvcol(curwin, &curwin->w_cursor, NULL, NULL, &want_vcol); - inc_cursor(); -#ifdef FEAT_VARTABS - if (p_sta && in_indent) + + space_ptr = ptr = line = ml_get_curline(); + cursor_ptr = line + curwin->w_cursor.col; + + // Compute virtual column of cursor position, and find the last + // whitespace before cursor that is preceded by non-whitespace. + // Use chartabsize() so that virtual text and wrapping are ignored. + while (ptr < cursor_ptr) { - ts = (int)get_sw_value(curbuf); - want_vcol = (want_vcol / ts) * ts; + int cur_space = VIM_ISWHITE(*ptr); + + if (!prev_space && cur_space) + { + space_ptr = ptr; + space_vcol = vcol; + } + vcol += chartabsize(ptr, vcol); + MB_PTR_ADV(ptr); + prev_space = cur_space; } + + // Compute the virtual column where we want to be. + want_vcol = vcol > 0 ? vcol - 1 : 0; + if (p_sta && in_indent) + want_vcol -= want_vcol % (int)get_sw_value(curbuf); else +#ifdef FEAT_VARTABS want_vcol = tabstop_start(want_vcol, get_sts_value(), curbuf->b_p_vsts_array); #else - if (p_sta && in_indent) - ts = (int)get_sw_value(curbuf); - else - ts = (int)get_sts_value(); - want_vcol = (want_vcol / ts) * ts; + want_vcol -= want_vcol % (int)get_sts_value(); #endif - // delete characters until we are at or before want_vcol - while (vcol > want_vcol && curwin->w_cursor.col > 0 - && (cc = *(ml_get_cursor() - 1), VIM_ISWHITE(cc))) - ins_bs_one(&vcol); + // Find the position to stop backspacing. + // Use chartabsize() so that virtual text and wrapping are ignored. + while (TRUE) + { + int size = chartabsize(space_ptr, space_vcol); - // insert extra spaces until we are at want_vcol - while (vcol < want_vcol) + if (space_vcol + size > want_vcol) + break; + space_vcol += size; + MB_PTR_ADV(space_ptr); + } + want_col = space_ptr - line; + + // Delete characters until we are at or before want_col. + while (curwin->w_cursor.col > want_col) + ins_bs_one(); + + // Insert extra spaces until we are at want_vcol. + for (; space_vcol < want_vcol; space_vcol++) { // Remember the first char we inserted if (curwin->w_cursor.lnum == Insstart_orig.lnum @@ -4263,13 +4288,7 @@ ins_bs( if ((State & REPLACE_FLAG)) replace_push(NUL); } - getvcol(curwin, &curwin->w_cursor, &vcol, NULL, NULL); } - - // If we are now back where we started delete one character. Can - // happen when using 'sts' and 'linebreak'. - if (vcol >= start_vcol) - ins_bs_one(&vcol); } /* @@ -4783,7 +4802,7 @@ ins_pageup(void) } tpos = curwin->w_cursor; - if (onepage(BACKWARD, 1L) == OK) + if (pagescroll(BACKWARD, 1L, FALSE) == OK) { start_arrow(&tpos); can_cindent = TRUE; @@ -4840,7 +4859,7 @@ ins_pagedown(void) } tpos = curwin->w_cursor; - if (onepage(FORWARD, 1L) == OK) + if (pagescroll(FORWARD, 1L, FALSE) == OK) { start_arrow(&tpos); can_cindent = TRUE; diff --git a/src/errors.h b/src/errors.h index 5dccc63..4387a29 100644 --- a/src/errors.h +++ b/src/errors.h @@ -2268,7 +2268,7 @@ EXTERN char e_nfa_regexp_while_converting_from_postfix_to_nfa_too_many_stats_lef EXTERN char e_nfa_regexp_not_enough_space_to_store_whole_nfa[] INIT(= N_("E876: (NFA regexp) Not enough space to store the whole NFA")); EXTERN char e_nfa_regexp_invalid_character_class_nr[] - INIT(= "E877: (NFA regexp) Invalid character class: %d"); + INIT(= N_("E877: (NFA regexp) Invalid character class: %d")); EXTERN char e_nfa_regexp_could_not_allocate_memory_for_branch_traversal[] INIT(= N_("E878: (NFA regexp) Could not allocate memory for branch traversal!")); #ifdef FEAT_SYN_HL @@ -3412,9 +3412,9 @@ EXTERN char e_invalid_class_variable_declaration_str[] EXTERN char e_invalid_type_for_object_variable_str[] INIT(= N_("E1330: Invalid type for object variable: %s")); EXTERN char e_public_must_be_followed_by_var_static_final_or_const[] - INIT(= N_("E1331: Public must be followed by \"var\" or \"static\" or \"final\" or \"const\"")); + INIT(= N_("E1331: public must be followed by \"var\" or \"static\" or \"final\" or \"const\"")); EXTERN char e_public_variable_name_cannot_start_with_underscore_str[] - INIT(= N_("E1332: Public variable name cannot start with underscore: %s")); + INIT(= N_("E1332: public variable name cannot start with underscore: %s")); EXTERN char e_cannot_access_protected_variable_str[] INIT(= N_("E1333: Cannot access protected variable \"%s\" in class \"%s\"")); // E1334 unused @@ -3532,9 +3532,9 @@ EXTERN char e_class_method_str_accessible_only_using_class_str[] EXTERN char e_object_method_str_accessible_only_using_object_str[] INIT(= N_("E1386: Object method \"%s\" accessible only using class \"%s\" object")); EXTERN char e_public_variable_not_supported_in_interface[] - INIT(= N_("E1387: Public variable not supported in an interface")); + INIT(= N_("E1387: public variable not supported in an interface")); EXTERN char e_public_keyword_not_supported_for_method[] - INIT(= N_("E1388: Public keyword not supported for a method")); + INIT(= N_("E1388: public keyword not supported for a method")); EXTERN char e_missing_name_after_implements[] INIT(= N_("E1389: Missing name after implements")); EXTERN char e_cannot_use_an_object_variable_except_with_the_new_method_str[] @@ -3585,8 +3585,40 @@ EXTERN char e_builtin_object_method_str_not_supported[] INIT(= N_("E1412: Builtin object method \"%s\" not supported")); EXTERN char e_builtin_class_method_not_supported[] INIT(= N_("E1413: Builtin class method not supported")); -#endif -// E1415 - E1499 unused (reserved for Vim9 class support) +EXTERN char e_enum_can_only_be_defined_in_vim9_script[] + INIT(= N_("E1414: Enum can only be defined in Vim9 script")); +EXTERN char e_enum_name_must_start_with_uppercase_letter_str[] + INIT(= N_("E1415: Enum name must start with an uppercase letter: %s")); +EXTERN char e_enum_cannot_extend_class[] + INIT(= N_("E1416: Enum cannot extend a class or enum")); +EXTERN char e_abstract_cannot_be_used_in_enum[] + INIT(= N_("E1417: Abstract cannot be used in an Enum")); +EXTERN char e_invalid_enum_value_declaration_str[] + INIT(= N_("E1418: Invalid enum value declaration: %s")); +EXTERN char e_not_valid_command_in_enum_str[] + INIT(= N_("E1419: Not a valid command in an Enum: %s")); +EXTERN char e_missing_endenum[] + INIT(= N_("E1420: Missing :endenum")); +EXTERN char e_using_enum_as_value_str[] + INIT(= N_("E1421: Enum \"%s\" cannot be used as a value")); +EXTERN char e_enum_value_str_not_found_in_enum_str[] + INIT(= N_("E1422: Enum value \"%s\" not found in enum \"%s\"")); +EXTERN char e_enumvalue_str_cannot_be_modified[] + INIT(= N_("E1423: Enum value \"%s.%s\" cannot be modified")); +EXTERN char e_using_enum_str_as_number[] + INIT(= N_("E1424: Using an Enum \"%s\" as a Number")); +EXTERN char e_using_enum_str_as_string[] + INIT(= N_("E1425: Using an Enum \"%s\" as a String")); +EXTERN char e_enum_str_ordinal_cannot_be_modified[] + INIT(= N_("E1426: Enum \"%s\" ordinal value cannot be modified")); +EXTERN char e_enum_str_name_cannot_be_modified[] + INIT(= N_("E1427: Enum \"%s\" name cannot be modified")); +EXTERN char e_duplicate_enum_str[] + INIT(= N_("E1428: Duplicate enum value: %s")); +EXTERN char e_class_can_only_be_used_in_script[] + INIT(= N_("E1429: Class can only be used in a script")); +#endif +// E1429 - E1499 unused (reserved for Vim9 class support) EXTERN char e_cannot_mix_positional_and_non_positional_str[] INIT(= N_("E1500: Cannot mix positional and non-positional arguments: %s")); EXTERN char e_fmt_arg_nr_unused_str[] @@ -549,6 +549,7 @@ skip_expr_concatenate( ((char_u **)gap->ga_data)[gap->ga_len - 1]; ((char_u **)gap->ga_data)[gap->ga_len - 1] = NULL; ga_clear_strings(gap); + ga_clear(freegap); } else { @@ -574,16 +575,16 @@ skip_expr_concatenate( /* * Convert "tv" to a string. - * When "convert" is TRUE convert a List into a sequence of lines. + * When "join_list" is TRUE convert a List into a sequence of lines. * Returns an allocated string (NULL when out of memory). */ char_u * -typval2string(typval_T *tv, int convert) +typval2string(typval_T *tv, int join_list) { garray_T ga; char_u *retval; - if (convert && tv->v_type == VAR_LIST) + if (join_list && tv->v_type == VAR_LIST) { ga_init2(&ga, sizeof(char), 80); if (tv->vval.v_list != NULL) @@ -595,6 +596,16 @@ typval2string(typval_T *tv, int convert) ga_append(&ga, NUL); retval = (char_u *)ga.ga_data; } + else if (tv->v_type == VAR_LIST || tv->v_type == VAR_DICT) + { + char_u *tofree; + char_u numbuf[NUMBUFLEN]; + + retval = tv2string(tv, &tofree, numbuf, 0); + // Make a copy if we have a value but it's not in allocated memory. + if (retval != NULL && tofree == NULL) + retval = vim_strsave(retval); + } else retval = vim_strsave(tv_get_string(tv)); return retval; @@ -603,13 +614,13 @@ typval2string(typval_T *tv, int convert) /* * Top level evaluation function, returning a string. Does not handle line * breaks. - * When "convert" is TRUE convert a List into a sequence of lines. + * When "join_list" is TRUE convert a List into a sequence of lines. * Return pointer to allocated memory, or NULL for failure. */ char_u * eval_to_string_eap( char_u *arg, - int convert, + int join_list, exarg_T *eap, int use_simple_function) { @@ -627,7 +638,7 @@ eval_to_string_eap( retval = NULL; else { - retval = typval2string(&tv, convert); + retval = typval2string(&tv, join_list); clear_tv(&tv); } clear_evalarg(&evalarg, NULL); @@ -638,10 +649,10 @@ eval_to_string_eap( char_u * eval_to_string( char_u *arg, - int convert, + int join_list, int use_simple_function) { - return eval_to_string_eap(arg, convert, NULL, use_simple_function); + return eval_to_string_eap(arg, join_list, NULL, use_simple_function); } /* @@ -1119,7 +1130,18 @@ get_lval_check_access( if (*p == '[' || *p == '.') break; if ((flags & GLV_READ_ONLY) == 0) - msg = e_variable_is_not_writable_str; + { + if (IS_ENUM(cl)) + { + if (om->ocm_type->tt_type == VAR_OBJECT) + semsg(_(e_enumvalue_str_cannot_be_modified), + cl->class_name, om->ocm_name); + else + msg = e_variable_is_not_writable_str; + } + else + msg = e_variable_is_not_writable_str; + } break; case VIM_ACCESS_ALL: break; @@ -1135,6 +1157,91 @@ get_lval_check_access( } /* + * Get lval information for a variable imported from script "imp_sid". On + * success, updates "lp" with the variable name, type, script ID and typval. + * The variable name starts at or after "p". + * If "rettv" is not NULL it points to the value to be assigned. This used to + * match the rhs and lhs types. + * Returns a pointer to the character after the variable name if the imported + * variable is valid and writable. + * Returns NULL if the variable is not exported or typval is not found or the + * rhs type doesn't match the lhs type or the variable is not writable. + */ + static char_u * +get_lval_imported( + lval_T *lp, + typval_T *rettv, + scid_T imp_sid, + char_u *p, + dictitem_T **dip, + int fne_flags, + int vim9script) +{ + ufunc_T *ufunc; + type_T *type = NULL; + int cc; + int rc = FAIL; + + p = skipwhite(p); + + import_check_sourced_sid(&imp_sid); + lp->ll_sid = imp_sid; + lp->ll_name = p; + p = find_name_end(lp->ll_name, NULL, NULL, fne_flags); + lp->ll_name_end = p; + + // check the item is exported + cc = *p; + *p = NUL; + if (find_exported(imp_sid, lp->ll_name, &ufunc, &type, NULL, NULL, + TRUE) == -1) + goto failed; + + if (vim9script && type != NULL) + { + where_T where = WHERE_INIT; + + // In a vim9 script, do type check and make sure the variable is + // writable. + if (check_typval_type(type, rettv, where) == FAIL) + goto failed; + } + + // Get the typval for the exported item + hashtab_T *ht = &SCRIPT_VARS(imp_sid); + if (ht == NULL) + goto failed; + + dictitem_T *di = find_var_in_ht(ht, 0, lp->ll_name, TRUE); + if (di == NULL) + // script is autoloaded. So variable will be found later + goto success; + + *dip = di; + + // Check whether the variable is writable. + svar_T *sv = find_typval_in_script(&di->di_tv, imp_sid, FALSE); + if (sv != NULL && sv->sv_const != 0) + { + semsg(_(e_cannot_change_readonly_variable_str), lp->ll_name); + goto failed; + } + + // check whether variable is locked + if (value_check_lock(di->di_tv.v_lock, lp->ll_name, FALSE)) + goto failed; + + lp->ll_tv = &di->di_tv; + +success: + rc = OK; + +failed: + *p = cc; + return rc == OK ? p : NULL; +} + +/* * Get an lval: variable, Dict item or List item that can be assigned a value * to: "name", "na{me}", "name[expr]", "name[expr:expr]", "name[expr][expr]", * "name.key", "name.key[expr]" etc. @@ -1166,7 +1273,7 @@ get_lval( char_u *p; char_u *expr_start, *expr_end; int cc; - dictitem_T *v; + dictitem_T *v = NULL; typval_T var1; typval_T var2; int empty1 = FALSE; @@ -1300,28 +1407,13 @@ get_lval( if (*p == '.') { imported_T *import = find_imported(lp->ll_name, p - lp->ll_name, TRUE); - if (import != NULL) { - ufunc_T *ufunc; - type_T *type; - - import_check_sourced_sid(&import->imp_sid); - lp->ll_sid = import->imp_sid; - lp->ll_name = skipwhite(p + 1); - p = find_name_end(lp->ll_name, NULL, NULL, fne_flags); - lp->ll_name_end = p; - - // check the item is exported - cc = *p; - *p = NUL; - if (find_exported(import->imp_sid, lp->ll_name, &ufunc, &type, - NULL, NULL, TRUE) == -1) - { - *p = cc; + p++; // skip '.' + p = get_lval_imported(lp, rettv, import->imp_sid, p, &v, + fne_flags, vim9script); + if (p == NULL) return NULL; - } - *p = cc; } } @@ -1341,7 +1433,7 @@ get_lval( lp->ll_tv = lval_root->lr_tv; v = NULL; } - else + else if (lp->ll_tv == NULL) { cc = *p; *p = NUL; @@ -6310,9 +6402,15 @@ echo_string_core( case VAR_CLASS: { class_T *cl = tv->vval.v_class; - size_t len = 6 + (cl == NULL ? 9 : STRLEN(cl->class_name)) + 1; + char *s = "class"; + if (IS_INTERFACE(cl)) + s = "interface"; + else if (IS_ENUM(cl)) + s = "enum"; + size_t len = STRLEN(s) + 1 + + (cl == NULL ? 9 : STRLEN(cl->class_name)) + 1; r = *tofree = alloc(len); - vim_snprintf((char *)r, len, "class %s", + vim_snprintf((char *)r, len, "%s %s", s, cl == NULL ? "[unknown]" : (char *)cl->class_name); } break; @@ -6806,7 +6904,7 @@ find_name_end( int br_nest = 0; char_u *p; int len; - int allow_curly = (flags & FNE_ALLOW_CURLY) || !in_vim9script(); + int allow_curly = !in_vim9script(); if (expr_start != NULL) { diff --git a/src/evalfunc.c b/src/evalfunc.c index 14650ca..2064982 100644 --- a/src/evalfunc.c +++ b/src/evalfunc.c @@ -3920,7 +3920,7 @@ f_deepcopy(typval_T *argvars, typval_T *rettv) static void f_did_filetype(typval_T *argvars UNUSED, typval_T *rettv UNUSED) { - rettv->vval.v_number = did_filetype; + rettv->vval.v_number = curbuf->b_did_filetype; } /* @@ -6129,6 +6129,13 @@ f_has(typval_T *argvars, typval_T *rettv) 0 #endif }, + {"dialog_con_gui", +#if defined(FEAT_CON_DIALOG) && defined(FEAT_GUI_DIALOG) + 1 +#else + 0 +#endif + }, {"dialog_gui", #ifdef FEAT_GUI_DIALOG 1 @@ -11486,15 +11493,31 @@ f_type(typval_T *argvars, typval_T *rettv) case VAR_CHANNEL: n = VAR_TYPE_CHANNEL; break; case VAR_BLOB: n = VAR_TYPE_BLOB; break; case VAR_INSTR: n = VAR_TYPE_INSTR; break; - case VAR_CLASS: n = VAR_TYPE_CLASS; break; - case VAR_OBJECT: n = VAR_TYPE_OBJECT; break; case VAR_TYPEALIAS: n = VAR_TYPE_TYPEALIAS; break; + case VAR_CLASS: + { + class_T *cl = argvars[0].vval.v_class; + if (IS_ENUM(cl)) + n = VAR_TYPE_ENUM; + else + n = VAR_TYPE_CLASS; + break; + } + case VAR_OBJECT: + { + class_T *cl = argvars[0].vval.v_object->obj_class; + if (IS_ENUM(cl)) + n = VAR_TYPE_ENUMVALUE; + else + n = VAR_TYPE_OBJECT; + break; + } case VAR_UNKNOWN: case VAR_ANY: case VAR_VOID: - internal_error_no_abort("f_type(UNKNOWN)"); - n = -1; - break; + internal_error_no_abort("f_type(UNKNOWN)"); + n = -1; + break; } rettv->vval.v_number = n; } diff --git a/src/evalvars.c b/src/evalvars.c index de9d5b2..6facbeb 100644 --- a/src/evalvars.c +++ b/src/evalvars.c @@ -159,6 +159,8 @@ static struct vimvar {VV_NAME("maxcol", VAR_NUMBER), NULL, VV_RO}, {VV_NAME("python3_version", VAR_NUMBER), NULL, VV_RO}, {VV_NAME("t_typealias", VAR_NUMBER), NULL, VV_RO}, + {VV_NAME("t_enum", VAR_NUMBER), NULL, VV_RO}, + {VV_NAME("t_enumvalue", VAR_NUMBER), NULL, VV_RO}, }; // shorthand @@ -262,6 +264,8 @@ evalvars_init(void) set_vim_var_nr(VV_TYPE_CLASS, VAR_TYPE_CLASS); set_vim_var_nr(VV_TYPE_OBJECT, VAR_TYPE_OBJECT); set_vim_var_nr(VV_TYPE_TYPEALIAS, VAR_TYPE_TYPEALIAS); + set_vim_var_nr(VV_TYPE_ENUM, VAR_TYPE_ENUM); + set_vim_var_nr(VV_TYPE_ENUMVALUE, VAR_TYPE_ENUMVALUE); set_vim_var_nr(VV_ECHOSPACE, sc_col - 1); @@ -658,7 +662,7 @@ eval_one_expr_in_str(char_u *p, garray_T *gap, int evaluate) if (evaluate) { *block_end = NUL; - expr_val = eval_to_string(block_start, TRUE, FALSE); + expr_val = eval_to_string(block_start, FALSE, FALSE); *block_end = '}'; if (expr_val == NULL) return NULL; @@ -775,8 +779,17 @@ heredoc_get(exarg_T *eap, char_u *cmd, int script_get, int vim9compile) int eval_failed = FALSE; cctx_T *cctx = vim9compile ? eap->cookie : NULL; int count = 0; + int heredoc_in_string = FALSE; + char_u *line_arg = NULL; + char_u *nl_ptr = vim_strchr(cmd, '\n'); - if (eap->ea_getline == NULL) + if (nl_ptr != NULL) + { + heredoc_in_string = TRUE; + line_arg = nl_ptr + 1; + *nl_ptr = NUL; + } + else if (eap->ea_getline == NULL) { emsg(_(e_cannot_use_heredoc_here)); return NULL; @@ -855,12 +868,38 @@ heredoc_get(exarg_T *eap, char_u *cmd, int script_get, int vim9compile) int mi = 0; int ti = 0; - vim_free(theline); - theline = eap->ea_getline(NUL, eap->cookie, 0, FALSE); - if (theline == NULL) + if (heredoc_in_string) { - semsg(_(e_missing_end_marker_str), marker); - break; + char_u *next_line; + + // heredoc in a string separated by newlines. Get the next line + // from the string. + + if (*line_arg == NUL) + { + semsg(_(e_missing_end_marker_str), marker); + break; + } + + theline = line_arg; + next_line = vim_strchr(theline, '\n'); + if (next_line == NULL) + line_arg += STRLEN(line_arg); + else + { + *next_line = NUL; + line_arg = next_line + 1; + } + } + else + { + vim_free(theline); + theline = eap->ea_getline(NUL, eap->cookie, 0, FALSE); + if (theline == NULL) + { + semsg(_(e_missing_end_marker_str), marker); + break; + } } // with "trim": skip the indent matching the :let line to find the @@ -907,6 +946,8 @@ heredoc_get(exarg_T *eap, char_u *cmd, int script_get, int vim9compile) } else { + int free_str = FALSE; + if (evalstr && !eap->skip) { str = eval_all_expr_in_str(str); @@ -916,15 +957,20 @@ heredoc_get(exarg_T *eap, char_u *cmd, int script_get, int vim9compile) eval_failed = TRUE; continue; } - vim_free(theline); - theline = str; + free_str = TRUE; } if (list_append_string(l, str, -1) == FAIL) break; + if (free_str) + vim_free(str); } } - vim_free(theline); + if (heredoc_in_string) + // Next command follows the heredoc in the string. + eap->nextcmd = line_arg; + else + vim_free(theline); vim_free(text_indent); if (vim9compile && cctx->ctx_skip != SKIP_YES && !eval_failed) @@ -3294,12 +3340,31 @@ find_var(char_u *name, hashtab_T **htp, int no_autoload) } } + // and finally try + return find_var_autoload_prefix(name, 0, htp, NULL); +} + +/* + * Find variable "name" with sn_autoload_prefix. + * Return a pointer to it if found, NULL if not found. + * When "sid" > 0, use it otherwise use "current_sctx.sc_sid". + * When "htp" is not NULL set "htp" to the hashtab_T used. + * When "namep" is not NULL set "namep" to the generated name, and + * then the caller gets ownership and is responsible for freeing the name. + */ + dictitem_T * +find_var_autoload_prefix(char_u *name, int sid, hashtab_T **htp, + char_u **namep) +{ + hashtab_T *ht; + dictitem_T *ret = NULL; // When using "vim9script autoload" script-local items are prefixed but can // be used with s:name. - if (SCRIPT_ID_VALID(current_sctx.sc_sid) + int check_sid = sid > 0 ? sid : current_sctx.sc_sid; + if (SCRIPT_ID_VALID(check_sid) && (in_vim9script() || (name[0] == 's' && name[1] == ':'))) { - scriptitem_T *si = SCRIPT_ITEM(current_sctx.sc_sid); + scriptitem_T *si = SCRIPT_ITEM(check_sid); if (si->sn_autoload_prefix != NULL) { @@ -3309,20 +3374,26 @@ find_var(char_u *name, hashtab_T **htp, int no_autoload) if (auto_name != NULL) { + int free_auto_name = TRUE; ht = &globvarht; ret = find_var_in_ht(ht, 'g', auto_name, TRUE); - vim_free(auto_name); if (ret != NULL) { if (htp != NULL) *htp = ht; - return ret; + if (namep != NULL) + { + free_auto_name = FALSE; + *namep = auto_name; + } } + if (free_auto_name) + vim_free(auto_name); } } } - return NULL; + return ret; } /* @@ -3462,7 +3533,11 @@ lookup_scriptitem( hi = hash_find(ht, p); res = HASHITEM_EMPTY(hi) ? FAIL : OK; - // if not script-local, then perhaps imported + // if not script-local, then perhaps autoload-exported + if (res == FAIL && find_var_autoload_prefix(p, 0, NULL, NULL) != NULL) + res = OK; + + // if not script-local or autoload, then perhaps imported if (res == FAIL && find_imported(p, 0, FALSE) != NULL) res = OK; if (p != buffer) @@ -3858,23 +3933,40 @@ set_var_const( if (sid != 0) { + varname = NULL; if (SCRIPT_ID_VALID(sid)) - ht = &SCRIPT_VARS(sid); - varname = name; + { + char_u *auto_name = NULL; + if (find_var_autoload_prefix(name, sid, &ht, &auto_name) != NULL) + { + var_in_autoload = TRUE; + varname = auto_name; + name_tofree = varname; + } + else + ht = &SCRIPT_VARS(sid); + } + if (varname == NULL) + varname = name; } else { - scriptitem_T *si; + scriptitem_T *si; + char_u *auto_name = NULL; - if (in_vim9script() && is_export - && SCRIPT_ID_VALID(current_sctx.sc_sid) - && (si = SCRIPT_ITEM(current_sctx.sc_sid)) - ->sn_autoload_prefix != NULL) + if (in_vim9script() + && SCRIPT_ID_VALID(current_sctx.sc_sid) + && (si = SCRIPT_ITEM(current_sctx.sc_sid)) + ->sn_autoload_prefix != NULL + && (is_export + || find_var_autoload_prefix(name, 0, NULL, &auto_name) + != NULL)) { // In a vim9 autoload script an exported variable is put in the // global namespace with the autoload prefix. var_in_autoload = TRUE; - varname = concat_str(si->sn_autoload_prefix, name); + varname = auto_name != NULL ? auto_name + : concat_str(si->sn_autoload_prefix, name); if (varname == NULL) goto failed; name_tofree = varname; @@ -4143,6 +4235,7 @@ failed: * - Whether the variable is read-only * - Whether the variable value is locked * - Whether the variable is locked + * NOTE: "name" is only used for error messages. */ int var_check_permission(dictitem_T *di, char_u *name) diff --git a/src/ex_cmds.c b/src/ex_cmds.c index 864f89d..2a5d842 100644 --- a/src/ex_cmds.c +++ b/src/ex_cmds.c @@ -2961,7 +2961,7 @@ do_ecmd( // Since we are starting to edit a file, consider the filetype to be // unset. Helps for when an autocommand changes files and expects syntax // highlighting to work in the other file. - did_filetype = FALSE; + curbuf->b_did_filetype = FALSE; /* * other_file oldbuf diff --git a/src/ex_cmds.h b/src/ex_cmds.h index bd26e81..70e5770 100644 --- a/src/ex_cmds.h +++ b/src/ex_cmds.h @@ -99,13 +99,14 @@ typedef struct exarg exarg_T; */ #ifdef DO_DECLARE_EXCMD # define EXCMD(a, b, c, d, e) \ - {(char_u *)b, c, (long_u)(d), e} + {(char_u *)b, STRLEN_LITERAL(b), c, (long_u)(d), e} typedef void (*ex_func_T) (exarg_T *eap); static struct cmdname { char_u *cmd_name; // name of the command + size_t cmd_namelen; // length of the command name ex_func_T cmd_func; // function for this command long_u cmd_argt; // flags declared above cmd_addr_T cmd_addr_type; // flag for address type @@ -595,7 +596,7 @@ EXCMD(CMD_endwhile, "endwhile", ex_endwhile, EXCMD(CMD_enew, "enew", ex_edit, EX_BANG|EX_TRLBAR, ADDR_NONE), -EXCMD(CMD_enum, "enum", ex_enum, +EXCMD(CMD_enum, "enum", ex_class, EX_EXTRA|EX_TRLBAR|EX_CMDWIN|EX_LOCK_OK|EX_EXPORT, ADDR_NONE), EXCMD(CMD_eval, "eval", ex_eval, diff --git a/src/ex_cmds2.c b/src/ex_cmds2.c index 4a6f519..ce30b8d 100644 --- a/src/ex_cmds2.c +++ b/src/ex_cmds2.c @@ -163,7 +163,7 @@ dialog_changed( char_u buff[DIALOG_MSG_SIZE]; int ret; buf_T *buf2; - exarg_T ea; + exarg_T ea; dialog_msg(buff, _("Save changes to \"%s\"?"), buf->b_fname); if (checkall) @@ -177,14 +177,31 @@ dialog_changed( if (ret == VIM_YES) { + int empty_bufname; + #ifdef FEAT_BROWSE // May get file name, when there is none browse_save_fname(buf); #endif - if (buf->b_fname != NULL && check_overwrite(&ea, buf, - buf->b_fname, buf->b_ffname, FALSE) == OK) + empty_bufname = buf->b_fname == NULL ? TRUE : FALSE; + if (empty_bufname) + buf_set_name(buf->b_fnum, (char_u *)"Untitled"); + + if (check_overwrite(&ea, buf, buf->b_fname, buf->b_ffname, FALSE) == OK) + { // didn't hit Cancel - (void)buf_write_all(buf, FALSE); + if (buf_write_all(buf, FALSE) == OK) + return; + } + + // restore to empty when write failed + if (empty_bufname) + { + VIM_CLEAR(buf->b_fname); + VIM_CLEAR(buf->b_ffname); + VIM_CLEAR(buf->b_sfname); + unchanged(buf, TRUE, FALSE); + } } else if (ret == VIM_NO) { diff --git a/src/ex_docmd.c b/src/ex_docmd.c index 19b1d85..a588f26 100644 --- a/src/ex_docmd.c +++ b/src/ex_docmd.c @@ -19,6 +19,10 @@ static int ex_pressedreturn = FALSE; # define ex_hardcopy ex_ni #endif +#if defined(FEAT_EVAL) || defined(PROTO) +static int cmp_cmdmod_info(const void *a, const void *b); +#endif + #ifdef FEAT_EVAL static char_u *do_one_cmd(char_u **, int, cstack_T *, char_u *(*fgetline)(int, void *, int, getline_opt_T), void *cookie); #else @@ -82,7 +86,7 @@ static void correct_range(exarg_T *eap); #ifdef FEAT_QUICKFIX static char_u *replace_makeprg(exarg_T *eap, char_u *p, char_u **cmdlinep); #endif -static char_u *repl_cmdline(exarg_T *eap, char_u *src, int srclen, char_u *repl, char_u **cmdlinep); +static char_u *repl_cmdline(exarg_T *eap, char_u *src, size_t srclen, char_u *repl, char_u **cmdlinep); static void ex_highlight(exarg_T *eap); static void ex_colorscheme(exarg_T *eap); static void ex_cquit(exarg_T *eap); @@ -461,6 +465,40 @@ restore_dbg_stuff(struct dbg_stuff *dsp) #endif /* + * Check if ffname differs from fnum. + * fnum is a buffer number. 0 == current buffer, 1-or-more must be a valid buffer ID. + * ffname is a full path to where a buffer lives on-disk or would live on-disk. + * + */ + static int +is_other_file(int fnum, char_u *ffname) +{ + if (fnum != 0) + { + if (fnum == curbuf->b_fnum) + return FALSE; + + return TRUE; + } + + if (ffname == NULL) + return TRUE; + + if (*ffname == NUL) + return FALSE; + + // TODO: Need a reliable way to know whether a buffer is meant to live on-disk + // !curbuf->b_dev_valid is not always available (example: missing on Windows) + if (curbuf->b_sfname != NULL + && *curbuf->b_sfname != NUL) + // This occurs with unsaved buffers. In which case `ffname` + // actually corresponds to curbuf->b_sfname + return fnamecmp(ffname, curbuf->b_sfname) != 0; + + return otherfile(ffname); +} + +/* * do_exmode(): Repeatedly get commands for the "Ex" mode, until the ":vi" * command is given. */ @@ -2911,7 +2949,7 @@ parse_command_modifiers( switch (*p) { - // When adding an entry, also modify cmdmods[]. + // When adding an entry, also modify cmdmod_info_tab[]. case 'a': if (!checkforcmd_noparen(&eap->cmd, "aboveleft", 3)) break; cmod->cmod_split |= WSP_ABOVE; @@ -3921,7 +3959,7 @@ find_ex_command( if (eap->cmdidx == CMD_mode || eap->cmdidx == CMD_Print) eap->cmdidx = CMD_SIZE; else if ((cmdnames[eap->cmdidx].cmd_argt & EX_WHOLE) - && len < (int)STRLEN(cmdnames[eap->cmdidx].cmd_name)) + && len < (int)cmdnames[eap->cmdidx].cmd_namelen) { semsg(_(e_command_cannot_be_shortened_str), eap->cmd); eap->cmdidx = CMD_SIZE; @@ -3970,12 +4008,14 @@ find_ex_command( } #if defined(FEAT_EVAL) || defined(PROTO) -static struct cmdmod +typedef struct { char *name; int minlen; int has_count; // :123verbose :3tab -} cmdmods[] = { +} cmdmod_info_T; + +static cmdmod_info_T cmdmod_info_tab[] = { {"aboveleft", 3, FALSE}, {"belowright", 3, FALSE}, {"botright", 2, FALSE}, @@ -4001,8 +4041,18 @@ static struct cmdmod {"unsilent", 3, FALSE}, {"verbose", 4, TRUE}, {"vertical", 4, FALSE}, - {"vim9cmd", 4, FALSE}, -}; + {"vim9cmd", 4, FALSE} +}; // cmdmod_info_tab + +// compare two cmdmod_info_T structs by case sensitive name with length + static int +cmp_cmdmod_info(const void *a, const void *b) +{ + cmdmod_info_T *cm1 = (cmdmod_info_T *)a; + cmdmod_info_T *cm2 = (cmdmod_info_T *)b; + + return STRNCMP(cm1->name, cm2->name, cm2->minlen); +} /* * Return length of a command modifier (including optional count). @@ -4011,20 +4061,36 @@ static struct cmdmod int modifier_len(char_u *cmd) { - int i, j; char_u *p = cmd; + cmdmod_info_T target; + cmdmod_info_T *entry; if (VIM_ISDIGIT(*cmd)) p = skipwhite(skipdigits(cmd + 1)); - for (i = 0; i < (int)ARRAY_LENGTH(cmdmods); ++i) + + // only lowercase characters can match + if (!ASCII_ISLOWER(*p)) + return 0; + + target.name = (char *)p; + target.minlen = 0; // not used, see cmp_cmdmod_info() + target.has_count = FALSE; + + entry = (cmdmod_info_T *)bsearch(&target, &cmdmod_info_tab, ARRAY_LENGTH(cmdmod_info_tab), sizeof(cmdmod_info_tab[0]), cmp_cmdmod_info); + if (entry != NULL) { - for (j = 0; p[j] != NUL; ++j) - if (p[j] != cmdmods[i].name[j]) + int i; + + for (i = entry->minlen; p[i] != NUL; ++i) + { + if (p[i] != entry->name[i]) break; - if (!ASCII_ISALPHA(p[j]) && j >= cmdmods[i].minlen - && (p == cmd || cmdmods[i].has_count)) - return j + (int)(p - cmd); + } + + if (!ASCII_ISALPHA(p[i]) && i >= entry->minlen && (p == cmd || entry->has_count)) + return i + (int)(p - cmd); } + return 0; } @@ -4038,18 +4104,33 @@ cmd_exists(char_u *name) { exarg_T ea; int full = FALSE; - int i; - int j; char_u *p; - // Check command modifiers. - for (i = 0; i < (int)ARRAY_LENGTH(cmdmods); ++i) + // only lowercase characters can match + if (ASCII_ISLOWER(*name)) { - for (j = 0; name[j] != NUL; ++j) - if (name[j] != cmdmods[i].name[j]) - break; - if (name[j] == NUL && j >= cmdmods[i].minlen) - return (cmdmods[i].name[j] == NUL ? 2 : 1); + cmdmod_info_T target; + cmdmod_info_T *entry; + + target.name = (char *)name; + target.minlen = 0; // not used, see cmp_cmdmod_info() + target.has_count = FALSE; + + // Check command modifiers. + entry = (cmdmod_info_T *)bsearch(&target, &cmdmod_info_tab, ARRAY_LENGTH(cmdmod_info_tab), sizeof(cmdmod_info_tab[0]), cmp_cmdmod_info); + if (entry != NULL) + { + int i; + + for (i = entry->minlen; name[i] != NUL; ++i) + { + if (name[i] != entry->name[i]) + break; + } + + if (name[i] == NUL && i >= entry->minlen) + return (entry->name[i] == NUL ? 2 : 1); + } } // Check built-in commands and user defined commands. @@ -4963,12 +5044,14 @@ replace_makeprg(exarg_T *eap, char_u *p, char_u **cmdlinep) } else { - new_cmdline = alloc(STRLEN(program) + STRLEN(p) + 2); + size_t program_len = STRLEN(program); + + new_cmdline = alloc(program_len + STRLEN(p) + 2); if (new_cmdline == NULL) return NULL; // out of memory STRCPY(new_cmdline, program); - STRCAT(new_cmdline, " "); - STRCAT(new_cmdline, p); + STRCPY(new_cmdline + program_len, " "); + STRCPY(new_cmdline + program_len + 1, p); } msg_make(p); @@ -5118,7 +5201,7 @@ expand_filename( } } - p = repl_cmdline(eap, p, srclen, repl, cmdlinep); + p = repl_cmdline(eap, p, (size_t)srclen, repl, cmdlinep); vim_free(repl); if (p == NULL) return FAIL; @@ -5189,7 +5272,7 @@ expand_filename( } if (p != NULL) { - (void)repl_cmdline(eap, eap->arg, (int)STRLEN(eap->arg), + (void)repl_cmdline(eap, eap->arg, STRLEN(eap->arg), p, cmdlinep); if (n == 2) // p came from ExpandOne() vim_free(p); @@ -5212,23 +5295,26 @@ expand_filename( repl_cmdline( exarg_T *eap, char_u *src, - int srclen, + size_t srclen, char_u *repl, char_u **cmdlinep) { - int len; - int i; + size_t repllen; + size_t taillen; + size_t i; char_u *new_cmdline; + size_t new_cmdlinelen; /* * The new command line is build in new_cmdline[]. * First allocate it. * Careful: a "+cmd" argument may have been NUL terminated. */ - len = (int)STRLEN(repl); - i = (int)(src - *cmdlinep) + (int)STRLEN(src + srclen) + len + 3; + repllen = STRLEN(repl); + taillen = STRLEN(src + srclen); + i = (src - *cmdlinep) + repllen + taillen + 3; if (eap->nextcmd != NULL) - i += (int)STRLEN(eap->nextcmd);// add space for next command + i += STRLEN(eap->nextcmd); // add space for next command if ((new_cmdline = alloc(i)) == NULL) return NULL; // out of memory! @@ -5238,19 +5324,19 @@ repl_cmdline( * Copy what came after the expanded part. * Copy the next commands, if there are any. */ - i = (int)(src - *cmdlinep); // length of part before match - mch_memmove(new_cmdline, *cmdlinep, (size_t)i); + new_cmdlinelen = src - *cmdlinep; // length of part before replacement + mch_memmove(new_cmdline, *cmdlinep, new_cmdlinelen); - mch_memmove(new_cmdline + i, repl, (size_t)len); - i += len; // remember the end of the string - STRCPY(new_cmdline + i, src + srclen); - src = new_cmdline + i; // remember where to continue + mch_memmove(new_cmdline + new_cmdlinelen, repl, repllen); + new_cmdlinelen += repllen; // remember the end of the string + STRCPY(new_cmdline + new_cmdlinelen, src + srclen); + src = new_cmdline + new_cmdlinelen; // remember where to continue if (eap->nextcmd != NULL) // append next command { - i = (int)STRLEN(new_cmdline) + 1; - STRCPY(new_cmdline + i, eap->nextcmd); - eap->nextcmd = new_cmdline + i; + new_cmdlinelen += taillen + 1; + STRCPY(new_cmdline + new_cmdlinelen, eap->nextcmd); + eap->nextcmd = new_cmdline + new_cmdlinelen; } eap->cmd = new_cmdline + (eap->cmd - *cmdlinep); eap->arg = new_cmdline + (eap->arg - *cmdlinep); @@ -5421,9 +5507,10 @@ get_bad_name(expand_T *xp UNUSED, int idx) "drop", }; - if (idx < (int)ARRAY_LENGTH(p_bad_values)) - return (char_u*)p_bad_values[idx]; - return NULL; + if (idx < 0 || idx >= (int)ARRAY_LENGTH(p_bad_values)) + return NULL; + + return (char_u*)p_bad_values[idx]; } /* @@ -5537,9 +5624,10 @@ get_argopt_name(expand_T *xp UNUSED, int idx) "edit", }; - if (idx < (int)ARRAY_LENGTH(p_opt_values)) - return (char_u*)p_opt_values[idx]; - return NULL; + if (idx < 0 || idx >= (int)ARRAY_LENGTH(p_opt_values)) + return NULL; + + return (char_u*)p_opt_values[idx]; } /* @@ -6317,11 +6405,19 @@ get_tabpage_arg(exarg_T *eap) else { tab_number = eap->line2; - if (!unaccept_arg0 && *skipwhite(*eap->cmdlinep) == '-') + if (!unaccept_arg0) { - --tab_number; - if (tab_number < unaccept_arg0) - eap->errmsg = _(e_invalid_range); + char_u *cmdp = eap->cmd; + + while (--cmdp > *eap->cmdlinep + && (VIM_ISWHITE(*cmdp) || VIM_ISDIGIT(*cmdp))) + ; + if (*cmdp == '-') + { + --tab_number; + if (tab_number < unaccept_arg0) + eap->errmsg = _(e_invalid_range); + } } } } @@ -7248,12 +7344,15 @@ ex_open(exarg_T *eap) static void ex_edit(exarg_T *eap) { + char_u *ffname = eap->cmdidx == CMD_enew ? NULL : eap->arg; + // Exclude commands which keep the window's current buffer if ( eap->cmdidx != CMD_badd && eap->cmdidx != CMD_balt // All other commands must obey 'winfixbuf' / ! rules - && !check_can_set_curbuf_forceit(eap->forceit)) + && (is_other_file(0, ffname) && !check_can_set_curbuf_forceit(eap->forceit)) + ) return; do_exedit(eap, NULL); @@ -9237,6 +9336,27 @@ ex_tag_cmd(exarg_T *eap, char_u *name) eap->forceit, TRUE); } +enum { + SPEC_PERC = 0, + SPEC_HASH, + SPEC_CWORD, // cursor word + SPEC_CCWORD, // cursor WORD + SPEC_CEXPR, // expr under cursor + SPEC_CFILE, // cursor path name + SPEC_SFILE, // ":so" file name + SPEC_SLNUM, // ":so" file line number + SPEC_STACK, // call stack + SPEC_SCRIPT, // script file name + SPEC_AFILE, // autocommand file name + SPEC_ABUF, // autocommand buffer number + SPEC_AMATCH, // autocommand match name + SPEC_SFLNUM, // script file line number + SPEC_SID // script ID: <SNR>123_ +#ifdef FEAT_CLIENTSERVER + , SPEC_CLIENT +#endif +}; + /* * Check "str" for starting with a special cmdline variable. * If found return one of the SPEC_ values and set "*usedlen" to the length of @@ -9245,54 +9365,54 @@ ex_tag_cmd(exarg_T *eap, char_u *name) int find_cmdline_var(char_u *src, int *usedlen) { - int len; - int i; - static char *(spec_str[]) = { - "%", -#define SPEC_PERC 0 - "#", -#define SPEC_HASH (SPEC_PERC + 1) - "<cword>", // cursor word -#define SPEC_CWORD (SPEC_HASH + 1) - "<cWORD>", // cursor WORD -#define SPEC_CCWORD (SPEC_CWORD + 1) - "<cexpr>", // expr under cursor -#define SPEC_CEXPR (SPEC_CCWORD + 1) - "<cfile>", // cursor path name -#define SPEC_CFILE (SPEC_CEXPR + 1) - "<sfile>", // ":so" file name -#define SPEC_SFILE (SPEC_CFILE + 1) - "<slnum>", // ":so" file line number -#define SPEC_SLNUM (SPEC_SFILE + 1) - "<stack>", // call stack -#define SPEC_STACK (SPEC_SLNUM + 1) - "<script>", // script file name -#define SPEC_SCRIPT (SPEC_STACK + 1) - "<afile>", // autocommand file name -#define SPEC_AFILE (SPEC_SCRIPT + 1) - "<abuf>", // autocommand buffer number -#define SPEC_ABUF (SPEC_AFILE + 1) - "<amatch>", // autocommand match name -#define SPEC_AMATCH (SPEC_ABUF + 1) - "<sflnum>", // script file line number -#define SPEC_SFLNUM (SPEC_AMATCH + 1) - "<SID>", // script ID: <SNR>123_ -#define SPEC_SID (SPEC_SFLNUM + 1) + // must be sorted by the 'value' field because it is used by bsearch()! + static keyvalue_T spec_str_tab[] = { + KEYVALUE_ENTRY(SPEC_SID, "SID>"), // script ID: <SNR>123_ + KEYVALUE_ENTRY(SPEC_ABUF, "abuf>"), // autocommand buffer number + KEYVALUE_ENTRY(SPEC_AFILE, "afile>"), // autocommand file name + KEYVALUE_ENTRY(SPEC_AMATCH, "amatch>"), // autocommand match name + KEYVALUE_ENTRY(SPEC_CCWORD, "cWORD>"), // cursor WORD + KEYVALUE_ENTRY(SPEC_CEXPR, "cexpr>"), // expr under cursor + KEYVALUE_ENTRY(SPEC_CFILE, "cfile>"), // cursor path name #ifdef FEAT_CLIENTSERVER - "<client>" -# define SPEC_CLIENT (SPEC_SID + 1) -#endif + KEYVALUE_ENTRY(SPEC_CLIENT, "client>"), +#endif + KEYVALUE_ENTRY(SPEC_CWORD, "cword>"), // cursor word + KEYVALUE_ENTRY(SPEC_SCRIPT, "script>"), // script file name + KEYVALUE_ENTRY(SPEC_SFILE, "sfile>"), // ":so" file name + KEYVALUE_ENTRY(SPEC_SFLNUM, "sflnum>"), // script file line number + KEYVALUE_ENTRY(SPEC_SLNUM, "slnum>"), // ":so" file line number + KEYVALUE_ENTRY(SPEC_STACK, "stack>") // call stack }; + keyvalue_T target; + keyvalue_T *entry; - for (i = 0; i < (int)ARRAY_LENGTH(spec_str); ++i) + switch (*src) { - len = (int)STRLEN(spec_str[i]); - if (STRNCMP(src, spec_str[i], len) == 0) - { - *usedlen = len; - return i; - } + case '%': + *usedlen = 1; + return SPEC_PERC; + + case '#': + *usedlen = 1; + return SPEC_HASH; + + case '<': + target.key = 0; + target.value = (char *)src + 1; // skip over '<' + target.length = 0; // not used, see cmp_keyvalue_value_n() + + entry = (keyvalue_T *)bsearch(&target, &spec_str_tab, ARRAY_LENGTH(spec_str_tab), sizeof(spec_str_tab[0]), cmp_keyvalue_value_n); + if (entry == NULL) + return -1; + + *usedlen = entry->length + 1; + return entry->key; + + default: + break; } + return -1; } @@ -9655,14 +9775,17 @@ eval_vars( expand_sfile(char_u *arg) { char *errormsg; - int len; char_u *result; + size_t resultlen; char_u *newres; + size_t len; char_u *repl; + size_t repllen; int srclen; char_u *p; - result = vim_strsave(arg); + resultlen = STRLEN(arg); + result = vim_strnsave(arg, resultlen); if (result == NULL) return NULL; @@ -9686,18 +9809,20 @@ expand_sfile(char_u *arg) p += srclen; continue; } - len = (int)STRLEN(result) - srclen + (int)STRLEN(repl) + 1; - newres = alloc(len); + repllen = STRLEN(repl); + resultlen += repllen - srclen; + newres = alloc(resultlen + 1); if (newres == NULL) { vim_free(repl); vim_free(result); return NULL; } - mch_memmove(newres, result, (size_t)(p - result)); - STRCPY(newres + (p - result), repl); - len = (int)STRLEN(newres); - STRCAT(newres, p + srclen); + len = p - result; + mch_memmove(newres, result, len); + STRCPY(newres + len, repl); + len += repllen; + STRCPY(newres + len, p + srclen); vim_free(repl); vim_free(result); result = newres; @@ -9853,7 +9978,7 @@ ex_filetype(exarg_T *eap) static void ex_setfiletype(exarg_T *eap) { - if (did_filetype) + if (curbuf->b_did_filetype) return; char_u *arg = eap->arg; @@ -9862,7 +9987,7 @@ ex_setfiletype(exarg_T *eap) set_option_value_give_err((char_u *)"filetype", 0L, arg, OPT_LOCAL); if (arg != eap->arg) - did_filetype = FALSE; + curbuf->b_did_filetype = FALSE; } static void diff --git a/src/fileio.c b/src/fileio.c index 53bfbea..07e05fc 100644 --- a/src/fileio.c +++ b/src/fileio.c @@ -225,7 +225,7 @@ readfile( int may_need_lseek = FALSE; #endif - au_did_filetype = FALSE; // reset before triggering any autocommands + curbuf->b_au_did_filetype = FALSE; // reset before triggering any autocommands curbuf->b_no_eol_lnum = 0; // in case it was set by the previous read @@ -2696,7 +2696,7 @@ failed: { apply_autocmds_exarg(EVENT_BUFREADPOST, NULL, sfname, FALSE, curbuf, eap); - if (!au_did_filetype && *curbuf->b_p_ft != NUL) + if (!curbuf->b_au_did_filetype && *curbuf->b_p_ft != NUL) /* * EVENT_FILETYPE was not triggered but the buffer already has a * filetype. Trigger EVENT_FILETYPE using the existing filetype. @@ -4492,7 +4492,7 @@ buf_reload(buf_T *buf, int orig_mode, int reload_options) int old_msg_silent = msg_silent; curbuf->b_flags |= BF_CHECK_RO; // check for RO again - keep_filetype = TRUE; // don't detect 'filetype' + curbuf->b_keep_filetype = TRUE; // don't detect 'filetype' if (shortmess(SHM_FILEINFO)) msg_silent = 1; @@ -4549,7 +4549,7 @@ buf_reload(buf_T *buf, int orig_mode, int reload_options) curwin->w_cursor = old_cursor; check_cursor(); update_topline(); - keep_filetype = FALSE; + curbuf->b_keep_filetype = FALSE; #ifdef FEAT_FOLDING { win_T *wp; diff --git a/src/filepath.c b/src/filepath.c index cbf2da4..3bf8a2d 100644 --- a/src/filepath.c +++ b/src/filepath.c @@ -2110,6 +2110,7 @@ f_resolve(typval_T *argvars, typval_T *rettv) if (buf == NULL) { vim_free(p); + vim_free(remain); goto fail; } diff --git a/src/getchar.c b/src/getchar.c index 49a24f0..1c544da 100644 --- a/src/getchar.c +++ b/src/getchar.c @@ -81,7 +81,7 @@ static int KeyNoremap = 0; // remapping flags static char_u typebuf_init[TYPELEN_INIT]; // initial typebuf.tb_buf static char_u noremapbuf_init[TYPELEN_INIT]; // initial typebuf.tb_noremap -static int last_recorded_len = 0; // number of last recorded chars +static size_t last_recorded_len = 0; // number of last recorded chars #ifdef FEAT_EVAL mapblock_T *last_used_map = NULL; @@ -163,7 +163,7 @@ get_recorded(void) * (possibly mapped) characters that stopped the recording. */ len = STRLEN(p); - if ((int)len >= last_recorded_len) + if (len >= last_recorded_len) { len -= last_recorded_len; p[len] = NUL; @@ -1282,50 +1282,104 @@ del_typebuf(int len, int offset) } /* + * State for adding bytes to a recording or 'showcmd'. + */ +typedef struct +{ + char_u buf[MB_MAXBYTES * 3 + 4]; + int prev_c; + size_t buflen; + unsigned pending_special; + unsigned pending_mbyte; +} gotchars_state_T; + +/* + * Add a single byte to a recording or 'showcmd'. + * Return TRUE if a full key has been received, FALSE otherwise. + */ + static int +gotchars_add_byte(gotchars_state_T *state, char_u byte) +{ + int c = state->buf[state->buflen++] = byte; + int retval = FALSE; + int in_special = state->pending_special > 0; + int in_mbyte = state->pending_mbyte > 0; + + if (in_special) + state->pending_special--; + else if (c == K_SPECIAL +#ifdef FEAT_GUI + || c == CSI +#endif + ) + // When receiving a special key sequence, store it until we have all + // the bytes and we can decide what to do with it. + state->pending_special = 2; + + if (state->pending_special > 0) + goto ret_false; + + if (in_mbyte) + state->pending_mbyte--; + else + { + if (in_special) + { + if (state->prev_c == KS_MODIFIER) + // When receiving a modifier, wait for the modified key. + goto ret_false; + c = TO_SPECIAL(state->prev_c, c); + if (c == K_FOCUSGAINED || c == K_FOCUSLOST) + // Drop K_FOCUSGAINED and K_FOCUSLOST, they are not useful + // in a recording. + state->buflen = 0; + } + // When receiving a multibyte character, store it until we have all + // the bytes, so that it won't be split between two buffer blocks, + // and delete_buff_tail() will work properly. + state->pending_mbyte = MB_BYTE2LEN_CHECK(c) - 1; + } + + if (state->pending_mbyte > 0) + goto ret_false; + + retval = TRUE; +ret_false: + state->prev_c = c; + return retval; +} + +/* * Write typed characters to script file. - * If recording is on put the character in the recordbuffer. + * If recording is on put the character in the record buffer. */ static void gotchars(char_u *chars, int len) { char_u *s = chars; - int i; - static char_u buf[4]; - static int buflen = 0; + size_t i; int todo = len; + static gotchars_state_T state; - while (todo--) + while (todo-- > 0) { - buf[buflen++] = *s++; - - // When receiving a special key sequence, store it until we have all - // the bytes and we can decide what to do with it. - if (buflen == 1 && buf[0] == K_SPECIAL) - continue; - if (buflen == 2) + if (!gotchars_add_byte(&state, *s++)) continue; - if (buflen == 3 && buf[1] == KS_EXTRA - && (buf[2] == KE_FOCUSGAINED || buf[2] == KE_FOCUSLOST)) - { - // Drop K_FOCUSGAINED and K_FOCUSLOST, they are not useful in a - // recording. - buflen = 0; - continue; - } // Handle one byte at a time; no translation to be done. - for (i = 0; i < buflen; ++i) - updatescript(buf[i]); + for (i = 0; i < state.buflen; ++i) + updatescript(state.buf[i]); if (reg_recording != 0) { - buf[buflen] = NUL; - add_buff(&recordbuff, buf, (long)buflen); + state.buf[state.buflen] = NUL; + add_buff(&recordbuff, state.buf, (long)state.buflen); // remember how many chars were last recorded - last_recorded_len += buflen; + last_recorded_len += state.buflen; } - buflen = 0; + state.buflen = 0; } + may_sync_undo(); #ifdef FEAT_EVAL @@ -1713,6 +1767,67 @@ merge_modifyOtherKeys(int c_arg, int *modifiers) } /* + * Add a single byte to 'showcmd' for a partially matched mapping. + * Call add_to_showcmd() if a full key has been received. + */ + static void +add_byte_to_showcmd(char_u byte) +{ + static gotchars_state_T state; + char_u *ptr; + int modifiers = 0; + int c = NUL; + + if (!p_sc || msg_silent != 0) + return; + + if (!gotchars_add_byte(&state, byte)) + return; + + state.buf[state.buflen] = NUL; + state.buflen = 0; + + ptr = state.buf; + if (ptr[0] == K_SPECIAL && ptr[1] == KS_MODIFIER && ptr[2] != NUL) + { + modifiers = ptr[2]; + ptr += 3; + } + + if (*ptr != NUL) + { + char_u *mb_ptr = mb_unescape(&ptr); + + c = mb_ptr != NULL ? (*mb_ptr2char)(mb_ptr) : *ptr++; + if (c <= 0x7f) + { + // Merge modifiers into the key to make the result more readable. + int modifiers_after = modifiers; + int mod_c = merge_modifyOtherKeys(c, &modifiers_after); + + if (modifiers_after == 0) + { + modifiers = 0; + c = mod_c; + } + } + } + + // TODO: is there a more readable and yet compact representation of + // modifiers and special keys? + if (modifiers != 0) + { + add_to_showcmd(K_SPECIAL); + add_to_showcmd(KS_MODIFIER); + add_to_showcmd(modifiers); + } + if (c != NUL) + add_to_showcmd(c); + while (*ptr != NUL) + add_to_showcmd(*ptr++); +} + +/* * Get the next input character. * Can return a special key or a multi-byte character. * Can return NUL when called recursively, use safe_vgetc() if that's not @@ -1751,7 +1866,7 @@ vgetc(void) else { // number of characters recorded from the last vgetc() call - static int last_vgetc_recorded_len = 0; + static size_t last_vgetc_recorded_len = 0; mod_mask = 0; vgetc_mod_mask = 0; @@ -3544,7 +3659,7 @@ vgetorpeek(int advance) if (typebuf.tb_len > SHOWCMD_COLS) showcmd_idx = typebuf.tb_len - SHOWCMD_COLS; while (showcmd_idx < typebuf.tb_len) - (void)add_to_showcmd( + add_byte_to_showcmd( typebuf.tb_buf[typebuf.tb_off + showcmd_idx++]); curwin->w_wcol = old_wcol; curwin->w_wrow = old_wrow; diff --git a/src/globals.h b/src/globals.h index f04f19d..2c00e5f 100644 --- a/src/globals.h +++ b/src/globals.h @@ -540,7 +540,10 @@ EXTERN int garbage_collect_at_exit INIT(= FALSE); #define t_class (static_types[84]) #define t_const_class (static_types[85]) -EXTERN type_T static_types[86] +#define t_typealias (static_types[86]) +#define t_const_typealias (static_types[87]) + +EXTERN type_T static_types[88] #ifdef DO_INIT = { // 0: t_unknown @@ -714,6 +717,10 @@ EXTERN type_T static_types[86] // 84: t_class {VAR_CLASS, 0, 0, TTFLAG_STATIC, NULL, NULL, NULL}, {VAR_CLASS, 0, 0, TTFLAG_STATIC|TTFLAG_CONST, NULL, NULL, NULL}, + + // 86: t_typealias + {VAR_TYPEALIAS, 0, 0, TTFLAG_STATIC, NULL, NULL, NULL}, + {VAR_TYPEALIAS, 0, 0, TTFLAG_STATIC|TTFLAG_CONST, NULL, NULL, NULL}, } #endif ; @@ -796,20 +803,6 @@ EXTERN int autocmd_no_enter INIT(= FALSE); // Buf/WinEnter autocmds disabled EXTERN int autocmd_no_leave INIT(= FALSE); // Buf/WinLeave autocmds disabled EXTERN int tabpage_move_disallowed INIT(= FALSE); // moving tabpages around disallowed -EXTERN int modified_was_set; // did ":set modified" -EXTERN int did_filetype INIT(= FALSE); // FileType event found -EXTERN int keep_filetype INIT(= FALSE); // value for did_filetype when - // starting to execute - // autocommands - -// Set by the apply_autocmds_group function if the given event is equal to -// EVENT_FILETYPE. Used by the readfile function in order to determine if -// EVENT_BUFREADPOST triggered the EVENT_FILETYPE. -// -// Relying on this value requires one to reset it prior calling -// apply_autocmds_group. -EXTERN int au_did_filetype INIT(= FALSE); - // When deleting the current buffer, another one must be loaded. If we know // which one is preferred, au_new_curbuf is set to it EXTERN bufref_T au_new_curbuf INIT3(NULL, 0, 0); diff --git a/src/gui_gtk_x11.c b/src/gui_gtk_x11.c index d4a8b93..4d201fc 100644 --- a/src/gui_gtk_x11.c +++ b/src/gui_gtk_x11.c @@ -2152,6 +2152,9 @@ scroll_event(GtkWidget *widget, FALSE, vim_modifiers); } } + else if (event->direction == GDK_SCROLL_SMOOTH && display_type == DT_X11) + // for X11 we deal with unsmooth events, and so ignore the smooth ones + ; else #undef DT_X11 #undef DT_WAYLAND diff --git a/src/gui_motif.c b/src/gui_motif.c index 630082e..ed721b5 100644 --- a/src/gui_motif.c +++ b/src/gui_motif.c @@ -2732,7 +2732,10 @@ gui_mch_dialog( // Motif. label = XmStringCreateLtoR((char *)message, STRING_TAG); if (label == NULL) + { + vim_free(buttons); return -1; + } w = XtVaCreateManagedWidget("dialogMessage", xmLabelGadgetClass, form, XmNlabelString, label, diff --git a/src/highlight.c b/src/highlight.c index 9b3b072..9aa149f 100644 --- a/src/highlight.c +++ b/src/highlight.c @@ -24,19 +24,110 @@ * The "term", "cterm" and "gui" arguments can be any combination of the * following names, separated by commas (but no spaces!). */ -static char *(hl_name_table[]) = - {"bold", "standout", "underline", - "undercurl", "underdouble", "underdotted", "underdashed", - "italic", "reverse", "inverse", "nocombine", "strikethrough", "NONE"}; -static int hl_attr_table[] = - {HL_BOLD, HL_STANDOUT, HL_UNDERLINE, - HL_UNDERCURL, HL_UNDERDOUBLE, HL_UNDERDOTTED, HL_UNDERDASHED, - HL_ITALIC, HL_INVERSE, HL_INVERSE, HL_NOCOMBINE, HL_STRIKETHROUGH, 0}; +// must be sorted by the 'value' field because it is used by bsearch()! +// note: inverse and reverse use the same key +static keyvalue_T highlight_tab[] = { + KEYVALUE_ENTRY(HL_BOLD, "bold"), // index 0 + KEYVALUE_ENTRY(HL_INVERSE, "inverse"), // index 1 + KEYVALUE_ENTRY(HL_ITALIC, "italic"), // index 2 + KEYVALUE_ENTRY(HL_NOCOMBINE, "nocombine"), // index 3 + KEYVALUE_ENTRY(HL_NORMAL, "NONE"), // index 4 + KEYVALUE_ENTRY(HL_INVERSE, "reverse"), // index 5 + KEYVALUE_ENTRY(HL_STANDOUT, "standout"), // index 6 + KEYVALUE_ENTRY(HL_STRIKETHROUGH, "strikethrough"), // index 7 + KEYVALUE_ENTRY(HL_UNDERCURL, "undercurl"), // index 8 + KEYVALUE_ENTRY(HL_UNDERDASHED, "underdashed"), // index 9 + KEYVALUE_ENTRY(HL_UNDERDOTTED, "underdotted"), // index 10 + KEYVALUE_ENTRY(HL_UNDERDOUBLE, "underdouble"), // index 11 + KEYVALUE_ENTRY(HL_UNDERLINE, "underline") // index 12 +}; + +// this table is used to display highlight names in the "correct" sequence. +// keep this in sync with highlight_tab[]. +static keyvalue_T *highlight_index_tab[] = { + &highlight_tab[0], // HL_BOLD + &highlight_tab[6], // HL_STANDOUT + &highlight_tab[12], // HL_UNDERLINE + &highlight_tab[8], // HL_UNDERCURL + &highlight_tab[11], // HL_UNDERDOUBLE + &highlight_tab[10], // HL_UNDERDOTTED + &highlight_tab[9], // HL_UNDERDASHED + &highlight_tab[2], // HL_ITALIC + &highlight_tab[5], // HL_REVERSE + &highlight_tab[1], // HL_INVERSE + &highlight_tab[3], // HL_NOCOMBINE + &highlight_tab[7], // HL_STRIKETHROUGH + &highlight_tab[4] // HL_NORMAL +}; + // length of all attribute names, plus commas, together (and a bit more) #define MAX_ATTR_LEN 120 #define ATTR_COMBINE(attr_a, attr_b) ((((attr_b) & HL_NOCOMBINE) ? (attr_b) : (attr_a)) | (attr_b)) +enum { + BLACK = 0, + DARKBLUE, + DARKGREEN, + DARKCYAN, + DARKRED, + DARKMAGENTA, + BROWN, + DARKYELLOW, + GRAY, + GREY, + LIGHTGRAY, + LIGHTGREY, + DARKGRAY, + DARKGREY, + BLUE, + LIGHTBLUE, + GREEN, + LIGHTGREEN, + CYAN, + LIGHTCYAN, + RED, + LIGHTRED, + MAGENTA, + LIGHTMAGENTA, + YELLOW, + LIGHTYELLOW, + WHITE, + NONE +}; + +// must be sorted by the 'value' field because it is used by bsearch()! +static keyvalue_T color_name_tab[] = { + KEYVALUE_ENTRY(BLACK, "Black"), + KEYVALUE_ENTRY(BLUE, "Blue"), + KEYVALUE_ENTRY(BROWN, "Brown"), + KEYVALUE_ENTRY(CYAN, "Cyan"), + KEYVALUE_ENTRY(DARKBLUE, "DarkBlue"), + KEYVALUE_ENTRY(DARKCYAN, "DarkCyan"), + KEYVALUE_ENTRY(DARKGRAY, "DarkGray"), + KEYVALUE_ENTRY(DARKGREEN, "DarkGreen"), + KEYVALUE_ENTRY(DARKGREY, "DarkGrey"), + KEYVALUE_ENTRY(DARKMAGENTA, "DarkMagenta"), + KEYVALUE_ENTRY(DARKRED, "DarkRed"), + KEYVALUE_ENTRY(DARKYELLOW, "DarkYellow"), + KEYVALUE_ENTRY(GRAY, "Gray"), + KEYVALUE_ENTRY(GREEN, "Green"), + KEYVALUE_ENTRY(GREY, "Grey"), + KEYVALUE_ENTRY(LIGHTBLUE, "LightBlue"), + KEYVALUE_ENTRY(LIGHTCYAN, "LightCyan"), + KEYVALUE_ENTRY(LIGHTGRAY, "LightGray"), + KEYVALUE_ENTRY(LIGHTGREEN, "LightGreen"), + KEYVALUE_ENTRY(LIGHTGREY, "LightGrey"), + KEYVALUE_ENTRY(LIGHTMAGENTA, "LightMagenta"), + KEYVALUE_ENTRY(LIGHTRED, "LightRed"), + KEYVALUE_ENTRY(LIGHTYELLOW, "LightYellow"), + KEYVALUE_ENTRY(MAGENTA, "Magenta"), + KEYVALUE_ENTRY(NONE, "NONE"), + KEYVALUE_ENTRY(RED, "Red"), + KEYVALUE_ENTRY(WHITE, "White"), + KEYVALUE_ENTRY(YELLOW, "Yellow") +}; + /* * Structure that stores information about a highlight group. * The ID of a highlight group is also called group ID. It is the index in @@ -518,22 +609,6 @@ load_colors(char_u *name) return retval; } -static char *(color_names[28]) = { - "Black", "DarkBlue", "DarkGreen", "DarkCyan", - "DarkRed", "DarkMagenta", "Brown", "DarkYellow", - "Gray", "Grey", "LightGray", "LightGrey", - "DarkGray", "DarkGrey", - "Blue", "LightBlue", "Green", "LightGreen", - "Cyan", "LightCyan", "Red", "LightRed", "Magenta", - "LightMagenta", "Yellow", "LightYellow", "White", "NONE"}; - // indices: - // 0, 1, 2, 3, - // 4, 5, 6, 7, - // 8, 9, 10, 11, - // 12, 13, - // 14, 15, 16, 17, - // 18, 19, 20, 21, 22, - // 23, 24, 25, 26, 27 static int color_numbers_16[28] = {0, 1, 2, 3, 4, 5, 6, 6, 7, 7, 7, 7, @@ -568,7 +643,7 @@ static int color_numbers_8[28] = {0, 4, 2, 6, /* * Lookup the "cterm" value to be used for color with index "idx" in - * color_names[]. + * color_name_tab[]. * "boldp" will be set to TRUE or FALSE for a foreground color when using 8 * colors, otherwise it will be unchanged. */ @@ -785,29 +860,26 @@ highlight_reset_all(void) highlight_set_termgui_attr(int idx, char_u *key, char_u *arg, int init) { int attr; - int off; - long i; - int len; + size_t off; + keyvalue_T target; + keyvalue_T *entry; attr = 0; off = 0; + target.key = 0; + target.length = 0; // not used, see cmp_keyvalue_value_ni() while (arg[off] != NUL) { - for (i = ARRAY_LENGTH(hl_attr_table); --i >= 0; ) - { - len = (int)STRLEN(hl_name_table[i]); - if (STRNICMP(arg + off, hl_name_table[i], len) == 0) - { - attr |= hl_attr_table[i]; - off += len; - break; - } - } - if (i < 0) + target.value = (char *)arg + off; + entry = (keyvalue_T *)bsearch(&target, &highlight_tab, ARRAY_LENGTH(highlight_tab), sizeof(highlight_tab[0]), cmp_keyvalue_value_ni); + if (entry == NULL) { semsg(_(e_illegal_value_str), arg); return FALSE; } + + attr |= entry->key; + off += entry->length; if (arg[off] == ',') // another one follows ++off; } @@ -1086,8 +1158,6 @@ highlight_set_cterm_color( int init) { int color; - long i; - int off; if (init && (HL_TABLE()[idx].sg_set & SG_CTERM)) return FALSE; @@ -1138,20 +1208,20 @@ highlight_set_cterm_color( else { int bold = MAYBE; - - // reduce calls to STRICMP a bit, it can be slow - off = TOUPPER_ASC(*arg); - for (i = ARRAY_LENGTH(color_names); --i >= 0; ) - if (off == color_names[i][0] - && STRICMP(arg + 1, color_names[i] + 1) == 0) - break; - if (i < 0) + keyvalue_T target; + keyvalue_T *entry; + + target.key = 0; + target.value = (char *)arg; + target.length = 0; // not used, see cmp_keyvalue_value_i() + entry = (keyvalue_T *)bsearch(&target, &color_name_tab, ARRAY_LENGTH(color_name_tab), sizeof(color_name_tab[0]), cmp_keyvalue_value_i); + if (entry == NULL) { semsg(_(e_color_name_or_number_not_recognized_str), key_start); return FALSE; } - color = lookup_color(i, key[5] == 'F', &bold); + color = lookup_color(entry->key, key[5] == 'F', &bold); // set/reset bold attribute to get light foreground // colors (on some terminals, e.g. "linux") @@ -2424,58 +2494,56 @@ colorname2rgb(char_u *name) guicolor_T gui_get_color_cmn(char_u *name) { - int i; guicolor_T color; - - struct rgbcolor_table_S { - char_u *color_name; - guicolor_T color; - }; - // Only non X11 colors (not present in rgb.txt) and colors in - // color_names[], useful when $VIMRUNTIME is not found,. - static struct rgbcolor_table_S rgb_table[] = { - {(char_u *)"black", RGB(0x00, 0x00, 0x00)}, - {(char_u *)"blue", RGB(0x00, 0x00, 0xFF)}, - {(char_u *)"brown", RGB(0xA5, 0x2A, 0x2A)}, - {(char_u *)"cyan", RGB(0x00, 0xFF, 0xFF)}, - {(char_u *)"darkblue", RGB(0x00, 0x00, 0x8B)}, - {(char_u *)"darkcyan", RGB(0x00, 0x8B, 0x8B)}, - {(char_u *)"darkgray", RGB(0xA9, 0xA9, 0xA9)}, - {(char_u *)"darkgreen", RGB(0x00, 0x64, 0x00)}, - {(char_u *)"darkgrey", RGB(0xA9, 0xA9, 0xA9)}, - {(char_u *)"darkmagenta", RGB(0x8B, 0x00, 0x8B)}, - {(char_u *)"darkred", RGB(0x8B, 0x00, 0x00)}, - {(char_u *)"darkyellow", RGB(0x8B, 0x8B, 0x00)}, // No X11 - {(char_u *)"gray", RGB(0xBE, 0xBE, 0xBE)}, - {(char_u *)"green", RGB(0x00, 0xFF, 0x00)}, - {(char_u *)"grey", RGB(0xBE, 0xBE, 0xBE)}, - {(char_u *)"grey40", RGB(0x66, 0x66, 0x66)}, - {(char_u *)"grey50", RGB(0x7F, 0x7F, 0x7F)}, - {(char_u *)"grey90", RGB(0xE5, 0xE5, 0xE5)}, - {(char_u *)"lightblue", RGB(0xAD, 0xD8, 0xE6)}, - {(char_u *)"lightcyan", RGB(0xE0, 0xFF, 0xFF)}, - {(char_u *)"lightgray", RGB(0xD3, 0xD3, 0xD3)}, - {(char_u *)"lightgreen", RGB(0x90, 0xEE, 0x90)}, - {(char_u *)"lightgrey", RGB(0xD3, 0xD3, 0xD3)}, - {(char_u *)"lightmagenta", RGB(0xFF, 0x8B, 0xFF)}, // No X11 - {(char_u *)"lightred", RGB(0xFF, 0x8B, 0x8B)}, // No X11 - {(char_u *)"lightyellow", RGB(0xFF, 0xFF, 0xE0)}, - {(char_u *)"magenta", RGB(0xFF, 0x00, 0xFF)}, - {(char_u *)"red", RGB(0xFF, 0x00, 0x00)}, - {(char_u *)"seagreen", RGB(0x2E, 0x8B, 0x57)}, - {(char_u *)"white", RGB(0xFF, 0xFF, 0xFF)}, - {(char_u *)"yellow", RGB(0xFF, 0xFF, 0x00)}, + // color_name_tab[], useful when $VIMRUNTIME is not found,. + // must be sorted by the 'value' field because it is used by bsearch()! + static keyvalue_T rgb_tab[] = { + KEYVALUE_ENTRY(RGB(0x00, 0x00, 0x00), "black"), + KEYVALUE_ENTRY(RGB(0x00, 0x00, 0xFF), "blue"), + KEYVALUE_ENTRY(RGB(0xA5, 0x2A, 0x2A), "brown"), + KEYVALUE_ENTRY(RGB(0x00, 0xFF, 0xFF), "cyan"), + KEYVALUE_ENTRY(RGB(0x00, 0x00, 0x8B), "darkblue"), + KEYVALUE_ENTRY(RGB(0x00, 0x8B, 0x8B), "darkcyan"), + KEYVALUE_ENTRY(RGB(0xA9, 0xA9, 0xA9), "darkgray"), + KEYVALUE_ENTRY(RGB(0x00, 0x64, 0x00), "darkgreen"), + KEYVALUE_ENTRY(RGB(0xA9, 0xA9, 0xA9), "darkgrey"), + KEYVALUE_ENTRY(RGB(0x8B, 0x00, 0x8B), "darkmagenta"), + KEYVALUE_ENTRY(RGB(0x8B, 0x00, 0x00), "darkred"), + KEYVALUE_ENTRY(RGB(0x8B, 0x8B, 0x00), "darkyellow"), // No X11 + KEYVALUE_ENTRY(RGB(0xBE, 0xBE, 0xBE), "gray"), + KEYVALUE_ENTRY(RGB(0x00, 0xFF, 0x00), "green"), + KEYVALUE_ENTRY(RGB(0xBE, 0xBE, 0xBE), "grey"), + KEYVALUE_ENTRY(RGB(0x66, 0x66, 0x66), "grey40"), + KEYVALUE_ENTRY(RGB(0x7F, 0x7F, 0x7F), "grey50"), + KEYVALUE_ENTRY(RGB(0xE5, 0xE5, 0xE5), "grey90"), + KEYVALUE_ENTRY(RGB(0xAD, 0xD8, 0xE6), "lightblue"), + KEYVALUE_ENTRY(RGB(0xE0, 0xFF, 0xFF), "lightcyan"), + KEYVALUE_ENTRY(RGB(0xD3, 0xD3, 0xD3), "lightgray"), + KEYVALUE_ENTRY(RGB(0x90, 0xEE, 0x90), "lightgreen"), + KEYVALUE_ENTRY(RGB(0xD3, 0xD3, 0xD3), "lightgrey"), + KEYVALUE_ENTRY(RGB(0xFF, 0x8B, 0xFF), "lightmagenta"), // No XX + KEYVALUE_ENTRY(RGB(0xFF, 0x8B, 0x8B), "lightred"), // No XX + KEYVALUE_ENTRY(RGB(0xFF, 0xFF, 0xE0), "lightyellow"), + KEYVALUE_ENTRY(RGB(0xFF, 0x00, 0xFF), "magenta"), + KEYVALUE_ENTRY(RGB(0xFF, 0x00, 0x00), "red"), + KEYVALUE_ENTRY(RGB(0x2E, 0x8B, 0x57), "seagreen"), + KEYVALUE_ENTRY(RGB(0xFF, 0xFF, 0xFF), "white"), + KEYVALUE_ENTRY(RGB(0xFF, 0xFF, 0x00), "yellow") }; + keyvalue_T target; + keyvalue_T *entry; color = decode_hex_color(name); if (color != INVALCOLOR) return color; - // Check if the name is one of the colors we know - for (i = 0; i < (int)ARRAY_LENGTH(rgb_table); i++) - if (STRICMP(name, rgb_table[i].color_name) == 0) - return gui_adjust_rgb(rgb_table[i].color); + target.key = 0; + target.value = (char *)name; + target.length = 0; // not used, see cmp_keyvalue_value_i() + entry = (keyvalue_T *)bsearch(&target, &rgb_tab, ARRAY_LENGTH(rgb_tab), sizeof(rgb_tab[0]), cmp_keyvalue_value_i); + if (entry != NULL) + return gui_adjust_rgb((guicolor_T)entry->key); #if defined(FEAT_EVAL) /* @@ -3056,15 +3124,22 @@ highlight_list_arg( ts = sarg; else // type == LIST_ATTR { + size_t buflen; + buf[0] = NUL; - for (i = 0; hl_attr_table[i] != 0; ++i) + buflen = 0; + for (i = 0; i < (int)ARRAY_LENGTH(highlight_index_tab); ++i) { - if (iarg & hl_attr_table[i]) + if (iarg & highlight_index_tab[i]->key) { - if (buf[0] != NUL) - vim_strcat(buf, (char_u *)",", MAX_ATTR_LEN); - vim_strcat(buf, (char_u *)hl_name_table[i], MAX_ATTR_LEN); - iarg &= ~hl_attr_table[i]; // don't want "inverse" + if (buflen > 0) + { + STRCPY(buf + buflen, (char_u *)","); + ++buflen; + } + STRCPY(buf + buflen, (char_u *)highlight_index_tab[i]->value); + buflen += highlight_index_tab[i]->length; + iarg &= ~highlight_index_tab[i]->key; // don't want "inverse"/"reverse" } } } @@ -4155,12 +4230,12 @@ highlight_get_attr_dict(int hlattr) if (dict == NULL) return NULL; - for (i = 0; hl_attr_table[i] != 0; ++i) + for (i = 0; i < (int)ARRAY_LENGTH(highlight_index_tab); ++i) { - if (hlattr & hl_attr_table[i]) + if (hlattr & highlight_index_tab[i]->key) { - dict_add_bool(dict, hl_name_table[i], VVAL_TRUE); - hlattr &= ~hl_attr_table[i]; // don't want "inverse" + dict_add_bool(dict, highlight_index_tab[i]->value, VVAL_TRUE); + hlattr &= ~highlight_index_tab[i]->key; // don't want "inverse"/"reverse" } } @@ -4377,7 +4452,6 @@ hldict_attr_to_str( dict_T *attrdict; int i; char_u *p; - size_t sz; attr_str[0] = NUL; di = dict_find(dict, key, -1); @@ -4400,17 +4474,16 @@ hldict_attr_to_str( } p = attr_str; - for (i = 0; i < (int)ARRAY_LENGTH(hl_name_table); i++) + for (i = 0; i < (int)ARRAY_LENGTH(highlight_tab); ++i) { - if (dict_get_bool(attrdict, hl_name_table[i], VVAL_FALSE) == VVAL_TRUE) + if (dict_get_bool(attrdict, highlight_tab[i].value, VVAL_FALSE) == VVAL_TRUE) { if (p != attr_str && (size_t)(p - attr_str + 2) < len) STRCPY(p, (char_u *)","); - sz = STRLEN(hl_name_table[i]); - if (p - attr_str + sz + 1 < len) + if (p - attr_str + highlight_tab[i].length + 1 < len) { - STRCPY(p, (char_u *)hl_name_table[i]); - p += sz; + STRCPY(p, highlight_tab[i].value); + p += highlight_tab[i].length; } } } diff --git a/src/indent.c b/src/indent.c index 56032fa..1dfde7d 100644 --- a/src/indent.c +++ b/src/indent.c @@ -163,7 +163,7 @@ tabstop_start(colnr_T col, int ts, int *vts) int excess; if (vts == NULL || vts[0] == 0) - return (col / ts) * ts; + return col - col % ts; tabcount = vts[0]; for (t = 1; t <= tabcount; ++t) @@ -174,7 +174,7 @@ tabstop_start(colnr_T col, int ts, int *vts) } excess = tabcol % vts[tabcount]; - return excess + ((col - excess) / vts[tabcount]) * vts[tabcount]; + return col - (col - excess) % vts[tabcount]; } /* diff --git a/src/insexpand.c b/src/insexpand.c index 9b5e5de..93a56a8 100644 --- a/src/insexpand.c +++ b/src/insexpand.c @@ -2741,6 +2741,7 @@ expand_by_function(int type, char_u *base) --textlock; curwin->w_cursor = pos; // restore the cursor position + check_cursor(); // make sure cursor position is valid, just in case validate_cursor(); if (!EQUAL_POS(curwin->w_cursor, pos)) { @@ -4606,6 +4607,7 @@ get_userdefined_compl_info(colnr_T curs_col UNUSED) State = save_State; curwin->w_cursor = pos; // restore the cursor position + check_cursor(); // make sure cursor position is valid, just in case validate_cursor(); if (!EQUAL_POS(curwin->w_cursor, pos)) { @@ -1098,7 +1098,7 @@ is_safe_now(void) } /* - * Trigger SafeState if currently in s safe state, that is "safe" is TRUE and + * Trigger SafeState if currently in a safe state, that is "safe" is TRUE and * there is no typeahead. */ void @@ -3276,6 +3276,10 @@ source_startup_scripts(mparm_T *parmp) && do_source((char_u *)USR_VIMRC_FILE2, TRUE, DOSO_VIMRC, NULL) == FAIL #endif +#ifdef XDG_VIMRC_FILE + && do_source((char_u *)XDG_VIMRC_FILE, TRUE, + DOSO_VIMRC, NULL) == FAIL +#endif #ifdef USR_VIMRC_FILE3 && do_source((char_u *)USR_VIMRC_FILE3, TRUE, DOSO_VIMRC, NULL) == FAIL @@ -2574,7 +2574,10 @@ f_maplist(typval_T *argvars UNUSED, typval_T *rettv) if ((d = dict_alloc()) == NULL) return; if (list_append_dict(rettv->vval.v_list, d) == FAIL) + { + dict_unref(d); return; + } keys_buf = NULL; did_simplify = FALSE; diff --git a/src/match.c b/src/match.c index f59c206..bc50757 100644 --- a/src/match.c +++ b/src/match.c @@ -87,7 +87,7 @@ match_add( m = ALLOC_CLEAR_ONE(matchitem_T); if (m == NULL) return -1; - if (pos_list != NULL) + if (pos_list != NULL && pos_list->lv_len > 0) { m->mit_pos_array = ALLOC_CLEAR_MULT(llpos_T, pos_list->lv_len); if (m->mit_pos_array == NULL) @@ -1294,7 +1294,7 @@ f_matchaddpos(typval_T *argvars UNUSED, typval_T *rettv UNUSED) return; } l = argvars[1].vval.v_list; - if (l == NULL) + if (l == NULL || l->lv_len == 0) return; if (argvars[2].v_type != VAR_UNKNOWN) diff --git a/src/mbyte.c b/src/mbyte.c index d6fb7ec..07446ca 100644 --- a/src/mbyte.c +++ b/src/mbyte.c @@ -5542,6 +5542,20 @@ string_convert_ext( return retval; } +/* + * Return 1 or 2 when "c" is in the cellwidth table. + * Return 0 if not. + */ + int +get_cellwidth(int c UNUSED) +{ +#ifdef FEAT_EVAL + return cw_value(c); +#else + return 0; +#endif +} + #if defined(FEAT_EVAL) || defined(PROTO) /* @@ -5733,6 +5747,7 @@ f_setcellwidths(typval_T *argvars, typval_T *rettv UNUSED) } vim_free(cw_table_save); + changed_window_setting_all(); redraw_all_later(UPD_CLEAR); } diff --git a/src/memline.c b/src/memline.c index 5ca50fc..6c63fad 100644 --- a/src/memline.c +++ b/src/memline.c @@ -5556,7 +5556,10 @@ ml_encrypt_data( new_data = alloc(size); if (new_data == NULL) + { + crypt_free_state(state); return NULL; + } head_end = (char_u *)(&dp->db_index[dp->db_line_count]); text_start = (char_u *)dp + dp->db_txt_start; text_len = size - dp->db_txt_start; diff --git a/src/message.c b/src/message.c index 80d6a18..03c7072 100644 --- a/src/message.c +++ b/src/message.c @@ -1637,6 +1637,9 @@ msg_outtrans_len_attr(char_u *msgstr, int len, int attr) // Only quit when got_int was set in here. got_int = FALSE; + if (attr == 0) + attr = HL_ATTR(HLF_MSG); + // if MSG_HIST flag set, add message to history if (attr & MSG_HIST) { @@ -2230,6 +2233,9 @@ msg_puts_attr_len(char *str, int maxlen, int attr) if (msg_silent != 0) return; + if (attr == 0) + attr = HL_ATTR(HLF_MSG); + // if MSG_HIST flag set, add message to history if ((attr & MSG_HIST) && maxlen < 0) { @@ -2678,13 +2684,15 @@ msg_scroll_up(void) // Scrolling up doesn't result in the right background. Set the // background here. It's not efficient, but avoids that we have to do // it all over the code. - screen_fill((int)Rows - 1, (int)Rows, 0, (int)Columns, ' ', ' ', 0); + screen_fill((int)Rows - 1, (int)Rows, 0, (int)Columns, + ' ', ' ', HL_ATTR(HLF_MSG)); // Also clear the last char of the last but one line if it was not // cleared before to avoid a scroll-up. if (ScreenAttrs[LineOffset[Rows - 2] + Columns - 1] == (sattr_T)-1) screen_fill((int)Rows - 2, (int)Rows - 1, - (int)Columns - 1, (int)Columns, ' ', ' ', 0); + (int)Columns - 1, (int)Columns, + ' ', ' ', HL_ATTR(HLF_MSG)); } } @@ -2963,7 +2971,8 @@ disp_sb_line(int row, msgchunk_T *smp, int clear_to_eol) // If clearing the screen did not work (e.g. because of a background // color and t_ut isn't set) clear until the last column here. if (clear_to_eol) - screen_fill(row, row + 1, msg_col, (int)Columns, ' ', ' ', 0); + screen_fill(row, row + 1, msg_col, (int)Columns, + ' ', ' ', HL_ATTR(HLF_MSG)); if (mp->sb_eol || mp->sb_next == NULL) break; @@ -3131,6 +3140,9 @@ do_more_prompt(int typed_char) msgchunk_T *mp_last = NULL; msgchunk_T *mp; int i; + int msg_attr; + + msg_attr = HL_ATTR(HLF_MSG); // We get called recursively when a timer callback outputs a message. In // that case don't show another prompt. Also when at the hit-Enter prompt @@ -3340,8 +3352,8 @@ do_more_prompt(int typed_char) // scroll up, display line at bottom msg_scroll_up(); inc_msg_scrolled(); - screen_fill((int)Rows - 2, (int)Rows - 1, 0, - (int)Columns, ' ', ' ', 0); + screen_fill((int)Rows - 2, (int)Rows - 1, 0, (int)Columns, + ' ', ' ', msg_attr); mp_last = disp_sb_line((int)Rows - 2, mp_last, FALSE); --toscroll; } @@ -3350,8 +3362,8 @@ do_more_prompt(int typed_char) if (toscroll <= 0) { // displayed the requested text, more prompt again - screen_fill((int)Rows - 1, (int)Rows, 0, - (int)Columns, ' ', ' ', 0); + screen_fill((int)Rows - 1, (int)Rows, 0, (int)Columns, + ' ', ' ', msg_attr); msg_moremsg(FALSE); continue; } @@ -3364,7 +3376,7 @@ do_more_prompt(int typed_char) } // clear the --more-- message - screen_fill((int)Rows - 1, (int)Rows, 0, (int)Columns, ' ', ' ', 0); + screen_fill((int)Rows - 1, (int)Rows, 0, (int)Columns, ' ', ' ', msg_attr); State = oldState; setmouse(); if (quit_more) @@ -3710,18 +3722,25 @@ msg_clr_eos_force(void) } else { + int msg_attr; + + msg_attr = HL_ATTR(HLF_MSG); + #ifdef FEAT_RIGHTLEFT if (cmdmsg_rl) { - screen_fill(msg_row, msg_row + 1, 0, msg_col + 1, ' ', ' ', 0); - screen_fill(msg_row + 1, (int)Rows, 0, (int)Columns, ' ', ' ', 0); + screen_fill(msg_row, msg_row + 1, 0, msg_col + 1, + ' ', ' ', msg_attr); + screen_fill(msg_row + 1, (int)Rows, 0, (int)Columns, + ' ', ' ', msg_attr); } else #endif { screen_fill(msg_row, msg_row + 1, msg_col, (int)Columns, - ' ', ' ', 0); - screen_fill(msg_row + 1, (int)Rows, 0, (int)Columns, ' ', ' ', 0); + ' ', ' ', msg_attr); + screen_fill(msg_row + 1, (int)Rows, 0, (int)Columns, + ' ', ' ', msg_attr); } } } diff --git a/src/misc1.c b/src/misc1.c index 3085fc7..c5a0c38 100644 --- a/src/misc1.c +++ b/src/misc1.c @@ -502,7 +502,7 @@ plines_m_win(win_T *wp, linenr_T first, linenr_T last, int limit_winheight) { int count = 0; - while (first <= last) + while (first <= last && (!limit_winheight || count < wp->w_height)) { #ifdef FEAT_FOLDING int x; @@ -520,14 +520,19 @@ plines_m_win(win_T *wp, linenr_T first, linenr_T last, int limit_winheight) { #ifdef FEAT_DIFF if (first == wp->w_topline) - count += plines_win_nofill(wp, first, limit_winheight) - + wp->w_topfill; + count += plines_win_nofill(wp, first, FALSE) + wp->w_topfill; else #endif - count += plines_win(wp, first, limit_winheight); + count += plines_win(wp, first, FALSE); ++first; } } +#ifdef FEAT_DIFF + if (first == wp->w_buffer->b_ml.ml_line_count + 1) + count += diff_check_fill(wp, first); +#endif + if (limit_winheight && count > wp->w_height) + return wp->w_height; return (count); } @@ -2092,7 +2097,7 @@ add_user(char_u *user, int need_copy) if (user_copy == NULL || *user_copy == NUL || ga_grow(&ga_users, 1) == FAIL) { if (need_copy) - vim_free(user); + vim_free(user_copy); return; } ((char_u **)(ga_users.ga_data))[ga_users.ga_len++] = user_copy; @@ -2172,7 +2177,7 @@ init_users(void) } /* - * Function given to ExpandGeneric() to obtain an user names. + * Function given to ExpandGeneric() to obtain user names. */ char_u* get_users(expand_T *xp UNUSED, int idx) diff --git a/src/misc2.c b/src/misc2.c index 6df0d39..c07ed80 100644 --- a/src/misc2.c +++ b/src/misc2.c @@ -3069,3 +3069,45 @@ get_special_pty_type(void) return 0; #endif } + +// compare two keyvalue_T structs by case sensitive value + int +cmp_keyvalue_value(const void *a, const void *b) +{ + keyvalue_T *kv1 = (keyvalue_T *)a; + keyvalue_T *kv2 = (keyvalue_T *)b; + + return STRCMP(kv1->value, kv2->value); +} + +// compare two keyvalue_T structs by value with length + int +cmp_keyvalue_value_n(const void *a, const void *b) +{ + keyvalue_T *kv1 = (keyvalue_T *)a; + keyvalue_T *kv2 = (keyvalue_T *)b; + + return STRNCMP(kv1->value, kv2->value, MAX(kv1->length, kv2->length)); +} + +// compare two keyvalue_T structs by case insensitive value + int +cmp_keyvalue_value_i(const void *a, const void *b) +{ + keyvalue_T *kv1 = (keyvalue_T *)a; + keyvalue_T *kv2 = (keyvalue_T *)b; + + return STRICMP(kv1->value, kv2->value); +} + +// compare two keyvalue_T structs by case insensitive value +// with length + int +cmp_keyvalue_value_ni(const void *a, const void *b) +{ + keyvalue_T *kv1 = (keyvalue_T *)a; + keyvalue_T *kv2 = (keyvalue_T *)b; + + return STRNICMP(kv1->value, kv2->value, MAX(kv1->length, kv2->length)); +} + diff --git a/src/mouse.c b/src/mouse.c index af14af0..247c6df 100644 --- a/src/mouse.c +++ b/src/mouse.c @@ -1129,7 +1129,7 @@ do_mousescroll(cmdarg_T *cap) if (!(State & MODE_INSERT) && (mouse_vert_step < 0 || shift_or_ctrl)) { // whole page up or down - onepage(cap->arg == MSCR_UP ? FORWARD : BACKWARD, 1L); + pagescroll(cap->arg == MSCR_UP ? FORWARD : BACKWARD, 1L, FALSE); } else { @@ -59,7 +59,7 @@ adjust_plines_for_skipcol(win_T *wp) * the window height. */ static int -plines_correct_topline(win_T *wp, linenr_T lnum) +plines_correct_topline(win_T *wp, linenr_T lnum, int limit_winheight) { int n; #ifdef FEAT_DIFF @@ -70,7 +70,7 @@ plines_correct_topline(win_T *wp, linenr_T lnum) n = plines_win(wp, lnum, FALSE); if (lnum == wp->w_topline) n -= adjust_plines_for_skipcol(wp); - if (n > wp->w_height) + if (limit_winheight && n > wp->w_height) n = wp->w_height; return n; } @@ -119,7 +119,7 @@ comp_botline(win_T *wp) else #endif { - n = plines_correct_topline(wp, lnum); + n = plines_correct_topline(wp, lnum, TRUE); } if ( #ifdef FEAT_FOLDING @@ -197,13 +197,15 @@ redraw_for_cursorcolumn(win_T *wp) * Calculates how much the 'listchars' "precedes" or 'smoothscroll' "<<<" * marker overlaps with buffer text for window "wp". * Parameter "extra2" should be the padding on the 2nd line, not the first - * line. + * line. When "extra2" is -1 calculate the padding. * Returns the number of columns of overlap with buffer text, excluding the * extra padding on the ledge. */ int sms_marker_overlap(win_T *wp, int extra2) { + if (extra2 == -1) + extra2 = win_col_off(wp) - win_col_off2(wp); #if defined(FEAT_LINEBREAK) // There is no marker overlap when in showbreak mode, thus no need to // account for it. See wlv_screen_line(). @@ -340,12 +342,12 @@ update_topline(void) && curwin->w_cursor.lnum == curwin->w_topline) { colnr_T vcol; + int overlap; // Check that the cursor position is visible. Add columns for // the marker displayed in the top-left if needed. getvvcol(curwin, &curwin->w_cursor, &vcol, NULL, NULL); - int overlap = sms_marker_overlap(curwin, curwin_col_off() - - curwin_col_off2()); + overlap = sms_marker_overlap(curwin, -1); if (curwin->w_skipcol + overlap > vcol) check_topline = TRUE; } @@ -676,6 +678,19 @@ changed_window_setting_buf(buf_T *buf) #endif /* + * Call changed_window_setting_win() for every window. + */ + void +changed_window_setting_all(void) +{ + tabpage_T *tp; + win_T *wp; + + FOR_ALL_TAB_WINDOWS(tp, wp) + changed_window_setting_win(wp); +} + +/* * Set wp->w_topline to a certain number. */ void @@ -919,7 +934,7 @@ curs_rows(win_T *wp) else #endif { - wp->w_cline_row += plines_correct_topline(wp, lnum); + wp->w_cline_row += plines_correct_topline(wp, lnum, TRUE); ++lnum; } } @@ -1600,6 +1615,127 @@ f_virtcol2col(typval_T *argvars UNUSED, typval_T *rettv) #endif /* + * Make sure the cursor is in the visible part of the topline after scrolling + * the screen with 'smoothscroll'. + */ +static void cursor_correct_sms(void) +{ + if (!curwin->w_p_sms ||!curwin->w_p_wrap + || curwin->w_cursor.lnum != curwin->w_topline) + return; + + long so = get_scrolloff_value(); + int width1 = curwin->w_width - curwin_col_off(); + int width2 = width1 + curwin_col_off2(); + int so_cols = so == 0 ? 0 : width1 + (so - 1) * width2; + int space_cols = (curwin->w_height - 1) * width2; + int size = so == 0 ? 0 : win_linetabsize(curwin, curwin->w_topline, + ml_get(curwin->w_topline), (colnr_T)MAXCOL); + + if (curwin->w_topline == 1 && curwin->w_skipcol == 0) + so_cols = 0; // Ignore 'scrolloff' at top of buffer. + else if (so_cols > space_cols / 2) + so_cols = space_cols / 2; // Not enough room: put cursor in the middle. + + // Not enough screen lines in topline: ignore 'scrolloff'. + while (so_cols > size && so_cols - width2 >= width1) + so_cols -= width2; + if (so_cols >= width1 && so_cols > size) + so_cols -= width1; + + // If there is no marker or we have non-zero scrolloff, just ignore it. + int overlap = (curwin->w_skipcol == 0 || so_cols != 0) ? 0 + : sms_marker_overlap(curwin, -1); + int top = curwin->w_skipcol + overlap + so_cols; + int bot = curwin->w_skipcol + width1 + (curwin->w_height - 1) * width2 + - so_cols; + validate_virtcol(); + colnr_T col = curwin->w_virtcol; + + if (col < top) + { + if (col < width1) + col += width1; + while (width2 > 0 && col < top) + col += width2; + } + else + while (width2 > 0 && col >= bot) + col -= width2; + + if (col != curwin->w_virtcol) + { + curwin->w_curswant = col; + coladvance(curwin->w_curswant); + // validate_virtcol() marked various things as valid, but after + // moving the cursor they need to be recomputed + curwin->w_valid &= + ~(VALID_WROW|VALID_WCOL|VALID_CHEIGHT|VALID_CROW|VALID_VIRTCOL); + } +} + +/* + * Scroll "count" lines up or down, and redraw. + */ + void +scroll_redraw(int up, long count) +{ + linenr_T prev_topline = curwin->w_topline; + int prev_skipcol = curwin->w_skipcol; +#ifdef FEAT_DIFF + int prev_topfill = curwin->w_topfill; +#endif + linenr_T prev_lnum = curwin->w_cursor.lnum; + + if (up) + scrollup(count, TRUE); + else + scrolldown(count, TRUE); + if (get_scrolloff_value() > 0) + { + // Adjust the cursor position for 'scrolloff'. Mark w_topline as + // valid, otherwise the screen jumps back at the end of the file. + cursor_correct(); + check_cursor_moved(curwin); + curwin->w_valid |= VALID_TOPLINE; + + // If moved back to where we were, at least move the cursor, otherwise + // we get stuck at one position. Don't move the cursor up if the + // first line of the buffer is already on the screen + while (curwin->w_topline == prev_topline + && curwin->w_skipcol == prev_skipcol +#ifdef FEAT_DIFF + && curwin->w_topfill == prev_topfill +#endif + ) + { + if (up) + { + if (curwin->w_cursor.lnum > prev_lnum + || cursor_down(1L, FALSE) == FAIL) + break; + } + else + { + if (curwin->w_cursor.lnum < prev_lnum + || prev_topline == 1L + || cursor_up(1L, FALSE) == FAIL) + break; + } + // Mark w_topline as valid, otherwise the screen jumps back at the + // end of the file. + check_cursor_moved(curwin); + curwin->w_valid |= VALID_TOPLINE; + } + } + + cursor_correct_sms(); + if (curwin->w_cursor.lnum != prev_lnum) + coladvance(curwin->w_curswant); + redraw_later(UPD_VALID); +} + +/* * Scroll the current window down by "line_count" logical lines. "CTRL-Y" */ void @@ -1744,35 +1880,8 @@ scrolldown( #endif coladvance(curwin->w_curswant); } - - if (curwin->w_cursor.lnum == curwin->w_topline && do_sms) - { - long so = get_scrolloff_value(); - int scrolloff_cols = so == 0 ? 0 : width1 + (so - 1) * width2; - - // make sure the cursor is in the visible text - validate_virtcol(); - int col = curwin->w_virtcol - curwin->w_skipcol + scrolloff_cols; - int row = 0; - if (col >= width1) - { - col -= width1; - ++row; - } - if (col > width2 && width2 > 0) - { - row += col / width2; - // even so col is not used anymore, - // make sure it is correct, just in case - col = col % width2; - } - if (row >= curwin->w_height) - { - curwin->w_curswant = curwin->w_virtcol - - (row - curwin->w_height + 1) * width2; - coladvance(curwin->w_curswant); - } - } + if (curwin->w_cursor.lnum < curwin->w_topline) + curwin->w_cursor.lnum = curwin->w_topline; } /* @@ -1894,47 +2003,6 @@ scrollup( ~(VALID_WROW|VALID_WCOL|VALID_CHEIGHT|VALID_CROW|VALID_VIRTCOL); coladvance(curwin->w_curswant); } - if (curwin->w_cursor.lnum == curwin->w_topline - && do_sms && curwin->w_skipcol > 0) - { - int col_off = curwin_col_off(); - int col_off2 = curwin_col_off2(); - - int width1 = curwin->w_width - col_off; - int width2 = width1 + col_off2; - int extra2 = col_off - col_off2; - long so = get_scrolloff_value(); - int scrolloff_cols = so == 0 ? 0 : width1 + (so - 1) * width2; - int space_cols = (curwin->w_height - 1) * width2; - - // If we have non-zero scrolloff, just ignore the marker as we are - // going past it anyway. - int overlap = scrolloff_cols != 0 ? 0 - : sms_marker_overlap(curwin, extra2); - - // Make sure the cursor is in a visible part of the line, taking - // 'scrolloff' into account, but using screen lines. - // If there are not enough screen lines put the cursor in the middle. - if (scrolloff_cols > space_cols / 2) - scrolloff_cols = space_cols / 2; - validate_virtcol(); - if (curwin->w_virtcol < curwin->w_skipcol + overlap + scrolloff_cols) - { - colnr_T col = curwin->w_virtcol; - - if (col < width1) - col += width1; - while (col < curwin->w_skipcol + overlap + scrolloff_cols) - col += width2; - curwin->w_curswant = col; - coladvance(curwin->w_curswant); - - // validate_virtcol() marked various things as valid, but after - // moving the cursor they need to be recomputed - curwin->w_valid &= - ~(VALID_WROW|VALID_WCOL|VALID_CHEIGHT|VALID_CROW|VALID_VIRTCOL); - } - } } /* @@ -1971,8 +2039,7 @@ adjust_skipcol(void) } validate_virtcol(); - int overlap = sms_marker_overlap(curwin, - curwin_col_off() - curwin_col_off2()); + int overlap = sms_marker_overlap(curwin, -1); while (curwin->w_skipcol > 0 && curwin->w_virtcol < curwin->w_skipcol + overlap + scrolloff_cols) { @@ -2047,26 +2114,6 @@ check_topfill( } } } - -/* - * Use as many filler lines as possible for w_topline. Make sure w_topline - * is still visible. - */ - static void -max_topfill(void) -{ - int n; - - n = plines_nofill(curwin->w_topline); - if (n >= curwin->w_height) - curwin->w_topfill = 0; - else - { - curwin->w_topfill = diff_check_fill(curwin, curwin->w_topline); - if (curwin->w_topfill + n > curwin->w_height) - curwin->w_topfill = curwin->w_height - n; - } -} #endif /* @@ -2269,38 +2316,6 @@ botline_forw(lineoff_T *lp) } } -#ifdef FEAT_DIFF -/* - * Switch from including filler lines below lp->lnum to including filler - * lines above loff.lnum + 1. This keeps pointing to the same line. - * When there are no filler lines nothing changes. - */ - static void -botline_topline(lineoff_T *lp) -{ - if (lp->fill > 0) - { - ++lp->lnum; - lp->fill = diff_check_fill(curwin, lp->lnum) - lp->fill + 1; - } -} - -/* - * Switch from including filler lines above lp->lnum to including filler - * lines below loff.lnum - 1. This keeps pointing to the same line. - * When there are no filler lines nothing changes. - */ - static void -topline_botline(lineoff_T *lp) -{ - if (lp->fill > 0) - { - lp->fill = diff_check_fill(curwin, lp->lnum) - lp->fill + 1; - --lp->lnum; - } -} -#endif - /* * Recompute topline to put the cursor at the top of the window. * Scroll at least "min_scroll" lines. @@ -2512,18 +2527,14 @@ scroll_cursor_bot(int min_scroll, int set_topbot) cln = curwin->w_cursor.lnum; if (set_topbot) { - int set_skipcol = FALSE; - used = 0; curwin->w_botline = cln + 1; + loff.lnum = cln + 1; #ifdef FEAT_DIFF loff.fill = 0; #endif - for (curwin->w_topline = curwin->w_botline; - curwin->w_topline > 1; - curwin->w_topline = loff.lnum) + while (TRUE) { - loff.lnum = curwin->w_topline; topline_back_winheight(&loff, FALSE); if (loff.height == MAXCOL) break; @@ -2545,27 +2556,28 @@ scroll_cursor_bot(int min_scroll, int set_topbot) curwin->w_topline = loff.lnum; curwin->w_skipcol = skipcol_from_plines( curwin, plines_offset); - set_skipcol = TRUE; } } break; } - used += loff.height; #ifdef FEAT_DIFF curwin->w_topfill = loff.fill; #endif + curwin->w_topline = loff.lnum; + used += loff.height; } + set_empty_rows(curwin, used); curwin->w_valid |= VALID_BOTLINE|VALID_BOTLINE_AP; if (curwin->w_topline != old_topline #ifdef FEAT_DIFF || curwin->w_topfill != old_topfill #endif - || set_skipcol + || curwin->w_skipcol != old_skipcol || curwin->w_skipcol != 0) { curwin->w_valid &= ~(VALID_WROW|VALID_CROW); - if (set_skipcol) + if (curwin->w_skipcol != old_skipcol) redraw_later(UPD_NOT_VALID); else reset_skipcol(); @@ -2768,6 +2780,8 @@ scroll_cursor_bot(int min_scroll, int set_topbot) curwin->w_valid = old_valid; } curwin->w_valid |= VALID_TOPLINE; + + cursor_correct_sms(); } /* @@ -3077,508 +3091,192 @@ cursor_correct(void) curwin->w_valid |= VALID_TOPLINE; } -static void get_scroll_overlap(lineoff_T *lp, int dir); - -/* - * Move screen "count" pages up ("dir" is BACKWARD) or down ("dir" is FORWARD) - * and update the screen. - * - * Return FAIL for failure, OK otherwise. - */ - int -onepage(int dir, long count) -{ - long n; - int retval = OK; - lineoff_T loff; - linenr_T old_topline = curwin->w_topline; - long so = get_scrolloff_value(); - - if (curbuf->b_ml.ml_line_count == 1) // nothing to do - { - beep_flush(); - return FAIL; - } - - for ( ; count > 0; --count) - { - validate_botline(); - /* - * It's an error to move a page up when the first line is already on - * the screen. It's an error to move a page down when the last line - * is on the screen and the topline is 'scrolloff' lines from the - * last line. - */ - if (dir == FORWARD - ? ((curwin->w_topline >= curbuf->b_ml.ml_line_count - so) - && curwin->w_botline > curbuf->b_ml.ml_line_count) - : (curwin->w_topline == 1 -#ifdef FEAT_DIFF - && curwin->w_topfill == - diff_check_fill(curwin, curwin->w_topline) -#endif - )) - { - beep_flush(); - retval = FAIL; - break; - } - -#ifdef FEAT_DIFF - loff.fill = 0; -#endif - if (dir == FORWARD) - { - if (ONE_WINDOW && p_window > 0 && p_window < Rows - 1) - { - // Vi compatible scrolling - if (p_window <= 2) - ++curwin->w_topline; - else - curwin->w_topline += p_window - 2; - if (curwin->w_topline > curbuf->b_ml.ml_line_count) - curwin->w_topline = curbuf->b_ml.ml_line_count; - curwin->w_cursor.lnum = curwin->w_topline; - } - else if (curwin->w_botline > curbuf->b_ml.ml_line_count) - { - // at end of file - curwin->w_topline = curbuf->b_ml.ml_line_count; -#ifdef FEAT_DIFF - curwin->w_topfill = 0; -#endif - curwin->w_valid &= ~(VALID_WROW|VALID_CROW); - } - else - { - // For the overlap, start with the line just below the window - // and go upwards. - loff.lnum = curwin->w_botline; -#ifdef FEAT_DIFF - loff.fill = diff_check_fill(curwin, loff.lnum) - - curwin->w_filler_rows; -#endif - get_scroll_overlap(&loff, -1); - curwin->w_topline = loff.lnum; -#ifdef FEAT_DIFF - curwin->w_topfill = loff.fill; - check_topfill(curwin, FALSE); -#endif - curwin->w_cursor.lnum = curwin->w_topline; - curwin->w_valid &= ~(VALID_WCOL|VALID_CHEIGHT|VALID_WROW| - VALID_CROW|VALID_BOTLINE|VALID_BOTLINE_AP); - } - } - else // dir == BACKWARDS - { -#ifdef FEAT_DIFF - if (curwin->w_topline == 1) - { - // Include max number of filler lines - max_topfill(); - continue; - } -#endif - if (ONE_WINDOW && p_window > 0 && p_window < Rows - 1) - { - // Vi compatible scrolling (sort of) - if (p_window <= 2) - --curwin->w_topline; - else - curwin->w_topline -= p_window - 2; - if (curwin->w_topline < 1) - curwin->w_topline = 1; - curwin->w_cursor.lnum = curwin->w_topline + p_window - 1; - if (curwin->w_cursor.lnum > curbuf->b_ml.ml_line_count) - curwin->w_cursor.lnum = curbuf->b_ml.ml_line_count; - continue; - } - - // Find the line at the top of the window that is going to be the - // line at the bottom of the window. Make sure this results in - // the same line as before doing CTRL-F. - loff.lnum = curwin->w_topline - 1; -#ifdef FEAT_DIFF - loff.fill = diff_check_fill(curwin, loff.lnum + 1) - - curwin->w_topfill; -#endif - get_scroll_overlap(&loff, 1); - - if (loff.lnum >= curbuf->b_ml.ml_line_count) - { - loff.lnum = curbuf->b_ml.ml_line_count; -#ifdef FEAT_DIFF - loff.fill = 0; - } - else - { - botline_topline(&loff); -#endif - } - curwin->w_cursor.lnum = loff.lnum; - - // Find the line just above the new topline to get the right line - // at the bottom of the window. - n = 0; - while (n <= curwin->w_height && loff.lnum >= 1) - { - topline_back(&loff); - if (loff.height == MAXCOL) - n = MAXCOL; - else - n += loff.height; - } - if (loff.lnum < 1) // at begin of file - { - curwin->w_topline = 1; -#ifdef FEAT_DIFF - max_topfill(); -#endif - curwin->w_valid &= ~(VALID_WROW|VALID_CROW|VALID_BOTLINE); - } - else - { - // Go two lines forward again. -#ifdef FEAT_DIFF - topline_botline(&loff); -#endif - botline_forw(&loff); - botline_forw(&loff); -#ifdef FEAT_DIFF - botline_topline(&loff); -#endif -#ifdef FEAT_FOLDING - // We're at the wrong end of a fold now. - (void)hasFolding(loff.lnum, &loff.lnum, NULL); -#endif - - // Always scroll at least one line. Avoid getting stuck on - // very long lines. - if (loff.lnum >= curwin->w_topline -#ifdef FEAT_DIFF - && (loff.lnum > curwin->w_topline - || loff.fill >= curwin->w_topfill) -#endif - ) - { -#ifdef FEAT_DIFF - // First try using the maximum number of filler lines. If - // that's not enough, backup one line. - loff.fill = curwin->w_topfill; - if (curwin->w_topfill < diff_check_fill(curwin, - curwin->w_topline)) - max_topfill(); - if (curwin->w_topfill == loff.fill) -#endif - { - --curwin->w_topline; -#ifdef FEAT_DIFF - curwin->w_topfill = 0; -#endif - curwin->w_valid &= ~(VALID_WROW|VALID_CROW); - } - comp_botline(curwin); - curwin->w_cursor.lnum = curwin->w_botline - 1; - curwin->w_valid &= - ~(VALID_WCOL|VALID_CHEIGHT|VALID_WROW|VALID_CROW); - } - else - { - curwin->w_topline = loff.lnum; -#ifdef FEAT_DIFF - curwin->w_topfill = loff.fill; - check_topfill(curwin, FALSE); -#endif - curwin->w_valid &= ~(VALID_WROW|VALID_CROW|VALID_BOTLINE); - } - } - } - } -#ifdef FEAT_FOLDING - foldAdjustCursor(); -#endif - cursor_correct(); - check_cursor_col(); - if (retval == OK) - beginline(BL_SOL | BL_FIX); - curwin->w_valid &= ~(VALID_WCOL|VALID_WROW|VALID_VIRTCOL); - - if (retval == OK && dir == FORWARD) - { - // Avoid the screen jumping up and down when 'scrolloff' is non-zero. - // But make sure we scroll at least one line (happens with mix of long - // wrapping lines and non-wrapping line). - if (check_top_offset()) - { - scroll_cursor_top(1, FALSE); - if (curwin->w_topline <= old_topline - && old_topline < curbuf->b_ml.ml_line_count) - { - curwin->w_topline = old_topline + 1; -#ifdef FEAT_FOLDING - (void)hasFolding(curwin->w_topline, &curwin->w_topline, NULL); -#endif - } - } -#ifdef FEAT_FOLDING - else if (curwin->w_botline > curbuf->b_ml.ml_line_count) - (void)hasFolding(curwin->w_topline, &curwin->w_topline, NULL); -#endif - } - - redraw_later(UPD_VALID); - return retval; -} - /* * Decide how much overlap to use for page-up or page-down scrolling. * This is symmetric, so that doing both keeps the same lines displayed. * Three lines are examined: * - * before CTRL-F after CTRL-F / before CTRL-B - * etc. l1 - * l1 last but one line ------------ - * l2 last text line l2 top text line - * ------------- l3 second text line - * l3 etc. + * before CTRL-F after CTRL-F / before CTRL-B + * etc. l1 + * l1 last but one line ------------ + * l2 last text line l2 top text line + * ------------- l3 second text line + * l3 etc. */ - static void -get_scroll_overlap(lineoff_T *lp, int dir) +static int get_scroll_overlap(int dir) { - int h1, h2, h3, h4; - int min_height = curwin->w_height - 2; - lineoff_T loff0, loff1, loff2; + lineoff_T loff; + int min_height = curwin->w_height - 2; + validate_botline(); + if ((dir == BACKWARD && curwin->w_topline == 1) + || (dir == FORWARD && curwin->w_botline > curbuf->b_ml.ml_line_count)) + return min_height + 2; // no overlap, still handle 'smoothscroll' + + loff.lnum = dir == FORWARD ? curwin->w_botline : curwin->w_topline - 1; #ifdef FEAT_DIFF - if (lp->fill > 0) - lp->height = 1; - else - lp->height = plines_nofill(lp->lnum); + loff.fill = diff_check_fill(curwin, loff.lnum + (dir == BACKWARD)) + - (dir == FORWARD ? curwin->w_filler_rows : curwin->w_topfill); + loff.height = loff.fill > 0 ? 1 : plines_nofill(loff.lnum); #else - lp->height = plines(lp->lnum); + loff.height = plines(loff.lnum); #endif - h1 = lp->height; - if (h1 > min_height) - return; // no overlap - loff0 = *lp; - if (dir > 0) - botline_forw(lp); + int h1 = loff.height; + if (h1 > min_height) + return min_height + 2; // no overlap + if (dir == FORWARD) + topline_back(&loff); else - topline_back(lp); - h2 = lp->height; - if (h2 == MAXCOL || h2 + h1 > min_height) - { - *lp = loff0; // no overlap - return; - } + botline_forw(&loff); - loff1 = *lp; - if (dir > 0) - botline_forw(lp); + int h2 = loff.height; + if (h2 == MAXCOL || h2 + h1 > min_height) + return min_height + 2; // no overlap + if (dir == FORWARD) + topline_back(&loff); else - topline_back(lp); - h3 = lp->height; - if (h3 == MAXCOL || h3 + h2 > min_height) - { - *lp = loff0; // no overlap - return; - } + botline_forw(&loff); - loff2 = *lp; - if (dir > 0) - botline_forw(lp); + int h3 = loff.height; + if (h3 == MAXCOL || h3 + h2 > min_height) + return min_height + 2; // no overlap + if (dir == FORWARD) + topline_back(&loff); else - topline_back(lp); - h4 = lp->height; + botline_forw(&loff); + + int h4 = loff.height; if (h4 == MAXCOL || h4 + h3 + h2 > min_height || h3 + h2 + h1 > min_height) - *lp = loff1; // 1 line overlap + return min_height + 1; // 1 line overlap else - *lp = loff2; // 2 lines overlap + return min_height; // 2 lines overlap } /* - * Scroll 'scroll' lines up or down. + * Scroll "count" lines with 'smoothscroll' in direction "dir". Return TRUE + * when scrolling happened. */ - void -halfpage(int flag, linenr_T Prenum) +static int scroll_with_sms(int dir, long count) { - long scrolled = 0; - int i; - int n; - int room; - - if (Prenum) - curwin->w_p_scr = (Prenum > curwin->w_height) ? - curwin->w_height : Prenum; - n = (curwin->w_p_scr <= curwin->w_height) ? - curwin->w_p_scr : curwin->w_height; - - update_topline(); - validate_botline(); - room = curwin->w_empty_rows; + int prev_sms = curwin->w_p_sms; + colnr_T prev_skipcol = curwin->w_skipcol; + linenr_T prev_topline = curwin->w_topline; #ifdef FEAT_DIFF - room += curwin->w_filler_rows; -#endif - if (flag) - { - /* - * scroll the text up - */ - while (n > 0 && curwin->w_botline <= curbuf->b_ml.ml_line_count) - { -#ifdef FEAT_DIFF - if (curwin->w_topfill > 0) - { - i = 1; - --n; - --curwin->w_topfill; - } - else -#endif - { - i = PLINES_NOFILL(curwin->w_topline); - n -= i; - if (n < 0 && scrolled > 0) - break; -#ifdef FEAT_FOLDING - (void)hasFolding(curwin->w_topline, NULL, &curwin->w_topline); -#endif - ++curwin->w_topline; -#ifdef FEAT_DIFF - curwin->w_topfill = diff_check_fill(curwin, curwin->w_topline); + int prev_topfill = curwin->w_topfill; #endif - if (curwin->w_cursor.lnum < curbuf->b_ml.ml_line_count) - { - ++curwin->w_cursor.lnum; - curwin->w_valid &= - ~(VALID_VIRTCOL|VALID_CHEIGHT|VALID_WCOL); - } - } - curwin->w_valid &= ~(VALID_CROW|VALID_WROW); - scrolled += i; + curwin->w_p_sms = TRUE; + scroll_redraw(dir == FORWARD, count); + + // Not actually smoothscrolling but ended up with partially visible line. + // Continue scrolling until skipcol is zero. + if (!prev_sms && curwin->w_skipcol > 0) + { + int fixdir = dir; + // Reverse the scroll direction when topline already changed. One line + // extra for scrolling backward so that consuming skipcol is symmetric. + if (labs(curwin->w_topline - prev_topline) > (dir == BACKWARD)) + fixdir = dir * -1; + while (curwin->w_skipcol > 0 + && curwin->w_topline < curbuf->b_ml.ml_line_count) + scroll_redraw(fixdir == FORWARD, 1); + } + curwin->w_p_sms = prev_sms; - /* - * Correct w_botline for changed w_topline. - * Won't work when there are filler lines. - */ + return curwin->w_topline == prev_topline #ifdef FEAT_DIFF - if (curwin->w_p_diff) - curwin->w_valid &= ~(VALID_BOTLINE|VALID_BOTLINE_AP); - else + && curwin->w_topfill == prev_topfill #endif - { - room += i; - do - { - i = plines(curwin->w_botline); - if (i > room) - break; -#ifdef FEAT_FOLDING - (void)hasFolding(curwin->w_botline, NULL, - &curwin->w_botline); -#endif - ++curwin->w_botline; - room -= i; - } while (curwin->w_botline <= curbuf->b_ml.ml_line_count); - } + && curwin->w_skipcol == prev_skipcol; +} + +/* + * Move screen "count" (half) pages up ("dir" is BACKWARD) or down ("dir" is + * FORWARD) and update the screen. Handle moving the cursor and not scrolling + * to reveal end of buffer lines for half-page scrolling with CTRL-D and CTRL-U. + * + * Return FAIL for failure, OK otherwise. + */ + int +pagescroll(int dir, long count, int half) +{ + int nochange = TRUE; + int buflen = curbuf->b_ml.ml_line_count; + colnr_T prev_col = curwin->w_cursor.col; + colnr_T prev_curswant = curwin->w_curswant; + linenr_T prev_lnum = curwin->w_cursor.lnum; + oparg_T oa = { 0 }; + cmdarg_T ca = { 0 }; + ca.oap = &oa; + + if (half) + { + // Scroll [count], 'scroll' or current window height lines. + if (count) + curwin->w_p_scr = MIN(curwin->w_height, count); + count = MIN(curwin->w_height, curwin->w_p_scr); + + int curscount = count; + // Adjust count so as to not reveal end of buffer lines. + if (dir == FORWARD) + { + int n = plines_correct_topline(curwin, curwin->w_topline, FALSE); + if (n - count < curwin->w_height && curwin->w_topline < buflen) + n += plines_m_win(curwin, curwin->w_topline + 1, buflen, FALSE); + if (n - count < curwin->w_height) + count = n - curwin->w_height; } - /* - * When hit bottom of the file: move cursor down. - */ - if (n > 0) + // (Try to) scroll the window unless already at the end of the buffer. + if (count > 0) { -# ifdef FEAT_FOLDING - if (hasAnyFolding(curwin)) - { - while (--n >= 0 - && curwin->w_cursor.lnum < curbuf->b_ml.ml_line_count) - { - (void)hasFolding(curwin->w_cursor.lnum, NULL, - &curwin->w_cursor.lnum); - ++curwin->w_cursor.lnum; - } - } - else -# endif - curwin->w_cursor.lnum += n; - check_cursor_lnum(); + nochange = scroll_with_sms(dir, count); + curwin->w_cursor.lnum = prev_lnum; + curwin->w_cursor.col = prev_col; + curwin->w_curswant = prev_curswant; } + + // Move the cursor the same amount of screen lines. + if (curwin->w_p_wrap) + nv_screengo(&oa, dir, curscount); + else if (dir == FORWARD) + cursor_down_inner(curwin, curscount); + else + cursor_up_inner(curwin, curscount); } else { - /* - * scroll the text down - */ - while (n > 0 && curwin->w_topline > 1) - { -#ifdef FEAT_DIFF - if (curwin->w_topfill < diff_check_fill(curwin, curwin->w_topline)) - { - i = 1; - --n; - ++curwin->w_topfill; - } - else -#endif - { - i = PLINES_NOFILL(curwin->w_topline - 1); - n -= i; - if (n < 0 && scrolled > 0) - break; - --curwin->w_topline; -#ifdef FEAT_FOLDING - (void)hasFolding(curwin->w_topline, &curwin->w_topline, NULL); -#endif -#ifdef FEAT_DIFF - curwin->w_topfill = 0; -#endif - } - curwin->w_valid &= ~(VALID_CROW|VALID_WROW| - VALID_BOTLINE|VALID_BOTLINE_AP); - scrolled += i; - if (curwin->w_cursor.lnum > 1) - { - --curwin->w_cursor.lnum; - curwin->w_valid &= ~(VALID_VIRTCOL|VALID_CHEIGHT|VALID_WCOL); - } - } + // Scroll [count] times 'window' or current window height lines. + count *= ((ONE_WINDOW && p_window > 0 && p_window < Rows - 1) ? + MAX(1, p_window - 2) : get_scroll_overlap(dir)); + nochange = scroll_with_sms(dir, count); - /* - * When hit top of the file: move cursor up. - */ - if (n > 0) - { - if (curwin->w_cursor.lnum <= (linenr_T)n) - curwin->w_cursor.lnum = 1; - else -# ifdef FEAT_FOLDING - if (hasAnyFolding(curwin)) - { - while (--n >= 0 && curwin->w_cursor.lnum > 1) - { - --curwin->w_cursor.lnum; - (void)hasFolding(curwin->w_cursor.lnum, - &curwin->w_cursor.lnum, NULL); - } - } - else -# endif - curwin->w_cursor.lnum -= n; - } + // Place cursor at top or bottom of window. + validate_botline(); + curwin->w_cursor.lnum = (dir == FORWARD ? curwin->w_topline + : curwin->w_botline - 1); } -# ifdef FEAT_FOLDING + + if (get_scrolloff_value() > 0) + cursor_correct(); +#ifdef FEAT_FOLDING // Move cursor to first line of closed fold. foldAdjustCursor(); -# endif -#ifdef FEAT_DIFF - check_topfill(curwin, !flag); #endif - cursor_correct(); - beginline(BL_SOL | BL_FIX); - redraw_later(UPD_VALID); + nochange = nochange + && prev_col == curwin->w_cursor.col + && prev_lnum == curwin->w_cursor.lnum; + + // Error if both the viewport and cursor did not change. + if (nochange) + beep_flush(); + else if (!curwin->w_p_sms) + beginline(BL_SOL | BL_FIX); + else if (p_sol) + nv_g_home_m_cmd(&ca); + + return nochange; } void diff --git a/src/normal.c b/src/normal.c index 5ef3a92..fef2826 100644 --- a/src/normal.c +++ b/src/normal.c @@ -1708,6 +1708,7 @@ add_to_showcmd(int c) int extra_len; int overflow; int i; + char_u mbyte_buf[MB_MAXBYTES]; static int ignore[] = { #ifdef FEAT_GUI @@ -1739,9 +1740,17 @@ add_to_showcmd(int c) if (ignore[i] == c) return FALSE; - p = transchar(c); - if (*p == ' ') - STRCPY(p, "<20>"); + if (c <= 0x7f || !vim_isprintc(c)) + { + p = transchar(c); + if (*p == ' ') + STRCPY(p, "<20>"); + } + else + { + mbyte_buf[(*mb_char2bytes)(c, mbyte_buf)] = NUL; + p = mbyte_buf; + } old_len = (int)STRLEN(showcmd_buf); extra_len = (int)STRLEN(p); overflow = old_len + extra_len - SHOWCMD_COLS; @@ -1810,7 +1819,7 @@ pop_showcmd(void) static void display_showcmd(void) { - int len = (int)STRLEN(showcmd_buf); + int len = vim_strsize(showcmd_buf); showcmd_is_clear = (len == 0); cursor_off(); @@ -2066,7 +2075,7 @@ nv_page(cmdarg_T *cap) goto_tabpage((int)cap->count0); } else - (void)onepage(cap->arg, cap->count1); + (void)pagescroll(cap->arg, cap->count1, FALSE); } /* @@ -2303,10 +2312,12 @@ find_decl( * * Return OK if able to move cursor, FAIL otherwise. */ - static int + int nv_screengo(oparg_T *oap, int dir, long dist) { - int linelen = linetabsize(curwin, curwin->w_cursor.lnum); + + int linelen = linetabsize_no_outer(curwin, curwin->w_cursor.lnum); + int retval = OK; int atend = FALSE; int n; @@ -2376,7 +2387,7 @@ nv_screengo(oparg_T *oap, int dir, long dist) } cursor_up_inner(curwin, 1); - linelen = linetabsize(curwin, curwin->w_cursor.lnum); + linelen = linetabsize_no_outer(curwin, curwin->w_cursor.lnum); if (linelen > width1) curwin->w_curswant += (((linelen - width1 - 1) / width2) + 1) * width2; @@ -2413,7 +2424,7 @@ nv_screengo(oparg_T *oap, int dir, long dist) // clipped to column 0. if (curwin->w_curswant >= width1) curwin->w_curswant -= width2; - linelen = linetabsize(curwin, curwin->w_cursor.lnum); + linelen = linetabsize_no_outer(curwin, curwin->w_cursor.lnum); } } } @@ -2472,65 +2483,6 @@ nv_scroll_line(cmdarg_T *cap) } /* - * Scroll "count" lines up or down, and redraw. - */ - void -scroll_redraw(int up, long count) -{ - linenr_T prev_topline = curwin->w_topline; - int prev_skipcol = curwin->w_skipcol; -#ifdef FEAT_DIFF - int prev_topfill = curwin->w_topfill; -#endif - linenr_T prev_lnum = curwin->w_cursor.lnum; - - if (up) - scrollup(count, TRUE); - else - scrolldown(count, TRUE); - if (get_scrolloff_value() > 0) - { - // Adjust the cursor position for 'scrolloff'. Mark w_topline as - // valid, otherwise the screen jumps back at the end of the file. - cursor_correct(); - check_cursor_moved(curwin); - curwin->w_valid |= VALID_TOPLINE; - - // If moved back to where we were, at least move the cursor, otherwise - // we get stuck at one position. Don't move the cursor up if the - // first line of the buffer is already on the screen - while (curwin->w_topline == prev_topline - && curwin->w_skipcol == prev_skipcol -#ifdef FEAT_DIFF - && curwin->w_topfill == prev_topfill -#endif - ) - { - if (up) - { - if (curwin->w_cursor.lnum > prev_lnum - || cursor_down(1L, FALSE) == FAIL) - break; - } - else - { - if (curwin->w_cursor.lnum < prev_lnum - || prev_topline == 1L - || cursor_up(1L, FALSE) == FAIL) - break; - } - // Mark w_topline as valid, otherwise the screen jumps back at the - // end of the file. - check_cursor_moved(curwin); - curwin->w_valid |= VALID_TOPLINE; - } - } - if (curwin->w_cursor.lnum != prev_lnum) - coladvance(curwin->w_curswant); - redraw_later(UPD_VALID); -} - -/* * Get the count specified after a 'z' command. Only the 'z<CR>', 'zl', 'zh', * 'z<Left>', and 'z<Right>' commands accept a count after 'z'. * Returns TRUE to process the 'z' command and FALSE to skip it. @@ -5743,7 +5695,7 @@ nv_gv_cmd(cmdarg_T *cap) * "g0", "g^" : Like "0" and "^" but for screen lines. * "gm": middle of "g0" and "g$". */ - static void + void nv_g_home_m_cmd(cmdarg_T *cap) { int i; @@ -5769,6 +5721,15 @@ nv_g_home_m_cmd(cmdarg_T *cap) i = 0; if (virtcol >= (colnr_T)width1 && width2 > 0) i = (virtcol - width1) / width2 * width2 + width1; + + // When ending up below 'smoothscroll' marker, move just beyond it so + // that skipcol is not adjusted later. + if (curwin->w_skipcol > 0 && curwin->w_cursor.lnum == curwin->w_topline) + { + int overlap = sms_marker_overlap(curwin, -1); + if (overlap > 0 && i == curwin->w_skipcol) + i += overlap; + } } else i = curwin->w_leftcol; @@ -6064,7 +6025,7 @@ nv_g_cmd(cmdarg_T *cap) { oap->motion_type = MCHAR; oap->inclusive = FALSE; - i = linetabsize(curwin, curwin->w_cursor.lnum); + i = linetabsize_no_outer(curwin, curwin->w_cursor.lnum); if (cap->count0 > 0 && cap->count0 <= 100) coladvance((colnr_T)(i * cap->count0 / 100)); else @@ -7261,12 +7222,9 @@ nv_at(cmdarg_T *cap) static void nv_halfpage(cmdarg_T *cap) { - if ((cap->cmdchar == Ctrl_U && curwin->w_cursor.lnum == 1) - || (cap->cmdchar == Ctrl_D - && curwin->w_cursor.lnum == curbuf->b_ml.ml_line_count)) - clearopbeep(cap->oap); - else if (!checkclearop(cap->oap)) - halfpage(cap->cmdchar == Ctrl_D, cap->count0); + int dir = cap->cmdchar == Ctrl_D ? FORWARD : BACKWARD; + if (!checkclearop(cap->oap)) + pagescroll(dir, cap->count0, TRUE); } /* @@ -281,6 +281,7 @@ shift_block(oparg_T *oap, int amount) int oldstate = State; int total; char_u *newp, *oldp; + size_t newlen, oldlen; int oldcol = curwin->w_cursor.col; int sw_val = (int)get_sw_value_indent(curbuf); int ts_val = (int)curbuf->b_p_ts; @@ -288,7 +289,7 @@ shift_block(oparg_T *oap, int amount) int incr; colnr_T ws_vcol; int added; - unsigned new_line_len; // the length of the line after the + size_t new_line_len; // the length of the line after the // block shift #ifdef FEAT_RIGHTLEFT int old_p_ri = p_ri; @@ -307,6 +308,7 @@ shift_block(oparg_T *oap, int amount) return; // multiplication overflow oldp = ml_get_curline(); + oldlen = ml_get_curline_len(); if (!left) { @@ -369,15 +371,16 @@ shift_block(oparg_T *oap, int amount) // if we're splitting a TAB, allow for it bd.textcol -= bd.pre_whitesp_c - (bd.startspaces != 0); - new_line_len = bd.textcol + tabs + spaces + (int)STRLEN(bd.textstart); + new_line_len = bd.textcol + tabs + spaces + (oldlen - (bd.textstart - oldp)); newp = alloc(new_line_len + 1); if (newp == NULL) return; mch_memmove(newp, oldp, (size_t)bd.textcol); - vim_memset(newp + bd.textcol, TAB, (size_t)tabs); - vim_memset(newp + bd.textcol + tabs, ' ', (size_t)spaces); - // Note that STRMOVE() copies the trailing NUL. - STRMOVE(newp + bd.textcol + tabs + spaces, bd.textstart); + newlen = bd.textcol; + vim_memset(newp + newlen, TAB, (size_t)tabs); + newlen += tabs; + vim_memset(newp + newlen, ' ', (size_t)spaces); + STRCPY(newp + newlen + spaces, bd.textstart); } else // left { @@ -387,11 +390,13 @@ shift_block(oparg_T *oap, int amount) // copied verbatim colnr_T verbatim_copy_width;// the (displayed) width of this part // of line - unsigned fill; // nr of spaces that replace a TAB + size_t fill; // nr of spaces that replace a TAB size_t block_space_width; size_t shift_amount; char_u *non_white = bd.textstart; colnr_T non_white_col; + size_t fixedlen; // length of string left of the shift + // position (ie the string not being shifted) chartabsize_T cts; /* @@ -463,21 +468,27 @@ shift_block(oparg_T *oap, int amount) // - the beginning of the original line up to "verbatim_copy_end", // - "fill" number of spaces, // - the rest of the line, pointed to by non_white. - new_line_len = (unsigned)(verbatim_copy_end - oldp) - + fill - + (unsigned)STRLEN(non_white); + fixedlen = verbatim_copy_end - oldp; + new_line_len = fixedlen + fill + (oldlen - (non_white - oldp)); newp = alloc(new_line_len + 1); if (newp == NULL) return; - mch_memmove(newp, oldp, (size_t)(verbatim_copy_end - oldp)); - vim_memset(newp + (verbatim_copy_end - oldp), ' ', (size_t)fill); - // Note that STRMOVE() copies the trailing NUL. - STRMOVE(newp + (verbatim_copy_end - oldp) + fill, non_white); + mch_memmove(newp, oldp, fixedlen); + newlen = fixedlen; + vim_memset(newp + newlen, ' ', (size_t)fill); + STRCPY(newp + newlen + fill, non_white); } // replace the line - added = new_line_len - ml_get_curline_len(); ml_replace(curwin->w_cursor.lnum, newp, FALSE); + + // compute the number of bytes added or subtracted. + // note new_line_len and oldlen are unsigned so we have + // to be careful about how we calculate this. + if (new_line_len >= oldlen) + added = (int)(new_line_len - oldlen); + else + added = 0 - (int)(oldlen - new_line_len); inserted_bytes(curwin->w_cursor.lnum, bd.textcol, added); State = oldstate; curwin->w_cursor.col = oldcol; @@ -494,6 +505,7 @@ shift_block(oparg_T *oap, int amount) block_insert( oparg_T *oap, char_u *s, + size_t slen, int b_insert, struct block_def *bdp) { @@ -502,13 +514,11 @@ block_insert( int spaces = 0; // non-zero if cutting a TAB colnr_T offset; // pointer along new line colnr_T startcol; // column where insert starts - unsigned s_len; // STRLEN(s) char_u *newp, *oldp; // new, old lines linenr_T lnum; // loop var int oldstate = State; State = MODE_INSERT; // don't want MODE_REPLACE for State - s_len = (unsigned)STRLEN(s); for (lnum = oap->start.lnum + 1; lnum <= oap->end.lnum; lnum++) { @@ -554,7 +564,7 @@ block_insert( spaces = 0; // Make sure the allocated size matches what is actually copied below. - newp = alloc(ml_get_len(lnum) + spaces + s_len + newp = alloc(ml_get_len(lnum) + spaces + slen + (spaces > 0 && !bdp->is_short ? ts_val - spaces : 0) + count + 1); if (newp == NULL) @@ -569,8 +579,8 @@ block_insert( startcol = offset + spaces; // copy the new text - mch_memmove(newp + startcol, s, (size_t)s_len); - offset += s_len; + mch_memmove(newp + startcol, s, slen); + offset += slen; if (spaces > 0 && !bdp->is_short) { @@ -591,13 +601,13 @@ block_insert( if (spaces > 0) offset += count; - STRMOVE(newp + offset, oldp); + STRCPY(newp + offset, oldp); ml_replace(lnum, newp, FALSE); if (b_insert) // correct any text properties - inserted_bytes(lnum, startcol, s_len); + inserted_bytes(lnum, startcol, slen); if (lnum == oap->end.lnum) { @@ -809,8 +819,8 @@ op_delete(oparg_T *oap) vim_memset(newp + bd.textcol, ' ', (size_t)(bd.startspaces + bd.endspaces)); // copy the part after the deleted part - oldp += bd.textcol + bd.textlen; - STRMOVE(newp + bd.textcol + bd.startspaces + bd.endspaces, oldp); + STRCPY(newp + bd.textcol + bd.startspaces + bd.endspaces, + oldp + bd.textcol + bd.textlen); // replace the line ml_replace(lnum, newp, FALSE); @@ -1030,7 +1040,7 @@ op_replace(oparg_T *oap, int c) int n, numc; int num_chars; char_u *newp, *oldp; - size_t oldlen; + size_t newlen, oldlen; struct block_def bd; char_u *after_p = NULL; int had_ctrl_v_cr = FALSE; @@ -1122,9 +1132,10 @@ op_replace(oparg_T *oap, int c) vim_memset(newp, NUL, (size_t)(oldlen + 1 + n)); // copy up to deleted part mch_memmove(newp, oldp, (size_t)bd.textcol); - oldp += bd.textcol + bd.textlen; + newlen = bd.textcol; // insert pre-spaces - vim_memset(newp + bd.textcol, ' ', (size_t)bd.startspaces); + vim_memset(newp + newlen, ' ', (size_t)bd.startspaces); + newlen += bd.startspaces; // insert replacement chars CHECK FOR ALLOCATED SPACE // REPLACE_CR_NCHAR/REPLACE_NL_NCHAR is used for entering CR // literally. @@ -1132,27 +1143,31 @@ op_replace(oparg_T *oap, int c) { if (has_mbyte) { - n = (int)STRLEN(newp); while (--num_chars >= 0) - n += (*mb_char2bytes)(c, newp + n); + newlen += (*mb_char2bytes)(c, newp + newlen); } else - vim_memset(newp + STRLEN(newp), c, (size_t)numc); + { + vim_memset(newp + newlen, c, (size_t)numc); + newlen += numc; + } if (!bd.is_short) { // insert post-spaces - vim_memset(newp + STRLEN(newp), ' ', (size_t)bd.endspaces); + vim_memset(newp + newlen, ' ', (size_t)bd.endspaces); // copy the part after the changed part - STRMOVE(newp + STRLEN(newp), oldp); + STRCPY(newp + newlen + bd.endspaces, + oldp + bd.textcol + bd.textlen); } } else { // Replacing with \r or \n means splitting the line. - after_p = alloc(oldlen + 1 + n - STRLEN(newp)); + after_p = alloc(oldlen + 1 + n - newlen); if (after_p != NULL) - STRMOVE(after_p, oldp); + STRCPY(after_p, oldp + bd.textcol + bd.textlen); } + // replace the line ml_replace(curwin->w_cursor.lnum, newp, FALSE); if (after_p != NULL) @@ -1593,12 +1608,12 @@ op_insert(oparg_T *oap, long count1) if (oap->block_mode) { - long ins_len; + size_t ins_len; char_u *firstline, *ins_text; struct block_def bd2; int did_indent = FALSE; size_t len; - int add; + size_t add; // offset when cursor was moved in insert mode int offset = 0; @@ -1703,7 +1718,7 @@ op_insert(oparg_T *oap, long count1) return; } } - if ((size_t)add > len) + if (add > len) add = len; // short line, point to the NUL firstline += add; len -= add; @@ -1715,7 +1730,7 @@ op_insert(oparg_T *oap, long count1) // block handled here if (u_save(oap->start.lnum, (linenr_T)(oap->end.lnum + 1)) == OK) - block_insert(oap, ins_text, (oap->op_type == OP_INSERT), + block_insert(oap, ins_text, ins_len, (oap->op_type == OP_INSERT), &bd); curwin->w_cursor.col = oap->start.col; @@ -1736,9 +1751,7 @@ op_change(oparg_T *oap) { colnr_T l; int retval; - long offset; linenr_T linenr; - long ins_len; long pre_textlen = 0; long pre_indent = 0; char_u *firstline; @@ -1798,6 +1811,8 @@ op_change(oparg_T *oap) */ if (oap->block_mode && oap->start.lnum != oap->end.lnum && !got_int) { + size_t ins_len; + // Auto-indenting may have changed the indent. If the cursor was past // the indent, exclude that indent change from the inserted text. firstline = ml_get(oap->start.lnum); @@ -1816,7 +1831,7 @@ op_change(oparg_T *oap) // copy of the inserted text. if ((ins_text = alloc(ins_len + 1)) != NULL) { - vim_strncpy(ins_text, firstline + bd.textcol, (size_t)ins_len); + vim_strncpy(ins_text, firstline + bd.textcol, ins_len); for (linenr = oap->start.lnum + 1; linenr <= oap->end.lnum; linenr++) { @@ -1824,6 +1839,7 @@ op_change(oparg_T *oap) if (!bd.is_short || virtual_op) { pos_T vpos; + size_t newlen; // If the block starts in virtual space, count the // initial coladd offset as part of "startspaces" @@ -1835,19 +1851,16 @@ op_change(oparg_T *oap) else vpos.coladd = 0; oldp = ml_get(linenr); - newp = alloc(ml_get_len(linenr) - + vpos.coladd + ins_len + 1); + newp = alloc(ml_get_len(linenr) + vpos.coladd + ins_len + 1); if (newp == NULL) continue; // copy up to block start mch_memmove(newp, oldp, (size_t)bd.textcol); - offset = bd.textcol; - vim_memset(newp + offset, ' ', (size_t)vpos.coladd); - offset += vpos.coladd; - mch_memmove(newp + offset, ins_text, (size_t)ins_len); - offset += ins_len; - oldp += bd.textcol; - STRMOVE(newp + offset, oldp); + newlen = bd.textcol; + vim_memset(newp + newlen, ' ', (size_t)vpos.coladd); + newlen += vpos.coladd; + mch_memmove(newp + newlen, ins_text, ins_len); + STRCPY(newp + newlen + ins_len, oldp + bd.textcol); ml_replace(linenr, newp, FALSE); #ifdef FEAT_PROP_POPUP // Shift the properties for linenr as edit() would do. diff --git a/src/option.c b/src/option.c index 8123a2a..0cd2823 100644 --- a/src/option.c +++ b/src/option.c @@ -364,6 +364,68 @@ set_init_clean_rtp(void) } #endif +#ifdef UNIX +/* + * Change 'runtimepath' and 'packdir' to '$XDG_CONFIG_HOME/vim' if the only + * vimrc found is located in '$XDG_CONFIG_HOME/vim/vimrc'. + * In case the '$XDG_CONFIG_HOME' variable is not set, '$HOME/.config' is used + * as a fallback as is defined in the XDG base dir specification: + * <https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html> + */ + static void +set_init_xdg_rtp(void) +{ + int opt_idx; + int has_xdg_env = TRUE; + int should_free_xdg_dir = FALSE; + char_u *vimrc1 = NULL; + char_u *vimrc2 = NULL; + char_u *xdg_dir = NULL; + char_u *xdg_rtp = NULL; + char_u *vimrc_xdg = NULL; + + // initialize chartab, so we can expand $HOME + (void)init_chartab(); + vimrc1 = expand_env_save((char_u *)USR_VIMRC_FILE); + vimrc2 = expand_env_save((char_u *)USR_VIMRC_FILE2); + + xdg_dir = mch_getenv("XDG_CONFIG_HOME"); + if (!xdg_dir) + { + xdg_dir = expand_env_save((char_u *)"~/.config"); + should_free_xdg_dir = TRUE; + has_xdg_env = FALSE; + } + vimrc_xdg = concat_fnames(xdg_dir, (char_u *)"vim/vimrc", TRUE); + + if (file_is_readable(vimrc1) || file_is_readable(vimrc2) || + !file_is_readable(vimrc_xdg)) + goto theend; + + xdg_rtp = has_xdg_env ? (char_u *)XDG_RUNTIMEPATH + : (char_u *)XDG_RUNTIMEPATH_FB; + + if ((opt_idx = findoption((char_u *)"runtimepath")) < 0) + goto theend; + + options[opt_idx].def_val[VI_DEFAULT] = xdg_rtp; + p_rtp = xdg_rtp; + + if ((opt_idx = findoption((char_u *)"packpath")) < 0) + goto theend; + + options[opt_idx].def_val[VI_DEFAULT] = xdg_rtp; + p_pp = xdg_rtp; + +theend: + vim_free(vimrc1); + vim_free(vimrc2); + vim_free(vimrc_xdg); + if (should_free_xdg_dir) + vim_free(xdg_dir); +} +#endif + /* * Expand environment variables and things like "~" for the defaults. * If option_expand() returns non-NULL the variable is expanded. This can @@ -588,6 +650,7 @@ set_init_1(int clean_arg) set_options_default(0); #ifdef UNIX + set_init_xdg_rtp(); set_init_restricted_mode(); #endif @@ -792,7 +855,10 @@ set_string_default_esc(char *name, char_u *val, int escape) opt_idx = findoption((char_u *)name); if (opt_idx < 0) + { + vim_free(p); return; + } if (options[opt_idx].flags & P_DEF_ALLOCED) vim_free(options[opt_idx].def_val[VI_DEFAULT]); @@ -3678,7 +3744,7 @@ did_set_modified(optset_T *args) if (!args->os_newval.boolean) save_file_ff(curbuf); // Buffer is unchanged redraw_titles(); - modified_was_set = args->os_newval.boolean; + curbuf->b_modified_was_set = args->os_newval.boolean; return NULL; } diff --git a/src/optiondefs.h b/src/optiondefs.h index 4ee2e20..33e3165 100644 --- a/src/optiondefs.h +++ b/src/optiondefs.h @@ -300,7 +300,7 @@ struct vimoption # define ISP_LATIN1 (char_u *)"@,161-255" #endif -# define HIGHLIGHT_INIT "8:SpecialKey,~:EndOfBuffer,@:NonText,d:Directory,e:ErrorMsg,i:IncSearch,l:Search,y:CurSearch,m:MoreMsg,M:ModeMsg,n:LineNr,a:LineNrAbove,b:LineNrBelow,N:CursorLineNr,G:CursorLineSign,O:CursorLineFold,r:Question,s:StatusLine,S:StatusLineNC,c:VertSplit,t:Title,v:Visual,V:VisualNOS,w:WarningMsg,W:WildMenu,f:Folded,F:FoldColumn,A:DiffAdd,C:DiffChange,D:DiffDelete,T:DiffText,>:SignColumn,-:Conceal,B:SpellBad,P:SpellCap,R:SpellRare,L:SpellLocal,+:Pmenu,=:PmenuSel,[:PmenuKind,]:PmenuKindSel,{:PmenuExtra,}:PmenuExtraSel,x:PmenuSbar,X:PmenuThumb,*:TabLine,#:TabLineSel,_:TabLineFill,!:CursorColumn,.:CursorLine,o:ColorColumn,q:QuickFixLine,z:StatusLineTerm,Z:StatusLineTermNC" +# define HIGHLIGHT_INIT "8:SpecialKey,~:EndOfBuffer,@:NonText,d:Directory,e:ErrorMsg,i:IncSearch,l:Search,y:CurSearch,m:MoreMsg,M:ModeMsg,n:LineNr,a:LineNrAbove,b:LineNrBelow,N:CursorLineNr,G:CursorLineSign,O:CursorLineFold,r:Question,s:StatusLine,S:StatusLineNC,c:VertSplit,t:Title,v:Visual,V:VisualNOS,w:WarningMsg,W:WildMenu,f:Folded,F:FoldColumn,A:DiffAdd,C:DiffChange,D:DiffDelete,T:DiffText,>:SignColumn,-:Conceal,B:SpellBad,P:SpellCap,R:SpellRare,L:SpellLocal,+:Pmenu,=:PmenuSel,[:PmenuKind,]:PmenuKindSel,{:PmenuExtra,}:PmenuExtraSel,x:PmenuSbar,X:PmenuThumb,*:TabLine,#:TabLineSel,_:TabLineFill,!:CursorColumn,.:CursorLine,o:ColorColumn,q:QuickFixLine,z:StatusLineTerm,Z:StatusLineTermNC,g:MsgArea" // Default python version for pyx* commands #if defined(FEAT_PYTHON) && defined(FEAT_PYTHON3) @@ -3014,6 +3014,7 @@ static struct vimoption options[] = p_term("t_8f", T_8F) p_term("t_8b", T_8B) p_term("t_8u", T_8U) + p_term("t_xo", T_XON) // terminal key codes are not in here diff --git a/src/optionstr.c b/src/optionstr.c index e5f4946..45f126f 100644 --- a/src/optionstr.c +++ b/src/optionstr.c @@ -4332,7 +4332,7 @@ do_filetype_autocmd(char_u **varp, int opt_flags, int value_changed) secure = 0; ++ft_recursive; - did_filetype = TRUE; + curbuf->b_did_filetype = TRUE; // Only pass TRUE for "force" when the value changed or not // used recursively, to avoid endless recurrence. apply_autocmds(EVENT_FILETYPE, curbuf->b_p_ft, curbuf->b_fname, diff --git a/src/os_unix.c b/src/os_unix.c index e98911e..d155142 100644 --- a/src/os_unix.c +++ b/src/os_unix.c @@ -3766,7 +3766,8 @@ mch_settmode(tmode_T tmode) { // ~ICRNL enables typing ^V^M // ~IXON disables CTRL-S stopping output, so that it can be mapped. - tnew.c_iflag &= ~(ICRNL | IXON); + tnew.c_iflag &= ~(ICRNL | + (T_XON == NULL || *T_XON == NUL ? IXON : 0)); tnew.c_lflag &= ~(ICANON | ECHO | ISIG | ECHOE # if defined(IEXTEN) | IEXTEN // IEXTEN enables typing ^V on SOLARIS @@ -7494,7 +7495,19 @@ gpm_open(void) return 1; // succeed } if (gpm_fd == -2) + { Gpm_Close(); // We don't want to talk to xterm via gpm + + // Gpm_Close fails to properly restore the WINCH and TSTP handlers, + // leading to Vim ignoring resize signals. We have to re-initialize + // these handlers again here. +# ifdef SIGWINCH + mch_signal(SIGWINCH, sig_winch); +# endif +# ifdef SIGTSTP + mch_signal(SIGTSTP, restricted ? SIG_IGN : sig_tstp); +# endif + } return 0; } diff --git a/src/os_unix.h b/src/os_unix.h index 4c77e15..6efd8ce 100644 --- a/src/os_unix.h +++ b/src/os_unix.h @@ -249,6 +249,12 @@ typedef struct dsc$descriptor DESC; # endif #endif +#ifndef XDG_VIMRC_FILE +# define XDG_VIMRC_FILE (mch_getenv("XDG_CONFIG_HOME") \ + ? "$XDG_CONFIG_HOME/vim/vimrc" \ + : "~/.config/vim/vimrc") +#endif + #if !defined(USR_VIMRC_FILE3) && defined(VMS) # define USR_VIMRC_FILE3 "sys$login:_vimrc" #endif @@ -273,6 +279,12 @@ typedef struct dsc$descriptor DESC; # ifndef USR_GVIMRC_FILE3 # define USR_GVIMRC_FILE3 "sys$login:_gvimrc" # endif +#else +# ifndef USR_GVIMRC_FILE3 +# define USR_GVIMRC_FILE3 (mch_getenv("XDG_CONFIG_HOME") \ + ? "$XDG_CONFIG_HOME/vim/gvimrc" \ + : "~/.config/vim/gvimrc") +# endif #endif #ifndef VIM_DEFAULTS_FILE @@ -349,13 +361,19 @@ typedef struct dsc$descriptor DESC; # ifdef RUNTIME_GLOBAL # ifdef RUNTIME_GLOBAL_AFTER # define DFLT_RUNTIMEPATH "~/.vim," RUNTIME_GLOBAL ",$VIMRUNTIME," RUNTIME_GLOBAL_AFTER ",~/.vim/after" +# define XDG_RUNTIMEPATH "$XDG_CONFIG_HOME/vim," RUNTIME_GLOBAL ",$VIMRUNTIME," RUNTIME_GLOBAL_AFTER "/after,$XDG_CONFIG_HOME/vim/after" +# define XDG_RUNTIMEPATH_FB "~/.config/vim," RUNTIME_GLOBAL ",$VIMRUNTIME," RUNTIME_GLOBAL_AFTER "/after,~/.config/vim/after" # define CLEAN_RUNTIMEPATH RUNTIME_GLOBAL ",$VIMRUNTIME," RUNTIME_GLOBAL_AFTER # else # define DFLT_RUNTIMEPATH "~/.vim," RUNTIME_GLOBAL ",$VIMRUNTIME," RUNTIME_GLOBAL "/after,~/.vim/after" +# define XDG_RUNTIMEPATH "$XDG_CONFIG_HOME/vim," RUNTIME_GLOBAL ",$VIMRUNTIME," RUNTIME_GLOBAL "/after,$XDG_CONFIG_HOME/vim/after" +# define XDG_RUNTIMEPATH_FB "~/.config/vim," RUNTIME_GLOBAL ",$VIMRUNTIME," RUNTIME_GLOBAL "/after,~/.config/vim/after" # define CLEAN_RUNTIMEPATH RUNTIME_GLOBAL ",$VIMRUNTIME," RUNTIME_GLOBAL "/after" # endif # else # define DFLT_RUNTIMEPATH "~/.vim,$VIM/vimfiles,$VIMRUNTIME,$VIM/vimfiles/after,~/.vim/after" +# define XDG_RUNTIMEPATH "$XDG_CONFIG_HOME/vim,$VIM/vimfiles,$VIMRUNTIME,$VIM/vimfiles/after,$XDG_CONFIG_HOME/vim/after" +# define XDG_RUNTIMEPATH_FB "~/.config/vim,$VIM/vimfiles,$VIMRUNTIME,$VIM/vimfiles/after,~/.config/vim/after" # define CLEAN_RUNTIMEPATH "$VIM/vimfiles,$VIMRUNTIME,$VIM/vimfiles/after" # endif # endif diff --git a/src/po/Make_mvc.mak b/src/po/Make_mvc.mak index fa6a1ba..a9a69fd 100644 --- a/src/po/Make_mvc.mak +++ b/src/po/Make_mvc.mak @@ -44,7 +44,9 @@ VIM = ..\vim.exe # Correct the following line for the directory where gettext et al is # installed. Please do not put the path in quotes. +!IFNDEF GETTEXT_PATH GETTEXT_PATH = D:\Programs\GetText\bin +!ENDIF # Starting from version 0.22, msgfmt forcibly converts text to UTF-8 regardless # of the value of the "charset" field. diff --git a/src/po/check.vim b/src/po/check.vim index 917c648..b0460f1 100644 --- a/src/po/check.vim +++ b/src/po/check.vim @@ -226,6 +226,15 @@ elseif ctu " endif endif +" Check that all lines are no longer than 80 chars +let overlong = search('\%>80v', 'n') +if overlong > 0 + echomsg "Lines should be wrapped at 80 columns" + " TODO: make this an error + " if error == 0 + " let error = overlong + " endif +endif if error == 0 " If all was OK restore the view. diff --git a/src/po/ru.cp1251.po b/src/po/ru.cp1251.po index 2dd453a..05d10e0 100644 --- a/src/po/ru.cp1251.po +++ b/src/po/ru.cp1251.po @@ -21,10 +21,10 @@ # msgid "" msgstr "" -"Project-Id-Version: RuVim_0.9010059.260124\n" +"Project-Id-Version: RuVim_0.9010225.290324\n" "Report-Msgid-Bugs-To: The Vim Project, <vim-dev@vim.org>\n" -"POT-Creation-Date: 2024-01-26 14:54+0300\n" -"PO-Revision-Date: 2024-01-26 14:57+0300\n" +"POT-Creation-Date: 2024-03-29 13:02+0300\n" +"PO-Revision-Date: 2024-03-29 13:57+0300\n" "Last-Translator: Restorer, <restorer@mail2k.ru>\n" "Language-Team: RuVim, https://github.com/RestorerZ/RuVim\n" "Language: ru_RU\n" @@ -692,7 +692,7 @@ msgstr "×æóèíü (áîïîìîôî)" # :!~ Restorer msgid "Not enough memory to set references, garbage collection aborted!" -msgstr "Ñáîðêà ìóñîðà ïðåðâàíà! Íåäîñòàòî÷íî ïàìÿòè äëÿ óñòàíîâêè ññûëîê" +msgstr "Ñáîð ìóñîðà ïðåðâàí! Íåäîñòàòî÷íî ïàìÿòè äëÿ óñòàíîâêè ññûëîê" # #Restorer: âûâîäèòñÿ ïðè çíà÷åíèè 'verbose'>0 # :!~ Restorer @@ -2490,11 +2490,11 @@ msgstr "--ttyfail\t\tÇàâåðøèòü ðàáîòó ïðè îòñóòñòâèè òåðìèíàëà ââîäà-âûâîäà" # :!~ Restorer msgid "-u <vimrc>\t\tUse <vimrc> instead of any .vimrc" -msgstr "-u <ôàéë>\t\tÏðèìåíèòü âìåñòî ôàéëîâ .vimrc óêàçàííûé <ôàéë>" +msgstr "-u <ôàéë>\t\tÈñïîëüçîâàòü âìåñòî ôàéëîâ .vimrc óêàçàííûé <ôàéë>" # :!~ Restorer msgid "-U <gvimrc>\t\tUse <gvimrc> instead of any .gvimrc" -msgstr "-U <ôàéë>\t\tÏðèìåíèòü âìåñòî ôàéëîâ .gvimrc óêàçàííûé <ôàéë>" +msgstr "-U <ôàéë>\t\tÈñïîëüçîâàòü âìåñòî ôàéëîâ .gvimrc óêàçàííûé <ôàéë>" # :!~ Restorer msgid "--noplugin\t\tDon't load plugin scripts" @@ -2511,7 +2511,7 @@ msgstr "" # :!~ Restorer msgid "-o[N]\t\tOpen N windows (default: one for each file)" msgstr "" -"-o[N]\t\tÑîçäàòü îêíà äëÿ N ôàéëîâ (ïî óìîë÷àíèþ ñîçäà¸òñÿ\n" +"-o[N]\t\tÑîçäàíèå îêîí äëÿ N ôàéëîâ (ïî óìîë÷àíèþ ñîçäà¸òñÿ\n" "\t\t\t ïî îäíîìó îêíó íà êàæäûé ôàéë)" # :!~ Restorer @@ -2528,19 +2528,19 @@ msgstr "+<íîìåð>\t\tÓñòàíîâêà êàðåòêè íà <íîìåð> ñòðîêè îòêðûòîãî ôàéëà" # :!~ Restorer msgid "--cmd <command>\tExecute <command> before loading any vimrc file" -msgstr "--cmd <êîìàíäà>\tÂûïîëíåíèå <êîìàíäû> ïåðåä îáðàáîòêîé ôàéëà .vimrc" +msgstr "--cmd <êîìàíäà>\tÈñïîëíåíèå <êîìàíäû> ïåðåä îáðàáîòêîé ôàéëà .vimrc" # ~!: earlier msgid "-c <command>\t\tExecute <command> after loading the first file" -msgstr "-c <êîìàíäà>\t\tÂûïîëíåíèå <êîìàíäû> ïîñëå çàãðóçêè ïåðâîãî ôàéëà" +msgstr "-c <êîìàíäà>\t\tÈñïîëíåíèå <êîìàíäû> ïîñëå ñ÷èòûâàíèÿ ïåðâîãî ôàéëà" # :!~ Restorer msgid "-S <session>\t\tSource file <session> after loading the first file" -msgstr "-S <ñåàíñ>\t\tÂûïîëíåíèå ôàéëà <ñåàíñà> ïîñëå çàãðóçêè ïåðâîãî ôàéëà" +msgstr "-S <ñåàíñ>\t\tÇàïóñê ôàéëà <ñåàíñà> ïîñëå ñ÷èòûâàíèÿ ïåðâîãî ôàéëà" # :!~ Restorer msgid "-s <scriptin>\tRead Normal mode commands from file <scriptin>" -msgstr "-s <ñöåíàðèé>\tÑ÷èòàòü êîìàíäû ðåæèìà êîìàíä èç ôàéëà <ñöåíàðèÿ>" +msgstr "-s <ñöåíàðèé>\tÑ÷èòûâàíèå êîìàíä ðåæèìà êîìàíä èç ôàéëà <ñöåíàðèÿ>" # :!~ Restorer msgid "-w <scriptout>\tAppend all typed commands to file <scriptout>" @@ -2556,8 +2556,7 @@ msgstr "-x\t\t\tÈñïîëüçîâàòü øèôðîâàíèå ïðè ñ÷èòûâàíèè è çàïèñè ôàéëîâ" # :!~ Restorer msgid "-display <display>\tConnect Vim to this particular X-server" -msgstr "" -"-display <display>\tÂûïîëíèòü ïîäêëþ÷åíèå ïðîãðàììû ê óêàçàííîìó X-ñåðâåðó" +msgstr "-display <display>\tÏîäêëþ÷åíèå ïðîãðàììû ê óêàçàííîìó X-ñåðâåðó" # :!~ Restorer msgid "-X\t\t\tDo not connect to X server" @@ -2620,7 +2619,7 @@ msgstr "" # :!~ Restorer msgid "-i <viminfo>\t\tUse <viminfo> instead of .viminfo" -msgstr "-i <ôàéë>\t\tÈñïîëüçîâàíèå âìåñòî ôàéëà .viminfo óêàçàííîãî <ôàéëà>" +msgstr "-i <ôàéë>\t\tÈñïîëüçîâàòü âìåñòî ôàéëà .viminfo óêàçàííûé <ôàéë>" # \n\t\t.. äëÿ óìåùåíèÿ â 80 ñòîëáöîâ (Ñ. Àë¸øèí) # :!~ Restorer @@ -6106,6 +6105,11 @@ msgstr "E105: Êîìàíäà :loadkeymap óêàçàíà âíå êîìàíäíîãî ôàéëà" # :!~ Restorer #, c-format +msgid "E106: Unsupported diff output format: %s" +msgstr "E106: Óêàçàííûé ôîðìàò ðåçóëüòàòà ñðàâíåíèÿ íå ïîääåðæèâàåòñÿ %s" + +# :!~ Restorer +#, c-format msgid "E107: Missing parentheses: %s" msgstr "E107: Íå óêàçàíû àðãóìåíòû â êðóãëûõ ñêîáêàõ ïðè âûçîâå ôóíêöèè %s" @@ -9695,6 +9699,11 @@ msgid "E876: (NFA regexp) Not enough space to store the whole NFA" msgstr "E876: ÍÊÀ. Íåäîñòàòî÷íî ïàìÿòè äëÿ ñîõðàíåíèÿ âñåõ ñîñòîÿíèé ìåõàíèçìà" # :!~ Restorer +#, c-format +msgid "E877: (NFA regexp) Invalid character class: %d" +msgstr "E877: ÍÊÀ. Íå óäàëîñü ðàñïîçíàòü ñèìâîëüíûé êëàññ %d" + +# :!~ Restorer msgid "E878: (NFA regexp) Could not allocate memory for branch traversal!" msgstr "E878: ÍÊÀ. Íå óäàëîñü âûäåëèòü ïàìÿòü äëÿ îáõîäà âåòâè!" @@ -12273,6 +12282,88 @@ msgstr "E1411: Íå óêàçàí ñèìâîë òî÷êè ïîñëå íàèìåíîâàíèÿ îáúåêòà %s" # :!~ Restorer #, c-format +msgid "E1412: Builtin object method \"%s\" not supported" +msgstr "E1412: Íå ïîääåðæèâàåòñÿ âñòðîåííûé ìåòîä îáúåêòà \"%s\"" + +# :!~ Restorer +msgid "E1413: Builtin class method not supported" +msgstr "E1413:  êëàññå íå äîñòóïíû âñòðîåííûå ìåòîäû" + +# :!~ Restorer +msgid "E1414: Enum can only be defined in Vim9 script" +msgstr "" +"E1414: Òèï äàííûõ Enum ìîæåò áûòü îïðåäåë¸í òîëüêî â êîìàíäíûõ ôàéëàõ Vim9" + +# :!~ Restorer +#, c-format +msgid "E1415: Enum name must start with an uppercase letter: %s" +msgstr "E1415: Íàèìåíîâàíèå òèïà Enum äîëæíî íà÷èíàòüñÿ ñ ïðîïèñíîé áóêâû %s" + +# :!~ Restorer +msgid "E1416: Enum cannot extend a class or enum" +msgstr "E1416: Òèï Enum íå ìîæåò íàñëåäîâàòüñÿ â êëàññàõ èëè äðóãèõ òèïàõ Enum" + +# :!~ Restorer +msgid "E1417: Abstract cannot be used in an Enum" +msgstr "E1417: Èíòåðôåéñû íå ïîääåðæèâàþò òèïû äàííûõ Enum" + +# :!~ Restorer +#, c-format +msgid "E1418: Invalid enum value declaration: %s" +msgstr "E1418: Íåäîïóñòèìîå îáúÿâëåíèå ïåðåìåííîé òèïà äàííûõ Enum %s" + +# :!~ Restorer +#, c-format +msgid "E1419: Not a valid command in an Enum: %s" +msgstr "E1419: Íåäîïóñòèìàÿ êîìàíäà â îáúÿâëåíèè òèïà äàííûõ Enum %s" + +# :!~ Restorer +msgid "E1420: Missing :endenum" +msgstr "E1420: Íå óêàçàíà êîìàíäà :endenum" + +# :!~ Restorer +#, c-format +msgid "E1421: Enum \"%s\" cannot be used as a value" +msgstr "E1421: Íå äîïóñêàåòñÿ â êà÷åñòâå çíà÷åíèÿ óêàçûâàòü òèï Enum \"%s\"" + +# :!~ Restorer +#, c-format +msgid "E1422: Enum value \"%s\" not found in enum \"%s\"" +msgstr "E1422: Ó òèïà äàííûõ Enum \"%2$s\" îòñóòñòâóåò ïåðåìåííàÿ \"%1$s\"" + +# :!~ Restorer +#, c-format +msgid "E1423: Enum value \"%s.%s\" cannot be modified" +msgstr "E1423: Íå äîïóñêàåòñÿ èçìåíåíèå çíà÷åíèÿ òèïà Enum \"%s.%s\"" + +# :!~ Restorer +#, c-format +msgid "E1424: Using an Enum \"%s\" as a Number" +msgstr "E1424: Îæèäàëñÿ òèï äàííûõ Number, à ïîëó÷åí òèï äàííûõ Enum \"%s\"" + +# :!~ Restorer +#, c-format +msgid "E1425: Using an Enum \"%s\" as a String" +msgstr "E1425: Îæèäàëñÿ òèï äàííûõ String, à ïîëó÷åí òèï äàííûõ Enum \"%s\"" + +# :!~ Restorer +#, c-format +msgid "E1426: Enum \"%s\" ordinal value cannot be modified" +msgstr "" +"E1426: Íå äîïóñêàåòñÿ èçìåíåíèå ïîðÿäêà çíà÷åíèé â òèïå äàííûõ Enum \"%s\"" + +# :!~ Restorer +#, c-format +msgid "E1427: Enum \"%s\" name cannot be modified" +msgstr "E1427: Íå äîïóñêàåòñÿ èçìåíåíèå íàèìåíîâàíèÿ òèïà äàííûõ Enum \"%s\"" + +# :!~ Restorer +#, c-format +msgid "E1428: Duplicate enum value: %s" +msgstr "E1428: Ïîâòîð çíà÷åíèÿ %s" + +# :!~ Restorer +#, c-format msgid "E1500: Cannot mix positional and non-positional arguments: %s" msgstr "E1500: Óêàçàíû êàê ïîçèöèîííûå, òàê è íå ïîçèöèîííûå ñïåöèôèêàòîðû %s" @@ -12340,6 +12431,10 @@ msgstr "E1511:  äàííîì ïîëå óêàçàíî íåäîïóñòèìîå êîëè÷åñòâî ñèìâîëîâ \"%s\"" msgid "E1512: Wrong character width for field \"%s\"" msgstr "E1512:  äàííîì ïîëå íå ïîääåðæèâàþòñÿ ïîëíîøèðèííûå ñèìâîëû \"%s\"" +# :!~ Restorer +msgid "E1513: Cannot switch buffer. 'winfixbuf' is enabled" +msgstr "E1513: Íå óäàëîñü ñìåíèòü áóôåð. Óñòàíîâëåí ïàðàìåòð 'winfixbuf'" + # #Restorer: âûâîäèòñÿ, íàïðèìåð, ïî êîìàíäå `CTRL+g`, `g CTRL+g` è ò. ï. # :!~ Restorer msgid "--No lines in buffer--" @@ -13331,6 +13426,10 @@ msgid "minimal number of lines used for any window" msgstr "ìèíèìàëüíîå êîëè÷åñòâî ñòðîê äëÿ âñåõ îêîí" # :!~ Restorer +msgid "keep window focused on a single buffer" +msgstr "çàêðåïèòü çà îêíîì îäèí áóôåð" + +# :!~ Restorer msgid "keep the height of the window" msgstr "îñòàâëÿòü íåèçìåííîé âûñîòó îêíà" diff --git a/src/po/ru.po b/src/po/ru.po index d4b7d6b..13589d0 100644 --- a/src/po/ru.po +++ b/src/po/ru.po @@ -21,10 +21,10 @@ # msgid "" msgstr "" -"Project-Id-Version: RuVim_0.9010059.260124\n" +"Project-Id-Version: RuVim_0.9010225.290324\n" "Report-Msgid-Bugs-To: The Vim Project, <vim-dev@vim.org>\n" -"POT-Creation-Date: 2024-01-26 14:54+0300\n" -"PO-Revision-Date: 2024-01-26 14:57+0300\n" +"POT-Creation-Date: 2024-03-29 13:02+0300\n" +"PO-Revision-Date: 2024-03-29 13:57+0300\n" "Last-Translator: Restorer, <restorer@mail2k.ru>\n" "Language-Team: RuVim, https://github.com/RestorerZ/RuVim\n" "Language: ru_RU\n" @@ -691,7 +691,7 @@ msgstr "Чжуинь (бопомофо)" # :!~ Restorer msgid "Not enough memory to set references, garbage collection aborted!" -msgstr "Сборка муÑора прервана! ÐедоÑтаточно памÑти Ð´Ð»Ñ ÑƒÑтановки ÑÑылок" +msgstr "Сбор муÑора прерван! ÐедоÑтаточно памÑти Ð´Ð»Ñ ÑƒÑтановки ÑÑылок" # #Restorer: выводитÑÑ Ð¿Ñ€Ð¸ значении 'verbose'>0 # :!~ Restorer @@ -2482,11 +2482,11 @@ msgstr "--ttyfail\t\tЗавершить работу при отÑутÑтвии # :!~ Restorer msgid "-u <vimrc>\t\tUse <vimrc> instead of any .vimrc" -msgstr "-u <файл>\t\tПрименить вмеÑто файлов .vimrc указанный <файл>" +msgstr "-u <файл>\t\tИÑпользовать вмеÑто файлов .vimrc указанный <файл>" # :!~ Restorer msgid "-U <gvimrc>\t\tUse <gvimrc> instead of any .gvimrc" -msgstr "-U <файл>\t\tПрименить вмеÑто файлов .gvimrc указанный <файл>" +msgstr "-U <файл>\t\tИÑпользовать вмеÑто файлов .gvimrc указанный <файл>" # :!~ Restorer msgid "--noplugin\t\tDon't load plugin scripts" @@ -2503,7 +2503,7 @@ msgstr "" # :!~ Restorer msgid "-o[N]\t\tOpen N windows (default: one for each file)" msgstr "" -"-o[N]\t\tСоздать окна Ð´Ð»Ñ N файлов (по умолчанию ÑоздаётÑÑ\n" +"-o[N]\t\tСоздание окон Ð´Ð»Ñ N файлов (по умолчанию ÑоздаётÑÑ\n" "\t\t\t по одному окну на каждый файл)" # :!~ Restorer @@ -2520,19 +2520,19 @@ msgstr "+<номер>\t\tУÑтановка каретки на <номер> ÑÑ # :!~ Restorer msgid "--cmd <command>\tExecute <command> before loading any vimrc file" -msgstr "--cmd <команда>\tВыполнение <команды> перед обработкой файла .vimrc" +msgstr "--cmd <команда>\tИÑполнение <команды> перед обработкой файла .vimrc" # ~!: earlier msgid "-c <command>\t\tExecute <command> after loading the first file" -msgstr "-c <команда>\t\tВыполнение <команды> поÑле загрузки первого файла" +msgstr "-c <команда>\t\tИÑполнение <команды> поÑле ÑÑ‡Ð¸Ñ‚Ñ‹Ð²Ð°Ð½Ð¸Ñ Ð¿ÐµÑ€Ð²Ð¾Ð³Ð¾ файла" # :!~ Restorer msgid "-S <session>\t\tSource file <session> after loading the first file" -msgstr "-S <ÑеанÑ>\t\tВыполнение файла <ÑеанÑа> поÑле загрузки первого файла" +msgstr "-S <ÑеанÑ>\t\tЗапуÑк файла <ÑеанÑа> поÑле ÑÑ‡Ð¸Ñ‚Ñ‹Ð²Ð°Ð½Ð¸Ñ Ð¿ÐµÑ€Ð²Ð¾Ð³Ð¾ файла" # :!~ Restorer msgid "-s <scriptin>\tRead Normal mode commands from file <scriptin>" -msgstr "-s <Ñценарий>\tСчитать команды режима команд из файла <ÑценариÑ>" +msgstr "-s <Ñценарий>\tСчитывание команд режима команд из файла <ÑценариÑ>" # :!~ Restorer msgid "-w <scriptout>\tAppend all typed commands to file <scriptout>" @@ -2548,8 +2548,7 @@ msgstr "-x\t\t\tИÑпользовать шифрование при ÑчитыР# :!~ Restorer msgid "-display <display>\tConnect Vim to this particular X-server" -msgstr "" -"-display <display>\tВыполнить подключение программы к указанному X-Ñерверу" +msgstr "-display <display>\tПодключение программы к указанному X-Ñерверу" # :!~ Restorer msgid "-X\t\t\tDo not connect to X server" @@ -2608,7 +2607,7 @@ msgstr "--log <файл>\t\tЗапиÑÑŒ протокола работы Ñ ÑÑ‚ # :!~ Restorer msgid "-i <viminfo>\t\tUse <viminfo> instead of .viminfo" -msgstr "-i <файл>\t\tИÑпользование вмеÑто файла .viminfo указанного <файла>" +msgstr "-i <файл>\t\tИÑпользовать вмеÑто файла .viminfo указанный <файл>" # \n\t\t.. Ð´Ð»Ñ ÑƒÐ¼ÐµÑ‰ÐµÐ½Ð¸Ñ Ð² 80 Ñтолбцов (С. Ðлёшин) # :!~ Restorer @@ -6070,6 +6069,11 @@ msgstr "E105: Команда :loadkeymap указана вне командноР# :!~ Restorer #, c-format +msgid "E106: Unsupported diff output format: %s" +msgstr "E106: Указанный формат результата ÑÑ€Ð°Ð²Ð½ÐµÐ½Ð¸Ñ Ð½Ðµ поддерживаетÑÑ %s" + +# :!~ Restorer +#, c-format msgid "E107: Missing parentheses: %s" msgstr "E107: Ðе указаны аргументы в круглых Ñкобках при вызове функции %s" @@ -9627,6 +9631,11 @@ msgid "E876: (NFA regexp) Not enough space to store the whole NFA" msgstr "E876: ÐКÐ. ÐедоÑтаточно памÑти Ð´Ð»Ñ ÑÐ¾Ñ…Ñ€Ð°Ð½ÐµÐ½Ð¸Ñ Ð²Ñех ÑоÑтоÑний механизма" # :!~ Restorer +#, c-format +msgid "E877: (NFA regexp) Invalid character class: %d" +msgstr "E877: ÐКÐ. Ðе удалоÑÑŒ раÑпознать Ñимвольный клаÑÑ %d" + +# :!~ Restorer msgid "E878: (NFA regexp) Could not allocate memory for branch traversal!" msgstr "E878: ÐКÐ. Ðе удалоÑÑŒ выделить памÑÑ‚ÑŒ Ð´Ð»Ñ Ð¾Ð±Ñ…Ð¾Ð´Ð° ветви!" @@ -12183,6 +12192,88 @@ msgstr "E1411: Ðе указан Ñимвол точки поÑле наимен # :!~ Restorer #, c-format +msgid "E1412: Builtin object method \"%s\" not supported" +msgstr "E1412: Ðе поддерживаетÑÑ Ð²Ñтроенный метод объекта \"%s\"" + +# :!~ Restorer +msgid "E1413: Builtin class method not supported" +msgstr "E1413: Ð’ клаÑÑе не доÑтупны вÑтроенные методы" + +# :!~ Restorer +msgid "E1414: Enum can only be defined in Vim9 script" +msgstr "" +"E1414: Тип данных Enum может быть определён только в командных файлах Vim9" + +# :!~ Restorer +#, c-format +msgid "E1415: Enum name must start with an uppercase letter: %s" +msgstr "E1415: Ðаименование типа Enum должно начинатьÑÑ Ñ Ð¿Ñ€Ð¾Ð¿Ð¸Ñной буквы %s" + +# :!~ Restorer +msgid "E1416: Enum cannot extend a class or enum" +msgstr "E1416: Тип Enum не может наÑледоватьÑÑ Ð² клаÑÑах или других типах Enum" + +# :!~ Restorer +msgid "E1417: Abstract cannot be used in an Enum" +msgstr "E1417: ИнтерфейÑÑ‹ не поддерживают типы данных Enum" + +# :!~ Restorer +#, c-format +msgid "E1418: Invalid enum value declaration: %s" +msgstr "E1418: ÐедопуÑтимое объÑвление переменной типа данных Enum %s" + +# :!~ Restorer +#, c-format +msgid "E1419: Not a valid command in an Enum: %s" +msgstr "E1419: ÐедопуÑÑ‚Ð¸Ð¼Ð°Ñ ÐºÐ¾Ð¼Ð°Ð½Ð´Ð° в объÑвлении типа данных Enum %s" + +# :!~ Restorer +msgid "E1420: Missing :endenum" +msgstr "E1420: Ðе указана команда :endenum" + +# :!~ Restorer +#, c-format +msgid "E1421: Enum \"%s\" cannot be used as a value" +msgstr "E1421: Ðе допуÑкаетÑÑ Ð² качеÑтве Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ ÑƒÐºÐ°Ð·Ñ‹Ð²Ð°Ñ‚ÑŒ тип Enum \"%s\"" + +# :!~ Restorer +#, c-format +msgid "E1422: Enum value \"%s\" not found in enum \"%s\"" +msgstr "E1422: У типа данных Enum \"%2$s\" отÑутÑтвует Ð¿ÐµÑ€ÐµÐ¼ÐµÐ½Ð½Ð°Ñ \"%1$s\"" + +# :!~ Restorer +#, c-format +msgid "E1423: Enum value \"%s.%s\" cannot be modified" +msgstr "E1423: Ðе допуÑкаетÑÑ Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ðµ Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ Ñ‚Ð¸Ð¿Ð° Enum \"%s.%s\"" + +# :!~ Restorer +#, c-format +msgid "E1424: Using an Enum \"%s\" as a Number" +msgstr "E1424: ОжидалÑÑ Ñ‚Ð¸Ð¿ данных Number, а получен тип данных Enum \"%s\"" + +# :!~ Restorer +#, c-format +msgid "E1425: Using an Enum \"%s\" as a String" +msgstr "E1425: ОжидалÑÑ Ñ‚Ð¸Ð¿ данных String, а получен тип данных Enum \"%s\"" + +# :!~ Restorer +#, c-format +msgid "E1426: Enum \"%s\" ordinal value cannot be modified" +msgstr "" +"E1426: Ðе допуÑкаетÑÑ Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ðµ порÑдка значений в типе данных Enum \"%s\"" + +# :!~ Restorer +#, c-format +msgid "E1427: Enum \"%s\" name cannot be modified" +msgstr "E1427: Ðе допуÑкаетÑÑ Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ðµ Ð½Ð°Ð¸Ð¼ÐµÐ½Ð¾Ð²Ð°Ð½Ð¸Ñ Ñ‚Ð¸Ð¿Ð° данных Enum \"%s\"" + +# :!~ Restorer +#, c-format +msgid "E1428: Duplicate enum value: %s" +msgstr "E1428: Повтор Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ %s" + +# :!~ Restorer +#, c-format msgid "E1500: Cannot mix positional and non-positional arguments: %s" msgstr "E1500: Указаны как позиционные, так и не позиционные Ñпецификаторы %s" @@ -12248,6 +12339,10 @@ msgstr "E1511: Ð’ данном поле указано недопуÑтимое msgid "E1512: Wrong character width for field \"%s\"" msgstr "E1512: Ð’ данном поле не поддерживаютÑÑ Ð¿Ð¾Ð»Ð½Ð¾ÑˆÐ¸Ñ€Ð¸Ð½Ð½Ñ‹Ðµ Ñимволы \"%s\"" +# :!~ Restorer +msgid "E1513: Cannot switch buffer. 'winfixbuf' is enabled" +msgstr "E1513: Ðе удалоÑÑŒ Ñменить буфер. УÑтановлен параметр 'winfixbuf'" + # #Restorer: выводитÑÑ, например, по команде `CTRL+g`, `g CTRL+g` и Ñ‚. п. # :!~ Restorer msgid "--No lines in buffer--" @@ -13235,6 +13330,10 @@ msgid "minimal number of lines used for any window" msgstr "минимальное количеÑтво Ñтрок Ð´Ð»Ñ Ð²Ñех окон" # :!~ Restorer +msgid "keep window focused on a single buffer" +msgstr "закрепить за окном один буфер" + +# :!~ Restorer msgid "keep the height of the window" msgstr "оÑтавлÑÑ‚ÑŒ неизменной выÑоту окна" diff --git a/src/po/sr.po b/src/po/sr.po index 2f5113c..6372f92 100644 --- a/src/po/sr.po +++ b/src/po/sr.po @@ -10,8 +10,8 @@ msgid "" msgstr "" "Project-Id-Version: Vim(Serbian)\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2024-03-04 14:05+0400\n" -"PO-Revision-Date: 2024-03-04 14:10+0400\n" +"POT-Creation-Date: 2024-04-25 12:55+0400\n" +"PO-Revision-Date: 2024-04-25 13:09+0400\n" "Last-Translator: Ivan PeÅ¡ić <ivan.pesic@gmail.com>\n" "Language-Team: Serbian\n" "Language: sr\n" @@ -3622,6 +3622,9 @@ msgstr " 2ги кориÑнички vimrc фајл: \"" msgid " 3rd user vimrc file: \"" msgstr " 3ћи кориÑнички vimrc фајл: \"" +msgid " 4th user vimrc file: \"" +msgstr " 4ти кориÑнички vimrc фајл: \"" + msgid " user exrc file: \"" msgstr " кориÑнички exrc фајл: \"" @@ -6834,6 +6837,10 @@ msgstr "" "E876: (ÐКРрегуларни израз) Ðема довољно проÑтора да Ñе уÑкладишти комплетан " "ÐКÐ" +#, c-format +msgid "E877: (NFA regexp) Invalid character class: %d" +msgstr "E877: (ÐКРрегуларни израз) ÐеиÑправна клаÑа карактера: %d" + msgid "E878: (NFA regexp) Could not allocate memory for branch traversal!" msgstr "" "E878: (ÐКРрегуларни израз) Ðије могла да Ñе алоцира меморија за обилазак " @@ -8457,14 +8464,14 @@ msgid "E1330: Invalid type for object variable: %s" msgstr "E1330: ÐеиÑправан тип променљиве објекта: %s" msgid "" -"E1331: Public must be followed by \"var\" or \"static\" or \"final\" or " +"E1331: public must be followed by \"var\" or \"static\" or \"final\" or " "\"const\"" msgstr "" -"E1331: Ðакон Public мора да Ñледи „var†или „static†или „final†или „constâ€" +"E1331: Ðакон public мора да Ñледи „var†или „static†или „final†или „constâ€" #, c-format -msgid "E1332: Public variable name cannot start with underscore: %s" -msgstr "E1332: Име Public променљиве не може почети доњом цртом: %s" +msgid "E1332: public variable name cannot start with underscore: %s" +msgstr "E1332: Име public променљиве не може почети доњом цртом: %s" #, c-format msgid "E1333: Cannot access protected variable \"%s\" in class \"%s\"" @@ -8662,10 +8669,10 @@ msgstr "" "E1386: Методи објекта „%s†може да Ñе приÑтупи Ñамо кориÑтећи објекат клаÑе " "„%sâ€" -msgid "E1387: Public variable not supported in an interface" -msgstr "E1387: У интерфејÑу Ñе не подржава јавна променљива" +msgid "E1387: public variable not supported in an interface" +msgstr "E1387: У интерфејÑу Ñе не подржава public променљива" -msgid "E1388: Public keyword not supported for a method" +msgid "E1388: public keyword not supported for a method" msgstr "E1388: Метода не подржава кључну реч public" msgid "E1389: Missing name after implements" @@ -8763,6 +8770,65 @@ msgstr "E1412: Ðије подржана уграђена метода објеРmsgid "E1413: Builtin class method not supported" msgstr "E1413: Ðије подржана уграђена метода клаÑе" +msgid "E1414: Enum can only be defined in Vim9 script" +msgstr "E1414: Ðабрајање може да Ñе дефинише Ñамо у Vim9 Ñкрипти" + +#, c-format +msgid "E1415: Enum name must start with an uppercase letter: %s" +msgstr "E1415: Име набрајања мора да почне великим Ñловом: %s" + +msgid "E1416: Enum cannot extend a class or enum" +msgstr "E1416: Ðабрајање не може да прошири клаÑу или набрајање" + +msgid "E1417: Abstract cannot be used in an Enum" +msgstr "E1417: Abstract не може да Ñе кориÑти у набрајању" + +#, c-format +msgid "E1418: Invalid enum value declaration: %s" +msgstr "E1418: ÐеиÑправна декларација вредноÑти набрајања: %s" + +#, c-format +msgid "E1419: Not a valid command in an Enum: %s" +msgstr "E1419: Команда не важи у набрајању: %s" + +msgid "E1420: Missing :endenum" +msgstr "E1420: ÐедоÑтаје :endenum" + +#, c-format +msgid "E1421: Enum \"%s\" cannot be used as a value" +msgstr "E1421: Ðабрајање „%s†не може да Ñе кориÑти као вредноÑÑ‚" + +#, c-format +msgid "E1422: Enum value \"%s\" not found in enum \"%s\"" +msgstr "E1422: ВредноÑÑ‚ набрајања „%s†није пронађена у набрајању „%sâ€" + +#, c-format +msgid "E1423: Enum value \"%s.%s\" cannot be modified" +msgstr "E1423: ВредноÑÑ‚ набрајања „%s.%s†не може да Ñе измени" + +#, c-format +msgid "E1424: Using an Enum \"%s\" as a Number" +msgstr "E1424: Ðабрајање „%s†Ñе кориÑти као Број" + +#, c-format +msgid "E1425: Using an Enum \"%s\" as a String" +msgstr "E1425: Ðабрајање „%s†Ñе кориÑти као Стринг" + +#, c-format +msgid "E1426: Enum \"%s\" ordinal value cannot be modified" +msgstr "E1426: Редна вредноÑÑ‚ набрајања „%s†не може да Ñе измени" + +#, c-format +msgid "E1427: Enum \"%s\" name cannot be modified" +msgstr "E1427: Ðабрајање „%s†не може да Ñе измени" + +#, c-format +msgid "E1428: Duplicate enum value: %s" +msgstr "E1428: Дуплирана вредноÑÑ‚ набрајања: %s" + +msgid "E1429: Class can only be used in a script" +msgstr "E1429: Class може да Ñе употреби Ñамо у Ñкрипти" + #, c-format msgid "E1500: Cannot mix positional and non-positional arguments: %s" msgstr "E1500: Ðе могу да Ñе мешају позициони и непозициони аргументи: %s" @@ -8817,8 +8883,8 @@ msgstr "E1511: Погрешан број карактера за поље „%sâ msgid "E1512: Wrong character width for field \"%s\"" msgstr "E1512: Погрешна ширина карактера за поље „%sâ€" -msgid "E1513: Cannot edit buffer. 'winfixbuf' is enabled" -msgstr "E1513: Ðе може да Ñе уређује бафер. Укључена је опција 'winfixbuf'" +msgid "E1513: Cannot switch buffer. 'winfixbuf' is enabled" +msgstr "E1513: Ðе може да пређе на други бафер. Укључена је опција 'winfixbuf'" msgid "--No lines in buffer--" msgstr "--У баферу нема линија--" diff --git a/src/popupwin.c b/src/popupwin.c index bdf4ac7..25bb153 100644 --- a/src/popupwin.c +++ b/src/popupwin.c @@ -654,7 +654,7 @@ popup_show_curline(win_T *wp) wp->w_topline = wp->w_buffer->b_ml.ml_line_count; while (wp->w_topline < wp->w_cursor.lnum && wp->w_topline < wp->w_buffer->b_ml.ml_line_count - && plines_m_win(wp, wp->w_topline, wp->w_cursor.lnum, TRUE) + && plines_m_win(wp, wp->w_topline, wp->w_cursor.lnum, FALSE) > wp->w_height) ++wp->w_topline; } diff --git a/src/proto/charset.pro b/src/proto/charset.pro index c915c58..a747319 100644 --- a/src/proto/charset.pro +++ b/src/proto/charset.pro @@ -20,6 +20,7 @@ int linetabsize_str(char_u *s); int linetabsize_col(int startcol, char_u *s); int win_linetabsize(win_T *wp, linenr_T lnum, char_u *line, colnr_T len); int linetabsize(win_T *wp, linenr_T lnum); +int linetabsize_no_outer(win_T *wp, linenr_T lnum); void win_linetabsize_cts(chartabsize_T *cts, colnr_T len); int vim_isIDc(int c); int vim_isNormalIDc(int c); diff --git a/src/proto/eval.pro b/src/proto/eval.pro index 47fd83d..1c2d05d 100644 --- a/src/proto/eval.pro +++ b/src/proto/eval.pro @@ -14,9 +14,9 @@ void init_evalarg(evalarg_T *evalarg); void clear_evalarg(evalarg_T *evalarg, exarg_T *eap); int skip_expr(char_u **pp, evalarg_T *evalarg); int skip_expr_concatenate(char_u **arg, char_u **start, char_u **end, evalarg_T *evalarg); -char_u *typval2string(typval_T *tv, int convert); -char_u *eval_to_string_eap(char_u *arg, int convert, exarg_T *eap, int use_simple_function); -char_u *eval_to_string(char_u *arg, int convert, int use_simple_function); +char_u *typval2string(typval_T *tv, int join_list); +char_u *eval_to_string_eap(char_u *arg, int join_list, exarg_T *eap, int use_simple_function); +char_u *eval_to_string(char_u *arg, int join_list, int use_simple_function); char_u *eval_to_string_safe(char_u *arg, int use_sandbox, int keep_script_version, int use_simple_function); varnumber_T eval_to_number(char_u *expr, int use_simple_function); typval_T *eval_expr(char_u *arg, exarg_T *eap); diff --git a/src/proto/evalvars.pro b/src/proto/evalvars.pro index ea14fe5..a0e0100 100644 --- a/src/proto/evalvars.pro +++ b/src/proto/evalvars.pro @@ -63,6 +63,7 @@ int eval_variable(char_u *name, int len, scid_T sid, typval_T *rettv, dictitem_T int eval_variable_import(char_u *name, typval_T *rettv); void check_vars(char_u *name, int len); dictitem_T *find_var(char_u *name, hashtab_T **htp, int no_autoload); +dictitem_T *find_var_autoload_prefix(char_u *name, int sid, hashtab_T **htp, char_u **namep); dictitem_T *find_var_also_in_script(char_u *name, hashtab_T **htp, int no_autoload); dictitem_T *find_var_in_ht(hashtab_T *ht, int htname, char_u *varname, int no_autoload); hashtab_T *get_script_local_ht(void); diff --git a/src/proto/mbyte.pro b/src/proto/mbyte.pro index 7883b3b..c57c94c 100644 --- a/src/proto/mbyte.pro +++ b/src/proto/mbyte.pro @@ -85,6 +85,7 @@ int convert_input(char_u *ptr, int len, int maxlen); int convert_input_safe(char_u *ptr, int len, int maxlen, char_u **restp, int *restlenp); char_u *string_convert(vimconv_T *vcp, char_u *ptr, int *lenp); char_u *string_convert_ext(vimconv_T *vcp, char_u *ptr, int *lenp, int *unconvlenp); +int get_cellwidth(int c); void f_setcellwidths(typval_T *argvars, typval_T *rettv); void f_getcellwidths(typval_T *argvars, typval_T *rettv); void f_charclass(typval_T *argvars, typval_T *rettv); diff --git a/src/proto/misc2.pro b/src/proto/misc2.pro index f596ffa..7a5b367 100644 --- a/src/proto/misc2.pro +++ b/src/proto/misc2.pro @@ -61,4 +61,8 @@ int mch_parse_cmd(char_u *cmd, int use_shcf, char ***argv, int *argc); int build_argv_from_string(char_u *cmd, char ***argv, int *argc); int build_argv_from_list(list_T *l, char ***argv, int *argc); int get_special_pty_type(void); +int cmp_keyvalue_value(const void *a, const void *b); +int cmp_keyvalue_value_n(const void *a, const void *b); +int cmp_keyvalue_value_i(const void *a, const void *b); +int cmp_keyvalue_value_ni(const void *a, const void *b); /* vim: set ft=c : */ diff --git a/src/proto/move.pro b/src/proto/move.pro index bc9c025..1302c29 100644 --- a/src/proto/move.pro +++ b/src/proto/move.pro @@ -9,6 +9,7 @@ void check_cursor_moved(win_T *wp); void changed_window_setting(void); void changed_window_setting_win(win_T *wp); void changed_window_setting_buf(buf_T *buf); +void changed_window_setting_all(void); void set_topline(win_T *wp, linenr_T lnum); void changed_cline_bef_curs(void); void changed_cline_bef_curs_win(win_T *wp); @@ -37,6 +38,7 @@ void f_screenpos(typval_T *argvars, typval_T *rettv); void f_virtcol2col(typval_T *argvars, typval_T *rettv); void scrolldown(long line_count, int byfold); void scrollup(long line_count, int byfold); +void scroll_redraw(int up, long count); void adjust_skipcol(void); void check_topfill(win_T *wp, int down); void scrolldown_clamp(void); @@ -46,7 +48,6 @@ void set_empty_rows(win_T *wp, int used); void scroll_cursor_bot(int min_scroll, int set_topbot); void scroll_cursor_halfway(int atend, int prefer_above); void cursor_correct(void); -int onepage(int dir, long count); -void halfpage(int flag, linenr_T Prenum); +int pagescroll(int dir, long count, int half); void do_check_cursorbind(void); /* vim: set ft=c : */ diff --git a/src/proto/normal.pro b/src/proto/normal.pro index eff08df..6dcbe41 100644 --- a/src/proto/normal.pro +++ b/src/proto/normal.pro @@ -22,8 +22,9 @@ void pop_showcmd(void); void do_check_scrollbind(int check); void check_scrollbind(linenr_T topline_diff, long leftcol_diff); int find_decl(char_u *ptr, int len, int locally, int thisblock, int flags_arg); +void nv_g_home_m_cmd(cmdarg_T *cap); +int nv_screengo(oparg_T *oap, int dir, long dist); void nv_scroll_line(cmdarg_T *cap); -void scroll_redraw(int up, long count); void handle_tabmenu(void); void do_nv_ident(int c1, int c2); int get_visual_text(cmdarg_T *cap, char_u **pp, int *lenp); diff --git a/src/proto/scriptfile.pro b/src/proto/scriptfile.pro index dbcc849..c8ff04a 100644 --- a/src/proto/scriptfile.pro +++ b/src/proto/scriptfile.pro @@ -9,6 +9,7 @@ void ex_runtime(exarg_T *eap); void set_context_in_runtime_cmd(expand_T *xp, char_u *arg); int find_script_by_name(char_u *name); int get_new_scriptitem_for_fname(int *error, char_u *fname); +void check_script_symlink(int sid); int do_in_path(char_u *path, char *prefix, 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); int source_runtime(char_u *name, int flags); diff --git a/src/proto/vim9class.pro b/src/proto/vim9class.pro index 1ed175e..d3d3b99 100644 --- a/src/proto/vim9class.pro +++ b/src/proto/vim9class.pro @@ -3,6 +3,7 @@ int object_index_from_itf_index(class_T *itf, int is_method, int idx, class_T *c int is_valid_builtin_obj_methodname(char_u *funcname); ufunc_T *class_get_builtin_method(class_T *cl, class_builtin_T builtin_method, int *method_idx); void ex_class(exarg_T *eap); +void enum_set_internal_obj_vars(class_T *en, object_T *enval); type_T *oc_member_type(class_T *cl, int is_object, char_u *name, char_u *name_end, int *member_idx); type_T *oc_member_type_by_idx(class_T *cl, int is_object, int member_idx); void ex_enum(exarg_T *eap); diff --git a/src/proto/vim9instr.pro b/src/proto/vim9instr.pro index 0fb449d..1b2f79c 100644 --- a/src/proto/vim9instr.pro +++ b/src/proto/vim9instr.pro @@ -7,7 +7,7 @@ int generate_CONSTRUCT(cctx_T *cctx, class_T *cl); int generate_GET_OBJ_MEMBER(cctx_T *cctx, int idx, type_T *type); int generate_GET_ITF_MEMBER(cctx_T *cctx, class_T *itf, int idx, type_T *type); int generate_STORE_THIS(cctx_T *cctx, int idx); -int may_generate_2STRING(int offset, int tolerant, cctx_T *cctx); +int may_generate_2STRING(int offset, int tostring_flags, cctx_T *cctx); int generate_add_instr(cctx_T *cctx, vartype_T vartype, type_T *type1, type_T *type2, exprtype_T expr_type); vartype_T operator_type(type_T *type1, type_T *type2); int generate_two_op(cctx_T *cctx, char_u *op); diff --git a/src/proto/window.pro b/src/proto/window.pro index 9e66db5..26c7040 100644 --- a/src/proto/window.pro +++ b/src/proto/window.pro @@ -57,6 +57,7 @@ tabpage_T *win_find_tabpage(win_T *win); win_T *win_vert_neighbor(tabpage_T *tp, win_T *wp, int up, long count); win_T *win_horz_neighbor(tabpage_T *tp, win_T *wp, int left, long count); void win_enter(win_T *wp, int undo_sync); +void win_fix_current_dir(void); win_T *buf_jump_open_win(buf_T *buf); win_T *buf_jump_open_tab(buf_T *buf); int win_unlisted(win_T *wp); diff --git a/src/quickfix.c b/src/quickfix.c index 0bf4cfe..2e5b693 100644 --- a/src/quickfix.c +++ b/src/quickfix.c @@ -4964,12 +4964,12 @@ qf_fill_buffer(qf_list_T *qfl, buf_T *buf, qfline_T *old_last, int qf_winid) 0L, (char_u *)"qf", OPT_LOCAL); curbuf->b_p_ma = FALSE; - keep_filetype = TRUE; // don't detect 'filetype' + curbuf->b_keep_filetype = TRUE; // don't detect 'filetype' apply_autocmds(EVENT_BUFREADPOST, (char_u *)"quickfix", NULL, FALSE, curbuf); apply_autocmds(EVENT_BUFWINENTER, (char_u *)"quickfix", NULL, FALSE, curbuf); - keep_filetype = FALSE; + curbuf->b_keep_filetype = FALSE; --curbuf_lock; // make sure it will be redrawn diff --git a/src/regexp_bt.c b/src/regexp_bt.c index 198946e..5d9450d 100644 --- a/src/regexp_bt.c +++ b/src/regexp_bt.c @@ -1641,7 +1641,7 @@ regatom(int *flagp) n = n * 10 + (c - '0'); c = getchr(); } - if (c == '\'' && n == 0) + if (no_Magic(c) == '\'' && n == 0) { // "\%'m", "\%<'m" and "\%>'m": Mark c = getchr(); diff --git a/src/regexp_nfa.c b/src/regexp_nfa.c index ff54348..5e4fadd 100644 --- a/src/regexp_nfa.c +++ b/src/regexp_nfa.c @@ -1733,7 +1733,7 @@ nfa_regatom(void) EMIT((int)n); break; } - else if (c == '\'' && n == 0) + else if (no_Magic(c) == '\'' && n == 0) { // \%'m \%<'m \%>'m EMIT(cmp == '<' ? NFA_MARK_LT : @@ -5150,7 +5150,7 @@ check_char_class(int class, int c) default: // should not be here :P - siemsg(e_nfa_regexp_invalid_character_class_nr, class); + siemsg(_(e_nfa_regexp_invalid_character_class_nr), class); return FAIL; } return FAIL; diff --git a/src/screen.c b/src/screen.c index 71ddbca..35d3002 100644 --- a/src/screen.c +++ b/src/screen.c @@ -1981,7 +1981,21 @@ screen_char(unsigned off, int row, int col) { char_u buf[MB_MAXBYTES + 1]; - if (utf_ambiguous_width(ScreenLinesUC[off])) + if ( +#ifdef FEAT_GUI + !gui.in_use && +#endif + get_cellwidth(ScreenLinesUC[off]) > 1 + ) + { + // If the width is set to 2 with setcellwidths() + // clear the two screen cells. If the character is actually + // single width it won't change the second cell. + out_str((char_u *)" "); + term_windgoto(row, col); + screen_cur_col = 9999; + } + else if (utf_ambiguous_width(ScreenLinesUC[off])) { if (*p_ambw == 'd' #ifdef FEAT_GUI diff --git a/src/scriptfile.c b/src/scriptfile.c index 6dc5557..d5ec7cf 100644 --- a/src/scriptfile.c +++ b/src/scriptfile.c @@ -215,6 +215,9 @@ estack_sfile(estack_arg_T which UNUSED) if (*class_name != NUL) { // For class methods prepend "<class name>." to the function name. + ga_concat(&ga, (char_u *)"<SNR>"); + ga.ga_len += vim_snprintf((char *)ga.ga_data + ga.ga_len, 23, + "%d_", entry->es_info.ufunc->uf_script_ctx.sc_sid); ga_concat(&ga, class_name); ga_append(&ga, '.'); } @@ -402,6 +405,43 @@ get_new_scriptitem_for_fname(int *error, char_u *fname) return sid; } +/* + * If the script for "sid" is a symlink and "sn_source_sid" is not set + * then initialize it. A new script_item is created if needed. + */ + void +check_script_symlink(int sid) +{ + scriptitem_T *si = SCRIPT_ITEM(sid); + if (si->sn_syml_checked || si->sn_sourced_sid > 0) + return; + si->sn_syml_checked = TRUE; + + // If fname is a symbolic link, create an script_item for the real file. + + char_u *real_fname = fix_fname(si->sn_name); + if (real_fname != NULL && STRCMP(real_fname, si->sn_name) != 0) + { + int real_sid = find_script_by_name(real_fname); + int error2 = OK; + int new_sid = FALSE; + if (real_sid < 0) + { + real_sid = get_new_scriptitem_for_fname(&error2, real_fname); + new_sid = TRUE; + } + if (error2 == OK) + { + si = SCRIPT_ITEM(sid); + si->sn_sourced_sid = real_sid; + if (new_sid) + SCRIPT_ITEM(real_sid)->sn_import_autoload + = si->sn_import_autoload; + } + } + vim_free(real_fname); +} + static void find_script_callback(char_u *fname, void *cookie) { @@ -1233,7 +1273,7 @@ cmd_source(char_u *fname, exarg_T *eap) emsg(_(e_argument_required)); else // source ex commands from the current buffer - do_source_ext(NULL, FALSE, FALSE, NULL, eap, clearvars); + do_source_ext(NULL, FALSE, DOSO_NONE, NULL, eap, clearvars); } else if (eap != NULL && eap->forceit) // ":source!": read Normal mode commands @@ -1384,14 +1424,17 @@ do_source_buffer_init(source_cookie_T *sp, exarg_T *eap) char_u *line = NULL; char_u *fname; - CLEAR_FIELD(*sp); - if (curbuf == NULL) return NULL; // Use ":source buffer=<num>" as the script name - vim_snprintf((char *)IObuff, IOSIZE, ":source buffer=%d", curbuf->b_fnum); - fname = vim_strsave(IObuff); + if (curbuf->b_ffname != NULL) + fname = vim_strsave(curbuf->b_ffname); + else + { + vim_snprintf((char *)IObuff, IOSIZE, ":source buffer=%d", curbuf->b_fnum); + fname = vim_strsave(IObuff); + } if (fname == NULL) return NULL; @@ -1408,6 +1451,8 @@ do_source_buffer_init(source_cookie_T *sp, exarg_T *eap) } sp->buf_lnum = 0; sp->source_from_buf = TRUE; + // When sourcing a range of lines from a buffer, use buffer line number. + sp->sourcing_lnum = eap->line1 - 1; return fname; @@ -1596,13 +1641,6 @@ do_source_ext( cookie.fileformat = EOL_UNKNOWN; #endif - if (fname == NULL) - // When sourcing a range of lines from a buffer, use the buffer line - // number. - cookie.sourcing_lnum = eap->line1 - 1; - else - cookie.sourcing_lnum = 0; - #ifdef FEAT_EVAL // Check if this script has a breakpoint. cookie.breakpoint = dbg_find_breakpoint(TRUE, fname_exp, (linenr_T)0); diff --git a/src/session.c b/src/session.c index e39ce4d..eea57a2 100644 --- a/src/session.c +++ b/src/session.c @@ -1392,6 +1392,8 @@ theend: #ifdef FEAT_SESSION vim_free(viewFile); #endif + + apply_autocmds(EVENT_SESSIONWRITEPOST, NULL, NULL, FALSE, curbuf); } #if (defined(FEAT_VIMINFO) || defined(FEAT_SESSION)) || defined(PROTO) diff --git a/src/structs.h b/src/structs.h index 47a0050..36339c4 100644 --- a/src/structs.h +++ b/src/structs.h @@ -1562,9 +1562,10 @@ struct itf2class_S { // array with ints follows }; -#define CLASS_INTERFACE 1 -#define CLASS_EXTENDED 2 // another class extends this one -#define CLASS_ABSTRACT 4 // abstract class +#define CLASS_INTERFACE 0x1 +#define CLASS_EXTENDED 0x2 // another class extends this one +#define CLASS_ABSTRACT 0x4 // abstract class +#define CLASS_ENUM 0x8 // enum // "class_T": used for v_class of typval of VAR_CLASS // Also used for an interface (class_flags has CLASS_INTERFACE). @@ -1613,6 +1614,9 @@ struct class_S type_T class_object_type; // same as class_type but VAR_OBJECT }; +#define IS_INTERFACE(cl) ((cl)->class_flags & CLASS_INTERFACE) +#define IS_ENUM(cl) ((cl)->class_flags & CLASS_ENUM) + // Used for v_object of typval of VAR_OBJECT. // The member variables follow in an array of typval_T. struct object_S @@ -2127,6 +2131,7 @@ typedef struct int sn_state; // SN_STATE_ values char_u *sn_save_cpo; // 'cpo' value when :vim9script found char sn_is_vimrc; // .vimrc file, do not restore 'cpo' + char sn_syml_checked;// flag: this has been checked for sym link // for a Vim9 script under "rtp/autoload/" this is "dir#scriptname#" char_u *sn_autoload_prefix; @@ -3129,6 +3134,19 @@ struct file_buffer int b_marks_read; // Have we read viminfo marks yet? #endif + int b_modified_was_set; // did ":set modified" + int b_did_filetype; // FileType event found + int b_keep_filetype; // value for did_filetype when starting + // to execute autocommands + + // Set by the apply_autocmds_group function if the given event is equal to + // EVENT_FILETYPE. Used by the readfile function in order to determine if + // EVENT_BUFREADPOST triggered the EVENT_FILETYPE. + // + // Relying on this value requires one to reset it prior calling + // apply_autocmds_group(). + int b_au_did_filetype; + /* * The following only used in undo.c. */ @@ -4380,6 +4398,7 @@ typedef struct int new_curwin_id; // ID of new curwin int save_prevwin_id; // ID of saved prevwin bufref_T new_curbuf; // new curbuf + char_u *tp_localdir; // saved value of tp_localdir char_u *globaldir; // saved value of globaldir int save_VIsual_active; // saved VIsual_active int save_State; // saved State @@ -5043,3 +5062,18 @@ typedef struct { linenr_T spv_capcol_lnum; // line number for "cap_col" #endif } spellvars_T; + +// Return the length of a string literal +#define STRLEN_LITERAL(s) (sizeof(s) - 1) + +// Store a key/value pair +typedef struct +{ + int key; // the key + char *value; // the value string + size_t length; // length of the value string +} keyvalue_T; + +#define KEYVALUE_ENTRY(k, v) \ + {(k), (v), STRLEN_LITERAL(v)} + @@ -289,17 +289,6 @@ do_tag( static char_u **matches = NULL; static int flags; - if (postponed_split == 0 && !check_can_set_curbuf_forceit(forceit)) - return FALSE; - -#ifdef FEAT_EVAL - if (tfu_in_use) - { - emsg(_(e_cannot_modify_tag_stack_within_tagfunc)); - return FALSE; - } -#endif - #ifdef EXITFREE if (type == DT_FREE) { @@ -313,6 +302,17 @@ do_tag( } #endif +#ifdef FEAT_EVAL + if (tfu_in_use) + { + emsg(_(e_cannot_modify_tag_stack_within_tagfunc)); + return FALSE; + } +#endif + + if (postponed_split == 0 && !check_can_set_curbuf_forceit(forceit)) + return FALSE; + if (type == DT_HELP) { type = DT_TAG; @@ -1798,6 +1798,8 @@ get_term_entries(int *height, int *width) T_DA = (char_u *)"y"; if ((T_UT == NULL || T_UT == empty_option) && tgetflag("ut") > 0) T_UT = (char_u *)"y"; + if ((T_XON == NULL || T_XON == empty_option) && tgetflag("xo") > 0) + T_XON = (char_u *)"y"; /* * get key codes diff --git a/src/termdefs.h b/src/termdefs.h index f28fd19..2b65abb 100644 --- a/src/termdefs.h +++ b/src/termdefs.h @@ -115,10 +115,11 @@ enum SpecialKey KS_SRI, // restore icon text KS_FD, // disable focus event tracking KS_FE, // enable focus event tracking - KS_CF // set terminal alternate font + KS_CF, // set terminal alternate font + KS_XON // terminal uses xon/xoff handshaking }; -#define KS_LAST KS_CF +#define KS_LAST KS_XON /* * the terminal capabilities are stored in this array @@ -224,6 +225,7 @@ extern char_u *(term_strings[]); // current terminal strings #define T_SRI (TERM_STR(KS_SRI)) // restore icon text #define T_FD (TERM_STR(KS_FD)) // disable focus event tracking #define T_FE (TERM_STR(KS_FE)) // enable focus event tracking +#define T_XON (TERM_STR(KS_XON)) // terminal uses xon/xoff handshaking typedef enum { TMODE_COOK, // terminal mode for external cmds and Ex mode diff --git a/src/testdir/Make_all.mak b/src/testdir/Make_all.mak index c4403e6..b41f5f4 100644 --- a/src/testdir/Make_all.mak +++ b/src/testdir/Make_all.mak @@ -40,6 +40,7 @@ TEST_VIM9 = \ test_vim9_class \ test_vim9_cmd \ test_vim9_disassemble \ + test_vim9_enum \ test_vim9_expr \ test_vim9_fails \ test_vim9_func \ @@ -53,6 +54,7 @@ TEST_VIM9_RES = \ test_vim9_class.res \ test_vim9_cmd.res \ test_vim9_disassemble.res \ + test_vim9_enum.res \ test_vim9_expr.res \ test_vim9_fails.res \ test_vim9_func.res \ @@ -329,6 +331,7 @@ NEW_TESTS = \ test_wnext \ test_wordcount \ test_writefile \ + test_xdg \ test_xxd \ test_alot_latin \ test_alot_utf8 \ @@ -459,6 +462,7 @@ NEW_TESTS_RES = \ test_matchadd_conceal.res \ test_matchadd_conceal_utf8.res \ test_matchfuzzy.res \ + test_matchparen.res \ test_memory_usage.res \ test_menu.res \ test_messages.res \ @@ -561,6 +565,7 @@ NEW_TESTS_RES = \ test_winfixbuf.res \ test_wordcount.res \ test_writefile.res \ + test_xdg.res \ test_xxd.res \ test_alot_latin.res \ test_alot_utf8.res \ diff --git a/src/testdir/Makefile b/src/testdir/Makefile index fd2e56c..4e476f9 100644 --- a/src/testdir/Makefile +++ b/src/testdir/Makefile @@ -89,7 +89,7 @@ RUN_VIM = VIMRUNTIME=$(SCRIPTSOURCE) $(VALGRIND) $(VIMPROG) -f $(GUI_FLAG) -u un # Delete files that may interfere with running tests. This includes some files # that may result from working on the tests, not only from running them. clean: - -rm -rf *.out *.failed *.res *.rej *.orig XfakeHOME Xdir1 Xfind + -rm -rf *.out *.failed *.res *.rej *.orig XfakeHOME Xdir1 Xfind failed -rm -f opt_test.vim test_result.log $(CLEANUP_FILES) -rm -rf $(RM_ON_RUN) $(RM_ON_START) -rm -f valgrind.* diff --git a/src/testdir/dumps/Test_ambiwidth_hl_dump_1.dump b/src/testdir/dumps/Test_ambiwidth_hl_dump_1.dump new file mode 100644 index 0000000..383a6f4 --- /dev/null +++ b/src/testdir/dumps/Test_ambiwidth_hl_dump_1.dump @@ -0,0 +1,6 @@ +>℃+8&#ffffff0@49 +@10|$+8#4040ff13&| +8#0000000&@38 +|℃+0&&@49 +@10|$+0#4040ff13&| +0#0000000&@38 +|~+0#4040ff13&| @48 +| +0#0000000&@31|1|,|1| @10|A|l@1| diff --git a/src/testdir/dumps/Test_ambiwidth_hl_dump_2.dump b/src/testdir/dumps/Test_ambiwidth_hl_dump_2.dump new file mode 100644 index 0000000..81aeb7b --- /dev/null +++ b/src/testdir/dumps/Test_ambiwidth_hl_dump_2.dump @@ -0,0 +1,6 @@ +>℃+8&#ffffff0| |℃| |℃| |℃| |℃| |℃| |℃| |℃| |℃| |℃| |℃| |℃| |℃| |℃| |℃| |℃| |℃| |℃| |℃| |℃| |℃| |℃| |℃| |℃| |℃| +|℃| |℃| |℃| |℃| |℃| |℃| |℃| |℃| |℃| |℃| |℃| |℃| |℃| |℃| |℃| |℃| |℃| |℃| |℃| |℃| |℃| |℃| |℃| |℃| |℃| +|℃| |℃| |℃| |℃| |℃| |℃| |℃| |℃| |℃| |℃| |$+8#4040ff13&| +8#0000000&@28 +|℃+0&&| |℃| |℃| |℃| |℃| |℃| |℃| |℃| |℃| |℃| |℃| |℃| |℃| |℃| |℃| |℃| |℃| |℃| |℃| |℃| |℃| |℃| |℃| |℃| |℃| +|℃| |℃| |℃| |℃| |℃| |℃| |℃| |℃| |℃| |℃| |℃| |℃| |℃| |℃| |℃| |℃| |℃| |℃| |℃| |℃| |℃| |℃| |℃| @1|@+0#4040ff13&@2 +| +0#0000000&@31|1|,|1| @10|T|o|p| diff --git a/src/testdir/dumps/Test_display_visual_block_scroll.dump b/src/testdir/dumps/Test_display_visual_block_scroll.dump index afb52fb..36eae0c 100644 --- a/src/testdir/dumps/Test_display_visual_block_scroll.dump +++ b/src/testdir/dumps/Test_display_visual_block_scroll.dump @@ -1,7 +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 +|{+0#0000001#a8a8a8255| | +0#0000000#ffffff0@72 +|}+0#0000001#a8a8a8255| | +0#0000000#ffffff0@72 +|{+0#0000001#a8a8a8255| | +0#0000000#ffffff0@72 +|f+0#0000001#a8a8a8255| | +0#0000000#ffffff0@72 +>g| +0#0000001#a8a8a8255| +0#0000000#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/dumps/Test_prop_normal_gj_gk_gM_with_outer_virtual_text_1.dump b/src/testdir/dumps/Test_prop_normal_gj_gk_gM_with_outer_virtual_text_1.dump new file mode 100644 index 0000000..7a0b848 --- /dev/null +++ b/src/testdir/dumps/Test_prop_normal_gj_gk_gM_with_outer_virtual_text_1.dump @@ -0,0 +1,16 @@ +| +0#af5f00255#ffffff0@3|A+0#0000001#ffff4012|b|o|v|e| +0#0000000#ffffff0@30 +| +0#af5f00255&@1|1| |F+0#0000000&|i|r>s|t| |l|i|n|e| |f|i|t|s| |o|n| |s|c|r|e@1|n| |l|i|n|e|.|A+0#0000001#ffff4012|f|t|e|r +| +0#af5f00255#ffffff0@3| +0#0000001#ffff4012|t|e|x|t| |w|r|a|p|s| |t|o| |n|e|x|t| |l|i|n|e|.| +0#0000000#ffffff0@10 +| +0#af5f00255&@3| +0#0000000&@5|R+0#0000001#ffff4012|i|g|h|t| |t|e|x|t| |w|r|a|p|s| |t|o| |n|e|x|t| |l|i|n|e|. +| +0#af5f00255#ffffff0@3|B+0#0000001#ffff4012|e|l|o|w| +0#0000000#ffffff0@30 +| +0#af5f00255&@3|A+0#0000001#ffff4012|b|o|v|e| +0#0000000#ffffff0@30 +| +0#af5f00255&@1|2| |A+0#0000001#ffff4012|f|t|e|r| |t|e|x|t| |w|r|a|p|s| |t|o| |n|e|x|t| |l|i|n|e|.| +0#0000000#ffffff0@5 +| +0#af5f00255&@3| +0#0000000&@5|R+0#0000001#ffff4012|i|g|h|t| |t|e|x|t| |w|r|a|p|s| |t|o| |n|e|x|t| |l|i|n|e|. +| +0#af5f00255#ffffff0@3| +0#0000000&@35 +| +0#af5f00255&@3|B+0#0000001#ffff4012|e|l|o|w| +0#0000000#ffffff0@30 +| +0#af5f00255&@3|A+0#0000001#ffff4012|b|o|v|e| +0#0000000#ffffff0@30 +| +0#af5f00255&@1|3| |T+0#0000000&|h|i|r|d| |l|i|n|e| |f|i|t|s| |o|n| |s|c|r|e@1|n| |l|i|n|e|.|A+0#0000001#ffff4012|f|t|e|r +| +0#af5f00255#ffffff0@3| +0#0000001#ffff4012|t|e|x|t| |w|r|a|p|s| |t|o| |n|e|x|t| |l|i|n|e|.| +0#0000000#ffffff0@10 +| +0#af5f00255&@3| +0#0000000&@5|R+0#0000001#ffff4012|i|g|h|t| |t|e|x|t| |w|r|a|p|s| |t|o| |n|e|x|t| |l|i|n|e|. +| +0#af5f00255#ffffff0@3|B+0#0000001#ffff4012|e|l|o|w| +0#0000000#ffffff0@30 +@22|1|,|4|-|4|0| @7|A|l@1| diff --git a/src/testdir/dumps/Test_prop_normal_gj_gk_gM_with_outer_virtual_text_2.dump b/src/testdir/dumps/Test_prop_normal_gj_gk_gM_with_outer_virtual_text_2.dump new file mode 100644 index 0000000..d463990 --- /dev/null +++ b/src/testdir/dumps/Test_prop_normal_gj_gk_gM_with_outer_virtual_text_2.dump @@ -0,0 +1,16 @@ +| +0#af5f00255#ffffff0@3|A+0#0000001#ffff4012|b|o|v|e| +0#0000000#ffffff0@30 +| +0#af5f00255&@1|1| |F+0#0000000&|i|r|s|t| |l|i|n|e| |f|i|t|s| |o|n| |s|c|r|e@1|n| |l|i|n|e|.|A+0#0000001#ffff4012|f|t|e|r +| +0#af5f00255#ffffff0@3| +0#0000001#ffff4012|t|e|x|t| |w|r|a|p|s| |t|o| |n|e|x|t| |l|i|n|e|.| +0#0000000#ffffff0@10 +| +0#af5f00255&@3| +0#0000000&@5|R+0#0000001#ffff4012|i|g|h|t| |t|e|x|t| |w|r|a|p|s| |t|o| |n|e|x|t| |l|i|n|e|. +| +0#af5f00255#ffffff0@3|B+0#0000001#ffff4012|e|l|o|w| +0#0000000#ffffff0@30 +| +0#af5f00255&@3|A+0#0000001#ffff4012|b|o|v|e| +0#0000000#ffffff0@30 +| +0#af5f00255&@1|2| >A+0#0000001#ffff4012|f|t|e|r| |t|e|x|t| |w|r|a|p|s| |t|o| |n|e|x|t| |l|i|n|e|.| +0#0000000#ffffff0@5 +| +0#af5f00255&@3| +0#0000000&@5|R+0#0000001#ffff4012|i|g|h|t| |t|e|x|t| |w|r|a|p|s| |t|o| |n|e|x|t| |l|i|n|e|. +| +0#af5f00255#ffffff0@3| +0#0000000&@35 +| +0#af5f00255&@3|B+0#0000001#ffff4012|e|l|o|w| +0#0000000#ffffff0@30 +| +0#af5f00255&@3|A+0#0000001#ffff4012|b|o|v|e| +0#0000000#ffffff0@30 +| +0#af5f00255&@1|3| |T+0#0000000&|h|i|r|d| |l|i|n|e| |f|i|t|s| |o|n| |s|c|r|e@1|n| |l|i|n|e|.|A+0#0000001#ffff4012|f|t|e|r +| +0#af5f00255#ffffff0@3| +0#0000001#ffff4012|t|e|x|t| |w|r|a|p|s| |t|o| |n|e|x|t| |l|i|n|e|.| +0#0000000#ffffff0@10 +| +0#af5f00255&@3| +0#0000000&@5|R+0#0000001#ffff4012|i|g|h|t| |t|e|x|t| |w|r|a|p|s| |t|o| |n|e|x|t| |l|i|n|e|. +| +0#af5f00255#ffffff0@3|B+0#0000001#ffff4012|e|l|o|w| +0#0000000#ffffff0@30 +@22|2|,|0|-|3|7| @7|A|l@1| diff --git a/src/testdir/dumps/Test_prop_normal_gj_gk_gM_with_outer_virtual_text_3.dump b/src/testdir/dumps/Test_prop_normal_gj_gk_gM_with_outer_virtual_text_3.dump new file mode 100644 index 0000000..85a469d --- /dev/null +++ b/src/testdir/dumps/Test_prop_normal_gj_gk_gM_with_outer_virtual_text_3.dump @@ -0,0 +1,16 @@ +| +0#af5f00255#ffffff0@3|A+0#0000001#ffff4012|b|o|v|e| +0#0000000#ffffff0@30 +| +0#af5f00255&@1|1| |F+0#0000000&|i|r|s|t| |l|i|n|e| |f|i|t|s| |o|n| |s|c|r|e@1|n| |l|i|n|e|.|A+0#0000001#ffff4012|f|t|e|r +| +0#af5f00255#ffffff0@3| +0#0000001#ffff4012|t|e|x|t| |w|r|a|p|s| |t|o| |n|e|x|t| |l|i|n|e|.| +0#0000000#ffffff0@10 +| +0#af5f00255&@3| +0#0000000&@5|R+0#0000001#ffff4012|i|g|h|t| |t|e|x|t| |w|r|a|p|s| |t|o| |n|e|x|t| |l|i|n|e|. +| +0#af5f00255#ffffff0@3|B+0#0000001#ffff4012|e|l|o|w| +0#0000000#ffffff0@30 +| +0#af5f00255&@3|A+0#0000001#ffff4012|b|o|v|e| +0#0000000#ffffff0@30 +| +0#af5f00255&@1|2| |A+0#0000001#ffff4012|f|t|e|r| |t|e|x|t| |w|r|a|p|s| |t|o| |n|e|x|t| |l|i|n|e|.| +0#0000000#ffffff0@5 +| +0#af5f00255&@3| +0#0000000&@5|R+0#0000001#ffff4012|i|g|h|t| |t|e|x|t| |w|r|a|p|s| |t|o| |n|e|x|t| |l|i|n|e|. +| +0#af5f00255#ffffff0@3| +0#0000000&@35 +| +0#af5f00255&@3|B+0#0000001#ffff4012|e|l|o|w| +0#0000000#ffffff0@30 +| +0#af5f00255&@3|A+0#0000001#ffff4012|b|o|v|e| +0#0000000#ffffff0@30 +| +0#af5f00255&@1|3| |T+0#0000000&|h|i>r|d| |l|i|n|e| |f|i|t|s| |o|n| |s|c|r|e@1|n| |l|i|n|e|.|A+0#0000001#ffff4012|f|t|e|r +| +0#af5f00255#ffffff0@3| +0#0000001#ffff4012|t|e|x|t| |w|r|a|p|s| |t|o| |n|e|x|t| |l|i|n|e|.| +0#0000000#ffffff0@10 +| +0#af5f00255&@3| +0#0000000&@5|R+0#0000001#ffff4012|i|g|h|t| |t|e|x|t| |w|r|a|p|s| |t|o| |n|e|x|t| |l|i|n|e|. +| +0#af5f00255#ffffff0@3|B+0#0000001#ffff4012|e|l|o|w| +0#0000000#ffffff0@30 +@22|3|,|4|-|4|0| @7|A|l@1| diff --git a/src/testdir/dumps/Test_prop_normal_gj_gk_gM_with_outer_virtual_text_4.dump b/src/testdir/dumps/Test_prop_normal_gj_gk_gM_with_outer_virtual_text_4.dump new file mode 100644 index 0000000..2c03fdf --- /dev/null +++ b/src/testdir/dumps/Test_prop_normal_gj_gk_gM_with_outer_virtual_text_4.dump @@ -0,0 +1,16 @@ +| +0#af5f00255#ffffff0@3|A+0#0000001#ffff4012|b|o|v|e| +0#0000000#ffffff0@30 +| +0#af5f00255&@1|1| |F+0#0000000&|i|r|s|t| |l|i|n|e| |f|i|t|s> |o|n| |s|c|r|e@1|n| |l|i|n|e|.|A+0#0000001#ffff4012|f|t|e|r +| +0#af5f00255#ffffff0@3| +0#0000001#ffff4012|t|e|x|t| |w|r|a|p|s| |t|o| |n|e|x|t| |l|i|n|e|.| +0#0000000#ffffff0@10 +| +0#af5f00255&@3| +0#0000000&@5|R+0#0000001#ffff4012|i|g|h|t| |t|e|x|t| |w|r|a|p|s| |t|o| |n|e|x|t| |l|i|n|e|. +| +0#af5f00255#ffffff0@3|B+0#0000001#ffff4012|e|l|o|w| +0#0000000#ffffff0@30 +| +0#af5f00255&@3|A+0#0000001#ffff4012|b|o|v|e| +0#0000000#ffffff0@30 +| +0#af5f00255&@1|2| |A+0#0000001#ffff4012|f|t|e|r| |t|e|x|t| |w|r|a|p|s| |t|o| |n|e|x|t| |l|i|n|e|.| +0#0000000#ffffff0@5 +| +0#af5f00255&@3| +0#0000000&@5|R+0#0000001#ffff4012|i|g|h|t| |t|e|x|t| |w|r|a|p|s| |t|o| |n|e|x|t| |l|i|n|e|. +| +0#af5f00255#ffffff0@3| +0#0000000&@35 +| +0#af5f00255&@3|B+0#0000001#ffff4012|e|l|o|w| +0#0000000#ffffff0@30 +| +0#af5f00255&@3|A+0#0000001#ffff4012|b|o|v|e| +0#0000000#ffffff0@30 +| +0#af5f00255&@1|3| |T+0#0000000&|h|i|r|d| |l|i|n|e| |f|i|t|s| |o|n| |s|c|r|e@1|n| |l|i|n|e|.|A+0#0000001#ffff4012|f|t|e|r +| +0#af5f00255#ffffff0@3| +0#0000001#ffff4012|t|e|x|t| |w|r|a|p|s| |t|o| |n|e|x|t| |l|i|n|e|.| +0#0000000#ffffff0@10 +| +0#af5f00255&@3| +0#0000000&@5|R+0#0000001#ffff4012|i|g|h|t| |t|e|x|t| |w|r|a|p|s| |t|o| |n|e|x|t| |l|i|n|e|. +| +0#af5f00255#ffffff0@3|B+0#0000001#ffff4012|e|l|o|w| +0#0000000#ffffff0@30 +@22|1|,|1|6|-|5|2| @6|A|l@1| diff --git a/src/testdir/dumps/Test_props_with_text_truncated_just_before_after_1.dump b/src/testdir/dumps/Test_props_with_text_truncated_just_before_after_1.dump new file mode 100644 index 0000000..f46f47e --- /dev/null +++ b/src/testdir/dumps/Test_props_with_text_truncated_just_before_after_1.dump @@ -0,0 +1,8 @@ +|h+0&#ffffff0|e|r|e| |i|s| |t|e|x|t| |l|o|n|g| |e|n|o|u|g|h| |t|o| |f|i|l@1| |t|h|e| |r|o|>+0#4040ff13& +|s+0#0000000&|e|c|o|n|d| |l|i|n>e| @28 +|~+0#4040ff13&| @38 +|~| @38 +|~| @38 +|~| @38 +|~| @38 +| +0#0000000&@21|2|,|1@1| @9|A|l@1| diff --git a/src/testdir/dumps/Test_props_with_text_truncated_just_before_after_2.dump b/src/testdir/dumps/Test_props_with_text_truncated_just_before_after_2.dump new file mode 100644 index 0000000..3434669 --- /dev/null +++ b/src/testdir/dumps/Test_props_with_text_truncated_just_before_after_2.dump @@ -0,0 +1,8 @@ +|h+0&#ffffff0|e|r|e| |i|s| |t|e|x|t| |l|o|n|g| |e|n|o|u|g|h| |t|o| |f|i|l@1| |t|h|e| |r|o|>+0#4040ff13& +|b+0#ffffff16#ff404010|e|l|o|w| |t|e|x|t| +0#0000000#ffffff0@29 +|s|e|c|o|n|d| |l|i|n>e| @28 +|~+0#4040ff13&| @38 +|~| @38 +|~| @38 +|~| @38 +| +0#0000000&@21|2|,|1@1| @9|A|l@1| diff --git a/src/testdir/dumps/Test_setcellwidths_with_non_ambiwidth_character_dump_1.dump b/src/testdir/dumps/Test_setcellwidths_with_non_ambiwidth_character_dump_1.dump new file mode 100644 index 0000000..73f4418 --- /dev/null +++ b/src/testdir/dumps/Test_setcellwidths_with_non_ambiwidth_character_dump_1.dump @@ -0,0 +1,6 @@ +>âžœ+0&#ffffff0@49 +@10| @39 +|âžœ@49 +@10| @39 +|~+0#4040ff13&| @48 +| +0#0000000&@31|1|,|1| @10|A|l@1| diff --git a/src/testdir/dumps/Test_setcellwidths_with_non_ambiwidth_character_dump_2.dump b/src/testdir/dumps/Test_setcellwidths_with_non_ambiwidth_character_dump_2.dump new file mode 100644 index 0000000..2b575f6 --- /dev/null +++ b/src/testdir/dumps/Test_setcellwidths_with_non_ambiwidth_character_dump_2.dump @@ -0,0 +1,6 @@ +>âžœ+0&#ffffff0| |âžœ| |âžœ| |âžœ| |âžœ| |âžœ| |âžœ| |âžœ| |âžœ| |âžœ| |âžœ| |âžœ| |âžœ| |âžœ| |âžœ| |âžœ| |âžœ| |âžœ| |âžœ| |âžœ| |âžœ| |âžœ| |âžœ| |âžœ| |âžœ| +|âžœ| |âžœ| |âžœ| |âžœ| |âžœ| |âžœ| |âžœ| |âžœ| |âžœ| |âžœ| |âžœ| |âžœ| |âžœ| |âžœ| |âžœ| |âžœ| |âžœ| |âžœ| |âžœ| |âžœ| |âžœ| |âžœ| |âžœ| |âžœ| |âžœ| +|âžœ| |âžœ| |âžœ| |âžœ| |âžœ| |âžœ| |âžœ| |âžœ| |âžœ| |âžœ| @30 +|âžœ| |âžœ| |âžœ| |âžœ| |âžœ| |âžœ| |âžœ| |âžœ| |âžœ| |âžœ| |âžœ| |âžœ| |âžœ| |âžœ| |âžœ| |âžœ| |âžœ| |âžœ| |âžœ| |âžœ| |âžœ| |âžœ| |âžœ| |âžœ| |âžœ| +|@+0#4040ff13&@2| @46 +| +0#0000000&@31|1|,|1| @10|T|o|p| diff --git a/src/testdir/dumps/Test_smooth_long_6.dump b/src/testdir/dumps/Test_smooth_long_6.dump index ba48c28..507aa46 100644 --- a/src/testdir/dumps/Test_smooth_long_6.dump +++ b/src/testdir/dumps/Test_smooth_long_6.dump @@ -3,4 +3,4 @@ |t|s| |o|f| |t|e|x|t| |w|i|t|h| |l|o|t|s| |o|f| |t|e|x|t| |w|i|t|h| |l|o|t|s| |o |f| |t|e|x|t| |w|i|t|h| |l|o|t|s| |o|f| |t|e|x|t| |w|i|t|h| |l|o|t|s| |o|f| |t|e |x|t| |w|i|t|h| |l|o|t|s| |o|f| |t|e|x|t| |w|i|t|h| |l|o|t|s| |o|f| |t|e|x|t| |w -| @21|3|,|9|0| @9|6@1|%| +|:|s|e|t| |s|c|r|o|l@1|o| @9|3|,|9|0| @9|6@1|%| diff --git a/src/testdir/dumps/Test_smooth_long_7.dump b/src/testdir/dumps/Test_smooth_long_7.dump index 222e001..225207f 100644 --- a/src/testdir/dumps/Test_smooth_long_7.dump +++ b/src/testdir/dumps/Test_smooth_long_7.dump @@ -3,4 +3,4 @@ |t|s| |o|f| |t|e|x|t| |w|i|t|h| |l|o|t|s| |o|f| |t|e|x|t| |w|i|t|h| |l|o|t|s| |o |f| |t|e|x|t| |w|i>t|h| |l|o|t|s| |o|f| |t|e|x|t| |w|i|t|h| |l|o|t|s| |o|f| |t|e |x|t| |w|i|t|h| |l|o|t|s| |o|f| |t|e|x|t| |w|i|t|h| |l|o|t|s| |o|f| |t|e|x|t| |w -| @21|3|,|1|7|0| @8|6@1|%| +|:|s|e|t| |s|c|r|o|l@1|o| @9|3|,|1|7|0| @8|6@1|%| diff --git a/src/testdir/test_autocmd.vim b/src/testdir/test_autocmd.vim index 564d568..6745ecb 100644 --- a/src/testdir/test_autocmd.vim +++ b/src/testdir/test_autocmd.vim @@ -3702,73 +3702,6 @@ func Test_autocmd_with_block() augroup END endfunc -" Test TextChangedI and TextChanged -func Test_Changed_ChangedI() - new - call test_override("char_avail", 1) - let [g:autocmd_i, g:autocmd_n] = ['',''] - - func! TextChangedAutocmdI(char) - let g:autocmd_{tolower(a:char)} = a:char .. b:changedtick - endfunc - - augroup Test_TextChanged - au! - au TextChanged <buffer> :call TextChangedAutocmdI('N') - au TextChangedI <buffer> :call TextChangedAutocmdI('I') - augroup END - - call feedkeys("ifoo\<esc>", 'tnix') - " TODO: Test test does not seem to trigger TextChanged autocommand, this - " requires running Vim in a terminal window. - " call assert_equal('N3', g:autocmd_n) - call assert_equal('I3', g:autocmd_i) - - call feedkeys("yyp", 'tnix') - " TODO: Test test does not seem to trigger TextChanged autocommand. - " call assert_equal('N4', g:autocmd_n) - call assert_equal('I3', g:autocmd_i) - - " TextChangedI should only trigger if change was done in Insert mode - let g:autocmd_i = '' - call feedkeys("yypi\<esc>", 'tnix') - call assert_equal('', g:autocmd_i) - - " TextChanged should only trigger if change was done in Normal mode - let g:autocmd_n = '' - call feedkeys("ibar\<esc>", 'tnix') - call assert_equal('', g:autocmd_n) - - " If change is a mix of Normal and Insert modes, TextChangedI should trigger - func s:validate_mixed_textchangedi(keys) - call feedkeys("ifoo\<esc>", 'tnix') - let g:autocmd_i = '' - let g:autocmd_n = '' - call feedkeys(a:keys, 'tnix') - call assert_notequal('', g:autocmd_i) - call assert_equal('', g:autocmd_n) - endfunc - - call s:validate_mixed_textchangedi("o\<esc>") - call s:validate_mixed_textchangedi("O\<esc>") - call s:validate_mixed_textchangedi("ciw\<esc>") - call s:validate_mixed_textchangedi("cc\<esc>") - call s:validate_mixed_textchangedi("C\<esc>") - call s:validate_mixed_textchangedi("s\<esc>") - call s:validate_mixed_textchangedi("S\<esc>") - - - " CleanUp - call test_override("char_avail", 0) - au! TextChanged <buffer> - au! TextChangedI <buffer> - augroup! Test_TextChanged - delfu TextChangedAutocmdI - unlet! g:autocmd_i g:autocmd_n - - bw! -endfunc - func Test_closing_autocmd_window() let lines =<< trim END edit Xa.txt @@ -3794,6 +3727,49 @@ func Test_switch_window_in_autocmd_window() call assert_false(bufexists('Xb.txt')) endfunc +" Test that using the autocommand window doesn't change current directory. +func Test_autocmd_window_cwd() + let saveddir = getcwd() + call mkdir('Xcwd/a/b/c/d', 'pR') + + new Xa.txt + tabnew + new Xb.txt + + tabprev + cd Xcwd + call assert_match('/Xcwd$', getcwd()) + call assert_match('\[global\] .*/Xcwd$', trim(execute('verbose pwd'))) + + autocmd BufEnter Xb.txt lcd ./a/b/c/d + doautoall BufEnter + au! BufEnter + call assert_match('/Xcwd$', getcwd()) + call assert_match('\[global\] .*/Xcwd$', trim(execute('verbose pwd'))) + + tabnext + cd ./a + tcd ./b + lcd ./c + call assert_match('/Xcwd/a/b/c$', getcwd()) + call assert_match('\[window\] .*/Xcwd/a/b/c$', trim(execute('verbose pwd'))) + + autocmd BufEnter Xa.txt call assert_match('Xcwd/a/b/c$', getcwd()) + doautoall BufEnter + au! BufEnter + call assert_match('/Xcwd/a/b/c$', getcwd()) + call assert_match('\[window\] .*/Xcwd/a/b/c$', trim(execute('verbose pwd'))) + bwipe! + call assert_match('/Xcwd/a/b$', getcwd()) + call assert_match('\[tabpage\] .*/Xcwd/a/b$', trim(execute('verbose pwd'))) + bwipe! + call assert_match('/Xcwd/a$', getcwd()) + call assert_match('\[global\] .*/Xcwd/a$', trim(execute('verbose pwd'))) + bwipe! + + call chdir(saveddir) +endfunc + func Test_bufwipeout_changes_window() " This should not crash, but we don't have any expectations about what " happens, changing window in BufWipeout has unpredictable results. @@ -4474,4 +4450,245 @@ func Test_autocmd_creates_new_buffer_on_bufleave() bw c.txt endfunc +" Ensure `expected` was just recently written as a Vim session +func s:assert_session_path(expected) + call assert_equal(a:expected, v:this_session) +endfunc + +" Check for `expected` after a session is written to-disk. +func s:watch_for_session_path(expected) + execute 'autocmd SessionWritePost * ++once execute "call s:assert_session_path(\"' + \ . a:expected + \ . '\")"' +endfunc + +" Ensure v:this_session gets the full session path, if explicitly stated +func Test_explicit_session_absolute_path() + %bwipeout! + + let directory = getcwd() + + let v:this_session = "" + let name = "some_file.vim" + let expected = fnamemodify(name, ":p") + call s:watch_for_session_path(expected) + execute "mksession! " .. expected + + call delete(expected) +endfunc + +" Ensure v:this_session gets the full session path, if explicitly stated +func Test_explicit_session_relative_path() + %bwipeout! + + let directory = getcwd() + + let v:this_session = "" + let name = "some_file.vim" + let expected = fnamemodify(name, ":p") + call s:watch_for_session_path(expected) + execute "mksession! " .. name + + call delete(expected) +endfunc + +" Ensure v:this_session gets the full session path, if not specified +func Test_implicit_session() + %bwipeout! + + let directory = getcwd() + + let v:this_session = "" + let expected = fnamemodify("Session.vim", ":p") + call s:watch_for_session_path(expected) + mksession! + + call delete(expected) +endfunc + +" Test TextChangedI and TextChanged +func Test_Changed_ChangedI() + " Run this test in a terminal because it requires running the main loop. + " Don't use CheckRunVimInTerminal as that will skip the test on Windows. + CheckFeature terminal + CheckNotGui + " Starting a terminal to run Vim is always considered flaky. + let g:test_is_flaky = 1 + + call writefile(['one', 'two', 'three'], 'XTextChangedI2', 'D') + let before =<< trim END + set ttimeout ttimeoutlen=10 + let [g:autocmd_n, g:autocmd_i] = ['',''] + + func TextChangedAutocmd(char) + let g:autocmd_{tolower(a:char)} = a:char .. b:changedtick + call writefile([$'{g:autocmd_n},{g:autocmd_i}'], 'XTextChangedI3') + endfunc + + au TextChanged <buffer> :call TextChangedAutocmd('N') + au TextChangedI <buffer> :call TextChangedAutocmd('I') + + nnoremap <CR> o<Esc> + autocmd SafeState * ++once call writefile([''], 'XTextChangedI3') + END + + call writefile(before, 'Xinit', 'D') + let buf = term_start( + \ GetVimCommandCleanTerm() .. '-n -S Xinit XTextChangedI2', + \ {'term_rows': 10}) + call assert_equal('running', term_getstatus(buf)) + call WaitForAssert({-> assert_true(filereadable('XTextChangedI3'))}) + defer delete('XTextChangedI3') + call WaitForAssert({-> assert_equal([''], readfile('XTextChangedI3'))}) + + " TextChanged should trigger if a mapping enters and leaves Insert mode. + call term_sendkeys(buf, "\<CR>") + call WaitForAssert({-> assert_equal('N4,', readfile('XTextChangedI3')->join("\n"))}) + + call term_sendkeys(buf, "i") + call WaitForAssert({-> assert_match('^-- INSERT --', term_getline(buf, 10))}) + call WaitForAssert({-> assert_equal('N4,', readfile('XTextChangedI3')->join("\n"))}) + " TextChangedI should trigger if change is done in Insert mode. + call term_sendkeys(buf, "f") + call WaitForAssert({-> assert_equal('N4,I5', readfile('XTextChangedI3')->join("\n"))}) + call term_sendkeys(buf, "o") + call WaitForAssert({-> assert_equal('N4,I6', readfile('XTextChangedI3')->join("\n"))}) + call term_sendkeys(buf, "o") + call WaitForAssert({-> assert_equal('N4,I7', readfile('XTextChangedI3')->join("\n"))}) + " TextChanged shouldn't trigger when leaving Insert mode and TextChangedI + " has been triggered. + call term_sendkeys(buf, "\<Esc>") + call WaitForAssert({-> assert_notmatch('^-- INSERT --', term_getline(buf, 10))}) + call WaitForAssert({-> assert_equal('N4,I7', readfile('XTextChangedI3')->join("\n"))}) + + " TextChanged should trigger if change is done in Normal mode. + call term_sendkeys(buf, "yyp") + call WaitForAssert({-> assert_equal('N8,I7', readfile('XTextChangedI3')->join("\n"))}) + + " TextChangedI shouldn't trigger if change isn't done in Insert mode. + call term_sendkeys(buf, "i") + call WaitForAssert({-> assert_match('^-- INSERT --', term_getline(buf, 10))}) + call WaitForAssert({-> assert_equal('N8,I7', readfile('XTextChangedI3')->join("\n"))}) + call term_sendkeys(buf, "\<Esc>") + call WaitForAssert({-> assert_notmatch('^-- INSERT --', term_getline(buf, 10))}) + call WaitForAssert({-> assert_equal('N8,I7', readfile('XTextChangedI3')->join("\n"))}) + + " TextChangedI should trigger if change is a mix of Normal and Insert modes. + func! s:validate_mixed_textchangedi(buf, keys) + let buf = a:buf + call term_sendkeys(buf, "ifoo") + call WaitForAssert({-> assert_match('^-- INSERT --', term_getline(buf, 10))}) + call term_sendkeys(buf, "\<Esc>") + call WaitForAssert({-> assert_notmatch('^-- INSERT --', term_getline(buf, 10))}) + call term_sendkeys(buf, ":let [g:autocmd_n, g:autocmd_i] = ['', '']\<CR>") + call writefile([], 'XTextChangedI3') + call term_sendkeys(buf, a:keys) + call WaitForAssert({-> assert_match('^-- INSERT --', term_getline(buf, 10))}) + call WaitForAssert({-> assert_match('^,I\d\+', readfile('XTextChangedI3')->join("\n"))}) + call term_sendkeys(buf, "\<Esc>") + call WaitForAssert({-> assert_notmatch('^-- INSERT --', term_getline(buf, 10))}) + call WaitForAssert({-> assert_match('^,I\d\+', readfile('XTextChangedI3')->join("\n"))}) + endfunc + + call s:validate_mixed_textchangedi(buf, "o") + call s:validate_mixed_textchangedi(buf, "O") + call s:validate_mixed_textchangedi(buf, "ciw") + call s:validate_mixed_textchangedi(buf, "cc") + call s:validate_mixed_textchangedi(buf, "C") + call s:validate_mixed_textchangedi(buf, "s") + call s:validate_mixed_textchangedi(buf, "S") + + " clean up + bwipe! +endfunc + +" Test that filetype detection still works when SwapExists autocommand sets +" filetype in another buffer. +func Test_SwapExists_set_other_buf_filetype() + let lines =<< trim END + set nocompatible directory=. + filetype on + + let g:buf = bufnr() + new + + func SwapExists() + let v:swapchoice = 'o' + call setbufvar(g:buf, '&filetype', 'text') + endfunc + + func SafeState() + edit <script> + redir! > XftSwapExists.out + set readonly? filetype? + redir END + qall! + endfunc + + autocmd SwapExists * ++nested call SwapExists() + autocmd SafeState * ++nested ++once call SafeState() + END + call writefile(lines, 'XftSwapExists.vim', 'D') + + new XftSwapExists.vim + if RunVim('', '', ' -S XftSwapExists.vim') + call assert_equal( + \ ['', ' readonly', ' filetype=vim'], + \ readfile('XftSwapExists.out')) + call delete('XftSwapExists.out') + endif + + bwipe! +endfunc + +" Test that file is not marked as modified when SwapExists autocommand sets +" 'modified' in another buffer. +func Test_SwapExists_set_other_buf_modified() + let lines =<< trim END + set nocompatible directory=. + + let g:buf = bufnr() + new + + func SwapExists() + let v:swapchoice = 'o' + call setbufvar(g:buf, '&modified', 1) + endfunc + + func SafeState() + edit <script> + redir! > XmodSwapExists.out + set readonly? modified? + redir END + qall! + endfunc + + autocmd SwapExists * ++nested call SwapExists() + autocmd SafeState * ++nested ++once call SafeState() + END + call writefile(lines, 'XmodSwapExists.vim', 'D') + + new XmodSwapExists.vim + if RunVim('', '', ' -S XmodSwapExists.vim') + call assert_equal( + \ ['', ' readonly', 'nomodified'], + \ readfile('XmodSwapExists.out')) + call delete('XmodSwapExists.out') + endif + + bwipe! +endfunc + +func Test_BufEnter_botline() + set hidden + call writefile(range(10), 'Xxx1', 'D') + call writefile(range(20), 'Xxx2', 'D') + edit Xxx1 + edit Xxx2 + au BufEnter Xxx1 call assert_true(line('w$') > 1) + edit Xxx1 + au! BufEnter Xxx1 + set hidden&vim +endfunc + " vim: shiftwidth=2 sts=2 expandtab diff --git a/src/testdir/test_buffer.vim b/src/testdir/test_buffer.vim index bc29c21..de088bd 100644 --- a/src/testdir/test_buffer.vim +++ b/src/testdir/test_buffer.vim @@ -133,7 +133,7 @@ func Test_bdelete_cmd() call assert_fails('1,1bdelete 1 2', 'E488:') call assert_fails('bdelete \)', 'E55:') - " Deleting a unlisted and unloaded buffer + " Deleting an unlisted and unloaded buffer edit Xbdelfile1 let bnr = bufnr() set nobuflisted @@ -252,21 +252,30 @@ func Test_goto_buf_with_confirm() CheckUnix CheckNotGui CheckFeature dialog_con + " When dialog_con_gui is defined, Vim is compiled with GUI support + " and FEAT_BROWSE will be defined, which causes :confirm :b to + " call do_browse(), which will try to use a GUI file browser, + " which aborts if a GUI is not available. + CheckNotFeature dialog_con_gui new XgotoConf enew call setline(1, 'test') call assert_fails('b XgotoConf', 'E37:') call feedkeys('c', 'L') call assert_fails('confirm b XgotoConf', 'E37:') - call assert_equal(1, &modified) - call assert_equal('', @%) + call assert_true(&modified) + call assert_true(empty(bufname('%'))) call feedkeys('y', 'L') - call assert_fails('confirm b XgotoConf', ['', 'E37:']) - call assert_equal(1, &modified) - call assert_equal('', @%) + confirm b XgotoConf + call assert_equal('XgotoConf', bufname('%')) + call assert_equal(['test'], readfile('Untitled')) + e Untitled + call setline(2, 'test2') call feedkeys('n', 'L') confirm b XgotoConf - call assert_equal('XgotoConf', @%) + call assert_equal('XgotoConf', bufname('%')) + call assert_equal(['test'], readfile('Untitled')) + call delete('Untitled') close! endfunc diff --git a/src/testdir/test_cmdline.vim b/src/testdir/test_cmdline.vim index 7c86bcd..ed8f89d 100644 --- a/src/testdir/test_cmdline.vim +++ b/src/testdir/test_cmdline.vim @@ -3733,9 +3733,9 @@ func Test_custom_completion() call assert_fails("call getcompletion('', 'custom')", 'E475:') call assert_fails("call getcompletion('', 'customlist')", 'E475:') - call assert_equal(getcompletion('', 'custom,CustomComplete1'), ['a', 'b', 'c']) - call assert_equal(getcompletion('', 'customlist,CustomComplete2'), ['a', 'b']) - call assert_equal(getcompletion('b', 'customlist,CustomComplete2'), ['b']) + call assert_equal(['a', 'b', 'c'], getcompletion('', 'custom,CustomComplete1')) + call assert_equal(['a', 'b'], getcompletion('', 'customlist,CustomComplete2')) + call assert_equal(['b'], getcompletion('b', 'customlist,CustomComplete2')) delcom Test1 delcom Test2 @@ -3792,4 +3792,21 @@ func Test_buffer_completion() call assert_equal("\"b Xbuf_complete/Foobar.c Xbuf_complete/MyFoobar.c AFoobar.h", @:) endfunc +" :set t_?? +func Test_term_option() + set wildoptions& + let _cpo = &cpo + set cpo-=C + " There may be more, test only until t_xo + let expected='"set t_AB t_AF t_AU t_AL t_al t_bc t_BE t_BD t_cd t_ce t_Ce t_CF t_cl t_cm' + \ .. ' t_Co t_CS t_Cs t_cs t_CV t_da t_db t_DL t_dl t_ds t_Ds t_EC t_EI t_fs t_fd t_fe' + \ .. ' t_GP t_IE t_IS t_ke t_ks t_le t_mb t_md t_me t_mr t_ms t_nd t_op t_RF t_RB t_RC' + \ .. ' t_RI t_Ri t_RK t_RS t_RT t_RV t_Sb t_SC t_se t_Sf t_SH t_SI t_Si t_so t_SR t_sr' + \ .. ' t_ST t_Te t_te t_TE t_ti t_TI t_Ts t_ts t_u7 t_ue t_us t_Us t_ut t_vb t_ve t_vi' + \ .. ' t_VS t_vs t_WP t_WS t_XM t_xn t_xs t_ZH t_ZR t_8f t_8b t_8u t_xo .*' + call feedkeys(":set t_\<C-A>\<C-B>\"\<CR>", 'tx') + call assert_match(expected, @:) + let &cpo = _cpo +endfunc + " vim: shiftwidth=2 sts=2 expandtab diff --git a/src/testdir/test_cmdmods.vim b/src/testdir/test_cmdmods.vim index 323a78e..66ff6a1 100644 --- a/src/testdir/test_cmdmods.vim +++ b/src/testdir/test_cmdmods.vim @@ -8,10 +8,10 @@ def Test_cmdmods_array() # :hide is both a command and a modifier cmds->extend(['hide']) - # Get the entries of cmdmods[] in ex_docmd.c + # Get the entries of cmdmod_info_tab[] in ex_docmd.c edit ../ex_docmd.c - var top = search('^} cmdmods[') + 1 - var bot = search('^};') - 1 + var top = search('^static cmdmod_info_T cmdmod_info_tab[') + 1 + var bot = search('^};.*\/\/ cmdmod_info_tab') - 1 lines = getline(top, bot) var mods = lines->map((_, v) => substitute(v, '.*"\(\k*\)".*', '\1', '')) diff --git a/src/testdir/test_codestyle.vim b/src/testdir/test_codestyle.vim index 359410d..a455264 100644 --- a/src/testdir/test_codestyle.vim +++ b/src/testdir/test_codestyle.vim @@ -7,13 +7,17 @@ def s:ReportError(fname: string, lnum: number, msg: string) enddef def s:PerformCheck(fname: string, pattern: string, msg: string, skip: string) + var prev_lnum = 1 var lnum = 1 while (lnum > 0) cursor(lnum, 1) lnum = search(pattern, 'W', 0, 0, skip) - ReportError(fname, lnum, msg) + if (prev_lnum == lnum) + break + endif + prev_lnum = lnum if (lnum > 0) - lnum += 1 + ReportError(fname, lnum, msg) endif endwhile enddef diff --git a/src/testdir/test_compiler.vim b/src/testdir/test_compiler.vim index 4b710df..b7315e1 100644 --- a/src/testdir/test_compiler.vim +++ b/src/testdir/test_compiler.vim @@ -71,10 +71,10 @@ func Test_compiler_completion() call assert_match('^"compiler ' .. clist .. '$', @:) call feedkeys(":compiler p\<C-A>\<C-B>\"\<CR>", 'tx') - call assert_match('"compiler pbx perl\( p[a-z]\+\)\+ pylint pyunit', @:) + call assert_match('"compiler pandoc pbx perl\( p[a-z_]\+\)\+ pylint pyunit', @:) call feedkeys(":compiler! p\<C-A>\<C-B>\"\<CR>", 'tx') - call assert_match('"compiler! pbx perl\( p[a-z]\+\)\+ pylint pyunit', @:) + call assert_match('"compiler! pandoc pbx perl\( p[a-z_]\+\)\+ pylint pyunit', @:) endfunc func Test_compiler_error() diff --git a/src/testdir/test_conceal.vim b/src/testdir/test_conceal.vim index 355817d..2ce7384 100644 --- a/src/testdir/test_conceal.vim +++ b/src/testdir/test_conceal.vim @@ -199,6 +199,7 @@ endfunc " Same as Test_conceal_wrapped_cursorline_wincolor(), but with 'rightleft'. func Test_conceal_wrapped_cursorline_wincolor_rightleft() + CheckFeature rightleft CheckScreendump let code =<< trim [CODE] diff --git a/src/testdir/test_diffmode.vim b/src/testdir/test_diffmode.vim index 7602bd3..098d5d0 100644 --- a/src/testdir/test_diffmode.vim +++ b/src/testdir/test_diffmode.vim @@ -1647,36 +1647,39 @@ endfunc func Test_diff_scroll_many_filler() 20new vnew - call setline(1, ['^^^', '^^^', '$$$', '$$$']) + call setline(1, range(1, 40)) diffthis setlocal scrolloff=0 wincmd p - call setline(1, ['^^^', '^^^'] + repeat(['###'], 41) + ['$$$', '$$$']) + call setline(1, range(1, 20)->reverse() + ['###']->repeat(41) + range(21, 40)->reverse()) diffthis setlocal scrolloff=0 wincmd p redraw " Note: need a redraw after each scroll, otherwise the test always passes. - normal! G - redraw - call assert_equal(3, winsaveview().topline) - call assert_equal(18, winsaveview().topfill) - exe "normal! \<C-B>" - redraw - call assert_equal(3, winsaveview().topline) - call assert_equal(19, winsaveview().topfill) - exe "normal! \<C-B>" - redraw - call assert_equal(2, winsaveview().topline) - call assert_equal(0, winsaveview().topfill) - exe "normal! \<C-B>" - redraw - call assert_equal(1, winsaveview().topline) - call assert_equal(0, winsaveview().topfill) + for _ in range(2) + normal! G + redraw + call assert_equal(40, winsaveview().topline) + call assert_equal(19, winsaveview().topfill) + exe "normal! \<C-B>" + redraw + call assert_equal(22, winsaveview().topline) + call assert_equal(0, winsaveview().topfill) + exe "normal! \<C-B>" + redraw + call assert_equal(4, winsaveview().topline) + call assert_equal(0, winsaveview().topfill) + exe "normal! \<C-B>" + redraw + call assert_equal(1, winsaveview().topline) + call assert_equal(0, winsaveview().topfill) + set smoothscroll + endfor - bwipe! - bwipe! + set smoothscroll& + %bwipe! endfunc " This was trying to update diffs for a buffer being closed @@ -2020,4 +2023,23 @@ func Test_diff_toggle_wrap_skipcol_leftcol() bwipe! endfunc +" Ctrl-D reveals filler lines below the last line in the buffer. +func Test_diff_eob_halfpage() + new + call setline(1, ['']->repeat(10) + ['a']) + diffthis + new + call setline(1, ['']->repeat(3) + ['a', 'b']) + diffthis + resize 5 + wincmd j + resize 5 + norm G + call assert_equal(7, line('w0')) + exe "norm! \<C-D>" + call assert_equal(8, line('w0')) + + %bwipe! +endfunc + " vim: shiftwidth=2 sts=2 expandtab diff --git a/src/testdir/test_digraph.vim b/src/testdir/test_digraph.vim index 4aed403..3312faf 100644 --- a/src/testdir/test_digraph.vim +++ b/src/testdir/test_digraph.vim @@ -595,13 +595,13 @@ func Test_digraph_getlist_function() call digraph_setlist([['aa', 'ã'], ['bb', 'ã']]) for pair in digraph_getlist(1) - call assert_equal(digraph_get(pair[0]), pair[1]) + call assert_equal(pair[1], digraph_get(pair[0])) endfor " We don't know how many digraphs are registered before, so check the number " of digraphs returned. call assert_equal(digraph_getlist()->len(), digraph_getlist(0)->len()) - call assert_notequal((digraph_getlist()->len()), digraph_getlist(1)->len()) + call assert_notequal(digraph_getlist()->len(), digraph_getlist(1)->len()) call assert_fails('call digraph_getlist(0z12)', 'E974: Using a Blob as a Number') endfunc diff --git a/src/testdir/test_edit.vim b/src/testdir/test_edit.vim index 36e0525..789e44c 100644 --- a/src/testdir/test_edit.vim +++ b/src/testdir/test_edit.vim @@ -6,8 +6,6 @@ endif source check.vim source screendump.vim - -" Needed for testing basic rightleft: Test_edit_rightleft source view_util.vim " Needs to come first until the bug in getchar() is @@ -1302,9 +1300,9 @@ func Test_edit_PAGEUP_PAGEDOWN() call feedkeys("A\<PageUp>\<esc>", 'tnix') call assert_equal([0, 13, 1, 0], getpos('.')) call feedkeys("A\<PageUp>\<esc>", 'tnix') - call assert_equal([0, 5, 1, 0], getpos('.')) + call assert_equal([0, 10, 1, 0], getpos('.')) call feedkeys("A\<PageUp>\<esc>", 'tnix') - call assert_equal([0, 5, 11, 0], getpos('.')) + call assert_equal([0, 10, 11, 0], getpos('.')) " <S-Up> is the same as <PageUp> " <S-Down> is the same as <PageDown> call cursor(1, 1) @@ -1325,9 +1323,9 @@ func Test_edit_PAGEUP_PAGEDOWN() call feedkeys("A\<S-Up>\<esc>", 'tnix') call assert_equal([0, 13, 1, 0], getpos('.')) call feedkeys("A\<S-Up>\<esc>", 'tnix') - call assert_equal([0, 5, 1, 0], getpos('.')) + call assert_equal([0, 10, 1, 0], getpos('.')) call feedkeys("A\<S-Up>\<esc>", 'tnix') - call assert_equal([0, 5, 11, 0], getpos('.')) + call assert_equal([0, 10, 11, 0], getpos('.')) set nostartofline call cursor(30, 11) norm! zt @@ -1338,9 +1336,9 @@ func Test_edit_PAGEUP_PAGEDOWN() call feedkeys("A\<PageUp>\<esc>", 'tnix') call assert_equal([0, 13, 11, 0], getpos('.')) call feedkeys("A\<PageUp>\<esc>", 'tnix') - call assert_equal([0, 5, 11, 0], getpos('.')) + call assert_equal([0, 10, 11, 0], getpos('.')) call feedkeys("A\<PageUp>\<esc>", 'tnix') - call assert_equal([0, 5, 11, 0], getpos('.')) + call assert_equal([0, 10, 11, 0], getpos('.')) call cursor(1, 1) call feedkeys("A\<PageDown>\<esc>", 'tnix') call assert_equal([0, 9, 11, 0], getpos('.')) @@ -1363,9 +1361,9 @@ func Test_edit_PAGEUP_PAGEDOWN() call feedkeys("A\<S-Up>\<esc>", 'tnix') call assert_equal([0, 13, 11, 0], getpos('.')) call feedkeys("A\<S-Up>\<esc>", 'tnix') - call assert_equal([0, 5, 11, 0], getpos('.')) + call assert_equal([0, 10, 11, 0], getpos('.')) call feedkeys("A\<S-Up>\<esc>", 'tnix') - call assert_equal([0, 5, 11, 0], getpos('.')) + call assert_equal([0, 10, 11, 0], getpos('.')) call cursor(1, 1) call feedkeys("A\<S-Down>\<esc>", 'tnix') call assert_equal([0, 9, 11, 0], getpos('.')) @@ -1964,8 +1962,8 @@ func Test_edit_ctrl_r_failed() let buf = RunVimInTerminal('', #{rows: 6, cols: 60}) - " trying to insert a dictionary produces an error - call term_sendkeys(buf, "i\<C-R>={}\<CR>") + " trying to insert a blob produces an error + call term_sendkeys(buf, "i\<C-R>=0z\<CR>") " ending Insert mode should put the cursor back on the ':' call term_sendkeys(buf, ":\<Esc>") @@ -2046,7 +2044,10 @@ func Test_edit_revins() call setline(1, 'one two three') exe "normal! wi\nfour" call assert_equal(['one two three', 'ruof'], getline(1, '$')) - set revins& + set backspace=indent,eol,start + exe "normal! ggA\<BS>:" + call assert_equal(['one two three:ruof'], getline(1, '$')) + set revins& backspace& bw! endfunc @@ -2158,4 +2159,133 @@ func Test_edit_Ctrl_RSB() bwipe! endfunc +func s:check_backspace(expected) + let g:actual = [] + inoremap <buffer> <F2> <Cmd>let g:actual += [getline('.')]<CR> + set backspace=indent,eol,start + + exe "normal i" .. repeat("\<BS>\<F2>", len(a:expected)) + call assert_equal(a:expected, g:actual) + + set backspace& + iunmap <buffer> <F2> + unlet g:actual +endfunc + +" Test that backspace works with 'smarttab' and mixed Tabs and spaces. +func Test_edit_backspace_smarttab_mixed() + set smarttab + call NewWindow(1, 30) + setlocal tabstop=4 shiftwidth=4 + + call setline(1, "\t \t \t a") + normal! $ + call s:check_backspace([ + \ "\t \t \ta", + \ "\t \t a", + \ "\t \t a", + \ "\t \ta", + \ "\t a", + \ "\ta", + \ "a", + \ ]) + + call CloseWindow() + set smarttab& +endfunc + +" Test that backspace works with 'smarttab' and 'varsofttabstop'. +func Test_edit_backspace_smarttab_varsofttabstop() + CheckFeature vartabs + + set smarttab + call NewWindow(1, 30) + setlocal tabstop=8 varsofttabstop=6,2,5,3 + + call setline(1, "a\t \t a") + normal! $ + call s:check_backspace([ + \ "a\t \ta", + \ "a\t a", + \ "a\ta", + \ "a a", + \ "aa", + \ "a", + \ ]) + + call CloseWindow() + set smarttab& +endfunc + +" Test that backspace works with 'smarttab' when a Tab is shown as "^I". +func Test_edit_backspace_smarttab_list() + set smarttab + call NewWindow(1, 30) + setlocal tabstop=4 shiftwidth=4 list listchars= + + call setline(1, "\t \t \t a") + normal! $ + call s:check_backspace([ + \ "\t \t a", + \ "\t \t a", + \ "\t \ta", + \ "\t a", + \ "a", + \ ]) + + call CloseWindow() + set smarttab& +endfunc + +" Test that backspace works with 'smarttab' and 'breakindent'. +func Test_edit_backspace_smarttab_breakindent() + CheckFeature linebreak + + set smarttab + call NewWindow(3, 17) + setlocal tabstop=4 shiftwidth=4 breakindent breakindentopt=min:5 + + call setline(1, "\t \t \t a") + normal! $ + call s:check_backspace([ + \ "\t \t \ta", + \ "\t \t a", + \ "\t \t a", + \ "\t \ta", + \ "\t a", + \ "\ta", + \ "a", + \ ]) + + call CloseWindow() + set smarttab& +endfunc + +" Test that backspace works with 'smarttab' and virtual text. +func Test_edit_backspace_smarttab_virtual_text() + CheckFeature textprop + + set smarttab + call NewWindow(1, 50) + setlocal tabstop=4 shiftwidth=4 + + call setline(1, "\t \t \t a") + call prop_type_add('theprop', {}) + call prop_add(1, 3, {'type': 'theprop', 'text': 'text'}) + normal! $ + call s:check_backspace([ + \ "\t \t \ta", + \ "\t \t a", + \ "\t \t a", + \ "\t \ta", + \ "\t a", + \ "\ta", + \ "a", + \ ]) + + call CloseWindow() + call prop_type_delete('theprop') + set smarttab& +endfunc + " vim: shiftwidth=2 sts=2 expandtab diff --git a/src/testdir/test_expr.vim b/src/testdir/test_expr.vim index c1869c1..6acfe00 100644 --- a/src/testdir/test_expr.vim +++ b/src/testdir/test_expr.vim @@ -950,6 +950,22 @@ func Test_string_interp() endif call assert_equal(0, tmp) + #" Dict interpolation + VAR d = {'a': 10, 'b': [1, 2]} + call assert_equal("{'a': 10, 'b': [1, 2]}", $'{d}') + VAR emptydict = {} + call assert_equal("a{}b", $'a{emptydict}b') + VAR nulldict = test_null_dict() + call assert_equal("a{}b", $'a{nulldict}b') + + #" List interpolation + VAR l = ['a', 'b', 'c'] + call assert_equal("['a', 'b', 'c']", $'{l}') + VAR emptylist = [] + call assert_equal("a[]b", $'a{emptylist}b') + VAR nulllist = test_null_list() + call assert_equal("a[]b", $'a{nulllist}b') + #" Stray closing brace. call assert_fails('echo $"moo}"', 'E1278:') #" Undefined variable in expansion. diff --git a/src/testdir/test_filechanged.vim b/src/testdir/test_filechanged.vim index c3a5664..12ac4cc 100644 --- a/src/testdir/test_filechanged.vim +++ b/src/testdir/test_filechanged.vim @@ -11,8 +11,12 @@ func Test_FileChangedShell_reload() new Xchanged_r call setline(1, 'reload this') write - " Need to wait until the timestamp would change by at least a second. - sleep 2 + " Need to wait until the timestamp would change. + if has('nanotime') + sleep 10m + else + sleep 2 + endif silent !echo 'extra line' >>Xchanged_r checktime call assert_equal('changed', g:reason) @@ -50,7 +54,11 @@ func Test_FileChangedShell_reload() call assert_equal('new line', getline(1)) " Only time changed - sleep 2 + if has('nanotime') + sleep 10m + else + sleep 2 + endif silent !touch Xchanged_r let g:reason = '' checktime @@ -65,7 +73,11 @@ func Test_FileChangedShell_reload() call setline(2, 'before write') write call setline(2, 'after write') - sleep 2 + if has('nanotime') + sleep 10m + else + sleep 2 + endif silent !echo 'different line' >>Xchanged_r let g:reason = '' checktime @@ -192,8 +204,12 @@ func Test_file_changed_dialog() new Xchanged_d call setline(1, 'reload this') write - " Need to wait until the timestamp would change by at least a second. - sleep 2 + " Need to wait until the timestamp would change. + if has('nanotime') + sleep 10m + else + sleep 2 + endif silent !echo 'extra line' >>Xchanged_d call feedkeys('L', 'L') checktime @@ -228,7 +244,11 @@ func Test_file_changed_dialog() call assert_equal('new line', getline(1)) " Only time changed, no prompt - sleep 2 + if has('nanotime') + sleep 10m + else + sleep 2 + endif silent !touch Xchanged_d let v:warningmsg = '' checktime Xchanged_d diff --git a/src/testdir/test_filetype.vim b/src/testdir/test_filetype.vim index d77e5e0..f8fe9ec 100644 --- a/src/testdir/test_filetype.vim +++ b/src/testdir/test_filetype.vim @@ -126,6 +126,7 @@ def s:GetFilenameChecks(): dict<list<string>> blade: ['file.blade.php'], blank: ['file.bl'], blueprint: ['file.blp'], + bp: ['Android.bp'], bsdl: ['file.bsd', 'file.bsdl'], bst: ['file.bst'], bzl: ['file.bazel', 'file.bzl', 'WORKSPACE', 'WORKSPACE.bzlmod'], @@ -144,6 +145,7 @@ def s:GetFilenameChecks(): dict<list<string>> cf: ['file.cfm', 'file.cfi', 'file.cfc'], cfengine: ['cfengine.conf'], cfg: ['file.hgrc', 'filehgrc', 'hgrc', 'some-hgrc'], + cgdbrc: ['cgdbrc'], ch: ['file.chf'], chaiscript: ['file.chai'], chaskell: ['file.chs'], @@ -153,16 +155,17 @@ def s:GetFilenameChecks(): dict<list<string>> chuck: ['file.ck'], cl: ['file.eni'], clean: ['file.dcl', 'file.icl'], - clojure: ['file.clj', 'file.cljs', 'file.cljx', 'file.cljc'], + clojure: ['file.clj', 'file.cljs', 'file.cljx', 'file.cljc', 'init.trans', 'any/etc/translate-shell', '.trans'], cmake: ['CMakeLists.txt', 'file.cmake', 'file.cmake.in'], + cmakecache: ['CMakeCache.txt'], cmod: ['file.cmod'], cmusrc: ['any/.cmus/autosave', 'any/.cmus/rc', 'any/.cmus/command-history', 'any/.cmus/file.theme', 'any/cmus/rc', 'any/cmus/file.theme', '/.cmus/autosave', '/.cmus/command-history', '/.cmus/file.theme', '/.cmus/rc', '/cmus/file.theme', '/cmus/rc'], cobol: ['file.cbl', 'file.cob', 'file.lib'], coco: ['file.atg'], conaryrecipe: ['file.recipe'], - conf: ['auto.master', 'file.conf'], + conf: ['auto.master', 'file.conf', 'texdoc.cnf', '.x11vncrc', '.chktexrc', '.ripgreprc', 'ripgreprc', 'file.ctags', '.mbsyncrc'], config: ['configure.in', 'configure.ac', '/etc/hostname.file', 'any/etc/hostname.file'], - confini: ['/etc/pacman.conf', 'any/etc/pacman.conf', 'mpv.conf', 'any/.aws/config', 'any/.aws/credentials', 'file.nmconnection'], + confini: ['pacman.conf', 'paru.conf', 'mpv.conf', 'any/.aws/config', 'any/.aws/credentials', 'file.nmconnection'], context: ['tex/context/any/file.tex', 'file.mkii', 'file.mkiv', 'file.mkvi', 'file.mkxl', 'file.mklx'], cook: ['file.cook'], corn: ['file.corn'], @@ -210,16 +213,24 @@ def s:GetFilenameChecks(): dict<list<string>> dnsmasq: ['/etc/dnsmasq.conf', '/etc/dnsmasq.d/file', 'any/etc/dnsmasq.conf', 'any/etc/dnsmasq.d/file'], dockerfile: ['Containerfile', 'Dockerfile', 'dockerfile', 'file.Dockerfile', 'file.dockerfile', 'Dockerfile.debian', 'Containerfile.something'], dosbatch: ['file.bat'], - dosini: ['/etc/yum.conf', 'file.ini', 'npmrc', '.npmrc', 'php.ini', 'php.ini-5', 'php.ini-file', '/etc/yum.repos.d/file', 'any/etc/yum.conf', 'any/etc/yum.repos.d/file', 'file.wrap', 'file.vbp', 'ja2.ini', 'JA2.INI'], + dosini: ['/etc/yum.conf', '/etc/nfs.conf', '/etc/nfsmount.conf', 'file.ini', + 'npmrc', '.npmrc', 'php.ini', 'php.ini-5', 'php.ini-file', + '/etc/yum.repos.d/file', 'any/etc/yum.conf', 'any/etc/yum.repos.d/file', 'file.wrap', + 'file.vbp', 'ja2.ini', 'JA2.INI', 'mimeapps.list', 'pip.conf', 'setup.cfg', 'pudb.cfg', + '.coveragerc', '.pypirc', '.gitlint', '.oelint.cfg', 'pylintrc', '.pylintrc', + '/home/user/.config/bpython/config', '/home/user/.config/mypy/config', '.wakatime.cfg', '.replyrc', + 'psprint.conf', 'sofficerc', 'any/.config/lxqt/globalkeyshortcuts.conf', 'any/.config/screengrab/screengrab.conf', + 'any/.local/share/flatpak/repo/config', '.notmuch-config'], dot: ['file.dot', 'file.gv'], dracula: ['file.drac', 'file.drc', 'filelvs', 'filelpe', 'drac.file', 'lpe', 'lvs', 'some-lpe', 'some-lvs'], dtd: ['file.dtd'], dtrace: ['/usr/lib/dtrace/io.d'], - dts: ['file.dts', 'file.dtsi', 'file.dtso', 'file.its'], + dts: ['file.dts', 'file.dtsi', 'file.dtso', 'file.its', 'file.keymap'], dune: ['jbuild', 'dune', 'dune-project', 'dune-workspace'], dylan: ['file.dylan'], dylanintr: ['file.intr'], dylanlid: ['file.lid'], + earthfile: ['Earthfile'], ecd: ['file.ecd'], edif: ['file.edf', 'file.edif', 'file.edo'], editorconfig: ['.editorconfig'], @@ -283,7 +294,7 @@ def s:GetFilenameChecks(): dict<list<string>> glsl: ['file.glsl'], gn: ['file.gn', 'file.gni'], gnash: ['gnashrc', '.gnashrc', 'gnashpluginrc', '.gnashpluginrc'], - gnuplot: ['file.gpi', '.gnuplot', 'file.gnuplot'], + gnuplot: ['file.gpi', '.gnuplot', 'file.gnuplot', '.gnuplot_history'], go: ['file.go'], gomod: ['go.mod'], gosum: ['go.sum', 'go.work.sum'], @@ -312,7 +323,7 @@ def s:GetFilenameChecks(): dict<list<string>> hcl: ['file.hcl'], heex: ['file.heex'], hercules: ['file.vc', 'file.ev', 'file.sum', 'file.errsum'], - hex: ['file.hex', 'file.h32'], + hex: ['file.hex', 'file.ihex', 'file.ihe', 'file.ihx', 'file.int', 'file.mcs', 'file.h32', 'file.h80', 'file.h86', 'file.a43', 'file.a90'], hgcommit: ['hg-editor-file.txt'], hjson: ['file.hjson'], hlsplaylist: ['file.m3u', 'file.m3u8'], @@ -342,7 +353,7 @@ def s:GetFilenameChecks(): dict<list<string>> janet: ['file.janet'], java: ['file.java', 'file.jav'], javacc: ['file.jj', 'file.jjt'], - javascript: ['file.js', 'file.jsm', 'file.javascript', 'file.es', 'file.mjs', 'file.cjs'], + javascript: ['file.js', 'file.jsm', 'file.javascript', 'file.es', 'file.mjs', 'file.cjs', '.node_repl_history'], 'javascript.glimmer': ['file.gjs'], javascriptreact: ['file.jsx'], jess: ['file.clp'], @@ -350,9 +361,9 @@ def s:GetFilenameChecks(): dict<list<string>> jq: ['file.jq'], jovial: ['file.jov', 'file.j73', 'file.jovial'], jproperties: ['file.properties', 'file.properties_xx', 'file.properties_xx_xx', 'some.properties_xx_xx_file', 'org.eclipse.xyz.prefs'], - json: ['file.json', 'file.jsonp', 'file.json-patch', 'file.geojson', 'file.webmanifest', 'Pipfile.lock', 'file.ipynb', '.prettierrc', '.firebaserc', '.stylelintrc', 'file.slnf'], + json: ['file.json', 'file.jsonp', 'file.json-patch', 'file.geojson', 'file.webmanifest', 'Pipfile.lock', 'file.ipynb', 'file.jupyterlab-settings', '.prettierrc', '.firebaserc', '.stylelintrc', 'file.slnf', 'file.sublime-project', 'file.sublime-settings', 'file.sublime-workspace', 'file.bd', 'file.bda', 'file.xci', 'flake.lock'], json5: ['file.json5'], - jsonc: ['file.jsonc', '.babelrc', '.eslintrc', '.jsfmtrc', '.jshintrc', '.hintrc', '.swrc', 'jsconfig.json', 'tsconfig.json', 'tsconfig.test.json', 'tsconfig-test.json', '.luaurc'], + jsonc: ['file.jsonc', '.babelrc', '.eslintrc', '.jsfmtrc', '.jshintrc', '.jscsrc', '.vsconfig', '.hintrc', '.swrc', 'jsconfig.json', 'tsconfig.json', 'tsconfig.test.json', 'tsconfig-test.json', '.luaurc'], jsonl: ['file.jsonl'], jsonnet: ['file.jsonnet', 'file.libsonnet'], jsp: ['file.jsp'], @@ -368,7 +379,7 @@ def s:GetFilenameChecks(): dict<list<string>> kwt: ['file.k'], lace: ['file.ace', 'file.ACE'], latte: ['file.latte', 'file.lte'], - ld: ['file.ld'], + ld: ['file.ld', 'any/usr/lib/aarch64-xilinx-linux/ldscripts/aarch64elf32b.x'], ldif: ['file.ldif'], lean: ['file.lean'], ledger: ['file.ldg', 'file.ledger', 'file.journal'], @@ -383,7 +394,7 @@ def s:GetFilenameChecks(): dict<list<string>> limits: ['/etc/limits', '/etc/anylimits.conf', '/etc/anylimits.d/file.conf', '/etc/limits.conf', '/etc/limits.d/file.conf', '/etc/some-limits.conf', '/etc/some-limits.d/file.conf', 'any/etc/limits', 'any/etc/limits.conf', 'any/etc/limits.d/file.conf', 'any/etc/some-limits.conf', 'any/etc/some-limits.d/file.conf'], liquidsoap: ['file.liq'], liquid: ['file.liquid'], - lisp: ['file.lsp', 'file.lisp', 'file.asd', 'file.el', 'file.cl', '.emacs', '.sawfishrc', 'sbclrc', '.sbclrc'], + lisp: ['file.lsp', 'file.lisp', 'file.asd', 'file.el', 'file.cl', '.emacs', '.sawfishrc', 'sbclrc', '.sbclrc', 'file.stsg', 'any/local/share/supertux2/config'], lite: ['file.lite', 'file.lt'], litestep: ['/LiteStep/any/file.rc', 'any/LiteStep/any/file.rc'], logcheck: ['/etc/logcheck/file.d-some/file', '/etc/logcheck/file.d/file', 'any/etc/logcheck/file.d-some/file', 'any/etc/logcheck/file.d/file'], @@ -396,13 +407,13 @@ def s:GetFilenameChecks(): dict<list<string>> lpc: ['file.lpc', 'file.ulpc'], lsl: ['file.lsl'], lss: ['file.lss'], - lua: ['file.lua', 'file.rockspec', 'file.nse', '.luacheckrc', '.busted'], + lua: ['file.lua', 'file.tlu', 'file.rockspec', 'file.nse', '.lua_history', '.luacheckrc', '.busted', 'rock_manifest', 'config.ld'], luau: ['file.luau'], lynx: ['lynx.cfg'], lyrics: ['file.lrc'], m3build: ['m3makefile', 'm3overrides'], m3quake: ['file.quake', 'cm3.cfg'], - m4: ['file.at'], + m4: ['file.at', '.m4_history'], mail: ['snd.123', '.letter', '.letter.123', '.followup', '.article', '.article.123', 'pico.123', 'mutt-xx-xxx', 'muttng-xx-xxx', 'ae123.txt', 'file.eml', 'reportbug-file'], mailaliases: ['/etc/mail/aliases', '/etc/aliases', 'any/etc/aliases', 'any/etc/mail/aliases'], mailcap: ['.mailcap', 'mailcap'], @@ -466,6 +477,7 @@ def s:GetFilenameChecks(): dict<list<string>> msidl: ['file.odl', 'file.mof'], msql: ['file.msql'], mojo: ['file.mojo', 'file.🔥'], + msmtp: ['.msmtprc'], mupad: ['file.mu'], mush: ['file.mush'], mustache: ['file.mustache'], @@ -481,7 +493,7 @@ def s:GetFilenameChecks(): dict<list<string>> 'any/.muttng/muttrc', 'any/.muttng/muttrc-file', 'any/etc/Muttrc.d/file', 'muttngrc', 'muttngrc-file', 'muttrc', 'muttrc-file'], - mysql: ['file.mysql'], + mysql: ['file.mysql', '.mysql_history'], n1ql: ['file.n1ql', 'file.nql'], named: ['namedfile.conf', 'rndcfile.conf', 'named-file.conf', 'named.conf', 'rndc-file.conf', 'rndc-file.key', 'rndc.conf', 'rndc.key'], nanorc: ['/etc/nanorc', 'file.nanorc', 'any/etc/nanorc'], @@ -503,9 +515,10 @@ def s:GetFilenameChecks(): dict<list<string>> obse: ['file.obl', 'file.obse', 'file.oblivion', 'file.obscript'], ocaml: ['file.ml', 'file.mli', 'file.mll', 'file.mly', '.ocamlinit', 'file.mlt', 'file.mlp', 'file.mlip', 'file.mli.cppo', 'file.ml.cppo'], occam: ['file.occ'], - octave: ['octaverc', '.octaverc', 'octave.conf'], + octave: ['octaverc', '.octaverc', 'octave.conf', 'any/.local/share/octave/history'], odin: ['file.odin'], omnimark: ['file.xom', 'file.xin'], + ondir: ['.ondirrc'], opam: ['opam', 'file.opam', 'file.opam.template'], openroad: ['file.or'], openscad: ['file.scad'], @@ -516,10 +529,11 @@ def s:GetFilenameChecks(): dict<list<string>> pacmanlog: ['pacman.log'], pamconf: ['/etc/pam.conf', '/etc/pam.d/file', 'any/etc/pam.conf', 'any/etc/pam.d/file'], pamenv: ['/etc/security/pam_env.conf', '/home/user/.pam_environment', '.pam_environment', 'pam_env.conf'], + pandoc: ['file.pandoc', 'file.pdk', 'file.pd', 'file.pdc'], papp: ['file.papp', 'file.pxml', 'file.pxsl'], pascal: ['file.pas', 'file.dpr', 'file.lpr'], passwd: ['any/etc/passwd', 'any/etc/passwd-', 'any/etc/passwd.edit', 'any/etc/shadow', 'any/etc/shadow-', 'any/etc/shadow.edit', 'any/var/backups/passwd.bak', 'any/var/backups/shadow.bak', '/etc/passwd', '/etc/passwd-', '/etc/passwd.edit', '/etc/shadow', '/etc/shadow-', '/etc/shadow.edit', '/var/backups/passwd.bak', '/var/backups/shadow.bak'], - pbtxt: ['file.pbtxt'], + pbtxt: ['file.txtpb', 'file.textproto', 'file.textpb', 'file.pbtxt'], pccts: ['file.g'], pcmk: ['file.pcmk'], pdf: ['file.pdf'], @@ -563,13 +577,13 @@ def s:GetFilenameChecks(): dict<list<string>> pymanifest: ['MANIFEST.in'], pyret: ['file.arr'], pyrex: ['file.pyx', 'file.pxd'], - python: ['file.py', 'file.pyw', '.pythonstartup', '.pythonrc', 'file.ptl', 'file.pyi', 'SConstruct'], + python: ['file.py', 'file.pyw', '.pythonstartup', '.pythonrc', '.python_history', '.jline-jython.history', 'file.ptl', 'file.pyi', 'SConstruct'], ql: ['file.ql', 'file.qll'], qml: ['file.qml', 'file.qbs'], qmldir: ['qmldir'], quake: ['anybaseq2/file.cfg', 'anyid1/file.cfg', 'quake3/file.cfg', 'baseq2/file.cfg', 'id1/file.cfg', 'quake1/file.cfg', 'some-baseq2/file.cfg', 'some-id1/file.cfg', 'some-quake1/file.cfg'], quarto: ['file.qmd'], - r: ['file.r', '.Rprofile', 'Rprofile', 'Rprofile.site'], + r: ['file.r', '.Rhistory', '.Rprofile', 'Rprofile', 'Rprofile.site'], racket: ['file.rkt', 'file.rktd', 'file.rktl'], radiance: ['file.rad', 'file.mat'], raku: ['file.pm6', 'file.p6', 'file.t6', 'file.pod6', 'file.raku', 'file.rakumod', 'file.rakudoc', 'file.rakutest'], @@ -581,7 +595,7 @@ def s:GetFilenameChecks(): dict<list<string>> readline: ['.inputrc', 'inputrc'], rego: ['file.rego'], remind: ['.reminders', 'file.remind', 'file.rem', '.reminders-file'], - requirements: ['file.pip', 'requirements.txt'], + requirements: ['file.pip', 'requirements.txt', 'dev-requirements.txt', 'constraints.txt', 'requirements.in', 'requirements/dev.txt', 'requires/dev.txt'], rescript: ['file.res', 'file.resi'], resolv: ['resolv.conf'], reva: ['file.frt'], @@ -595,6 +609,7 @@ def s:GetFilenameChecks(): dict<list<string>> rpgle: ['file.rpgle', 'file.rpgleinc'], robot: ['file.robot', 'file.resource'], robots: ['robots.txt'], + roc: ['file.roc'], ron: ['file.ron'], routeros: ['file.rsc'], rpcgen: ['file.x'], @@ -602,7 +617,7 @@ def s:GetFilenameChecks(): dict<list<string>> rrst: ['file.rrst', 'file.srst'], rst: ['file.rst'], rtf: ['file.rtf'], - ruby: ['.irbrc', 'irbrc', 'file.rb', 'file.rbw', 'file.gemspec', 'file.ru', 'Gemfile', 'file.builder', 'file.rxml', 'file.rjs', 'file.rant', 'file.rake', 'rakefile', 'Rakefile', 'rantfile', 'Rantfile', 'rakefile-file', 'Rakefile-file', 'Puppetfile', 'Vagrantfile'], + ruby: ['.irbrc', 'irbrc', '.irb_history', 'irb_history', 'file.rb', 'file.rbw', 'file.gemspec', 'file.ru', 'Gemfile', 'file.builder', 'file.rxml', 'file.rjs', 'file.rant', 'file.rake', 'rakefile', 'Rakefile', 'rantfile', 'Rantfile', 'rakefile-file', 'Rakefile-file', 'Puppetfile', 'Vagrantfile'], rust: ['file.rs'], samba: ['smb.conf'], sas: ['file.sas'], @@ -622,7 +637,10 @@ def s:GetFilenameChecks(): dict<list<string>> services: ['/etc/services', 'any/etc/services'], setserial: ['/etc/serial.conf', 'any/etc/serial.conf'], sexplib: ['file.sexp'], - sh: ['.bashrc', '.bash_profile', '.bash-profile', '.bash_logout', '.bash-logout', '.bash_aliases', '.bash-aliases', '/tmp/bash-fc-3Ozjlw', '/tmp/bash-fc.3Ozjlw', 'PKGBUILD', 'APKBUILD', 'file.bash', '/usr/share/doc/bash-completion/filter.sh', '/etc/udev/cdsymlinks.conf', 'any/etc/udev/cdsymlinks.conf', 'file.bats'], + sh: ['.bashrc', '.bash_profile', '.bash-profile', '.bash_logout', '.bash-logout', '.bash_aliases', '.bash-aliases', '.bash_history', '.bash-history', + '/tmp/bash-fc-3Ozjlw', '/tmp/bash-fc.3Ozjlw', 'PKGBUILD', 'APKBUILD', 'file.bash', '/usr/share/doc/bash-completion/filter.sh', + '/etc/udev/cdsymlinks.conf', 'any/etc/udev/cdsymlinks.conf', 'file.bats', '.ash_history', 'any/etc/neofetch/config.conf', '.xprofile', + 'user-dirs.defaults', 'user-dirs.dirs', 'makepkg.conf', '.makepkg.conf'], sieve: ['file.siv', 'file.sieve'], sil: ['file.sil'], simula: ['file.sim'], @@ -653,7 +671,7 @@ def s:GetFilenameChecks(): dict<list<string>> spice: ['file.sp', 'file.spice'], spup: ['file.speedup', 'file.spdata', 'file.spd'], spyce: ['file.spy', 'file.spi'], - sql: ['file.tyb', 'file.tyc', 'file.pkb', 'file.pks'], + sql: ['file.tyb', 'file.tyc', 'file.pkb', 'file.pks', '.sqlite_history'], sqlj: ['file.sqlj'], prql: ['file.prql'], sqr: ['file.sqr', 'file.sqi'], @@ -725,14 +743,14 @@ def s:GetFilenameChecks(): dict<list<string>> tal: ['file.tal'], taskdata: ['pending.data', 'completed.data', 'undo.data'], taskedit: ['file.task'], - tcl: ['file.tcl', 'file.tm', 'file.tk', 'file.itcl', 'file.itk', 'file.jacl', '.tclshrc', 'tclsh.rc', '.wishrc'], + tcl: ['file.tcl', 'file.tm', 'file.tk', 'file.itcl', 'file.itk', 'file.jacl', '.tclshrc', 'tclsh.rc', '.wishrc', '.tclsh-history', '.xsctcmdhistory', '.xsdbcmdhistory'], tablegen: ['file.td'], teal: ['file.tl'], template: ['file.tmpl'], teraterm: ['file.ttl'], terminfo: ['file.ti'], 'terraform-vars': ['file.tfvars'], - tex: ['file.latex', 'file.sty', 'file.dtx', 'file.ltx', 'file.bbl'], + tex: ['file.latex', 'file.sty', 'file.dtx', 'file.ltx', 'file.bbl', 'any/.texlive/texmf-config/tex/latex/file/file.cfg', 'file.pgf', 'file.nlo', 'file.nls', 'file.out', 'file.thm', 'file.eps_tex', 'file.pygtex', 'file.pygstyle', 'file.clo', 'file.aux', 'file.brf', 'file.ind', 'file.lof', 'file.loe', 'file.nav', 'file.vrb', 'file.ins', 'file.tikz', 'file.bbx', 'file.cbx', 'file.beamer'], texinfo: ['file.texinfo', 'file.texi', 'file.txi'], texmf: ['texmf.cnf'], text: ['file.text', 'file.txt', 'README', 'LICENSE', 'COPYING', 'AUTHORS', '/usr/share/doc/bash-completion/AUTHORS', '/etc/apt/apt.conf.d/README', '/etc/Muttrc.d/README'], @@ -743,7 +761,7 @@ def s:GetFilenameChecks(): dict<list<string>> tla: ['file.tla'], tli: ['file.tli'], tmux: ['tmuxfile.conf', '.tmuxfile.conf', '.tmux-file.conf', '.tmux.conf', 'tmux-file.conf', 'tmux.conf', 'tmux.conf.local'], - toml: ['file.toml', 'Gopkg.lock', 'Pipfile', '/home/user/.cargo/config'], + toml: ['file.toml', 'Gopkg.lock', 'Pipfile', '/home/user/.cargo/config', '.black'], tpp: ['file.tpp'], treetop: ['file.treetop'], trustees: ['trustees.conf'], @@ -753,9 +771,10 @@ def s:GetFilenameChecks(): dict<list<string>> tssop: ['file.tssop'], tsv: ['file.tsv'], twig: ['file.twig'], - typescript: ['file.mts', 'file.cts'], + typescript: ['file.mts', 'file.cts', '.ts_node_repl_history'], 'typescript.glimmer': ['file.gts'], typescriptreact: ['file.tsx'], + typespec: ['file.tsp'], ungrammar: ['file.ungram'], uc: ['file.uc'], udevconf: ['/etc/udev/udev.conf', 'any/etc/udev/udev.conf'], @@ -785,7 +804,7 @@ def s:GetFilenameChecks(): dict<list<string>> vgrindefs: ['vgrindefs'], vhdl: ['file.hdl', 'file.vhd', 'file.vhdl', 'file.vbe', 'file.vst', 'file.vhdl_123', 'file.vho', 'some.vhdl_1', 'some.vhdl_1-file'], vhs: ['file.tape'], - vim: ['file.vim', '.exrc', '_exrc', 'some-vimrc', 'some-vimrc-file', 'vimrc', 'vimrc-file'], + vim: ['file.vim', '.exrc', '_exrc', 'some-vimrc', 'some-vimrc-file', 'vimrc', 'vimrc-file', '.netrwhist'], viminfo: ['.viminfo', '_viminfo'], vmasm: ['file.mar'], voscm: ['file.cm'], @@ -811,7 +830,7 @@ def s:GetFilenameChecks(): dict<list<string>> xinetd: ['/etc/xinetd.conf', '/etc/xinetd.d/file', 'any/etc/xinetd.conf', 'any/etc/xinetd.d/file'], xkb: ['/usr/share/X11/xkb/compat/pc', '/usr/share/X11/xkb/geometry/pc', '/usr/share/X11/xkb/keycodes/evdev', '/usr/share/X11/xkb/symbols/pc', '/usr/share/X11/xkb/types/pc'], xmath: ['file.msc', 'file.msf'], - xml: ['/etc/blkid.tab', '/etc/blkid.tab.old', 'file.xmi', 'file.csproj', 'file.csproj.user', 'file.fsproj', 'file.fsproj.user', 'file.vbproj', 'file.vbproj.user', 'file.ui', 'file.tpm', '/etc/xdg/menus/file.menu', 'fglrxrc', 'file.xlf', 'file.xliff', 'file.xul', 'file.wsdl', 'file.wpl', 'any/etc/blkid.tab', 'any/etc/blkid.tab.old', 'any/etc/xdg/menus/file.menu', 'file.atom', 'file.rss', 'file.cdxml', 'file.psc1', 'file.mpd'], + xml: ['/etc/blkid.tab', '/etc/blkid.tab.old', 'file.xmi', 'file.csproj', 'file.csproj.user', 'file.fsproj', 'file.fsproj.user', 'file.vbproj', 'file.vbproj.user', 'file.ui', 'file.tpm', '/etc/xdg/menus/file.menu', 'fglrxrc', 'file.xlf', 'file.xliff', 'file.xul', 'file.wsdl', 'file.wpl', 'any/etc/blkid.tab', 'any/etc/blkid.tab.old', 'any/etc/xdg/menus/file.menu', 'file.atom', 'file.rss', 'file.cdxml', 'file.psc1', 'file.mpd', 'fonts.conf', 'file.xcu', 'file.xlb', 'file.xlc', 'file.xba', 'file.xpr', 'file.xpfm', 'file.spfm', 'file.bxml'], xmodmap: ['anyXmodmap', 'Xmodmap', 'some-Xmodmap', 'some-xmodmap', 'some-xmodmap-file', 'xmodmap', 'xmodmap-file'], xpm: ['file.xpm'], xpm2: ['file.xpm2'], @@ -820,16 +839,17 @@ def s:GetFilenameChecks(): dict<list<string>> xsd: ['file.xsd'], xslt: ['file.xsl', 'file.xslt'], yacc: ['file.yy', 'file.yxx', 'file.y++'], - yaml: ['file.yaml', 'file.yml', 'file.eyaml', '.clangd', '.clang-format', '.clang-tidy'], + yaml: ['file.yaml', 'file.yml', 'file.eyaml', 'any/.bundle/config', '.clangd', '.clang-format', '.clang-tidy', 'file.mplstyle', 'matplotlibrc', 'yarn.lock'], yang: ['file.yang'], yuck: ['file.yuck'], z8a: ['file.z8a'], + zathurarc: ['zathurarc'], zig: ['file.zig', 'build.zig.zon'], zimbu: ['file.zu'], zimbutempl: ['file.zut'], zserio: ['file.zs'], - zsh: ['.zprofile', '/etc/zprofile', '.zfbfmarks', 'file.zsh', - '.zcompdump', '.zlogin', '.zlogout', '.zshenv', '.zshrc', + zsh: ['.zprofile', '/etc/zprofile', '.zfbfmarks', 'file.zsh', 'file.zsh-theme', 'file.zunit', + '.zcompdump', '.zlogin', '.zlogout', '.zshenv', '.zshrc', '.zsh_history', '.zcompdump-file', '.zlog', '.zlog-file', '.zsh', '.zsh-file', 'any/etc/zprofile', 'zlog', 'zlog-file', 'zsh', 'zsh-file'], @@ -2422,4 +2442,26 @@ func Test_def_file() filetype off endfunc +func Test_uci_file() + filetype on + + call mkdir('any/etc/config', 'pR') + call writefile(['config firewall'], 'any/etc/config/firewall', 'D') + split any/etc/config/firewall + call assert_equal('uci', &filetype) + bwipe! + + call writefile(['# config for nginx here'], 'any/etc/config/firewall', 'D') + split any/etc/config/firewall + call assert_notequal('uci', &filetype) + bwipe! + + call writefile(['# Copyright Cool Cats 1997', 'config firewall'], 'any/etc/config/firewall', 'D') + split any/etc/config/firewall + call assert_equal('uci', &filetype) + bwipe! + + filetype off +endfunc + " vim: shiftwidth=2 sts=2 expandtab diff --git a/src/testdir/test_functions.vim b/src/testdir/test_functions.vim index fecebc4..f0d7385 100644 --- a/src/testdir/test_functions.vim +++ b/src/testdir/test_functions.vim @@ -3794,6 +3794,43 @@ func Test_funcref_to_string() call assert_equal("function('g:Test_funcref_to_string')", string(Fn)) endfunc +" A funcref cannot start with an underscore (except when used as a protected +" class or object variable) +func Test_funcref_with_underscore() + " at script level + let lines =<< trim END + vim9script + var _Fn = () => 10 + END + call v9.CheckSourceFailure(lines, 'E704: Funcref variable name must start with a capital: _Fn') + + " inside a function + let lines =<< trim END + vim9script + def Func() + var _Fn = () => 10 + enddef + defcompile + END + call v9.CheckSourceFailure(lines, 'E704: Funcref variable name must start with a capital: _Fn', 1) + + " as a function argument + let lines =<< trim END + vim9script + def Func(_Fn: func) + enddef + defcompile + END + call v9.CheckSourceFailure(lines, 'E704: Funcref variable name must start with a capital: _Fn', 2) + + " as a lambda argument + let lines =<< trim END + vim9script + var Fn = (_Farg: func) => 10 + END + call v9.CheckSourceFailure(lines, 'E704: Funcref variable name must start with a capital: _Farg', 2) +endfunc + " Test for isabsolutepath() func Test_isabsolutepath() call assert_false(isabsolutepath('')) diff --git a/src/testdir/test_highlight.vim b/src/testdir/test_highlight.vim index d6c9f50..9bc5f12 100644 --- a/src/testdir/test_highlight.vim +++ b/src/testdir/test_highlight.vim @@ -856,6 +856,15 @@ func Test_highlight_User() hi clear endfunc +" Test for MsgArea highlighting +func Test_highlight_MsgArea() + CheckNotGui + hi MsgArea ctermfg=20 + redraw! + call assert_equal('20', synIDattr(synIDtrans(hlID('MsgArea')), 'fg')) + hi clear +endfunc + " Test for using RGB color values in a highlight group func Test_xxlast_highlight_RGB_color() CheckCanRunGui diff --git a/src/testdir/test_history.vim b/src/testdir/test_history.vim index 482328a..19490f2 100644 --- a/src/testdir/test_history.vim +++ b/src/testdir/test_history.vim @@ -254,7 +254,7 @@ func Test_history_crypt_key() set key& bs& ts& endfunc -" The following used to overflow and causing an use-after-free +" The following used to overflow and causing a use-after-free func Test_history_max_val() set history=10 diff --git a/src/testdir/test_ins_complete.vim b/src/testdir/test_ins_complete.vim index 52306e8..eb89a15 100644 --- a/src/testdir/test_ins_complete.vim +++ b/src/testdir/test_ins_complete.vim @@ -1130,7 +1130,7 @@ func Test_complete_wholeline_unlistedbuf() edit Xfile1 enew set complete=U - " completing from a unloaded buffer should fail + " completing from an unloaded buffer should fail exe "normal! ia\<C-X>\<C-L>\<C-P>" call assert_equal('a', getline(1)) %d @@ -2429,4 +2429,26 @@ func Test_complete_changed_complete_info() call StopVimInTerminal(buf) endfunc +func Test_completefunc_first_call_complete_add() + new + + func Complete(findstart, base) abort + if a:findstart + let col = col('.') + call complete_add('#') + return col - 1 + else + return [] + endif + endfunc + + set completeopt=longest completefunc=Complete + " This used to cause heap-buffer-overflow + call assert_fails('call feedkeys("ifoo#\<C-X>\<C-U>", "xt")', 'E840:') + + delfunc Complete + set completeopt& completefunc& + bwipe! +endfunc + " vim: shiftwidth=2 sts=2 expandtab nofoldenable diff --git a/src/testdir/test_let.vim b/src/testdir/test_let.vim index c99207c..2aba1d3 100644 --- a/src/testdir/test_let.vim +++ b/src/testdir/test_let.vim @@ -396,6 +396,45 @@ func Test_let_heredoc_fails() call assert_report('Caught exception: ' .. v:exception) endtry + try + let @- =<< trim TEXT + change + insert + append + TEXT + call assert_report('No exception thrown') + catch /E730:/ + catch + call assert_report('Caught exception: ' .. v:exception) + endtry + + try + let [] =<< trim TEXT + TEXT + call assert_report('No exception thrown') + catch /E475:/ + catch + call assert_report('Caught exception: ' .. v:exception) + endtry + + try + let [a b c] =<< trim TEXT + TEXT + call assert_report('No exception thrown') + catch /E475:/ + catch + call assert_report('Caught exception: ' .. v:exception) + endtry + + try + let [a; b; c] =<< trim TEXT + TEXT + call assert_report('No exception thrown') + catch /E452:/ + catch + call assert_report('Caught exception: ' .. v:exception) + endtry + let text =<< trim END func WrongSyntax() let v =<< that there @@ -497,6 +536,13 @@ END XX call assert_equal(['Line1'], var1) + let var1 =<< trim XX " comment + Line1 + Line2 + Line3 + XX + call assert_equal(['Line1', ' Line2', 'Line3'], var1) + " ignore "endfunc" let var1 =<< END something @@ -571,6 +617,22 @@ append END call assert_equal(['change', 'insert', 'append'], [a, b, c]) + " unpack assignment with semicolon + let [a; b] =<< END +change +insert +append +END + call assert_equal(['change', ['insert', 'append']], [a, b]) + + " unpack assignment with registers + let [@/, @", @-] =<< END +change +insert +append +END + call assert_equal(['change', 'insert', 'append'], [@/, @", @-]) + " curly braces name and list slice assignment let foo_3_bar = ['', '', ''] let foo_{1 + 2}_bar[ : ] =<< END @@ -627,6 +689,48 @@ END END call assert_equal(['let a = {abc}', 'let b = X', 'let c = {'], code) + " Evaluate a dictionary + let d1 = #{a: 10, b: 'ss', c: {}} + let code =<< eval trim END + let d2 = {d1} + END + call assert_equal(["let d2 = {'a': 10, 'b': 'ss', 'c': {}}"], code) + + " Empty dictionary + let d1 = {} + let code =<< eval trim END + let d2 = {d1} + END + call assert_equal(["let d2 = {}"], code) + + " null dictionary + let d1 = test_null_dict() + let code =<< eval trim END + let d2 = {d1} + END + call assert_equal(["let d2 = {}"], code) + + " Evaluate a List + let l1 = ['a', 'b', 'c'] + let code =<< eval trim END + let l2 = {l1} + END + call assert_equal(["let l2 = ['a', 'b', 'c']"], code) + + " Empty List + let l1 = [] + let code =<< eval trim END + let l2 = {l1} + END + call assert_equal(["let l2 = []"], code) + + " Null List + let l1 = test_null_list() + let code =<< eval trim END + let l2 = {l1} + END + call assert_equal(["let l2 = []"], code) + let code = 'xxx' let code =<< eval trim END let n = {5 + @@ -660,6 +764,34 @@ END LINES call v9.CheckScriptFailure(lines, 'E15:') + " Test for using heredoc in a single string using :execute or execute() + for [cmd, res] in items({ + \ "let x =<< trim END\n one\n two\nEND": ['one', 'two'], + \ "let x =<< trim END\n one\n two\nEND": ['one', ' two'], + \ " let x =<< trim END\n one\n two\n END": ['one', 'two'], + \ " let x =<< trim END\n one\n two\n END": ['one', ' two'], + \ "let x =<< END\n one\n two\nEND": [' one', ' two'], + \ "let x =<< END\none\ntwo\nEND": ['one', 'two'], + \ "let x =<< END \" comment\none\ntwo\nEND": ['one', 'two'], + \ }) + execute cmd + call assert_equal(res, x) + unlet x + call assert_equal($"\n{string(res)}", execute($"{cmd}\necho x")) + unlet x + endfor + for [cmd, err] in items({ + \ "let x =<<\none\ntwo": "E172:", + \ "let x =<< trim\n one\n two": "E172:", + \ "let x =<< end\none\ntwo\nend": "E221:", + \ "let x =<< END\none\ntwo": "E990: Missing end marker 'END'", + \ "let x =<< END !\none\ntwo\nEND": "E488: Trailing characters: !", + \ "let x =<< eval END\none\ntwo{y}\nEND": "E121: Undefined variable: y", + \ }) + call assert_fails('execute cmd', err) + call assert_fails('call execute(cmd)', err) + endfor + " skipped heredoc if 0 let msg =<< trim eval END diff --git a/src/testdir/test_listdict.vim b/src/testdir/test_listdict.vim index 8b2c27a..4c69476 100644 --- a/src/testdir/test_listdict.vim +++ b/src/testdir/test_listdict.vim @@ -1530,4 +1530,10 @@ func Test_indexof() delfunc TestIdx endfunc +func Test_extendnew_leak() + " This used to leak memory + for i in range(100) | silent! call extendnew([], [], []) | endfor + for i in range(100) | silent! call extendnew({}, {}, {}) | endfor +endfunc + " vim: shiftwidth=2 sts=2 expandtab diff --git a/src/testdir/test_mapping.vim b/src/testdir/test_mapping.vim index 71d9046..1175310 100644 --- a/src/testdir/test_mapping.vim +++ b/src/testdir/test_mapping.vim @@ -248,21 +248,25 @@ func Test_map_meta_multibyte() endfunc func Test_map_super_quotes() - if has('gui_gtk') || has('gui_gtk3') || has("macos") - imap <D-"> foo - call feedkeys("Go-\<*D-\">-\<Esc>", "xt") - call assert_equal("-foo-", getline('$')) - set nomodified - iunmap <D-"> + if "\<D-j>"[-1:] == '>' + throw 'Skipped: <D- modifier not supported' endif + + imap <D-"> foo + call feedkeys("Go-\<*D-\">-\<Esc>", "xt") + call assert_equal("-foo-", getline('$')) + set nomodified + iunmap <D-"> endfunc func Test_map_super_multibyte() - if has('gui_gtk') || has('gui_gtk3') || has("macos") - imap <D-á> foo - call assert_match('i <D-á>\s*foo', execute('imap')) - iunmap <D-á> + if "\<D-j>"[-1:] == '>' + throw 'Skipped: <D- modifier not supported' endif + + imap <D-á> foo + call assert_match('i <D-á>\s*foo', execute('imap')) + iunmap <D-á> endfunc func Test_abbr_after_line_join() @@ -1807,6 +1811,49 @@ func Test_map_after_timed_out_nop() call StopVimInTerminal(buf) endfunc +" Test 'showcmd' behavior with a partial mapping +func Test_showcmd_part_map() + CheckRunVimInTerminal + + let lines =<< trim END + set notimeout showcmd + nnoremap ,a <Ignore> + nnoremap ;a <Ignore> + nnoremap Àa <Ignore> + nnoremap Ëa <Ignore> + nnoremap βa <Ignore> + nnoremap ωa <Ignore> + nnoremap …a <Ignore> + nnoremap <C-W>a <Ignore> + END + call writefile(lines, 'Xtest_showcmd_part_map', 'D') + let buf = RunVimInTerminal('-S Xtest_showcmd_part_map', #{rows: 6}) + + call term_sendkeys(buf, ":set noruler | echo\<CR>") + call WaitForAssert({-> assert_equal('', term_getline(buf, 6))}) + + for c in [',', ';', 'À', 'Ë', 'β', 'ω', '…'] + call term_sendkeys(buf, c) + call WaitForAssert({-> assert_equal(c, trim(term_getline(buf, 6)))}) + call term_sendkeys(buf, 'a') + call WaitForAssert({-> assert_equal('', trim(term_getline(buf, 6)))}) + endfor + + call term_sendkeys(buf, "\<C-W>") + call WaitForAssert({-> assert_equal('^W', trim(term_getline(buf, 6)))}) + call term_sendkeys(buf, 'a') + call WaitForAssert({-> assert_equal('', trim(term_getline(buf, 6)))}) + + " Use feedkeys() as terminal buffer cannot forward unsimplified Ctrl-W. + " This is like typing Ctrl-W with modifyOtherKeys enabled. + call term_sendkeys(buf, ':call feedkeys("\<*C-W>", "m")' .. " | echo\<CR>") + call WaitForAssert({-> assert_equal('^W', trim(term_getline(buf, 6)))}) + call term_sendkeys(buf, 'a') + call WaitForAssert({-> assert_equal('', trim(term_getline(buf, 6)))}) + + call StopVimInTerminal(buf) +endfunc + func Test_using_past_typeahead() nnoremap :00 0 exe "norm :set \x80\xfb0=0\<CR>" diff --git a/src/testdir/test_match.vim b/src/testdir/test_match.vim index 1896158..eb77791 100644 --- a/src/testdir/test_match.vim +++ b/src/testdir/test_match.vim @@ -307,6 +307,7 @@ func Test_matchaddpos_error() " Why doesn't the following error have an error code E...? call assert_fails("call matchaddpos('Error', [{}])", 'E290:') call assert_equal(-1, matchaddpos('Error', test_null_list())) + call assert_equal(-1, matchaddpos('Error', [])) call assert_fails("call matchaddpos('Error', [1], [], 1)", 'E745:') call assert_equal(-1, matchaddpos('Search', [[]])) call assert_fails("call matchaddpos('Search', [[{}]])", 'E728:') @@ -433,5 +434,4 @@ func Test_match_tab_with_linebreak() call StopVimInTerminal(buf) endfunc - " vim: shiftwidth=2 sts=2 expandtab diff --git a/src/testdir/test_mksession.vim b/src/testdir/test_mksession.vim index 78d301f..914d1e3 100644 --- a/src/testdir/test_mksession.vim +++ b/src/testdir/test_mksession.vim @@ -708,11 +708,11 @@ endfunc func Test_mkview_no_file_name() new - " :mkview or :mkview {nr} should fail in a unnamed buffer. + " :mkview or :mkview {nr} should fail in an unnamed buffer. call assert_fails('mkview', 'E32:') call assert_fails('mkview 1', 'E32:') - " :mkview {file} should succeed in a unnamed buffer. + " :mkview {file} should succeed in an unnamed buffer. mkview Xview help source Xview diff --git a/src/testdir/test_normal.vim b/src/testdir/test_normal.vim index b180637..4b7e5e6 100644 --- a/src/testdir/test_normal.vim +++ b/src/testdir/test_normal.vim @@ -130,7 +130,7 @@ func Test_normal01_keymodel() call assert_equal([0, 1, 1, 0], getpos("'<")) call assert_equal([0, 3, 1, 0], getpos("'>")) call feedkeys("Gz\<CR>8|\<S-PageUp>y", 'xt') - call assert_equal([0, 2, 1, 0], getpos("'<")) + call assert_equal([0, 3, 1, 0], getpos("'<")) call assert_equal([0, 3, 8, 0], getpos("'>")) " Test for <S-C-Home> and <S-C-End> call cursor(2, 12) @@ -912,12 +912,10 @@ func Test_normal14_page() set scrolloff=0 100 exe "norm! $\<c-b>" - call assert_equal('92', getline('.')) call assert_equal([0, 92, 1, 0, 1], getcurpos()) 100 set nostartofline exe "norm! $\<c-b>" - call assert_equal('92', getline('.')) call assert_equal([0, 92, 2, 0, v:maxcol], getcurpos()) " cleanup set startofline @@ -1284,7 +1282,7 @@ func Test_vert_scroll_cmds() exe "normal \<C-U>" call assert_equal(36, line('.')) exe "normal \<C-U>" - call assert_equal(10, line('.')) + call assert_equal(1, line('.')) exe "normal \<C-U>" call assert_equal(1, line('.')) set scroll& @@ -3815,8 +3813,8 @@ func Test_normal_vert_scroll_longline() call assert_equal(11, line('.')) call assert_equal(1, winline()) exe "normal \<C-B>" - call assert_equal(10, line('.')) - call assert_equal(3, winline()) + call assert_equal(11, line('.')) + call assert_equal(5, winline()) exe "normal \<C-B>\<C-B>" call assert_equal(5, line('.')) call assert_equal(5, winline()) @@ -4174,12 +4172,8 @@ endfunc " Test for { and } paragraph movements in a single line func Test_brace_single_line() - let text =<< trim [DATA] - foobar one two three - [DATA] - new - call setline(1, text) + call setline(1, ['foobar one two three']) 1 norm! 0} @@ -4189,4 +4183,81 @@ func Test_brace_single_line() bw! endfunc +" Test for Ctrl-B/Ctrl-U in buffer with a single line +func Test_single_line_scroll() + CheckFeature textprop + + new + call setline(1, ['foobar one two three']) + let vt = 'virt_above' + call prop_type_add(vt, {'highlight': 'IncSearch'}) + call prop_add(1, 0, {'type': vt, 'text': '---', 'text_align': 'above'}) + call cursor(1, 1) + + " Ctrl-B/Ctrl-U scroll up with hidden "above" virtual text. + set smoothscroll + exe "normal \<C-E>" + call assert_notequal(0, winsaveview().skipcol) + exe "normal \<C-B>" + call assert_equal(0, winsaveview().skipcol) + exe "normal \<C-E>" + call assert_notequal(0, winsaveview().skipcol) + exe "normal \<C-U>" + call assert_equal(0, winsaveview().skipcol) + + set smoothscroll& + bw! + call prop_type_delete(vt) +endfunc + +" Test for zb in buffer with a single line and filler lines +func Test_single_line_filler_zb() + call setline(1, ['', 'foobar one two three']) + diffthis + new + call setline(1, ['foobar one two three']) + diffthis + + " zb scrolls to reveal filler lines at the start of the buffer. + exe "normal \<C-E>zb" + call assert_equal(1, winsaveview().topfill) + + bw! +endfunc + +" Test for Ctrl-U not getting stuck at end of buffer with 'scrolloff'. +func Test_halfpage_scrolloff_eob() + set scrolloff=5 + + call setline(1, range(1, 100)) + exe "norm! Gzz\<C-U>zz" + call assert_notequal(100, line('.')) + + set scrolloff& + bwipe! +endfunc + +" Test for Ctrl-U/D moving the cursor at the buffer boundaries. +func Test_halfpage_cursor_startend() + call setline(1, range(1, 100)) + exe "norm! jztj\<C-U>" + call assert_equal(1, line('.')) + exe "norm! G\<C-Y>k\<C-D>" + call assert_equal(100, line('.')) + bwipe! +endfunc + +" Test for Ctrl-F/B moving the cursor to the window boundaries. +func Test_page_cursor_topbot() + 10new + call setline(1, range(1, 100)) + exe "norm! gg2\<C-F>" + call assert_equal(17, line('.')) + exe "norm! \<C-B>" + call assert_equal(18, line('.')) + exe "norm! \<C-B>\<C-F>" + call assert_equal(9, line('.')) + bwipe! +endfunc + " vim: shiftwidth=2 sts=2 expandtab nofoldenable diff --git a/src/testdir/test_put.vim b/src/testdir/test_put.vim index 5b5c354..69c2943 100644 --- a/src/testdir/test_put.vim +++ b/src/testdir/test_put.vim @@ -319,4 +319,21 @@ func Test_put_visual_replace_fold_marker() bwipe! endfunc +func Test_put_dict() + new + let d = #{a: #{b: 'abc'}, c: [1, 2], d: 0z10} + put! =d + call assert_equal(["{'a': {'b': 'abc'}, 'c': [1, 2], 'd': 0z10}", ''], + \ getline(1, '$')) + bw! +endfunc + +func Test_put_list() + new + let l = ['a', 'b', 'c'] + put! =l + call assert_equal(['a', 'b', 'c', ''], getline(1, '$')) + bw! +endfunc + " vim: shiftwidth=2 sts=2 expandtab diff --git a/src/testdir/test_recover.vim b/src/testdir/test_recover.vim index a084ef4..e85b2e9 100644 --- a/src/testdir/test_recover.vim +++ b/src/testdir/test_recover.vim @@ -380,7 +380,7 @@ func Test_recover_encrypted_swap_file() call delete('Xfile1') endfunc -" Test for :recover using a unreadable swap file +" Test for :recover using an unreadable swap file func Test_recover_unreadable_swap_file() CheckUnix CheckNotRoot diff --git a/src/testdir/test_regexp_latin.vim b/src/testdir/test_regexp_latin.vim index 9acb12b..63f093a 100644 --- a/src/testdir/test_regexp_latin.vim +++ b/src/testdir/test_regexp_latin.vim @@ -874,12 +874,26 @@ func Regex_Mark() %d endfunc +" Same test as above, but use verymagic +func Regex_Mark_Verymagic() + call append(0, ['', '', '', 'Marks:', 'asdfSasdfsadfEasdf', 'asdfSas', + \ 'dfsadfEasdf', '', '', '', '', '']) + call cursor(4, 1) + exe "normal jfSmsfEme:.-4,.+6s/\\v.%>'s.*%<'e../here/\<CR>" + exe "normal jfSmsj0fEme:.-4,.+6s/\\v.%>'s\\_.*%<'e../again/\<CR>" + call assert_equal(['', '', '', 'Marks:', 'asdfhereasdf', 'asdfagainasdf', + \ '', '', '', '', '', ''], getline(1, '$')) + %d +endfunc + func Test_matching_marks() new set regexpengine=1 call Regex_Mark() + call Regex_Mark_Verymagic() set regexpengine=2 call Regex_Mark() + call Regex_Mark_Verymagic() bwipe! endfunc diff --git a/src/testdir/test_regexp_utf8.vim b/src/testdir/test_regexp_utf8.vim index 6669dee..bc70544 100644 --- a/src/testdir/test_regexp_utf8.vim +++ b/src/testdir/test_regexp_utf8.vim @@ -342,7 +342,7 @@ func Test_multibyte_chars() endfunc " check that 'ambiwidth' does not change the meaning of \p -func Test_ambiwidth() +func Test_regexp_ambiwidth() set regexpengine=1 ambiwidth=single call assert_equal(0, match("\u00EC", '\p')) set regexpengine=1 ambiwidth=double diff --git a/src/testdir/test_registers.vim b/src/testdir/test_registers.vim index cb4cee7..b2261d4 100644 --- a/src/testdir/test_registers.vim +++ b/src/testdir/test_registers.vim @@ -209,6 +209,71 @@ func Test_recording_with_select_mode() bwipe! endfunc +func Run_test_recording_with_select_mode_utf8() + new + + " Test with different text lengths: 5, 7, 9, 11, 13, 15, to check that + " a character isn't split between two buffer blocks. + for s in ['12345', 'å£=å£', 'å£å£å£', 'å£=å£=å£', 'å£å£=å£å£', 'å£å£å£å£å£'] + " 0x80 is K_SPECIAL + " 0x9B is CSI + " 哦: 0xE5 0x93 0xA6 + " æ´›: 0xE6 0xB4 0x9B + " 固: 0xE5 0x9B 0xBA + " å››: 0xE5 0x9B 0x9B + " 最: 0xE6 0x9C 0x80 + " 倒: 0xE5 0x80 0x92 + " 倀: 0xE5 0x80 0x80 + for c in ['哦', 'æ´›', '固', 'å››', '最', '倒', '倀'] + call setline(1, 'asdf') + call feedkeys($"qacc{s}\<Esc>gH{c}\<Esc>q", "tx") + call assert_equal(c, getline(1)) + call assert_equal($"cc{s}\<Esc>gH{c}\<Esc>", @a) + call setline(1, 'asdf') + normal! @a + call assert_equal(c, getline(1)) + + " Test with Shift modifier. + let shift_c = eval($'"\<S-{c}>"') + call setline(1, 'asdf') + call feedkeys($"qacc{s}\<Esc>gH{shift_c}\<Esc>q", "tx") + call assert_equal(c, getline(1)) + call assert_equal($"cc{s}\<Esc>gH{shift_c}\<Esc>", @a) + call setline(1, 'asdf') + normal! @a + call assert_equal(c, getline(1)) + endfor + endfor + + bwipe! +endfunc + +func Test_recording_with_select_mode_utf8() + call Run_test_recording_with_select_mode_utf8() +endfunc + +" This must be done as one of the last tests, because it starts the GUI, which +" cannot be undone. +func Test_zz_recording_with_select_mode_utf8_gui() + CheckCanRunGui + + gui -f + call Run_test_recording_with_select_mode_utf8() +endfunc + +func Test_recording_with_super_mod() + if "\<D-j>"[-1:] == '>' + throw 'Skipped: <D- modifier not supported' + endif + + nnoremap <D-j> <Ignore> + let s = repeat("\<D-j>", 1000) + " This used to crash Vim + call feedkeys($'qr{s}q', 'tx') + call assert_equal(s, @r) + nunmap <D-j> +endfunc + " Test for executing the last used register (@) func Test_last_used_exec_reg() " Test for the @: command @@ -745,13 +810,13 @@ func Test_ve_blockpaste() call cursor(1,1) exe ":norm! \<C-V>3ljdP" call assert_equal(1, col('.')) - call assert_equal(getline(1, 2), ['QWERTZ', 'ASDFGH']) + call assert_equal(['QWERTZ', 'ASDFGH'], getline(1, 2)) call cursor(1,1) exe ":norm! \<C-V>3ljd" call cursor(1,1) norm! $3lP call assert_equal(5, col('.')) - call assert_equal(getline(1, 2), ['TZ QWER', 'GH ASDF']) + call assert_equal(['TZ QWER', 'GH ASDF'], getline(1, 2)) set ve&vim bwipe! endfunc diff --git a/src/testdir/test_remote.vim b/src/testdir/test_remote.vim index ae931fd..1475052 100644 --- a/src/testdir/test_remote.vim +++ b/src/testdir/test_remote.vim @@ -76,4 +76,49 @@ func Test_remote_servername() close endfunc +func Test_remote_servername_shellslash() + " Note this test does not currently run on Windows + " because: + " 1) we cannot run the gui version of Vim inside a terminal + " 2) Running Windows vim.exe inside a terminal would work, but is + " disabled because of the limited colors inside the default Windows + " console (see CanRunVimInTerminal in term_util.vim) + CheckRunVimInTerminal + CheckMSWindows + + " That is the file we want the server to open, + " despite the wildignore setting + call mkdir(expand('~/remote/'), 'pD') + call writefile(range(1, 20), expand('~/remote/XTEST.txt'), 'D') + " just a dummy file, so that the ':wq' further down is successful + call writefile(range(1, 20), 'Xdummy.log', 'D') + + " Run Vim in a terminal and open a terminal window to run Vim in. + let lines =<< trim END + set shellslash + cd ~/remote + END + call writefile(lines, 'XRemoteEditing1.vim', 'D') + let buf = RunVimInTerminal('--servername XVIMTEST -S XRemoteEditing1.vim Xdummy.log', {'rows': 10}) + call TermWait(buf) + + " wildignore setting should be ignored and the XVIMTEST server should now + " open XTEST.txt, if wildignore setting is not ignored, the server + " will continue with the Xdummy.log file + let buf2 = RunVimInTerminal('--servername XVIMTEST --remote-silent ~/remote/XTEST.txt', {'rows': 5, 'wait_for_ruler': 0}) + " job should be no-longer running, so we can just close it + exe buf2 .. 'bw!' + + call term_sendkeys(buf, ":pwd\<CR>") + call WaitForAssert({-> assert_match('remote/$', term_getline(buf, 10))}, 1000) + call TermWait(buf) + call term_sendkeys(buf, ":q!\<CR>") + call TermWait(buf) + if term_getstatus(buf) == 'running' + call StopVimInTerminal(buf) + endif + bw! + close +endfunc + " vim: shiftwidth=2 sts=2 expandtab diff --git a/src/testdir/test_scroll_opt.vim b/src/testdir/test_scroll_opt.vim index 3467760..cda9bf0 100644 --- a/src/testdir/test_scroll_opt.vim +++ b/src/testdir/test_scroll_opt.vim @@ -552,11 +552,11 @@ func Test_smoothscroll_cursor_position() " Test "g0/g<Home>" exe "normal gg\<C-E>" norm $gkg0 - call s:check_col_calc(1, 2, 21) + call s:check_col_calc(4, 1, 24) " Test moving the cursor behind the <<< display with 'virtualedit' set virtualedit=all - exe "normal \<C-E>3lgkh" + exe "normal \<C-E>gkh" call s:check_col_calc(3, 2, 23) set virtualedit& @@ -738,6 +738,7 @@ func Test_smoothscroll_mouse_pos() let &mouse = save_mouse let &term = save_term let &ttymouse = save_ttymouse + bwipe! endfunc " this was dividing by zero @@ -829,7 +830,7 @@ func Test_smoothscroll_eob() call VerifyScreenDump(buf, 'Test_smooth_eob_1', {}) " cursor is not placed below window - call term_sendkeys(buf, ":call setline(92, 'a'->repeat(100))\<CR>\<C-B>G") + call term_sendkeys(buf, ":call setline(92, 'a'->repeat(100))\<CR>\<C-L>\<C-B>G") call VerifyScreenDump(buf, 'Test_smooth_eob_2', {}) call StopVimInTerminal(buf) @@ -998,4 +999,113 @@ func Test_smoothscroll_textoff_small_winwidth() set smoothscroll& number& endfunc +func Test_smoothscroll_page() + call NewWindow(10, 40) + setlocal smoothscroll + call setline(1, 'abcde '->repeat(150)) + + exe "norm! \<C-F>" + call assert_equal(400, winsaveview().skipcol) + exe "norm! \<C-F>" + call assert_equal(800, winsaveview().skipcol) + exe "norm! \<C-F>" + call assert_equal(880, winsaveview().skipcol) + exe "norm! \<C-B>" + call assert_equal(480, winsaveview().skipcol) + exe "norm! \<C-B>" + call assert_equal(80, winsaveview().skipcol) + exe "norm! \<C-B>" + call assert_equal(0, winsaveview().skipcol) + + " Half-page scrolling does not go beyond end of buffer and moves the cursor. + " Even with 'nostartofline', the correct amount of lines is scrolled. + setl nostartofline + exe "norm! 15|\<C-D>" + call assert_equal(200, winsaveview().skipcol) + call assert_equal(215, col('.')) + exe "norm! \<C-D>" + call assert_equal(400, winsaveview().skipcol) + call assert_equal(415, col('.')) + exe "norm! \<C-D>" + call assert_equal(520, winsaveview().skipcol) + call assert_equal(615, col('.')) + exe "norm! \<C-D>" + call assert_equal(520, winsaveview().skipcol) + call assert_equal(815, col('.')) + exe "norm! \<C-D>" + call assert_equal(520, winsaveview().skipcol) + call assert_equal(895, col('.')) + exe "norm! \<C-U>" + call assert_equal(320, winsaveview().skipcol) + call assert_equal(695, col('.')) + exe "norm! \<C-U>" + call assert_equal(120, winsaveview().skipcol) + call assert_equal(495, col('.')) + exe "norm! \<C-U>" + call assert_equal(0, winsaveview().skipcol) + call assert_equal(295, col('.')) + exe "norm! \<C-U>" + call assert_equal(0, winsaveview().skipcol) + call assert_equal(95, col('.')) + exe "norm! \<C-U>" + call assert_equal(0, winsaveview().skipcol) + call assert_equal(15, col('.')) + + bwipe! +endfunc + +func Test_smoothscroll_next_topline() + call NewWindow(10, 40) + setlocal smoothscroll + call setline(1, ['abcde '->repeat(150)]->repeat(2)) + + " Scrolling a screenline that causes the cursor to move to the next buffer + " line should not skip part of that line to bring the cursor into view. + exe "norm! 22\<C-E>" + call assert_equal(880, winsaveview().skipcol) + exe "norm! \<C-E>" + redraw + call assert_equal(0, winsaveview().skipcol) + + " Also when scrolling back. + exe "norm! G\<C-Y>" + redraw + call assert_equal(880, winsaveview().skipcol) + + " Cursor in correct place when not in the first screenline of a buffer line. + exe "norm! gg4gj20\<C-D>\<C-D>" + redraw + call assert_equal(2, line('w0')) + + " Cursor does not end up above topline, adjusting topline later. + setlocal nu cpo+=n + exe "norm! G$g013\<C-Y>" + redraw + call assert_equal(2, line('.')) + call assert_equal(0, winsaveview().skipcol) + + set cpo-=n + bwipe! +endfunc + +func Test_smoothscroll_long_line_zb() + call NewWindow(10, 40) + call setline(1, 'abcde '->repeat(150)) + + " Also works without 'smoothscroll' when last line of buffer doesn't fit. + " Used to set topline to buffer line count plus one, causing an empty screen. + norm zb + redraw + call assert_equal(1, winsaveview().topline) + + " Moving cursor to bottom works on line that doesn't fit with 'smoothscroll'. + " Skipcol was adjusted later for cursor being on not visible part of line. + setlocal smoothscroll + norm zb + redraw + call assert_equal(520, winsaveview().skipcol) + + bwipe! +endfunc + " vim: shiftwidth=2 sts=2 expandtab diff --git a/src/testdir/test_sound.vim b/src/testdir/test_sound.vim index e97ac61..401753e 100644 --- a/src/testdir/test_sound.vim +++ b/src/testdir/test_sound.vim @@ -15,6 +15,7 @@ func Test_play_event() if has('win32') throw 'Skipped: Playing event with callback is not supported on Windows' endif + let g:result = 0 let g:playcallback_count = 0 let g:id = 0 let event_name = 'bell' @@ -37,6 +38,7 @@ endfunc func Test_play_silent() let fname = fnamemodify('silent.wav', '%p') let g:playcallback_count = 0 + let g:result = -1 " play without callback let id1 = sound_playfile(fname) diff --git a/src/testdir/test_tabpage.vim b/src/testdir/test_tabpage.vim index a531f19..3624790 100644 --- a/src/testdir/test_tabpage.vim +++ b/src/testdir/test_tabpage.vim @@ -117,10 +117,16 @@ function Test_tabpage() call assert_equal(3, tabpagenr()) +3tabmove call assert_equal(6, tabpagenr()) + silent -tabmove + call assert_equal(5, tabpagenr()) + silent -2 tabmove + call assert_equal(3, tabpagenr()) + silent -2 tabmove + call assert_equal(1, tabpagenr()) - " The following are a no-op norm! 2gt call assert_equal(2, tabpagenr()) + " The following are a no-op tabmove 2 call assert_equal(2, tabpagenr()) 2tabmove diff --git a/src/testdir/test_taglist.vim b/src/testdir/test_taglist.vim index 39e78bc..2dd2366 100644 --- a/src/testdir/test_taglist.vim +++ b/src/testdir/test_taglist.vim @@ -100,7 +100,10 @@ func Test_tagfiles() help let tf = tagfiles() - call assert_equal(1, len(tf)) + " if 'helplang includes another language, then we may find + " 2 tagfiles (e.g.: for EN and RU) + " we may need to adjust this, if further translated help files are included + call assert_inrange(1, 2, len(tf)) call assert_equal(fnamemodify(expand('$VIMRUNTIME/doc/tags'), ':p:gs?\\?/?'), \ fnamemodify(tf[0], ':p:gs?\\?/?')) helpclose diff --git a/src/testdir/test_terminal3.vim b/src/testdir/test_terminal3.vim index 96a9e63..223bcc5 100644 --- a/src/testdir/test_terminal3.vim +++ b/src/testdir/test_terminal3.vim @@ -931,5 +931,25 @@ func Test_terminal_term_start_error() delfunc s:term_start_error endfunc +func Test_terminal_vt420() + CheckRunVimInTerminal + " For Termcap + CheckUnix + let rows=15 + call writefile([':set term=vt420'], 'Xterm420', 'D') + + let buf = RunVimInTerminal('-S Xterm420', #{rows: rows}) + call TermWait(buf, 100) + call term_sendkeys(buf, ":set t_xo?\<CR>") + call WaitForAssert({-> assert_match('t_xo=y', term_getline(buf, rows))}) + call StopVimInTerminal(buf) + + call writefile([''], 'Xterm420') + let buf = RunVimInTerminal('-S Xterm420', #{rows: rows}) + call TermWait(buf, 100) + call term_sendkeys(buf, ":set t_xo?\<CR>") + call WaitForAssert({-> assert_match('t_xo=\s\+', term_getline(buf, rows))}) + call StopVimInTerminal(buf) +endfunc " vim: shiftwidth=2 sts=2 expandtab diff --git a/src/testdir/test_textformat.vim b/src/testdir/test_textformat.vim index c5f5975..a9cffd0 100644 --- a/src/testdir/test_textformat.vim +++ b/src/testdir/test_textformat.vim @@ -1303,4 +1303,13 @@ func Test_correct_cursor_position() set encoding=utf8 endfunc +" This was crashing Vim +func Test_textwdith_overflow() + new + setl tw=999999999 + normal 10ig + call feedkeys('a ab cd ef', 'xt') + bw! +endfunc + " vim: shiftwidth=2 sts=2 expandtab diff --git a/src/testdir/test_textprop.vim b/src/testdir/test_textprop.vim index a06f733..2bf2834 100644 --- a/src/testdir/test_textprop.vim +++ b/src/testdir/test_textprop.vim @@ -2690,6 +2690,48 @@ func Test_prop_inserts_text_normal_gj_gk() call Run_test_prop_inserts_text_normal_gj_gk('set virtualedit=all') endfunc +func Test_prop_normal_gj_gk_gM_with_outer_virtual_text() + CheckRunVimInTerminal + + let lines =<< trim END + vim9script + setlocal number + setline(1, ['First line fits on screen line.', '', 'Third line fits on screen line.']) + + var vt = 'test' + prop_type_add(vt, {highlight: 'ToDo'}) + for ln in range(1, line('$')) + prop_add(ln, 0, {type: vt, text: 'Above', text_align: 'above'}) + prop_add(ln, 0, {type: vt, text: 'After text wraps to next line.', text_align: 'after', text_wrap: 'wrap'}) + prop_add(ln, 0, {type: vt, text: 'Right text wraps to next line.', text_align: 'right', text_wrap: 'wrap'}) + prop_add(ln, 0, {type: vt, text: 'Below', text_align: 'below'}) + endfor + normal 3l + END + call writefile(lines, 'XscriptPropsNormal_gj_gk_gM_with_outer_text', 'D') + let buf = RunVimInTerminal('-S XscriptPropsNormal_gj_gk_gM_with_outer_text', #{rows: 16, cols: 40}) + call VerifyScreenDump(buf, 'Test_prop_normal_gj_gk_gM_with_outer_virtual_text_1', {}) + + call term_sendkeys(buf, "gj") + call VerifyScreenDump(buf, 'Test_prop_normal_gj_gk_gM_with_outer_virtual_text_2', {}) + call term_sendkeys(buf, "gj") + call VerifyScreenDump(buf, 'Test_prop_normal_gj_gk_gM_with_outer_virtual_text_3', {}) + call term_sendkeys(buf, "gk") + call VerifyScreenDump(buf, 'Test_prop_normal_gj_gk_gM_with_outer_virtual_text_2', {}) + call term_sendkeys(buf, "gk") + call VerifyScreenDump(buf, 'Test_prop_normal_gj_gk_gM_with_outer_virtual_text_1', {}) + + call term_sendkeys(buf, "2gj") + call VerifyScreenDump(buf, 'Test_prop_normal_gj_gk_gM_with_outer_virtual_text_3', {}) + call term_sendkeys(buf, "2gk") + call VerifyScreenDump(buf, 'Test_prop_normal_gj_gk_gM_with_outer_virtual_text_1', {}) + + call term_sendkeys(buf, "gM") + call VerifyScreenDump(buf, 'Test_prop_normal_gj_gk_gM_with_outer_virtual_text_4', {}) + + call StopVimInTerminal(buf) +endfunc + func Test_prop_inserts_text_visual_block() CheckRunVimInTerminal @@ -3026,6 +3068,43 @@ func Test_props_with_text_after_below_trunc() call StopVimInTerminal(buf) endfunc +func Test_props_with_text_truncated_just_before_after() + CheckRunVimInTerminal + + let lines =<< trim END + vim9script + set showbreak=+++ + set list listchars=extends:> + set nowrap + + setline(1, [ + 'here is text long enough to fill the row', + 'second line', + ]) + + prop_type_add("test", {"highlight": "Error"}) + prop_add(1, 0, {type: "test", text_align: "right", text: "right text"}) + def g:AddPropBelow() + prop_add(1, 0, {type: "test", text_align: "below", text: "below text"}) + enddef + def g:AddPropAfter() + prop_add(1, 0, {type: "test", text: "after text", text_padding_left: 1}) + enddef + normal G$ + END + call writefile(lines, 'XscriptPropsWithTextTruncatedJustBeforeAfter', 'D') + let buf = RunVimInTerminal('-S XscriptPropsWithTextTruncatedJustBeforeAfter', #{rows: 8, cols: 40}) + call VerifyScreenDump(buf, 'Test_props_with_text_truncated_just_before_after_1', {}) + + call term_sendkeys(buf, ":call AddPropBelow()\<CR>") + call VerifyScreenDump(buf, 'Test_props_with_text_truncated_just_before_after_2', {}) + + call term_sendkeys(buf, ":call AddPropAfter()\<CR>:\<Esc>") + call VerifyScreenDump(buf, 'Test_props_with_text_truncated_just_before_after_2', {}) + + call StopVimInTerminal(buf) +endfunc + func Test_prop_with_text_below_after_empty() CheckRunVimInTerminal diff --git a/src/testdir/test_utf8.vim b/src/testdir/test_utf8.vim index 3bb7459..0f46240 100644 --- a/src/testdir/test_utf8.vim +++ b/src/testdir/test_utf8.vim @@ -62,6 +62,9 @@ func Test_customlist_completion() call assert_equal('"Test3 N', getreg(':')) call garbagecollect(1) + delcommand Test1 + delcommand Test2 + delcommand Test3 endfunc " Yank one 3 byte character and check the mark columns. @@ -170,6 +173,7 @@ func Test_screenchar_utf8() endfunc func Test_setcellwidths() + new call setcellwidths([ \ [0x1330, 0x1330, 2], \ [9999, 10000, 1], @@ -212,6 +216,18 @@ func Test_setcellwidths() " Ambiguous width chars call assert_equal(2, strwidth("\u00A1")) call assert_equal(2, strwidth("\u2010")) + + call setcellwidths([]) + call setline(1, repeat("\u2103", 10)) + normal! $ + redraw + call assert_equal((aw == 'single') ? 10 : 19, wincol()) + call setcellwidths([[0x2103, 0x2103, 1]]) + redraw + call assert_equal(10, wincol()) + call setcellwidths([[0x2103, 0x2103, 2]]) + redraw + call assert_equal(19, wincol()) endfor set ambiwidth& isprint& @@ -245,6 +261,7 @@ func Test_setcellwidths() set listchars& set fillchars& call setcellwidths([]) + bwipe! endfunc func Test_getcellwidths() @@ -283,64 +300,66 @@ func Test_setcellwidths_dump() call StopVimInTerminal(buf) endfunc -func Test_print_overlong() - " Text with more composing characters than MB_MAXBYTES. - new - call setline(1, 'axxxxxxxxxxxxxxxxxxxxxxxxxxxxxx') - s/x/\=nr2char(1629)/g - print - bwipe! -endfunc +" Test setcellwidths() on characters that are not targets of 'ambiwidth'. +func Test_setcellwidths_with_non_ambiwidth_character_dump() + CheckRunVimInTerminal -func Test_recording_with_select_mode_utf8() - call Run_test_recording_with_select_mode_utf8() + let lines =<< trim END + call setline(1, [repeat("\u279c", 60), repeat("\u279c", 60)]) + set ambiwidth=single + END + call writefile(lines, 'XCellwidthsWithNonAmbiwidthCharacter', 'D') + let buf = RunVimInTerminal('-S XCellwidthsWithNonAmbiwidthCharacter', {'rows': 6, 'cols': 50}) + call term_sendkeys(buf, ":call setcellwidths([[0x279c, 0x279c, 1]])\<CR>") + call term_sendkeys(buf, ":echo\<CR>") + call VerifyScreenDump(buf, 'Test_setcellwidths_with_non_ambiwidth_character_dump_1', {}) + + call term_sendkeys(buf, ":call setcellwidths([[0x279c, 0x279c, 2]])\<CR>") + call term_sendkeys(buf, ":echo\<CR>") + call VerifyScreenDump(buf, 'Test_setcellwidths_with_non_ambiwidth_character_dump_2', {}) + + call StopVimInTerminal(buf) endfunc -func Run_test_recording_with_select_mode_utf8() - new +" For some reason this test causes Test_customlist_completion() to fail on CI, +" so run it as the last test. +func Test_zz_ambiwidth_hl_dump() + CheckRunVimInTerminal - " No escaping - call feedkeys("qacc12345\<Esc>gH哦\<Esc>q", "tx") - call assert_equal("哦", getline(1)) - call assert_equal("cc12345\<Esc>gH哦\<Esc>", @a) - call setline(1, 'asdf') - normal! @a - call assert_equal("哦", getline(1)) - - " 固 is 0xE5 0x9B 0xBA where 0x9B is CSI - call feedkeys("qacc12345\<Esc>gH固\<Esc>q", "tx") - call assert_equal("固", getline(1)) - call assert_equal("cc12345\<Esc>gH固\<Esc>", @a) - call setline(1, 'asdf') - normal! @a - call assert_equal("固", getline(1)) - - " å›› is 0xE5 0x9B 0x9B where 0x9B is CSI - call feedkeys("qacc12345\<Esc>gHå››\<Esc>q", "tx") - call assert_equal("å››", getline(1)) - call assert_equal("cc12345\<Esc>gHå››\<Esc>", @a) - call setline(1, 'asdf') - normal! @a - call assert_equal("å››", getline(1)) - - " 倒 is 0xE5 0x80 0x92 where 0x80 is K_SPECIAL - call feedkeys("qacc12345\<Esc>gH倒\<Esc>q", "tx") - call assert_equal("倒", getline(1)) - call assert_equal("cc12345\<Esc>gH倒\<Esc>", @a) - call setline(1, 'asdf') - normal! @a - call assert_equal("倒", getline(1)) + let lines =<< trim END + call setline(1, [repeat("\u2103", 60), repeat("\u2103", 60)]) + set ambiwidth=single cursorline list display=lastline + END + call writefile(lines, 'XAmbiwidthHl', 'D') + let buf = RunVimInTerminal('-S XAmbiwidthHl', {'rows': 6, 'cols': 50}) + call VerifyScreenDump(buf, 'Test_ambiwidth_hl_dump_1', {}) - bwipe! -endfunc + call term_sendkeys(buf, ":set ambiwidth=double\<CR>") + call term_sendkeys(buf, ":echo\<CR>") + call VerifyScreenDump(buf, 'Test_ambiwidth_hl_dump_2', {}) + + call term_sendkeys(buf, ":set ambiwidth=single\<CR>") + call term_sendkeys(buf, ":echo\<CR>") + call VerifyScreenDump(buf, 'Test_ambiwidth_hl_dump_1', {}) + + call term_sendkeys(buf, ":call setcellwidths([[0x2103, 0x2103, 2]])\<CR>") + call term_sendkeys(buf, ":echo\<CR>") + call VerifyScreenDump(buf, 'Test_ambiwidth_hl_dump_2', {}) + + call term_sendkeys(buf, ":call setcellwidths([[0x2103, 0x2103, 1]])\<CR>") + call term_sendkeys(buf, ":echo\<CR>") + call VerifyScreenDump(buf, 'Test_ambiwidth_hl_dump_1', {}) -" This must be done as one of the last tests, because it starts the GUI, which -" cannot be undone. -func Test_zz_recording_with_select_mode_utf8_gui() - CheckCanRunGui + call StopVimInTerminal(buf) +endfunc - gui -f - call Run_test_recording_with_select_mode_utf8() +func Test_print_overlong() + " Text with more composing characters than MB_MAXBYTES. + new + call setline(1, 'axxxxxxxxxxxxxxxxxxxxxxxxxxxxxx') + s/x/\=nr2char(1629)/g + print + bwipe! endfunc " vim: shiftwidth=2 sts=2 expandtab diff --git a/src/testdir/test_vim9_assign.vim b/src/testdir/test_vim9_assign.vim index 4414f55..4296c37 100644 --- a/src/testdir/test_vim9_assign.vim +++ b/src/testdir/test_vim9_assign.vim @@ -1104,6 +1104,27 @@ def Test_assignment_partial() Ref(0) END v9.CheckScriptFailure(lines, 'E1013: Argument 2: type mismatch, expected string but got number') + + lines =<< trim END + var Fn1 = () => { + return 10 + } + assert_equal('func(): number', typename(Fn1)) + var Fn2 = () => { + return "a" + } + assert_equal('func(): string', typename(Fn2)) + var Fn3 = () => { + return {a: [1]} + } + assert_equal('func(): dict<list<number>>', typename(Fn3)) + var Fn4 = (...l: list<string>) => { + return [] + } + assert_equal('func(...list<string>): list<any>', typename(Fn4)) + END + v9.CheckSourceSuccess(['vim9script'] + lines) + v9.CheckSourceSuccess(['def Xfunc()'] + lines + ['enddef', 'defcompile']) enddef def Test_assignment_list_any_index() @@ -1997,6 +2018,31 @@ def Test_heredoc() END v9.CheckScriptSuccess(lines) + # commented out heredoc assignment without space after '#' + lines =<< trim END + vim9script + def Func() + #x =<< trim [CODE] + #[CODE] + enddef + Func() + END + v9.CheckScriptSuccess(lines) + + # heredoc start should not be recognized in string + lines =<< trim END + vim9script + def Func() + new + @" = 'bar' + ['foo', @"]->setline("]=<<"->count('=')) + assert_equal(['foo', 'bar'], getline(1, '$')) + bwipe! + enddef + Func() + END + v9.CheckScriptSuccess(lines) + v9.CheckDefFailure(['var lines =<< trim END X', 'END'], 'E488:') v9.CheckDefFailure(['var lines =<< trim END " comment', 'END'], 'E488:') @@ -2938,6 +2984,66 @@ def Test_heredoc_expr() CODE v9.CheckDefAndScriptSuccess(lines) + # Evaluate a dictionary + lines =<< trim CODE + var d1 = {'a': 10, 'b': [1, 2]} + var code =<< trim eval END + var d2 = {d1} + END + assert_equal(["var d2 = {'a': 10, 'b': [1, 2]}"], code) + CODE + v9.CheckDefAndScriptSuccess(lines) + + # Evaluate an empty dictionary + lines =<< trim CODE + var d1 = {} + var code =<< trim eval END + var d2 = {d1} + END + assert_equal(["var d2 = {}"], code) + CODE + v9.CheckDefAndScriptSuccess(lines) + + # Evaluate a null dictionary + lines =<< trim CODE + var d1 = test_null_dict() + var code =<< trim eval END + var d2 = {d1} + END + assert_equal(["var d2 = {}"], code) + CODE + v9.CheckDefAndScriptSuccess(lines) + + # Evaluate a List + lines =<< trim CODE + var l1 = ['a', 'b', 'c'] + var code =<< trim eval END + var l2 = {l1} + END + assert_equal(["var l2 = ['a', 'b', 'c']"], code) + CODE + v9.CheckDefAndScriptSuccess(lines) + + # Evaluate an empty List + lines =<< trim CODE + var l1 = [] + var code =<< trim eval END + var l2 = {l1} + END + assert_equal(["var l2 = []"], code) + CODE + v9.CheckDefAndScriptSuccess(lines) + + # Evaluate a null List + lines =<< trim CODE + var l1 = test_null_list() + var code =<< trim eval END + var l2 = {l1} + END + assert_equal(["var l2 = []"], code) + CODE + v9.CheckDefAndScriptSuccess(lines) + lines =<< trim CODE var code =<< eval trim END var s = "{$SOME_ENV_VAR}" diff --git a/src/testdir/test_vim9_builtin.vim b/src/testdir/test_vim9_builtin.vim index 442d375..42d09fe 100644 --- a/src/testdir/test_vim9_builtin.vim +++ b/src/testdir/test_vim9_builtin.vim @@ -66,16 +66,16 @@ def Test_abs() assert_equal(0, abs(0)) assert_equal(2, abs(-2)) assert_equal(3, abs(3)) - v9.CheckDefAndScriptFailure(['abs("text")'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1219: Float or Number required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['abs("text")'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1219: Float or Number required for argument 1']) assert_equal(0, abs(0)) assert_equal(2.0, abs(-2.0)) assert_equal(3.0, abs(3.0)) enddef def Test_add() - v9.CheckDefAndScriptFailure(['add({}, 1)'], ['E1013: Argument 1: type mismatch, expected list<any> but got dict<any>', 'E1226: List or Blob required for argument 1']) - v9.CheckDefAndScriptFailure(['add([])'], 'E119:') - v9.CheckDefExecFailure([ + v9.CheckSourceDefAndScriptFailure(['add({}, 1)'], ['E1013: Argument 1: type mismatch, expected list<any> but got dict<any>', 'E1226: List or Blob required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['add([])'], 'E119:') + v9.CheckSourceDefExecFailure([ 'var ln: list<number> = [1]', 'add(ln, "a")'], 'E1012: Type mismatch; expected number but got string') @@ -91,7 +91,7 @@ def Test_add() enddef TryChange() END - v9.CheckScriptFailure(lines, 'E741:') + v9.CheckSourceScriptFailure(lines, 'E741:') enddef def Test_add_blob() @@ -107,18 +107,18 @@ def Test_add_blob() var b: blob add(b, "x") END - v9.CheckDefFailure(lines, 'E1012:', 2) + v9.CheckSourceDefFailure(lines, 'E1012:', 2) lines =<< trim END add(test_null_blob(), 123) END - v9.CheckDefExecAndScriptFailure(lines, 'E1131:', 1) + v9.CheckSourceDefExecAndScriptFailure(lines, 'E1131:', 1) lines =<< trim END var b: blob = test_null_blob() add(b, 123) END - v9.CheckDefExecFailure(lines, 'E1131:', 2) + v9.CheckSourceDefExecFailure(lines, 'E1131:', 2) # Getting variable with NULL blob fails lines =<< trim END @@ -126,7 +126,7 @@ def Test_add_blob() var b: blob = test_null_blob() add(b, 123) END - v9.CheckScriptFailure(lines, 'E1131:', 3) + v9.CheckSourceScriptFailure(lines, 'E1131:', 3) enddef def Test_add_list() @@ -138,18 +138,18 @@ def Test_add_list() var l: list<number> add(l, "x") END - v9.CheckDefFailure(lines, 'E1012:', 2) + v9.CheckSourceDefFailure(lines, 'E1012:', 2) lines =<< trim END add(test_null_list(), 123) END - v9.CheckDefExecAndScriptFailure(lines, 'E1130:', 1) + v9.CheckSourceDefExecAndScriptFailure(lines, 'E1130:', 1) lines =<< trim END var l: list<number> = test_null_list() add(l, 123) END - v9.CheckDefExecFailure(lines, 'E1130:', 2) + v9.CheckSourceDefExecFailure(lines, 'E1130:', 2) # Getting an uninitialized variable allocates a new list at script level lines =<< trim END @@ -157,7 +157,7 @@ def Test_add_list() var l: list<number> add(l, 123) END - v9.CheckScriptSuccess(lines) + v9.CheckSourceScriptSuccess(lines) # Adding to a variable set to a NULL list fails lines =<< trim END @@ -165,21 +165,21 @@ def Test_add_list() var l: list<number> = test_null_list() add(l, 123) END - v9.CheckScriptFailure(lines, 'E1130:', 3) + v9.CheckSourceScriptFailure(lines, 'E1130:', 3) lines =<< trim END vim9script var l: list<string> = ['a'] l->add(123) END - v9.CheckScriptFailure(lines, 'E1012: Type mismatch; expected string but got number', 3) + v9.CheckSourceScriptFailure(lines, 'E1012: Type mismatch; expected string but got number', 3) lines =<< trim END vim9script var l: list<string> l->add(123) END - v9.CheckScriptFailure(lines, 'E1012: Type mismatch; expected string but got number', 3) + v9.CheckSourceScriptFailure(lines, 'E1012: Type mismatch; expected string but got number', 3) enddef def Test_add_const() @@ -187,26 +187,26 @@ def Test_add_const() const l = [1, 2] add(l, 3) END - v9.CheckDefFailure(lines, 'E1307: Argument 1: Trying to modify a const list<number>') + v9.CheckSourceDefFailure(lines, 'E1307: Argument 1: Trying to modify a const list<number>') lines =<< trim END final l = [1, 2] add(l, 3) assert_equal([1, 2, 3], l) END - v9.CheckDefSuccess(lines) + v9.CheckSourceDefSuccess(lines) lines =<< trim END const b = 0z0102 add(b, 0z03) END - v9.CheckDefFailure(lines, 'E1307: Argument 1: Trying to modify a const blob') + v9.CheckSourceDefFailure(lines, 'E1307: Argument 1: Trying to modify a const blob') enddef def Test_and() - v9.CheckDefAndScriptFailure(['and("x", 0x2)'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1210: Number required for argument 1']) - v9.CheckDefAndScriptFailure(['and(0x1, "x")'], ['E1013: Argument 2: type mismatch, expected number but got string', 'E1210: Number required for argument 2']) + v9.CheckSourceDefAndScriptFailure(['and("x", 0x2)'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1210: Number required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['and(0x1, "x")'], ['E1013: Argument 2: type mismatch, expected number but got string', 'E1210: Number required for argument 2']) enddef def Test_append() @@ -224,12 +224,12 @@ def Test_append() assert_equal("{'a': 10}", getline(1)) append(0, function('min')) assert_equal("function('min')", getline(1)) - v9.CheckDefAndScriptFailure(['append([1], "x")'], ['E1013: Argument 1: type mismatch, expected string but got list<number>', 'E1220: String or Number required for argument 1']) - v9.CheckDefExecAndScriptFailure(['append("", "x")'], 'E1209: Invalid value for a line number') - v9.CheckDefExecAndScriptFailure(['append(".a", "x")'], 'E1209: Invalid value for a line number') + v9.CheckSourceDefAndScriptFailure(['append([1], "x")'], ['E1013: Argument 1: type mismatch, expected string but got list<number>', 'E1220: String or Number required for argument 1']) + v9.CheckSourceDefExecAndScriptFailure(['append("", "x")'], 'E1209: Invalid value for a line number') + v9.CheckSourceDefExecAndScriptFailure(['append(".a", "x")'], 'E1209: Invalid value for a line number') # only get one error assert_fails('append("''aa", "x")', ['E1209: Invalid value for a line number: "''aa"', 'E1209:']) - v9.CheckDefExecAndScriptFailure(['append(-1, "x")'], 'E966: Invalid line number: -1') + v9.CheckSourceDefExecAndScriptFailure(['append(-1, "x")'], 'E966: Invalid line number: -1') bwipe! enddef @@ -245,12 +245,12 @@ def Test_appendbufline() assert_equal(['0', 'one', '1', 'two', '2', ''], getbufline(bnum, 1, '$')) appendbufline(bnum, 0, 'zero') assert_equal(['zero'], getbufline(bnum, 1)) - v9.CheckDefAndScriptFailure(['appendbufline([1], 1, "x")'], ['E1013: Argument 1: type mismatch, expected string but got list<number>', 'E1220: String or Number required for argument 1']) - v9.CheckDefAndScriptFailure(['appendbufline(1, [1], "x")'], ['E1013: Argument 2: type mismatch, expected string but got list<number>', 'E1220: String or Number required for argument 2']) - v9.CheckDefExecAndScriptFailure(['appendbufline(' .. bnum .. ', -1, "x")'], 'E966: Invalid line number: -1') - v9.CheckDefExecAndScriptFailure(['appendbufline(' .. bnum .. ', "$a", "x")'], 'E1030: Using a String as a Number: "$a"') + v9.CheckSourceDefAndScriptFailure(['appendbufline([1], 1, "x")'], ['E1013: Argument 1: type mismatch, expected string but got list<number>', 'E1220: String or Number required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['appendbufline(1, [1], "x")'], ['E1013: Argument 2: type mismatch, expected string but got list<number>', 'E1220: String or Number required for argument 2']) + v9.CheckSourceDefExecAndScriptFailure(['appendbufline(' .. bnum .. ', -1, "x")'], 'E966: Invalid line number: -1') + v9.CheckSourceDefExecAndScriptFailure(['appendbufline(' .. bnum .. ', "$a", "x")'], 'E1030: Using a String as a Number: "$a"') assert_fails('appendbufline(' .. bnum .. ', "$a", "x")', ['E1030: Using a String as a Number: "$a"', 'E1030:']) - v9.CheckDefAndScriptFailure(['appendbufline(1, 1, {"a": 10})'], ['E1013: Argument 3: type mismatch, expected string but got dict<number>', 'E1224: String, Number or List required for argument 3']) + v9.CheckSourceDefAndScriptFailure(['appendbufline(1, 1, {"a": 10})'], ['E1013: Argument 3: type mismatch, expected string but got dict<number>', 'E1224: String, Number or List required for argument 3']) bnum->bufwinid()->win_gotoid() appendbufline('', 0, 'numbers') getline(1)->assert_equal('numbers') @@ -258,80 +258,80 @@ def Test_appendbufline() enddef def Test_argc() - v9.CheckDefAndScriptFailure(['argc("x")'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1210: Number required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['argc("x")'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1210: Number required for argument 1']) enddef def Test_arglistid() - v9.CheckDefAndScriptFailure(['arglistid("x")'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1210: Number required for argument 1']) - v9.CheckDefAndScriptFailure(['arglistid(1, "y")'], ['E1013: Argument 2: type mismatch, expected number but got string', 'E1210: Number required for argument 2']) - v9.CheckDefAndScriptFailure(['arglistid("x", "y")'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1210: Number required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['arglistid("x")'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1210: Number required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['arglistid(1, "y")'], ['E1013: Argument 2: type mismatch, expected number but got string', 'E1210: Number required for argument 2']) + v9.CheckSourceDefAndScriptFailure(['arglistid("x", "y")'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1210: Number required for argument 1']) enddef def Test_argv() - v9.CheckDefAndScriptFailure(['argv("x")'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1210: Number required for argument 1']) - v9.CheckDefAndScriptFailure(['argv(1, "x")'], ['E1013: Argument 2: type mismatch, expected number but got string', 'E1210: Number required for argument 2']) - v9.CheckDefAndScriptFailure(['argv("x", "y")'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1210: Number required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['argv("x")'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1210: Number required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['argv(1, "x")'], ['E1013: Argument 2: type mismatch, expected number but got string', 'E1210: Number required for argument 2']) + v9.CheckSourceDefAndScriptFailure(['argv("x", "y")'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1210: Number required for argument 1']) enddef def Test_assert_beeps() - v9.CheckDefAndScriptFailure(['assert_beeps(1)'], ['E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['assert_beeps(1)'], ['E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1']) enddef def Test_assert_equalfile() - v9.CheckDefAndScriptFailure(['assert_equalfile(1, "f2")'], ['E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1']) - v9.CheckDefAndScriptFailure(['assert_equalfile("f1", true)'], ['E1013: Argument 2: type mismatch, expected string but got bool', 'E1174: String required for argument 2']) - v9.CheckDefAndScriptFailure(['assert_equalfile("f1", "f2", ["a"])'], ['E1013: Argument 3: type mismatch, expected string but got list<string>', 'E1174: String required for argument 3']) + v9.CheckSourceDefAndScriptFailure(['assert_equalfile(1, "f2")'], ['E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['assert_equalfile("f1", true)'], ['E1013: Argument 2: type mismatch, expected string but got bool', 'E1174: String required for argument 2']) + v9.CheckSourceDefAndScriptFailure(['assert_equalfile("f1", "f2", ["a"])'], ['E1013: Argument 3: type mismatch, expected string but got list<string>', 'E1174: String required for argument 3']) enddef def Test_assert_exception() - v9.CheckDefAndScriptFailure(['assert_exception({})'], ['E1013: Argument 1: type mismatch, expected string but got dict<any>', 'E1174: String required for argument 1']) - v9.CheckDefAndScriptFailure(['assert_exception("E1:", v:null)'], ['E1013: Argument 2: type mismatch, expected string but got special', 'E1174: String required for argument 2']) + v9.CheckSourceDefAndScriptFailure(['assert_exception({})'], ['E1013: Argument 1: type mismatch, expected string but got dict<any>', 'E1174: String required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['assert_exception("E1:", v:null)'], ['E1013: Argument 2: type mismatch, expected string but got special', 'E1174: String required for argument 2']) enddef def Test_assert_fails() - v9.CheckDefAndScriptFailure(['assert_fails([])'], ['E1013: Argument 1: type mismatch, expected string but got list<any>', 'E1220: String or Number required for argument 1']) - v9.CheckDefAndScriptFailure(['assert_fails("a", true)'], ['E1013: Argument 2: type mismatch, expected string but got bool', 'E1222: String or List required for argument 2']) - v9.CheckDefAndScriptFailure(['assert_fails("a", "b", "c", "d")'], ['E1013: Argument 4: type mismatch, expected number but got string', 'E1210: Number required for argument 4']) - v9.CheckDefAndScriptFailure(['assert_fails("a", "b", "c", 4, 5)'], ['E1013: Argument 5: type mismatch, expected string but got number', 'E1174: String required for argument 5']) + v9.CheckSourceDefAndScriptFailure(['assert_fails([])'], ['E1013: Argument 1: type mismatch, expected string but got list<any>', 'E1220: String or Number required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['assert_fails("a", true)'], ['E1013: Argument 2: type mismatch, expected string but got bool', 'E1222: String or List required for argument 2']) + v9.CheckSourceDefAndScriptFailure(['assert_fails("a", "b", "c", "d")'], ['E1013: Argument 4: type mismatch, expected number but got string', 'E1210: Number required for argument 4']) + v9.CheckSourceDefAndScriptFailure(['assert_fails("a", "b", "c", 4, 5)'], ['E1013: Argument 5: type mismatch, expected string but got number', 'E1174: String required for argument 5']) enddef def Test_assert_inrange() - v9.CheckDefAndScriptFailure(['assert_inrange("a", 2, 3)'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1219: Float or Number required for argument 1']) - v9.CheckDefAndScriptFailure(['assert_inrange(1, "b", 3)'], ['E1013: Argument 2: type mismatch, expected number but got string', 'E1219: Float or Number required for argument 2']) - v9.CheckDefAndScriptFailure(['assert_inrange(1, 2, "c")'], ['E1013: Argument 3: type mismatch, expected number but got string', 'E1219: Float or Number required for argument 3']) - v9.CheckDefAndScriptFailure(['assert_inrange(1, 2, 3, 4)'], ['E1013: Argument 4: type mismatch, expected string but got number', 'E1174: String required for argument 4']) + v9.CheckSourceDefAndScriptFailure(['assert_inrange("a", 2, 3)'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1219: Float or Number required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['assert_inrange(1, "b", 3)'], ['E1013: Argument 2: type mismatch, expected number but got string', 'E1219: Float or Number required for argument 2']) + v9.CheckSourceDefAndScriptFailure(['assert_inrange(1, 2, "c")'], ['E1013: Argument 3: type mismatch, expected number but got string', 'E1219: Float or Number required for argument 3']) + v9.CheckSourceDefAndScriptFailure(['assert_inrange(1, 2, 3, 4)'], ['E1013: Argument 4: type mismatch, expected string but got number', 'E1174: String required for argument 4']) enddef def Test_assert_match() - v9.CheckDefAndScriptFailure(['assert_match({}, "b")'], ['E1013: Argument 1: type mismatch, expected string but got dict<any>', '']) - v9.CheckDefAndScriptFailure(['assert_match("a", 1)'], ['E1013: Argument 2: type mismatch, expected string but got number', '']) - v9.CheckDefAndScriptFailure(['assert_match("a", "b", null)'], ['E1013: Argument 3: type mismatch, expected string but got special', '']) + v9.CheckSourceDefAndScriptFailure(['assert_match({}, "b")'], ['E1013: Argument 1: type mismatch, expected string but got dict<any>', '']) + v9.CheckSourceDefAndScriptFailure(['assert_match("a", 1)'], ['E1013: Argument 2: type mismatch, expected string but got number', '']) + v9.CheckSourceDefAndScriptFailure(['assert_match("a", "b", null)'], ['E1013: Argument 3: type mismatch, expected string but got special', '']) enddef def Test_assert_nobeep() - v9.CheckDefAndScriptFailure(['assert_nobeep(1)'], ['E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['assert_nobeep(1)'], ['E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1']) enddef def Test_assert_notmatch() - v9.CheckDefAndScriptFailure(['assert_notmatch({}, "b")'], ['E1013: Argument 1: type mismatch, expected string but got dict<any>', '']) - v9.CheckDefAndScriptFailure(['assert_notmatch("a", 1)'], ['E1013: Argument 2: type mismatch, expected string but got number', '']) - v9.CheckDefAndScriptFailure(['assert_notmatch("a", "b", null)'], ['E1013: Argument 3: type mismatch, expected string but got special', '']) + v9.CheckSourceDefAndScriptFailure(['assert_notmatch({}, "b")'], ['E1013: Argument 1: type mismatch, expected string but got dict<any>', '']) + v9.CheckSourceDefAndScriptFailure(['assert_notmatch("a", 1)'], ['E1013: Argument 2: type mismatch, expected string but got number', '']) + v9.CheckSourceDefAndScriptFailure(['assert_notmatch("a", "b", null)'], ['E1013: Argument 3: type mismatch, expected string but got special', '']) enddef def Test_assert_report() - v9.CheckDefAndScriptFailure(['assert_report([1, 2])'], ['E1013: Argument 1: type mismatch, expected string but got list<number>', 'E1174: String required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['assert_report([1, 2])'], ['E1013: Argument 1: type mismatch, expected string but got list<number>', 'E1174: String required for argument 1']) enddef def Test_autocmd_add() - v9.CheckDefAndScriptFailure(['autocmd_add({})'], ['E1013: Argument 1: type mismatch, expected list<any> but got dict<any>', 'E1211: List required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['autocmd_add({})'], ['E1013: Argument 1: type mismatch, expected list<any> but got dict<any>', 'E1211: List required for argument 1']) enddef def Test_autocmd_delete() - v9.CheckDefAndScriptFailure(['autocmd_delete({})'], ['E1013: Argument 1: type mismatch, expected list<any> but got dict<any>', 'E1211: List required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['autocmd_delete({})'], ['E1013: Argument 1: type mismatch, expected list<any> but got dict<any>', 'E1211: List required for argument 1']) enddef def Test_autocmd_get() - v9.CheckDefAndScriptFailure(['autocmd_get(10)'], ['E1013: Argument 1: type mismatch, expected dict<any> but got number', 'E1206: Dictionary required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['autocmd_get(10)'], ['E1013: Argument 1: type mismatch, expected dict<any> but got number', 'E1206: Dictionary required for argument 1']) enddef def Test_balloon_show() @@ -341,8 +341,8 @@ def Test_balloon_show() assert_fails('balloon_show(10)', 'E1222:') assert_fails('balloon_show(true)', 'E1222:') - v9.CheckDefAndScriptFailure(['balloon_show(1.2)'], ['E1013: Argument 1: type mismatch, expected string but got float', 'E1222: String or List required for argument 1']) - v9.CheckDefAndScriptFailure(['balloon_show({"a": 10})'], ['E1013: Argument 1: type mismatch, expected string but got dict<number>', 'E1222: String or List required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['balloon_show(1.2)'], ['E1013: Argument 1: type mismatch, expected string but got float', 'E1222: String or List required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['balloon_show({"a": 10})'], ['E1013: Argument 1: type mismatch, expected string but got dict<number>', 'E1222: String or List required for argument 1']) enddef def Test_balloon_split() @@ -354,22 +354,22 @@ enddef def Test_blob2list() assert_equal(['x', 'x'], blob2list(0z1234)->map((_, _) => 'x')) - v9.CheckDefAndScriptFailure(['blob2list(10)'], ['E1013: Argument 1: type mismatch, expected blob but got number', 'E1238: Blob required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['blob2list(10)'], ['E1013: Argument 1: type mismatch, expected blob but got number', 'E1238: Blob required for argument 1']) enddef def Test_browse() CheckFeature browse - v9.CheckDefAndScriptFailure(['browse(2, "title", "dir", "file")'], ['E1013: Argument 1: type mismatch, expected bool but got number', 'E1212: Bool required for argument 1']) - v9.CheckDefAndScriptFailure(['browse(true, 2, "dir", "file")'], ['E1013: Argument 2: type mismatch, expected string but got number', 'E1174: String required for argument 2']) - v9.CheckDefAndScriptFailure(['browse(true, "title", 3, "file")'], ['E1013: Argument 3: type mismatch, expected string but got number', 'E1174: String required for argument 3']) - v9.CheckDefAndScriptFailure(['browse(true, "title", "dir", 4)'], ['E1013: Argument 4: type mismatch, expected string but got number', 'E1174: String required for argument 4']) + v9.CheckSourceDefAndScriptFailure(['browse(2, "title", "dir", "file")'], ['E1013: Argument 1: type mismatch, expected bool but got number', 'E1212: Bool required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['browse(true, 2, "dir", "file")'], ['E1013: Argument 2: type mismatch, expected string but got number', 'E1174: String required for argument 2']) + v9.CheckSourceDefAndScriptFailure(['browse(true, "title", 3, "file")'], ['E1013: Argument 3: type mismatch, expected string but got number', 'E1174: String required for argument 3']) + v9.CheckSourceDefAndScriptFailure(['browse(true, "title", "dir", 4)'], ['E1013: Argument 4: type mismatch, expected string but got number', 'E1174: String required for argument 4']) enddef def Test_browsedir() if has('browse') - v9.CheckDefAndScriptFailure(['browsedir({}, "b")'], ['E1013: Argument 1: type mismatch, expected string but got dict<any>', 'E1174: String required for argument 1']) - v9.CheckDefAndScriptFailure(['browsedir("a", [])'], ['E1013: Argument 2: type mismatch, expected string but got list<any>', 'E1174: String required for argument 2']) + v9.CheckSourceDefAndScriptFailure(['browsedir({}, "b")'], ['E1013: Argument 1: type mismatch, expected string but got dict<any>', 'E1174: String required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['browsedir("a", [])'], ['E1013: Argument 2: type mismatch, expected string but got list<any>', 'E1174: String required for argument 2']) endif enddef @@ -425,8 +425,8 @@ def Test_bufnr() buf = bufnr('Xdummy', true) buf->assert_notequal(-1) exe 'bwipe! ' .. buf - v9.CheckDefAndScriptFailure(['bufnr([1])'], ['E1013: Argument 1: type mismatch, expected string but got list<number>', 'E1220: String or Number required for argument 1']) - v9.CheckDefAndScriptFailure(['bufnr(1, 2)'], ['E1013: Argument 2: type mismatch, expected bool but got number', 'E1212: Bool required for argument 2']) + v9.CheckSourceDefAndScriptFailure(['bufnr([1])'], ['E1013: Argument 1: type mismatch, expected string but got list<number>', 'E1220: String or Number required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['bufnr(1, 2)'], ['E1013: Argument 2: type mismatch, expected bool but got number', 'E1212: Bool required for argument 2']) enddef def Test_bufwinid() @@ -452,23 +452,23 @@ def Test_bufwinnr() enddef def Test_byte2line() - v9.CheckDefAndScriptFailure(['byte2line("1")'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1210: Number required for argument 1']) - v9.CheckDefAndScriptFailure(['byte2line([])'], ['E1013: Argument 1: type mismatch, expected number but got list<any>', 'E1210: Number required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['byte2line("1")'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1210: Number required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['byte2line([])'], ['E1013: Argument 1: type mismatch, expected number but got list<any>', 'E1210: Number required for argument 1']) byte2line(0)->assert_equal(-1) enddef def Test_byteidx() - v9.CheckDefAndScriptFailure(['byteidx(1, 2)'], ['E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1']) - v9.CheckDefAndScriptFailure(['byteidx("a", "b")'], ['E1013: Argument 2: type mismatch, expected number but got string', 'E1210: Number required for argument 2']) - v9.CheckDefAndScriptFailure(['byteidx("a", 0, "")'], ['E1013: Argument 3: type mismatch, expected bool but got string', 'E1212: Bool required for argument 3']) + v9.CheckSourceDefAndScriptFailure(['byteidx(1, 2)'], ['E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['byteidx("a", "b")'], ['E1013: Argument 2: type mismatch, expected number but got string', 'E1210: Number required for argument 2']) + v9.CheckSourceDefAndScriptFailure(['byteidx("a", 0, "")'], ['E1013: Argument 3: type mismatch, expected bool but got string', 'E1212: Bool required for argument 3']) byteidx('', 0)->assert_equal(0) byteidx('', 1)->assert_equal(-1) enddef def Test_byteidxcomp() - v9.CheckDefAndScriptFailure(['byteidxcomp(1, 2)'], ['E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1']) - v9.CheckDefAndScriptFailure(['byteidxcomp("a", "b")'], ['E1013: Argument 2: type mismatch, expected number but got string', 'E1210: Number required for argument 2']) - v9.CheckDefAndScriptFailure(['byteidxcomp("a", 0, "")'], ['E1013: Argument 3: type mismatch, expected bool but got string', 'E1212: Bool required for argument 3']) + v9.CheckSourceDefAndScriptFailure(['byteidxcomp(1, 2)'], ['E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['byteidxcomp("a", "b")'], ['E1013: Argument 2: type mismatch, expected number but got string', 'E1210: Number required for argument 2']) + v9.CheckSourceDefAndScriptFailure(['byteidxcomp("a", 0, "")'], ['E1013: Argument 3: type mismatch, expected bool but got string', 'E1212: Bool required for argument 3']) enddef def Test_call_call() @@ -488,20 +488,20 @@ def Test_call_call() assert_equal('Inner', g:done) unlet g:done END - v9.CheckScriptSuccess(lines) + v9.CheckSourceScriptSuccess(lines) delfunc g:Inner - v9.CheckDefExecAndScriptFailure(['call(123, [2])'], 'E1256: String or function required for argument 1') - v9.CheckDefExecAndScriptFailure(['call(true, [2])'], 'E1256: String or function required for argument 1') - v9.CheckDefAndScriptFailure(['call("reverse", 2)'], ['E1013: Argument 2: type mismatch, expected list<any> but got number', 'E1211: List required for argument 2']) - v9.CheckDefAndScriptFailure(['call("reverse", [2], [1])'], ['E1013: Argument 3: type mismatch, expected dict<any> but got list<number>', 'E1206: Dictionary required for argument 3']) + v9.CheckSourceDefExecAndScriptFailure(['call(123, [2])'], 'E1256: String or function required for argument 1') + v9.CheckSourceDefExecAndScriptFailure(['call(true, [2])'], 'E1256: String or function required for argument 1') + v9.CheckSourceDefAndScriptFailure(['call("reverse", 2)'], ['E1013: Argument 2: type mismatch, expected list<any> but got number', 'E1211: List required for argument 2']) + v9.CheckSourceDefAndScriptFailure(['call("reverse", [2], [1])'], ['E1013: Argument 3: type mismatch, expected dict<any> but got list<number>', 'E1206: Dictionary required for argument 3']) enddef def Test_ch_canread() if !has('channel') CheckFeature channel else - v9.CheckDefAndScriptFailure(['ch_canread(10)'], ['E1013: Argument 1: type mismatch, expected channel but got number', 'E1217: Channel or Job required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['ch_canread(10)'], ['E1013: Argument 1: type mismatch, expected channel but got number', 'E1217: Channel or Job required for argument 1']) endif enddef @@ -509,7 +509,7 @@ def Test_ch_close() if !has('channel') CheckFeature channel else - v9.CheckDefAndScriptFailure(['ch_close("c")'], ['E1013: Argument 1: type mismatch, expected channel but got string', 'E1217: Channel or Job required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['ch_close("c")'], ['E1013: Argument 1: type mismatch, expected channel but got string', 'E1217: Channel or Job required for argument 1']) endif enddef @@ -517,7 +517,7 @@ def Test_ch_close_in() if !has('channel') CheckFeature channel else - v9.CheckDefAndScriptFailure(['ch_close_in(true)'], ['E1013: Argument 1: type mismatch, expected channel but got bool', 'E1217: Channel or Job required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['ch_close_in(true)'], ['E1013: Argument 1: type mismatch, expected channel but got bool', 'E1217: Channel or Job required for argument 1']) endif enddef @@ -525,8 +525,8 @@ def Test_ch_evalexpr() if !has('channel') CheckFeature channel else - v9.CheckDefAndScriptFailure(['ch_evalexpr(1, "a")'], ['E1013: Argument 1: type mismatch, expected channel but got number', 'E1217: Channel or Job required for argument 1']) - v9.CheckDefAndScriptFailure(['ch_evalexpr(test_null_channel(), 1, [])'], ['E1013: Argument 3: type mismatch, expected dict<any> but got list<any>', 'E1206: Dictionary required for argument 3']) + v9.CheckSourceDefAndScriptFailure(['ch_evalexpr(1, "a")'], ['E1013: Argument 1: type mismatch, expected channel but got number', 'E1217: Channel or Job required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['ch_evalexpr(test_null_channel(), 1, [])'], ['E1013: Argument 3: type mismatch, expected dict<any> but got list<any>', 'E1206: Dictionary required for argument 3']) endif enddef @@ -534,9 +534,9 @@ def Test_ch_evalraw() if !has('channel') CheckFeature channel else - v9.CheckDefAndScriptFailure(['ch_evalraw(1, "")'], ['E1013: Argument 1: type mismatch, expected channel but got number', 'E1217: Channel or Job required for argument 1']) - v9.CheckDefAndScriptFailure(['ch_evalraw(test_null_channel(), 1)'], ['E1013: Argument 2: type mismatch, expected string but got number', 'E1221: String or Blob required for argument 2']) - v9.CheckDefAndScriptFailure(['ch_evalraw(test_null_channel(), "", [])'], ['E1013: Argument 3: type mismatch, expected dict<any> but got list<any>', 'E1206: Dictionary required for argument 3']) + v9.CheckSourceDefAndScriptFailure(['ch_evalraw(1, "")'], ['E1013: Argument 1: type mismatch, expected channel but got number', 'E1217: Channel or Job required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['ch_evalraw(test_null_channel(), 1)'], ['E1013: Argument 2: type mismatch, expected string but got number', 'E1221: String or Blob required for argument 2']) + v9.CheckSourceDefAndScriptFailure(['ch_evalraw(test_null_channel(), "", [])'], ['E1013: Argument 3: type mismatch, expected dict<any> but got list<any>', 'E1206: Dictionary required for argument 3']) endif enddef @@ -544,8 +544,8 @@ def Test_ch_getbufnr() if !has('channel') CheckFeature channel else - v9.CheckDefAndScriptFailure(['ch_getbufnr(1, "a")'], ['E1013: Argument 1: type mismatch, expected channel but got number', 'E1217: Channel or Job required for argument 1']) - v9.CheckDefAndScriptFailure(['ch_getbufnr(test_null_channel(), 1)'], ['E1013: Argument 2: type mismatch, expected string but got number', 'E1174: String required for argument 2']) + v9.CheckSourceDefAndScriptFailure(['ch_getbufnr(1, "a")'], ['E1013: Argument 1: type mismatch, expected channel but got number', 'E1217: Channel or Job required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['ch_getbufnr(test_null_channel(), 1)'], ['E1013: Argument 2: type mismatch, expected string but got number', 'E1174: String required for argument 2']) # test empty string argument for ch_getbufnr() var job: job = job_start(&shell) g:WaitForAssert(() => assert_equal('run', job_status(job))) @@ -558,8 +558,8 @@ def Test_ch_getjob() if !has('channel') CheckFeature channel else - v9.CheckDefAndScriptFailure(['ch_getjob(1)'], ['E1013: Argument 1: type mismatch, expected channel but got number', 'E1217: Channel or Job required for argument 1']) - v9.CheckDefAndScriptFailure(['ch_getjob({"a": 10})'], ['E1013: Argument 1: type mismatch, expected channel but got dict<number>', 'E1217: Channel or Job required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['ch_getjob(1)'], ['E1013: Argument 1: type mismatch, expected channel but got number', 'E1217: Channel or Job required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['ch_getjob({"a": 10})'], ['E1013: Argument 1: type mismatch, expected channel but got dict<number>', 'E1217: Channel or Job required for argument 1']) assert_equal(0, ch_getjob(test_null_channel())) endif enddef @@ -568,7 +568,7 @@ def Test_ch_info() if !has('channel') CheckFeature channel else - v9.CheckDefAndScriptFailure(['ch_info([1])'], ['E1013: Argument 1: type mismatch, expected channel but got list<number>', 'E1217: Channel or Job required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['ch_info([1])'], ['E1013: Argument 1: type mismatch, expected channel but got list<number>', 'E1217: Channel or Job required for argument 1']) endif enddef @@ -576,8 +576,8 @@ def Test_ch_log() if !has('channel') CheckFeature channel else - v9.CheckDefAndScriptFailure(['ch_log(true)'], ['E1013: Argument 1: type mismatch, expected string but got bool', 'E1174: String required for argument 1']) - v9.CheckDefAndScriptFailure(['ch_log("a", 1)'], ['E1013: Argument 2: type mismatch, expected channel but got number', 'E1217: Channel or Job required for argument 2']) + v9.CheckSourceDefAndScriptFailure(['ch_log(true)'], ['E1013: Argument 1: type mismatch, expected string but got bool', 'E1174: String required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['ch_log("a", 1)'], ['E1013: Argument 2: type mismatch, expected channel but got number', 'E1217: Channel or Job required for argument 2']) endif enddef @@ -589,8 +589,8 @@ def Test_ch_logfile() assert_fails('ch_logfile("foo", true)', 'E1174:') ch_logfile('', '')->assert_equal(0) - v9.CheckDefAndScriptFailure(['ch_logfile(1)'], ['E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1']) - v9.CheckDefAndScriptFailure(['ch_logfile("a", true)'], ['E1013: Argument 2: type mismatch, expected string but got bool', 'E1174: String required for argument 2']) + v9.CheckSourceDefAndScriptFailure(['ch_logfile(1)'], ['E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['ch_logfile("a", true)'], ['E1013: Argument 2: type mismatch, expected string but got bool', 'E1174: String required for argument 2']) endif enddef @@ -598,9 +598,9 @@ def Test_ch_open() if !has('channel') CheckFeature channel else - v9.CheckDefAndScriptFailure(['ch_open({"a": 10}, "a")'], ['E1013: Argument 1: type mismatch, expected string but got dict<number>', 'E1174: String required for argument 1']) - v9.CheckDefAndScriptFailure(['ch_open("a", [1])'], ['E1013: Argument 2: type mismatch, expected dict<any> but got list<number>', 'E1206: Dictionary required for argument 2']) - v9.CheckDefExecAndScriptFailure(['ch_open("")'], 'E475: Invalid argument') + v9.CheckSourceDefAndScriptFailure(['ch_open({"a": 10}, "a")'], ['E1013: Argument 1: type mismatch, expected string but got dict<number>', 'E1174: String required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['ch_open("a", [1])'], ['E1013: Argument 2: type mismatch, expected dict<any> but got list<number>', 'E1206: Dictionary required for argument 2']) + v9.CheckSourceDefExecAndScriptFailure(['ch_open("")'], 'E475: Invalid argument') endif enddef @@ -608,8 +608,8 @@ def Test_ch_read() if !has('channel') CheckFeature channel else - v9.CheckDefAndScriptFailure(['ch_read(1)'], ['E1013: Argument 1: type mismatch, expected channel but got number', 'E1217: Channel or Job required for argument 1']) - v9.CheckDefAndScriptFailure(['ch_read(test_null_channel(), [])'], ['E1013: Argument 2: type mismatch, expected dict<any> but got list<any>', 'E1206: Dictionary required for argument 2']) + v9.CheckSourceDefAndScriptFailure(['ch_read(1)'], ['E1013: Argument 1: type mismatch, expected channel but got number', 'E1217: Channel or Job required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['ch_read(test_null_channel(), [])'], ['E1013: Argument 2: type mismatch, expected dict<any> but got list<any>', 'E1206: Dictionary required for argument 2']) endif enddef @@ -617,8 +617,8 @@ def Test_ch_readblob() if !has('channel') CheckFeature channel else - v9.CheckDefAndScriptFailure(['ch_readblob(1)'], ['E1013: Argument 1: type mismatch, expected channel but got number', 'E1217: Channel or Job required for argument 1']) - v9.CheckDefAndScriptFailure(['ch_readblob(test_null_channel(), [])'], ['E1013: Argument 2: type mismatch, expected dict<any> but got list<any>', 'E1206: Dictionary required for argument 2']) + v9.CheckSourceDefAndScriptFailure(['ch_readblob(1)'], ['E1013: Argument 1: type mismatch, expected channel but got number', 'E1217: Channel or Job required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['ch_readblob(test_null_channel(), [])'], ['E1013: Argument 2: type mismatch, expected dict<any> but got list<any>', 'E1206: Dictionary required for argument 2']) endif enddef @@ -626,8 +626,8 @@ def Test_ch_readraw() if !has('channel') CheckFeature channel else - v9.CheckDefAndScriptFailure(['ch_readraw(1)'], ['E1013: Argument 1: type mismatch, expected channel but got number', 'E1217: Channel or Job required for argument 1']) - v9.CheckDefAndScriptFailure(['ch_readraw(test_null_channel(), [])'], ['E1013: Argument 2: type mismatch, expected dict<any> but got list<any>', 'E1206: Dictionary required for argument 2']) + v9.CheckSourceDefAndScriptFailure(['ch_readraw(1)'], ['E1013: Argument 1: type mismatch, expected channel but got number', 'E1217: Channel or Job required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['ch_readraw(test_null_channel(), [])'], ['E1013: Argument 2: type mismatch, expected dict<any> but got list<any>', 'E1206: Dictionary required for argument 2']) endif enddef @@ -635,8 +635,8 @@ def Test_ch_sendexpr() if !has('channel') CheckFeature channel else - v9.CheckDefAndScriptFailure(['ch_sendexpr(1, "a")'], ['E1013: Argument 1: type mismatch, expected channel but got number', 'E1217: Channel or Job required for argument 1']) - v9.CheckDefAndScriptFailure(['ch_sendexpr(test_null_channel(), 1, [])'], ['E1013: Argument 3: type mismatch, expected dict<any> but got list<any>', 'E1206: Dictionary required for argument 3']) + v9.CheckSourceDefAndScriptFailure(['ch_sendexpr(1, "a")'], ['E1013: Argument 1: type mismatch, expected channel but got number', 'E1217: Channel or Job required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['ch_sendexpr(test_null_channel(), 1, [])'], ['E1013: Argument 3: type mismatch, expected dict<any> but got list<any>', 'E1206: Dictionary required for argument 3']) endif enddef @@ -644,9 +644,9 @@ def Test_ch_sendraw() if !has('channel') CheckFeature channel else - v9.CheckDefAndScriptFailure(['ch_sendraw(1, "")'], ['E1013: Argument 1: type mismatch, expected channel but got number', 'E1217: Channel or Job required for argument 1']) - v9.CheckDefAndScriptFailure(['ch_sendraw(test_null_channel(), 1)'], ['E1013: Argument 2: type mismatch, expected string but got number', 'E1221: String or Blob required for argument 2']) - v9.CheckDefAndScriptFailure(['ch_sendraw(test_null_channel(), "", [])'], ['E1013: Argument 3: type mismatch, expected dict<any> but got list<any>', 'E1206: Dictionary required for argument 3']) + v9.CheckSourceDefAndScriptFailure(['ch_sendraw(1, "")'], ['E1013: Argument 1: type mismatch, expected channel but got number', 'E1217: Channel or Job required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['ch_sendraw(test_null_channel(), 1)'], ['E1013: Argument 2: type mismatch, expected string but got number', 'E1221: String or Blob required for argument 2']) + v9.CheckSourceDefAndScriptFailure(['ch_sendraw(test_null_channel(), "", [])'], ['E1013: Argument 3: type mismatch, expected dict<any> but got list<any>', 'E1206: Dictionary required for argument 3']) endif enddef @@ -654,8 +654,8 @@ def Test_ch_setoptions() if !has('channel') CheckFeature channel else - v9.CheckDefAndScriptFailure(['ch_setoptions(1, {})'], ['E1013: Argument 1: type mismatch, expected channel but got number', 'E1217: Channel or Job required for argument 1']) - v9.CheckDefAndScriptFailure(['ch_setoptions(test_null_channel(), [])'], ['E1013: Argument 2: type mismatch, expected dict<any> but got list<any>', 'E1206: Dictionary required for argument 2']) + v9.CheckSourceDefAndScriptFailure(['ch_setoptions(1, {})'], ['E1013: Argument 1: type mismatch, expected channel but got number', 'E1217: Channel or Job required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['ch_setoptions(test_null_channel(), [])'], ['E1013: Argument 2: type mismatch, expected dict<any> but got list<any>', 'E1206: Dictionary required for argument 2']) endif enddef @@ -663,8 +663,8 @@ def Test_ch_status() if !has('channel') CheckFeature channel else - v9.CheckDefAndScriptFailure(['ch_status(1)'], ['E1013: Argument 1: type mismatch, expected channel but got number', 'E1217: Channel or Job required for argument 1']) - v9.CheckDefAndScriptFailure(['ch_status(test_null_channel(), [])'], ['E1013: Argument 2: type mismatch, expected dict<any> but got list<any>', 'E1206: Dictionary required for argument 2']) + v9.CheckSourceDefAndScriptFailure(['ch_status(1)'], ['E1013: Argument 1: type mismatch, expected channel but got number', 'E1217: Channel or Job required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['ch_status(test_null_channel(), [])'], ['E1013: Argument 2: type mismatch, expected dict<any> but got list<any>', 'E1206: Dictionary required for argument 2']) endif enddef @@ -672,8 +672,8 @@ def Test_char2nr() char2nr('ã‚', true)->assert_equal(12354) assert_fails('char2nr(true)', 'E1174:') - v9.CheckDefAndScriptFailure(['char2nr(10)'], ['E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1']) - v9.CheckDefAndScriptFailure(['char2nr("a", 2)'], ['E1013: Argument 2: type mismatch, expected bool but got number', 'E1212: Bool required for argument 2']) + v9.CheckSourceDefAndScriptFailure(['char2nr(10)'], ['E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['char2nr("a", 2)'], ['E1013: Argument 2: type mismatch, expected bool but got number', 'E1212: Bool required for argument 2']) assert_equal(97, char2nr('a', 1)) assert_equal(97, char2nr('a', 0)) assert_equal(97, char2nr('a', true)) @@ -687,10 +687,10 @@ def Test_charclass() enddef def Test_charcol() - v9.CheckDefAndScriptFailure(['charcol(10)'], ['E1013: Argument 1: type mismatch, expected string but got number', 'E1222: String or List required for argument 1']) - v9.CheckDefAndScriptFailure(['charcol({a: 10})'], ['E1013: Argument 1: type mismatch, expected string but got dict<number>', 'E1222: String or List required for argument 1']) - v9.CheckDefAndScriptFailure(['charcol(".", [])'], ['E1013: Argument 2: type mismatch, expected number but got list<any>', 'E1210: Number required for argument 2']) - v9.CheckDefExecAndScriptFailure(['charcol("")'], 'E1209: Invalid value for a line number') + v9.CheckSourceDefAndScriptFailure(['charcol(10)'], ['E1013: Argument 1: type mismatch, expected string but got number', 'E1222: String or List required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['charcol({a: 10})'], ['E1013: Argument 1: type mismatch, expected string but got dict<number>', 'E1222: String or List required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['charcol(".", [])'], ['E1013: Argument 2: type mismatch, expected number but got list<any>', 'E1210: Number required for argument 2']) + v9.CheckSourceDefExecAndScriptFailure(['charcol("")'], 'E1209: Invalid value for a line number') new setline(1, ['abcdefgh']) cursor(1, 4) @@ -701,10 +701,10 @@ def Test_charcol() enddef def Test_charidx() - v9.CheckDefAndScriptFailure(['charidx(0z10, 1)'], ['E1013: Argument 1: type mismatch, expected string but got blob', 'E1174: String required for argument 1']) - v9.CheckDefAndScriptFailure(['charidx("a", "b")'], ['E1013: Argument 2: type mismatch, expected number but got string', 'E1210: Number required for argument 2']) - v9.CheckDefAndScriptFailure(['charidx("a", 1, "")'], ['E1013: Argument 3: type mismatch, expected bool but got string', 'E1212: Bool required for argument 3']) - v9.CheckDefAndScriptFailure(['charidx("a", 1, 0, "")'], ['E1013: Argument 4: type mismatch, expected bool but got string', 'E1212: Bool required for argument 4']) + v9.CheckSourceDefAndScriptFailure(['charidx(0z10, 1)'], ['E1013: Argument 1: type mismatch, expected string but got blob', 'E1174: String required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['charidx("a", "b")'], ['E1013: Argument 2: type mismatch, expected number but got string', 'E1210: Number required for argument 2']) + v9.CheckSourceDefAndScriptFailure(['charidx("a", 1, "")'], ['E1013: Argument 3: type mismatch, expected bool but got string', 'E1212: Bool required for argument 3']) + v9.CheckSourceDefAndScriptFailure(['charidx("a", 1, 0, "")'], ['E1013: Argument 4: type mismatch, expected bool but got string', 'E1212: Bool required for argument 4']) charidx('', 0)->assert_equal(0) charidx('', 1)->assert_equal(-1) enddef @@ -714,15 +714,15 @@ def Test_chdir() enddef def Test_cindent() - v9.CheckDefAndScriptFailure(['cindent([])'], ['E1013: Argument 1: type mismatch, expected string but got list<any>', 'E1220: String or Number required for argument 1']) - v9.CheckDefAndScriptFailure(['cindent(null)'], ['E1013: Argument 1: type mismatch, expected string but got special', 'E1220: String or Number required for argument 1']) - v9.CheckDefExecAndScriptFailure(['cindent("")'], 'E1209: Invalid value for a line number') + v9.CheckSourceDefAndScriptFailure(['cindent([])'], ['E1013: Argument 1: type mismatch, expected string but got list<any>', 'E1220: String or Number required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['cindent(null)'], ['E1013: Argument 1: type mismatch, expected string but got special', 'E1220: String or Number required for argument 1']) + v9.CheckSourceDefExecAndScriptFailure(['cindent("")'], 'E1209: Invalid value for a line number') assert_equal(-1, cindent(0)) assert_equal(0, cindent('.')) enddef def Test_clearmatches() - v9.CheckDefAndScriptFailure(['clearmatches("x")'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1210: Number required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['clearmatches("x")'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1210: Number required for argument 1']) enddef def Test_col() @@ -735,26 +735,26 @@ def Test_col() assert_fails('col(true)', 'E1222:') - v9.CheckDefAndScriptFailure(['col(10)'], ['E1013: Argument 1: type mismatch, expected string but got number', 'E1222: String or List required for argument 1']) - v9.CheckDefAndScriptFailure(['col({a: 10})'], ['E1013: Argument 1: type mismatch, expected string but got dict<number>', 'E1222: String or List required for argument 1']) - v9.CheckDefAndScriptFailure(['col(true)'], ['E1013: Argument 1: type mismatch, expected string but got bool', 'E1222: String or List required for argument 1']) - v9.CheckDefAndScriptFailure(['col(".", [])'], ['E1013: Argument 2: type mismatch, expected number but got list<any>', 'E1210: Number required for argument 2']) - v9.CheckDefExecAndScriptFailure(['col("")'], 'E1209: Invalid value for a line number') + v9.CheckSourceDefAndScriptFailure(['col(10)'], ['E1013: Argument 1: type mismatch, expected string but got number', 'E1222: String or List required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['col({a: 10})'], ['E1013: Argument 1: type mismatch, expected string but got dict<number>', 'E1222: String or List required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['col(true)'], ['E1013: Argument 1: type mismatch, expected string but got bool', 'E1222: String or List required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['col(".", [])'], ['E1013: Argument 2: type mismatch, expected number but got list<any>', 'E1210: Number required for argument 2']) + v9.CheckSourceDefExecAndScriptFailure(['col("")'], 'E1209: Invalid value for a line number') bw! enddef def Test_complete() - v9.CheckDefAndScriptFailure(['complete("1", [])'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1210: Number required for argument 1']) - v9.CheckDefAndScriptFailure(['complete(1, {})'], ['E1013: Argument 2: type mismatch, expected list<any> but got dict<any>', 'E1211: List required for argument 2']) + v9.CheckSourceDefAndScriptFailure(['complete("1", [])'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1210: Number required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['complete(1, {})'], ['E1013: Argument 2: type mismatch, expected list<any> but got dict<any>', 'E1211: List required for argument 2']) enddef def Test_complete_add() - v9.CheckDefAndScriptFailure(['complete_add([])'], ['E1013: Argument 1: type mismatch, expected string but got list<any>', 'E1223: String or Dictionary required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['complete_add([])'], ['E1013: Argument 1: type mismatch, expected string but got list<any>', 'E1223: String or Dictionary required for argument 1']) enddef def Test_complete_info() - v9.CheckDefAndScriptFailure(['complete_info("")'], ['E1013: Argument 1: type mismatch, expected list<string> but got string', 'E1211: List required for argument 1']) - v9.CheckDefAndScriptFailure(['complete_info({})'], ['E1013: Argument 1: type mismatch, expected list<string> but got dict<any>', 'E1211: List required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['complete_info("")'], ['E1013: Argument 1: type mismatch, expected list<string> but got string', 'E1211: List required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['complete_info({})'], ['E1013: Argument 1: type mismatch, expected list<string> but got dict<any>', 'E1211: List required for argument 1']) assert_equal({'pum_visible': 0, 'mode': '', 'selected': -1, 'items': []}, complete_info()) assert_equal({'mode': '', 'items': []}, complete_info(['mode', 'items'])) enddef @@ -767,10 +767,10 @@ def Test_confirm() assert_fails('confirm(true)', 'E1174:') assert_fails('confirm("yes", true)', 'E1174:') assert_fails('confirm("yes", "maybe", 2, true)', 'E1174:') - v9.CheckDefAndScriptFailure(['confirm(1)'], ['E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1']) - v9.CheckDefAndScriptFailure(['confirm("a", 2)'], ['E1013: Argument 2: type mismatch, expected string but got number', 'E1174: String required for argument 2']) - v9.CheckDefAndScriptFailure(['confirm("a", "b", "c")'], ['E1013: Argument 3: type mismatch, expected number but got string', 'E1210: Number required for argument 3']) - v9.CheckDefAndScriptFailure(['confirm("a", "b", 3, 4)'], ['E1013: Argument 4: type mismatch, expected string but got number', 'E1174: String required for argument 4']) + v9.CheckSourceDefAndScriptFailure(['confirm(1)'], ['E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['confirm("a", 2)'], ['E1013: Argument 2: type mismatch, expected string but got number', 'E1174: String required for argument 2']) + v9.CheckSourceDefAndScriptFailure(['confirm("a", "b", "c")'], ['E1013: Argument 3: type mismatch, expected number but got string', 'E1210: Number required for argument 3']) + v9.CheckSourceDefAndScriptFailure(['confirm("a", "b", 3, 4)'], ['E1013: Argument 4: type mismatch, expected string but got number', 'E1174: String required for argument 4']) enddef def Test_copy_return_type() @@ -798,7 +798,7 @@ def Test_copy_return_type() var nll: list<list<number>> = [[1, 2]] nll->copy()[0]->extend(['x']) END - v9.CheckDefExecAndScriptFailure(lines, 'E1013: Argument 2: type mismatch, expected list<number> but got list<string> in extend()') + v9.CheckSourceDefExecAndScriptFailure(lines, 'E1013: Argument 2: type mismatch, expected list<number> but got list<string> in extend()') var nd: dict<number> = {a: 1, b: 2} assert_equal({a: 1, b: 2, c: 'x'}, nd->copy()->extend({c: 'x'})) @@ -806,7 +806,7 @@ def Test_copy_return_type() var ndd: dict<dict<number>> = {a: {x: 1, y: 2}} ndd->copy()['a']->extend({z: 'x'}) END - v9.CheckDefExecAndScriptFailure(lines, 'E1013: Argument 2: type mismatch, expected dict<number> but got dict<string> in extend()') + v9.CheckSourceDefExecAndScriptFailure(lines, 'E1013: Argument 2: type mismatch, expected dict<number> but got dict<string> in extend()') # after a deepcopy() the item type can also change var nll: list<list<number>> = [[1, 2]] @@ -822,9 +822,9 @@ enddef def Test_count() count('ABC ABC ABC', 'b', true)->assert_equal(3) count('ABC ABC ABC', 'b', false)->assert_equal(0) - v9.CheckDefAndScriptFailure(['count(10, 1)'], 'E1225: String, List or Dictionary required for argument 1') - v9.CheckDefAndScriptFailure(['count("a", [1], 2)'], ['E1013: Argument 3: type mismatch, expected bool but got number', 'E1212: Bool required for argument 3']) - v9.CheckDefAndScriptFailure(['count("a", [1], 0, "b")'], ['E1013: Argument 4: type mismatch, expected number but got string', 'E1210: Number required for argument 4']) + v9.CheckSourceDefAndScriptFailure(['count(10, 1)'], 'E1225: String, List or Dictionary required for argument 1') + v9.CheckSourceDefAndScriptFailure(['count("a", [1], 2)'], ['E1013: Argument 3: type mismatch, expected bool but got number', 'E1212: Bool required for argument 3']) + v9.CheckSourceDefAndScriptFailure(['count("a", [1], 0, "b")'], ['E1013: Argument 4: type mismatch, expected number but got string', 'E1210: Number required for argument 4']) count([1, 2, 2, 3], 2)->assert_equal(2) count([1, 2, 2, 3], 2, false, 2)->assert_equal(1) count({a: 1.1, b: 2.2, c: 1.1}, 1.1)->assert_equal(2) @@ -833,9 +833,9 @@ enddef def Test_cscope_connection() CheckFeature cscope assert_equal(0, cscope_connection()) - v9.CheckDefAndScriptFailure(['cscope_connection("a")'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1210: Number required for argument 1']) - v9.CheckDefAndScriptFailure(['cscope_connection(1, 2)'], ['E1013: Argument 2: type mismatch, expected string but got number', 'E1174: String required for argument 2']) - v9.CheckDefAndScriptFailure(['cscope_connection(1, "b", 3)'], ['E1013: Argument 3: type mismatch, expected string but got number', 'E1174: String required for argument 3']) + v9.CheckSourceDefAndScriptFailure(['cscope_connection("a")'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1210: Number required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['cscope_connection(1, 2)'], ['E1013: Argument 2: type mismatch, expected string but got number', 'E1174: String required for argument 2']) + v9.CheckSourceDefAndScriptFailure(['cscope_connection(1, "b", 3)'], ['E1013: Argument 3: type mismatch, expected string but got number', 'E1174: String required for argument 3']) enddef def Test_cursor() @@ -851,35 +851,35 @@ def Test_cursor() var lines =<< trim END cursor('2', 1) END - v9.CheckDefExecAndScriptFailure(lines, 'E1209:') - v9.CheckDefAndScriptFailure(['cursor(0z10, 1)'], ['E1013: Argument 1: type mismatch, expected number but got blob', 'E1224: String, Number or List required for argument 1']) - v9.CheckDefAndScriptFailure(['cursor(1, "2")'], ['E1013: Argument 2: type mismatch, expected number but got string', 'E1210: Number required for argument 2']) - v9.CheckDefAndScriptFailure(['cursor(1, 2, "3")'], ['E1013: Argument 3: type mismatch, expected number but got string', 'E1210: Number required for argument 3']) - v9.CheckDefExecAndScriptFailure(['cursor("", 2)'], 'E1209: Invalid value for a line number') + v9.CheckSourceDefExecAndScriptFailure(lines, 'E1209:') + v9.CheckSourceDefAndScriptFailure(['cursor(0z10, 1)'], ['E1013: Argument 1: type mismatch, expected number but got blob', 'E1224: String, Number or List required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['cursor(1, "2")'], ['E1013: Argument 2: type mismatch, expected number but got string', 'E1210: Number required for argument 2']) + v9.CheckSourceDefAndScriptFailure(['cursor(1, 2, "3")'], ['E1013: Argument 3: type mismatch, expected number but got string', 'E1210: Number required for argument 3']) + v9.CheckSourceDefExecAndScriptFailure(['cursor("", 2)'], 'E1209: Invalid value for a line number') enddef def Test_debugbreak() CheckMSWindows - v9.CheckDefAndScriptFailure(['debugbreak("x")'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1210: Number required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['debugbreak("x")'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1210: Number required for argument 1']) enddef def Test_deepcopy() - v9.CheckDefAndScriptFailure(['deepcopy({}, 2)'], ['E1013: Argument 2: type mismatch, expected bool but got number', 'E1212: Bool required for argument 2']) + v9.CheckSourceDefAndScriptFailure(['deepcopy({}, 2)'], ['E1013: Argument 2: type mismatch, expected bool but got number', 'E1212: Bool required for argument 2']) enddef def Test_delete() var res: bool = delete('doesnotexist') assert_equal(true, res) - v9.CheckDefAndScriptFailure(['delete(10)'], ['E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1']) - v9.CheckDefAndScriptFailure(['delete("a", 10)'], ['E1013: Argument 2: type mismatch, expected string but got number', 'E1174: String required for argument 2']) - v9.CheckDefExecAndScriptFailure(['delete("")'], 'E474: Invalid argument') + v9.CheckSourceDefAndScriptFailure(['delete(10)'], ['E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['delete("a", 10)'], ['E1013: Argument 2: type mismatch, expected string but got number', 'E1174: String required for argument 2']) + v9.CheckSourceDefExecAndScriptFailure(['delete("")'], 'E474: Invalid argument') enddef def Test_deletebufline() - v9.CheckDefAndScriptFailure(['deletebufline([], 2)'], ['E1013: Argument 1: type mismatch, expected string but got list<any>', 'E1220: String or Number required for argument 1']) - v9.CheckDefAndScriptFailure(['deletebufline("a", [])'], ['E1013: Argument 2: type mismatch, expected string but got list<any>', 'E1220: String or Number required for argument 2']) - v9.CheckDefAndScriptFailure(['deletebufline("a", 2, 0z10)'], ['E1013: Argument 3: type mismatch, expected string but got blob', 'E1220: String or Number required for argument 3']) + v9.CheckSourceDefAndScriptFailure(['deletebufline([], 2)'], ['E1013: Argument 1: type mismatch, expected string but got list<any>', 'E1220: String or Number required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['deletebufline("a", [])'], ['E1013: Argument 2: type mismatch, expected string but got list<any>', 'E1220: String or Number required for argument 2']) + v9.CheckSourceDefAndScriptFailure(['deletebufline("a", 2, 0z10)'], ['E1013: Argument 3: type mismatch, expected string but got blob', 'E1220: String or Number required for argument 3']) new setline(1, ['one', 'two']) deletebufline('', 1) @@ -892,58 +892,58 @@ def Test_deletebufline() enddef def Test_diff_filler() - v9.CheckDefAndScriptFailure(['diff_filler([])'], ['E1013: Argument 1: type mismatch, expected string but got list<any>', 'E1220: String or Number required for argument 1']) - v9.CheckDefAndScriptFailure(['diff_filler(true)'], ['E1013: Argument 1: type mismatch, expected string but got bool', 'E1220: String or Number required for argument 1']) - v9.CheckDefExecAndScriptFailure(['diff_filler("")'], 'E1209: Invalid value for a line number') + v9.CheckSourceDefAndScriptFailure(['diff_filler([])'], ['E1013: Argument 1: type mismatch, expected string but got list<any>', 'E1220: String or Number required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['diff_filler(true)'], ['E1013: Argument 1: type mismatch, expected string but got bool', 'E1220: String or Number required for argument 1']) + v9.CheckSourceDefExecAndScriptFailure(['diff_filler("")'], 'E1209: Invalid value for a line number') assert_equal(0, diff_filler(1)) assert_equal(0, diff_filler('.')) enddef def Test_diff_hlID() - v9.CheckDefAndScriptFailure(['diff_hlID(0z10, 1)'], ['E1013: Argument 1: type mismatch, expected string but got blob', 'E1220: String or Number required for argument 1']) - v9.CheckDefAndScriptFailure(['diff_hlID(1, "a")'], ['E1013: Argument 2: type mismatch, expected number but got string', 'E1210: Number required for argument 2']) - v9.CheckDefExecAndScriptFailure(['diff_hlID("", 10)'], 'E1209: Invalid value for a line number') + v9.CheckSourceDefAndScriptFailure(['diff_hlID(0z10, 1)'], ['E1013: Argument 1: type mismatch, expected string but got blob', 'E1220: String or Number required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['diff_hlID(1, "a")'], ['E1013: Argument 2: type mismatch, expected number but got string', 'E1210: Number required for argument 2']) + v9.CheckSourceDefExecAndScriptFailure(['diff_hlID("", 10)'], 'E1209: Invalid value for a line number') enddef def Test_digraph_get() - v9.CheckDefAndScriptFailure(['digraph_get(10)'], ['E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1']) - v9.CheckDefExecAndScriptFailure(['digraph_get("")'], 'E1214: Digraph must be just two characters') + v9.CheckSourceDefAndScriptFailure(['digraph_get(10)'], ['E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1']) + v9.CheckSourceDefExecAndScriptFailure(['digraph_get("")'], 'E1214: Digraph must be just two characters') enddef def Test_digraph_getlist() - v9.CheckDefAndScriptFailure(['digraph_getlist(10)'], ['E1013: Argument 1: type mismatch, expected bool but got number', 'E1212: Bool required for argument 1']) - v9.CheckDefAndScriptFailure(['digraph_getlist("")'], ['E1013: Argument 1: type mismatch, expected bool but got string', 'E1212: Bool required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['digraph_getlist(10)'], ['E1013: Argument 1: type mismatch, expected bool but got number', 'E1212: Bool required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['digraph_getlist("")'], ['E1013: Argument 1: type mismatch, expected bool but got string', 'E1212: Bool required for argument 1']) enddef def Test_digraph_set() - v9.CheckDefAndScriptFailure(['digraph_set(10, "a")'], ['E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1']) - v9.CheckDefAndScriptFailure(['digraph_set("ab", 0z10)'], ['E1013: Argument 2: type mismatch, expected string but got blob', 'E1174: String required for argument 2']) - v9.CheckDefExecAndScriptFailure(['digraph_set("", "a")'], 'E1214: Digraph must be just two characters') + v9.CheckSourceDefAndScriptFailure(['digraph_set(10, "a")'], ['E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['digraph_set("ab", 0z10)'], ['E1013: Argument 2: type mismatch, expected string but got blob', 'E1174: String required for argument 2']) + v9.CheckSourceDefExecAndScriptFailure(['digraph_set("", "a")'], 'E1214: Digraph must be just two characters') enddef def Test_digraph_setlist() - v9.CheckDefAndScriptFailure(['digraph_setlist("a")'], ['E1013: Argument 1: type mismatch, expected list<string> but got string', 'E1216: digraph_setlist() argument must be a list of lists with two items']) - v9.CheckDefAndScriptFailure(['digraph_setlist({})'], ['E1013: Argument 1: type mismatch, expected list<string> but got dict<any>', 'E1216: digraph_setlist() argument must be a list of lists with two items']) + v9.CheckSourceDefAndScriptFailure(['digraph_setlist("a")'], ['E1013: Argument 1: type mismatch, expected list<string> but got string', 'E1216: digraph_setlist() argument must be a list of lists with two items']) + v9.CheckSourceDefAndScriptFailure(['digraph_setlist({})'], ['E1013: Argument 1: type mismatch, expected list<string> but got dict<any>', 'E1216: digraph_setlist() argument must be a list of lists with two items']) enddef def Test_echoraw() - v9.CheckDefAndScriptFailure(['echoraw(1)'], ['E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1']) - v9.CheckDefAndScriptFailure(['echoraw(["x"])'], ['E1013: Argument 1: type mismatch, expected string but got list<string>', 'E1174: String required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['echoraw(1)'], ['E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['echoraw(["x"])'], ['E1013: Argument 1: type mismatch, expected string but got list<string>', 'E1174: String required for argument 1']) enddef def Test_escape() - v9.CheckDefAndScriptFailure(['escape(10, " ")'], ['E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1']) - v9.CheckDefAndScriptFailure(['escape(true, false)'], ['E1013: Argument 1: type mismatch, expected string but got bool', 'E1174: String required for argument 1']) - v9.CheckDefAndScriptFailure(['escape("a", 10)'], ['E1013: Argument 2: type mismatch, expected string but got number', 'E1174: String required for argument 2']) + v9.CheckSourceDefAndScriptFailure(['escape(10, " ")'], ['E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['escape(true, false)'], ['E1013: Argument 1: type mismatch, expected string but got bool', 'E1174: String required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['escape("a", 10)'], ['E1013: Argument 2: type mismatch, expected string but got number', 'E1174: String required for argument 2']) assert_equal('a\:b', escape("a:b", ":")) escape('abc', '')->assert_equal('abc') escape('', ':')->assert_equal('') enddef def Test_eval() - v9.CheckDefAndScriptFailure(['eval(10)'], ['E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1']) - v9.CheckDefAndScriptFailure(['eval(null)'], ['E1013: Argument 1: type mismatch, expected string but got special', 'E1174: String required for argument 1']) - v9.CheckDefExecAndScriptFailure(['eval("")'], 'E15: Invalid expression') + v9.CheckSourceDefAndScriptFailure(['eval(10)'], ['E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['eval(null)'], ['E1013: Argument 1: type mismatch, expected string but got special', 'E1174: String required for argument 1']) + v9.CheckSourceDefExecAndScriptFailure(['eval("")'], 'E15: Invalid expression') assert_equal(2, eval('1 + 1')) enddef @@ -951,8 +951,8 @@ def Test_executable() assert_false(executable("")) assert_false(executable(test_null_string())) - v9.CheckDefExecFailure(['echo executable(123)'], 'E1013:') - v9.CheckDefExecFailure(['echo executable(true)'], 'E1013:') + v9.CheckSourceDefExecFailure(['echo executable(123)'], 'E1013:') + v9.CheckSourceDefExecFailure(['echo executable(true)'], 'E1013:') enddef def Test_execute() @@ -961,22 +961,22 @@ def Test_execute() res = execute(["echo 'here'", "echo 'there'"]) assert_equal("\nhere\nthere", res) - v9.CheckDefAndScriptFailure(['execute(123)'], ['E1013: Argument 1: type mismatch, expected string but got number', 'E1222: String or List required for argument 1']) - v9.CheckDefFailure(['execute([123])'], 'E1013: Argument 1: type mismatch, expected list<string> but got list<number>') - v9.CheckDefExecFailure(['echo execute(["xx", 123])'], 'E492') - v9.CheckDefAndScriptFailure(['execute("xx", 123)'], ['E1013: Argument 2: type mismatch, expected string but got number', 'E1174: String required for argument 2']) + v9.CheckSourceDefAndScriptFailure(['execute(123)'], ['E1013: Argument 1: type mismatch, expected string but got number', 'E1222: String or List required for argument 1']) + v9.CheckSourceDefFailure(['execute([123])'], 'E1013: Argument 1: type mismatch, expected list<string> but got list<number>') + v9.CheckSourceDefExecFailure(['echo execute(["xx", 123])'], 'E492') + v9.CheckSourceDefAndScriptFailure(['execute("xx", 123)'], ['E1013: Argument 2: type mismatch, expected string but got number', 'E1174: String required for argument 2']) enddef def Test_exepath() - v9.CheckDefExecFailure(['echo exepath(true)'], 'E1013:') - v9.CheckDefExecFailure(['echo exepath(v:null)'], 'E1013:') - v9.CheckDefExecFailure(['echo exepath("")'], 'E1175:') + v9.CheckSourceDefExecFailure(['echo exepath(true)'], 'E1013:') + v9.CheckSourceDefExecFailure(['echo exepath(v:null)'], 'E1013:') + v9.CheckSourceDefExecFailure(['echo exepath("")'], 'E1175:') enddef command DoSomeCommand let g:didSomeCommand = 4 def Test_exists() - v9.CheckDefAndScriptFailure(['exists(10)'], ['E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['exists(10)'], ['E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1']) call assert_equal(1, exists('&tabstop')) var lines =<< trim END @@ -985,14 +985,14 @@ def Test_exists() endif endif END - v9.CheckDefFailure(lines, 'E113:') - v9.CheckScriptSuccess(lines) + v9.CheckSourceDefFailure(lines, 'E113:') + v9.CheckSourceScriptSuccess(lines) enddef def Test_exists_compiled() call assert_equal(1, exists_compiled('&tabstop')) - v9.CheckDefAndScriptFailure(['exists_compiled(10)'], ['E1232:', 'E1233:']) - v9.CheckDefAndScriptFailure(['exists_compiled(v:progname)'], ['E1232:', 'E1233:']) + v9.CheckSourceDefAndScriptFailure(['exists_compiled(10)'], ['E1232:', 'E1233:']) + v9.CheckSourceDefAndScriptFailure(['exists_compiled(v:progname)'], ['E1232:', 'E1233:']) if exists_compiled('+newoption') if &newoption == 'ok' @@ -1044,9 +1044,9 @@ def Test_expand() split SomeFile expand('%', true, true)->assert_equal(['SomeFile']) close - v9.CheckDefAndScriptFailure(['expand(1)'], ['E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1']) - v9.CheckDefAndScriptFailure(['expand("a", 2)'], ['E1013: Argument 2: type mismatch, expected bool but got number', 'E1212: Bool required for argument 2']) - v9.CheckDefAndScriptFailure(['expand("a", true, 2)'], ['E1013: Argument 3: type mismatch, expected bool but got number', 'E1212: Bool required for argument 3']) + v9.CheckSourceDefAndScriptFailure(['expand(1)'], ['E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['expand("a", 2)'], ['E1013: Argument 2: type mismatch, expected bool but got number', 'E1212: Bool required for argument 2']) + v9.CheckSourceDefAndScriptFailure(['expand("a", true, 2)'], ['E1013: Argument 3: type mismatch, expected bool but got number', 'E1212: Bool required for argument 3']) expand('')->assert_equal('') var caught = false @@ -1065,8 +1065,8 @@ def Test_expandcmd() assert_equal("yes", expandcmd("`={a: 'yes'}['a']`")) expandcmd('')->assert_equal('') - v9.CheckDefAndScriptFailure(['expandcmd([1])'], ['E1013: Argument 1: type mismatch, expected string but got list<number>', 'E1174: String required for argument 1']) - v9.CheckDefAndScriptFailure(['expandcmd("abc", [])'], ['E1013: Argument 2: type mismatch, expected dict<any> but got list<any>', 'E1206: Dictionary required for argument 2']) + v9.CheckSourceDefAndScriptFailure(['expandcmd([1])'], ['E1013: Argument 1: type mismatch, expected string but got list<number>', 'E1174: String required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['expandcmd("abc", [])'], ['E1013: Argument 2: type mismatch, expected dict<any> but got list<any>', 'E1206: Dictionary required for argument 2']) enddef def Test_extend_arg_types() @@ -1093,7 +1093,7 @@ def Test_extend_arg_types() dany->extend({b: 'x'}) assert_equal({a: 0, b: 'x'}, dany) END - v9.CheckDefAndScriptSuccess(lines) + v9.CheckSourceDefAndScriptSuccess(lines) lines =<< trim END assert_equal([1, 2, "x"], extend([1, 2], ["x"])) @@ -1101,17 +1101,17 @@ def Test_extend_arg_types() assert_equal({a: 1, b: "x"}, extend({a: 1}, {b: "x"})) END - v9.CheckDefAndScriptSuccess(lines) + v9.CheckSourceDefAndScriptSuccess(lines) - v9.CheckDefAndScriptFailure(['extend("a", 1)'], ['E1013: Argument 1: type mismatch, expected list<any> but got string', 'E712: Argument of extend() must be a List or Dictionary']) - v9.CheckDefAndScriptFailure(['extend([1, 2], 3)'], ['E1013: Argument 2: type mismatch, expected list<any> but got number', 'E712: Argument of extend() must be a List or Dictionary']) - v9.CheckDefAndScriptFailure(['var ll = [1, 2]', 'extend(ll, ["x"])'], ['E1013: Argument 2: type mismatch, expected list<number> but got list<string>', 'E1013: Argument 2: type mismatch, expected list<number> but got list<string>']) - v9.CheckDefFailure(['extend([1, 2], [3], "x")'], 'E1013: Argument 3: type mismatch, expected number but got string') + v9.CheckSourceDefAndScriptFailure(['extend("a", 1)'], ['E1013: Argument 1: type mismatch, expected list<any> but got string', 'E712: Argument of extend() must be a List or Dictionary']) + v9.CheckSourceDefAndScriptFailure(['extend([1, 2], 3)'], ['E1013: Argument 2: type mismatch, expected list<any> but got number', 'E712: Argument of extend() must be a List or Dictionary']) + v9.CheckSourceDefAndScriptFailure(['var ll = [1, 2]', 'extend(ll, ["x"])'], ['E1013: Argument 2: type mismatch, expected list<number> but got list<string>', 'E1013: Argument 2: type mismatch, expected list<number> but got list<string>']) + v9.CheckSourceDefFailure(['extend([1, 2], [3], "x")'], 'E1013: Argument 3: type mismatch, expected number but got string') - v9.CheckDefFailure(['extend({a: 1}, 42)'], 'E1013: Argument 2: type mismatch, expected dict<any> but got number') - v9.CheckDefFailure(['extend({a: 1}, {b: 2}, 1)'], 'E1013: Argument 3: type mismatch, expected string but got number') + v9.CheckSourceDefFailure(['extend({a: 1}, 42)'], 'E1013: Argument 2: type mismatch, expected dict<any> but got number') + v9.CheckSourceDefFailure(['extend({a: 1}, {b: 2}, 1)'], 'E1013: Argument 3: type mismatch, expected string but got number') - v9.CheckScriptFailure(['vim9script', 'var l = [1]', 'extend(l, ["b", 1])'], 'E1013: Argument 2: type mismatch, expected list<number> but got list<any> in extend()') + v9.CheckSourceScriptFailure(['vim9script', 'var l = [1]', 'extend(l, ["b", 1])'], 'E1013: Argument 2: type mismatch, expected list<number> but got list<any> in extend()') enddef func g:ExtendDict(d) @@ -1123,26 +1123,26 @@ def Test_extend_dict_item_type() var d: dict<number> = {a: 1} extend(d, {b: 2}) END - v9.CheckDefAndScriptSuccess(lines) + v9.CheckSourceDefAndScriptSuccess(lines) lines =<< trim END var d: dict<number> = {a: 1} extend(d, {b: 'x'}) END - v9.CheckDefAndScriptFailure(lines, 'E1013: Argument 2: type mismatch, expected dict<number> but got dict<string>', 2) + v9.CheckSourceDefAndScriptFailure(lines, 'E1013: Argument 2: type mismatch, expected dict<number> but got dict<string>', 2) lines =<< trim END var d: dict<number> = {a: 1} g:ExtendDict(d) END - v9.CheckDefExecFailure(lines, 'E1012: Type mismatch; expected number but got string', 0) - v9.CheckScriptFailure(['vim9script'] + lines, 'E1012:', 1) + v9.CheckSourceDefExecFailure(lines, 'E1012: Type mismatch; expected number but got string', 0) + v9.CheckSourceScriptFailure(['vim9script'] + lines, 'E1012:', 1) lines =<< trim END var d: dict<bool> extend(d, {b: 0}) END - v9.CheckDefAndScriptFailure(lines, 'E1013: Argument 2: type mismatch, expected dict<bool> but got dict<number>', 2) + v9.CheckSourceDefAndScriptFailure(lines, 'E1013: Argument 2: type mismatch, expected dict<bool> but got dict<number>', 2) enddef func g:ExtendList(l) @@ -1154,26 +1154,26 @@ def Test_extend_list_item_type() var l: list<number> = [1] extend(l, [2]) END - v9.CheckDefAndScriptSuccess(lines) + v9.CheckSourceDefAndScriptSuccess(lines) lines =<< trim END var l: list<number> = [1] extend(l, ['x']) END - v9.CheckDefAndScriptFailure(lines, 'E1013: Argument 2: type mismatch, expected list<number> but got list<string>', 2) + v9.CheckSourceDefAndScriptFailure(lines, 'E1013: Argument 2: type mismatch, expected list<number> but got list<string>', 2) lines =<< trim END var l: list<number> = [1] g:ExtendList(l) END - v9.CheckDefExecFailure(lines, 'E1012: Type mismatch; expected number but got string', 0) - v9.CheckScriptFailure(['vim9script'] + lines, 'E1012:', 1) + v9.CheckSourceDefExecFailure(lines, 'E1012: Type mismatch; expected number but got string', 0) + v9.CheckSourceScriptFailure(['vim9script'] + lines, 'E1012:', 1) lines =<< trim END var l: list<bool> extend(l, [0]) END - v9.CheckDefAndScriptFailure(lines, 'E1013: Argument 2: type mismatch, expected list<bool> but got list<number>', 2) + v9.CheckSourceDefAndScriptFailure(lines, 'E1013: Argument 2: type mismatch, expected list<bool> but got list<number>', 2) enddef def Test_extend_return_type() @@ -1203,7 +1203,7 @@ def Test_extend_with_error_function() Test() END - v9.CheckScriptFailure(lines, 'E1001: Variable not found: m') + v9.CheckSourceScriptFailure(lines, 'E1001: Variable not found: m') enddef def Test_extend_const() @@ -1211,20 +1211,20 @@ def Test_extend_const() const l = [1, 2] extend(l, [3]) END - v9.CheckDefFailure(lines, 'E1307: Argument 1: Trying to modify a const list<number>') + v9.CheckSourceDefFailure(lines, 'E1307: Argument 1: Trying to modify a const list<number>') lines =<< trim END const d = {a: 1, b: 2} extend(d, {c: 3}) END - v9.CheckDefFailure(lines, 'E1307: Argument 1: Trying to modify a const dict<number>') + v9.CheckSourceDefFailure(lines, 'E1307: Argument 1: Trying to modify a const dict<number>') lines =<< trim END final d = {a: 1, b: 2} extend(d, {c: 3}) assert_equal({a: 1, b: 2, c: 3}, d) END - v9.CheckDefSuccess(lines) + v9.CheckSourceDefSuccess(lines) # item in a for loop is final lines =<< trim END @@ -1233,23 +1233,23 @@ def Test_extend_const() item->extend({x: 2}) endfor END - v9.CheckDefSuccess(lines) + v9.CheckSourceDefSuccess(lines) enddef def Test_extendnew() assert_equal([1, 2, 'a'], extendnew([1, 2], ['a'])) assert_equal({one: 1, two: 'a'}, extendnew({one: 1}, {two: 'a'})) - v9.CheckDefAndScriptFailure(['extendnew({a: 1}, 42)'], ['E1013: Argument 2: type mismatch, expected dict<number> but got number', 'E712: Argument of extendnew() must be a List or Dictionary']) - v9.CheckDefAndScriptFailure(['extendnew({a: 1}, [42])'], ['E1013: Argument 2: type mismatch, expected dict<number> but got list<number>', 'E712: Argument of extendnew() must be a List or Dictionary']) - v9.CheckDefAndScriptFailure(['extendnew([1, 2], "x")'], ['E1013: Argument 2: type mismatch, expected list<number> but got string', 'E712: Argument of extendnew() must be a List or Dictionary']) - v9.CheckDefAndScriptFailure(['extendnew([1, 2], {x: 1})'], ['E1013: Argument 2: type mismatch, expected list<number> but got dict<number>', 'E712: Argument of extendnew() must be a List or Dictionary']) + v9.CheckSourceDefAndScriptFailure(['extendnew({a: 1}, 42)'], ['E1013: Argument 2: type mismatch, expected dict<number> but got number', 'E712: Argument of extendnew() must be a List or Dictionary']) + v9.CheckSourceDefAndScriptFailure(['extendnew({a: 1}, [42])'], ['E1013: Argument 2: type mismatch, expected dict<number> but got list<number>', 'E712: Argument of extendnew() must be a List or Dictionary']) + v9.CheckSourceDefAndScriptFailure(['extendnew([1, 2], "x")'], ['E1013: Argument 2: type mismatch, expected list<number> but got string', 'E712: Argument of extendnew() must be a List or Dictionary']) + v9.CheckSourceDefAndScriptFailure(['extendnew([1, 2], {x: 1})'], ['E1013: Argument 2: type mismatch, expected list<number> but got dict<number>', 'E712: Argument of extendnew() must be a List or Dictionary']) enddef def Test_feedkeys() - v9.CheckDefAndScriptFailure(['feedkeys(10)'], ['E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1']) - v9.CheckDefAndScriptFailure(['feedkeys("x", 10)'], ['E1013: Argument 2: type mismatch, expected string but got number', 'E1174: String required for argument 2']) - v9.CheckDefAndScriptFailure(['feedkeys([], {})'], ['E1013: Argument 1: type mismatch, expected string but got list<any>', 'E1174: String required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['feedkeys(10)'], ['E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['feedkeys("x", 10)'], ['E1013: Argument 2: type mismatch, expected string but got number', 'E1174: String required for argument 2']) + v9.CheckSourceDefAndScriptFailure(['feedkeys([], {})'], ['E1013: Argument 1: type mismatch, expected string but got list<any>', 'E1174: String required for argument 1']) g:TestVar = 1 feedkeys(":g:TestVar = 789\n", 'xt') assert_equal(789, g:TestVar) @@ -1260,16 +1260,16 @@ def Test_filereadable() assert_false(filereadable("")) assert_false(filereadable(test_null_string())) - v9.CheckDefExecFailure(['echo filereadable(123)'], 'E1013:') - v9.CheckDefExecFailure(['echo filereadable(true)'], 'E1013:') + v9.CheckSourceDefExecFailure(['echo filereadable(123)'], 'E1013:') + v9.CheckSourceDefExecFailure(['echo filereadable(true)'], 'E1013:') enddef def Test_filewritable() assert_false(filewritable("")) assert_false(filewritable(test_null_string())) - v9.CheckDefExecFailure(['echo filewritable(123)'], 'E1013:') - v9.CheckDefExecFailure(['echo filewritable(true)'], 'E1013:') + v9.CheckSourceDefExecFailure(['echo filewritable(123)'], 'E1013:') + v9.CheckSourceDefExecFailure(['echo filewritable(true)'], 'E1013:') enddef def Test_finddir() @@ -1278,20 +1278,20 @@ def Test_finddir() var lines =<< trim END var l: list<string> = finddir('nothing', '*;', -1) END - v9.CheckDefAndScriptSuccess(lines) + v9.CheckSourceDefAndScriptSuccess(lines) delete('Xtestdir', 'rf') - v9.CheckDefAndScriptFailure(['finddir(true)'], ['E1013: Argument 1: type mismatch, expected string but got bool', 'E1174: String required for argument 1']) - v9.CheckDefAndScriptFailure(['finddir(v:null)'], ['E1013: Argument 1: type mismatch, expected string but got special', 'E1174: String required for argument 1']) - v9.CheckDefExecFailure(['echo finddir("")'], 'E1175:') - v9.CheckDefAndScriptFailure(['finddir("a", [])'], ['E1013: Argument 2: type mismatch, expected string but got list<any>', 'E1174: String required for argument 2']) - v9.CheckDefAndScriptFailure(['finddir("a", "b", "c")'], ['E1013: Argument 3: type mismatch, expected number but got string', 'E1210: Number required for argument 3']) + v9.CheckSourceDefAndScriptFailure(['finddir(true)'], ['E1013: Argument 1: type mismatch, expected string but got bool', 'E1174: String required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['finddir(v:null)'], ['E1013: Argument 1: type mismatch, expected string but got special', 'E1174: String required for argument 1']) + v9.CheckSourceDefExecFailure(['echo finddir("")'], 'E1175:') + v9.CheckSourceDefAndScriptFailure(['finddir("a", [])'], ['E1013: Argument 2: type mismatch, expected string but got list<any>', 'E1174: String required for argument 2']) + v9.CheckSourceDefAndScriptFailure(['finddir("a", "b", "c")'], ['E1013: Argument 3: type mismatch, expected number but got string', 'E1210: Number required for argument 3']) finddir('abc', '')->assert_equal('') - v9.CheckDefFailure(['var s: list<string> = finddir("foo")'], 'E1012: Type mismatch; expected list<string> but got string') - v9.CheckDefFailure(['var s: list<string> = finddir("foo", "path")'], 'E1012: Type mismatch; expected list<string> but got string') + v9.CheckSourceDefFailure(['var s: list<string> = finddir("foo")'], 'E1012: Type mismatch; expected list<string> but got string') + v9.CheckSourceDefFailure(['var s: list<string> = finddir("foo", "path")'], 'E1012: Type mismatch; expected list<string> but got string') # with third argument only runtime type checking - v9.CheckDefCompileSuccess(['var s: list<string> = finddir("foo", "path", 1)']) + v9.CheckSourceDefCompileSuccess(['var s: list<string> = finddir("foo", "path", 1)']) enddef def Test_findfile() @@ -1299,13 +1299,13 @@ def Test_findfile() var lines =<< trim END var l: list<string> = findfile('nothing', '*;', -1) END - v9.CheckDefAndScriptSuccess(lines) + v9.CheckSourceDefAndScriptSuccess(lines) - v9.CheckDefExecFailure(['findfile(true)'], 'E1013: Argument 1: type mismatch, expected string but got bool') - v9.CheckDefExecFailure(['findfile(v:null)'], 'E1013: Argument 1: type mismatch, expected string but got special') - v9.CheckDefExecFailure(['findfile("")'], 'E1175:') - v9.CheckDefAndScriptFailure(['findfile("a", [])'], ['E1013: Argument 2: type mismatch, expected string but got list<any>', 'E1174: String required for argument 2']) - v9.CheckDefAndScriptFailure(['findfile("a", "b", "c")'], ['E1013: Argument 3: type mismatch, expected number but got string', 'E1210: Number required for argument 3']) + v9.CheckSourceDefExecFailure(['findfile(true)'], 'E1013: Argument 1: type mismatch, expected string but got bool') + v9.CheckSourceDefExecFailure(['findfile(v:null)'], 'E1013: Argument 1: type mismatch, expected string but got special') + v9.CheckSourceDefExecFailure(['findfile("")'], 'E1175:') + v9.CheckSourceDefAndScriptFailure(['findfile("a", [])'], ['E1013: Argument 2: type mismatch, expected string but got list<any>', 'E1174: String required for argument 2']) + v9.CheckSourceDefAndScriptFailure(['findfile("a", "b", "c")'], ['E1013: Argument 3: type mismatch, expected number but got string', 'E1210: Number required for argument 3']) findfile('abc', '')->assert_equal('') enddef @@ -1313,7 +1313,7 @@ def Test_flatten() var lines =<< trim END echo flatten([1, 2, 3]) END - v9.CheckDefAndScriptFailure(lines, 'E1158:') + v9.CheckSourceDefAndScriptFailure(lines, 'E1158:') enddef def Test_flattennew() @@ -1328,106 +1328,106 @@ def Test_flattennew() var ll: list<list<string>> = [['a', 'b', 'c']] assert_equal(['a', 'b', 'c'], ll->flattennew()) END - v9.CheckDefAndScriptSuccess(lines) + v9.CheckSourceDefAndScriptSuccess(lines) - v9.CheckDefAndScriptFailure(['flattennew({})'], ['E1013: Argument 1: type mismatch, expected list<any> but got dict<any>', 'E1211: List required for argument 1']) - v9.CheckDefAndScriptFailure(['flattennew([], "1")'], ['E1013: Argument 2: type mismatch, expected number but got string', 'E1210: Number required for argument 2']) + v9.CheckSourceDefAndScriptFailure(['flattennew({})'], ['E1013: Argument 1: type mismatch, expected list<any> but got dict<any>', 'E1211: List required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['flattennew([], "1")'], ['E1013: Argument 2: type mismatch, expected number but got string', 'E1210: Number required for argument 2']) enddef " Test for float functions argument type def Test_float_funcs_args() # acos() - v9.CheckDefAndScriptFailure(['acos("a")'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1219: Float or Number required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['acos("a")'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1219: Float or Number required for argument 1']) assert_equal('1.570796', string(acos(0.0))) # asin() - v9.CheckDefAndScriptFailure(['asin("a")'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1219: Float or Number required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['asin("a")'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1219: Float or Number required for argument 1']) assert_equal('0.0', string(asin(0.0))) # atan() - v9.CheckDefAndScriptFailure(['atan("a")'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1219: Float or Number required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['atan("a")'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1219: Float or Number required for argument 1']) assert_equal('0.0', string(atan(0.0))) # atan2() - v9.CheckDefAndScriptFailure(['atan2("a", 1.1)'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1219: Float or Number required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['atan2("a", 1.1)'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1219: Float or Number required for argument 1']) assert_equal('-2.356194', string(atan2(-1, -1))) - v9.CheckDefAndScriptFailure(['atan2(1.2, "a")'], ['E1013: Argument 2: type mismatch, expected number but got string', 'E1219: Float or Number required for argument 2']) - v9.CheckDefAndScriptFailure(['atan2(1.2)'], ['E119:', 'E119:']) + v9.CheckSourceDefAndScriptFailure(['atan2(1.2, "a")'], ['E1013: Argument 2: type mismatch, expected number but got string', 'E1219: Float or Number required for argument 2']) + v9.CheckSourceDefAndScriptFailure(['atan2(1.2)'], ['E119:', 'E119:']) # ceil() - v9.CheckDefAndScriptFailure(['ceil("a")'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1219: Float or Number required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['ceil("a")'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1219: Float or Number required for argument 1']) assert_equal('2.0', string(ceil(2.0))) # cos() - v9.CheckDefAndScriptFailure(['cos("a")'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1219: Float or Number required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['cos("a")'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1219: Float or Number required for argument 1']) assert_equal('1.0', string(cos(0.0))) # cosh() - v9.CheckDefAndScriptFailure(['cosh("a")'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1219: Float or Number required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['cosh("a")'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1219: Float or Number required for argument 1']) assert_equal('1.0', string(cosh(0.0))) # exp() - v9.CheckDefAndScriptFailure(['exp("a")'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1219: Float or Number required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['exp("a")'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1219: Float or Number required for argument 1']) assert_equal('1.0', string(exp(0.0))) # float2nr() - v9.CheckDefAndScriptFailure(['float2nr("a")'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1219: Float or Number required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['float2nr("a")'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1219: Float or Number required for argument 1']) assert_equal(1, float2nr(1.234)) # floor() - v9.CheckDefAndScriptFailure(['floor("a")'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1219: Float or Number required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['floor("a")'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1219: Float or Number required for argument 1']) assert_equal('2.0', string(floor(2.0))) # fmod() - v9.CheckDefAndScriptFailure(['fmod(1.1, "a")'], ['E1013: Argument 2: type mismatch, expected number but got string', 'E1219: Float or Number required for argument 2']) - v9.CheckDefAndScriptFailure(['fmod("a", 1.1)'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1219: Float or Number required for argument 1']) - v9.CheckDefAndScriptFailure(['fmod(1.1)'], ['E119:', 'E119:']) + v9.CheckSourceDefAndScriptFailure(['fmod(1.1, "a")'], ['E1013: Argument 2: type mismatch, expected number but got string', 'E1219: Float or Number required for argument 2']) + v9.CheckSourceDefAndScriptFailure(['fmod("a", 1.1)'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1219: Float or Number required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['fmod(1.1)'], ['E119:', 'E119:']) assert_equal('0.13', string(fmod(12.33, 1.22))) # isinf() - v9.CheckDefAndScriptFailure(['isinf("a")'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1219: Float or Number required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['isinf("a")'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1219: Float or Number required for argument 1']) assert_equal(1, isinf(1.0 / 0.0)) # isnan() - v9.CheckDefAndScriptFailure(['isnan("a")'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1219: Float or Number required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['isnan("a")'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1219: Float or Number required for argument 1']) assert_true(isnan(0.0 / 0.0)) # log() - v9.CheckDefAndScriptFailure(['log("a")'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1219: Float or Number required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['log("a")'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1219: Float or Number required for argument 1']) assert_equal('0.0', string(log(1.0))) # log10() - v9.CheckDefAndScriptFailure(['log10("a")'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1219: Float or Number required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['log10("a")'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1219: Float or Number required for argument 1']) assert_equal('0.0', string(log10(1.0))) # pow() - v9.CheckDefAndScriptFailure(['pow("a", 1.1)'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1219: Float or Number required for argument 1']) - v9.CheckDefAndScriptFailure(['pow(1.1, "a")'], ['E1013: Argument 2: type mismatch, expected number but got string', 'E1219: Float or Number required for argument 2']) - v9.CheckDefAndScriptFailure(['pow(1.1)'], ['E119:', 'E119:']) + v9.CheckSourceDefAndScriptFailure(['pow("a", 1.1)'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1219: Float or Number required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['pow(1.1, "a")'], ['E1013: Argument 2: type mismatch, expected number but got string', 'E1219: Float or Number required for argument 2']) + v9.CheckSourceDefAndScriptFailure(['pow(1.1)'], ['E119:', 'E119:']) assert_equal('1.0', string(pow(0.0, 0.0))) # round() - v9.CheckDefAndScriptFailure(['round("a")'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1219: Float or Number required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['round("a")'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1219: Float or Number required for argument 1']) assert_equal('2.0', string(round(2.1))) # sin() - v9.CheckDefAndScriptFailure(['sin("a")'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1219: Float or Number required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['sin("a")'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1219: Float or Number required for argument 1']) assert_equal('0.0', string(sin(0.0))) # sinh() - v9.CheckDefAndScriptFailure(['sinh("a")'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1219: Float or Number required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['sinh("a")'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1219: Float or Number required for argument 1']) assert_equal('0.0', string(sinh(0.0))) # sqrt() - v9.CheckDefAndScriptFailure(['sqrt("a")'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1219: Float or Number required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['sqrt("a")'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1219: Float or Number required for argument 1']) assert_equal('0.0', string(sqrt(0.0))) # tan() - v9.CheckDefAndScriptFailure(['tan("a")'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1219: Float or Number required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['tan("a")'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1219: Float or Number required for argument 1']) assert_equal('0.0', string(tan(0.0))) # tanh() - v9.CheckDefAndScriptFailure(['tanh("a")'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1219: Float or Number required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['tanh("a")'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1219: Float or Number required for argument 1']) assert_equal('0.0', string(tanh(0.0))) # trunc() - v9.CheckDefAndScriptFailure(['trunc("a")'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1219: Float or Number required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['trunc("a")'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1219: Float or Number required for argument 1']) assert_equal('2.0', string(trunc(2.1))) enddef def Test_fnameescape() - v9.CheckDefAndScriptFailure(['fnameescape(10)'], ['E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['fnameescape(10)'], ['E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1']) assert_equal('\+a\%b\|', fnameescape('+a%b|')) fnameescape('')->assert_equal('') enddef def Test_fnamemodify() - v9.CheckDefSuccess(['echo fnamemodify(test_null_string(), ":p")']) - v9.CheckDefSuccess(['echo fnamemodify("", ":p")']) - v9.CheckDefSuccess(['echo fnamemodify("file", test_null_string())']) - v9.CheckDefSuccess(['echo fnamemodify("file", "")']) + v9.CheckSourceDefSuccess(['echo fnamemodify(test_null_string(), ":p")']) + v9.CheckSourceDefSuccess(['echo fnamemodify("", ":p")']) + v9.CheckSourceDefSuccess(['echo fnamemodify("file", test_null_string())']) + v9.CheckSourceDefSuccess(['echo fnamemodify("file", "")']) - v9.CheckDefExecFailure(['echo fnamemodify(true, ":p")'], 'E1013: Argument 1: type mismatch, expected string but got bool') - v9.CheckDefExecFailure(['echo fnamemodify(v:null, ":p")'], 'E1013: Argument 1: type mismatch, expected string but got special') - v9.CheckDefExecFailure(['echo fnamemodify("file", true)'], 'E1013: Argument 2: type mismatch, expected string but got bool') + v9.CheckSourceDefExecFailure(['echo fnamemodify(true, ":p")'], 'E1013: Argument 1: type mismatch, expected string but got bool') + v9.CheckSourceDefExecFailure(['echo fnamemodify(v:null, ":p")'], 'E1013: Argument 1: type mismatch, expected string but got special') + v9.CheckSourceDefExecFailure(['echo fnamemodify("file", true)'], 'E1013: Argument 2: type mismatch, expected string but got bool') enddef def Wrong_dict_key_type(items: list<number>): list<number> @@ -1454,10 +1454,10 @@ def Test_filter() enddef assert_equal(['xxx'], Func()) END - v9.CheckScriptSuccess(lines) + v9.CheckSourceScriptSuccess(lines) - v9.CheckDefAndScriptFailure(['filter(1.1, "1")'], ['E1013: Argument 1: type mismatch, expected list<any> but got float', 'E1251: List, Dictionary, Blob or String required for argument 1']) - v9.CheckDefAndScriptFailure(['filter([1, 2], 4)'], ['E1256: String or function required for argument 2', 'E1024: Using a Number as a String']) + v9.CheckSourceDefAndScriptFailure(['filter(1.1, "1")'], ['E1013: Argument 1: type mismatch, expected list<any> but got float', 'E1251: List, Dictionary, Blob or String required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['filter([1, 2], 4)'], ['E1256: String or function required for argument 2', 'E1024: Using a Number as a String']) lines =<< trim END def F(i: number, v: any): string @@ -1465,51 +1465,51 @@ def Test_filter() enddef echo filter([1, 2, 3], F) END - v9.CheckDefAndScriptFailure(lines, ['E1013: Argument 2: type mismatch, expected func(?number, ?any): bool but got func(number, any): string', 'E1135: Using a String as a Bool:']) + v9.CheckSourceDefAndScriptFailure(lines, ['E1013: Argument 2: type mismatch, expected func(?number, ?any): bool but got func(number, any): string', 'E1135: Using a String as a Bool:']) # check first function argument type lines =<< trim END var l = [1, 2, 3] filter(l, (i: string, v: number) => true) END - v9.CheckDefAndScriptFailure(lines, ['E1013: Argument 2: type mismatch, expected func(?number, ?number): bool but got func(string, number): bool', 'E1013: Argument 1: type mismatch, expected string but got number']) + v9.CheckSourceDefAndScriptFailure(lines, ['E1013: Argument 2: type mismatch, expected func(?number, ?number): bool but got func(string, number): bool', 'E1013: Argument 1: type mismatch, expected string but got number']) lines =<< trim END var d = {a: 1} filter(d, (i: number, v: number) => true) END - v9.CheckDefAndScriptFailure(lines, ['E1013: Argument 2: type mismatch, expected func(?string, ?number): bool but got func(number, number): bool', 'E1013: Argument 1: type mismatch, expected number but got string']) + v9.CheckSourceDefAndScriptFailure(lines, ['E1013: Argument 2: type mismatch, expected func(?string, ?number): bool but got func(number, number): bool', 'E1013: Argument 1: type mismatch, expected number but got string']) lines =<< trim END var b = 0z1122 filter(b, (i: string, v: number) => true) END - v9.CheckDefAndScriptFailure(lines, ['E1013: Argument 2: type mismatch, expected func(?number, ?number): bool but got func(string, number): bool', 'E1013: Argument 1: type mismatch, expected string but got number']) + v9.CheckSourceDefAndScriptFailure(lines, ['E1013: Argument 2: type mismatch, expected func(?number, ?number): bool but got func(string, number): bool', 'E1013: Argument 1: type mismatch, expected string but got number']) lines =<< trim END var s = 'text' filter(s, (i: string, v: string) => true) END - v9.CheckDefAndScriptFailure(lines, ['E1013: Argument 2: type mismatch, expected func(?number, ?string): bool but got func(string, string): bool', 'E1013: Argument 1: type mismatch, expected string but got number']) + v9.CheckSourceDefAndScriptFailure(lines, ['E1013: Argument 2: type mismatch, expected func(?number, ?string): bool but got func(string, string): bool', 'E1013: Argument 1: type mismatch, expected string but got number']) # check second function argument type lines =<< trim END var l = [1, 2, 3] filter(l, (i: number, v: string) => true) END - v9.CheckDefAndScriptFailure(lines, ['E1013: Argument 2: type mismatch, expected func(?number, ?number): bool but got func(number, string): bool', 'E1013: Argument 2: type mismatch, expected string but got number']) + v9.CheckSourceDefAndScriptFailure(lines, ['E1013: Argument 2: type mismatch, expected func(?number, ?number): bool but got func(number, string): bool', 'E1013: Argument 2: type mismatch, expected string but got number']) lines =<< trim END var d = {a: 1} filter(d, (i: string, v: string) => true) END - v9.CheckDefAndScriptFailure(lines, ['E1013: Argument 2: type mismatch, expected func(?string, ?number): bool but got func(string, string): bool', 'E1013: Argument 2: type mismatch, expected string but got number']) + v9.CheckSourceDefAndScriptFailure(lines, ['E1013: Argument 2: type mismatch, expected func(?string, ?number): bool but got func(string, string): bool', 'E1013: Argument 2: type mismatch, expected string but got number']) lines =<< trim END var b = 0z1122 filter(b, (i: number, v: string) => true) END - v9.CheckDefAndScriptFailure(lines, ['E1013: Argument 2: type mismatch, expected func(?number, ?number): bool but got func(number, string): bool', 'E1013: Argument 2: type mismatch, expected string but got number']) + v9.CheckSourceDefAndScriptFailure(lines, ['E1013: Argument 2: type mismatch, expected func(?number, ?number): bool but got func(number, string): bool', 'E1013: Argument 2: type mismatch, expected string but got number']) lines =<< trim END var s = 'text' filter(s, (i: number, v: number) => true) END - v9.CheckDefAndScriptFailure(lines, ['E1013: Argument 2: type mismatch, expected func(?number, ?string): bool but got func(number, number): bool', 'E1013: Argument 2: type mismatch, expected number but got string']) + v9.CheckSourceDefAndScriptFailure(lines, ['E1013: Argument 2: type mismatch, expected func(?number, ?string): bool but got func(number, number): bool', 'E1013: Argument 2: type mismatch, expected number but got string']) enddef def Test_filter_wrong_dict_key_type() @@ -1536,39 +1536,39 @@ def Test_filter_const() const l = [1, 2, 3] filter(l, 'v:val == 2') END - v9.CheckDefFailure(lines, 'E1307: Argument 1: Trying to modify a const list<number>') + v9.CheckSourceDefFailure(lines, 'E1307: Argument 1: Trying to modify a const list<number>') lines =<< trim END const d = {a: 1, b: 2} filter(d, 'v:val == 2') END - v9.CheckDefFailure(lines, 'E1307: Argument 1: Trying to modify a const dict<number>') + v9.CheckSourceDefFailure(lines, 'E1307: Argument 1: Trying to modify a const dict<number>') enddef def Test_foldclosed() - v9.CheckDefAndScriptFailure(['foldclosed(function("min"))'], ['E1013: Argument 1: type mismatch, expected string but got func(...): unknown', 'E1220: String or Number required for argument 1']) - v9.CheckDefExecAndScriptFailure(['foldclosed("")'], 'E1209: Invalid value for a line number') + v9.CheckSourceDefAndScriptFailure(['foldclosed(function("min"))'], ['E1013: Argument 1: type mismatch, expected string but got func(...): unknown', 'E1220: String or Number required for argument 1']) + v9.CheckSourceDefExecAndScriptFailure(['foldclosed("")'], 'E1209: Invalid value for a line number') assert_equal(-1, foldclosed(1)) assert_equal(-1, foldclosed('$')) enddef def Test_foldclosedend() - v9.CheckDefAndScriptFailure(['foldclosedend(true)'], ['E1013: Argument 1: type mismatch, expected string but got bool', 'E1220: String or Number required for argument 1']) - v9.CheckDefExecAndScriptFailure(['foldclosedend("")'], 'E1209: Invalid value for a line number') + v9.CheckSourceDefAndScriptFailure(['foldclosedend(true)'], ['E1013: Argument 1: type mismatch, expected string but got bool', 'E1220: String or Number required for argument 1']) + v9.CheckSourceDefExecAndScriptFailure(['foldclosedend("")'], 'E1209: Invalid value for a line number') assert_equal(-1, foldclosedend(1)) assert_equal(-1, foldclosedend('w0')) enddef def Test_foldlevel() - v9.CheckDefAndScriptFailure(['foldlevel(0z10)'], ['E1013: Argument 1: type mismatch, expected string but got blob', 'E1220: String or Number required for argument 1']) - v9.CheckDefExecAndScriptFailure(['foldlevel("")'], 'E1209: Invalid value for a line number') + v9.CheckSourceDefAndScriptFailure(['foldlevel(0z10)'], ['E1013: Argument 1: type mismatch, expected string but got blob', 'E1220: String or Number required for argument 1']) + v9.CheckSourceDefExecAndScriptFailure(['foldlevel("")'], 'E1209: Invalid value for a line number') assert_equal(0, foldlevel(1)) assert_equal(0, foldlevel('.')) enddef def Test_foldtextresult() - v9.CheckDefAndScriptFailure(['foldtextresult(1.1)'], ['E1013: Argument 1: type mismatch, expected string but got float', 'E1220: String or Number required for argument 1']) - v9.CheckDefExecAndScriptFailure(['foldtextresult("")'], 'E1209: Invalid value for a line number') + v9.CheckSourceDefAndScriptFailure(['foldtextresult(1.1)'], ['E1013: Argument 1: type mismatch, expected string but got float', 'E1220: String or Number required for argument 1']) + v9.CheckSourceDefExecAndScriptFailure(['foldtextresult("")'], 'E1209: Invalid value for a line number') assert_equal('', foldtextresult(1)) assert_equal('', foldtextresult('.')) enddef @@ -1605,8 +1605,8 @@ def Test_fullcommand() enddef def Test_funcref() - v9.CheckDefAndScriptFailure(['funcref("reverse", 2)'], ['E1013: Argument 2: type mismatch, expected list<any> but got number', 'E1211: List required for argument 2']) - v9.CheckDefAndScriptFailure(['funcref("reverse", [2], [1])'], ['E1013: Argument 3: type mismatch, expected dict<any> but got list<number>', 'E1206: Dictionary required for argument 3']) + v9.CheckSourceDefAndScriptFailure(['funcref("reverse", 2)'], ['E1013: Argument 2: type mismatch, expected list<any> but got number', 'E1211: List required for argument 2']) + v9.CheckSourceDefAndScriptFailure(['funcref("reverse", [2], [1])'], ['E1013: Argument 3: type mismatch, expected dict<any> but got list<number>', 'E1206: Dictionary required for argument 3']) var lines =<< trim END vim9script @@ -1623,7 +1623,7 @@ def Test_funcref() defcompile GetRefOk() END - v9.CheckScriptSuccess(lines) + v9.CheckSourceScriptSuccess(lines) lines =<< trim END vim9script @@ -1635,14 +1635,14 @@ def Test_funcref() enddef GetRefBad() END - v9.CheckScriptFailure(lines, 'E1012: Type mismatch; expected func(number) but got func(bool)') + v9.CheckSourceScriptFailure(lines, 'E1012: Type mismatch; expected func(number) but got func(bool)') enddef def Test_function() - v9.CheckDefExecAndScriptFailure(['function(123)'], 'E1256: String or function required for argument 1') + v9.CheckSourceDefExecAndScriptFailure(['function(123)'], 'E1256: String or function required for argument 1') - v9.CheckDefAndScriptFailure(['function("reverse", 2)'], ['E1013: Argument 2: type mismatch, expected list<any> but got number', 'E1211: List required for argument 2']) - v9.CheckDefAndScriptFailure(['function("reverse", [2], [1])'], ['E1013: Argument 3: type mismatch, expected dict<any> but got list<number>', 'E1206: Dictionary required for argument 3']) + v9.CheckSourceDefAndScriptFailure(['function("reverse", 2)'], ['E1013: Argument 2: type mismatch, expected list<any> but got number', 'E1211: List required for argument 2']) + v9.CheckSourceDefAndScriptFailure(['function("reverse", [2], [1])'], ['E1013: Argument 3: type mismatch, expected dict<any> but got list<number>', 'E1206: Dictionary required for argument 3']) var lines =<< trim END vim9script @@ -1659,7 +1659,7 @@ def Test_function() defcompile GetRefOk() END - v9.CheckScriptSuccess(lines) + v9.CheckSourceScriptSuccess(lines) lines =<< trim END vim9script @@ -1671,17 +1671,17 @@ def Test_function() enddef GetRefBad() END - v9.CheckScriptFailure(lines, 'E1012: Type mismatch; expected func(number) but got func(bool)') + v9.CheckSourceScriptFailure(lines, 'E1012: Type mismatch; expected func(number) but got func(bool)') enddef def Test_garbagecollect() garbagecollect(true) - v9.CheckDefAndScriptFailure(['garbagecollect("1")'], ['E1013: Argument 1: type mismatch, expected bool but got string', 'E1212: Bool required for argument 1']) - v9.CheckDefAndScriptFailure(['garbagecollect(20)'], ['E1013: Argument 1: type mismatch, expected bool but got number', 'E1212: Bool required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['garbagecollect("1")'], ['E1013: Argument 1: type mismatch, expected bool but got string', 'E1212: Bool required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['garbagecollect(20)'], ['E1013: Argument 1: type mismatch, expected bool but got number', 'E1212: Bool required for argument 1']) enddef def Test_get() - v9.CheckDefAndScriptFailure(['get("a", 1)'], ['E1013: Argument 1: type mismatch, expected list<any> but got string', 'E896: Argument of get() must be a List, Dictionary or Blob']) + v9.CheckSourceDefAndScriptFailure(['get("a", 1)'], ['E1013: Argument 1: type mismatch, expected list<any> but got string', 'E896: Argument of get() must be a List, Dictionary or Blob']) [3, 5, 2]->get(1)->assert_equal(5) [3, 5, 2]->get(3)->assert_equal(0) [3, 5, 2]->get(3, 9)->assert_equal(9) @@ -1701,7 +1701,7 @@ def Test_get() enddef assert_equal(0, DoThat()) END - v9.CheckScriptSuccess(lines) + v9.CheckSourceScriptSuccess(lines) enddef def Test_getbufinfo() @@ -1714,7 +1714,7 @@ def Test_getbufinfo() getbufinfo({bufloaded: true, buflisted: true, bufmodified: false}) ->len()->assert_equal(3) bwipe Xtestfile1 Xtestfile2 - v9.CheckDefAndScriptFailure(['getbufinfo(true)'], ['E1013: Argument 1: type mismatch, expected string but got bool', 'E1174: String required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['getbufinfo(true)'], ['E1013: Argument 1: type mismatch, expected string but got bool', 'E1174: String required for argument 1']) enddef def Test_getbufline() @@ -1738,17 +1738,17 @@ def Test_getbufline() assert_fails('getbufoneline("", "$a")', ['E1030: Using a String as a Number: "$a"', 'E1030: Using a String as a Number: "$a"']) bwipe! - v9.CheckDefAndScriptFailure(['getbufline([], 2)'], ['E1013: Argument 1: type mismatch, expected string but got list<any>', 'E1220: String or Number required for argument 1']) - v9.CheckDefAndScriptFailure(['getbufline("a", [])'], ['E1013: Argument 2: type mismatch, expected string but got list<any>', 'E1220: String or Number required for argument 2']) - v9.CheckDefAndScriptFailure(['getbufline("a", 2, 0z10)'], ['E1013: Argument 3: type mismatch, expected string but got blob', 'E1220: String or Number required for argument 3']) + v9.CheckSourceDefAndScriptFailure(['getbufline([], 2)'], ['E1013: Argument 1: type mismatch, expected string but got list<any>', 'E1220: String or Number required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['getbufline("a", [])'], ['E1013: Argument 2: type mismatch, expected string but got list<any>', 'E1220: String or Number required for argument 2']) + v9.CheckSourceDefAndScriptFailure(['getbufline("a", 2, 0z10)'], ['E1013: Argument 3: type mismatch, expected string but got blob', 'E1220: String or Number required for argument 3']) - v9.CheckDefAndScriptFailure(['getbufoneline([], 2)'], ['E1013: Argument 1: type mismatch, expected string but got list<any>', 'E1220: String or Number required for argument 1']) - v9.CheckDefAndScriptFailure(['getbufoneline("a", [])'], ['E1013: Argument 2: type mismatch, expected string but got list<any>', 'E1220: String or Number required for argument 2']) + v9.CheckSourceDefAndScriptFailure(['getbufoneline([], 2)'], ['E1013: Argument 1: type mismatch, expected string but got list<any>', 'E1220: String or Number required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['getbufoneline("a", [])'], ['E1013: Argument 2: type mismatch, expected string but got list<any>', 'E1220: String or Number required for argument 2']) enddef def Test_getbufvar() - v9.CheckDefAndScriptFailure(['getbufvar(true, "v")'], ['E1013: Argument 1: type mismatch, expected string but got bool', 'E1220: String or Number required for argument 1']) - v9.CheckDefAndScriptFailure(['getbufvar(1, 2, 3)'], ['E1013: Argument 2: type mismatch, expected string but got number', 'E1174: String required for argument 2']) + v9.CheckSourceDefAndScriptFailure(['getbufvar(true, "v")'], ['E1013: Argument 1: type mismatch, expected string but got bool', 'E1220: String or Number required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['getbufvar(1, 2, 3)'], ['E1013: Argument 2: type mismatch, expected string but got number', 'E1174: String required for argument 2']) enddef def Test_getchangelist() @@ -1764,21 +1764,21 @@ def Test_getchar() endwhile getchar(true)->assert_equal(0) getchar(1)->assert_equal(0) - v9.CheckDefAndScriptFailure(['getchar(2)'], ['E1013: Argument 1: type mismatch, expected bool but got number', 'E1212: Bool required for argument 1']) - v9.CheckDefAndScriptFailure(['getchar("1")'], ['E1013: Argument 1: type mismatch, expected bool but got string', 'E1212: Bool required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['getchar(2)'], ['E1013: Argument 1: type mismatch, expected bool but got number', 'E1212: Bool required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['getchar("1")'], ['E1013: Argument 1: type mismatch, expected bool but got string', 'E1212: Bool required for argument 1']) enddef def Test_getcharpos() assert_equal(['x', 'x', 'x', 'x'], getcharpos('.')->map((_, _) => 'x')) - v9.CheckDefAndScriptFailure(['getcharpos(true)'], ['E1013: Argument 1: type mismatch, expected string but got bool', 'E1174: String required for argument 1']) - v9.CheckDefAndScriptFailure(['getcharpos(1)'], ['E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1']) - v9.CheckDefExecAndScriptFailure(['getcharpos("")'], 'E1209: Invalid value for a line number') + v9.CheckSourceDefAndScriptFailure(['getcharpos(true)'], ['E1013: Argument 1: type mismatch, expected string but got bool', 'E1174: String required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['getcharpos(1)'], ['E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1']) + v9.CheckSourceDefExecAndScriptFailure(['getcharpos("")'], 'E1209: Invalid value for a line number') enddef def Test_getcharstr() - v9.CheckDefAndScriptFailure(['getcharstr(2)'], ['E1013: Argument 1: type mismatch, expected bool but got number', 'E1212: Bool required for argument 1']) - v9.CheckDefAndScriptFailure(['getcharstr("1")'], ['E1013: Argument 1: type mismatch, expected bool but got string', 'E1212: Bool required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['getcharstr(2)'], ['E1013: Argument 1: type mismatch, expected bool but got number', 'E1212: Bool required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['getcharstr("1")'], ['E1013: Argument 1: type mismatch, expected bool but got string', 'E1212: Bool required for argument 1']) enddef def Test_getcompletion() @@ -1786,29 +1786,29 @@ def Test_getcompletion() var l = getcompletion('run', 'file', true) l->assert_equal([]) set wildignore& - v9.CheckDefAndScriptFailure(['getcompletion(1, "b")'], ['E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1']) - v9.CheckDefAndScriptFailure(['getcompletion("a", 2)'], ['E1013: Argument 2: type mismatch, expected string but got number', 'E1174: String required for argument 2']) - v9.CheckDefAndScriptFailure(['getcompletion("a", "b", 2)'], ['E1013: Argument 3: type mismatch, expected bool but got number', 'E1212: Bool required for argument 3']) - v9.CheckDefExecAndScriptFailure(['getcompletion("a", "")'], 'E475: Invalid argument') + v9.CheckSourceDefAndScriptFailure(['getcompletion(1, "b")'], ['E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['getcompletion("a", 2)'], ['E1013: Argument 2: type mismatch, expected string but got number', 'E1174: String required for argument 2']) + v9.CheckSourceDefAndScriptFailure(['getcompletion("a", "b", 2)'], ['E1013: Argument 3: type mismatch, expected bool but got number', 'E1212: Bool required for argument 3']) + v9.CheckSourceDefExecAndScriptFailure(['getcompletion("a", "")'], 'E475: Invalid argument') getcompletion('', 'messages')->assert_equal(['clear']) enddef def Test_getcurpos() assert_equal(['x', 'x', 'x', 'x', 'x'], getcurpos()->map((_, _) => 'x')) - v9.CheckDefAndScriptFailure(['getcurpos("x")'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1210: Number required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['getcurpos("x")'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1210: Number required for argument 1']) enddef def Test_getcursorcharpos() assert_equal(['x', 'x', 'x', 'x', 'x'], getcursorcharpos()->map((_, _) => 'x')) - v9.CheckDefAndScriptFailure(['getcursorcharpos("x")'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1210: Number required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['getcursorcharpos("x")'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1210: Number required for argument 1']) enddef def Test_getcwd() - v9.CheckDefAndScriptFailure(['getcwd("x")'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1210: Number required for argument 1']) - v9.CheckDefAndScriptFailure(['getcwd("x", 1)'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1210: Number required for argument 1']) - v9.CheckDefAndScriptFailure(['getcwd(1, "x")'], ['E1013: Argument 2: type mismatch, expected number but got string', 'E1210: Number required for argument 2']) + v9.CheckSourceDefAndScriptFailure(['getcwd("x")'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1210: Number required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['getcwd("x", 1)'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1210: Number required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['getcwd(1, "x")'], ['E1013: Argument 2: type mismatch, expected number but got string', 'E1210: Number required for argument 2']) enddef def Test_getenv() @@ -1827,7 +1827,7 @@ def Test_getenv() enddef def Test_getfontname() - v9.CheckDefAndScriptFailure(['getfontname(10)'], ['E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['getfontname(10)'], ['E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1']) #getfontname('')->assert_equal('') enddef @@ -1835,38 +1835,38 @@ def Test_getfperm() assert_equal('', getfperm("")) assert_equal('', getfperm(test_null_string())) - v9.CheckDefExecFailure(['echo getfperm(true)'], 'E1013:') - v9.CheckDefExecFailure(['echo getfperm(v:null)'], 'E1013:') + v9.CheckSourceDefExecFailure(['echo getfperm(true)'], 'E1013:') + v9.CheckSourceDefExecFailure(['echo getfperm(v:null)'], 'E1013:') enddef def Test_getfsize() assert_equal(-1, getfsize("")) assert_equal(-1, getfsize(test_null_string())) - v9.CheckDefExecFailure(['echo getfsize(true)'], 'E1013:') - v9.CheckDefExecFailure(['echo getfsize(v:null)'], 'E1013:') + v9.CheckSourceDefExecFailure(['echo getfsize(true)'], 'E1013:') + v9.CheckSourceDefExecFailure(['echo getfsize(v:null)'], 'E1013:') enddef def Test_getftime() assert_equal(-1, getftime("")) assert_equal(-1, getftime(test_null_string())) - v9.CheckDefExecFailure(['echo getftime(true)'], 'E1013:') - v9.CheckDefExecFailure(['echo getftime(v:null)'], 'E1013:') + v9.CheckSourceDefExecFailure(['echo getftime(true)'], 'E1013:') + v9.CheckSourceDefExecFailure(['echo getftime(v:null)'], 'E1013:') enddef def Test_getftype() assert_equal('', getftype("")) assert_equal('', getftype(test_null_string())) - v9.CheckDefExecFailure(['echo getftype(true)'], 'E1013:') - v9.CheckDefExecFailure(['echo getftype(v:null)'], 'E1013:') + v9.CheckSourceDefExecFailure(['echo getftype(true)'], 'E1013:') + v9.CheckSourceDefExecFailure(['echo getftype(v:null)'], 'E1013:') enddef def Test_getjumplist() - v9.CheckDefAndScriptFailure(['getjumplist("x")'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1210: Number required for argument 1']) - v9.CheckDefAndScriptFailure(['getjumplist("x", 1)'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1210: Number required for argument 1']) - v9.CheckDefAndScriptFailure(['getjumplist(1, "x")'], ['E1013: Argument 2: type mismatch, expected number but got string', 'E1210: Number required for argument 2']) + v9.CheckSourceDefAndScriptFailure(['getjumplist("x")'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1210: Number required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['getjumplist("x", 1)'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1210: Number required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['getjumplist(1, "x")'], ['E1013: Argument 2: type mismatch, expected number but got string', 'E1210: Number required for argument 2']) enddef def Test_getline() @@ -1882,20 +1882,20 @@ def Test_getline() assert_equal([3, 3, 3], getline(1, 3)->map((_, _) => 3)) END - v9.CheckDefAndScriptSuccess(lines) + v9.CheckSourceDefAndScriptSuccess(lines) lines =<< trim END echo getline('1') END - v9.CheckDefExecAndScriptFailure(lines, 'E1209:') - v9.CheckDefAndScriptFailure(['getline(true)'], ['E1013: Argument 1: type mismatch, expected string but got bool', 'E1220: String or Number required for argument 1']) - v9.CheckDefAndScriptFailure(['getline(1, true)'], ['E1013: Argument 2: type mismatch, expected string but got bool', 'E1220: String or Number required for argument 2']) - v9.CheckDefExecAndScriptFailure(['getline("")'], 'E1209: Invalid value for a line number') + v9.CheckSourceDefExecAndScriptFailure(lines, 'E1209:') + v9.CheckSourceDefAndScriptFailure(['getline(true)'], ['E1013: Argument 1: type mismatch, expected string but got bool', 'E1220: String or Number required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['getline(1, true)'], ['E1013: Argument 2: type mismatch, expected string but got bool', 'E1220: String or Number required for argument 2']) + v9.CheckSourceDefExecAndScriptFailure(['getline("")'], 'E1209: Invalid value for a line number') enddef def Test_getloclist() - v9.CheckDefAndScriptFailure(['getloclist("x")'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1210: Number required for argument 1']) - v9.CheckDefAndScriptFailure(['getloclist(1, [])'], ['E1013: Argument 2: type mismatch, expected dict<any> but got list<any>', 'E1206: Dictionary required for argument 2']) + v9.CheckSourceDefAndScriptFailure(['getloclist("x")'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1210: Number required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['getloclist(1, [])'], ['E1013: Argument 2: type mismatch, expected dict<any> but got list<any>', 'E1206: Dictionary required for argument 2']) enddef def Test_getloclist_return_type() @@ -1907,26 +1907,26 @@ def Test_getloclist_return_type() enddef def Test_getmarklist() - v9.CheckDefAndScriptFailure(['getmarklist([])'], ['E1013: Argument 1: type mismatch, expected string but got list<any>', 'E1220: String or Number required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['getmarklist([])'], ['E1013: Argument 1: type mismatch, expected string but got list<any>', 'E1220: String or Number required for argument 1']) assert_equal([], getmarklist(10000)) assert_fails('getmarklist("a%b@#")', 'E94:') enddef def Test_getmatches() - v9.CheckDefAndScriptFailure(['getmatches("x")'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1210: Number required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['getmatches("x")'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1210: Number required for argument 1']) enddef def Test_getpos() assert_equal(['x', 'x', 'x', 'x'], getpos('.')->map((_, _) => 'x')) - v9.CheckDefAndScriptFailure(['getpos(10)'], ['E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['getpos(10)'], ['E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1']) assert_equal([0, 1, 1, 0], getpos('.')) - v9.CheckDefExecFailure(['getpos("a")'], 'E1209:') - v9.CheckDefExecAndScriptFailure(['getpos("")'], 'E1209: Invalid value for a line number') + v9.CheckSourceDefExecFailure(['getpos("a")'], 'E1209:') + v9.CheckSourceDefExecAndScriptFailure(['getpos("")'], 'E1209: Invalid value for a line number') enddef def Test_getqflist() - v9.CheckDefAndScriptFailure(['getqflist([])'], ['E1013: Argument 1: type mismatch, expected dict<any> but got list<any>', 'E1206: Dictionary required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['getqflist([])'], ['E1013: Argument 1: type mismatch, expected dict<any> but got list<any>', 'E1206: Dictionary required for argument 1']) call assert_equal({}, getqflist({})) enddef @@ -1945,9 +1945,9 @@ def Test_getreg() assert_equal([7, 7, 7], getreg('a', true, true)->map((_, _) => 7)) assert_fails('getreg("ab")', 'E1162:') - v9.CheckDefAndScriptFailure(['getreg(1)'], ['E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1']) - v9.CheckDefAndScriptFailure(['getreg(".", 2)'], ['E1013: Argument 2: type mismatch, expected bool but got number', 'E1212: Bool required for argument 2']) - v9.CheckDefAndScriptFailure(['getreg(".", 1, "b")'], ['E1013: Argument 3: type mismatch, expected bool but got string', 'E1212: Bool required for argument 3']) + v9.CheckSourceDefAndScriptFailure(['getreg(1)'], ['E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['getreg(".", 2)'], ['E1013: Argument 2: type mismatch, expected bool but got number', 'E1212: Bool required for argument 2']) + v9.CheckSourceDefAndScriptFailure(['getreg(".", 1, "b")'], ['E1013: Argument 3: type mismatch, expected bool but got string', 'E1212: Bool required for argument 3']) @" = 'A1B2C3' getreg('')->assert_equal('A1B2C3') enddef @@ -1977,7 +1977,7 @@ def Test_getregtype() enddef def Test_getscriptinfo() - v9.CheckDefAndScriptFailure(['getscriptinfo("x")'], ['E1013: Argument 1: type mismatch, expected dict<any> but got string', 'E1206: Dictionary required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['getscriptinfo("x")'], ['E1013: Argument 1: type mismatch, expected dict<any> but got string', 'E1206: Dictionary required for argument 1']) var lines1 =<< trim END vim9script @@ -2016,78 +2016,78 @@ def Test_getscriptinfo() assert_true(index(l[0].functions, f) != -1) endfor END - v9.CheckDefAndScriptSuccess(lines2) + v9.CheckSourceDefAndScriptSuccess(lines2) enddef def Test_gettabinfo() - v9.CheckDefAndScriptFailure(['gettabinfo("x")'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1210: Number required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['gettabinfo("x")'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1210: Number required for argument 1']) enddef def Test_gettabvar() - v9.CheckDefAndScriptFailure(['gettabvar("a", "b")'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1210: Number required for argument 1']) - v9.CheckDefAndScriptFailure(['gettabvar(1, 2)'], ['E1013: Argument 2: type mismatch, expected string but got number', 'E1174: String required for argument 2']) + v9.CheckSourceDefAndScriptFailure(['gettabvar("a", "b")'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1210: Number required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['gettabvar(1, 2)'], ['E1013: Argument 2: type mismatch, expected string but got number', 'E1174: String required for argument 2']) enddef def Test_gettabwinvar() - v9.CheckDefAndScriptFailure(['gettabwinvar("a", 2, "c")'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1210: Number required for argument 1']) - v9.CheckDefAndScriptFailure(['gettabwinvar(1, "b", "c", [])'], ['E1013: Argument 2: type mismatch, expected number but got string', 'E1210: Number required for argument 2']) - v9.CheckDefAndScriptFailure(['gettabwinvar(1, 1, 3, {})'], ['E1013: Argument 3: type mismatch, expected string but got number', 'E1174: String required for argument 3']) + v9.CheckSourceDefAndScriptFailure(['gettabwinvar("a", 2, "c")'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1210: Number required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['gettabwinvar(1, "b", "c", [])'], ['E1013: Argument 2: type mismatch, expected number but got string', 'E1210: Number required for argument 2']) + v9.CheckSourceDefAndScriptFailure(['gettabwinvar(1, 1, 3, {})'], ['E1013: Argument 3: type mismatch, expected string but got number', 'E1174: String required for argument 3']) enddef def Test_gettagstack() - v9.CheckDefAndScriptFailure(['gettagstack("x")'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1210: Number required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['gettagstack("x")'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1210: Number required for argument 1']) enddef def Test_gettext() - v9.CheckDefAndScriptFailure(['gettext(10)'], ['E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1']) - v9.CheckDefExecAndScriptFailure(['gettext("")'], 'E1175: Non-empty string required for argument 1') + v9.CheckSourceDefAndScriptFailure(['gettext(10)'], ['E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1']) + v9.CheckSourceDefExecAndScriptFailure(['gettext("")'], 'E1175: Non-empty string required for argument 1') assert_equal('abc', gettext("abc")) assert_fails('gettext("")', 'E1175:') enddef def Test_getwininfo() - v9.CheckDefAndScriptFailure(['getwininfo("x")'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1210: Number required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['getwininfo("x")'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1210: Number required for argument 1']) enddef def Test_getwinpos() assert_equal(['x', 'x'], getwinpos()->map((_, _) => 'x')) - v9.CheckDefAndScriptFailure(['getwinpos("x")'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1210: Number required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['getwinpos("x")'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1210: Number required for argument 1']) enddef def Test_getwinvar() - v9.CheckDefAndScriptFailure(['getwinvar("a", "b")'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1210: Number required for argument 1']) - v9.CheckDefAndScriptFailure(['getwinvar(1, 2)'], ['E1013: Argument 2: type mismatch, expected string but got number', 'E1174: String required for argument 2']) + v9.CheckSourceDefAndScriptFailure(['getwinvar("a", "b")'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1210: Number required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['getwinvar(1, 2)'], ['E1013: Argument 2: type mismatch, expected string but got number', 'E1174: String required for argument 2']) enddef def Test_glob() glob('runtest.vim', true, true, true)->assert_equal(['runtest.vim']) - v9.CheckDefAndScriptFailure(['glob(1)'], ['E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1']) - v9.CheckDefAndScriptFailure(['glob("a", 2)'], ['E1013: Argument 2: type mismatch, expected bool but got number', 'E1212: Bool required for argument 2']) - v9.CheckDefAndScriptFailure(['glob("a", 1, "b")'], ['E1013: Argument 3: type mismatch, expected bool but got string', 'E1212: Bool required for argument 3']) - v9.CheckDefAndScriptFailure(['glob("a", 1, true, 2)'], ['E1013: Argument 4: type mismatch, expected bool but got number', 'E1212: Bool required for argument 4']) + v9.CheckSourceDefAndScriptFailure(['glob(1)'], ['E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['glob("a", 2)'], ['E1013: Argument 2: type mismatch, expected bool but got number', 'E1212: Bool required for argument 2']) + v9.CheckSourceDefAndScriptFailure(['glob("a", 1, "b")'], ['E1013: Argument 3: type mismatch, expected bool but got string', 'E1212: Bool required for argument 3']) + v9.CheckSourceDefAndScriptFailure(['glob("a", 1, true, 2)'], ['E1013: Argument 4: type mismatch, expected bool but got number', 'E1212: Bool required for argument 4']) glob('')->assert_equal('') enddef def Test_glob2regpat() - v9.CheckDefAndScriptFailure(['glob2regpat(null)'], ['E1013: Argument 1: type mismatch, expected string but got special', 'E1174: String required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['glob2regpat(null)'], ['E1013: Argument 1: type mismatch, expected string but got special', 'E1174: String required for argument 1']) glob2regpat('')->assert_equal('^$') enddef def Test_globpath() globpath('.', 'runtest.vim', true, true, true)->assert_equal(['./runtest.vim']) - v9.CheckDefAndScriptFailure(['globpath(1, "b")'], ['E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1']) - v9.CheckDefAndScriptFailure(['globpath("a", 2)'], ['E1013: Argument 2: type mismatch, expected string but got number', 'E1174: String required for argument 2']) - v9.CheckDefAndScriptFailure(['globpath("a", "b", "c")'], ['E1013: Argument 3: type mismatch, expected bool but got string', 'E1212: Bool required for argument 3']) - v9.CheckDefAndScriptFailure(['globpath("a", "b", true, "d")'], ['E1013: Argument 4: type mismatch, expected bool but got string', 'E1212: Bool required for argument 4']) - v9.CheckDefAndScriptFailure(['globpath("a", "b", true, false, "e")'], ['E1013: Argument 5: type mismatch, expected bool but got string', 'E1212: Bool required for argument 5']) + v9.CheckSourceDefAndScriptFailure(['globpath(1, "b")'], ['E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['globpath("a", 2)'], ['E1013: Argument 2: type mismatch, expected string but got number', 'E1174: String required for argument 2']) + v9.CheckSourceDefAndScriptFailure(['globpath("a", "b", "c")'], ['E1013: Argument 3: type mismatch, expected bool but got string', 'E1212: Bool required for argument 3']) + v9.CheckSourceDefAndScriptFailure(['globpath("a", "b", true, "d")'], ['E1013: Argument 4: type mismatch, expected bool but got string', 'E1212: Bool required for argument 4']) + v9.CheckSourceDefAndScriptFailure(['globpath("a", "b", true, false, "e")'], ['E1013: Argument 5: type mismatch, expected bool but got string', 'E1212: Bool required for argument 5']) globpath('', '')->assert_equal('') enddef def Test_has() has('eval', true)->assert_equal(1) - v9.CheckDefAndScriptFailure(['has(["a"])'], ['E1013: Argument 1: type mismatch, expected string but got list<string>', 'E1174: String required for argument 1']) - v9.CheckDefAndScriptFailure(['has("a", "b")'], ['E1013: Argument 2: type mismatch, expected bool but got string', 'E1212: Bool required for argument 2']) + v9.CheckSourceDefAndScriptFailure(['has(["a"])'], ['E1013: Argument 1: type mismatch, expected string but got list<string>', 'E1174: String required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['has("a", "b")'], ['E1013: Argument 2: type mismatch, expected bool but got string', 'E1212: Bool required for argument 2']) has('')->assert_equal(0) enddef @@ -2098,14 +2098,14 @@ def Test_has_key() assert_false(has_key(d, 'x')) assert_false(has_key(d, 99)) - v9.CheckDefAndScriptFailure(['has_key([1, 2], "k")'], ['E1013: Argument 1: type mismatch, expected dict<any> but got list<number>', 'E1206: Dictionary required for argument 1']) - v9.CheckDefAndScriptFailure(['has_key({"a": 10}, ["a"])'], ['E1013: Argument 2: type mismatch, expected string but got list<string>', 'E1220: String or Number required for argument 2']) + v9.CheckSourceDefAndScriptFailure(['has_key([1, 2], "k")'], ['E1013: Argument 1: type mismatch, expected dict<any> but got list<number>', 'E1206: Dictionary required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['has_key({"a": 10}, ["a"])'], ['E1013: Argument 2: type mismatch, expected string but got list<string>', 'E1220: String or Number required for argument 2']) enddef def Test_haslocaldir() - v9.CheckDefAndScriptFailure(['haslocaldir("x")'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1210: Number required for argument 1']) - v9.CheckDefAndScriptFailure(['haslocaldir("x", 1)'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1210: Number required for argument 1']) - v9.CheckDefAndScriptFailure(['haslocaldir(1, "x")'], ['E1013: Argument 2: type mismatch, expected number but got string', 'E1210: Number required for argument 2']) + v9.CheckSourceDefAndScriptFailure(['haslocaldir("x")'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1210: Number required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['haslocaldir("x", 1)'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1210: Number required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['haslocaldir(1, "x")'], ['E1013: Argument 2: type mismatch, expected number but got string', 'E1210: Number required for argument 2']) enddef def Test_hasmapto() @@ -2113,81 +2113,81 @@ def Test_hasmapto() iabbrev foo foobar hasmapto('foobar', 'i', true)->assert_equal(1) iunabbrev foo - v9.CheckDefAndScriptFailure(['hasmapto(1, "b")'], ['E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1']) - v9.CheckDefAndScriptFailure(['hasmapto("a", 2)'], ['E1013: Argument 2: type mismatch, expected string but got number', 'E1174: String required for argument 2']) - v9.CheckDefAndScriptFailure(['hasmapto("a", "b", 2)'], ['E1013: Argument 3: type mismatch, expected bool but got number', 'E1212: Bool required for argument 3']) + v9.CheckSourceDefAndScriptFailure(['hasmapto(1, "b")'], ['E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['hasmapto("a", 2)'], ['E1013: Argument 2: type mismatch, expected string but got number', 'E1174: String required for argument 2']) + v9.CheckSourceDefAndScriptFailure(['hasmapto("a", "b", 2)'], ['E1013: Argument 3: type mismatch, expected bool but got number', 'E1212: Bool required for argument 3']) hasmapto('', '')->assert_equal(0) enddef def Test_histadd() - v9.CheckDefAndScriptFailure(['histadd(1, "x")'], ['E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1']) - v9.CheckDefAndScriptFailure(['histadd(":", 10)'], ['E1013: Argument 2: type mismatch, expected string but got number', 'E1174: String required for argument 2']) + v9.CheckSourceDefAndScriptFailure(['histadd(1, "x")'], ['E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['histadd(":", 10)'], ['E1013: Argument 2: type mismatch, expected string but got number', 'E1174: String required for argument 2']) histadd("search", 'skyblue') assert_equal('skyblue', histget('/', -1)) histadd("search", '')->assert_equal(0) enddef def Test_histdel() - v9.CheckDefAndScriptFailure(['histdel(1, "x")'], ['E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1']) - v9.CheckDefAndScriptFailure(['histdel(":", true)'], ['E1013: Argument 2: type mismatch, expected string but got bool', 'E1220: String or Number required for argument 2']) + v9.CheckSourceDefAndScriptFailure(['histdel(1, "x")'], ['E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['histdel(":", true)'], ['E1013: Argument 2: type mismatch, expected string but got bool', 'E1220: String or Number required for argument 2']) histdel('search', '')->assert_equal(0) enddef def Test_histget() - v9.CheckDefAndScriptFailure(['histget(1)'], ['E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1']) - v9.CheckDefAndScriptFailure(['histget("a", "b")'], ['E1013: Argument 2: type mismatch, expected number but got string', 'E1210: Number required for argument 2']) + v9.CheckSourceDefAndScriptFailure(['histget(1)'], ['E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['histget("a", "b")'], ['E1013: Argument 2: type mismatch, expected number but got string', 'E1210: Number required for argument 2']) enddef def Test_histnr() - v9.CheckDefAndScriptFailure(['histnr(10)'], ['E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['histnr(10)'], ['E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1']) assert_equal(-1, histnr('abc')) enddef def Test_hlID() - v9.CheckDefAndScriptFailure(['hlID(10)'], ['E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['hlID(10)'], ['E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1']) assert_equal(0, hlID('NonExistingHighlight')) hlID('')->assert_equal(0) enddef def Test_hlexists() - v9.CheckDefAndScriptFailure(['hlexists([])'], ['E1013: Argument 1: type mismatch, expected string but got list<any>', 'E1174: String required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['hlexists([])'], ['E1013: Argument 1: type mismatch, expected string but got list<any>', 'E1174: String required for argument 1']) assert_equal(0, hlexists('NonExistingHighlight')) hlexists('')->assert_equal(0) enddef def Test_hlget() - v9.CheckDefAndScriptFailure(['hlget([])'], ['E1013: Argument 1: type mismatch, expected string but got list<any>', 'E1174: String required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['hlget([])'], ['E1013: Argument 1: type mismatch, expected string but got list<any>', 'E1174: String required for argument 1']) hlget('')->assert_equal([]) enddef def Test_hlset() - v9.CheckDefAndScriptFailure(['hlset("id")'], ['E1013: Argument 1: type mismatch, expected list<any> but got string', 'E1211: List required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['hlset("id")'], ['E1013: Argument 1: type mismatch, expected list<any> but got string', 'E1211: List required for argument 1']) hlset([])->assert_equal(0) enddef def Test_iconv() - v9.CheckDefAndScriptFailure(['iconv(1, "from", "to")'], ['E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1']) - v9.CheckDefAndScriptFailure(['iconv("abc", 10, "to")'], ['E1013: Argument 2: type mismatch, expected string but got number', 'E1174: String required for argument 2']) - v9.CheckDefAndScriptFailure(['iconv("abc", "from", 20)'], ['E1013: Argument 3: type mismatch, expected string but got number', 'E1174: String required for argument 3']) + v9.CheckSourceDefAndScriptFailure(['iconv(1, "from", "to")'], ['E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['iconv("abc", 10, "to")'], ['E1013: Argument 2: type mismatch, expected string but got number', 'E1174: String required for argument 2']) + v9.CheckSourceDefAndScriptFailure(['iconv("abc", "from", 20)'], ['E1013: Argument 3: type mismatch, expected string but got number', 'E1174: String required for argument 3']) assert_equal('abc', iconv('abc', 'fromenc', 'toenc')) iconv('', '', '')->assert_equal('') enddef def Test_indent() - v9.CheckDefAndScriptFailure(['indent([1])'], ['E1013: Argument 1: type mismatch, expected string but got list<number>', 'E1220: String or Number required for argument 1']) - v9.CheckDefAndScriptFailure(['indent(true)'], ['E1013: Argument 1: type mismatch, expected string but got bool', 'E1220: String or Number required for argument 1']) - v9.CheckDefExecAndScriptFailure(['indent("")'], 'E1209: Invalid value for a line number') - v9.CheckDefExecAndScriptFailure(['indent(-1)'], 'E966: Invalid line number: -1') + v9.CheckSourceDefAndScriptFailure(['indent([1])'], ['E1013: Argument 1: type mismatch, expected string but got list<number>', 'E1220: String or Number required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['indent(true)'], ['E1013: Argument 1: type mismatch, expected string but got bool', 'E1220: String or Number required for argument 1']) + v9.CheckSourceDefExecAndScriptFailure(['indent("")'], 'E1209: Invalid value for a line number') + v9.CheckSourceDefExecAndScriptFailure(['indent(-1)'], 'E966: Invalid line number: -1') assert_equal(0, indent(1)) enddef def Test_index() index(['a', 'b', 'a', 'B'], 'b', 2, true)->assert_equal(3) - v9.CheckDefAndScriptFailure(['index("a", "a")'], ['E1013: Argument 1: type mismatch, expected list<any> but got string', 'E1226: List or Blob required for argument 1']) - v9.CheckDefFailure(['index(["1"], 1)'], 'E1013: Argument 2: type mismatch, expected string but got number') - v9.CheckDefAndScriptFailure(['index(0z10, "b")'], ['E1013: Argument 2: type mismatch, expected number but got string', 'E1210: Number required for argument 2']) - v9.CheckDefAndScriptFailure(['index([1], 1, "c")'], ['E1013: Argument 3: type mismatch, expected number but got string', 'E1210: Number required for argument 3']) - v9.CheckDefAndScriptFailure(['index(0z1020, 10, 1, 2)'], ['E1013: Argument 4: type mismatch, expected bool but got number', 'E1212: Bool required for argument 4']) + v9.CheckSourceDefAndScriptFailure(['index("a", "a")'], ['E1013: Argument 1: type mismatch, expected list<any> but got string', 'E1226: List or Blob required for argument 1']) + v9.CheckSourceDefFailure(['index(["1"], 1)'], 'E1013: Argument 2: type mismatch, expected string but got number') + v9.CheckSourceDefAndScriptFailure(['index(0z10, "b")'], ['E1013: Argument 2: type mismatch, expected number but got string', 'E1210: Number required for argument 2']) + v9.CheckSourceDefAndScriptFailure(['index([1], 1, "c")'], ['E1013: Argument 3: type mismatch, expected number but got string', 'E1210: Number required for argument 3']) + v9.CheckSourceDefAndScriptFailure(['index(0z1020, 10, 1, 2)'], ['E1013: Argument 4: type mismatch, expected bool but got number', 'E1212: Bool required for argument 4']) enddef def Test_indexof() @@ -2210,7 +2210,7 @@ def Test_indexof() indexof([{color: "red"}], TestIdx) END - v9.CheckDefAndScriptFailure(lines, ['E176: Invalid number of arguments', 'E118: Too many arguments for function']) + v9.CheckSourceDefAndScriptFailure(lines, ['E176: Invalid number of arguments', 'E118: Too many arguments for function']) lines =<< trim END def TestIdx(k: number, v: dict<any>) @@ -2218,7 +2218,7 @@ def Test_indexof() indexof([{color: "red"}], TestIdx) END - v9.CheckDefAndScriptFailure(lines, ['E1013: Argument 2: type mismatch, expected func(?number, ?any): bool', 'E1031: Cannot use void value']) + v9.CheckSourceDefAndScriptFailure(lines, ['E1013: Argument 2: type mismatch, expected func(?number, ?any): bool', 'E1031: Cannot use void value']) lines =<< trim END def TestIdx(k: number, v: dict<any>): string @@ -2227,35 +2227,35 @@ def Test_indexof() indexof([{color: "red"}], TestIdx) END - v9.CheckDefAndScriptFailure(lines, ['E1013: Argument 2: type mismatch, expected func(?number, ?any): bool', 'E1135: Using a String as a Bool']) + v9.CheckSourceDefAndScriptFailure(lines, ['E1013: Argument 2: type mismatch, expected func(?number, ?any): bool', 'E1135: Using a String as a Bool']) enddef def Test_input() - v9.CheckDefAndScriptFailure(['input(5)'], ['E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1']) - v9.CheckDefAndScriptFailure(['input(["a"])'], ['E1013: Argument 1: type mismatch, expected string but got list<string>', 'E1174: String required for argument 1']) - v9.CheckDefAndScriptFailure(['input("p", 10)'], ['E1013: Argument 2: type mismatch, expected string but got number', 'E1174: String required for argument 2']) - v9.CheckDefAndScriptFailure(['input("p", "q", 20)'], ['E1013: Argument 3: type mismatch, expected string but got number', 'E1174: String required for argument 3']) + v9.CheckSourceDefAndScriptFailure(['input(5)'], ['E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['input(["a"])'], ['E1013: Argument 1: type mismatch, expected string but got list<string>', 'E1174: String required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['input("p", 10)'], ['E1013: Argument 2: type mismatch, expected string but got number', 'E1174: String required for argument 2']) + v9.CheckSourceDefAndScriptFailure(['input("p", "q", 20)'], ['E1013: Argument 3: type mismatch, expected string but got number', 'E1174: String required for argument 3']) enddef def Test_inputdialog() - v9.CheckDefAndScriptFailure(['inputdialog(5)'], ['E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1']) - v9.CheckDefAndScriptFailure(['inputdialog(["a"])'], ['E1013: Argument 1: type mismatch, expected string but got list<string>', 'E1174: String required for argument 1']) - v9.CheckDefAndScriptFailure(['inputdialog("p", 10)'], ['E1013: Argument 2: type mismatch, expected string but got number', 'E1174: String required for argument 2']) - v9.CheckDefAndScriptFailure(['inputdialog("p", "q", 20)'], ['E1013: Argument 3: type mismatch, expected string but got number', 'E1174: String required for argument 3']) + v9.CheckSourceDefAndScriptFailure(['inputdialog(5)'], ['E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['inputdialog(["a"])'], ['E1013: Argument 1: type mismatch, expected string but got list<string>', 'E1174: String required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['inputdialog("p", 10)'], ['E1013: Argument 2: type mismatch, expected string but got number', 'E1174: String required for argument 2']) + v9.CheckSourceDefAndScriptFailure(['inputdialog("p", "q", 20)'], ['E1013: Argument 3: type mismatch, expected string but got number', 'E1174: String required for argument 3']) enddef def Test_inputlist() - v9.CheckDefAndScriptFailure(['inputlist(10)'], ['E1013: Argument 1: type mismatch, expected list<string> but got number', 'E1211: List required for argument 1']) - v9.CheckDefAndScriptFailure(['inputlist("abc")'], ['E1013: Argument 1: type mismatch, expected list<string> but got string', 'E1211: List required for argument 1']) - v9.CheckDefFailure(['inputlist([1, 2, 3])'], 'E1013: Argument 1: type mismatch, expected list<string> but got list<number>') + v9.CheckSourceDefAndScriptFailure(['inputlist(10)'], ['E1013: Argument 1: type mismatch, expected list<string> but got number', 'E1211: List required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['inputlist("abc")'], ['E1013: Argument 1: type mismatch, expected list<string> but got string', 'E1211: List required for argument 1']) + v9.CheckSourceDefFailure(['inputlist([1, 2, 3])'], 'E1013: Argument 1: type mismatch, expected list<string> but got list<number>') feedkeys("2\<CR>", 't') var r: number = inputlist(['a', 'b', 'c']) assert_equal(2, r) enddef def Test_inputsecret() - v9.CheckDefAndScriptFailure(['inputsecret(10)'], ['E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1']) - v9.CheckDefAndScriptFailure(['inputsecret("Pass:", 20)'], ['E1013: Argument 2: type mismatch, expected string but got number', 'E1174: String required for argument 2']) + v9.CheckSourceDefAndScriptFailure(['inputsecret(10)'], ['E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['inputsecret("Pass:", 20)'], ['E1013: Argument 2: type mismatch, expected string but got number', 'E1174: String required for argument 2']) feedkeys("\<CR>", 't') var ans: string = inputsecret('Pass:', '123') assert_equal('123', ans) @@ -2282,12 +2282,12 @@ def Test_insert() var lines =<< trim END insert(test_null_list(), 123) END - v9.CheckDefExecAndScriptFailure(lines, 'E1130:', 1) + v9.CheckSourceDefExecAndScriptFailure(lines, 'E1130:', 1) lines =<< trim END insert(test_null_blob(), 123) END - v9.CheckDefExecAndScriptFailure(lines, 'E1131:', 1) + v9.CheckSourceDefExecAndScriptFailure(lines, 'E1131:', 1) assert_equal([1, 2, 3], insert([2, 3], 1)) assert_equal([1, 2, 3], insert([2, 3], number_one)) @@ -2296,9 +2296,9 @@ def Test_insert() assert_equal(['a', 'b', 'c'], insert(['b', 'c'], 'a')) assert_equal(0z1234, insert(0z34, 0x12)) - v9.CheckDefAndScriptFailure(['insert("a", 1)'], ['E1013: Argument 1: type mismatch, expected list<any> but got string', 'E1226: List or Blob required for argument 1']) - v9.CheckDefFailure(['insert([2, 3], "a")'], 'E1013: Argument 2: type mismatch, expected number but got string') - v9.CheckDefAndScriptFailure(['insert([2, 3], 1, "x")'], ['E1013: Argument 3: type mismatch, expected number but got string', 'E1210: Number required for argument 3']) + v9.CheckSourceDefAndScriptFailure(['insert("a", 1)'], ['E1013: Argument 1: type mismatch, expected list<any> but got string', 'E1226: List or Blob required for argument 1']) + v9.CheckSourceDefFailure(['insert([2, 3], "a")'], 'E1013: Argument 2: type mismatch, expected number but got string') + v9.CheckSourceDefAndScriptFailure(['insert([2, 3], 1, "x")'], ['E1013: Argument 3: type mismatch, expected number but got string', 'E1210: Number required for argument 3']) enddef def Test_instanceof() @@ -2308,7 +2308,7 @@ def Test_instanceof() endclass instanceof('hello', Foo) END - v9.CheckScriptFailure(lines, 'E616: Object required for argument 1') + v9.CheckSourceScriptFailure(lines, 'E616: Object required for argument 1') lines =<< trim END vim9script @@ -2316,7 +2316,7 @@ def Test_instanceof() endclass instanceof(Foo.new(), 123) END - v9.CheckScriptFailure(lines, 'E693: Class or class typealias required for argument 2') + v9.CheckSourceScriptFailure(lines, 'E693: Class or class typealias required for argument 2') lines =<< trim END vim9script @@ -2327,7 +2327,7 @@ def Test_instanceof() enddef Bar() END - v9.CheckScriptFailure(lines, 'E1013: Argument 1: type mismatch, expected object<Unknown> but got string') + v9.CheckSourceScriptFailure(lines, 'E1013: Argument 1: type mismatch, expected object<Unknown> but got string') lines =<< trim END vim9script @@ -2338,7 +2338,7 @@ def Test_instanceof() enddef Bar() END - v9.CheckScriptFailure(lines, 'E693: Class or class typealias required for argument 2') + v9.CheckSourceScriptFailure(lines, 'E693: Class or class typealias required for argument 2') lines =<< trim END vim9script @@ -2346,7 +2346,7 @@ def Test_instanceof() endclass instanceof(Foo.new(), [{}]) END - v9.CheckSourceFailure(lines, 'E693: Class or class typealias required for argument 2') + v9.CheckSourceScriptFailure(lines, 'E693: Class or class typealias required for argument 2') lines =<< trim END vim9script @@ -2357,22 +2357,22 @@ def Test_instanceof() enddef Bar() END - v9.CheckSourceFailure(lines, 'E693: Class or class typealias required for argument 2') + v9.CheckSourceScriptFailure(lines, 'E693: Class or class typealias required for argument 2') enddef def Test_invert() - v9.CheckDefAndScriptFailure(['invert("x")'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1210: Number required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['invert("x")'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1210: Number required for argument 1']) enddef def Test_isdirectory() - v9.CheckDefAndScriptFailure(['isdirectory(1.1)'], ['E1013: Argument 1: type mismatch, expected string but got float', 'E1174: String required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['isdirectory(1.1)'], ['E1013: Argument 1: type mismatch, expected string but got float', 'E1174: String required for argument 1']) assert_false(isdirectory('NonExistingDir')) assert_false(isdirectory('')) enddef def Test_islocked() - v9.CheckDefAndScriptFailure(['islocked(true)'], ['E1013: Argument 1: type mismatch, expected string but got bool', 'E1174: String required for argument 1']) - v9.CheckDefAndScriptFailure(['var n1: number = 10', 'islocked(n1)'], ['E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['islocked(true)'], ['E1013: Argument 1: type mismatch, expected string but got bool', 'E1174: String required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['var n1: number = 10', 'islocked(n1)'], ['E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1']) g:v1 = 10 assert_false(islocked('g:v1')) lockvar g:v1 @@ -2382,7 +2382,7 @@ def Test_islocked() enddef def Test_items() - v9.CheckDefFailure(['123->items()'], 'E1225:') + v9.CheckSourceDefFailure(['123->items()'], 'E1225:') assert_equal([['a', 10], ['b', 20]], {'a': 10, 'b': 20}->items()) assert_equal([], {}->items()) assert_equal(['x', 'x'], {'a': 10, 'b': 20}->items()->map((_, _) => 'x')) @@ -2400,7 +2400,7 @@ def Test_job_getchannel() if !has('job') CheckFeature job else - v9.CheckDefAndScriptFailure(['job_getchannel("a")'], ['E1013: Argument 1: type mismatch, expected job but got string', 'E1218: Job required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['job_getchannel("a")'], ['E1013: Argument 1: type mismatch, expected job but got string', 'E1218: Job required for argument 1']) assert_fails('job_getchannel(test_null_job())', 'E916: Not a valid job') endif enddef @@ -2409,7 +2409,7 @@ def Test_job_info() if !has('job') CheckFeature job else - v9.CheckDefAndScriptFailure(['job_info("a")'], ['E1013: Argument 1: type mismatch, expected job but got string', 'E1218: Job required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['job_info("a")'], ['E1013: Argument 1: type mismatch, expected job but got string', 'E1218: Job required for argument 1']) assert_fails('job_info(test_null_job())', 'E916: Not a valid job') endif enddef @@ -2420,8 +2420,8 @@ def Test_job_setoptions() if !has('job') CheckFeature job else - v9.CheckDefAndScriptFailure(['job_setoptions(test_null_channel(), {})'], ['E1013: Argument 1: type mismatch, expected job but got channel', 'E1218: Job required for argument 1']) - v9.CheckDefAndScriptFailure(['job_setoptions(test_null_job(), [])'], ['E1013: Argument 2: type mismatch, expected dict<any> but got list<any>', 'E1206: Dictionary required for argument 2']) + v9.CheckSourceDefAndScriptFailure(['job_setoptions(test_null_channel(), {})'], ['E1013: Argument 1: type mismatch, expected job but got channel', 'E1218: Job required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['job_setoptions(test_null_job(), [])'], ['E1013: Argument 2: type mismatch, expected dict<any> but got list<any>', 'E1206: Dictionary required for argument 2']) assert_equal('fail', job_status(test_null_job())) endif enddef @@ -2430,7 +2430,7 @@ def Test_job_status() if !has('job') CheckFeature job else - v9.CheckDefAndScriptFailure(['job_status("a")'], ['E1013: Argument 1: type mismatch, expected job but got string', 'E1218: Job required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['job_status("a")'], ['E1013: Argument 1: type mismatch, expected job but got string', 'E1218: Job required for argument 1']) assert_equal('fail', job_status(test_null_job())) endif enddef @@ -2439,25 +2439,25 @@ def Test_job_stop() if !has('job') CheckFeature job else - v9.CheckDefAndScriptFailure(['job_stop("a")'], ['E1013: Argument 1: type mismatch, expected job but got string', 'E1218: Job required for argument 1']) - v9.CheckDefAndScriptFailure(['job_stop(test_null_job(), true)'], ['E1013: Argument 2: type mismatch, expected string but got bool', 'E1220: String or Number required for argument 2']) + v9.CheckSourceDefAndScriptFailure(['job_stop("a")'], ['E1013: Argument 1: type mismatch, expected job but got string', 'E1218: Job required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['job_stop(test_null_job(), true)'], ['E1013: Argument 2: type mismatch, expected string but got bool', 'E1220: String or Number required for argument 2']) endif enddef def Test_join() - v9.CheckDefAndScriptFailure(['join("abc")'], ['E1013: Argument 1: type mismatch, expected list<any> but got string', 'E1211: List required for argument 1']) - v9.CheckDefAndScriptFailure(['join([], 2)'], ['E1013: Argument 2: type mismatch, expected string but got number', 'E1174: String required for argument 2']) + v9.CheckSourceDefAndScriptFailure(['join("abc")'], ['E1013: Argument 1: type mismatch, expected list<any> but got string', 'E1211: List required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['join([], 2)'], ['E1013: Argument 2: type mismatch, expected string but got number', 'E1174: String required for argument 2']) join([''], '')->assert_equal('') enddef def Test_js_decode() - v9.CheckDefAndScriptFailure(['js_decode(10)'], ['E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['js_decode(10)'], ['E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1']) assert_equal([1, 2], js_decode('[1,2]')) js_decode('')->assert_equal(v:none) enddef def Test_json_decode() - v9.CheckDefAndScriptFailure(['json_decode(true)'], ['E1013: Argument 1: type mismatch, expected string but got bool', 'E1174: String required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['json_decode(true)'], ['E1013: Argument 1: type mismatch, expected string but got bool', 'E1174: String required for argument 1']) assert_equal(1.0, json_decode('1.0')) json_decode('')->assert_equal(v:none) enddef @@ -2465,7 +2465,7 @@ enddef def Test_keys() assert_equal([7, 7], keys({a: 1, b: 2})->map((_, _) => 7)) - v9.CheckDefAndScriptFailure(['keys([])'], ['E1013: Argument 1: type mismatch, expected dict<any> but got list<any>', 'E1206: Dictionary required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['keys([])'], ['E1013: Argument 1: type mismatch, expected dict<any> but got list<any>', 'E1206: Dictionary required for argument 1']) assert_equal(['a'], {a: 'v'}->keys()) assert_equal([], {}->keys()) enddef @@ -2476,7 +2476,7 @@ def Test_keys_return_type() enddef def Test_len() - v9.CheckDefAndScriptFailure(['len(true)'], ['E1013: Argument 1: type mismatch, expected list<any> but got bool', 'E701: Invalid type for len()']) + v9.CheckSourceDefAndScriptFailure(['len(true)'], ['E1013: Argument 1: type mismatch, expected list<any> but got bool', 'E701: Invalid type for len()']) assert_equal(2, "ab"->len()) assert_equal(3, 456->len()) assert_equal(0, []->len()) @@ -2486,42 +2486,42 @@ enddef def Test_libcall() CheckFeature libcall - v9.CheckDefAndScriptFailure(['libcall(1, "b", 3)'], ['E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1']) - v9.CheckDefAndScriptFailure(['libcall("a", 2, 3)'], ['E1013: Argument 2: type mismatch, expected string but got number', 'E1174: String required for argument 2']) - v9.CheckDefAndScriptFailure(['libcall("a", "b", 1.1)'], ['E1013: Argument 3: type mismatch, expected string but got float', 'E1220: String or Number required for argument 3']) + v9.CheckSourceDefAndScriptFailure(['libcall(1, "b", 3)'], ['E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['libcall("a", 2, 3)'], ['E1013: Argument 2: type mismatch, expected string but got number', 'E1174: String required for argument 2']) + v9.CheckSourceDefAndScriptFailure(['libcall("a", "b", 1.1)'], ['E1013: Argument 3: type mismatch, expected string but got float', 'E1220: String or Number required for argument 3']) enddef def Test_libcallnr() CheckFeature libcall - v9.CheckDefAndScriptFailure(['libcallnr(1, "b", 3)'], ['E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1']) - v9.CheckDefAndScriptFailure(['libcallnr("a", 2, 3)'], ['E1013: Argument 2: type mismatch, expected string but got number', 'E1174: String required for argument 2']) - v9.CheckDefAndScriptFailure(['libcallnr("a", "b", 1.1)'], ['E1013: Argument 3: type mismatch, expected string but got float', 'E1220: String or Number required for argument 3']) + v9.CheckSourceDefAndScriptFailure(['libcallnr(1, "b", 3)'], ['E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['libcallnr("a", 2, 3)'], ['E1013: Argument 2: type mismatch, expected string but got number', 'E1174: String required for argument 2']) + v9.CheckSourceDefAndScriptFailure(['libcallnr("a", "b", 1.1)'], ['E1013: Argument 3: type mismatch, expected string but got float', 'E1220: String or Number required for argument 3']) enddef def Test_line() assert_fails('line(true)', 'E1174:') - v9.CheckDefAndScriptFailure(['line(1)'], ['E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1']) - v9.CheckDefAndScriptFailure(['line(".", "a")'], ['E1013: Argument 2: type mismatch, expected number but got string', 'E1210: Number required for argument 2']) - v9.CheckDefExecAndScriptFailure(['line("")'], 'E1209: Invalid value for a line number') + v9.CheckSourceDefAndScriptFailure(['line(1)'], ['E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['line(".", "a")'], ['E1013: Argument 2: type mismatch, expected number but got string', 'E1210: Number required for argument 2']) + v9.CheckSourceDefExecAndScriptFailure(['line("")'], 'E1209: Invalid value for a line number') enddef def Test_line2byte() - v9.CheckDefAndScriptFailure(['line2byte(true)'], ['E1013: Argument 1: type mismatch, expected string but got bool', 'E1220: String or Number required for argument 1']) - v9.CheckDefExecAndScriptFailure(['line2byte("")'], 'E1209: Invalid value for a line number') + v9.CheckSourceDefAndScriptFailure(['line2byte(true)'], ['E1013: Argument 1: type mismatch, expected string but got bool', 'E1220: String or Number required for argument 1']) + v9.CheckSourceDefExecAndScriptFailure(['line2byte("")'], 'E1209: Invalid value for a line number') assert_equal(-1, line2byte(1)) assert_equal(-1, line2byte(10000)) enddef def Test_lispindent() - v9.CheckDefAndScriptFailure(['lispindent({})'], ['E1013: Argument 1: type mismatch, expected string but got dict<any>', 'E1220: String or Number required for argument 1']) - v9.CheckDefExecAndScriptFailure(['lispindent("")'], 'E1209: Invalid value for a line number') - v9.CheckDefExecAndScriptFailure(['lispindent(-1)'], 'E966: Invalid line number: -1') + v9.CheckSourceDefAndScriptFailure(['lispindent({})'], ['E1013: Argument 1: type mismatch, expected string but got dict<any>', 'E1220: String or Number required for argument 1']) + v9.CheckSourceDefExecAndScriptFailure(['lispindent("")'], 'E1209: Invalid value for a line number') + v9.CheckSourceDefExecAndScriptFailure(['lispindent(-1)'], 'E966: Invalid line number: -1') assert_equal(0, lispindent(1)) enddef def Test_list2blob() - v9.CheckDefAndScriptFailure(['list2blob(10)'], ['E1013: Argument 1: type mismatch, expected list<number> but got number', 'E1211: List required for argument 1']) - v9.CheckDefFailure(['list2blob([0z10, 0z02])'], 'E1013: Argument 1: type mismatch, expected list<number> but got list<blob>') + v9.CheckSourceDefAndScriptFailure(['list2blob(10)'], ['E1013: Argument 1: type mismatch, expected list<number> but got number', 'E1211: List required for argument 1']) + v9.CheckSourceDefFailure(['list2blob([0z10, 0z02])'], 'E1013: Argument 1: type mismatch, expected list<number> but got list<blob>') enddef def Test_list2str_str2list_utf8() @@ -2532,8 +2532,8 @@ def Test_list2str_str2list_utf8() enddef def Test_list2str() - v9.CheckDefAndScriptFailure(['list2str(".", true)'], ['E1013: Argument 1: type mismatch, expected list<number> but got string', 'E1211: List required for argument 1']) - v9.CheckDefAndScriptFailure(['list2str([1], 0z10)'], ['E1013: Argument 2: type mismatch, expected bool but got blob', 'E1212: Bool required for argument 2']) + v9.CheckSourceDefAndScriptFailure(['list2str(".", true)'], ['E1013: Argument 1: type mismatch, expected list<number> but got string', 'E1211: List required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['list2str([1], 0z10)'], ['E1013: Argument 2: type mismatch, expected bool but got blob', 'E1212: Bool required for argument 2']) enddef def s:SID(): number @@ -2543,22 +2543,22 @@ def s:SID(): number enddef def Test_listener_add() - v9.CheckDefAndScriptFailure(['listener_add("1", true)'], ['E1013: Argument 2: type mismatch, expected string but got bool', 'E1220: String or Number required for argument 2']) + v9.CheckSourceDefAndScriptFailure(['listener_add("1", true)'], ['E1013: Argument 2: type mismatch, expected string but got bool', 'E1220: String or Number required for argument 2']) enddef def Test_listener_flush() - v9.CheckDefAndScriptFailure(['listener_flush([1])'], ['E1013: Argument 1: type mismatch, expected string but got list<number>', 'E1220: String or Number required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['listener_flush([1])'], ['E1013: Argument 1: type mismatch, expected string but got list<number>', 'E1220: String or Number required for argument 1']) enddef def Test_listener_remove() - v9.CheckDefAndScriptFailure(['listener_remove("x")'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1210: Number required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['listener_remove("x")'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1210: Number required for argument 1']) enddef def Test_luaeval() if !has('lua') CheckFeature lua endif - v9.CheckDefAndScriptFailure(['luaeval(10)'], ['E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['luaeval(10)'], ['E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1']) if exists_compiled('*luaeval') luaeval('')->assert_equal(v:null) endif @@ -2566,10 +2566,10 @@ enddef def Test_map() if has('channel') - v9.CheckDefAndScriptFailure(['map(test_null_channel(), "1")'], ['E1013: Argument 1: type mismatch, expected list<any> but got channel', 'E1251: List, Dictionary, Blob or String required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['map(test_null_channel(), "1")'], ['E1013: Argument 1: type mismatch, expected list<any> but got channel', 'E1251: List, Dictionary, Blob or String required for argument 1']) endif - v9.CheckDefAndScriptFailure(['map(1, "1")'], ['E1013: Argument 1: type mismatch, expected list<any> but got number', 'E1251: List, Dictionary, Blob or String required for argument 1']) - v9.CheckDefAndScriptFailure(['map([1, 2], 4)'], ['E1256: String or function required for argument 2', 'E1024: Using a Number as a String']) + v9.CheckSourceDefAndScriptFailure(['map(1, "1")'], ['E1013: Argument 1: type mismatch, expected list<any> but got number', 'E1251: List, Dictionary, Blob or String required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['map([1, 2], 4)'], ['E1256: String or function required for argument 2', 'E1024: Using a Number as a String']) # type of dict remains dict<any> even when type of values changes # same for list @@ -2599,7 +2599,7 @@ def Test_map() assert_equal({a: 'x'}, {a: [1, 2]}->map((_, v) => 'x')) assert_equal({a: 'x'}, {a: {b: 2}}->map((_, v) => 'x')) END - v9.CheckDefAndScriptSuccess(lines) + v9.CheckSourceDefAndScriptSuccess(lines) enddef def Test_map_failure() @@ -2627,7 +2627,7 @@ def Test_map_failure() g:gd = d map(g:gd, (k, v) => true) END - v9.CheckDefExecAndScriptFailure(lines, 'E1012: Type mismatch; expected number but got bool') + v9.CheckSourceDefExecAndScriptFailure(lines, 'E1012: Type mismatch; expected number but got bool') enddef def Test_map_const() @@ -2635,13 +2635,13 @@ def Test_map_const() const l = [1, 2, 3] map(l, 'SomeFunc') END - v9.CheckDefFailure(lines, 'E1307: Argument 1: Trying to modify a const list<number>') + v9.CheckSourceDefFailure(lines, 'E1307: Argument 1: Trying to modify a const list<number>') lines =<< trim END const d = {a: 1, b: 2} map(d, 'SomeFunc') END - v9.CheckDefFailure(lines, 'E1307: Argument 1: Trying to modify a const dict<number>') + v9.CheckSourceDefFailure(lines, 'E1307: Argument 1: Trying to modify a const dict<number>') enddef def Test_map_function_arg() @@ -2653,16 +2653,16 @@ def Test_map_function_arg() map(l, MapOne) assert_equal(['0:a', '1:b', '2:c'], l) END - v9.CheckDefAndScriptSuccess(lines) + v9.CheckSourceDefAndScriptSuccess(lines) lines =<< trim END range(3)->map((a, b, c) => a + b + c) END - v9.CheckDefAndScriptFailure(lines, ['E176:', 'E1190: One argument too few']) + v9.CheckSourceDefAndScriptFailure(lines, ['E176:', 'E1190: One argument too few']) lines =<< trim END range(3)->map((a, b, c, d) => a + b + c + d) END - v9.CheckDefAndScriptFailure(lines, ['E176:', 'E1190: 2 arguments too few']) + v9.CheckSourceDefAndScriptFailure(lines, ['E176:', 'E1190: 2 arguments too few']) # declared list cannot change type lines =<< trim END @@ -2672,7 +2672,7 @@ def Test_map_function_arg() var ll: list<number> = [1, 2, 3] echo map(ll, Map) END - v9.CheckDefAndScriptFailure(lines, ['E1013: Argument 2: type mismatch, expected func(?number, ?number): number but got func(number, number): string', 'E1012: Type mismatch; expected number but got string']) + v9.CheckSourceDefAndScriptFailure(lines, ['E1013: Argument 2: type mismatch, expected func(?number, ?number): number but got func(number, number): string', 'E1012: Type mismatch; expected number but got string']) # not declared list can change type echo [1, 2, 3]->map((..._) => 'x') @@ -2684,25 +2684,25 @@ def Test_map_item_type() map(l, (k, v) => k .. '/' .. v ) assert_equal(['0/a', '1/b', '2/c'], l) END - v9.CheckDefAndScriptSuccess(lines) + v9.CheckSourceDefAndScriptSuccess(lines) lines =<< trim END var l: list<number> = [0] echo map(l, (_, v) => []) END - v9.CheckDefAndScriptFailure(lines, ['E1013: Argument 2: type mismatch, expected func(?number, ?number): number but got func(any, any): list<any>', 'E1012: Type mismatch; expected number but got list<any>'], 2) + v9.CheckSourceDefAndScriptFailure(lines, ['E1013: Argument 2: type mismatch, expected func(?number, ?number): number but got func(any, any): list<any>', 'E1012: Type mismatch; expected number but got list<any>'], 2) lines =<< trim END var l: list<number> = range(2) echo map(l, (_, v) => []) END - v9.CheckDefAndScriptFailure(lines, ['E1013: Argument 2: type mismatch, expected func(?number, ?number): number but got func(any, any): list<any>', 'E1012: Type mismatch; expected number but got list<any>'], 2) + v9.CheckSourceDefAndScriptFailure(lines, ['E1013: Argument 2: type mismatch, expected func(?number, ?number): number but got func(any, any): list<any>', 'E1012: Type mismatch; expected number but got list<any>'], 2) lines =<< trim END var d: dict<number> = {key: 0} echo map(d, (_, v) => []) END - v9.CheckDefAndScriptFailure(lines, ['E1013: Argument 2: type mismatch, expected func(?string, ?number): number but got func(any, any): list<any>', 'E1012: Type mismatch; expected number but got list<any>'], 2) + v9.CheckSourceDefAndScriptFailure(lines, ['E1013: Argument 2: type mismatch, expected func(?string, ?number): number but got func(any, any): list<any>', 'E1012: Type mismatch; expected number but got list<any>'], 2) enddef def Test_maparg() @@ -2725,10 +2725,10 @@ def Test_maparg() abbr: 0, mode_bits: 0x47}) unmap foo - v9.CheckDefAndScriptFailure(['maparg(1)'], ['E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1']) - v9.CheckDefAndScriptFailure(['maparg("a", 2)'], ['E1013: Argument 2: type mismatch, expected string but got number', 'E1174: String required for argument 2']) - v9.CheckDefAndScriptFailure(['maparg("a", "b", 2)'], ['E1013: Argument 3: type mismatch, expected bool but got number', 'E1212: Bool required for argument 3']) - v9.CheckDefAndScriptFailure(['maparg("a", "b", true, 2)'], ['E1013: Argument 4: type mismatch, expected bool but got number', 'E1212: Bool required for argument 4']) + v9.CheckSourceDefAndScriptFailure(['maparg(1)'], ['E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['maparg("a", 2)'], ['E1013: Argument 2: type mismatch, expected string but got number', 'E1174: String required for argument 2']) + v9.CheckSourceDefAndScriptFailure(['maparg("a", "b", 2)'], ['E1013: Argument 3: type mismatch, expected bool but got number', 'E1212: Bool required for argument 3']) + v9.CheckSourceDefAndScriptFailure(['maparg("a", "b", true, 2)'], ['E1013: Argument 4: type mismatch, expected bool but got number', 'E1212: Bool required for argument 4']) maparg('')->assert_equal('') # value argument type is checked at compile time @@ -2736,46 +2736,46 @@ def Test_maparg() var l = [123] l->map((i: number, v: string) => 0) END - v9.CheckDefFailure(lines, 'E1013: Argument 2: type mismatch, expected func(?number, ?number): number but got func(number, string): number') + v9.CheckSourceDefFailure(lines, 'E1013: Argument 2: type mismatch, expected func(?number, ?number): number but got func(number, string): number') lines =<< trim END var d = {a: 123} d->map((i: string, v: string) => 0) END - v9.CheckDefFailure(lines, 'E1013: Argument 2: type mismatch, expected func(?string, ?number): number but got func(string, string): number') + v9.CheckSourceDefFailure(lines, 'E1013: Argument 2: type mismatch, expected func(?string, ?number): number but got func(string, string): number') lines =<< trim END var s = 'abc' s->map((i: number, v: number) => 'x') END - v9.CheckDefFailure(lines, 'E1013: Argument 2: type mismatch, expected func(?number, ?string): string but got func(number, number): string') + v9.CheckSourceDefFailure(lines, 'E1013: Argument 2: type mismatch, expected func(?number, ?string): string but got func(number, number): string') lines =<< trim END var s = 0z1122 s->map((i: number, v: string) => 0) END - v9.CheckDefFailure(lines, 'E1013: Argument 2: type mismatch, expected func(?number, ?number): number but got func(number, string): number') + v9.CheckSourceDefFailure(lines, 'E1013: Argument 2: type mismatch, expected func(?number, ?number): number but got func(number, string): number') # index argument type is checked at compile time lines =<< trim END ['x']->map((i: string, v: string) => 'y') END - v9.CheckDefFailure(lines, 'E1013: Argument 2: type mismatch, expected func(?number, ?any): any but got func(string, string): string') + v9.CheckSourceDefFailure(lines, 'E1013: Argument 2: type mismatch, expected func(?number, ?any): any but got func(string, string): string') lines =<< trim END {a: 1}->map((i: number, v: number) => 0) END - v9.CheckDefFailure(lines, 'E1013: Argument 2: type mismatch, expected func(?string, ?any): any but got func(number, number): number') + v9.CheckSourceDefFailure(lines, 'E1013: Argument 2: type mismatch, expected func(?string, ?any): any but got func(number, number): number') lines =<< trim END 'abc'->map((i: string, v: string) => 'x') END - v9.CheckDefFailure(lines, 'E1013: Argument 2: type mismatch, expected func(?number, ?string): string but got func(string, string): string') + v9.CheckSourceDefFailure(lines, 'E1013: Argument 2: type mismatch, expected func(?number, ?string): string but got func(string, string): string') lines =<< trim END 0z1122->map((i: string, v: number) => 0) END - v9.CheckDefFailure(lines, 'E1013: Argument 2: type mismatch, expected func(?number, ?number): number but got func(string, number): number') + v9.CheckSourceDefFailure(lines, 'E1013: Argument 2: type mismatch, expected func(?number, ?number): number but got func(string, number): number') enddef def Test_maparg_mapset() @@ -2790,31 +2790,31 @@ def Test_mapcheck() iabbrev foo foobar mapcheck('foo', 'i', true)->assert_equal('foobar') iunabbrev foo - v9.CheckDefAndScriptFailure(['mapcheck(1)'], ['E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1']) - v9.CheckDefAndScriptFailure(['mapcheck("a", 2)'], ['E1013: Argument 2: type mismatch, expected string but got number', 'E1174: String required for argument 2']) - v9.CheckDefAndScriptFailure(['mapcheck("a", "b", 2)'], ['E1013: Argument 3: type mismatch, expected bool but got number', 'E1212: Bool required for argument 3']) + v9.CheckSourceDefAndScriptFailure(['mapcheck(1)'], ['E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['mapcheck("a", 2)'], ['E1013: Argument 2: type mismatch, expected string but got number', 'E1174: String required for argument 2']) + v9.CheckSourceDefAndScriptFailure(['mapcheck("a", "b", 2)'], ['E1013: Argument 3: type mismatch, expected bool but got number', 'E1212: Bool required for argument 3']) mapcheck('')->assert_equal('') mapcheck('', '')->assert_equal('') enddef def Test_mapnew() if has('channel') - v9.CheckDefAndScriptFailure(['mapnew(test_null_job(), "1")'], ['E1013: Argument 1: type mismatch, expected list<any> but got job', 'E1251: List, Dictionary, Blob or String required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['mapnew(test_null_job(), "1")'], ['E1013: Argument 1: type mismatch, expected list<any> but got job', 'E1251: List, Dictionary, Blob or String required for argument 1']) endif - v9.CheckDefAndScriptFailure(['mapnew(1, "1")'], ['E1013: Argument 1: type mismatch, expected list<any> but got number', 'E1251: List, Dictionary, Blob or String required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['mapnew(1, "1")'], ['E1013: Argument 1: type mismatch, expected list<any> but got number', 'E1251: List, Dictionary, Blob or String required for argument 1']) enddef def Test_mapset() - v9.CheckDefAndScriptFailure(['mapset(1, true, {})'], ['E1013: Argument 1: type mismatch, expected string but got number', 'E1223: String or Dictionary required for argument 1']) - v9.CheckDefAndScriptFailure(['mapset("a", 2, {})'], ['E1013: Argument 2: type mismatch, expected bool but got number', 'E1212: Bool required for argument 2']) - v9.CheckDefAndScriptFailure(['mapset("a", false, [])'], ['E1013: Argument 3: type mismatch, expected dict<any> but got list<any>', 'E1206: Dictionary required for argument 3']) + v9.CheckSourceDefAndScriptFailure(['mapset(1, true, {})'], ['E1013: Argument 1: type mismatch, expected string but got number', 'E1223: String or Dictionary required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['mapset("a", 2, {})'], ['E1013: Argument 2: type mismatch, expected bool but got number', 'E1212: Bool required for argument 2']) + v9.CheckSourceDefAndScriptFailure(['mapset("a", false, [])'], ['E1013: Argument 3: type mismatch, expected dict<any> but got list<any>', 'E1206: Dictionary required for argument 3']) enddef def Test_match() - v9.CheckDefAndScriptFailure(['match(0z12, "p")'], ['E1013: Argument 1: type mismatch, expected string but got blob', 'E1222: String or List required for argument 1']) - v9.CheckDefAndScriptFailure(['match(["s"], [2])'], ['E1013: Argument 2: type mismatch, expected string but got list<number>', 'E1174: String required for argument 2']) - v9.CheckDefAndScriptFailure(['match("s", "p", "q")'], ['E1013: Argument 3: type mismatch, expected number but got string', 'E1210: Number required for argument 3']) - v9.CheckDefAndScriptFailure(['match("s", "p", 1, "r")'], ['E1013: Argument 4: type mismatch, expected number but got string', 'E1210: Number required for argument 4']) + v9.CheckSourceDefAndScriptFailure(['match(0z12, "p")'], ['E1013: Argument 1: type mismatch, expected string but got blob', 'E1222: String or List required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['match(["s"], [2])'], ['E1013: Argument 2: type mismatch, expected string but got list<number>', 'E1174: String required for argument 2']) + v9.CheckSourceDefAndScriptFailure(['match("s", "p", "q")'], ['E1013: Argument 3: type mismatch, expected number but got string', 'E1210: Number required for argument 3']) + v9.CheckSourceDefAndScriptFailure(['match("s", "p", 1, "r")'], ['E1013: Argument 4: type mismatch, expected number but got string', 'E1210: Number required for argument 4']) assert_equal(2, match('ab12cd', '12')) assert_equal(-1, match('ab12cd', '34')) assert_equal(6, match('ab12cd12ef', '12', 4)) @@ -2829,39 +2829,39 @@ def Test_match() enddef def Test_matchadd() - v9.CheckDefAndScriptFailure(['matchadd(1, "b")'], ['E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1']) - v9.CheckDefAndScriptFailure(['matchadd("a", 2)'], ['E1013: Argument 2: type mismatch, expected string but got number', 'E1174: String required for argument 2']) - v9.CheckDefAndScriptFailure(['matchadd("a", "b", "c")'], ['E1013: Argument 3: type mismatch, expected number but got string', 'E1210: Number required for argument 3']) - v9.CheckDefAndScriptFailure(['matchadd("a", "b", 1, "d")'], ['E1013: Argument 4: type mismatch, expected number but got string', 'E1210: Number required for argument 4']) - v9.CheckDefAndScriptFailure(['matchadd("a", "b", 1, 1, [])'], ['E1013: Argument 5: type mismatch, expected dict<any> but got list<any>', 'E1206: Dictionary required for argument 5']) + v9.CheckSourceDefAndScriptFailure(['matchadd(1, "b")'], ['E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['matchadd("a", 2)'], ['E1013: Argument 2: type mismatch, expected string but got number', 'E1174: String required for argument 2']) + v9.CheckSourceDefAndScriptFailure(['matchadd("a", "b", "c")'], ['E1013: Argument 3: type mismatch, expected number but got string', 'E1210: Number required for argument 3']) + v9.CheckSourceDefAndScriptFailure(['matchadd("a", "b", 1, "d")'], ['E1013: Argument 4: type mismatch, expected number but got string', 'E1210: Number required for argument 4']) + v9.CheckSourceDefAndScriptFailure(['matchadd("a", "b", 1, 1, [])'], ['E1013: Argument 5: type mismatch, expected dict<any> but got list<any>', 'E1206: Dictionary required for argument 5']) matchadd('', 'a')->assert_equal(-1) matchadd('Search', '')->assert_equal(-1) enddef def Test_matchaddpos() - v9.CheckDefAndScriptFailure(['matchaddpos(1, [1])'], ['E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1']) - v9.CheckDefAndScriptFailure(['matchaddpos("a", "b")'], ['E1013: Argument 2: type mismatch, expected list<any> but got string', 'E1211: List required for argument 2']) - v9.CheckDefAndScriptFailure(['matchaddpos("a", [1], "c")'], ['E1013: Argument 3: type mismatch, expected number but got string', 'E1210: Number required for argument 3']) - v9.CheckDefAndScriptFailure(['matchaddpos("a", [1], 1, "d")'], ['E1013: Argument 4: type mismatch, expected number but got string', 'E1210: Number required for argument 4']) - v9.CheckDefAndScriptFailure(['matchaddpos("a", [1], 1, 1, [])'], ['E1013: Argument 5: type mismatch, expected dict<any> but got list<any>', 'E1206: Dictionary required for argument 5']) + v9.CheckSourceDefAndScriptFailure(['matchaddpos(1, [1])'], ['E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['matchaddpos("a", "b")'], ['E1013: Argument 2: type mismatch, expected list<any> but got string', 'E1211: List required for argument 2']) + v9.CheckSourceDefAndScriptFailure(['matchaddpos("a", [1], "c")'], ['E1013: Argument 3: type mismatch, expected number but got string', 'E1210: Number required for argument 3']) + v9.CheckSourceDefAndScriptFailure(['matchaddpos("a", [1], 1, "d")'], ['E1013: Argument 4: type mismatch, expected number but got string', 'E1210: Number required for argument 4']) + v9.CheckSourceDefAndScriptFailure(['matchaddpos("a", [1], 1, 1, [])'], ['E1013: Argument 5: type mismatch, expected dict<any> but got list<any>', 'E1206: Dictionary required for argument 5']) matchaddpos('', [1])->assert_equal(-1) enddef def Test_matcharg() - v9.CheckDefAndScriptFailure(['matcharg("x")'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1210: Number required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['matcharg("x")'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1210: Number required for argument 1']) enddef def Test_matchdelete() - v9.CheckDefAndScriptFailure(['matchdelete("x")'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1210: Number required for argument 1']) - v9.CheckDefAndScriptFailure(['matchdelete("x", 1)'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1210: Number required for argument 1']) - v9.CheckDefAndScriptFailure(['matchdelete(1, "x")'], ['E1013: Argument 2: type mismatch, expected number but got string', 'E1210: Number required for argument 2']) + v9.CheckSourceDefAndScriptFailure(['matchdelete("x")'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1210: Number required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['matchdelete("x", 1)'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1210: Number required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['matchdelete(1, "x")'], ['E1013: Argument 2: type mismatch, expected number but got string', 'E1210: Number required for argument 2']) enddef def Test_matchend() - v9.CheckDefAndScriptFailure(['matchend(0z12, "p")'], ['E1013: Argument 1: type mismatch, expected string but got blob', 'E1222: String or List required for argument 1']) - v9.CheckDefAndScriptFailure(['matchend(["s"], [2])'], ['E1013: Argument 2: type mismatch, expected string but got list<number>', 'E1174: String required for argument 2']) - v9.CheckDefAndScriptFailure(['matchend("s", "p", "q")'], ['E1013: Argument 3: type mismatch, expected number but got string', 'E1210: Number required for argument 3']) - v9.CheckDefAndScriptFailure(['matchend("s", "p", 1, "r")'], ['E1013: Argument 4: type mismatch, expected number but got string', 'E1210: Number required for argument 4']) + v9.CheckSourceDefAndScriptFailure(['matchend(0z12, "p")'], ['E1013: Argument 1: type mismatch, expected string but got blob', 'E1222: String or List required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['matchend(["s"], [2])'], ['E1013: Argument 2: type mismatch, expected string but got list<number>', 'E1174: String required for argument 2']) + v9.CheckSourceDefAndScriptFailure(['matchend("s", "p", "q")'], ['E1013: Argument 3: type mismatch, expected number but got string', 'E1210: Number required for argument 3']) + v9.CheckSourceDefAndScriptFailure(['matchend("s", "p", 1, "r")'], ['E1013: Argument 4: type mismatch, expected number but got string', 'E1210: Number required for argument 4']) assert_equal(4, matchend('ab12cd', '12')) assert_equal(-1, matchend('ab12cd', '34')) assert_equal(8, matchend('ab12cd12ef', '12', 4)) @@ -2876,9 +2876,9 @@ def Test_matchend() enddef def Test_matchfuzzy() - v9.CheckDefAndScriptFailure(['matchfuzzy({}, "p")'], ['E1013: Argument 1: type mismatch, expected list<any> but got dict<any>', 'E1211: List required for argument 1']) - v9.CheckDefAndScriptFailure(['matchfuzzy([], 1)'], ['E1013: Argument 2: type mismatch, expected string but got number', 'E1174: String required for argument 2']) - v9.CheckDefAndScriptFailure(['matchfuzzy([], "a", [])'], ['E1013: Argument 3: type mismatch, expected dict<any> but got list<any>', 'E1206: Dictionary required for argument 3']) + v9.CheckSourceDefAndScriptFailure(['matchfuzzy({}, "p")'], ['E1013: Argument 1: type mismatch, expected list<any> but got dict<any>', 'E1211: List required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['matchfuzzy([], 1)'], ['E1013: Argument 2: type mismatch, expected string but got number', 'E1174: String required for argument 2']) + v9.CheckSourceDefAndScriptFailure(['matchfuzzy([], "a", [])'], ['E1013: Argument 3: type mismatch, expected dict<any> but got list<any>', 'E1206: Dictionary required for argument 3']) matchfuzzy(['abc', 'xyz'], '')->assert_equal([]) var lines =<< trim END var items = [{name: 'xyz', id: 1}, {name: 'def', id: 2}, @@ -2888,13 +2888,13 @@ def Test_matchfuzzy() var k: list<string> = matchfuzzy(['one', 'two', 'who'], 'o') assert_equal(['one', 'two', 'who'], k) END - v9.CheckDefAndScriptSuccess(lines) + v9.CheckSourceDefAndScriptSuccess(lines) enddef def Test_matchfuzzypos() - v9.CheckDefAndScriptFailure(['matchfuzzypos({}, "p")'], ['E1013: Argument 1: type mismatch, expected list<any> but got dict<any>', 'E1211: List required for argument 1']) - v9.CheckDefAndScriptFailure(['matchfuzzypos([], 1)'], ['E1013: Argument 2: type mismatch, expected string but got number', 'E1174: String required for argument 2']) - v9.CheckDefAndScriptFailure(['matchfuzzypos([], "a", [])'], ['E1013: Argument 3: type mismatch, expected dict<any> but got list<any>', 'E1206: Dictionary required for argument 3']) + v9.CheckSourceDefAndScriptFailure(['matchfuzzypos({}, "p")'], ['E1013: Argument 1: type mismatch, expected list<any> but got dict<any>', 'E1211: List required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['matchfuzzypos([], 1)'], ['E1013: Argument 2: type mismatch, expected string but got number', 'E1174: String required for argument 2']) + v9.CheckSourceDefAndScriptFailure(['matchfuzzypos([], "a", [])'], ['E1013: Argument 3: type mismatch, expected dict<any> but got list<any>', 'E1206: Dictionary required for argument 3']) matchfuzzypos(['abc', 'xyz'], '')->assert_equal([[], [], []]) var lines =<< trim END var items = [{name: 'xyz', id: 1}, {name: 'def', id: 2}, @@ -2904,14 +2904,14 @@ def Test_matchfuzzypos() var k: list<string> = matchfuzzypos(['one', 'two', 'who'], 'o')[0] assert_equal(['one', 'two', 'who'], k) END - v9.CheckDefAndScriptSuccess(lines) + v9.CheckSourceDefAndScriptSuccess(lines) enddef def Test_matchlist() - v9.CheckDefAndScriptFailure(['matchlist(0z12, "p")'], ['E1013: Argument 1: type mismatch, expected string but got blob', 'E1222: String or List required for argument 1']) - v9.CheckDefAndScriptFailure(['matchlist(["s"], [2])'], ['E1013: Argument 2: type mismatch, expected string but got list<number>', 'E1174: String required for argument 2']) - v9.CheckDefAndScriptFailure(['matchlist("s", "p", "q")'], ['E1013: Argument 3: type mismatch, expected number but got string', 'E1210: Number required for argument 3']) - v9.CheckDefAndScriptFailure(['matchlist("s", "p", 1, "r")'], ['E1013: Argument 4: type mismatch, expected number but got string', 'E1210: Number required for argument 4']) + v9.CheckSourceDefAndScriptFailure(['matchlist(0z12, "p")'], ['E1013: Argument 1: type mismatch, expected string but got blob', 'E1222: String or List required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['matchlist(["s"], [2])'], ['E1013: Argument 2: type mismatch, expected string but got list<number>', 'E1174: String required for argument 2']) + v9.CheckSourceDefAndScriptFailure(['matchlist("s", "p", "q")'], ['E1013: Argument 3: type mismatch, expected number but got string', 'E1210: Number required for argument 3']) + v9.CheckSourceDefAndScriptFailure(['matchlist("s", "p", 1, "r")'], ['E1013: Argument 4: type mismatch, expected number but got string', 'E1210: Number required for argument 4']) var l: list<string> = ['12', '', '', '', '', '', '', '', '', ''] assert_equal(l, matchlist('ab12cd', '12')) assert_equal([], matchlist('ab12cd', '34')) @@ -2929,10 +2929,10 @@ def Test_matchlist() enddef def Test_matchstr() - v9.CheckDefAndScriptFailure(['matchstr(0z12, "p")'], ['E1013: Argument 1: type mismatch, expected string but got blob', 'E1222: String or List required for argument 1']) - v9.CheckDefAndScriptFailure(['matchstr(["s"], [2])'], ['E1013: Argument 2: type mismatch, expected string but got list<number>', 'E1174: String required for argument 2']) - v9.CheckDefAndScriptFailure(['matchstr("s", "p", "q")'], ['E1013: Argument 3: type mismatch, expected number but got string', 'E1210: Number required for argument 3']) - v9.CheckDefAndScriptFailure(['matchstr("s", "p", 1, "r")'], ['E1013: Argument 4: type mismatch, expected number but got string', 'E1210: Number required for argument 4']) + v9.CheckSourceDefAndScriptFailure(['matchstr(0z12, "p")'], ['E1013: Argument 1: type mismatch, expected string but got blob', 'E1222: String or List required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['matchstr(["s"], [2])'], ['E1013: Argument 2: type mismatch, expected string but got list<number>', 'E1174: String required for argument 2']) + v9.CheckSourceDefAndScriptFailure(['matchstr("s", "p", "q")'], ['E1013: Argument 3: type mismatch, expected number but got string', 'E1210: Number required for argument 3']) + v9.CheckSourceDefAndScriptFailure(['matchstr("s", "p", 1, "r")'], ['E1013: Argument 4: type mismatch, expected number but got string', 'E1210: Number required for argument 4']) assert_equal('12', matchstr('ab12cd', '12')) assert_equal('', matchstr('ab12cd', '34')) assert_equal('12', matchstr('ab12cd12ef', '12', 4)) @@ -2947,10 +2947,10 @@ def Test_matchstr() enddef def Test_matchstrpos() - v9.CheckDefAndScriptFailure(['matchstrpos(0z12, "p")'], ['E1013: Argument 1: type mismatch, expected string but got blob', 'E1222: String or List required for argument 1']) - v9.CheckDefAndScriptFailure(['matchstrpos(["s"], [2])'], ['E1013: Argument 2: type mismatch, expected string but got list<number>', 'E1174: String required for argument 2']) - v9.CheckDefAndScriptFailure(['matchstrpos("s", "p", "q")'], ['E1013: Argument 3: type mismatch, expected number but got string', 'E1210: Number required for argument 3']) - v9.CheckDefAndScriptFailure(['matchstrpos("s", "p", 1, "r")'], ['E1013: Argument 4: type mismatch, expected number but got string', 'E1210: Number required for argument 4']) + v9.CheckSourceDefAndScriptFailure(['matchstrpos(0z12, "p")'], ['E1013: Argument 1: type mismatch, expected string but got blob', 'E1222: String or List required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['matchstrpos(["s"], [2])'], ['E1013: Argument 2: type mismatch, expected string but got list<number>', 'E1174: String required for argument 2']) + v9.CheckSourceDefAndScriptFailure(['matchstrpos("s", "p", "q")'], ['E1013: Argument 3: type mismatch, expected number but got string', 'E1210: Number required for argument 3']) + v9.CheckSourceDefAndScriptFailure(['matchstrpos("s", "p", 1, "r")'], ['E1013: Argument 4: type mismatch, expected number but got string', 'E1210: Number required for argument 4']) assert_equal(['12', 2, 4], matchstrpos('ab12cd', '12')) assert_equal(['', -1, -1], matchstrpos('ab12cd', '34')) assert_equal(['12', 6, 8], matchstrpos('ab12cd12ef', '12', 4)) @@ -2978,13 +2978,13 @@ def Test_max() ? [1, max([2, 3])] : [4, 5] assert_equal([4, 5], l2) - v9.CheckDefAndScriptFailure(['max(5)'], ['E1013: Argument 1: type mismatch, expected list<any> but got number', 'E1227: List or Dictionary required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['max(5)'], ['E1013: Argument 1: type mismatch, expected list<any> but got number', 'E1227: List or Dictionary required for argument 1']) enddef def Test_menu_info() - v9.CheckDefAndScriptFailure(['menu_info(10)'], ['E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1']) - v9.CheckDefAndScriptFailure(['menu_info(10, "n")'], ['E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1']) - v9.CheckDefAndScriptFailure(['menu_info("File", 10)'], ['E1013: Argument 2: type mismatch, expected string but got number', 'E1174: String required for argument 2']) + v9.CheckSourceDefAndScriptFailure(['menu_info(10)'], ['E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['menu_info(10, "n")'], ['E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['menu_info("File", 10)'], ['E1013: Argument 2: type mismatch, expected string but got number', 'E1174: String required for argument 2']) assert_equal({}, menu_info('aMenu')) enddef @@ -3000,49 +3000,49 @@ def Test_min() ? [1, min([2, 3])] : [4, 5] assert_equal([4, 5], l2) - v9.CheckDefAndScriptFailure(['min(5)'], ['E1013: Argument 1: type mismatch, expected list<any> but got number', 'E1227: List or Dictionary required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['min(5)'], ['E1013: Argument 1: type mismatch, expected list<any> but got number', 'E1227: List or Dictionary required for argument 1']) enddef def Test_mkdir() - v9.CheckDefAndScriptFailure(['mkdir(["a"])'], ['E1013: Argument 1: type mismatch, expected string but got list<string>', 'E1174: String required for argument 1']) - v9.CheckDefAndScriptFailure(['mkdir("a", {})'], ['E1013: Argument 2: type mismatch, expected string but got dict<any>', 'E1174: String required for argument 2']) - v9.CheckDefAndScriptFailure(['mkdir("a", "b", "c")'], ['E1013: Argument 3: type mismatch, expected number but got string', 'E1210: Number required for argument 3']) - v9.CheckDefExecAndScriptFailure(['mkdir("")'], 'E1175: Non-empty string required for argument 1') + v9.CheckSourceDefAndScriptFailure(['mkdir(["a"])'], ['E1013: Argument 1: type mismatch, expected string but got list<string>', 'E1174: String required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['mkdir("a", {})'], ['E1013: Argument 2: type mismatch, expected string but got dict<any>', 'E1174: String required for argument 2']) + v9.CheckSourceDefAndScriptFailure(['mkdir("a", "b", "c")'], ['E1013: Argument 3: type mismatch, expected number but got string', 'E1210: Number required for argument 3']) + v9.CheckSourceDefExecAndScriptFailure(['mkdir("")'], 'E1175: Non-empty string required for argument 1') delete('a', 'rf') enddef def Test_mode() - v9.CheckDefAndScriptFailure(['mode("1")'], ['E1013: Argument 1: type mismatch, expected bool but got string', 'E1212: Bool required for argument 1']) - v9.CheckDefAndScriptFailure(['mode(2)'], ['E1013: Argument 1: type mismatch, expected bool but got number', 'E1212: Bool required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['mode("1")'], ['E1013: Argument 1: type mismatch, expected bool but got string', 'E1212: Bool required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['mode(2)'], ['E1013: Argument 1: type mismatch, expected bool but got number', 'E1212: Bool required for argument 1']) enddef def Test_mzeval() if !has('mzscheme') CheckFeature mzscheme endif - v9.CheckDefAndScriptFailure(['mzeval(["a"])'], ['E1013: Argument 1: type mismatch, expected string but got list<string>', 'E1174: String required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['mzeval(["a"])'], ['E1013: Argument 1: type mismatch, expected string but got list<string>', 'E1174: String required for argument 1']) enddef def Test_nextnonblank() - v9.CheckDefAndScriptFailure(['nextnonblank(null)'], ['E1013: Argument 1: type mismatch, expected string but got special', 'E1220: String or Number required for argument 1']) - v9.CheckDefExecAndScriptFailure(['nextnonblank("")'], 'E1209: Invalid value for a line number') + v9.CheckSourceDefAndScriptFailure(['nextnonblank(null)'], ['E1013: Argument 1: type mismatch, expected string but got special', 'E1220: String or Number required for argument 1']) + v9.CheckSourceDefExecAndScriptFailure(['nextnonblank("")'], 'E1209: Invalid value for a line number') assert_equal(0, nextnonblank(1)) enddef def Test_nr2char() nr2char(97, true)->assert_equal('a') - v9.CheckDefAndScriptFailure(['nr2char("x")'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1210: Number required for argument 1']) - v9.CheckDefAndScriptFailure(['nr2char(1, "a")'], ['E1013: Argument 2: type mismatch, expected bool but got string', 'E1212: Bool required for argument 2']) + v9.CheckSourceDefAndScriptFailure(['nr2char("x")'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1210: Number required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['nr2char(1, "a")'], ['E1013: Argument 2: type mismatch, expected bool but got string', 'E1212: Bool required for argument 2']) enddef def Test_or() - v9.CheckDefAndScriptFailure(['or("x", 0x2)'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1210: Number required for argument 1']) - v9.CheckDefAndScriptFailure(['or(0x1, "x")'], ['E1013: Argument 2: type mismatch, expected number but got string', 'E1210: Number required for argument 2']) + v9.CheckSourceDefAndScriptFailure(['or("x", 0x2)'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1210: Number required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['or(0x1, "x")'], ['E1013: Argument 2: type mismatch, expected number but got string', 'E1210: Number required for argument 2']) enddef def Test_pathshorten() - v9.CheckDefAndScriptFailure(['pathshorten(1)'], ['E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1']) - v9.CheckDefAndScriptFailure(['pathshorten("a", "x")'], ['E1013: Argument 2: type mismatch, expected number but got string', 'E1210: Number required for argument 2']) + v9.CheckSourceDefAndScriptFailure(['pathshorten(1)'], ['E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['pathshorten("a", "x")'], ['E1013: Argument 2: type mismatch, expected number but got string', 'E1210: Number required for argument 2']) pathshorten('')->assert_equal('') enddef @@ -3050,12 +3050,12 @@ def Test_perleval() if !has('perl') CheckFeature perl endif - v9.CheckDefAndScriptFailure(['perleval(["a"])'], ['E1013: Argument 1: type mismatch, expected string but got list<string>', 'E1174: String required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['perleval(["a"])'], ['E1013: Argument 1: type mismatch, expected string but got list<string>', 'E1174: String required for argument 1']) enddef def Test_popup_atcursor() - v9.CheckDefAndScriptFailure(['popup_atcursor({"a": 10}, {})'], ['E1013: Argument 1: type mismatch, expected string but got dict<number>', 'E1224: String, Number or List required for argument 1']) - v9.CheckDefAndScriptFailure(['popup_atcursor("a", [1, 2])'], ['E1013: Argument 2: type mismatch, expected dict<any> but got list<number>', 'E1206: Dictionary required for argument 2']) + v9.CheckSourceDefAndScriptFailure(['popup_atcursor({"a": 10}, {})'], ['E1013: Argument 1: type mismatch, expected string but got dict<number>', 'E1224: String, Number or List required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['popup_atcursor("a", [1, 2])'], ['E1013: Argument 2: type mismatch, expected dict<any> but got list<number>', 'E1206: Dictionary required for argument 2']) # Pass variable of type 'any' to popup_atcursor() var what: any = 'Hello' @@ -3065,17 +3065,17 @@ def Test_popup_atcursor() enddef def Test_popup_beval() - v9.CheckDefAndScriptFailure(['popup_beval({"a": 10}, {})'], ['E1013: Argument 1: type mismatch, expected string but got dict<number>', 'E1224: String, Number or List required for argument 1']) - v9.CheckDefAndScriptFailure(['popup_beval("a", [1, 2])'], ['E1013: Argument 2: type mismatch, expected dict<any> but got list<number>', 'E1206: Dictionary required for argument 2']) + v9.CheckSourceDefAndScriptFailure(['popup_beval({"a": 10}, {})'], ['E1013: Argument 1: type mismatch, expected string but got dict<number>', 'E1224: String, Number or List required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['popup_beval("a", [1, 2])'], ['E1013: Argument 2: type mismatch, expected dict<any> but got list<number>', 'E1206: Dictionary required for argument 2']) enddef def Test_popup_clear() - v9.CheckDefAndScriptFailure(['popup_clear(["a"])'], ['E1013: Argument 1: type mismatch, expected bool but got list<string>', 'E1212: Bool required for argument 1']) - v9.CheckDefAndScriptFailure(['popup_clear(2)'], ['E1013: Argument 1: type mismatch, expected bool but got number', 'E1212: Bool required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['popup_clear(["a"])'], ['E1013: Argument 1: type mismatch, expected bool but got list<string>', 'E1212: Bool required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['popup_clear(2)'], ['E1013: Argument 1: type mismatch, expected bool but got number', 'E1212: Bool required for argument 1']) enddef def Test_popup_close() - v9.CheckDefAndScriptFailure(['popup_close("a")'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1210: Number required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['popup_close("a")'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1210: Number required for argument 1']) enddef def Test_popup_create() @@ -3087,81 +3087,81 @@ def Test_popup_create() enddef def Test_popup_dialog() - v9.CheckDefAndScriptFailure(['popup_dialog({"a": 10}, {})'], ['E1013: Argument 1: type mismatch, expected string but got dict<number>', 'E1224: String, Number or List required for argument 1']) - v9.CheckDefAndScriptFailure(['popup_dialog("a", [1, 2])'], ['E1013: Argument 2: type mismatch, expected dict<any> but got list<number>', 'E1206: Dictionary required for argument 2']) + v9.CheckSourceDefAndScriptFailure(['popup_dialog({"a": 10}, {})'], ['E1013: Argument 1: type mismatch, expected string but got dict<number>', 'E1224: String, Number or List required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['popup_dialog("a", [1, 2])'], ['E1013: Argument 2: type mismatch, expected dict<any> but got list<number>', 'E1206: Dictionary required for argument 2']) enddef def Test_popup_filter_menu() - v9.CheckDefAndScriptFailure(['popup_filter_menu("x", "")'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1210: Number required for argument 1']) - v9.CheckDefAndScriptFailure(['popup_filter_menu(1, 1)'], ['E1013: Argument 2: type mismatch, expected string but got number', 'E1174: String required for argument 2']) + v9.CheckSourceDefAndScriptFailure(['popup_filter_menu("x", "")'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1210: Number required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['popup_filter_menu(1, 1)'], ['E1013: Argument 2: type mismatch, expected string but got number', 'E1174: String required for argument 2']) var id: number = popup_menu(["one", "two", "three"], {}) popup_filter_menu(id, '') popup_close(id) enddef def Test_popup_filter_yesno() - v9.CheckDefAndScriptFailure(['popup_filter_yesno("x", "")'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1210: Number required for argument 1']) - v9.CheckDefAndScriptFailure(['popup_filter_yesno(1, 1)'], ['E1013: Argument 2: type mismatch, expected string but got number', 'E1174: String required for argument 2']) + v9.CheckSourceDefAndScriptFailure(['popup_filter_yesno("x", "")'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1210: Number required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['popup_filter_yesno(1, 1)'], ['E1013: Argument 2: type mismatch, expected string but got number', 'E1174: String required for argument 2']) enddef def Test_popup_getoptions() - v9.CheckDefAndScriptFailure(['popup_getoptions("a")'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1210: Number required for argument 1']) - v9.CheckDefAndScriptFailure(['popup_getoptions(true)'], ['E1013: Argument 1: type mismatch, expected number but got bool', 'E1210: Number required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['popup_getoptions("a")'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1210: Number required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['popup_getoptions(true)'], ['E1013: Argument 1: type mismatch, expected number but got bool', 'E1210: Number required for argument 1']) enddef def Test_popup_getpos() - v9.CheckDefAndScriptFailure(['popup_getpos("a")'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1210: Number required for argument 1']) - v9.CheckDefAndScriptFailure(['popup_getpos(true)'], ['E1013: Argument 1: type mismatch, expected number but got bool', 'E1210: Number required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['popup_getpos("a")'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1210: Number required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['popup_getpos(true)'], ['E1013: Argument 1: type mismatch, expected number but got bool', 'E1210: Number required for argument 1']) enddef def Test_popup_hide() - v9.CheckDefAndScriptFailure(['popup_hide("a")'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1210: Number required for argument 1']) - v9.CheckDefAndScriptFailure(['popup_hide(true)'], ['E1013: Argument 1: type mismatch, expected number but got bool', 'E1210: Number required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['popup_hide("a")'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1210: Number required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['popup_hide(true)'], ['E1013: Argument 1: type mismatch, expected number but got bool', 'E1210: Number required for argument 1']) enddef def Test_popup_locate() - v9.CheckDefAndScriptFailure(['popup_locate("a", 20)'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1210: Number required for argument 1']) - v9.CheckDefAndScriptFailure(['popup_locate(10, "b")'], ['E1013: Argument 2: type mismatch, expected number but got string', 'E1210: Number required for argument 2']) + v9.CheckSourceDefAndScriptFailure(['popup_locate("a", 20)'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1210: Number required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['popup_locate(10, "b")'], ['E1013: Argument 2: type mismatch, expected number but got string', 'E1210: Number required for argument 2']) enddef def Test_popup_menu() - v9.CheckDefAndScriptFailure(['popup_menu({"a": 10}, {})'], ['E1013: Argument 1: type mismatch, expected string but got dict<number>', 'E1224: String, Number or List required for argument 1']) - v9.CheckDefAndScriptFailure(['popup_menu("a", [1, 2])'], ['E1013: Argument 2: type mismatch, expected dict<any> but got list<number>', 'E1206: Dictionary required for argument 2']) + v9.CheckSourceDefAndScriptFailure(['popup_menu({"a": 10}, {})'], ['E1013: Argument 1: type mismatch, expected string but got dict<number>', 'E1224: String, Number or List required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['popup_menu("a", [1, 2])'], ['E1013: Argument 2: type mismatch, expected dict<any> but got list<number>', 'E1206: Dictionary required for argument 2']) enddef def Test_popup_move() - v9.CheckDefAndScriptFailure(['popup_move("x", {})'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1210: Number required for argument 1']) - v9.CheckDefAndScriptFailure(['popup_move(1, [])'], ['E1013: Argument 2: type mismatch, expected dict<any> but got list<any>', 'E1206: Dictionary required for argument 2']) + v9.CheckSourceDefAndScriptFailure(['popup_move("x", {})'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1210: Number required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['popup_move(1, [])'], ['E1013: Argument 2: type mismatch, expected dict<any> but got list<any>', 'E1206: Dictionary required for argument 2']) enddef def Test_popup_notification() - v9.CheckDefAndScriptFailure(['popup_notification({"a": 10}, {})'], ['E1013: Argument 1: type mismatch, expected string but got dict<number>', 'E1224: String, Number or List required for argument 1']) - v9.CheckDefAndScriptFailure(['popup_notification("a", [1, 2])'], ['E1013: Argument 2: type mismatch, expected dict<any> but got list<number>', 'E1206: Dictionary required for argument 2']) + v9.CheckSourceDefAndScriptFailure(['popup_notification({"a": 10}, {})'], ['E1013: Argument 1: type mismatch, expected string but got dict<number>', 'E1224: String, Number or List required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['popup_notification("a", [1, 2])'], ['E1013: Argument 2: type mismatch, expected dict<any> but got list<number>', 'E1206: Dictionary required for argument 2']) enddef def Test_popup_setoptions() - v9.CheckDefAndScriptFailure(['popup_setoptions("x", {})'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1210: Number required for argument 1']) - v9.CheckDefAndScriptFailure(['popup_setoptions(1, [])'], ['E1013: Argument 2: type mismatch, expected dict<any> but got list<any>', 'E1206: Dictionary required for argument 2']) + v9.CheckSourceDefAndScriptFailure(['popup_setoptions("x", {})'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1210: Number required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['popup_setoptions(1, [])'], ['E1013: Argument 2: type mismatch, expected dict<any> but got list<any>', 'E1206: Dictionary required for argument 2']) enddef def Test_popup_settext() - v9.CheckDefAndScriptFailure(['popup_settext("x", [])'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1210: Number required for argument 1']) - v9.CheckDefAndScriptFailure(['popup_settext(1, 2)'], ['E1013: Argument 2: type mismatch, expected string but got number', 'E1222: String or List required for argument 2']) + v9.CheckSourceDefAndScriptFailure(['popup_settext("x", [])'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1210: Number required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['popup_settext(1, 2)'], ['E1013: Argument 2: type mismatch, expected string but got number', 'E1222: String or List required for argument 2']) enddef def Test_popup_show() - v9.CheckDefAndScriptFailure(['popup_show("a")'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1210: Number required for argument 1']) - v9.CheckDefAndScriptFailure(['popup_show(true)'], ['E1013: Argument 1: type mismatch, expected number but got bool', 'E1210: Number required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['popup_show("a")'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1210: Number required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['popup_show(true)'], ['E1013: Argument 1: type mismatch, expected number but got bool', 'E1210: Number required for argument 1']) enddef def Test_prevnonblank() - v9.CheckDefAndScriptFailure(['prevnonblank(null)'], ['E1013: Argument 1: type mismatch, expected string but got special', 'E1220: String or Number required for argument 1']) - v9.CheckDefExecAndScriptFailure(['prevnonblank("")'], 'E1209: Invalid value for a line number') + v9.CheckSourceDefAndScriptFailure(['prevnonblank(null)'], ['E1013: Argument 1: type mismatch, expected string but got special', 'E1220: String or Number required for argument 1']) + v9.CheckSourceDefExecAndScriptFailure(['prevnonblank("")'], 'E1209: Invalid value for a line number') assert_equal(0, prevnonblank(1)) enddef def Test_printf() - v9.CheckDefAndScriptFailure(['printf([1])'], ['E1013: Argument 1: type mismatch, expected string but got list<number>', 'E1220: String or Number required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['printf([1])'], ['E1013: Argument 1: type mismatch, expected string but got list<number>', 'E1220: String or Number required for argument 1']) printf(0x10)->assert_equal('16') assert_equal(" abc", "abc"->printf("%4s")) enddef @@ -3170,7 +3170,7 @@ def Test_prompt_getprompt() if !has('channel') CheckFeature channel else - v9.CheckDefAndScriptFailure(['prompt_getprompt([])'], ['E1013: Argument 1: type mismatch, expected string but got list<any>', 'E1220: String or Number required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['prompt_getprompt([])'], ['E1013: Argument 1: type mismatch, expected string but got list<any>', 'E1220: String or Number required for argument 1']) assert_equal('', prompt_getprompt('NonExistingBuf')) endif enddef @@ -3179,7 +3179,7 @@ def Test_prompt_setcallback() if !has('channel') CheckFeature channel else - v9.CheckDefAndScriptFailure(['prompt_setcallback(true, "1")'], ['E1013: Argument 1: type mismatch, expected string but got bool', 'E1220: String or Number required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['prompt_setcallback(true, "1")'], ['E1013: Argument 1: type mismatch, expected string but got bool', 'E1220: String or Number required for argument 1']) endif enddef @@ -3187,7 +3187,7 @@ def Test_prompt_setinterrupt() if !has('channel') CheckFeature channel else - v9.CheckDefAndScriptFailure(['prompt_setinterrupt(true, "1")'], ['E1013: Argument 1: type mismatch, expected string but got bool', 'E1220: String or Number required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['prompt_setinterrupt(true, "1")'], ['E1013: Argument 1: type mismatch, expected string but got bool', 'E1220: String or Number required for argument 1']) endif enddef @@ -3195,109 +3195,109 @@ def Test_prompt_setprompt() if !has('channel') CheckFeature channel else - v9.CheckDefAndScriptFailure(['prompt_setprompt([], "p")'], ['E1013: Argument 1: type mismatch, expected string but got list<any>', 'E1220: String or Number required for argument 1']) - v9.CheckDefAndScriptFailure(['prompt_setprompt(1, [])'], ['E1013: Argument 2: type mismatch, expected string but got list<any>', 'E1174: String required for argument 2']) + v9.CheckSourceDefAndScriptFailure(['prompt_setprompt([], "p")'], ['E1013: Argument 1: type mismatch, expected string but got list<any>', 'E1220: String or Number required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['prompt_setprompt(1, [])'], ['E1013: Argument 2: type mismatch, expected string but got list<any>', 'E1174: String required for argument 2']) endif enddef def Test_prop_add() - v9.CheckDefAndScriptFailure(['prop_add("a", 2, {})'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1210: Number required for argument 1']) - v9.CheckDefAndScriptFailure(['prop_add(1, "b", {})'], ['E1013: Argument 2: type mismatch, expected number but got string', 'E1210: Number required for argument 2']) - v9.CheckDefAndScriptFailure(['prop_add(1, 2, [])'], ['E1013: Argument 3: type mismatch, expected dict<any> but got list<any>', 'E1206: Dictionary required for argument 3']) + v9.CheckSourceDefAndScriptFailure(['prop_add("a", 2, {})'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1210: Number required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['prop_add(1, "b", {})'], ['E1013: Argument 2: type mismatch, expected number but got string', 'E1210: Number required for argument 2']) + v9.CheckSourceDefAndScriptFailure(['prop_add(1, 2, [])'], ['E1013: Argument 3: type mismatch, expected dict<any> but got list<any>', 'E1206: Dictionary required for argument 3']) enddef def Test_prop_add_list() - v9.CheckDefAndScriptFailure(['prop_add_list([], [])'], ['E1013: Argument 1: type mismatch, expected dict<any> but got list<any>', 'E1206: Dictionary required for argument 1']) - v9.CheckDefAndScriptFailure(['prop_add_list({}, {})'], ['E1013: Argument 2: type mismatch, expected list<any> but got dict<any>', 'E1211: List required for argument 2']) + v9.CheckSourceDefAndScriptFailure(['prop_add_list([], [])'], ['E1013: Argument 1: type mismatch, expected dict<any> but got list<any>', 'E1206: Dictionary required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['prop_add_list({}, {})'], ['E1013: Argument 2: type mismatch, expected list<any> but got dict<any>', 'E1211: List required for argument 2']) enddef def Test_prop_clear() - v9.CheckDefAndScriptFailure(['prop_clear("a")'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1210: Number required for argument 1']) - v9.CheckDefAndScriptFailure(['prop_clear(1, "b")'], ['E1013: Argument 2: type mismatch, expected number but got string', 'E1210: Number required for argument 2']) - v9.CheckDefAndScriptFailure(['prop_clear(1, 2, [])'], ['E1013: Argument 3: type mismatch, expected dict<any> but got list<any>', 'E1206: Dictionary required for argument 3']) + v9.CheckSourceDefAndScriptFailure(['prop_clear("a")'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1210: Number required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['prop_clear(1, "b")'], ['E1013: Argument 2: type mismatch, expected number but got string', 'E1210: Number required for argument 2']) + v9.CheckSourceDefAndScriptFailure(['prop_clear(1, 2, [])'], ['E1013: Argument 3: type mismatch, expected dict<any> but got list<any>', 'E1206: Dictionary required for argument 3']) enddef def Test_prop_find() - v9.CheckDefAndScriptFailure(['prop_find([1, 2])'], ['E1013: Argument 1: type mismatch, expected dict<any> but got list<number>', 'E1206: Dictionary required for argument 1']) - v9.CheckDefAndScriptFailure(['prop_find([1, 2], "k")'], ['E1013: Argument 1: type mismatch, expected dict<any> but got list<number>', 'E1206: Dictionary required for argument 1']) - v9.CheckDefAndScriptFailure(['prop_find({"a": 10}, ["a"])'], ['E1013: Argument 2: type mismatch, expected string but got list<string>', 'E1174: String required for argument 2']) + v9.CheckSourceDefAndScriptFailure(['prop_find([1, 2])'], ['E1013: Argument 1: type mismatch, expected dict<any> but got list<number>', 'E1206: Dictionary required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['prop_find([1, 2], "k")'], ['E1013: Argument 1: type mismatch, expected dict<any> but got list<number>', 'E1206: Dictionary required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['prop_find({"a": 10}, ["a"])'], ['E1013: Argument 2: type mismatch, expected string but got list<string>', 'E1174: String required for argument 2']) assert_fails("prop_find({}, '')", 'E474:') enddef def Test_prop_list() - v9.CheckDefAndScriptFailure(['prop_list("x")'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1210: Number required for argument 1']) - v9.CheckDefAndScriptFailure(['prop_list(1, [])'], ['E1013: Argument 2: type mismatch, expected dict<any> but got list<any>', 'E1206: Dictionary required for argument 2']) + v9.CheckSourceDefAndScriptFailure(['prop_list("x")'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1210: Number required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['prop_list(1, [])'], ['E1013: Argument 2: type mismatch, expected dict<any> but got list<any>', 'E1206: Dictionary required for argument 2']) enddef def Test_prop_remove() - v9.CheckDefAndScriptFailure(['prop_remove([])'], ['E1013: Argument 1: type mismatch, expected dict<any> but got list<any>', 'E1206: Dictionary required for argument 1']) - v9.CheckDefAndScriptFailure(['prop_remove({}, "a")'], ['E1013: Argument 2: type mismatch, expected number but got string', 'E1210: Number required for argument 2']) - v9.CheckDefAndScriptFailure(['prop_remove({}, 1, "b")'], ['E1013: Argument 3: type mismatch, expected number but got string', 'E1210: Number required for argument 3']) + v9.CheckSourceDefAndScriptFailure(['prop_remove([])'], ['E1013: Argument 1: type mismatch, expected dict<any> but got list<any>', 'E1206: Dictionary required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['prop_remove({}, "a")'], ['E1013: Argument 2: type mismatch, expected number but got string', 'E1210: Number required for argument 2']) + v9.CheckSourceDefAndScriptFailure(['prop_remove({}, 1, "b")'], ['E1013: Argument 3: type mismatch, expected number but got string', 'E1210: Number required for argument 3']) enddef def Test_prop_type_add() - v9.CheckDefAndScriptFailure(['prop_type_add({"a": 10}, "b")'], ['E1013: Argument 1: type mismatch, expected string but got dict<number>', 'E1174: String required for argument 1']) - v9.CheckDefAndScriptFailure(['prop_type_add("a", "b")'], ['E1013: Argument 2: type mismatch, expected dict<any> but got string', 'E1206: Dictionary required for argument 2']) + v9.CheckSourceDefAndScriptFailure(['prop_type_add({"a": 10}, "b")'], ['E1013: Argument 1: type mismatch, expected string but got dict<number>', 'E1174: String required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['prop_type_add("a", "b")'], ['E1013: Argument 2: type mismatch, expected dict<any> but got string', 'E1206: Dictionary required for argument 2']) assert_fails("prop_type_add('', {highlight: 'Search'})", 'E475:') enddef def Test_prop_type_change() - v9.CheckDefAndScriptFailure(['prop_type_change({"a": 10}, "b")'], ['E1013: Argument 1: type mismatch, expected string but got dict<number>', 'E1174: String required for argument 1']) - v9.CheckDefAndScriptFailure(['prop_type_change("a", "b")'], ['E1013: Argument 2: type mismatch, expected dict<any> but got string', 'E1206: Dictionary required for argument 2']) + v9.CheckSourceDefAndScriptFailure(['prop_type_change({"a": 10}, "b")'], ['E1013: Argument 1: type mismatch, expected string but got dict<number>', 'E1174: String required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['prop_type_change("a", "b")'], ['E1013: Argument 2: type mismatch, expected dict<any> but got string', 'E1206: Dictionary required for argument 2']) assert_fails("prop_type_change('', {highlight: 'Search'})", 'E475:') enddef def Test_prop_type_delete() - v9.CheckDefAndScriptFailure(['prop_type_delete({"a": 10})'], ['E1013: Argument 1: type mismatch, expected string but got dict<number>', 'E1174: String required for argument 1']) - v9.CheckDefAndScriptFailure(['prop_type_delete({"a": 10}, "b")'], ['E1013: Argument 1: type mismatch, expected string but got dict<number>', 'E1174: String required for argument 1']) - v9.CheckDefAndScriptFailure(['prop_type_delete("a", "b")'], ['E1013: Argument 2: type mismatch, expected dict<any> but got string', 'E1206: Dictionary required for argument 2']) + v9.CheckSourceDefAndScriptFailure(['prop_type_delete({"a": 10})'], ['E1013: Argument 1: type mismatch, expected string but got dict<number>', 'E1174: String required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['prop_type_delete({"a": 10}, "b")'], ['E1013: Argument 1: type mismatch, expected string but got dict<number>', 'E1174: String required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['prop_type_delete("a", "b")'], ['E1013: Argument 2: type mismatch, expected dict<any> but got string', 'E1206: Dictionary required for argument 2']) assert_fails("prop_type_delete('')", 'E475:') enddef def Test_prop_type_get() - v9.CheckDefAndScriptFailure(['prop_type_get({"a": 10})'], ['E1013: Argument 1: type mismatch, expected string but got dict<number>', 'E1174: String required for argument 1']) - v9.CheckDefAndScriptFailure(['prop_type_get({"a": 10}, "b")'], ['E1013: Argument 1: type mismatch, expected string but got dict<number>', 'E1174: String required for argument 1']) - v9.CheckDefAndScriptFailure(['prop_type_get("a", "b")'], ['E1013: Argument 2: type mismatch, expected dict<any> but got string', 'E1206: Dictionary required for argument 2']) + v9.CheckSourceDefAndScriptFailure(['prop_type_get({"a": 10})'], ['E1013: Argument 1: type mismatch, expected string but got dict<number>', 'E1174: String required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['prop_type_get({"a": 10}, "b")'], ['E1013: Argument 1: type mismatch, expected string but got dict<number>', 'E1174: String required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['prop_type_get("a", "b")'], ['E1013: Argument 2: type mismatch, expected dict<any> but got string', 'E1206: Dictionary required for argument 2']) assert_fails("prop_type_get('')", 'E475:') enddef def Test_prop_type_list() - v9.CheckDefAndScriptFailure(['prop_type_list(["a"])'], ['E1013: Argument 1: type mismatch, expected dict<any> but got list<string>', 'E1206: Dictionary required for argument 1']) - v9.CheckDefAndScriptFailure(['prop_type_list(2)'], ['E1013: Argument 1: type mismatch, expected dict<any> but got number', 'E1206: Dictionary required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['prop_type_list(["a"])'], ['E1013: Argument 1: type mismatch, expected dict<any> but got list<string>', 'E1206: Dictionary required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['prop_type_list(2)'], ['E1013: Argument 1: type mismatch, expected dict<any> but got number', 'E1206: Dictionary required for argument 1']) enddef def Test_py3eval() if !has('python3') CheckFeature python3 endif - v9.CheckDefAndScriptFailure(['py3eval([2])'], ['E1013: Argument 1: type mismatch, expected string but got list<number>', 'E1174: String required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['py3eval([2])'], ['E1013: Argument 1: type mismatch, expected string but got list<number>', 'E1174: String required for argument 1']) enddef def Test_pyeval() if !has('python') CheckFeature python endif - v9.CheckDefAndScriptFailure(['pyeval([2])'], ['E1013: Argument 1: type mismatch, expected string but got list<number>', 'E1174: String required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['pyeval([2])'], ['E1013: Argument 1: type mismatch, expected string but got list<number>', 'E1174: String required for argument 1']) enddef def Test_pyxeval() if !has('python') && !has('python3') CheckFeature python endif - v9.CheckDefAndScriptFailure(['pyxeval([2])'], ['E1013: Argument 1: type mismatch, expected string but got list<number>', 'E1174: String required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['pyxeval([2])'], ['E1013: Argument 1: type mismatch, expected string but got list<number>', 'E1174: String required for argument 1']) enddef def Test_rand() - v9.CheckDefAndScriptFailure(['rand(10)'], ['E1013: Argument 1: type mismatch, expected list<number> but got number', 'E1211: List required for argument 1']) - v9.CheckDefFailure(['rand(["a"])'], 'E1013: Argument 1: type mismatch, expected list<number> but got list<string>') + v9.CheckSourceDefAndScriptFailure(['rand(10)'], ['E1013: Argument 1: type mismatch, expected list<number> but got number', 'E1211: List required for argument 1']) + v9.CheckSourceDefFailure(['rand(["a"])'], 'E1013: Argument 1: type mismatch, expected list<number> but got list<string>') assert_true(rand() >= 0) assert_true(rand(srand()) >= 0) enddef def Test_range() - v9.CheckDefAndScriptFailure(['range("a")'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1210: Number required for argument 1']) - v9.CheckDefAndScriptFailure(['range(10, "b")'], ['E1013: Argument 2: type mismatch, expected number but got string', 'E1210: Number required for argument 2']) - v9.CheckDefAndScriptFailure(['range(10, 20, "c")'], ['E1013: Argument 3: type mismatch, expected number but got string', 'E1210: Number required for argument 3']) + v9.CheckSourceDefAndScriptFailure(['range("a")'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1210: Number required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['range(10, "b")'], ['E1013: Argument 2: type mismatch, expected number but got string', 'E1210: Number required for argument 2']) + v9.CheckSourceDefAndScriptFailure(['range(10, 20, "c")'], ['E1013: Argument 3: type mismatch, expected number but got string', 'E1210: Number required for argument 3']) # returns a list<number> but it's not declared as such assert_equal(['x', 'x'], range(2)->map((i, v) => 'x')) @@ -3306,8 +3306,8 @@ enddef def Test_readdir() eval expand('sautest')->readdir((e) => e[0] !=# '.') eval expand('sautest')->readdirex((e) => e.name[0] !=# '.') - v9.CheckDefAndScriptFailure(['readdir(["a"])'], ['E1013: Argument 1: type mismatch, expected string but got list<string>', 'E1174: String required for argument 1']) - v9.CheckDefAndScriptFailure(['readdir("a", "1", [3])'], ['E1013: Argument 3: type mismatch, expected dict<any> but got list<number>', 'E1206: Dictionary required for argument 3']) + v9.CheckSourceDefAndScriptFailure(['readdir(["a"])'], ['E1013: Argument 1: type mismatch, expected string but got list<string>', 'E1174: String required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['readdir("a", "1", [3])'], ['E1013: Argument 3: type mismatch, expected dict<any> but got list<number>', 'E1206: Dictionary required for argument 3']) if has('unix') # only fails on Unix-like systems assert_fails('readdir("")', 'E484: Can''t open file') @@ -3315,8 +3315,8 @@ def Test_readdir() enddef def Test_readdirex() - v9.CheckDefAndScriptFailure(['readdirex(["a"])'], ['E1013: Argument 1: type mismatch, expected string but got list<string>', 'E1174: String required for argument 1']) - v9.CheckDefAndScriptFailure(['readdirex("a", "1", [3])'], ['E1013: Argument 3: type mismatch, expected dict<any> but got list<number>', 'E1206: Dictionary required for argument 3']) + v9.CheckSourceDefAndScriptFailure(['readdirex(["a"])'], ['E1013: Argument 1: type mismatch, expected string but got list<string>', 'E1174: String required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['readdirex("a", "1", [3])'], ['E1013: Argument 3: type mismatch, expected dict<any> but got list<number>', 'E1206: Dictionary required for argument 3']) if has('unix') # only fails on Unix-like systems assert_fails('readdirex("")', 'E484: Can''t open file') @@ -3332,8 +3332,8 @@ def Test_readblob() var lines =<< trim END var read: list<string> = readblob('Xreadblob') END - v9.CheckDefAndScriptFailure(lines, 'E1012: Type mismatch; expected list<string> but got blob', 1) - v9.CheckDefExecAndScriptFailure(['readblob("")'], 'E484: Can''t open file <empty>') + v9.CheckSourceDefAndScriptFailure(lines, 'E1012: Type mismatch; expected list<string> but got blob', 1) + v9.CheckSourceDefExecAndScriptFailure(['readblob("")'], 'E484: Can''t open file <empty>') enddef def Test_readfile() @@ -3346,15 +3346,15 @@ def Test_readfile() var lines =<< trim END var read: dict<string> = readfile('Xreadfile') END - v9.CheckDefAndScriptFailure(lines, 'E1012: Type mismatch; expected dict<string> but got list<string>', 1) + v9.CheckSourceDefAndScriptFailure(lines, 'E1012: Type mismatch; expected dict<string> but got list<string>', 1) - v9.CheckDefAndScriptFailure(['readfile("a", 0z10)'], ['E1013: Argument 2: type mismatch, expected string but got blob', 'E1174: String required for argument 2']) - v9.CheckDefAndScriptFailure(['readfile("a", "b", "c")'], ['E1013: Argument 3: type mismatch, expected number but got string', 'E1210: Number required for argument 3']) - v9.CheckDefExecAndScriptFailure(['readfile("")'], 'E1175: Non-empty string required for argument 1') + v9.CheckSourceDefAndScriptFailure(['readfile("a", 0z10)'], ['E1013: Argument 2: type mismatch, expected string but got blob', 'E1174: String required for argument 2']) + v9.CheckSourceDefAndScriptFailure(['readfile("a", "b", "c")'], ['E1013: Argument 3: type mismatch, expected number but got string', 'E1210: Number required for argument 3']) + v9.CheckSourceDefExecAndScriptFailure(['readfile("")'], 'E1175: Non-empty string required for argument 1') enddef def Test_reduce() - v9.CheckDefAndScriptFailure(['reduce({a: 10}, "1")'], ['E1013: Argument 1: type mismatch, expected list<any> but got dict<number>', 'E1252: String, List or Blob required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['reduce({a: 10}, "1")'], ['E1013: Argument 1: type mismatch, expected list<any> but got dict<number>', 'E1252: String, List or Blob required for argument 1']) assert_equal(6, [1, 2, 3]->reduce((r, c) => r + c, 0)) assert_equal(11, 0z0506->reduce((r, c) => r + c, 0)) enddef @@ -3362,13 +3362,13 @@ enddef def Test_reltime() CheckFeature reltime - v9.CheckDefExecAndScriptFailure(['[]->reltime()'], 'E474:') - v9.CheckDefExecAndScriptFailure(['[]->reltime([])'], 'E474:') + v9.CheckSourceDefExecAndScriptFailure(['[]->reltime()'], 'E474:') + v9.CheckSourceDefExecAndScriptFailure(['[]->reltime([])'], 'E474:') - v9.CheckDefAndScriptFailure(['reltime("x")'], ['E1013: Argument 1: type mismatch, expected list<number> but got string', 'E1211: List required for argument 1']) - v9.CheckDefFailure(['reltime(["x", "y"])'], 'E1013: Argument 1: type mismatch, expected list<number> but got list<string>') - v9.CheckDefAndScriptFailure(['reltime([1, 2], 10)'], ['E1013: Argument 2: type mismatch, expected list<number> but got number', 'E1211: List required for argument 2']) - v9.CheckDefFailure(['reltime([1, 2], ["a", "b"])'], 'E1013: Argument 2: type mismatch, expected list<number> but got list<string>') + v9.CheckSourceDefAndScriptFailure(['reltime("x")'], ['E1013: Argument 1: type mismatch, expected list<number> but got string', 'E1211: List required for argument 1']) + v9.CheckSourceDefFailure(['reltime(["x", "y"])'], 'E1013: Argument 1: type mismatch, expected list<number> but got list<string>') + v9.CheckSourceDefAndScriptFailure(['reltime([1, 2], 10)'], ['E1013: Argument 2: type mismatch, expected list<number> but got number', 'E1211: List required for argument 2']) + v9.CheckSourceDefFailure(['reltime([1, 2], ["a", "b"])'], 'E1013: Argument 2: type mismatch, expected list<number> but got list<string>') var start: list<any> = reltime() assert_true(type(reltime(start)) == v:t_list) var end: list<any> = reltime() @@ -3378,31 +3378,31 @@ enddef def Test_reltimefloat() CheckFeature reltime - v9.CheckDefExecAndScriptFailure(['[]->reltimefloat()'], 'E474:') + v9.CheckSourceDefExecAndScriptFailure(['[]->reltimefloat()'], 'E474:') - v9.CheckDefAndScriptFailure(['reltimefloat("x")'], ['E1013: Argument 1: type mismatch, expected list<number> but got string', 'E1211: List required for argument 1']) - v9.CheckDefFailure(['reltimefloat([1.1])'], 'E1013: Argument 1: type mismatch, expected list<number> but got list<float>') + v9.CheckSourceDefAndScriptFailure(['reltimefloat("x")'], ['E1013: Argument 1: type mismatch, expected list<number> but got string', 'E1211: List required for argument 1']) + v9.CheckSourceDefFailure(['reltimefloat([1.1])'], 'E1013: Argument 1: type mismatch, expected list<number> but got list<float>') assert_true(type(reltimefloat(reltime())) == v:t_float) enddef def Test_reltimestr() CheckFeature reltime - v9.CheckDefExecAndScriptFailure(['[]->reltimestr()'], 'E474:') + v9.CheckSourceDefExecAndScriptFailure(['[]->reltimestr()'], 'E474:') - v9.CheckDefAndScriptFailure(['reltimestr(true)'], ['E1013: Argument 1: type mismatch, expected list<number> but got bool', 'E1211: List required for argument 1']) - v9.CheckDefFailure(['reltimestr([true])'], 'E1013: Argument 1: type mismatch, expected list<number> but got list<bool>') + v9.CheckSourceDefAndScriptFailure(['reltimestr(true)'], ['E1013: Argument 1: type mismatch, expected list<number> but got bool', 'E1211: List required for argument 1']) + v9.CheckSourceDefFailure(['reltimestr([true])'], 'E1013: Argument 1: type mismatch, expected list<number> but got list<bool>') assert_true(type(reltimestr(reltime())) == v:t_string) enddef def Test_remote_expr() CheckFeature clientserver CheckEnv DISPLAY - v9.CheckDefAndScriptFailure(['remote_expr(1, "b")'], ['E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1']) - v9.CheckDefAndScriptFailure(['remote_expr("a", 2)'], ['E1013: Argument 2: type mismatch, expected string but got number', 'E1174: String required for argument 2']) - v9.CheckDefAndScriptFailure(['remote_expr("a", "b", 3)'], ['E1013: Argument 3: type mismatch, expected string but got number', 'E1174: String required for argument 3']) - v9.CheckDefAndScriptFailure(['remote_expr("a", "b", "c", "d")'], ['E1013: Argument 4: type mismatch, expected number but got string', 'E1210: Number required for argument 4']) - v9.CheckDefExecAndScriptFailure(['remote_expr("", "")'], 'E241: Unable to send to ') + v9.CheckSourceDefAndScriptFailure(['remote_expr(1, "b")'], ['E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['remote_expr("a", 2)'], ['E1013: Argument 2: type mismatch, expected string but got number', 'E1174: String required for argument 2']) + v9.CheckSourceDefAndScriptFailure(['remote_expr("a", "b", 3)'], ['E1013: Argument 3: type mismatch, expected string but got number', 'E1174: String required for argument 3']) + v9.CheckSourceDefAndScriptFailure(['remote_expr("a", "b", "c", "d")'], ['E1013: Argument 4: type mismatch, expected number but got string', 'E1210: Number required for argument 4']) + v9.CheckSourceDefExecAndScriptFailure(['remote_expr("", "")'], 'E241: Unable to send to ') enddef def Test_remote_foreground() @@ -3411,7 +3411,7 @@ def Test_remote_foreground() CheckNotMSWindows CheckX11 - v9.CheckDefAndScriptFailure(['remote_foreground(10)'], ['E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['remote_foreground(10)'], ['E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1']) assert_fails('remote_foreground("NonExistingServer")', 'E241:') assert_fails('remote_foreground("")', 'E241:') enddef @@ -3419,32 +3419,32 @@ enddef def Test_remote_peek() CheckFeature clientserver CheckEnv DISPLAY - v9.CheckDefAndScriptFailure(['remote_peek(0z10)'], ['E1013: Argument 1: type mismatch, expected string but got blob', 'E1174: String required for argument 1']) - v9.CheckDefAndScriptFailure(['remote_peek("a5b6c7", [1])'], ['E1013: Argument 2: type mismatch, expected string but got list<number>', 'E1174: String required for argument 2']) - v9.CheckDefExecAndScriptFailure(['remote_peek("")'], 'E573: Invalid server id used') + v9.CheckSourceDefAndScriptFailure(['remote_peek(0z10)'], ['E1013: Argument 1: type mismatch, expected string but got blob', 'E1174: String required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['remote_peek("a5b6c7", [1])'], ['E1013: Argument 2: type mismatch, expected string but got list<number>', 'E1174: String required for argument 2']) + v9.CheckSourceDefExecAndScriptFailure(['remote_peek("")'], 'E573: Invalid server id used') enddef def Test_remote_read() CheckFeature clientserver CheckEnv DISPLAY - v9.CheckDefAndScriptFailure(['remote_read(1)'], ['E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1']) - v9.CheckDefAndScriptFailure(['remote_read("a", "x")'], ['E1013: Argument 2: type mismatch, expected number but got string', 'E1210: Number required for argument 2']) - v9.CheckDefExecAndScriptFailure(['remote_read("")'], 'E573: Invalid server id used') + v9.CheckSourceDefAndScriptFailure(['remote_read(1)'], ['E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['remote_read("a", "x")'], ['E1013: Argument 2: type mismatch, expected number but got string', 'E1210: Number required for argument 2']) + v9.CheckSourceDefExecAndScriptFailure(['remote_read("")'], 'E573: Invalid server id used') enddef def Test_remote_send() CheckFeature clientserver CheckEnv DISPLAY - v9.CheckDefAndScriptFailure(['remote_send(1, "b")'], ['E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1']) - v9.CheckDefAndScriptFailure(['remote_send("a", 2)'], ['E1013: Argument 2: type mismatch, expected string but got number', 'E1174: String required for argument 2']) - v9.CheckDefAndScriptFailure(['remote_send("a", "b", 3)'], ['E1013: Argument 3: type mismatch, expected string but got number', 'E1174: String required for argument 3']) + v9.CheckSourceDefAndScriptFailure(['remote_send(1, "b")'], ['E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['remote_send("a", 2)'], ['E1013: Argument 2: type mismatch, expected string but got number', 'E1174: String required for argument 2']) + v9.CheckSourceDefAndScriptFailure(['remote_send("a", "b", 3)'], ['E1013: Argument 3: type mismatch, expected string but got number', 'E1174: String required for argument 3']) assert_fails('remote_send("", "")', 'E241:') enddef def Test_remote_startserver() CheckFeature clientserver CheckEnv DISPLAY - v9.CheckDefAndScriptFailure(['remote_startserver({})'], ['E1013: Argument 1: type mismatch, expected string but got dict<any>', 'E1174: String required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['remote_startserver({})'], ['E1013: Argument 1: type mismatch, expected string but got dict<any>', 'E1174: String required for argument 1']) enddef def Test_remove_literal_list() @@ -3458,28 +3458,28 @@ def Test_remove_const() const l = [1, 2, 3, 4] remove(l, 1) END - v9.CheckDefFailure(lines, 'E1307: Argument 1: Trying to modify a const list<number>') + v9.CheckSourceDefFailure(lines, 'E1307: Argument 1: Trying to modify a const list<number>') lines =<< trim END const d = {a: 1, b: 2} remove(d, 'a') END - v9.CheckDefFailure(lines, 'E1307: Argument 1: Trying to modify a const dict<number>') + v9.CheckSourceDefFailure(lines, 'E1307: Argument 1: Trying to modify a const dict<number>') lines =<< trim END const b = 0z010203 remove(b, 1) END - v9.CheckDefFailure(lines, 'E1307: Argument 1: Trying to modify a const blob') + v9.CheckSourceDefFailure(lines, 'E1307: Argument 1: Trying to modify a const blob') enddef def Test_remove() - v9.CheckDefAndScriptFailure(['remove("a", 1)'], ['E1013: Argument 1: type mismatch, expected list<any> but got string', 'E1228: List, Dictionary or Blob required for argument 1']) - v9.CheckDefAndScriptFailure(['remove([], "b")'], ['E1013: Argument 2: type mismatch, expected number but got string', 'E1210: Number required for argument 2']) - v9.CheckDefAndScriptFailure(['remove([], 1, "c")'], ['E1013: Argument 3: type mismatch, expected number but got string', 'E1210: Number required for argument 3']) - v9.CheckDefAndScriptFailure(['remove({}, 1.1)'], ['E1013: Argument 2: type mismatch, expected string but got float', 'E1220: String or Number required for argument 2']) - v9.CheckDefAndScriptFailure(['remove(0z10, "b")'], ['E1013: Argument 2: type mismatch, expected number but got string', 'E1210: Number required for argument 2']) - v9.CheckDefAndScriptFailure(['remove(0z20, 1, "c")'], ['E1013: Argument 3: type mismatch, expected number but got string', 'E1210: Number required for argument 3']) + v9.CheckSourceDefAndScriptFailure(['remove("a", 1)'], ['E1013: Argument 1: type mismatch, expected list<any> but got string', 'E1228: List, Dictionary or Blob required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['remove([], "b")'], ['E1013: Argument 2: type mismatch, expected number but got string', 'E1210: Number required for argument 2']) + v9.CheckSourceDefAndScriptFailure(['remove([], 1, "c")'], ['E1013: Argument 3: type mismatch, expected number but got string', 'E1210: Number required for argument 3']) + v9.CheckSourceDefAndScriptFailure(['remove({}, 1.1)'], ['E1013: Argument 2: type mismatch, expected string but got float', 'E1220: String or Number required for argument 2']) + v9.CheckSourceDefAndScriptFailure(['remove(0z10, "b")'], ['E1013: Argument 2: type mismatch, expected number but got string', 'E1210: Number required for argument 2']) + v9.CheckSourceDefAndScriptFailure(['remove(0z20, 1, "c")'], ['E1013: Argument 3: type mismatch, expected number but got string', 'E1210: Number required for argument 3']) var l: any = [1, 2, 3, 4] remove(l, 1) assert_equal([1, 3, 4], l) @@ -3511,14 +3511,14 @@ def Test_remove_return_type() enddef def Test_rename() - v9.CheckDefAndScriptFailure(['rename(1, "b")'], ['E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1']) - v9.CheckDefAndScriptFailure(['rename("a", 2)'], ['E1013: Argument 2: type mismatch, expected string but got number', 'E1174: String required for argument 2']) + v9.CheckSourceDefAndScriptFailure(['rename(1, "b")'], ['E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['rename("a", 2)'], ['E1013: Argument 2: type mismatch, expected string but got number', 'E1174: String required for argument 2']) rename('', '')->assert_equal(0) enddef def Test_repeat() - v9.CheckDefAndScriptFailure(['repeat(1.1, 2)'], ['E1013: Argument 1: type mismatch, expected string but got float', 'E1301: String, Number, List or Blob required for argument 1']) - v9.CheckDefAndScriptFailure(['repeat({a: 10}, 2)'], ['E1013: Argument 1: type mismatch, expected string but got dict<', 'E1301: String, Number, List or Blob required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['repeat(1.1, 2)'], ['E1013: Argument 1: type mismatch, expected string but got float', 'E1301: String, Number, List or Blob required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['repeat({a: 10}, 2)'], ['E1013: Argument 1: type mismatch, expected string but got dict<', 'E1301: String, Number, List or Blob required for argument 1']) var lines =<< trim END assert_equal('aaa', repeat('a', 3)) assert_equal('111', repeat(1, 3)) @@ -3529,17 +3529,17 @@ def Test_repeat() s ..= repeat(5, 3) assert_equal('-555', s) END - v9.CheckDefAndScriptSuccess(lines) + v9.CheckSourceDefAndScriptSuccess(lines) enddef def Test_resolve() - v9.CheckDefAndScriptFailure(['resolve([])'], ['E1013: Argument 1: type mismatch, expected string but got list<any>', 'E1174: String required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['resolve([])'], ['E1013: Argument 1: type mismatch, expected string but got list<any>', 'E1174: String required for argument 1']) assert_equal('SomeFile', resolve('SomeFile')) resolve('')->assert_equal('') enddef def Test_reverse() - v9.CheckDefAndScriptFailure(['reverse(10)'], ['E1013: Argument 1: type mismatch, expected list<any> but got number', 'E1252: String, List or Blob required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['reverse(10)'], ['E1013: Argument 1: type mismatch, expected list<any> but got number', 'E1252: String, List or Blob required for argument 1']) enddef def Test_reverse_return_type() @@ -3556,49 +3556,49 @@ def Test_reverse_const() const l = [1, 2, 3, 4] reverse(l) END - v9.CheckDefFailure(lines, 'E1307: Argument 1: Trying to modify a const list<number>') + v9.CheckSourceDefFailure(lines, 'E1307: Argument 1: Trying to modify a const list<number>') lines =<< trim END const b = 0z010203 reverse(b) END - v9.CheckDefFailure(lines, 'E1307: Argument 1: Trying to modify a const blob') + v9.CheckSourceDefFailure(lines, 'E1307: Argument 1: Trying to modify a const blob') enddef def Test_rubyeval() if !has('ruby') CheckFeature ruby endif - v9.CheckDefAndScriptFailure(['rubyeval([2])'], ['E1013: Argument 1: type mismatch, expected string but got list<number>', 'E1174: String required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['rubyeval([2])'], ['E1013: Argument 1: type mismatch, expected string but got list<number>', 'E1174: String required for argument 1']) enddef def Test_screenattr() - v9.CheckDefAndScriptFailure(['screenattr("x", 1)'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1210: Number required for argument 1']) - v9.CheckDefAndScriptFailure(['screenattr(1, "x")'], ['E1013: Argument 2: type mismatch, expected number but got string', 'E1210: Number required for argument 2']) + v9.CheckSourceDefAndScriptFailure(['screenattr("x", 1)'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1210: Number required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['screenattr(1, "x")'], ['E1013: Argument 2: type mismatch, expected number but got string', 'E1210: Number required for argument 2']) enddef def Test_screenchar() - v9.CheckDefAndScriptFailure(['screenchar("x", 1)'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1210: Number required for argument 1']) - v9.CheckDefAndScriptFailure(['screenchar(1, "x")'], ['E1013: Argument 2: type mismatch, expected number but got string', 'E1210: Number required for argument 2']) + v9.CheckSourceDefAndScriptFailure(['screenchar("x", 1)'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1210: Number required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['screenchar(1, "x")'], ['E1013: Argument 2: type mismatch, expected number but got string', 'E1210: Number required for argument 2']) enddef def Test_screenchars() assert_equal(['x'], screenchars(1, 1)->map((_, _) => 'x')) - v9.CheckDefAndScriptFailure(['screenchars("x", 1)'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1210: Number required for argument 1']) - v9.CheckDefAndScriptFailure(['screenchars(1, "x")'], ['E1013: Argument 2: type mismatch, expected number but got string', 'E1210: Number required for argument 2']) + v9.CheckSourceDefAndScriptFailure(['screenchars("x", 1)'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1210: Number required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['screenchars(1, "x")'], ['E1013: Argument 2: type mismatch, expected number but got string', 'E1210: Number required for argument 2']) enddef def Test_screenpos() - v9.CheckDefAndScriptFailure(['screenpos("a", 1, 1)'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1210: Number required for argument 1']) - v9.CheckDefAndScriptFailure(['screenpos(1, "b", 1)'], ['E1013: Argument 2: type mismatch, expected number but got string', 'E1210: Number required for argument 2']) - v9.CheckDefAndScriptFailure(['screenpos(1, 1, "c")'], ['E1013: Argument 3: type mismatch, expected number but got string', 'E1210: Number required for argument 3']) + v9.CheckSourceDefAndScriptFailure(['screenpos("a", 1, 1)'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1210: Number required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['screenpos(1, "b", 1)'], ['E1013: Argument 2: type mismatch, expected number but got string', 'E1210: Number required for argument 2']) + v9.CheckSourceDefAndScriptFailure(['screenpos(1, 1, "c")'], ['E1013: Argument 3: type mismatch, expected number but got string', 'E1210: Number required for argument 3']) assert_equal({col: 1, row: 1, endcol: 1, curscol: 1}, screenpos(1, 1, 1)) enddef def Test_screenstring() - v9.CheckDefAndScriptFailure(['screenstring("x", 1)'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1210: Number required for argument 1']) - v9.CheckDefAndScriptFailure(['screenstring(1, "x")'], ['E1013: Argument 2: type mismatch, expected number but got string', 'E1210: Number required for argument 2']) + v9.CheckSourceDefAndScriptFailure(['screenstring("x", 1)'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1210: Number required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['screenstring(1, "x")'], ['E1013: Argument 2: type mismatch, expected number but got string', 'E1210: Number required for argument 2']) enddef def Test_search() @@ -3630,13 +3630,13 @@ def Test_search() normal 0 assert_equal([0, 0], searchpos('this', '', 0, 0, 'col(".") > col')) bwipe! - v9.CheckDefAndScriptFailure(['search(1)'], ['E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1']) - v9.CheckDefAndScriptFailure(['search("a", 2)'], ['E1013: Argument 2: type mismatch, expected string but got number', 'E1174: String required for argument 2']) - v9.CheckDefAndScriptFailure(['search("a", "b", "c")'], ['E1013: Argument 3: type mismatch, expected number but got string', 'E1210: Number required for argument 3']) - v9.CheckDefAndScriptFailure(['search("a", "b", 3, "d")'], ['E1013: Argument 4: type mismatch, expected number but got string', 'E1210: Number required for argument 4']) + v9.CheckSourceDefAndScriptFailure(['search(1)'], ['E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['search("a", 2)'], ['E1013: Argument 2: type mismatch, expected string but got number', 'E1174: String required for argument 2']) + v9.CheckSourceDefAndScriptFailure(['search("a", "b", "c")'], ['E1013: Argument 3: type mismatch, expected number but got string', 'E1210: Number required for argument 3']) + v9.CheckSourceDefAndScriptFailure(['search("a", "b", 3, "d")'], ['E1013: Argument 4: type mismatch, expected number but got string', 'E1210: Number required for argument 4']) new setline(1, "match this") - v9.CheckDefAndScriptFailure(['search("a", "", 9, 0, [0])'], ['E1013: Argument 5: type mismatch, expected func(...): any but got list<number>', 'E730: Using a List as a String']) + v9.CheckSourceDefAndScriptFailure(['search("a", "", 9, 0, [0])'], ['E1013: Argument 5: type mismatch, expected func(...): any but got list<number>', 'E730: Using a List as a String']) bwipe! enddef @@ -3652,14 +3652,14 @@ def Test_searchcount() maxcount: 99, incomplete: 0}) bwipe! - v9.CheckDefAndScriptFailure(['searchcount([1])'], ['E1013: Argument 1: type mismatch, expected dict<any> but got list<number>', 'E1206: Dictionary required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['searchcount([1])'], ['E1013: Argument 1: type mismatch, expected dict<any> but got list<number>', 'E1206: Dictionary required for argument 1']) enddef def Test_searchdecl() searchdecl('blah', true, true)->assert_equal(1) - v9.CheckDefAndScriptFailure(['searchdecl(1)'], ['E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1']) - v9.CheckDefAndScriptFailure(['searchdecl("a", 2)'], ['E1013: Argument 2: type mismatch, expected bool but got number', 'E1212: Bool required for argument 2']) - v9.CheckDefAndScriptFailure(['searchdecl("a", true, 2)'], ['E1013: Argument 3: type mismatch, expected bool but got number', 'E1212: Bool required for argument 3']) + v9.CheckSourceDefAndScriptFailure(['searchdecl(1)'], ['E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['searchdecl("a", 2)'], ['E1013: Argument 2: type mismatch, expected bool but got number', 'E1212: Bool required for argument 2']) + v9.CheckSourceDefAndScriptFailure(['searchdecl("a", true, 2)'], ['E1013: Argument 3: type mismatch, expected bool but got number', 'E1212: Bool required for argument 3']) # search for an empty string declaration var lines: list<string> =<< trim END @@ -3719,7 +3719,7 @@ def Test_searchpair() enddef Fail() END - v9.CheckScriptSuccess(lines) + v9.CheckSourceScriptSuccess(lines) assert_equal('yes', g:caught) unlet g:caught bwipe! @@ -3727,64 +3727,64 @@ def Test_searchpair() lines =<< trim END echo searchpair("a", "b", "c", "d", "f", 33) END - v9.CheckDefAndScriptFailure(lines, ['E1001: Variable not found: f', 'E475: Invalid argument: d']) + v9.CheckSourceDefAndScriptFailure(lines, ['E1001: Variable not found: f', 'E475: Invalid argument: d']) var errors = ['E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1'] - v9.CheckDefAndScriptFailure(['searchpair(1, "b", "c")'], errors) - v9.CheckDefAndScriptFailure(['searchpairpos(1, "b", "c")'], errors) + v9.CheckSourceDefAndScriptFailure(['searchpair(1, "b", "c")'], errors) + v9.CheckSourceDefAndScriptFailure(['searchpairpos(1, "b", "c")'], errors) errors = ['E1013: Argument 2: type mismatch, expected string but got number', 'E1174: String required for argument 2'] - v9.CheckDefAndScriptFailure(['searchpair("a", 2, "c")'], errors) - v9.CheckDefAndScriptFailure(['searchpairpos("a", 2, "c")'], errors) + v9.CheckSourceDefAndScriptFailure(['searchpair("a", 2, "c")'], errors) + v9.CheckSourceDefAndScriptFailure(['searchpairpos("a", 2, "c")'], errors) errors = ['E1013: Argument 3: type mismatch, expected string but got number', 'E1174: String required for argument 3'] - v9.CheckDefAndScriptFailure(['searchpair("a", "b", 3)'], errors) - v9.CheckDefAndScriptFailure(['searchpairpos("a", "b", 3)'], errors) + v9.CheckSourceDefAndScriptFailure(['searchpair("a", "b", 3)'], errors) + v9.CheckSourceDefAndScriptFailure(['searchpairpos("a", "b", 3)'], errors) errors = ['E1013: Argument 4: type mismatch, expected string but got number', 'E1174: String required for argument 4'] - v9.CheckDefAndScriptFailure(['searchpair("a", "b", "c", 4)'], errors) + v9.CheckSourceDefAndScriptFailure(['searchpair("a", "b", "c", 4)'], errors) new setline(1, "match this") errors = ['E1013: Argument 5: type mismatch, expected func(...): any but got list<number>', 'E730: Using a List as a String'] - v9.CheckDefAndScriptFailure(['searchpair("a", "b", "c", "r", [0])'], errors) - v9.CheckDefAndScriptFailure(['searchpairpos("a", "b", "c", "r", [0])'], errors) + v9.CheckSourceDefAndScriptFailure(['searchpair("a", "b", "c", "r", [0])'], errors) + v9.CheckSourceDefAndScriptFailure(['searchpairpos("a", "b", "c", "r", [0])'], errors) bwipe! errors = ['E1013: Argument 6: type mismatch, expected number but got string', 'E1210: Number required for argument 6'] - v9.CheckDefAndScriptFailure(['searchpair("a", "b", "c", "r", "1", "f")'], errors) - v9.CheckDefAndScriptFailure(['searchpairpos("a", "b", "c", "r", "1", "f")'], errors) + v9.CheckSourceDefAndScriptFailure(['searchpair("a", "b", "c", "r", "1", "f")'], errors) + v9.CheckSourceDefAndScriptFailure(['searchpairpos("a", "b", "c", "r", "1", "f")'], errors) errors = ['E1013: Argument 7: type mismatch, expected number but got string', 'E1210: Number required for argument 7'] - v9.CheckDefAndScriptFailure(['searchpair("a", "b", "c", "r", "1", 3, "g")'], errors) - v9.CheckDefAndScriptFailure(['searchpairpos("a", "b", "c", "r", "1", 3, "g")'], errors) + v9.CheckSourceDefAndScriptFailure(['searchpair("a", "b", "c", "r", "1", 3, "g")'], errors) + v9.CheckSourceDefAndScriptFailure(['searchpairpos("a", "b", "c", "r", "1", 3, "g")'], errors) enddef def Test_searchpos() assert_equal(['x', 'x'], searchpos('.')->map((_, _) => 'x')) - v9.CheckDefAndScriptFailure(['searchpos(1)'], ['E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1']) - v9.CheckDefAndScriptFailure(['searchpos("a", 2)'], ['E1013: Argument 2: type mismatch, expected string but got number', 'E1174: String required for argument 2']) - v9.CheckDefAndScriptFailure(['searchpos("a", "b", "c")'], ['E1013: Argument 3: type mismatch, expected number but got string', 'E1210: Number required for argument 3']) - v9.CheckDefAndScriptFailure(['searchpos("a", "b", 3, "d")'], ['E1013: Argument 4: type mismatch, expected number but got string', 'E1210: Number required for argument 4']) + v9.CheckSourceDefAndScriptFailure(['searchpos(1)'], ['E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['searchpos("a", 2)'], ['E1013: Argument 2: type mismatch, expected string but got number', 'E1174: String required for argument 2']) + v9.CheckSourceDefAndScriptFailure(['searchpos("a", "b", "c")'], ['E1013: Argument 3: type mismatch, expected number but got string', 'E1210: Number required for argument 3']) + v9.CheckSourceDefAndScriptFailure(['searchpos("a", "b", 3, "d")'], ['E1013: Argument 4: type mismatch, expected number but got string', 'E1210: Number required for argument 4']) new setline(1, "match this") - v9.CheckDefAndScriptFailure(['searchpos("a", "", 9, 0, [0])'], ['E1013: Argument 5: type mismatch, expected func(...): any but got list<number>', 'E730: Using a List as a String']) + v9.CheckSourceDefAndScriptFailure(['searchpos("a", "", 9, 0, [0])'], ['E1013: Argument 5: type mismatch, expected func(...): any but got list<number>', 'E730: Using a List as a String']) bwipe! enddef def Test_server2client() CheckFeature clientserver CheckEnv DISPLAY - v9.CheckDefAndScriptFailure(['server2client(10, "b")'], ['E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1']) - v9.CheckDefAndScriptFailure(['server2client("a", 10)'], ['E1013: Argument 2: type mismatch, expected string but got number', 'E1174: String required for argument 2']) - v9.CheckDefExecAndScriptFailure(['server2client("", "a")'], 'E573: Invalid server id used') - v9.CheckDefExecAndScriptFailure(['server2client("", "")'], 'E573: Invalid server id used') + v9.CheckSourceDefAndScriptFailure(['server2client(10, "b")'], ['E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['server2client("a", 10)'], ['E1013: Argument 2: type mismatch, expected string but got number', 'E1174: String required for argument 2']) + v9.CheckSourceDefExecAndScriptFailure(['server2client("", "a")'], 'E573: Invalid server id used') + v9.CheckSourceDefExecAndScriptFailure(['server2client("", "")'], 'E573: Invalid server id used') enddef def Test_shellescape() - v9.CheckDefAndScriptFailure(['shellescape(1)'], ['E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1']) - v9.CheckDefAndScriptFailure(['shellescape("a", 2)'], ['E1013: Argument 2: type mismatch, expected bool but got number', 'E1212: Bool required for argument 2']) + v9.CheckSourceDefAndScriptFailure(['shellescape(1)'], ['E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['shellescape("a", 2)'], ['E1013: Argument 2: type mismatch, expected bool but got number', 'E1212: Bool required for argument 2']) if has('unix') assert_equal("''", shellescape('')) endif @@ -3837,7 +3837,7 @@ def Test_set_get_bufline() exe 'bwipe! ' .. b END - v9.CheckDefAndScriptSuccess(lines) + v9.CheckSourceDefAndScriptSuccess(lines) enddef def Test_setbufvar() @@ -3864,8 +3864,8 @@ def Test_setbufvar() setbufvar('%', 'myvar', 123) getbufvar('%', 'myvar')->assert_equal(123) - v9.CheckDefAndScriptFailure(['setbufvar(true, "v", 3)'], ['E1013: Argument 1: type mismatch, expected string but got bool', 'E1220: String or Number required for argument 1']) - v9.CheckDefAndScriptFailure(['setbufvar(1, 2, 3)'], ['E1013: Argument 2: type mismatch, expected string but got number', 'E1174: String required for argument 2']) + v9.CheckSourceDefAndScriptFailure(['setbufvar(true, "v", 3)'], ['E1013: Argument 1: type mismatch, expected string but got bool', 'E1220: String or Number required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['setbufvar(1, 2, 3)'], ['E1013: Argument 2: type mismatch, expected string but got number', 'E1174: String required for argument 2']) assert_fails('setbufvar("%", "", 10)', 'E461: Illegal variable name') enddef @@ -3878,10 +3878,10 @@ def Test_setbufline() setbufline(bnum, 5, 10) setbufline(bnum, 6, ['two', 11]) assert_equal(['1', '2', '3', 'one', '10', 'two', '11'], getbufline(bnum, 1, '$')) - v9.CheckDefAndScriptFailure(['setbufline([1], 1, "x")'], ['E1013: Argument 1: type mismatch, expected string but got list<number>', 'E1220: String or Number required for argument 1']) - v9.CheckDefAndScriptFailure(['setbufline(1, [1], "x")'], ['E1013: Argument 2: type mismatch, expected string but got list<number>', 'E1220: String or Number required for argument 2']) - v9.CheckDefExecAndScriptFailure(['setbufline(' .. bnum .. ', -1, "x")'], 'E966: Invalid line number: -1') - v9.CheckDefAndScriptFailure(['setbufline(1, 1, {"a": 10})'], ['E1013: Argument 3: type mismatch, expected string but got dict<number>', 'E1224: String, Number or List required for argument 3']) + v9.CheckSourceDefAndScriptFailure(['setbufline([1], 1, "x")'], ['E1013: Argument 1: type mismatch, expected string but got list<number>', 'E1220: String or Number required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['setbufline(1, [1], "x")'], ['E1013: Argument 2: type mismatch, expected string but got list<number>', 'E1220: String or Number required for argument 2']) + v9.CheckSourceDefExecAndScriptFailure(['setbufline(' .. bnum .. ', -1, "x")'], 'E966: Invalid line number: -1') + v9.CheckSourceDefAndScriptFailure(['setbufline(1, 1, {"a": 10})'], ['E1013: Argument 3: type mismatch, expected string but got dict<number>', 'E1224: String, Number or List required for argument 3']) bnum->bufwinid()->win_gotoid() setbufline('', 1, 'nombres') getline(1)->assert_equal('nombres') @@ -3889,53 +3889,53 @@ def Test_setbufline() enddef def Test_setcellwidths() - v9.CheckDefAndScriptFailure(['setcellwidths(1)'], ['E1013: Argument 1: type mismatch, expected list<any> but got number', 'E1211: List required for argument 1']) - v9.CheckDefAndScriptFailure(['setcellwidths({"a": 10})'], ['E1013: Argument 1: type mismatch, expected list<any> but got dict<number>', 'E1211: List required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['setcellwidths(1)'], ['E1013: Argument 1: type mismatch, expected list<any> but got number', 'E1211: List required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['setcellwidths({"a": 10})'], ['E1013: Argument 1: type mismatch, expected list<any> but got dict<number>', 'E1211: List required for argument 1']) enddef def Test_setcharpos() - v9.CheckDefAndScriptFailure(['setcharpos(1, [])'], ['E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1']) - v9.CheckDefFailure(['setcharpos(".", ["a"])'], 'E1013: Argument 2: type mismatch, expected list<number> but got list<string>') - v9.CheckDefAndScriptFailure(['setcharpos(".", 1)'], ['E1013: Argument 2: type mismatch, expected list<number> but got number', 'E1211: List required for argument 2']) - v9.CheckDefExecAndScriptFailure(['setcharpos("", [0, 1, 1, 1])'], 'E474: Invalid argument') + v9.CheckSourceDefAndScriptFailure(['setcharpos(1, [])'], ['E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1']) + v9.CheckSourceDefFailure(['setcharpos(".", ["a"])'], 'E1013: Argument 2: type mismatch, expected list<number> but got list<string>') + v9.CheckSourceDefAndScriptFailure(['setcharpos(".", 1)'], ['E1013: Argument 2: type mismatch, expected list<number> but got number', 'E1211: List required for argument 2']) + v9.CheckSourceDefExecAndScriptFailure(['setcharpos("", [0, 1, 1, 1])'], 'E474: Invalid argument') enddef def Test_setcharsearch() - v9.CheckDefAndScriptFailure(['setcharsearch("x")'], ['E1013: Argument 1: type mismatch, expected dict<any> but got string', 'E1206: Dictionary required for argument 1']) - v9.CheckDefAndScriptFailure(['setcharsearch([])'], ['E1013: Argument 1: type mismatch, expected dict<any> but got list<any>', 'E1206: Dictionary required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['setcharsearch("x")'], ['E1013: Argument 1: type mismatch, expected dict<any> but got string', 'E1206: Dictionary required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['setcharsearch([])'], ['E1013: Argument 1: type mismatch, expected dict<any> but got list<any>', 'E1206: Dictionary required for argument 1']) var d: dict<any> = {char: 'x', forward: 1, until: 1} setcharsearch(d) assert_equal(d, getcharsearch()) enddef def Test_setcmdline() - v9.CheckDefAndScriptSuccess(['setcmdline("ls", 2)']) - v9.CheckDefAndScriptFailure(['setcmdline(123)'], ['E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1']) - v9.CheckDefAndScriptFailure(['setcmdline("ls", "x")'], ['E1013: Argument 2: type mismatch, expected number but got string', 'E1210: Number required for argument 2']) + v9.CheckSourceDefAndScriptSuccess(['setcmdline("ls", 2)']) + v9.CheckSourceDefAndScriptFailure(['setcmdline(123)'], ['E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['setcmdline("ls", "x")'], ['E1013: Argument 2: type mismatch, expected number but got string', 'E1210: Number required for argument 2']) enddef def Test_setcmdpos() - v9.CheckDefAndScriptFailure(['setcmdpos("x")'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1210: Number required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['setcmdpos("x")'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1210: Number required for argument 1']) enddef def Test_setcursorcharpos() - v9.CheckDefAndScriptFailure(['setcursorcharpos(0z10, 1)'], ['E1013: Argument 1: type mismatch, expected number but got blob', 'E1224: String, Number or List required for argument 1']) - v9.CheckDefAndScriptFailure(['setcursorcharpos(1, "2")'], ['E1013: Argument 2: type mismatch, expected number but got string', 'E1210: Number required for argument 2']) - v9.CheckDefAndScriptFailure(['setcursorcharpos(1, 2, "3")'], ['E1013: Argument 3: type mismatch, expected number but got string', 'E1210: Number required for argument 3']) - v9.CheckDefExecAndScriptFailure(['setcursorcharpos("", 10)'], 'E1209: Invalid value for a line number') + v9.CheckSourceDefAndScriptFailure(['setcursorcharpos(0z10, 1)'], ['E1013: Argument 1: type mismatch, expected number but got blob', 'E1224: String, Number or List required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['setcursorcharpos(1, "2")'], ['E1013: Argument 2: type mismatch, expected number but got string', 'E1210: Number required for argument 2']) + v9.CheckSourceDefAndScriptFailure(['setcursorcharpos(1, 2, "3")'], ['E1013: Argument 3: type mismatch, expected number but got string', 'E1210: Number required for argument 3']) + v9.CheckSourceDefExecAndScriptFailure(['setcursorcharpos("", 10)'], 'E1209: Invalid value for a line number') enddef def Test_setenv() - v9.CheckDefAndScriptFailure(['setenv(1, 2)'], ['E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['setenv(1, 2)'], ['E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1']) assert_equal(0, setenv('', '')) assert_equal(0, setenv('', v:null)) enddef def Test_setfperm() - v9.CheckDefAndScriptFailure(['setfperm(1, "b")'], ['E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1']) - v9.CheckDefAndScriptFailure(['setfperm("a", 0z10)'], ['E1013: Argument 2: type mismatch, expected string but got blob', 'E1174: String required for argument 2']) - v9.CheckDefExecAndScriptFailure(['setfperm("Xfile", "")'], 'E475: Invalid argument') - v9.CheckDefExecAndScriptFailure(['setfperm("", "")'], 'E475: Invalid argument') + v9.CheckSourceDefAndScriptFailure(['setfperm(1, "b")'], ['E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['setfperm("a", 0z10)'], ['E1013: Argument 2: type mismatch, expected string but got blob', 'E1174: String required for argument 2']) + v9.CheckSourceDefExecAndScriptFailure(['setfperm("Xfile", "")'], 'E475: Invalid argument') + v9.CheckSourceDefExecAndScriptFailure(['setfperm("", "")'], 'E475: Invalid argument') assert_equal(0, setfperm('', 'rw-r--r--')) enddef @@ -3949,9 +3949,9 @@ def Test_setline() assert_equal(['one', 'b', 'c', 'd'], getline(1, '$')) setline(1, 10) assert_equal(['10', 'b', 'c', 'd'], getline(1, '$')) - v9.CheckDefAndScriptFailure(['setline([1], "x")'], ['E1013: Argument 1: type mismatch, expected string but got list<number>', 'E1220: String or Number required for argument 1']) - v9.CheckDefExecAndScriptFailure(['setline("", "x")'], 'E1209: Invalid value for a line number') - v9.CheckDefExecAndScriptFailure(['setline(-1, "x")'], 'E966: Invalid line number: -1') + v9.CheckSourceDefAndScriptFailure(['setline([1], "x")'], ['E1013: Argument 1: type mismatch, expected string but got list<number>', 'E1220: String or Number required for argument 1']) + v9.CheckSourceDefExecAndScriptFailure(['setline("", "x")'], 'E1209: Invalid value for a line number') + v9.CheckSourceDefExecAndScriptFailure(['setline(-1, "x")'], 'E966: Invalid line number: -1') assert_fails('setline(".a", "x")', ['E1209:', 'E1209:']) bw! enddef @@ -3961,28 +3961,28 @@ def Test_setloclist() var what = {items: items} setqflist([], ' ', what) setloclist(0, [], ' ', what) - v9.CheckDefAndScriptFailure(['setloclist("1", [])'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1210: Number required for argument 1']) - v9.CheckDefAndScriptFailure(['setloclist(1, 2)'], ['E1013: Argument 2: type mismatch, expected list<any> but got number', 'E1211: List required for argument 2']) - v9.CheckDefAndScriptFailure(['setloclist(1, [], 3)'], ['E1013: Argument 3: type mismatch, expected string but got number', 'E1174: String required for argument 3']) - v9.CheckDefAndScriptFailure(['setloclist(1, [], "a", [])'], ['E1013: Argument 4: type mismatch, expected dict<any> but got list<any>', 'E1206: Dictionary required for argument 4']) + v9.CheckSourceDefAndScriptFailure(['setloclist("1", [])'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1210: Number required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['setloclist(1, 2)'], ['E1013: Argument 2: type mismatch, expected list<any> but got number', 'E1211: List required for argument 2']) + v9.CheckSourceDefAndScriptFailure(['setloclist(1, [], 3)'], ['E1013: Argument 3: type mismatch, expected string but got number', 'E1174: String required for argument 3']) + v9.CheckSourceDefAndScriptFailure(['setloclist(1, [], "a", [])'], ['E1013: Argument 4: type mismatch, expected dict<any> but got list<any>', 'E1206: Dictionary required for argument 4']) enddef def Test_setmatches() - v9.CheckDefAndScriptFailure(['setmatches({})'], ['E1013: Argument 1: type mismatch, expected list<any> but got dict<any>', 'E1211: List required for argument 1']) - v9.CheckDefAndScriptFailure(['setmatches([], "1")'], ['E1013: Argument 2: type mismatch, expected number but got string', 'E1210: Number required for argument 2']) + v9.CheckSourceDefAndScriptFailure(['setmatches({})'], ['E1013: Argument 1: type mismatch, expected list<any> but got dict<any>', 'E1211: List required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['setmatches([], "1")'], ['E1013: Argument 2: type mismatch, expected number but got string', 'E1210: Number required for argument 2']) enddef def Test_setpos() - v9.CheckDefAndScriptFailure(['setpos(1, [])'], ['E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1']) - v9.CheckDefFailure(['setpos(".", ["a"])'], 'E1013: Argument 2: type mismatch, expected list<number> but got list<string>') - v9.CheckDefAndScriptFailure(['setpos(".", 1)'], ['E1013: Argument 2: type mismatch, expected list<number> but got number', 'E1211: List required for argument 2']) - v9.CheckDefExecAndScriptFailure(['setpos("", [0, 1, 1, 1])'], 'E474: Invalid argument') + v9.CheckSourceDefAndScriptFailure(['setpos(1, [])'], ['E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1']) + v9.CheckSourceDefFailure(['setpos(".", ["a"])'], 'E1013: Argument 2: type mismatch, expected list<number> but got list<string>') + v9.CheckSourceDefAndScriptFailure(['setpos(".", 1)'], ['E1013: Argument 2: type mismatch, expected list<number> but got number', 'E1211: List required for argument 2']) + v9.CheckSourceDefExecAndScriptFailure(['setpos("", [0, 1, 1, 1])'], 'E474: Invalid argument') enddef def Test_setqflist() - v9.CheckDefAndScriptFailure(['setqflist(1, "")'], ['E1013: Argument 1: type mismatch, expected list<any> but got number', 'E1211: List required for argument 1']) - v9.CheckDefAndScriptFailure(['setqflist([], 2)'], ['E1013: Argument 2: type mismatch, expected string but got number', 'E1174: String required for argument 2']) - v9.CheckDefAndScriptFailure(['setqflist([], "", [])'], ['E1013: Argument 3: type mismatch, expected dict<any> but got list<any>', 'E1206: Dictionary required for argument 3']) + v9.CheckSourceDefAndScriptFailure(['setqflist(1, "")'], ['E1013: Argument 1: type mismatch, expected list<any> but got number', 'E1211: List required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['setqflist([], 2)'], ['E1013: Argument 2: type mismatch, expected string but got number', 'E1174: String required for argument 2']) + v9.CheckSourceDefAndScriptFailure(['setqflist([], "", [])'], ['E1013: Argument 3: type mismatch, expected dict<any> but got list<any>', 'E1206: Dictionary required for argument 3']) enddef def Test_setreg() @@ -3991,111 +3991,111 @@ def Test_setreg() setreg('a', reginfo) getreginfo('a')->assert_equal(reginfo) assert_fails('setreg("ab", 0)', 'E1162:') - v9.CheckDefAndScriptFailure(['setreg(1, "b")'], ['E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1']) - v9.CheckDefAndScriptFailure(['setreg("a", "b", 3)'], ['E1013: Argument 3: type mismatch, expected string but got number', 'E1174: String required for argument 3']) + v9.CheckSourceDefAndScriptFailure(['setreg(1, "b")'], ['E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['setreg("a", "b", 3)'], ['E1013: Argument 3: type mismatch, expected string but got number', 'E1174: String required for argument 3']) setreg('', '1a2b3c') assert_equal('1a2b3c', @") enddef def Test_settabvar() - v9.CheckDefAndScriptFailure(['settabvar("a", "b", 1)'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1210: Number required for argument 1']) - v9.CheckDefAndScriptFailure(['settabvar(1, 2, "c")'], ['E1013: Argument 2: type mismatch, expected string but got number', 'E1174: String required for argument 2']) + v9.CheckSourceDefAndScriptFailure(['settabvar("a", "b", 1)'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1210: Number required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['settabvar(1, 2, "c")'], ['E1013: Argument 2: type mismatch, expected string but got number', 'E1174: String required for argument 2']) assert_fails('settabvar(1, "", 10)', 'E461: Illegal variable name') enddef def Test_settabwinvar() - v9.CheckDefAndScriptFailure(['settabwinvar("a", 2, "c", true)'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1210: Number required for argument 1']) - v9.CheckDefAndScriptFailure(['settabwinvar(1, "b", "c", [])'], ['E1013: Argument 2: type mismatch, expected number but got string', 'E1210: Number required for argument 2']) - v9.CheckDefAndScriptFailure(['settabwinvar(1, 1, 3, {})'], ['E1013: Argument 3: type mismatch, expected string but got number', 'E1174: String required for argument 3']) + v9.CheckSourceDefAndScriptFailure(['settabwinvar("a", 2, "c", true)'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1210: Number required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['settabwinvar(1, "b", "c", [])'], ['E1013: Argument 2: type mismatch, expected number but got string', 'E1210: Number required for argument 2']) + v9.CheckSourceDefAndScriptFailure(['settabwinvar(1, 1, 3, {})'], ['E1013: Argument 3: type mismatch, expected string but got number', 'E1174: String required for argument 3']) assert_fails('settabwinvar(1, 1, "", 10)', 'E461: Illegal variable name') enddef def Test_settagstack() - v9.CheckDefAndScriptFailure(['settagstack(true, {})'], ['E1013: Argument 1: type mismatch, expected number but got bool', 'E1210: Number required for argument 1']) - v9.CheckDefAndScriptFailure(['settagstack(1, [1])'], ['E1013: Argument 2: type mismatch, expected dict<any> but got list<number>', 'E1206: Dictionary required for argument 2']) - v9.CheckDefAndScriptFailure(['settagstack(1, {}, 2)'], ['E1013: Argument 3: type mismatch, expected string but got number', 'E1174: String required for argument 3']) + v9.CheckSourceDefAndScriptFailure(['settagstack(true, {})'], ['E1013: Argument 1: type mismatch, expected number but got bool', 'E1210: Number required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['settagstack(1, [1])'], ['E1013: Argument 2: type mismatch, expected dict<any> but got list<number>', 'E1206: Dictionary required for argument 2']) + v9.CheckSourceDefAndScriptFailure(['settagstack(1, {}, 2)'], ['E1013: Argument 3: type mismatch, expected string but got number', 'E1174: String required for argument 3']) assert_fails('settagstack(1, {}, "")', 'E962: Invalid action') enddef def Test_setwinvar() - v9.CheckDefAndScriptFailure(['setwinvar("a", "b", 1)'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1210: Number required for argument 1']) - v9.CheckDefAndScriptFailure(['setwinvar(1, 2, "c")'], ['E1013: Argument 2: type mismatch, expected string but got number', 'E1174: String required for argument 2']) + v9.CheckSourceDefAndScriptFailure(['setwinvar("a", "b", 1)'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1210: Number required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['setwinvar(1, 2, "c")'], ['E1013: Argument 2: type mismatch, expected string but got number', 'E1174: String required for argument 2']) assert_fails('setwinvar(1, "", 10)', 'E461: Illegal variable name') assert_fails('setwinvar(0, "&rulerformat", true)', ['E928:', 'E928:']) enddef def Test_sha256() - v9.CheckDefAndScriptFailure(['sha256(100)'], ['E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1']) - v9.CheckDefAndScriptFailure(['sha256(0zABCD)'], ['E1013: Argument 1: type mismatch, expected string but got blob', 'E1174: String required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['sha256(100)'], ['E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['sha256(0zABCD)'], ['E1013: Argument 1: type mismatch, expected string but got blob', 'E1174: String required for argument 1']) assert_equal('ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad', sha256('abc')) assert_equal('e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855', sha256('')) enddef def Test_shiftwidth() - v9.CheckDefAndScriptFailure(['shiftwidth("x")'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1210: Number required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['shiftwidth("x")'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1210: Number required for argument 1']) enddef def Test_sign_define() - v9.CheckDefAndScriptFailure(['sign_define({"a": 10})'], ['E1013: Argument 1: type mismatch, expected string but got dict<number>', 'E1222: String or List required for argument 1']) - v9.CheckDefAndScriptFailure(['sign_define({"a": 10}, "b")'], ['E1013: Argument 1: type mismatch, expected string but got dict<number>', 'E1222: String or List required for argument 1']) - v9.CheckDefAndScriptFailure(['sign_define("a", ["b"])'], ['E1013: Argument 2: type mismatch, expected dict<any> but got list<string>', 'E1206: Dictionary required for argument 2']) + v9.CheckSourceDefAndScriptFailure(['sign_define({"a": 10})'], ['E1013: Argument 1: type mismatch, expected string but got dict<number>', 'E1222: String or List required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['sign_define({"a": 10}, "b")'], ['E1013: Argument 1: type mismatch, expected string but got dict<number>', 'E1222: String or List required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['sign_define("a", ["b"])'], ['E1013: Argument 2: type mismatch, expected dict<any> but got list<string>', 'E1206: Dictionary required for argument 2']) enddef def Test_sign_getdefined() - v9.CheckDefAndScriptFailure(['sign_getdefined(["x"])'], ['E1013: Argument 1: type mismatch, expected string but got list<string>', 'E1174: String required for argument 1']) - v9.CheckDefAndScriptFailure(['sign_getdefined(2)'], ['E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['sign_getdefined(["x"])'], ['E1013: Argument 1: type mismatch, expected string but got list<string>', 'E1174: String required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['sign_getdefined(2)'], ['E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1']) sign_getdefined('')->assert_equal([]) enddef def Test_sign_getplaced() - v9.CheckDefAndScriptFailure(['sign_getplaced(["x"])'], ['E1013: Argument 1: type mismatch, expected string but got list<string>', 'E1220: String or Number required for argument 1']) - v9.CheckDefAndScriptFailure(['sign_getplaced(1, ["a"])'], ['E1013: Argument 2: type mismatch, expected dict<any> but got list<string>', 'E1206: Dictionary required for argument 2']) - v9.CheckDefAndScriptFailure(['sign_getplaced("a", 1.1)'], ['E1013: Argument 2: type mismatch, expected dict<any> but got float', 'E1206: Dictionary required for argument 2']) - v9.CheckDefExecAndScriptFailure(['sign_getplaced(bufnr(), {lnum: ""})'], 'E1030: Using a String as a Number:') + v9.CheckSourceDefAndScriptFailure(['sign_getplaced(["x"])'], ['E1013: Argument 1: type mismatch, expected string but got list<string>', 'E1220: String or Number required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['sign_getplaced(1, ["a"])'], ['E1013: Argument 2: type mismatch, expected dict<any> but got list<string>', 'E1206: Dictionary required for argument 2']) + v9.CheckSourceDefAndScriptFailure(['sign_getplaced("a", 1.1)'], ['E1013: Argument 2: type mismatch, expected dict<any> but got float', 'E1206: Dictionary required for argument 2']) + v9.CheckSourceDefExecAndScriptFailure(['sign_getplaced(bufnr(), {lnum: ""})'], 'E1030: Using a String as a Number:') sign_getplaced('')->assert_equal([{signs: [], bufnr: bufnr()}]) enddef def Test_sign_jump() - v9.CheckDefAndScriptFailure(['sign_jump("a", "b", "c")'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1210: Number required for argument 1']) - v9.CheckDefAndScriptFailure(['sign_jump(1, 2, 3)'], ['E1013: Argument 2: type mismatch, expected string but got number', 'E1174: String required for argument 2']) - v9.CheckDefAndScriptFailure(['sign_jump(1, "b", true)'], ['E1013: Argument 3: type mismatch, expected string but got bool', 'E1220: String or Number required for argument 3']) + v9.CheckSourceDefAndScriptFailure(['sign_jump("a", "b", "c")'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1210: Number required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['sign_jump(1, 2, 3)'], ['E1013: Argument 2: type mismatch, expected string but got number', 'E1174: String required for argument 2']) + v9.CheckSourceDefAndScriptFailure(['sign_jump(1, "b", true)'], ['E1013: Argument 3: type mismatch, expected string but got bool', 'E1220: String or Number required for argument 3']) enddef def Test_sign_place() - v9.CheckDefAndScriptFailure(['sign_place("a", "b", "c", "d")'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1210: Number required for argument 1']) - v9.CheckDefAndScriptFailure(['sign_place(1, 2, "c", "d")'], ['E1013: Argument 2: type mismatch, expected string but got number', 'E1174: String required for argument 2']) - v9.CheckDefAndScriptFailure(['sign_place(1, "b", 3, "d")'], ['E1013: Argument 3: type mismatch, expected string but got number', 'E1174: String required for argument 3']) - v9.CheckDefAndScriptFailure(['sign_place(1, "b", "c", 1.1)'], ['E1013: Argument 4: type mismatch, expected string but got float', 'E1220: String or Number required for argument 4']) - v9.CheckDefAndScriptFailure(['sign_place(1, "b", "c", "d", [1])'], ['E1013: Argument 5: type mismatch, expected dict<any> but got list<number>', 'E1206: Dictionary required for argument 5']) - v9.CheckDefExecAndScriptFailure(['sign_place(0, "", "MySign", bufnr(), {lnum: ""})'], 'E1209: Invalid value for a line number: ""') + v9.CheckSourceDefAndScriptFailure(['sign_place("a", "b", "c", "d")'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1210: Number required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['sign_place(1, 2, "c", "d")'], ['E1013: Argument 2: type mismatch, expected string but got number', 'E1174: String required for argument 2']) + v9.CheckSourceDefAndScriptFailure(['sign_place(1, "b", 3, "d")'], ['E1013: Argument 3: type mismatch, expected string but got number', 'E1174: String required for argument 3']) + v9.CheckSourceDefAndScriptFailure(['sign_place(1, "b", "c", 1.1)'], ['E1013: Argument 4: type mismatch, expected string but got float', 'E1220: String or Number required for argument 4']) + v9.CheckSourceDefAndScriptFailure(['sign_place(1, "b", "c", "d", [1])'], ['E1013: Argument 5: type mismatch, expected dict<any> but got list<number>', 'E1206: Dictionary required for argument 5']) + v9.CheckSourceDefExecAndScriptFailure(['sign_place(0, "", "MySign", bufnr(), {lnum: ""})'], 'E1209: Invalid value for a line number: ""') assert_fails("sign_place(0, '', '', '')", 'E155:') enddef def Test_sign_placelist() - v9.CheckDefAndScriptFailure(['sign_placelist("x")'], ['E1013: Argument 1: type mismatch, expected list<any> but got string', 'E1211: List required for argument 1']) - v9.CheckDefAndScriptFailure(['sign_placelist({"a": 10})'], ['E1013: Argument 1: type mismatch, expected list<any> but got dict<number>', 'E1211: List required for argument 1']) - v9.CheckDefExecAndScriptFailure(['sign_placelist([{"name": "MySign", "buffer": bufnr(), "lnum": ""}])'], 'E1209: Invalid value for a line number: ""') + v9.CheckSourceDefAndScriptFailure(['sign_placelist("x")'], ['E1013: Argument 1: type mismatch, expected list<any> but got string', 'E1211: List required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['sign_placelist({"a": 10})'], ['E1013: Argument 1: type mismatch, expected list<any> but got dict<number>', 'E1211: List required for argument 1']) + v9.CheckSourceDefExecAndScriptFailure(['sign_placelist([{"name": "MySign", "buffer": bufnr(), "lnum": ""}])'], 'E1209: Invalid value for a line number: ""') assert_fails('sign_placelist([{name: "MySign", buffer: "", lnum: 1}])', 'E155:') enddef def Test_sign_undefine() - v9.CheckDefAndScriptFailure(['sign_undefine({})'], ['E1013: Argument 1: type mismatch, expected string but got dict<any>', 'E1222: String or List required for argument 1']) - v9.CheckDefAndScriptFailure(['sign_undefine([1])'], ['E1013: Argument 1: type mismatch, expected list<string> but got list<number>', 'E155: Unknown sign:']) + v9.CheckSourceDefAndScriptFailure(['sign_undefine({})'], ['E1013: Argument 1: type mismatch, expected string but got dict<any>', 'E1222: String or List required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['sign_undefine([1])'], ['E1013: Argument 1: type mismatch, expected list<string> but got list<number>', 'E155: Unknown sign:']) enddef def Test_sign_unplace() - v9.CheckDefAndScriptFailure(['sign_unplace({"a": 10})'], ['E1013: Argument 1: type mismatch, expected string but got dict<number>', 'E1174: String required for argument 1']) - v9.CheckDefAndScriptFailure(['sign_unplace({"a": 10}, "b")'], ['E1013: Argument 1: type mismatch, expected string but got dict<number>', 'E1174: String required for argument 1']) - v9.CheckDefAndScriptFailure(['sign_unplace("a", ["b"])'], ['E1013: Argument 2: type mismatch, expected dict<any> but got list<string>', 'E1206: Dictionary required for argument 2']) + v9.CheckSourceDefAndScriptFailure(['sign_unplace({"a": 10})'], ['E1013: Argument 1: type mismatch, expected string but got dict<number>', 'E1174: String required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['sign_unplace({"a": 10}, "b")'], ['E1013: Argument 1: type mismatch, expected string but got dict<number>', 'E1174: String required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['sign_unplace("a", ["b"])'], ['E1013: Argument 2: type mismatch, expected dict<any> but got list<string>', 'E1206: Dictionary required for argument 2']) enddef def Test_sign_unplacelist() - v9.CheckDefAndScriptFailure(['sign_unplacelist("x")'], ['E1013: Argument 1: type mismatch, expected list<any> but got string', 'E1211: List required for argument 1']) - v9.CheckDefAndScriptFailure(['sign_unplacelist({"a": 10})'], ['E1013: Argument 1: type mismatch, expected list<any> but got dict<number>', 'E1211: List required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['sign_unplacelist("x")'], ['E1013: Argument 1: type mismatch, expected list<any> but got string', 'E1211: List required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['sign_unplacelist({"a": 10})'], ['E1013: Argument 1: type mismatch, expected list<any> but got dict<number>', 'E1211: List required for argument 1']) enddef def Test_simplify() - v9.CheckDefAndScriptFailure(['simplify(100)'], ['E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['simplify(100)'], ['E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1']) call assert_equal('NonExistingFile', simplify('NonExistingFile')) simplify('')->assert_equal('') enddef @@ -4105,9 +4105,9 @@ def Test_slice() assert_equal(['val'], lds->slice(0, 1)->map((_, v) => 'val')) assert_equal(['val'], lds[ : ]->map((_, v) => 'val')) - v9.CheckDefAndScriptFailure(['slice({"a": 10}, 1)'], ['E1013: Argument 1: type mismatch, expected list<any> but got dict<number>', 'E1211: List required for argument 1']) - v9.CheckDefAndScriptFailure(['slice([1, 2, 3], "b")'], ['E1013: Argument 2: type mismatch, expected number but got string', 'E1210: Number required for argument 2']) - v9.CheckDefAndScriptFailure(['slice("abc", 1, "c")'], ['E1013: Argument 3: type mismatch, expected number but got string', 'E1210: Number required for argument 3']) + v9.CheckSourceDefAndScriptFailure(['slice({"a": 10}, 1)'], ['E1013: Argument 1: type mismatch, expected list<any> but got dict<number>', 'E1211: List required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['slice([1, 2, 3], "b")'], ['E1013: Argument 2: type mismatch, expected number but got string', 'E1210: Number required for argument 2']) + v9.CheckSourceDefAndScriptFailure(['slice("abc", 1, "c")'], ['E1013: Argument 3: type mismatch, expected number but got string', 'E1210: Number required for argument 3']) enddef def Test_spellsuggest() @@ -4116,29 +4116,29 @@ def Test_spellsuggest() else spellsuggest('marrch', 1, true)->assert_equal(['March']) endif - v9.CheckDefAndScriptFailure(['spellsuggest(1)'], ['E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1']) - v9.CheckDefAndScriptFailure(['spellsuggest("a", "b")'], ['E1013: Argument 2: type mismatch, expected number but got string', 'E1210: Number required for argument 2']) - v9.CheckDefAndScriptFailure(['spellsuggest("a", 1, 0z01)'], ['E1013: Argument 3: type mismatch, expected bool but got blob', 'E1212: Bool required for argument 3']) + v9.CheckSourceDefAndScriptFailure(['spellsuggest(1)'], ['E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['spellsuggest("a", "b")'], ['E1013: Argument 2: type mismatch, expected number but got string', 'E1210: Number required for argument 2']) + v9.CheckSourceDefAndScriptFailure(['spellsuggest("a", 1, 0z01)'], ['E1013: Argument 3: type mismatch, expected bool but got blob', 'E1212: Bool required for argument 3']) spellsuggest('')->assert_equal([]) enddef def Test_sound_playevent() CheckFeature sound - v9.CheckDefAndScriptFailure(['sound_playevent(1)'], ['E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['sound_playevent(1)'], ['E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1']) enddef def Test_sound_playfile() CheckFeature sound - v9.CheckDefAndScriptFailure(['sound_playfile(1)'], ['E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['sound_playfile(1)'], ['E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1']) enddef def Test_sound_stop() CheckFeature sound - v9.CheckDefAndScriptFailure(['sound_stop("x")'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1210: Number required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['sound_stop("x")'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1210: Number required for argument 1']) enddef def Test_soundfold() - v9.CheckDefAndScriptFailure(['soundfold(20)'], ['E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['soundfold(20)'], ['E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1']) assert_equal('abc', soundfold('abc')) assert_equal('', soundfold('')) enddef @@ -4160,12 +4160,12 @@ def Test_sort_argument() sort(l, Compare) assert_equal([1, 2, 3, 4, 5, 6, 7, 8], l) END - v9.CheckDefAndScriptSuccess(lines) + v9.CheckSourceDefAndScriptSuccess(lines) lines =<< trim END sort([1, 2, 3], (a: any, b: any) => 1) END - v9.CheckDefAndScriptSuccess(lines) + v9.CheckSourceDefAndScriptSuccess(lines) lines =<< trim END vim9script @@ -4176,7 +4176,7 @@ def Test_sort_argument() enddef SortedList()->assert_equal([1, 2, 3]) END - v9.CheckScriptSuccess(lines) + v9.CheckSourceScriptSuccess(lines) enddef def Test_sort_const() @@ -4184,12 +4184,12 @@ def Test_sort_const() const l = [1, 2, 3, 4] sort(l) END - v9.CheckDefFailure(lines, 'E1307: Argument 1: Trying to modify a const list<number>') + v9.CheckSourceDefFailure(lines, 'E1307: Argument 1: Trying to modify a const list<number>') enddef def Test_sort_compare_func_fails() - v9.CheckDefAndScriptFailure(['sort("a")'], ['E1013: Argument 1: type mismatch, expected list<any> but got string', 'E1211: List required for argument 1']) - v9.CheckDefAndScriptFailure(['sort([1], "", [1])'], ['E1013: Argument 3: type mismatch, expected dict<any> but got list<number>', 'E1206: Dictionary required for argument 3']) + v9.CheckSourceDefAndScriptFailure(['sort("a")'], ['E1013: Argument 1: type mismatch, expected list<any> but got string', 'E1211: List required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['sort([1], "", [1])'], ['E1013: Argument 3: type mismatch, expected dict<any> but got list<number>', 'E1206: Dictionary required for argument 3']) var lines =<< trim END vim9script @@ -4202,31 +4202,31 @@ def Test_sort_compare_func_fails() var l = [1, 2, 3] sort(l, (a: string, b: number) => 1) END - v9.CheckDefAndScriptFailure(lines, ['E1013: Argument 2: type mismatch, expected func(?number, ?number): number but got func(string, number): number', 'E1013: Argument 1: type mismatch, expected string but got number']) + v9.CheckSourceDefAndScriptFailure(lines, ['E1013: Argument 2: type mismatch, expected func(?number, ?number): number but got func(string, number): number', 'E1013: Argument 1: type mismatch, expected string but got number']) lines =<< trim END var l = ['a', 'b', 'c'] sort(l, (a: string, b: number) => 1) END - v9.CheckDefAndScriptFailure(lines, ['E1013: Argument 2: type mismatch, expected func(?string, ?string): number but got func(string, number): number', 'E1013: Argument 2: type mismatch, expected number but got string']) + v9.CheckSourceDefAndScriptFailure(lines, ['E1013: Argument 2: type mismatch, expected func(?string, ?string): number but got func(string, number): number', 'E1013: Argument 2: type mismatch, expected number but got string']) lines =<< trim END sort([1, 2, 3], (a: number, b: number) => true) END - v9.CheckDefAndScriptFailure(lines, ['E1013: Argument 2: type mismatch, expected func(?number, ?number): number but got func(number, number): bool', 'E1138: Using a Bool as a Number']) + v9.CheckSourceDefAndScriptFailure(lines, ['E1013: Argument 2: type mismatch, expected func(?number, ?number): number but got func(number, number): bool', 'E1138: Using a Bool as a Number']) enddef def Test_spellbadword() - v9.CheckDefAndScriptFailure(['spellbadword(100)'], ['E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['spellbadword(100)'], ['E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1']) spellbadword('good')->assert_equal(['', '']) spellbadword('')->assert_equal(['', '']) enddef def Test_split() split(' aa bb ', '\W\+', true)->assert_equal(['', 'aa', 'bb', '']) - v9.CheckDefAndScriptFailure(['split(1, "b")'], ['E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1']) - v9.CheckDefAndScriptFailure(['split("a", 2)'], ['E1013: Argument 2: type mismatch, expected string but got number', 'E1174: String required for argument 2']) - v9.CheckDefAndScriptFailure(['split("a", "b", 2)'], ['E1013: Argument 3: type mismatch, expected bool but got number', 'E1212: Bool required for argument 3']) + v9.CheckSourceDefAndScriptFailure(['split(1, "b")'], ['E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['split("a", 2)'], ['E1013: Argument 2: type mismatch, expected string but got number', 'E1174: String required for argument 2']) + v9.CheckSourceDefAndScriptFailure(['split("a", "b", 2)'], ['E1013: Argument 3: type mismatch, expected bool but got number', 'E1212: Bool required for argument 3']) split('')->assert_equal([]) split('', '')->assert_equal([]) enddef @@ -4235,12 +4235,12 @@ def Test_srand() var expected = srand()->len()->range()->map((_, _) => 'x') assert_equal(expected, srand()->map((_, _) => 'x')) - v9.CheckDefAndScriptFailure(['srand("a")'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1210: Number required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['srand("a")'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1210: Number required for argument 1']) type(srand(100))->assert_equal(v:t_list) enddef def Test_state() - v9.CheckDefAndScriptFailure(['state({})'], ['E1013: Argument 1: type mismatch, expected string but got dict<any>', 'E1174: String required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['state({})'], ['E1013: Argument 1: type mismatch, expected string but got dict<any>', 'E1174: String required for argument 1']) assert_equal('', state('a')) enddef @@ -4249,14 +4249,14 @@ def Test_str2float() str2float("2e-2")->assert_equal(0.02) str2float('')->assert_equal(0.0) - v9.CheckDefAndScriptFailure(['str2float(123)'], ['E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['str2float(123)'], ['E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1']) enddef def Test_str2list() assert_equal(['x', 'x', 'x'], str2list('abc')->map((_, _) => 'x')) - v9.CheckDefAndScriptFailure(['str2list(10)'], ['E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1']) - v9.CheckDefAndScriptFailure(['str2list("a", 2)'], ['E1013: Argument 2: type mismatch, expected bool but got number', 'E1212: Bool required for argument 2']) + v9.CheckSourceDefAndScriptFailure(['str2list(10)'], ['E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['str2list("a", 2)'], ['E1013: Argument 2: type mismatch, expected bool but got number', 'E1212: Bool required for argument 2']) assert_equal([97], str2list('a')) assert_equal([97], str2list('a', 1)) assert_equal([97], str2list('a', true)) @@ -4267,29 +4267,29 @@ def Test_str2nr() str2nr("1'000'000", 10, true)->assert_equal(1000000) str2nr('')->assert_equal(0) - v9.CheckDefAndScriptFailure(['str2nr(123)'], ['E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1']) - v9.CheckDefAndScriptFailure(['str2nr("123", "x")'], ['E1013: Argument 2: type mismatch, expected number but got string', 'E1210: Number required for argument 2']) - v9.CheckDefAndScriptFailure(['str2nr("123", 10, "x")'], ['E1013: Argument 3: type mismatch, expected bool but got string', 'E1212: Bool required for argument 3']) + v9.CheckSourceDefAndScriptFailure(['str2nr(123)'], ['E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['str2nr("123", "x")'], ['E1013: Argument 2: type mismatch, expected number but got string', 'E1210: Number required for argument 2']) + v9.CheckSourceDefAndScriptFailure(['str2nr("123", 10, "x")'], ['E1013: Argument 3: type mismatch, expected bool but got string', 'E1212: Bool required for argument 3']) enddef def Test_strcharlen() - v9.CheckDefAndScriptFailure(['strcharlen([1])'], ['E1013: Argument 1: type mismatch, expected string but got list<number>', 'E1220: String or Number required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['strcharlen([1])'], ['E1013: Argument 1: type mismatch, expected string but got list<number>', 'E1220: String or Number required for argument 1']) "abc"->strcharlen()->assert_equal(3) strcharlen(99)->assert_equal(2) enddef def Test_strcharpart() - v9.CheckDefAndScriptFailure(['strcharpart(1, 2)'], ['E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1']) - v9.CheckDefAndScriptFailure(['strcharpart("a", "b")'], ['E1013: Argument 2: type mismatch, expected number but got string', 'E1210: Number required for argument 2']) - v9.CheckDefAndScriptFailure(['strcharpart("a", 1, "c")'], ['E1013: Argument 3: type mismatch, expected number but got string', 'E1210: Number required for argument 3']) - v9.CheckDefAndScriptFailure(['strcharpart("a", 1, 1, 2)'], ['E1013: Argument 4: type mismatch, expected bool but got number', 'E1212: Bool required for argument 4']) + v9.CheckSourceDefAndScriptFailure(['strcharpart(1, 2)'], ['E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['strcharpart("a", "b")'], ['E1013: Argument 2: type mismatch, expected number but got string', 'E1210: Number required for argument 2']) + v9.CheckSourceDefAndScriptFailure(['strcharpart("a", 1, "c")'], ['E1013: Argument 3: type mismatch, expected number but got string', 'E1210: Number required for argument 3']) + v9.CheckSourceDefAndScriptFailure(['strcharpart("a", 1, 1, 2)'], ['E1013: Argument 4: type mismatch, expected bool but got number', 'E1212: Bool required for argument 4']) strcharpart('', 0)->assert_equal('') enddef def Test_strchars() strchars("A\u20dd", true)->assert_equal(1) - v9.CheckDefAndScriptFailure(['strchars(10)'], ['E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1']) - v9.CheckDefAndScriptFailure(['strchars("a", 2)'], ['E1013: Argument 2: type mismatch, expected bool but got number', 'E1212: Bool required for argument 2']) + v9.CheckSourceDefAndScriptFailure(['strchars(10)'], ['E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['strchars("a", 2)'], ['E1013: Argument 2: type mismatch, expected bool but got number', 'E1212: Bool required for argument 2']) assert_equal(3, strchars('abc')) assert_equal(3, strchars('abc', 1)) assert_equal(3, strchars('abc', true)) @@ -4297,46 +4297,46 @@ def Test_strchars() enddef def Test_strdisplaywidth() - v9.CheckDefAndScriptFailure(['strdisplaywidth(1)'], ['E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1']) - v9.CheckDefAndScriptFailure(['strdisplaywidth("a", "x")'], ['E1013: Argument 2: type mismatch, expected number but got string', 'E1210: Number required for argument 2']) + v9.CheckSourceDefAndScriptFailure(['strdisplaywidth(1)'], ['E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['strdisplaywidth("a", "x")'], ['E1013: Argument 2: type mismatch, expected number but got string', 'E1210: Number required for argument 2']) strdisplaywidth('')->assert_equal(0) enddef def Test_strftime() if exists('*strftime') - v9.CheckDefAndScriptFailure(['strftime(1)'], ['E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1']) - v9.CheckDefAndScriptFailure(['strftime("a", "x")'], ['E1013: Argument 2: type mismatch, expected number but got string', 'E1210: Number required for argument 2']) + v9.CheckSourceDefAndScriptFailure(['strftime(1)'], ['E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['strftime("a", "x")'], ['E1013: Argument 2: type mismatch, expected number but got string', 'E1210: Number required for argument 2']) strftime('')->assert_equal('') endif enddef def Test_strgetchar() - v9.CheckDefAndScriptFailure(['strgetchar(1, 1)'], ['E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1']) - v9.CheckDefAndScriptFailure(['strgetchar("a", "x")'], ['E1013: Argument 2: type mismatch, expected number but got string', 'E1210: Number required for argument 2']) + v9.CheckSourceDefAndScriptFailure(['strgetchar(1, 1)'], ['E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['strgetchar("a", "x")'], ['E1013: Argument 2: type mismatch, expected number but got string', 'E1210: Number required for argument 2']) strgetchar('', 0)->assert_equal(-1) strgetchar('', 1)->assert_equal(-1) enddef def Test_stridx() - v9.CheckDefAndScriptFailure(['stridx([1], "b")'], ['E1013: Argument 1: type mismatch, expected string but got list<number>', 'E1174: String required for argument 1']) - v9.CheckDefAndScriptFailure(['stridx("a", {})'], ['E1013: Argument 2: type mismatch, expected string but got dict<any>', 'E1174: String required for argument 2']) - v9.CheckDefAndScriptFailure(['stridx("a", "b", "c")'], ['E1013: Argument 3: type mismatch, expected number but got string', 'E1210: Number required for argument 3']) + v9.CheckSourceDefAndScriptFailure(['stridx([1], "b")'], ['E1013: Argument 1: type mismatch, expected string but got list<number>', 'E1174: String required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['stridx("a", {})'], ['E1013: Argument 2: type mismatch, expected string but got dict<any>', 'E1174: String required for argument 2']) + v9.CheckSourceDefAndScriptFailure(['stridx("a", "b", "c")'], ['E1013: Argument 3: type mismatch, expected number but got string', 'E1210: Number required for argument 3']) stridx('', '')->assert_equal(0) stridx('', 'a')->assert_equal(-1) stridx('a', '')->assert_equal(0) enddef def Test_strlen() - v9.CheckDefAndScriptFailure(['strlen([])'], ['E1013: Argument 1: type mismatch, expected string but got list<any>', 'E1220: String or Number required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['strlen([])'], ['E1013: Argument 1: type mismatch, expected string but got list<any>', 'E1220: String or Number required for argument 1']) "abc"->strlen()->assert_equal(3) strlen(99)->assert_equal(2) enddef def Test_strpart() - v9.CheckDefAndScriptFailure(['strpart(1, 2)'], ['E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1']) - v9.CheckDefAndScriptFailure(['strpart("a", "b")'], ['E1013: Argument 2: type mismatch, expected number but got string', 'E1210: Number required for argument 2']) - v9.CheckDefAndScriptFailure(['strpart("a", 1, "c")'], ['E1013: Argument 3: type mismatch, expected number but got string', 'E1210: Number required for argument 3']) - v9.CheckDefAndScriptFailure(['strpart("a", 1, 1, 2)'], ['E1013: Argument 4: type mismatch, expected bool but got number', 'E1212: Bool required for argument 4']) + v9.CheckSourceDefAndScriptFailure(['strpart(1, 2)'], ['E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['strpart("a", "b")'], ['E1013: Argument 2: type mismatch, expected number but got string', 'E1210: Number required for argument 2']) + v9.CheckSourceDefAndScriptFailure(['strpart("a", 1, "c")'], ['E1013: Argument 3: type mismatch, expected number but got string', 'E1210: Number required for argument 3']) + v9.CheckSourceDefAndScriptFailure(['strpart("a", 1, 1, 2)'], ['E1013: Argument 4: type mismatch, expected bool but got number', 'E1212: Bool required for argument 4']) strpart('', 0)->assert_equal('') enddef @@ -4344,8 +4344,8 @@ def Test_strptime() CheckFunction strptime CheckNotBSD if exists_compiled('*strptime') - v9.CheckDefAndScriptFailure(['strptime(10, "2021")'], ['E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1']) - v9.CheckDefAndScriptFailure(['strptime("%Y", 2021)'], ['E1013: Argument 2: type mismatch, expected string but got number', 'E1174: String required for argument 2']) + v9.CheckSourceDefAndScriptFailure(['strptime(10, "2021")'], ['E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['strptime("%Y", 2021)'], ['E1013: Argument 2: type mismatch, expected string but got number', 'E1174: String required for argument 2']) assert_notequal(0, strptime('%Y', '2021')) # This fails on BSD 14 and returns # -2209078800 instead of 0 @@ -4354,30 +4354,30 @@ def Test_strptime() enddef def Test_strridx() - v9.CheckDefAndScriptFailure(['strridx([1], "b")'], ['E1013: Argument 1: type mismatch, expected string but got list<number>', 'E1174: String required for argument 1']) - v9.CheckDefAndScriptFailure(['strridx("a", {})'], ['E1013: Argument 2: type mismatch, expected string but got dict<any>', 'E1174: String required for argument 2']) - v9.CheckDefAndScriptFailure(['strridx("a", "b", "c")'], ['E1013: Argument 3: type mismatch, expected number but got string', 'E1210: Number required for argument 3']) + v9.CheckSourceDefAndScriptFailure(['strridx([1], "b")'], ['E1013: Argument 1: type mismatch, expected string but got list<number>', 'E1174: String required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['strridx("a", {})'], ['E1013: Argument 2: type mismatch, expected string but got dict<any>', 'E1174: String required for argument 2']) + v9.CheckSourceDefAndScriptFailure(['strridx("a", "b", "c")'], ['E1013: Argument 3: type mismatch, expected number but got string', 'E1210: Number required for argument 3']) strridx('', '')->assert_equal(0) strridx('', 'a')->assert_equal(-1) strridx('a', '')->assert_equal(1) enddef def Test_strtrans() - v9.CheckDefAndScriptFailure(['strtrans(20)'], ['E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['strtrans(20)'], ['E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1']) assert_equal('abc', strtrans('abc')) strtrans('')->assert_equal('') enddef def Test_strutf16len() - v9.CheckDefAndScriptFailure(['strutf16len([])'], ['E1013: Argument 1: type mismatch, expected string but got list<any>', 'E1174: String required for argument 1']) - v9.CheckDefAndScriptFailure(['strutf16len("a", "")'], ['E1013: Argument 2: type mismatch, expected bool but got string', 'E1212: Bool required for argument 2']) + v9.CheckSourceDefAndScriptFailure(['strutf16len([])'], ['E1013: Argument 1: type mismatch, expected string but got list<any>', 'E1174: String required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['strutf16len("a", "")'], ['E1013: Argument 2: type mismatch, expected bool but got string', 'E1212: Bool required for argument 2']) ""->strutf16len()->assert_equal(0) '-ąÌ-ąÌ'->strutf16len(true)->assert_equal(8) '-ąÌ-ąÌ'->strutf16len(false)->assert_equal(4) enddef def Test_strwidth() - v9.CheckDefAndScriptFailure(['strwidth(10)'], ['E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['strwidth(10)'], ['E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1']) assert_equal(4, strwidth('abcd')) strwidth('')->assert_equal(0) enddef @@ -4388,8 +4388,8 @@ def Test_submatch() var actual = substitute('A123456789', pat, Rep, '') var expected = "[['A123456789'], ['1'], ['2'], ['3'], ['4'], ['5'], ['6'], ['7'], ['8'], ['9']]" actual->assert_equal(expected) - v9.CheckDefAndScriptFailure(['submatch("x")'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1210: Number required for argument 1']) - v9.CheckDefAndScriptFailure(['submatch(1, "a")'], ['E1013: Argument 2: type mismatch, expected bool but got string', 'E1212: Bool required for argument 2']) + v9.CheckSourceDefAndScriptFailure(['submatch("x")'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1210: Number required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['submatch(1, "a")'], ['E1013: Argument 2: type mismatch, expected bool but got string', 'E1212: Bool required for argument 2']) enddef def Test_substitute() @@ -4400,30 +4400,30 @@ def Test_substitute() assert_fails('"text"->substitute(".*", () => test_null_job(), "")', 'E908: Using an invalid value as a String: job') assert_fails('"text"->substitute(".*", () => test_null_channel(), "")', 'E908: Using an invalid value as a String: channel') endif - v9.CheckDefAndScriptFailure(['substitute(1, "b", "1", "d")'], ['E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1']) - v9.CheckDefAndScriptFailure(['substitute("a", 2, "1", "d")'], ['E1013: Argument 2: type mismatch, expected string but got number', 'E1174: String required for argument 2']) - v9.CheckDefAndScriptFailure(['substitute("a", "b", "1", 4)'], ['E1013: Argument 4: type mismatch, expected string but got number', 'E1174: String required for argument 4']) + v9.CheckSourceDefAndScriptFailure(['substitute(1, "b", "1", "d")'], ['E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['substitute("a", 2, "1", "d")'], ['E1013: Argument 2: type mismatch, expected string but got number', 'E1174: String required for argument 2']) + v9.CheckSourceDefAndScriptFailure(['substitute("a", "b", "1", 4)'], ['E1013: Argument 4: type mismatch, expected string but got number', 'E1174: String required for argument 4']) substitute('', '', '', '')->assert_equal('') var lines =<< trim END assert_equal("4", substitute("3", '\d', '\=str2nr(submatch(0)) + 1', 'g')) END - v9.CheckDefAndScriptSuccess(lines) + v9.CheckSourceDefAndScriptSuccess(lines) lines =<< trim END assert_equal("4", substitute("3", '\d', '\="text" x', 'g')) END - v9.CheckDefAndScriptFailure(lines, 'E488: Trailing characters: x') + v9.CheckSourceDefAndScriptFailure(lines, 'E488: Trailing characters: x') enddef def Test_swapinfo() - v9.CheckDefAndScriptFailure(['swapinfo({})'], ['E1013: Argument 1: type mismatch, expected string but got dict<any>', 'E1174: String required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['swapinfo({})'], ['E1013: Argument 1: type mismatch, expected string but got dict<any>', 'E1174: String required for argument 1']) call swapinfo('x')->assert_equal({error: 'Cannot open file'}) call swapinfo('')->assert_equal({error: 'Cannot open file'}) enddef def Test_swapname() - v9.CheckDefAndScriptFailure(['swapname([])'], ['E1013: Argument 1: type mismatch, expected string but got list<any>', 'E1220: String or Number required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['swapname([])'], ['E1013: Argument 1: type mismatch, expected string but got list<any>', 'E1220: String or Number required for argument 1']) assert_fails('swapname("NonExistingBuf")', 'E94:') enddef @@ -4432,46 +4432,46 @@ def Test_synID() setline(1, "text") synID(1, 1, true)->assert_equal(0) bwipe! - v9.CheckDefAndScriptFailure(['synID(0z10, 1, true)'], ['E1013: Argument 1: type mismatch, expected string but got blob', 'E1220: String or Number required for argument 1']) - v9.CheckDefAndScriptFailure(['synID("a", true, false)'], ['E1013: Argument 2: type mismatch, expected number but got bool', 'E1210: Number required for argument 2']) - v9.CheckDefAndScriptFailure(['synID(1, 1, 2)'], ['E1013: Argument 3: type mismatch, expected bool but got number', 'E1212: Bool required for argument 3']) - v9.CheckDefExecAndScriptFailure(['synID("", 10, true)'], 'E1209: Invalid value for a line number') + v9.CheckSourceDefAndScriptFailure(['synID(0z10, 1, true)'], ['E1013: Argument 1: type mismatch, expected string but got blob', 'E1220: String or Number required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['synID("a", true, false)'], ['E1013: Argument 2: type mismatch, expected number but got bool', 'E1210: Number required for argument 2']) + v9.CheckSourceDefAndScriptFailure(['synID(1, 1, 2)'], ['E1013: Argument 3: type mismatch, expected bool but got number', 'E1212: Bool required for argument 3']) + v9.CheckSourceDefExecAndScriptFailure(['synID("", 10, true)'], 'E1209: Invalid value for a line number') enddef def Test_synIDattr() - v9.CheckDefAndScriptFailure(['synIDattr("a", "b")'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1210: Number required for argument 1']) - v9.CheckDefAndScriptFailure(['synIDattr(1, 2)'], ['E1013: Argument 2: type mismatch, expected string but got number', 'E1174: String required for argument 2']) - v9.CheckDefAndScriptFailure(['synIDattr(1, "b", 3)'], ['E1013: Argument 3: type mismatch, expected string but got number', 'E1174: String required for argument 3']) + v9.CheckSourceDefAndScriptFailure(['synIDattr("a", "b")'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1210: Number required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['synIDattr(1, 2)'], ['E1013: Argument 2: type mismatch, expected string but got number', 'E1174: String required for argument 2']) + v9.CheckSourceDefAndScriptFailure(['synIDattr(1, "b", 3)'], ['E1013: Argument 3: type mismatch, expected string but got number', 'E1174: String required for argument 3']) synIDattr(1, '', '')->assert_equal('') enddef def Test_synIDtrans() - v9.CheckDefAndScriptFailure(['synIDtrans("a")'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1210: Number required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['synIDtrans("a")'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1210: Number required for argument 1']) enddef def Test_synconcealed() - v9.CheckDefAndScriptFailure(['synconcealed(0z10, 1)'], ['E1013: Argument 1: type mismatch, expected string but got blob', 'E1220: String or Number required for argument 1']) - v9.CheckDefAndScriptFailure(['synconcealed(1, "a")'], ['E1013: Argument 2: type mismatch, expected number but got string', 'E1210: Number required for argument 2']) + v9.CheckSourceDefAndScriptFailure(['synconcealed(0z10, 1)'], ['E1013: Argument 1: type mismatch, expected string but got blob', 'E1220: String or Number required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['synconcealed(1, "a")'], ['E1013: Argument 2: type mismatch, expected number but got string', 'E1210: Number required for argument 2']) if has('conceal') - v9.CheckDefExecAndScriptFailure(['synconcealed("", 4)'], 'E1209: Invalid value for a line number') + v9.CheckSourceDefExecAndScriptFailure(['synconcealed("", 4)'], 'E1209: Invalid value for a line number') endif enddef def Test_synstack() - v9.CheckDefAndScriptFailure(['synstack(0z10, 1)'], ['E1013: Argument 1: type mismatch, expected string but got blob', 'E1220: String or Number required for argument 1']) - v9.CheckDefAndScriptFailure(['synstack(1, "a")'], ['E1013: Argument 2: type mismatch, expected number but got string', 'E1210: Number required for argument 2']) - v9.CheckDefExecAndScriptFailure(['synstack("", 4)'], 'E1209: Invalid value for a line number') + v9.CheckSourceDefAndScriptFailure(['synstack(0z10, 1)'], ['E1013: Argument 1: type mismatch, expected string but got blob', 'E1220: String or Number required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['synstack(1, "a")'], ['E1013: Argument 2: type mismatch, expected number but got string', 'E1210: Number required for argument 2']) + v9.CheckSourceDefExecAndScriptFailure(['synstack("", 4)'], 'E1209: Invalid value for a line number') enddef def Test_system() - v9.CheckDefAndScriptFailure(['system(1)'], ['E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1']) - v9.CheckDefAndScriptFailure(['system("a", {})'], ['E1013: Argument 2: type mismatch, expected string but got dict<any>', 'E1224: String, Number or List required for argument 2']) + v9.CheckSourceDefAndScriptFailure(['system(1)'], ['E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['system("a", {})'], ['E1013: Argument 2: type mismatch, expected string but got dict<any>', 'E1224: String, Number or List required for argument 2']) assert_equal("123\n", system('echo 123')) enddef def Test_systemlist() - v9.CheckDefAndScriptFailure(['systemlist(1)'], ['E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1']) - v9.CheckDefAndScriptFailure(['systemlist("a", {})'], ['E1013: Argument 2: type mismatch, expected string but got dict<any>', 'E1224: String, Number or List required for argument 2']) + v9.CheckSourceDefAndScriptFailure(['systemlist(1)'], ['E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['systemlist("a", {})'], ['E1013: Argument 2: type mismatch, expected string but got dict<any>', 'E1224: String, Number or List required for argument 2']) if has('win32') call assert_equal(["123\r"], systemlist('echo 123')) else @@ -4480,106 +4480,106 @@ def Test_systemlist() enddef def Test_tabpagebuflist() - v9.CheckDefAndScriptFailure(['tabpagebuflist("t")'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1210: Number required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['tabpagebuflist("t")'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1210: Number required for argument 1']) assert_equal([bufnr('')], tabpagebuflist()) assert_equal([bufnr('')], tabpagebuflist(1)) assert_equal(['x'], tabpagebuflist()->map((_, _) => 'x')) enddef def Test_tabpagenr() - v9.CheckDefAndScriptFailure(['tabpagenr(1)'], ['E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1']) - v9.CheckDefExecAndScriptFailure(['tabpagenr("")'], 'E15: Invalid expression') + v9.CheckSourceDefAndScriptFailure(['tabpagenr(1)'], ['E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1']) + v9.CheckSourceDefExecAndScriptFailure(['tabpagenr("")'], 'E15: Invalid expression') assert_equal(1, tabpagenr('$')) assert_equal(1, tabpagenr()) enddef def Test_tabpagewinnr() - v9.CheckDefAndScriptFailure(['tabpagewinnr("x")'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1210: Number required for argument 1']) - v9.CheckDefAndScriptFailure(['tabpagewinnr(1, 2)'], ['E1013: Argument 2: type mismatch, expected string but got number', 'E1174: String required for argument 2']) - v9.CheckDefExecAndScriptFailure(['tabpagewinnr(1, "")'], 'E15: Invalid expression') + v9.CheckSourceDefAndScriptFailure(['tabpagewinnr("x")'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1210: Number required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['tabpagewinnr(1, 2)'], ['E1013: Argument 2: type mismatch, expected string but got number', 'E1174: String required for argument 2']) + v9.CheckSourceDefExecAndScriptFailure(['tabpagewinnr(1, "")'], 'E15: Invalid expression') enddef def Test_taglist() - v9.CheckDefAndScriptFailure(['taglist([1])'], ['E1013: Argument 1: type mismatch, expected string but got list<number>', 'E1174: String required for argument 1']) - v9.CheckDefAndScriptFailure(['taglist("a", [2])'], ['E1013: Argument 2: type mismatch, expected string but got list<number>', 'E1174: String required for argument 2']) + v9.CheckSourceDefAndScriptFailure(['taglist([1])'], ['E1013: Argument 1: type mismatch, expected string but got list<number>', 'E1174: String required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['taglist("a", [2])'], ['E1013: Argument 2: type mismatch, expected string but got list<number>', 'E1174: String required for argument 2']) taglist('')->assert_equal(0) taglist('', '')->assert_equal(0) enddef def Test_term_dumpload() CheckRunVimInTerminal - v9.CheckDefAndScriptFailure(['term_dumpload({"a": 10})'], ['E1013: Argument 1: type mismatch, expected string but got dict<number>', 'E1174: String required for argument 1']) - v9.CheckDefAndScriptFailure(['term_dumpload({"a": 10}, "b")'], ['E1013: Argument 1: type mismatch, expected string but got dict<number>', 'E1174: String required for argument 1']) - v9.CheckDefAndScriptFailure(['term_dumpload("a", ["b"])'], ['E1013: Argument 2: type mismatch, expected dict<any> but got list<string>', 'E1206: Dictionary required for argument 2']) - v9.CheckDefExecAndScriptFailure(['term_dumpload("")'], 'E485: Can''t read file') + v9.CheckSourceDefAndScriptFailure(['term_dumpload({"a": 10})'], ['E1013: Argument 1: type mismatch, expected string but got dict<number>', 'E1174: String required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['term_dumpload({"a": 10}, "b")'], ['E1013: Argument 1: type mismatch, expected string but got dict<number>', 'E1174: String required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['term_dumpload("a", ["b"])'], ['E1013: Argument 2: type mismatch, expected dict<any> but got list<string>', 'E1206: Dictionary required for argument 2']) + v9.CheckSourceDefExecAndScriptFailure(['term_dumpload("")'], 'E485: Can''t read file') enddef def Test_term_dumpdiff() CheckRunVimInTerminal - v9.CheckDefAndScriptFailure(['term_dumpdiff(1, "b")'], ['E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1']) - v9.CheckDefAndScriptFailure(['term_dumpdiff("a", 2)'], ['E1013: Argument 2: type mismatch, expected string but got number', 'E1174: String required for argument 2']) - v9.CheckDefAndScriptFailure(['term_dumpdiff("a", "b", [1])'], ['E1013: Argument 3: type mismatch, expected dict<any> but got list<number>', 'E1206: Dictionary required for argument 3']) - v9.CheckDefExecAndScriptFailure(['term_dumpdiff("", "")'], 'E485: Can''t read file') + v9.CheckSourceDefAndScriptFailure(['term_dumpdiff(1, "b")'], ['E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['term_dumpdiff("a", 2)'], ['E1013: Argument 2: type mismatch, expected string but got number', 'E1174: String required for argument 2']) + v9.CheckSourceDefAndScriptFailure(['term_dumpdiff("a", "b", [1])'], ['E1013: Argument 3: type mismatch, expected dict<any> but got list<number>', 'E1206: Dictionary required for argument 3']) + v9.CheckSourceDefExecAndScriptFailure(['term_dumpdiff("", "")'], 'E485: Can''t read file') enddef def Test_term_dumpwrite() CheckRunVimInTerminal - v9.CheckDefAndScriptFailure(['term_dumpwrite(true, "b")'], ['E1013: Argument 1: type mismatch, expected string but got bool', 'E1220: String or Number required for argument 1']) - v9.CheckDefAndScriptFailure(['term_dumpwrite(1, 2)'], ['E1013: Argument 2: type mismatch, expected string but got number', 'E1174: String required for argument 2']) - v9.CheckDefAndScriptFailure(['term_dumpwrite("a", "b", [1])'], ['E1013: Argument 3: type mismatch, expected dict<any> but got list<number>', 'E1206: Dictionary required for argument 3']) + v9.CheckSourceDefAndScriptFailure(['term_dumpwrite(true, "b")'], ['E1013: Argument 1: type mismatch, expected string but got bool', 'E1220: String or Number required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['term_dumpwrite(1, 2)'], ['E1013: Argument 2: type mismatch, expected string but got number', 'E1174: String required for argument 2']) + v9.CheckSourceDefAndScriptFailure(['term_dumpwrite("a", "b", [1])'], ['E1013: Argument 3: type mismatch, expected dict<any> but got list<number>', 'E1206: Dictionary required for argument 3']) enddef def Test_term_getaltscreen() CheckRunVimInTerminal - v9.CheckDefAndScriptFailure(['term_getaltscreen(true)'], ['E1013: Argument 1: type mismatch, expected string but got bool', 'E1220: String or Number required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['term_getaltscreen(true)'], ['E1013: Argument 1: type mismatch, expected string but got bool', 'E1220: String or Number required for argument 1']) enddef def Test_term_getansicolors() CheckRunVimInTerminal CheckFeature termguicolors - v9.CheckDefAndScriptFailure(['term_getansicolors(["a"])'], ['E1013: Argument 1: type mismatch, expected string but got list<string>', 'E1220: String or Number required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['term_getansicolors(["a"])'], ['E1013: Argument 1: type mismatch, expected string but got list<string>', 'E1220: String or Number required for argument 1']) enddef def Test_term_getattr() CheckRunVimInTerminal - v9.CheckDefAndScriptFailure(['term_getattr("x", "a")'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1210: Number required for argument 1']) - v9.CheckDefAndScriptFailure(['term_getattr(1, 2)'], ['E1013: Argument 2: type mismatch, expected string but got number', 'E1174: String required for argument 2']) + v9.CheckSourceDefAndScriptFailure(['term_getattr("x", "a")'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1210: Number required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['term_getattr(1, 2)'], ['E1013: Argument 2: type mismatch, expected string but got number', 'E1174: String required for argument 2']) enddef def Test_term_getcursor() CheckRunVimInTerminal - v9.CheckDefAndScriptFailure(['term_getcursor({"a": 10})'], ['E1013: Argument 1: type mismatch, expected string but got dict<number>', 'E1220: String or Number required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['term_getcursor({"a": 10})'], ['E1013: Argument 1: type mismatch, expected string but got dict<number>', 'E1220: String or Number required for argument 1']) enddef def Test_term_getjob() CheckRunVimInTerminal - v9.CheckDefAndScriptFailure(['term_getjob(0z10)'], ['E1013: Argument 1: type mismatch, expected string but got blob', 'E1220: String or Number required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['term_getjob(0z10)'], ['E1013: Argument 1: type mismatch, expected string but got blob', 'E1220: String or Number required for argument 1']) enddef def Test_term_getline() CheckRunVimInTerminal - v9.CheckDefAndScriptFailure(['term_getline(1.1, 1)'], ['E1013: Argument 1: type mismatch, expected string but got float', 'E1220: String or Number required for argument 1']) - v9.CheckDefAndScriptFailure(['term_getline(1, 1.1)'], ['E1013: Argument 2: type mismatch, expected string but got float', 'E1220: String or Number required for argument 2']) + v9.CheckSourceDefAndScriptFailure(['term_getline(1.1, 1)'], ['E1013: Argument 1: type mismatch, expected string but got float', 'E1220: String or Number required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['term_getline(1, 1.1)'], ['E1013: Argument 2: type mismatch, expected string but got float', 'E1220: String or Number required for argument 2']) enddef def Test_term_getscrolled() CheckRunVimInTerminal - v9.CheckDefAndScriptFailure(['term_getscrolled(1.1)'], ['E1013: Argument 1: type mismatch, expected string but got float', 'E1220: String or Number required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['term_getscrolled(1.1)'], ['E1013: Argument 1: type mismatch, expected string but got float', 'E1220: String or Number required for argument 1']) enddef def Test_term_getsize() CheckRunVimInTerminal - v9.CheckDefAndScriptFailure(['term_getsize(1.1)'], ['E1013: Argument 1: type mismatch, expected string but got float', 'E1220: String or Number required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['term_getsize(1.1)'], ['E1013: Argument 1: type mismatch, expected string but got float', 'E1220: String or Number required for argument 1']) enddef def Test_term_getstatus() CheckRunVimInTerminal - v9.CheckDefAndScriptFailure(['term_getstatus(1.1)'], ['E1013: Argument 1: type mismatch, expected string but got float', 'E1220: String or Number required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['term_getstatus(1.1)'], ['E1013: Argument 1: type mismatch, expected string but got float', 'E1220: String or Number required for argument 1']) enddef def Test_term_gettitle() CheckRunVimInTerminal - v9.CheckDefAndScriptFailure(['term_gettitle(1.1)'], ['E1013: Argument 1: type mismatch, expected string but got float', 'E1220: String or Number required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['term_gettitle(1.1)'], ['E1013: Argument 1: type mismatch, expected string but got float', 'E1220: String or Number required for argument 1']) enddef def Test_term_gettty() @@ -4590,28 +4590,28 @@ def Test_term_gettty() term_gettty(buf, true)->assert_notequal('') g:StopShellInTerminal(buf) endif - v9.CheckDefAndScriptFailure(['term_gettty([1])'], ['E1013: Argument 1: type mismatch, expected string but got list<number>', 'E1220: String or Number required for argument 1']) - v9.CheckDefAndScriptFailure(['term_gettty(1, 2)'], ['E1013: Argument 2: type mismatch, expected bool but got number', 'E1212: Bool required for argument 2']) + v9.CheckSourceDefAndScriptFailure(['term_gettty([1])'], ['E1013: Argument 1: type mismatch, expected string but got list<number>', 'E1220: String or Number required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['term_gettty(1, 2)'], ['E1013: Argument 2: type mismatch, expected bool but got number', 'E1212: Bool required for argument 2']) enddef def Test_term_scrape() CheckRunVimInTerminal - v9.CheckDefAndScriptFailure(['term_scrape(1.1, 1)'], ['E1013: Argument 1: type mismatch, expected string but got float', 'E1220: String or Number required for argument 1']) - v9.CheckDefAndScriptFailure(['term_scrape(1, 1.1)'], ['E1013: Argument 2: type mismatch, expected string but got float', 'E1220: String or Number required for argument 2']) + v9.CheckSourceDefAndScriptFailure(['term_scrape(1.1, 1)'], ['E1013: Argument 1: type mismatch, expected string but got float', 'E1220: String or Number required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['term_scrape(1, 1.1)'], ['E1013: Argument 2: type mismatch, expected string but got float', 'E1220: String or Number required for argument 2']) enddef def Test_term_sendkeys() CheckRunVimInTerminal - v9.CheckDefAndScriptFailure(['term_sendkeys([], "p")'], ['E1013: Argument 1: type mismatch, expected string but got list<any>', 'E1220: String or Number required for argument 1']) - v9.CheckDefAndScriptFailure(['term_sendkeys(1, [])'], ['E1013: Argument 2: type mismatch, expected string but got list<any>', 'E1174: String required for argument 2']) + v9.CheckSourceDefAndScriptFailure(['term_sendkeys([], "p")'], ['E1013: Argument 1: type mismatch, expected string but got list<any>', 'E1220: String or Number required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['term_sendkeys(1, [])'], ['E1013: Argument 2: type mismatch, expected string but got list<any>', 'E1174: String required for argument 2']) enddef def Test_term_setansicolors() CheckRunVimInTerminal if has('termguicolors') || has('gui') - v9.CheckDefAndScriptFailure(['term_setansicolors([], "p")'], ['E1013: Argument 1: type mismatch, expected string but got list<any>', 'E1220: String or Number required for argument 1']) - v9.CheckDefAndScriptFailure(['term_setansicolors(10, {})'], ['E1013: Argument 2: type mismatch, expected list<any> but got dict<any>', 'E1211: List required for argument 2']) + v9.CheckSourceDefAndScriptFailure(['term_setansicolors([], "p")'], ['E1013: Argument 1: type mismatch, expected string but got list<any>', 'E1220: String or Number required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['term_setansicolors(10, {})'], ['E1013: Argument 2: type mismatch, expected list<any> but got dict<any>', 'E1211: List required for argument 2']) else throw 'Skipped: Only works with termguicolors or gui feature' endif @@ -4619,27 +4619,27 @@ enddef def Test_term_setapi() CheckRunVimInTerminal - v9.CheckDefAndScriptFailure(['term_setapi([], "p")'], ['E1013: Argument 1: type mismatch, expected string but got list<any>', 'E1220: String or Number required for argument 1']) - v9.CheckDefAndScriptFailure(['term_setapi(1, [])'], ['E1013: Argument 2: type mismatch, expected string but got list<any>', 'E1174: String required for argument 2']) + v9.CheckSourceDefAndScriptFailure(['term_setapi([], "p")'], ['E1013: Argument 1: type mismatch, expected string but got list<any>', 'E1220: String or Number required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['term_setapi(1, [])'], ['E1013: Argument 2: type mismatch, expected string but got list<any>', 'E1174: String required for argument 2']) enddef def Test_term_setkill() CheckRunVimInTerminal - v9.CheckDefAndScriptFailure(['term_setkill([], "p")'], ['E1013: Argument 1: type mismatch, expected string but got list<any>', 'E1220: String or Number required for argument 1']) - v9.CheckDefAndScriptFailure(['term_setkill(1, [])'], ['E1013: Argument 2: type mismatch, expected string but got list<any>', 'E1174: String required for argument 2']) + v9.CheckSourceDefAndScriptFailure(['term_setkill([], "p")'], ['E1013: Argument 1: type mismatch, expected string but got list<any>', 'E1220: String or Number required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['term_setkill(1, [])'], ['E1013: Argument 2: type mismatch, expected string but got list<any>', 'E1174: String required for argument 2']) enddef def Test_term_setrestore() CheckRunVimInTerminal - v9.CheckDefAndScriptFailure(['term_setrestore([], "p")'], ['E1013: Argument 1: type mismatch, expected string but got list<any>', 'E1220: String or Number required for argument 1']) - v9.CheckDefAndScriptFailure(['term_setrestore(1, [])'], ['E1013: Argument 2: type mismatch, expected string but got list<any>', 'E1174: String required for argument 2']) + v9.CheckSourceDefAndScriptFailure(['term_setrestore([], "p")'], ['E1013: Argument 1: type mismatch, expected string but got list<any>', 'E1220: String or Number required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['term_setrestore(1, [])'], ['E1013: Argument 2: type mismatch, expected string but got list<any>', 'E1174: String required for argument 2']) enddef def Test_term_setsize() CheckRunVimInTerminal - v9.CheckDefAndScriptFailure(['term_setsize(1.1, 2, 3)'], ['E1013: Argument 1: type mismatch, expected string but got float', 'E1220: String or Number required for argument 1']) - v9.CheckDefAndScriptFailure(['term_setsize(1, "2", 3)'], ['E1013: Argument 2: type mismatch, expected number but got string', 'E1210: Number required for argument 2']) - v9.CheckDefAndScriptFailure(['term_setsize(1, 2, "3")'], ['E1013: Argument 3: type mismatch, expected number but got string', 'E1210: Number required for argument 3']) + v9.CheckSourceDefAndScriptFailure(['term_setsize(1.1, 2, 3)'], ['E1013: Argument 1: type mismatch, expected string but got float', 'E1220: String or Number required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['term_setsize(1, "2", 3)'], ['E1013: Argument 2: type mismatch, expected number but got string', 'E1210: Number required for argument 2']) + v9.CheckSourceDefAndScriptFailure(['term_setsize(1, 2, "3")'], ['E1013: Argument 3: type mismatch, expected number but got string', 'E1210: Number required for argument 3']) enddef def Test_term_start() @@ -4652,76 +4652,76 @@ def Test_term_start() winnr()->assert_equal(winnr) bwipe! endif - v9.CheckDefAndScriptFailure(['term_start({})'], ['E1013: Argument 1: type mismatch, expected string but got dict<any>', 'E1222: String or List required for argument 1']) - v9.CheckDefAndScriptFailure(['term_start([], [])'], ['E1013: Argument 2: type mismatch, expected dict<any> but got list<any>', 'E1206: Dictionary required for argument 2']) - v9.CheckDefAndScriptFailure(['term_start("", "")'], ['E1013: Argument 2: type mismatch, expected dict<any> but got string', 'E1206: Dictionary required for argument 2']) - v9.CheckDefExecAndScriptFailure(['term_start("")'], 'E474: Invalid argument') + v9.CheckSourceDefAndScriptFailure(['term_start({})'], ['E1013: Argument 1: type mismatch, expected string but got dict<any>', 'E1222: String or List required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['term_start([], [])'], ['E1013: Argument 2: type mismatch, expected dict<any> but got list<any>', 'E1206: Dictionary required for argument 2']) + v9.CheckSourceDefAndScriptFailure(['term_start("", "")'], ['E1013: Argument 2: type mismatch, expected dict<any> but got string', 'E1206: Dictionary required for argument 2']) + v9.CheckSourceDefExecAndScriptFailure(['term_start("")'], 'E474: Invalid argument') enddef def Test_term_wait() CheckRunVimInTerminal - v9.CheckDefAndScriptFailure(['term_wait(0z10, 1)'], ['E1013: Argument 1: type mismatch, expected string but got blob', 'E1220: String or Number required for argument 1']) - v9.CheckDefAndScriptFailure(['term_wait(1, "a")'], ['E1013: Argument 2: type mismatch, expected number but got string', 'E1210: Number required for argument 2']) + v9.CheckSourceDefAndScriptFailure(['term_wait(0z10, 1)'], ['E1013: Argument 1: type mismatch, expected string but got blob', 'E1220: String or Number required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['term_wait(1, "a")'], ['E1013: Argument 2: type mismatch, expected number but got string', 'E1210: Number required for argument 2']) enddef def Test_test_alloc_fail() - v9.CheckDefAndScriptFailure(['test_alloc_fail("a", 10, 20)'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1210: Number required for argument 1']) - v9.CheckDefAndScriptFailure(['test_alloc_fail(10, "b", 20)'], ['E1013: Argument 2: type mismatch, expected number but got string', 'E1210: Number required for argument 2']) - v9.CheckDefAndScriptFailure(['test_alloc_fail(10, 20, "c")'], ['E1013: Argument 3: type mismatch, expected number but got string', 'E1210: Number required for argument 3']) + v9.CheckSourceDefAndScriptFailure(['test_alloc_fail("a", 10, 20)'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1210: Number required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['test_alloc_fail(10, "b", 20)'], ['E1013: Argument 2: type mismatch, expected number but got string', 'E1210: Number required for argument 2']) + v9.CheckSourceDefAndScriptFailure(['test_alloc_fail(10, 20, "c")'], ['E1013: Argument 3: type mismatch, expected number but got string', 'E1210: Number required for argument 3']) enddef def Test_test_feedinput() - v9.CheckDefAndScriptFailure(['test_feedinput(test_void())'], ['E1013: Argument 1: type mismatch, expected string but got void', 'E1174: String required for argument 1']) - v9.CheckDefAndScriptFailure(['test_feedinput(["a"])'], ['E1013: Argument 1: type mismatch, expected string but got list<string>', 'E1174: String required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['test_feedinput(test_void())'], ['E1013: Argument 1: type mismatch, expected string but got void', 'E1174: String required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['test_feedinput(["a"])'], ['E1013: Argument 1: type mismatch, expected string but got list<string>', 'E1174: String required for argument 1']) enddef def Test_test_getvalue() - v9.CheckDefAndScriptFailure(['test_getvalue(1.1)'], ['E1013: Argument 1: type mismatch, expected string but got float', 'E1174: String required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['test_getvalue(1.1)'], ['E1013: Argument 1: type mismatch, expected string but got float', 'E1174: String required for argument 1']) enddef def Test_test_gui_event() CheckGui - v9.CheckDefAndScriptFailure(['test_gui_event([], {})'], ['E1013: Argument 1: type mismatch, expected string but got list<any>', 'E1174: String required for argument 1']) - v9.CheckDefAndScriptFailure(['test_gui_event("abc", 1)'], ['E1013: Argument 2: type mismatch, expected dict<any> but got number', 'E1206: Dictionary required for argument 2']) + v9.CheckSourceDefAndScriptFailure(['test_gui_event([], {})'], ['E1013: Argument 1: type mismatch, expected string but got list<any>', 'E1174: String required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['test_gui_event("abc", 1)'], ['E1013: Argument 2: type mismatch, expected dict<any> but got number', 'E1206: Dictionary required for argument 2']) enddef def Test_test_ignore_error() - v9.CheckDefAndScriptFailure(['test_ignore_error([])'], ['E1013: Argument 1: type mismatch, expected string but got list<any>', 'E1174: String required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['test_ignore_error([])'], ['E1013: Argument 1: type mismatch, expected string but got list<any>', 'E1174: String required for argument 1']) test_ignore_error('RESET') enddef def Test_test_option_not_set() - v9.CheckDefAndScriptFailure(['test_option_not_set([])'], ['E1013: Argument 1: type mismatch, expected string but got list<any>', 'E1174: String required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['test_option_not_set([])'], ['E1013: Argument 1: type mismatch, expected string but got list<any>', 'E1174: String required for argument 1']) enddef def Test_test_override() - v9.CheckDefAndScriptFailure(['test_override(1, 1)'], ['E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1']) - v9.CheckDefAndScriptFailure(['test_override("a", "x")'], ['E1013: Argument 2: type mismatch, expected number but got string', 'E1210: Number required for argument 2']) + v9.CheckSourceDefAndScriptFailure(['test_override(1, 1)'], ['E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['test_override("a", "x")'], ['E1013: Argument 2: type mismatch, expected number but got string', 'E1210: Number required for argument 2']) enddef def Test_test_setmouse() - v9.CheckDefAndScriptFailure(['test_setmouse("a", 10)'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1210: Number required for argument 1']) - v9.CheckDefAndScriptFailure(['test_setmouse(10, "b")'], ['E1013: Argument 2: type mismatch, expected number but got string', 'E1210: Number required for argument 2']) + v9.CheckSourceDefAndScriptFailure(['test_setmouse("a", 10)'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1210: Number required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['test_setmouse(10, "b")'], ['E1013: Argument 2: type mismatch, expected number but got string', 'E1210: Number required for argument 2']) enddef def Test_test_settime() - v9.CheckDefAndScriptFailure(['test_settime([1])'], ['E1013: Argument 1: type mismatch, expected number but got list<number>', 'E1210: Number required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['test_settime([1])'], ['E1013: Argument 1: type mismatch, expected number but got list<number>', 'E1210: Number required for argument 1']) enddef def Test_test_srand_seed() - v9.CheckDefAndScriptFailure(['test_srand_seed([1])'], ['E1013: Argument 1: type mismatch, expected number but got list<number>', 'E1210: Number required for argument 1']) - v9.CheckDefAndScriptFailure(['test_srand_seed("10")'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1210: Number required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['test_srand_seed([1])'], ['E1013: Argument 1: type mismatch, expected number but got list<number>', 'E1210: Number required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['test_srand_seed("10")'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1210: Number required for argument 1']) enddef def Test_timer_info() - v9.CheckDefAndScriptFailure(['timer_info("id")'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1210: Number required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['timer_info("id")'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1210: Number required for argument 1']) assert_equal([], timer_info(100)) assert_equal([], timer_info()->filter((_, t) => t.callback->string() !~ 'TestTimeout')) enddef def Test_timer_pause() - v9.CheckDefAndScriptFailure(['timer_pause("x", 1)'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1210: Number required for argument 1']) - v9.CheckDefAndScriptFailure(['timer_pause(1, "a")'], ['E1013: Argument 2: type mismatch, expected bool but got string', 'E1212: Bool required for argument 2']) + v9.CheckSourceDefAndScriptFailure(['timer_pause("x", 1)'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1210: Number required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['timer_pause(1, "a")'], ['E1013: Argument 2: type mismatch, expected bool but got string', 'E1212: Bool required for argument 2']) enddef def Test_timer_paused() @@ -4733,31 +4733,31 @@ def Test_timer_paused() enddef def Test_timer_start() - v9.CheckDefAndScriptFailure(['timer_start("a", "1")'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1210: Number required for argument 1']) - v9.CheckDefAndScriptFailure(['timer_start(1, "1", [1])'], ['E1013: Argument 3: type mismatch, expected dict<any> but got list<number>', 'E1206: Dictionary required for argument 3']) - v9.CheckDefExecAndScriptFailure(['timer_start(100, 0)'], 'E921:') - v9.CheckDefExecAndScriptFailure(['timer_start(100, "")'], 'E921:') + v9.CheckSourceDefAndScriptFailure(['timer_start("a", "1")'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1210: Number required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['timer_start(1, "1", [1])'], ['E1013: Argument 3: type mismatch, expected dict<any> but got list<number>', 'E1206: Dictionary required for argument 3']) + v9.CheckSourceDefExecAndScriptFailure(['timer_start(100, 0)'], 'E921:') + v9.CheckSourceDefExecAndScriptFailure(['timer_start(100, "")'], 'E921:') enddef def Test_timer_stop() - v9.CheckDefAndScriptFailure(['timer_stop("x")'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1210: Number required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['timer_stop("x")'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1210: Number required for argument 1']) assert_equal(0, timer_stop(100)) enddef def Test_tolower() - v9.CheckDefAndScriptFailure(['tolower(1)'], ['E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['tolower(1)'], ['E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1']) tolower('')->assert_equal('') enddef def Test_toupper() - v9.CheckDefAndScriptFailure(['toupper(1)'], ['E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['toupper(1)'], ['E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1']) toupper('')->assert_equal('') enddef def Test_tr() - v9.CheckDefAndScriptFailure(['tr(1, "a", "b")'], ['E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1']) - v9.CheckDefAndScriptFailure(['tr("a", 1, "b")'], ['E1013: Argument 2: type mismatch, expected string but got number', 'E1174: String required for argument 2']) - v9.CheckDefAndScriptFailure(['tr("a", "a", 1)'], ['E1013: Argument 3: type mismatch, expected string but got number', 'E1174: String required for argument 3']) + v9.CheckSourceDefAndScriptFailure(['tr(1, "a", "b")'], ['E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['tr("a", 1, "b")'], ['E1013: Argument 2: type mismatch, expected string but got number', 'E1174: String required for argument 2']) + v9.CheckSourceDefAndScriptFailure(['tr("a", "a", 1)'], ['E1013: Argument 3: type mismatch, expected string but got number', 'E1174: String required for argument 3']) tr('', '', '')->assert_equal('') tr('ab', '', '')->assert_equal('ab') assert_fails("tr('ab', 'ab', '')", 'E475:') @@ -4765,9 +4765,9 @@ def Test_tr() enddef def Test_trim() - v9.CheckDefAndScriptFailure(['trim(["a"])'], ['E1013: Argument 1: type mismatch, expected string but got list<string>', 'E1174: String required for argument 1']) - v9.CheckDefAndScriptFailure(['trim("a", ["b"])'], ['E1013: Argument 2: type mismatch, expected string but got list<string>', 'E1174: String required for argument 2']) - v9.CheckDefAndScriptFailure(['trim("a", "b", "c")'], ['E1013: Argument 3: type mismatch, expected number but got string', 'E1210: Number required for argument 3']) + v9.CheckSourceDefAndScriptFailure(['trim(["a"])'], ['E1013: Argument 1: type mismatch, expected string but got list<string>', 'E1174: String required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['trim("a", ["b"])'], ['E1013: Argument 2: type mismatch, expected string but got list<string>', 'E1174: String required for argument 2']) + v9.CheckSourceDefAndScriptFailure(['trim("a", "b", "c")'], ['E1013: Argument 3: type mismatch, expected number but got string', 'E1210: Number required for argument 3']) trim('')->assert_equal('') trim('', '')->assert_equal('') enddef @@ -4783,26 +4783,30 @@ def Test_typename() if has('channel') assert_equal('channel', test_null_channel()->typename()) endif + assert_equal('class<Unknown>', typename(null_class)) + assert_equal('object<Unknown>', typename(null_object)) + var l: list<func(list<number>): number> = [function('min')] + assert_equal('list<func(list<number>): number>', typename(l)) enddef def Test_undofile() - v9.CheckDefAndScriptFailure(['undofile(10)'], ['E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['undofile(10)'], ['E1013: Argument 1: type mismatch, expected string but got number', 'E1174: String required for argument 1']) assert_equal('.abc.un~', fnamemodify(undofile('abc'), ':t')) undofile('')->assert_equal('') enddef def Test_uniq() - v9.CheckDefAndScriptFailure(['uniq("a")'], ['E1013: Argument 1: type mismatch, expected list<any> but got string', 'E1211: List required for argument 1']) - v9.CheckDefAndScriptFailure(['uniq([1], "", [1])'], ['E1013: Argument 3: type mismatch, expected dict<any> but got list<number>', 'E1206: Dictionary required for argument 3']) + v9.CheckSourceDefAndScriptFailure(['uniq("a")'], ['E1013: Argument 1: type mismatch, expected list<any> but got string', 'E1211: List required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['uniq([1], "", [1])'], ['E1013: Argument 3: type mismatch, expected dict<any> but got list<number>', 'E1206: Dictionary required for argument 3']) - v9.CheckDefFailure(['var l: list<number> = uniq(["a", "b"])'], 'E1012: Type mismatch; expected list<number> but got list<string>') + v9.CheckSourceDefFailure(['var l: list<number> = uniq(["a", "b"])'], 'E1012: Type mismatch; expected list<number> but got list<string>') enddef def Test_utf16idx() - v9.CheckDefAndScriptFailure(['utf16idx(0z10, 1)'], ['E1013: Argument 1: type mismatch, expected string but got blob', 'E1174: String required for argument 1']) - v9.CheckDefAndScriptFailure(['utf16idx("a", "b")'], ['E1013: Argument 2: type mismatch, expected number but got string', 'E1210: Number required for argument 2']) - v9.CheckDefAndScriptFailure(['utf16idx("a", 1, "")'], ['E1013: Argument 3: type mismatch, expected bool but got string', 'E1212: Bool required for argument 3']) - v9.CheckDefAndScriptFailure(['utf16idx("a", 1, 0, "")'], ['E1013: Argument 4: type mismatch, expected bool but got string', 'E1212: Bool required for argument 4']) + v9.CheckSourceDefAndScriptFailure(['utf16idx(0z10, 1)'], ['E1013: Argument 1: type mismatch, expected string but got blob', 'E1174: String required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['utf16idx("a", "b")'], ['E1013: Argument 2: type mismatch, expected number but got string', 'E1210: Number required for argument 2']) + v9.CheckSourceDefAndScriptFailure(['utf16idx("a", 1, "")'], ['E1013: Argument 3: type mismatch, expected bool but got string', 'E1212: Bool required for argument 3']) + v9.CheckSourceDefAndScriptFailure(['utf16idx("a", 1, 0, "")'], ['E1013: Argument 4: type mismatch, expected bool but got string', 'E1212: Bool required for argument 4']) utf16idx('', 0)->assert_equal(0) utf16idx('', 1)->assert_equal(-1) enddef @@ -4812,11 +4816,11 @@ def Test_uniq_const() const l = [1, 2, 3, 4] uniq(l) END - v9.CheckDefFailure(lines, 'E1307: Argument 1: Trying to modify a const list<number>') + v9.CheckSourceDefFailure(lines, 'E1307: Argument 1: Trying to modify a const list<number>') enddef def Test_values() - v9.CheckDefAndScriptFailure(['values([])'], ['E1013: Argument 1: type mismatch, expected dict<any> but got list<any>', 'E1206: Dictionary required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['values([])'], ['E1013: Argument 1: type mismatch, expected dict<any> but got list<any>', 'E1206: Dictionary required for argument 1']) assert_equal([], {}->values()) assert_equal(['sun'], {star: 'sun'}->values()) @@ -4843,20 +4847,20 @@ def Test_values() Process(D) END - v9.CheckScriptSuccess(lines) + v9.CheckSourceScriptSuccess(lines) enddef def Test_virtcol() - v9.CheckDefAndScriptFailure(['virtcol(1.1)'], [ + v9.CheckSourceDefAndScriptFailure(['virtcol(1.1)'], [ 'E1013: Argument 1: type mismatch, expected string but got float', 'E1222: String or List required for argument 1']) - v9.CheckDefAndScriptFailure(['virtcol(".", "a")'], [ + v9.CheckSourceDefAndScriptFailure(['virtcol(".", "a")'], [ 'E1013: Argument 2: type mismatch, expected bool but got string', 'E1212: Bool required for argument 2']) - v9.CheckDefAndScriptFailure(['virtcol(".", v:true, [])'], [ + v9.CheckSourceDefAndScriptFailure(['virtcol(".", v:true, [])'], [ 'E1013: Argument 3: type mismatch, expected number but got list', 'E1210: Number required for argument 3']) - v9.CheckDefExecAndScriptFailure(['virtcol("")'], + v9.CheckSourceDefExecAndScriptFailure(['virtcol("")'], 'E1209: Invalid value for a line number') new setline(1, ['abcde和平fgh']) @@ -4872,8 +4876,8 @@ def Test_virtcol() enddef def Test_visualmode() - v9.CheckDefAndScriptFailure(['visualmode("1")'], ['E1013: Argument 1: type mismatch, expected bool but got string', 'E1212: Bool required for argument 1']) - v9.CheckDefAndScriptFailure(['visualmode(2)'], ['E1013: Argument 1: type mismatch, expected bool but got number', 'E1212: Bool required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['visualmode("1")'], ['E1013: Argument 1: type mismatch, expected bool but got string', 'E1212: Bool required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['visualmode(2)'], ['E1013: Argument 1: type mismatch, expected bool but got number', 'E1212: Bool required for argument 1']) enddef def Test_win_execute() @@ -4881,29 +4885,29 @@ def Test_win_execute() assert_equal("\n" .. winnr(), 'echo winnr()'->win_execute(win_getid())) assert_equal("\n" .. winnr(), win_execute(win_getid(), 'echo winnr()', 'silent')) assert_equal('', win_execute(342343, 'echo winnr()')) - v9.CheckDefAndScriptFailure(['win_execute("a", "b", "c")'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1210: Number required for argument 1']) - v9.CheckDefAndScriptFailure(['win_execute(1, 2, "c")'], ['E1013: Argument 2: type mismatch, expected string but got number', 'E1222: String or List required for argument 2']) - v9.CheckDefAndScriptFailure(['win_execute(1, "b", 3)'], ['E1013: Argument 3: type mismatch, expected string but got number', 'E1174: String required for argument 3']) + v9.CheckSourceDefAndScriptFailure(['win_execute("a", "b", "c")'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1210: Number required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['win_execute(1, 2, "c")'], ['E1013: Argument 2: type mismatch, expected string but got number', 'E1222: String or List required for argument 2']) + v9.CheckSourceDefAndScriptFailure(['win_execute(1, "b", 3)'], ['E1013: Argument 3: type mismatch, expected string but got number', 'E1174: String required for argument 3']) enddef def Test_win_findbuf() - v9.CheckDefAndScriptFailure(['win_findbuf("a")'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1210: Number required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['win_findbuf("a")'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1210: Number required for argument 1']) assert_equal([], win_findbuf(1000)) assert_equal([win_getid()], win_findbuf(bufnr(''))) enddef def Test_win_getid() - v9.CheckDefAndScriptFailure(['win_getid(".")'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1210: Number required for argument 1']) - v9.CheckDefAndScriptFailure(['win_getid(1, ".")'], ['E1013: Argument 2: type mismatch, expected number but got string', 'E1210: Number required for argument 2']) + v9.CheckSourceDefAndScriptFailure(['win_getid(".")'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1210: Number required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['win_getid(1, ".")'], ['E1013: Argument 2: type mismatch, expected number but got string', 'E1210: Number required for argument 2']) assert_equal(win_getid(), win_getid(1, 1)) enddef def Test_win_gettype() - v9.CheckDefAndScriptFailure(['win_gettype("x")'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1210: Number required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['win_gettype("x")'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1210: Number required for argument 1']) enddef def Test_win_gotoid() - v9.CheckDefAndScriptFailure(['win_gotoid("x")'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1210: Number required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['win_gotoid("x")'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1210: Number required for argument 1']) enddef func Test_win_gotoid_in_mapping() @@ -4948,43 +4952,43 @@ func Test_win_gotoid_in_mapping() endfunc def Test_win_id2tabwin() - v9.CheckDefAndScriptFailure(['win_id2tabwin("x")'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1210: Number required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['win_id2tabwin("x")'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1210: Number required for argument 1']) enddef def Test_win_id2win() - v9.CheckDefAndScriptFailure(['win_id2win("x")'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1210: Number required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['win_id2win("x")'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1210: Number required for argument 1']) enddef def Test_win_screenpos() assert_equal(['x', 'x'], win_screenpos(1)->map((_, _) => 'x')) - v9.CheckDefAndScriptFailure(['win_screenpos("x")'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1210: Number required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['win_screenpos("x")'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1210: Number required for argument 1']) enddef def Test_win_splitmove() split win_splitmove(1, 2, {vertical: true, rightbelow: true}) close - v9.CheckDefAndScriptFailure(['win_splitmove("a", 2)'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1210: Number required for argument 1']) - v9.CheckDefAndScriptFailure(['win_splitmove(1, "b")'], ['E1013: Argument 2: type mismatch, expected number but got string', 'E1210: Number required for argument 2']) - v9.CheckDefAndScriptFailure(['win_splitmove(1, 2, [])'], ['E1013: Argument 3: type mismatch, expected dict<any> but got list<any>', 'E1206: Dictionary required for argument 3']) + v9.CheckSourceDefAndScriptFailure(['win_splitmove("a", 2)'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1210: Number required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['win_splitmove(1, "b")'], ['E1013: Argument 2: type mismatch, expected number but got string', 'E1210: Number required for argument 2']) + v9.CheckSourceDefAndScriptFailure(['win_splitmove(1, 2, [])'], ['E1013: Argument 3: type mismatch, expected dict<any> but got list<any>', 'E1206: Dictionary required for argument 3']) enddef def Test_winbufnr() - v9.CheckDefAndScriptFailure(['winbufnr("x")'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1210: Number required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['winbufnr("x")'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1210: Number required for argument 1']) enddef def Test_winheight() - v9.CheckDefAndScriptFailure(['winheight("x")'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1210: Number required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['winheight("x")'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1210: Number required for argument 1']) enddef def Test_winlayout() - v9.CheckDefAndScriptFailure(['winlayout("x")'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1210: Number required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['winlayout("x")'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1210: Number required for argument 1']) enddef def Test_winnr() - v9.CheckDefAndScriptFailure(['winnr([])'], ['E1013: Argument 1: type mismatch, expected string but got list<any>', 'E1174: String required for argument 1']) - v9.CheckDefExecAndScriptFailure(['winnr("")'], 'E15: Invalid expression') + v9.CheckSourceDefAndScriptFailure(['winnr([])'], ['E1013: Argument 1: type mismatch, expected string but got list<any>', 'E1174: String required for argument 1']) + v9.CheckSourceDefExecAndScriptFailure(['winnr("")'], 'E15: Invalid expression') assert_equal(1, winnr()) assert_equal(1, winnr('$')) enddef @@ -4999,7 +5003,7 @@ def Test_winrestcmd() enddef def Test_winrestview() - v9.CheckDefAndScriptFailure(['winrestview([])'], ['E1013: Argument 1: type mismatch, expected dict<any> but got list<any>', 'E1206: Dictionary required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['winrestview([])'], ['E1013: Argument 1: type mismatch, expected dict<any> but got list<any>', 'E1206: Dictionary required for argument 1']) :%d _ setline(1, 'Hello World') winrestview({lnum: 1, col: 6}) @@ -5012,20 +5016,20 @@ def Test_winsaveview() var lines =<< trim END var view: list<number> = winsaveview() END - v9.CheckDefAndScriptFailure(lines, 'E1012: Type mismatch; expected list<number> but got dict<number>', 1) + v9.CheckSourceDefAndScriptFailure(lines, 'E1012: Type mismatch; expected list<number> but got dict<number>', 1) enddef def Test_winwidth() - v9.CheckDefAndScriptFailure(['winwidth("x")'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1210: Number required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['winwidth("x")'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1210: Number required for argument 1']) enddef def Test_xor() - v9.CheckDefAndScriptFailure(['xor("x", 0x2)'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1210: Number required for argument 1']) - v9.CheckDefAndScriptFailure(['xor(0x1, "x")'], ['E1013: Argument 2: type mismatch, expected number but got string', 'E1210: Number required for argument 2']) + v9.CheckSourceDefAndScriptFailure(['xor("x", 0x2)'], ['E1013: Argument 1: type mismatch, expected number but got string', 'E1210: Number required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['xor(0x1, "x")'], ['E1013: Argument 2: type mismatch, expected number but got string', 'E1210: Number required for argument 2']) enddef def Test_writefile() - v9.CheckDefExecAndScriptFailure(['writefile(["a"], "")'], 'E482: Can''t create file <empty>') + v9.CheckSourceDefExecAndScriptFailure(['writefile(["a"], "")'], 'E482: Can''t create file <empty>') enddef def Test_passing_type_to_builtin() @@ -5045,7 +5049,7 @@ def Test_passing_type_to_builtin() x = string(T) x = instanceof(C.new(), U, C) END - v9.CheckScriptSuccess(lines) + v9.CheckSourceScriptSuccess(lines) # check argument to add at script level # Note: add() is special cased in compile_call in vim9expr @@ -5055,7 +5059,7 @@ def Test_passing_type_to_builtin() endclass add([], C) END - v9.CheckScriptFailure(lines, 'E1405: Class "C" cannot be used as a value') + v9.CheckSourceScriptFailure(lines, 'E1405: Class "C" cannot be used as a value') # check argument to add in :def lines =<< trim END @@ -5067,7 +5071,7 @@ def Test_passing_type_to_builtin() enddef F() END - v9.CheckScriptFailure(lines, 'E1405: Class "C" cannot be used as a value') + v9.CheckSourceScriptFailure(lines, 'E1405: Class "C" cannot be used as a value') # check member call argument to add at script level lines =<< trim END @@ -5076,7 +5080,7 @@ def Test_passing_type_to_builtin() endclass []->add(C) END - v9.CheckScriptFailure(lines, 'E1405: Class "C" cannot be used as a value') + v9.CheckSourceScriptFailure(lines, 'E1405: Class "C" cannot be used as a value') # check member call argument to add in :def lines =<< trim END @@ -5088,7 +5092,7 @@ def Test_passing_type_to_builtin() enddef F() END - v9.CheckScriptFailure(lines, 'E1405: Class "C" cannot be used as a value') + v9.CheckSourceScriptFailure(lines, 'E1405: Class "C" cannot be used as a value') # Try "empty()" builtin # check argument to empty at script level @@ -5098,7 +5102,7 @@ def Test_passing_type_to_builtin() endclass empty(C) END - v9.CheckScriptFailure(lines, 'E1405: Class "C" cannot be used as a value') + v9.CheckSourceScriptFailure(lines, 'E1405: Class "C" cannot be used as a value') # check argument to empty in :def lines =<< trim END @@ -5110,7 +5114,7 @@ def Test_passing_type_to_builtin() enddef F() END - v9.CheckScriptFailure(lines, 'E1405: Class "C" cannot be used as a value') + v9.CheckSourceScriptFailure(lines, 'E1405: Class "C" cannot be used as a value') # check member call argument to empty at script level lines =<< trim END @@ -5119,7 +5123,7 @@ def Test_passing_type_to_builtin() endclass C->empty() END - v9.CheckScriptFailure(lines, 'E1405: Class "C" cannot be used as a value') + v9.CheckSourceScriptFailure(lines, 'E1405: Class "C" cannot be used as a value') # check member call argument to empty in :def lines =<< trim END @@ -5131,7 +5135,7 @@ def Test_passing_type_to_builtin() enddef F() END - v9.CheckScriptFailure(lines, 'E1405: Class "C" cannot be used as a value') + v9.CheckSourceScriptFailure(lines, 'E1405: Class "C" cannot be used as a value') # Try "abs()" builtin # check argument to abs at script level @@ -5141,7 +5145,7 @@ def Test_passing_type_to_builtin() endclass abs(C) END - v9.CheckScriptFailure(lines, 'E1405: Class "C" cannot be used as a value') + v9.CheckSourceScriptFailure(lines, 'E1405: Class "C" cannot be used as a value') # check argument to abs in :def lines =<< trim END @@ -5153,7 +5157,7 @@ def Test_passing_type_to_builtin() enddef F() END - v9.CheckScriptFailure(lines, 'E1405: Class "C" cannot be used as a value') + v9.CheckSourceScriptFailure(lines, 'E1405: Class "C" cannot be used as a value') # check member call argument to abs at script level lines =<< trim END @@ -5162,7 +5166,7 @@ def Test_passing_type_to_builtin() endclass C->abs() END - v9.CheckScriptFailure(lines, 'E1405: Class "C" cannot be used as a value') + v9.CheckSourceScriptFailure(lines, 'E1405: Class "C" cannot be used as a value') # check member call argument to abs in :def lines =<< trim END @@ -5174,15 +5178,15 @@ def Test_passing_type_to_builtin() enddef F() END - v9.CheckScriptFailure(lines, 'E1405: Class "C" cannot be used as a value') + v9.CheckSourceScriptFailure(lines, 'E1405: Class "C" cannot be used as a value') enddef def Test_getregion() assert_equal(['x'], getregion(getpos('.'), getpos('.'))->map((_, _) => 'x')) - v9.CheckDefAndScriptFailure(['getregion(10, getpos("."))'], ['E1013: Argument 1: type mismatch, expected list<any> but got number', 'E1211: List required for argument 1']) + v9.CheckSourceDefAndScriptFailure(['getregion(10, getpos("."))'], ['E1013: Argument 1: type mismatch, expected list<any> but got number', 'E1211: List required for argument 1']) assert_equal([''], getregion(getpos('.'), getpos('.'))) - v9.CheckDefExecFailure(['getregion(getpos("a"), getpos("."))'], 'E1209:') + v9.CheckSourceDefExecFailure(['getregion(getpos("a"), getpos("."))'], 'E1209:') enddef " vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker diff --git a/src/testdir/test_vim9_class.vim b/src/testdir/test_vim9_class.vim index d6c55bf..5957f57 100644 --- a/src/testdir/test_vim9_class.vim +++ b/src/testdir/test_vim9_class.vim @@ -400,7 +400,7 @@ def Test_class_def_method() enddef endclass END - v9.CheckSourceFailure(lines, 'E1331: Public must be followed by "var" or "static"', 3) + v9.CheckSourceFailure(lines, 'E1388: public keyword not supported for a method', 3) # Using the "public" keyword when defining a class method lines =<< trim END @@ -410,7 +410,7 @@ def Test_class_def_method() enddef endclass END - v9.CheckSourceFailure(lines, 'E1388: Public keyword not supported for a method', 3) + v9.CheckSourceFailure(lines, 'E1388: public keyword not supported for a method', 3) # Using the "public" keyword when defining an object protected method lines =<< trim END @@ -420,7 +420,7 @@ def Test_class_def_method() enddef endclass END - v9.CheckSourceFailure(lines, 'E1331: Public must be followed by "var" or "static"', 3) + v9.CheckSourceFailure(lines, 'E1388: public keyword not supported for a method', 3) # Using the "public" keyword when defining a class protected method lines =<< trim END @@ -430,7 +430,7 @@ def Test_class_def_method() enddef endclass END - v9.CheckSourceFailure(lines, 'E1388: Public keyword not supported for a method', 3) + v9.CheckSourceFailure(lines, 'E1388: public keyword not supported for a method', 3) # Using a "def" keyword without an object method name lines =<< trim END @@ -1191,7 +1191,7 @@ def Test_instance_variable_access() public var _val = 10 endclass END - v9.CheckSourceFailure(lines, 'E1332: Public variable name cannot start with underscore: public var _val = 10', 3) + v9.CheckSourceFailure(lines, 'E1332: public variable name cannot start with underscore: public var _val = 10', 3) lines =<< trim END vim9script @@ -1287,7 +1287,7 @@ def Test_instance_variable_access() public val = 1 endclass END - v9.CheckSourceFailure(lines, 'E1331: Public must be followed by "var" or "static"', 3) + v9.CheckSourceFailure(lines, 'E1331: public must be followed by "var" or "static"', 3) # Modify a instance variable using the class name in the script context lines =<< trim END @@ -2275,6 +2275,18 @@ def Test_interface_basics() v9.CheckScriptSuccess(lines) enddef +" Test for using string() with an interface +def Test_interface_to_string() + var lines =<< trim END + vim9script + interface Intf + def Method(nr: number) + endinterface + assert_equal("interface Intf", string(Intf)) + END + v9.CheckSourceSuccess(lines) +enddef + def Test_class_implements_interface() var lines =<< trim END vim9script @@ -3109,6 +3121,28 @@ def Test_class_import() v9.CheckScriptSuccess(lines) enddef +" Test for importing a class into a legacy script and calling the class method +def Test_class_method_from_legacy_script() + var lines =<< trim END + vim9script + export class A + static var name: string = 'a' + static def SetName(n: string) + name = n + enddef + endclass + END + writefile(lines, 'Xvim9export.vim', 'D') + + lines =<< trim END + import './Xvim9export.vim' as vim9 + + call s:vim9.A.SetName('b') + call assert_equal('b', s:vim9.A.name) + END + v9.CheckScriptSuccess(lines) +enddef + " Test for implementing an imported interface def Test_implement_imported_interface() var lines =<< trim END @@ -3208,6 +3242,23 @@ def Test_abstract_class() endclass END v9.CheckSourceFailure(lines, 'E1359: Cannot define a "new" method in an abstract class', 4) + + # extending an abstract class with class methods and variables + lines =<< trim END + vim9script + abstract class A + static var s: string = 'vim' + static def Fn(): list<number> + return [10] + enddef + endclass + class B extends A + endclass + var b = B.new() + assert_equal('vim', A.s) + assert_equal([10], A.Fn()) + END + v9.CheckScriptSuccess(lines) enddef def Test_closure_in_class() @@ -3729,7 +3780,7 @@ def Test_stack_expansion_with_methods() endclass def F0() - assert_match('<SNR>\d\+_F\[1\]\.\.C\.M1\[1\]\.\.<SNR>\d\+_F0\[1\]$', expand('<stack>')) + assert_match('<SNR>\d\+_F\[1\]\.\.<SNR>\d\+_C\.M1\[1\]\.\.<SNR>\d\+_F0\[1\]$', expand('<stack>')) enddef def F() @@ -6486,7 +6537,7 @@ def Test_interface_with_unsupported_members() public static var num: number endinterface END - v9.CheckSourceFailure(lines, 'E1387: Public variable not supported in an interface', 3) + v9.CheckSourceFailure(lines, 'E1387: public variable not supported in an interface', 3) lines =<< trim END vim9script @@ -6494,7 +6545,7 @@ def Test_interface_with_unsupported_members() public static var num: number endinterface END - v9.CheckSourceFailure(lines, 'E1387: Public variable not supported in an interface', 3) + v9.CheckSourceFailure(lines, 'E1387: public variable not supported in an interface', 3) lines =<< trim END vim9script @@ -10391,6 +10442,23 @@ def Test_compound_op_in_objmethod_lambda() v9.CheckScriptSuccess(lines) enddef +" Test for using test_refcount() with a class and an object +def Test_class_object_refcount() + var lines =<< trim END + vim9script + class A + endclass + var a: A = A.new() + assert_equal(2, test_refcount(A)) + assert_equal(1, test_refcount(a)) + var b = a + assert_equal(2, test_refcount(A)) + assert_equal(2, test_refcount(a)) + assert_equal(2, test_refcount(b)) + END + v9.CheckScriptSuccess(lines) +enddef + " call a lambda function in one object from another object def Test_lambda_invocation_across_classes() var lines =<< trim END @@ -10420,4 +10488,154 @@ def Test_lambda_invocation_across_classes() v9.CheckScriptSuccess(lines) enddef +" Test for using a class member which is an object of the current class +def Test_current_class_object_class_member() + var lines =<< trim END + vim9script + class A + public static var obj1: A = A.new(10) + var n: number + endclass + defcompile + assert_equal(10, A.obj1.n) + END + v9.CheckScriptSuccess(lines) +enddef + +" Test for updating a base class variable from a base class method without the +" class name. This used to crash Vim (Github issue #14352). +def Test_use_base_class_variable_from_base_class_method() + var lines =<< trim END + vim9script + + class DictKeyClass + static var _obj_id_count = 1 + def _GenerateKey() + _obj_id_count += 1 + enddef + static def GetIdCount(): number + return _obj_id_count + enddef + endclass + + class C extends DictKeyClass + def F() + this._GenerateKey() + enddef + endclass + + C.new().F() + assert_equal(2, DictKeyClass.GetIdCount()) + END + v9.CheckScriptSuccess(lines) +enddef + +" Test for accessing protected funcref object and class variables +def Test_protected_funcref() + # protected funcref object variable + var lines =<< trim END + vim9script + class Test1 + const _Id: func(any): any = (v) => v + endclass + var n = Test1.new()._Id(1) + END + v9.CheckScriptFailure(lines, 'E1333: Cannot access protected variable "_Id" in class "Test1"', 5) + + # protected funcref class variable + lines =<< trim END + vim9script + class Test2 + static const _Id: func(any): any = (v) => v + endclass + var n = Test2._Id(2) + END + v9.CheckScriptFailure(lines, 'E1333: Cannot access protected variable "_Id" in class "Test2"', 5) +enddef + +" Test for using lambda block in classes +def Test_lambda_block_in_class() + # This used to crash Vim + var lines =<< trim END + vim9script + class IdClass1 + const Id: func(number): number = (num: number): number => { + # Return a ID + return num * 10 + } + endclass + var id = IdClass1.new() + assert_equal(20, id.Id(2)) + END + v9.CheckScriptSuccess(lines) + + # This used to crash Vim + lines =<< trim END + vim9script + class IdClass2 + static const Id: func(number): number = (num: number): number => { + # Return a ID + return num * 2 + } + endclass + assert_equal(16, IdClass2.Id(8)) + END + v9.CheckScriptSuccess(lines) +enddef + +" Test for defcompiling an abstract method +def Test_abstract_method_defcompile() + # Compile an abstract class with abstract object methods + var lines =<< trim END + vim9script + abstract class A + abstract def Foo(): string + abstract def Bar(): list<string> + endclass + defcompile + END + v9.CheckScriptSuccess(lines) + + # Compile a concrete object method in an abstract class + lines =<< trim END + vim9script + abstract class A + abstract def Foo(): string + abstract def Bar(): list<string> + def Baz(): string + pass + enddef + endclass + defcompile + END + v9.CheckScriptFailure(lines, 'E476: Invalid command: pass', 1) + + # Compile a concrete class method in an abstract class + lines =<< trim END + vim9script + abstract class A + abstract def Foo(): string + abstract def Bar(): list<string> + static def Baz(): string + pass + enddef + endclass + defcompile + END + v9.CheckScriptFailure(lines, 'E476: Invalid command: pass', 1) +enddef + +" Test for defining a class in a function +def Test_class_definition_in_a_function() + var lines =<< trim END + vim9script + def Foo() + class A + endclass + enddef + defcompile + END + v9.CheckScriptFailure(lines, 'E1429: Class can only be used in a script', 1) +enddef + " vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker diff --git a/src/testdir/test_vim9_disassemble.vim b/src/testdir/test_vim9_disassemble.vim index 1daef22..c74cce4 100644 --- a/src/testdir/test_vim9_disassemble.vim +++ b/src/testdir/test_vim9_disassemble.vim @@ -381,6 +381,34 @@ def Test_disassemble_import_autoload() v9.CheckScriptSuccess(lines) enddef +def Test_disassemble_import_autoload_autoload() + mkdir('Xauto_auto/autoload', 'pR') + var lines =<< trim END + vim9script + export const val = 11 + END + writefile(lines, 'Xauto_auto/autoload/Xauto_vars_f1.vim') + + lines =<< trim END + vim9script + + import autoload './Xauto_auto/autoload/Xauto_vars_f1.vim' as f1 + def F() + f1.val = 13 + enddef + var res = execute('disass F') + + assert_match('<SNR>\d*_F.*' .. + 'f1.val = 13\_s*' .. + '\d PUSHNR 13\_s*' .. + '\d SOURCE .*/Xauto_auto/autoload/Xauto_vars_f1.vim\_s*' .. + '\d STOREEXPORT val in .*/Xauto_auto/autoload/Xauto_vars_f1.vim\_s*' .. + '\d RETURN void', + res) + END + v9.CheckScriptSuccess(lines) +enddef + def s:ScriptFuncStore() var localnr = 1 localnr = 2 @@ -1030,7 +1058,7 @@ def Test_disassemble_closure_in_loop() 'endif\_s*' .. 'g:Ref = () => ii\_s*' .. - '\d\+ FUNCREF <lambda>4 vars $3-$3\_s*' .. + '\d\+ FUNCREF <lambda>\d\+ vars $3-$3\_s*' .. '\d\+ STOREG g:Ref\_s*' .. 'continue\_s*' .. diff --git a/src/testdir/test_vim9_enum.vim b/src/testdir/test_vim9_enum.vim new file mode 100644 index 0000000..274b556 --- /dev/null +++ b/src/testdir/test_vim9_enum.vim @@ -0,0 +1,1537 @@ +" Test Vim9 enums + +source check.vim +import './vim9.vim' as v9 + +" Test for parsing an enum definition +def Test_enum_parse() + # enum supported only in a Vim9 script + var lines =<< trim END + enum Foo + endenum + END + v9.CheckSourceFailure(lines, 'E1414: Enum can only be defined in Vim9 script', 1) + + # First character in an enum name should be capitalized. + lines =<< trim END + vim9script + enum foo + endenum + END + v9.CheckSourceFailure(lines, 'E1415: Enum name must start with an uppercase letter: foo', 2) + + # Only alphanumeric characters are supported in an enum name + lines =<< trim END + vim9script + enum Foo@bar + endenum + END + v9.CheckSourceFailure(lines, 'E1315: White space required after name: Foo@bar', 2) + + # Unsupported keyword (instead of enum) + lines =<< trim END + vim9script + noenum Something + endenum + END + v9.CheckSourceFailure(lines, 'E492: Not an editor command: noenum Something', 2) + + # Only the complete word "enum" should be recognized + lines =<< trim END + vim9script + enums Something + endenum + END + v9.CheckSourceFailure(lines, 'E492: Not an editor command: enums Something', 2) + + # The complete "endenum" should be specified. + lines =<< trim END + vim9script + enum Something + enden + END + v9.CheckSourceFailure(lines, 'E1065: Command cannot be shortened: enden', 3) + + # Only the complete word "endenum" should be recognized + lines =<< trim END + vim9script + enum Something + endenums + END + v9.CheckSourceFailure(lines, 'E1420: Missing :endenum', 4) + + # all lower case should be used for "enum" + lines =<< trim END + vim9script + Enum Something + endenum + END + v9.CheckSourceFailure(lines, 'E492: Not an editor command: Enum Something', 2) + + # all lower case should be used for "endenum" + lines =<< trim END + vim9script + enum Something + Endenum + END + v9.CheckSourceFailure(lines, 'E1420: Missing :endenum', 4) + + # Additional words after "endenum" + lines =<< trim END + vim9script + enum Something + endenum school's out + END + v9.CheckSourceFailure(lines, "E488: Trailing characters: school's out", 3) + + # Additional commands after "endenum" + lines =<< trim END + vim9script + enum Something + endenum | echo 'done' + END + v9.CheckSourceFailure(lines, "E488: Trailing characters: | echo 'done'", 3) + + # Try to define enum in a single command + lines =<< trim END + vim9script + enum Something | endenum + END + v9.CheckSourceFailure(lines, 'E1420: Missing :endenum', 3) + + # Try to define an enum with the same name as an existing variable + lines =<< trim END + vim9script + var Something: list<number> = [1] + enum Something + endenum + END + v9.CheckSourceFailure(lines, 'E1041: Redefining script item: "Something"', 3) + + # Unsupported special character following enum name + lines =<< trim END + vim9script + enum Foo + first, + second : 20 + endenum + END + v9.CheckSourceFailure(lines, 'E1123: Missing comma before argument: : 20', 4) + + # Try initializing an enum item with a number + lines =<< trim END + vim9script + enum Foo + first, + second = 2 + endenum + END + v9.CheckSourceFailure(lines, 'E1123: Missing comma before argument: = 2', 4) + + # Try initializing an enum item with a String + lines =<< trim END + vim9script + enum Foo + first, + second = 'second' + endenum + defcompile + END + v9.CheckSourceFailure(lines, "E1123: Missing comma before argument: = 'second'", 4) + + # Try initializing an enum item with a List + lines =<< trim END + vim9script + enum Foo + first, + second = [] + endenum + END + v9.CheckSourceFailure(lines, 'E1123: Missing comma before argument: = []', 4) + + # Use a colon after name + lines =<< trim END + vim9script + enum Foo + + # first + first: + second + endenum + END + v9.CheckSourceFailure(lines, 'E1123: Missing comma before argument: :', 5) + + # Use a '==' + lines =<< trim END + vim9script + enum Foo + first == 1 + endenum + defcompile + END + v9.CheckSourceFailure(lines, 'E1123: Missing comma before argument: == 1', 3) + + # Missing comma after an enum item + lines =<< trim END + vim9script + enum Planet + mercury + venus + endenum + END + v9.CheckSourceFailure(lines, 'E1419: Not a valid command in an Enum: venus', 4) + + # Comma at the beginning of an item + lines =<< trim END + vim9script + enum Planet + mercury + ,venus + endenum + END + v9.CheckSourceFailure(lines, 'E1419: Not a valid command in an Enum: ,venus', 4) + # Space before comma + lines =<< trim END + vim9script + enum Planet + mercury , + venus + endenum + END + v9.CheckSourceFailure(lines, "E1068: No white space allowed before ','", 3) + + # No space after comma + lines =<< trim END + vim9script + enum Planet + mercury,venus + endenum + END + v9.CheckSourceFailure(lines, "E1069: White space required after ',': mercury,venus", 3) + + # no comma between items in the same line + lines =<< trim END + vim9script + enum Planet + mercury venus earth + endenum + defcompile + END + v9.CheckSourceFailure(lines, 'E1123: Missing comma before argument: venus earth', 3) + + # No space after an item and comment between items + lines =<< trim END + vim9script + enum Planet + mercury + + # Venus + venus + endenum + END + v9.CheckSourceFailure(lines, 'E1419: Not a valid command in an Enum: venus', 6) + + # Comma is supported for the last item + lines =<< trim END + vim9script + enum Planet + mercury, + venus, + endenum + var p: Planet + p = Planet.mercury + p = Planet.venus + END + v9.CheckSourceSuccess(lines) + + # invalid enum value declaration + lines =<< trim END + vim9script + enum Fruit + Apple, + $%@ + endenum + defcompile + END + v9.CheckSourceFailure(lines, 'E1418: Invalid enum value declaration: $%@', 4) + + # Duplicate enum value + lines =<< trim END + vim9script + enum A + Foo, + Bar, + Foo + endenum + END + v9.CheckSourceFailure(lines, 'E1428: Duplicate enum value: Foo', 5) + + # Duplicate enum value in the same line + lines =<< trim END + vim9script + enum A + Foo, Bar, Foo, + Bar + endenum + END + v9.CheckSourceFailure(lines, 'E1428: Duplicate enum value: Foo', 3) + + # Try extending a class when defining an enum + lines =<< trim END + vim9script + class Foo + endclass + enum Bar extends Foo + endenum + END + v9.CheckSourceFailure(lines, 'E1416: Enum cannot extend a class or enum', 4) + + # Try extending an enum + lines =<< trim END + vim9script + enum Foo + endenum + enum Bar extends Foo + endenum + END + v9.CheckSourceFailure(lines, 'E1416: Enum cannot extend a class or enum', 4) + + # Try extending an enum using a class + lines =<< trim END + vim9script + enum Foo + endenum + class Bar extends Foo + endclass + END + v9.CheckSourceFailure(lines, 'E1354: Cannot extend Foo', 5) + + # Try implementing an enum using a class + lines =<< trim END + vim9script + enum Foo + endenum + class Bar implements Foo + endclass + END + v9.CheckSourceFailure(lines, 'E1347: Not a valid interface: Foo', 5) + + # abstract method is not supported in an enum + lines =<< trim END + vim9script + enum Foo + Apple + abstract def Bar() + endenum + END + v9.CheckSourceFailure(lines, 'E1417: Abstract cannot be used in an Enum', 4) + + # Define an enum without any enum values but only with an object variable + lines =<< trim END + vim9script + enum Foo + final n: number = 10 + endenum + END + v9.CheckSourceFailure(lines, 'E1123: Missing comma before argument: n: number = 10', 3) +enddef + +def Test_basic_enum() + # Declare a simple enum + var lines =<< trim END + vim9script + enum Foo + apple, + orange + endenum + var a: Foo = Foo.apple + var b: Foo = Foo.orange + assert_equal(a, Foo.apple) + assert_equal(b, Foo.orange) + END + v9.CheckSourceSuccess(lines) + + # Multiple enums in a single line + lines =<< trim END + vim9script + enum Foo + apple, orange + endenum + assert_equal('enum<Foo>', typename(Foo.apple)) + assert_equal('enum<Foo>', typename(Foo.orange)) + END + v9.CheckSourceSuccess(lines) + + # Comments and empty lines are supported between enum items + lines =<< trim END + vim9script + enum Foo + # Apple + apple, + + # Orange + orange + endenum + def Fn() + var a: Foo = Foo.apple + var b: Foo = Foo.orange + assert_equal(a, Foo.apple) + assert_equal(b, Foo.orange) + enddef + END + v9.CheckSourceSuccess(lines) + + # Try using a non-existing enum value + lines =<< trim END + vim9script + enum Foo + apple, + orange + endenum + var a: Foo = Foo.pear + END + v9.CheckSourceFailure(lines, 'E1422: Enum value "pear" not found in enum "Foo"', 6) + + # Enum function argument + lines =<< trim END + vim9script + enum Foo + apple, + orange + endenum + def Fn(a: Foo): Foo + return a + enddef + assert_equal(Foo.apple, Fn(Foo.apple)) + END + v9.CheckSourceSuccess(lines) + + # Enum function argument + lines =<< trim END + vim9script + enum Foo + apple, + orange + endenum + def Fn(a: Foo): Foo + return a + enddef + Fn({}) + END + v9.CheckSourceFailure(lines, 'E1013: Argument 1: type mismatch, expected enum<Foo> but got dict<any>', 9) + + # Returning an enum in a function returning number + lines =<< trim END + vim9script + enum Foo + apple, + orange + endenum + def Fn(): number + return Foo.orange + enddef + Fn() + END + v9.CheckSourceFailure(lines, 'E1012: Type mismatch; expected number but got enum<Foo>', 1) + + # Returning a number in a function returning enum + lines =<< trim END + vim9script + enum Foo + apple, + orange + endenum + def Fn(): Foo + return 20 + enddef + Fn() + END + v9.CheckSourceFailure(lines, 'E1012: Type mismatch; expected enum<Foo> but got number', 1) + + # Use a List of enums + lines =<< trim END + vim9script + enum Planet + Mercury, + Venus, + Earth + endenum + var l1: list<Planet> = [Planet.Mercury, Planet.Venus] + assert_equal(Planet.Venus, l1[1]) + def Fn() + var l2: list<Planet> = [Planet.Mercury, Planet.Venus] + assert_equal(Planet.Venus, l2[1]) + enddef + END + v9.CheckSourceSuccess(lines) + + # Try using an enum as a value + lines =<< trim END + vim9script + enum Fruit + Apple, + Orange + endenum + var a = Fruit + END + v9.CheckSourceFailure(lines, 'E1421: Enum "Fruit" cannot be used as a value', 6) +enddef + +" Test for type() and typename() of an enum +def Test_enum_type() + var lines =<< trim END + vim9script + enum Fruit + Apple, + Orange + endenum + assert_equal('enum<Fruit>', typename(Fruit)) + assert_equal('enum<Fruit>', typename(Fruit.Apple)) + assert_equal(v:t_enum, type(Fruit)) + assert_equal(v:t_enumvalue, type(Fruit.Apple)) + assert_equal(15, type(Fruit)) + assert_equal(16, type(Fruit.Apple)) + END + v9.CheckSourceSuccess(lines) + + # Assign an enum to a variable with any type + lines =<< trim END + vim9script + enum Fruit + Apple, + Orange + endenum + var a = Fruit.Apple + var b: any = Fruit.Orange + assert_equal('enum<Fruit>', typename(a)) + assert_equal('enum<Fruit>', typename(b)) + END + v9.CheckSourceSuccess(lines) +enddef + +" Try modifying an enum or an enum item +def Test_enum_modify() + # Try assigning an unsupported value to an enum + var lines =<< trim END + vim9script + enum Foo + apple + endenum + var a: Foo = 30 + END + v9.CheckSourceFailure(lines, 'E1012: Type mismatch; expected enum<Foo> but got number', 5) + + # Try assigning an unsupported value to an enum in a function + lines =<< trim END + vim9script + enum Foo + apple + endenum + def Fn() + var a: Foo = 30 + enddef + defcompile + END + v9.CheckSourceFailure(lines, 'E1012: Type mismatch; expected enum<Foo> but got number', 1) + + # Try assigning a number to an enum + lines =<< trim END + vim9script + enum Foo + apple, + orange + endenum + Foo = 10 + END + v9.CheckSourceFailure(lines, 'E1421: Enum "Foo" cannot be used as a value', 6) + + # Try assigning a number to an enum in a function + lines =<< trim END + vim9script + enum Foo + apple + endenum + def Fn() + Foo = 10 + enddef + defcompile + END + v9.CheckSourceFailure(lines, 'E1012: Type mismatch; expected enum<Foo> but got number', 1) + + # Try assigning a number to an enum value + lines =<< trim END + vim9script + enum Foo + apple + endenum + Foo.apple = 20 + END + v9.CheckSourceFailure(lines, 'E1423: Enum value "Foo.apple" cannot be modified', 5) + + # Try assigning a number to an enum value in a function + lines =<< trim END + vim9script + enum Foo + apple + endenum + def Fn() + Foo.apple = 20 + enddef + defcompile + END + v9.CheckSourceFailure(lines, 'E1423: Enum value "Foo.apple" cannot be modified', 1) + + # Try assigning one enum to another + lines =<< trim END + vim9script + enum Foo + endenum + enum Bar + endenum + Foo = Bar + END + v9.CheckSourceFailure(lines, 'E1421: Enum "Bar" cannot be used as a value', 6) + + # Try assigning one enum to another in a function + lines =<< trim END + vim9script + enum Foo + endenum + enum Bar + endenum + def Fn() + Foo = Bar + enddef + defcompile + END + v9.CheckSourceFailure(lines, 'E1421: Enum "Bar" cannot be used as a value', 1) + + # Try assigning one enum item to another enum item + lines =<< trim END + vim9script + enum Foo + Apple + endenum + enum Bar + Orange + endenum + Foo.Apple = Bar.Orange + END + v9.CheckSourceFailure(lines, 'E1423: Enum value "Foo.Apple" cannot be modified', 8) + + # Try assigning one enum item to another enum item in a function + lines =<< trim END + vim9script + enum Foo + Apple + endenum + enum Bar + Orange + endenum + def Fn() + Foo.Apple = Bar.Orange + enddef + defcompile + END + v9.CheckSourceFailure(lines, 'E1423: Enum value "Foo.Apple" cannot be modified', 1) +enddef + +" Test for using enum in an expression +def Test_enum_expr() + var lines =<< trim END + vim9script + enum Color + Red, Blue, Green + endenum + var a: number = 1 + Color + END + v9.CheckSourceFailure(lines, 'E1421: Enum "Color" cannot be used as a value', 5) + + lines =<< trim END + vim9script + enum Color + Red, Blue, Green + endenum + var a: number = 1 + Color.Red + END + v9.CheckSourceFailure(lines, 'E1424: Using an Enum "Color" as a Number', 5) + + lines =<< trim END + vim9script + enum Color + Red, Blue, Green + endenum + var s: string = "abc" .. Color + END + v9.CheckSourceFailure(lines, 'E1421: Enum "Color" cannot be used as a value', 5) + + lines =<< trim END + vim9script + enum Color + Red, Blue, Green + endenum + var s: string = "abc" .. Color.Red + END + v9.CheckSourceFailure(lines, 'E1425: Using an Enum "Color" as a String', 5) +enddef + +" Using an enum in a lambda function +def Test_enum_lambda() + var lines =<< trim END + vim9script + enum Planet + Mercury, + Venus, + Earth, + endenum + var Fn = (p: Planet): Planet => p + for [idx, v] in items([Planet.Mercury, Planet.Venus, Planet.Earth]) + assert_equal(idx, Fn(v).ordinal) + endfor + END + v9.CheckSourceSuccess(lines) +enddef + +" Comparison using enums +def Test_enum_compare() + var lines =<< trim END + vim9script + enum Planet + Mercury, + Venus, + Earth, + endenum + enum Fruit + Apple, + Orange + endenum + + var p: Planet = Planet.Venus + var f: Fruit = Fruit.Orange + assert_equal(true, p == Planet.Venus) + assert_equal(false, p == Planet.Earth) + assert_equal(false, p == f) + assert_equal(true, Planet.Mercury == Planet.Mercury) + assert_equal(true, Planet.Venus != Planet.Earth) + assert_equal(true, Planet.Mercury != Fruit.Apple) + + def Fn1() + var p2: Planet = Planet.Venus + var f2: Fruit = Fruit.Orange + assert_equal(true, p2 == Planet.Venus) + assert_equal(false, p2 == Planet.Earth) + assert_equal(false, p2 == f2) + enddef + Fn1() + + # comparison using "is" and "isnot" + assert_equal(true, p is Planet.Venus) + assert_equal(true, p isnot Planet.Earth) + assert_equal(false, p is Fruit.Orange) + assert_equal(true, p isnot Fruit.Orange) + def Fn2(arg: Planet) + assert_equal(true, arg is Planet.Venus) + assert_equal(true, arg isnot Planet.Earth) + assert_equal(false, arg is Fruit.Orange) + assert_equal(true, arg isnot Fruit.Orange) + enddef + Fn2(p) + + class A + endclass + var o: A = A.new() + assert_equal(false, p == o) + END + v9.CheckSourceSuccess(lines) +enddef + +" Test for using an enum as a default argument to a function +def Test_enum_default_arg() + var lines =<< trim END + vim9script + enum Day + Monday, Tuesday, Wednesday + endenum + def Fn(d: Day = Day.Tuesday): Day + return d + enddef + assert_equal(Day.Tuesday, Fn()) + assert_equal(Day.Wednesday, Fn(Day.Wednesday)) + END + v9.CheckSourceSuccess(lines) +enddef + +" Test for enum garbage collection +func Test_enum_garbagecollect() + let lines =<< trim END + vim9script + enum Car + Honda, Ford, Tesla + endenum + assert_equal(1, Car.Ford.ordinal) + call test_garbagecollect_now() + assert_equal(1, Car.Ford.ordinal) + var c: Car = Car.Tesla + assert_equal(2, c.ordinal) + call test_garbagecollect_now() + assert_equal(2, c.ordinal) + END + call v9.CheckSourceSuccess(lines) + + " garbage collection with a variable of type any + let lines =<< trim END + vim9script + enum Car + Honda, Ford, Tesla + endenum + call test_garbagecollect_now() + var c: any = Car.Tesla + call test_garbagecollect_now() + assert_equal(Car.Tesla, c) + END + call v9.CheckSourceSuccess(lines) + + " garbage collection with function arguments and return types + let lines =<< trim END + vim9script + enum Car + Honda, Ford, Tesla + endenum + def Fn(a: Car): Car + assert_equal(Car.Ford, a) + return Car.Tesla + enddef + call test_garbagecollect_now() + var b: Car = Car.Ford + call test_garbagecollect_now() + assert_equal(Car.Tesla, Fn(b)) + call test_garbagecollect_now() + END + call v9.CheckSourceSuccess(lines) +endfunc + +" Test for the enum values class variable +def Test_enum_values() + var lines =<< trim END + vim9script + enum Car + Honda, Ford, Tesla + endenum + var l: list<Car> = Car.values + assert_equal(Car.Ford, l[1]) + END + v9.CheckSourceSuccess(lines) + + # empty enum + lines =<< trim END + vim9script + enum Car + endenum + assert_equal([], Car.values) + END + v9.CheckSourceSuccess(lines) + + # single value + lines =<< trim END + vim9script + enum Car + Honda + endenum + assert_equal([Car.Honda], Car.values) + END + v9.CheckSourceSuccess(lines) + + lines =<< trim END + vim9script + enum A + Red, + Blue + static def GetValues(): list<A> + return values + enddef + endenum + assert_equal([A.Red, A.Blue], A.GetValues()) + END + v9.CheckSourceSuccess(lines) + + # Other class variables in an enum should not be added to 'values' + lines =<< trim END + vim9script + enum LogLevel + Error, Warn + static const x: number = 22 + endenum + assert_equal([LogLevel.Error, LogLevel.Warn], LogLevel.values) + END + v9.CheckSourceSuccess(lines) + + # Other class variable of enum type should not be added to 'values' + lines =<< trim END + vim9script + enum LogLevel + Error, Warn + static const x: LogLevel = LogLevel.Warn + endenum + assert_equal([LogLevel.Error, LogLevel.Warn], LogLevel.values) + END + v9.CheckSourceSuccess(lines) +enddef + +" Test comments in enums +def Test_enum_comments() + var lines =<< trim END + vim9script + enum Car # cars + # before enum + Honda, # honda + # before enum + Ford # ford + endenum + assert_equal(1, Car.Ford.ordinal) + END + v9.CheckSourceSuccess(lines) + + # Test for using an unsupported comment + lines =<< trim END + vim9script + enum Car + Honda, + Ford, + #{ + endenum + defcompile + END + v9.CheckSourceFailure(lines, 'E1170: Cannot use #{ to start a comment', 4) +enddef + +" Test string() with enums +def Test_enum_string() + var lines =<< trim END + vim9script + enum Car + Honda, + Ford + endenum + assert_equal("enum Car", string(Car)) + assert_equal("enum Car.Honda {name: 'Honda', ordinal: 0}", string(Car.Honda)) + END + v9.CheckSourceSuccess(lines) + + # customized string function + lines =<< trim END + vim9script + enum Dir + North, + South + + def string(): string + return $'Dir.{this.name}' + enddef + endenum + assert_equal('Dir.North', string(Dir.North)) + assert_equal('Dir.South', string(Dir.South)) + END + v9.CheckSourceSuccess(lines) +enddef + +" Test for importing an enum +def Test_enum_import() + var lines =<< trim END + vim9script + export enum Star + Gemini, + Orion, + Pisces + endenum + END + writefile(lines, 'Xenumexport.vim', 'D') + + lines =<< trim END + vim9script + import './Xenumexport.vim' as mod + + var s1: mod.Star = mod.Star.Orion + assert_equal(true, s1 == mod.Star.Orion) + assert_equal(2, mod.Star.Pisces.ordinal) + var l1: list<mod.Star> = mod.Star.values + assert_equal("enum Star.Orion {name: 'Orion', ordinal: 1}", string(l1[1])) + assert_equal(s1, l1[1]) + + def Fn() + var s2: mod.Star = mod.Star.Orion + assert_equal(true, s2 == mod.Star.Orion) + assert_equal(2, mod.Star.Pisces.ordinal) + var l2: list<mod.Star> = mod.Star.values + assert_equal("enum Star.Orion {name: 'Orion', ordinal: 1}", string(l2[1])) + assert_equal(s2, l2[1]) + enddef + Fn() + END + v9.CheckScriptSuccess(lines) +enddef + +" Test for using test_refcount() with enum +def Test_enum_refcount() + var lines =<< trim END + vim9script + enum Foo + endenum + assert_equal(1, test_refcount(Foo)) + + enum Star + Gemini, + Orion + endenum + assert_equal(3, test_refcount(Star)) + assert_equal(2, test_refcount(Star.Gemini)) + assert_equal(2, test_refcount(Star.Orion)) + + var s: Star + assert_equal(3, test_refcount(Star)) + assert_equal(-1, test_refcount(s)) + s = Star.Orion + assert_equal(3, test_refcount(Star)) + assert_equal(3, test_refcount(s)) + assert_equal(2, test_refcount(Star.Gemini)) + var t = s + assert_equal(3, test_refcount(Star)) + assert_equal(4, test_refcount(s)) + assert_equal(4, test_refcount(Star.Orion)) + END + v9.CheckSourceSuccess(lines) +enddef + +" Test for defining an enum with additional object variables and methods +def Test_enum_enhanced() + var lines =<< trim END + vim9script + enum Vehicle + car(4, 5, 400), + bus(6, 50, 800), + bicycle(2, 1, 0) + + final tires: number + final passengers: number + final carbonPerKilometer: number + + def new(t: number, p: number, cpk: number) + this.tires = t + this.passengers = p + this.carbonPerKilometer = cpk + enddef + + def CarbonFootprint(): float + return round(this.carbonPerKilometer / this.passengers) + enddef + + def IsTwoWheeled(): bool + return this == Vehicle.bicycle + enddef + + def CompareTo(other: Vehicle): float + return this.CarbonFootprint() - other.CarbonFootprint() + enddef + endenum + + var v: Vehicle = Vehicle.bus + assert_equal([6, 50, 800], [v.tires, v.passengers, v.carbonPerKilometer]) + assert_equal(true, Vehicle.bicycle.IsTwoWheeled()) + assert_equal(false, Vehicle.car.IsTwoWheeled()) + assert_equal(16.0, Vehicle.bus.CarbonFootprint()) + END + v9.CheckSourceSuccess(lines) +enddef + +" Test for the enum value 'name' variable +def Test_enum_name() + # Check the names of enum values + var lines =<< trim END + vim9script + enum Planet + Mercury, + Venus, + Earth + endenum + assert_equal('Mercury', Planet.Mercury.name) + assert_equal('Venus', Planet.Venus.name) + assert_equal('Earth', Planet.Earth.name) + assert_equal('string', typename(Planet.Earth.name)) + END + v9.CheckSourceSuccess(lines) + + # Check the name of enum items in the constructor + lines =<< trim END + vim9script + enum Planet + Mercury("Mercury"), + Venus("Venus"), + Earth("Earth") + + def new(s: string) + assert_equal(s, this.name) + enddef + endenum + defcompile + END + v9.CheckSourceSuccess(lines) + + # Try assigning to the name of an enum + lines =<< trim END + vim9script + enum Fruit + Apple + endenum + Fruit.Apple.name = 'foo' + END + v9.CheckSourceFailure(lines, 'E1335: Variable "name" in class "Fruit" is not writable', 5) + + # Try assigning to the name of an enum in a function + lines =<< trim END + vim9script + enum Fruit + Apple + endenum + def Fn() + Fruit.Apple.name = 'bar' + enddef + defcompile + END + v9.CheckSourceFailure(lines, 'E1423: Enum value "Fruit.name" cannot be modified', 1) + + # Try to overwrite an enum value name in the enum constructor + lines =<< trim END + vim9script + enum Planet + Mercury, + Venus + + def new() + this.name = 'foo' + enddef + endenum + END + v9.CheckSourceFailure(lines, 'E1427: Enum "Planet" name cannot be modified', 1) + + # Try to declare an object variable named 'name' + lines =<< trim END + vim9script + enum Planet + Mercury + var name: string + endenum + END + v9.CheckSourceFailure(lines, 'E1369: Duplicate variable: name', 4) +enddef + +" Test for the enum value 'ordinal' variable +def Test_enum_ordinal() + # Check the ordinal values of enum items + var lines =<< trim END + vim9script + enum Planet + Mercury, + Venus, + Earth + endenum + assert_equal(0, Planet.Mercury.ordinal) + assert_equal(1, Planet.Venus.ordinal) + assert_equal(2, Planet.Earth.ordinal) + assert_equal('number', typename(Planet.Earth.ordinal)) + END + v9.CheckSourceSuccess(lines) + + # Check the ordinal value of enum items in the constructor + lines =<< trim END + vim9script + enum Planet + Mercury(0), + Venus(1), + Earth(2) + + def new(v: number) + assert_equal(v, this.ordinal) + enddef + endenum + defcompile + END + v9.CheckSourceSuccess(lines) + + # Try assigning to the ordinal value of an enum + lines =<< trim END + vim9script + enum Fruit + Apple + endenum + Fruit.Apple.ordinal = 20 + END + v9.CheckSourceFailure(lines, 'E1335: Variable "ordinal" in class "Fruit" is not writable', 5) + + # Try assigning to the ordinal value of an enum in a function + lines =<< trim END + vim9script + enum Fruit + Apple + endenum + def Fn() + Fruit.Apple.ordinal = 20 + enddef + defcompile + END + v9.CheckSourceFailure(lines, 'E1423: Enum value "Fruit.ordinal" cannot be modified', 1) + + # Try to overwrite an enum value ordinal in the enum constructor + lines =<< trim END + vim9script + enum Planet + Mercury, + Venus + + def new() + this.ordinal = 20 + enddef + endenum + END + v9.CheckSourceFailure(lines, 'E1426: Enum "Planet" ordinal value cannot be modified', 1) + + # Try to declare an object variable named 'ordinal' + lines =<< trim END + vim9script + enum Planet + Mercury + var ordinal: number + endenum + END + v9.CheckSourceFailure(lines, 'E1369: Duplicate variable: ordinal', 4) +enddef + +" Test for trying to create a new enum object using the constructor +def Test_enum_invoke_constructor() + var lines =<< trim END + vim9script + enum Foo + endenum + var f: Foo = Foo.new() + END + v9.CheckSourceFailure(lines, 'E1325: Method "new" not found in class "Foo"', 4) + + lines =<< trim END + vim9script + enum Fruit + Apple, + Orange + endenum + var f: Fruit = Fruit.new() + END + v9.CheckSourceFailure(lines, 'E1325: Method "new" not found in class "Fruit"', 6) + + lines =<< trim END + vim9script + enum Fruit + Apple, + Orange + def newFruit() + enddef + endenum + var f: Fruit = Fruit.newFruit() + END + v9.CheckSourceFailure(lines, 'E1325: Method "newFruit" not found in class "Fruit"', 8) + + lines =<< trim END + vim9script + enum Fruit + Apple, + Orange + endenum + def Fn() + var f: Fruit = Fruit.new() + enddef + Fn() + END + v9.CheckSourceFailure(lines, 'E1325: Method "new" not found in class "Fruit"', 1) + + # error in the enum constructor + lines =<< trim END + vim9script + enum Planet + earth + def new() + x = 123 + enddef + endenum + END + v9.CheckSourceFailureList(lines, ['E1100:', 'E1100:'], 1) +enddef + +" Test for checking "this" in an enum constructor +def Test_enum_this_in_constructor() + var lines =<< trim END + vim9script + enum A + Red("enum A.Red {name: 'Red', ordinal: 0}"), + Blue("enum A.Blue {name: 'Blue', ordinal: 1}"), + Green("enum A.Green {name: 'Green', ordinal: 2}") + + def new(s: string) + assert_equal(s, string(this)) + enddef + endenum + defcompile + END + v9.CheckSourceSuccess(lines) +enddef + +" Test for using member variables in an enum object +def Test_enum_object_variable() + var lines =<< trim END + vim9script + enum Planet + Jupiter(95), + Saturn(146) + + var moons: number + endenum + assert_equal(95, Planet.Jupiter.moons) + assert_equal(146, Planet.Saturn.moons) + END + v9.CheckSourceSuccess(lines) + + # Use a final object variable + lines =<< trim END + vim9script + enum Planet + Jupiter(95), + Saturn(146) + + final moons: number + def new(n: number) + this.moons = n + enddef + endenum + assert_equal(95, Planet.Jupiter.moons) + assert_equal(146, Planet.Saturn.moons) + END + v9.CheckSourceSuccess(lines) + + # Use a const object variable + lines =<< trim END + vim9script + enum Planet + Mars(false), + Jupiter(true) + + const has_ring: bool + def new(r: bool) + this.has_ring = r + enddef + endenum + assert_equal(false, Planet.Mars.has_ring) + assert_equal(true, Planet.Jupiter.has_ring) + END + v9.CheckSourceSuccess(lines) + + # Use a regular object variable + lines =<< trim END + vim9script + enum Fruit + Apple, + Orange + + final farm: string = 'SunValley' + endenum + assert_equal('SunValley', Fruit.Apple.farm) + assert_equal('SunValley', Fruit.Apple.farm) + END + v9.CheckSourceSuccess(lines) + + # Invoke the default constructor with an object variable + lines =<< trim END + vim9script + enum Fruit + Apple('foo'), + Orange('bar') + + final t: string + endenum + assert_equal('foo', Fruit.Apple.t) + assert_equal('bar', Fruit.Orange.t) + END + v9.CheckSourceSuccess(lines) + + # Invoke the default constructor with an argument but without the object + # variable + lines =<< trim END + vim9script + enum Fruit + Apple, + Orange('bar') + endenum + defcompile + END + v9.CheckSourceFailure(lines, 'E118: Too many arguments for function: new', 5) + + # Define a default constructor with an argument, but don't pass it in when + # defining the enum value + lines =<< trim END + vim9script + enum Fruit + Apple(5), + Orange + + def new(t: number) + enddef + endenum + defcompile + END + v9.CheckSourceFailure(lines, 'E119: Not enough arguments for function: new', 8) +enddef + +" Test for using a custom constructor with an enum +def Test_enum_custom_constructor() + # space before "(" + var lines =<< trim END + vim9script + enum Fruit + Apple(10), + Orange (20) + + def new(t: number) + enddef + endenum + defcompile + END + v9.CheckSourceFailure(lines, "E1068: No white space allowed before '(': Orange (20)", 4) + + # no closing ")" + lines =<< trim END + vim9script + enum Fruit + Apple(10), + Orange (20 + + def new(t: number) + enddef + endenum + defcompile + END + v9.CheckSourceFailure(lines, "E1068: No white space allowed before '(': Orange (20", 4) + + # Specify constructor arguments split across multiple lines + lines =<< trim END + vim9script + enum Fruit + Apple(10, + 'foo'), Orange(20, + 'bar'), + Pear(30, + 'baz'), Mango(40, + 'qux') + + final n: number + final s: string + def new(t: number, str: string) + this.n = t + this.s = str + enddef + endenum + defcompile + assert_equal([10, 'foo'], [Fruit.Apple.n, Fruit.Apple.s]) + assert_equal([20, 'bar'], [Fruit.Orange.n, Fruit.Orange.s]) + assert_equal([30, 'baz'], [Fruit.Pear.n, Fruit.Pear.s]) + assert_equal([40, 'qux'], [Fruit.Mango.n, Fruit.Mango.s]) + END + v9.CheckSourceSuccess(lines) + + # specify multiple enums with constructor arguments in a single line + lines =<< trim END + vim9script + enum Fruit + Apple(10, 'foo'), Orange(20, 'bar'), Pear(30, 'baz'), Mango(40, 'qux') + const n: number + const s: string + endenum + defcompile + assert_equal([10, 'foo'], [Fruit.Apple.n, Fruit.Apple.s]) + assert_equal([20, 'bar'], [Fruit.Orange.n, Fruit.Orange.s]) + assert_equal([30, 'baz'], [Fruit.Pear.n, Fruit.Pear.s]) + assert_equal([40, 'qux'], [Fruit.Mango.n, Fruit.Mango.s]) + END + v9.CheckSourceSuccess(lines) +enddef + +" Test for using class variables in an enum class +def Test_enum_class_variable() + var lines =<< trim END + vim9script + enum Fruit + Apple, + Orange + + static var farm: string = 'SunValley' + endenum + assert_equal('SunValley', Fruit.farm) + END + v9.CheckSourceSuccess(lines) +enddef + +" Test for converting a string to an enum value +def Test_enum_eval() + var lines =<< trim END + vim9script + enum Color + Red, + Blue + endenum + var e = eval('Color.Blue') + assert_equal(Color.Blue, e) + assert_equal(1, e.ordinal) + assert_fails("eval('Color.Green')", 'E1422: Enum value "Green" not found in enum "Color"') + assert_fails("var x = eval('Color')", 'E1421: Enum "Color" cannot be used as a value') + END + v9.CheckSourceSuccess(lines) +enddef + +" Test for using "values" in an enum class variable +def Test_use_enum_values_in_class_variable() + var lines =<< trim END + vim9script + enum Dir + North, South + static const dirs: list<Dir> = Dir.values + endenum + assert_equal([Dir.North, Dir.South], Dir.dirs) + END + v9.CheckSourceSuccess(lines) +enddef + +" Test for using lambda block in enums +def Test_lambda_block_in_enum() + # This used to crash Vim + var lines =<< trim END + vim9script + enum IdEnum1 + ID1 + const Id: func(number): number = (num: number): number => { + # Return a ID + return num / 2 + } + endenum + assert_equal(5, IdEnum1.ID1.Id(10)) + END + v9.CheckScriptSuccess(lines) + + # This used to crash Vim + lines =<< trim END + vim9script + enum IdEnum2 + ID1 + static const Id: func(number): number = (num: number): number => { + # Return a ID + return num + 2 + } + endenum + assert_equal(12, IdEnum2.Id(10)) + END + v9.CheckScriptSuccess(lines) +enddef + +" vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker diff --git a/src/testdir/test_vim9_func.vim b/src/testdir/test_vim9_func.vim index 27585a9..b008929 100644 --- a/src/testdir/test_vim9_func.vim +++ b/src/testdir/test_vim9_func.vim @@ -166,6 +166,37 @@ def Test_wrong_function_name() delfunc g:Define enddef +" Check that in a legacy script a :def accesses the correct script variables. +" Github issue: #14615. +def Test_access_var_from_legacy_def() + # Access a script variable by name WITH "s:" prefix. + var lines =<< trim END + let s:foo = 'init' + let s:xxfoo = 'init' + def! AccessVarFromLegacyDef() + s:xxfoo = 'CHANGED' + enddef + call AccessVarFromLegacyDef() + call assert_equal('init', s:foo) + call assert_equal('CHANGED', s:xxfoo) + END + v9.CheckScriptSuccess(lines) + + # Access a script variable by name WITHOUT "s:" prefix; + # previously this accessed "foo" and not "xxfoo" + lines =<< trim END + let s:foo = 'init' + let s:xxfoo = 'init' + def! AccessVarFromLegacyDef() + xxfoo = 'CHANGED' + enddef + call AccessVarFromLegacyDef() + call assert_equal('init', s:foo) + call assert_equal('CHANGED', s:xxfoo) + END + v9.CheckScriptSuccess(lines) +enddef + def Test_listing_function_error() var lines =<< trim END var filler = 123 diff --git a/src/testdir/test_vim9_import.vim b/src/testdir/test_vim9_import.vim index fa1aeb1..581925d 100644 --- a/src/testdir/test_vim9_import.vim +++ b/src/testdir/test_vim9_import.vim @@ -1140,6 +1140,182 @@ def Test_autoload_import_relative() v9.CheckScriptFailure(lines, 'E484:') enddef +" autoload relative, access from compiled function. +" Github issues: #14565, #14579 +def Test_autoload_import_relative_compiled_buffer() + var lines =<< trim END + vim9script + + export def F1(): string + return 'InFile.vim' + enddef + END + writefile(lines, 'Ximportrelativebuffer.vim', 'D') + lines =<< trim END + vim9script + + import autoload './Ximportrelativebuffer.vim' as xfile + + def F(): string + return xfile.F1() + enddef + assert_equal('InFile.vim', F()) + END + new + setline(1, lines) + :source + # source one more time to detect issues with clearing the script state and + # variables + :source + :bw! +enddef + +" Test for relative import when sourcing a buffer in another directory +def Test_autoload_import_relative_from_buffer_in_dir() + mkdir('Ximportrelative/dir1/dir2', 'pR') + var lines =<< trim END + vim9script + + export def F1(): string + return 'InFile.vim' + enddef + END + writefile(lines, 'Ximportrelative/dir1/dir2/Ximport.vim') + lines =<< trim END + vim9script + + import autoload './Ximport.vim' as xfile + + def F(): string + return xfile.F1() + enddef + assert_equal('InFile.vim', F()) + END + writefile(lines, 'Ximportrelative/dir1/dir2/Xrelative.vim') + + split Ximportrelative/dir1/dir2/Xrelative.vim + :source + # source one more time to detect issues with clearing the script state and + # variables + :source + :bw! +enddef + +" Test modifying exported autoload variable. Github issue: #14591 +def Test_autoload_export_variables() + mkdir('Xautoload_vars/autoload', 'pR') + var lines =<< trim END + vim9script + g:Xautoload_vars_autoload = true + export var val = 11 + val = 42 + END + + # Test that the imported script, above, can modify the exported variable; + # and test that the importing script, below, can modify the variable. + writefile(lines, 'Xautoload_vars/autoload/Xauto_vars_f2.vim', 'D') + lines =<< trim END + vim9script + g:Xautoload_vars_autoload = false + + import autoload './Xautoload_vars/autoload/Xauto_vars_f2.vim' as f2 + # Verify that the import statement does not load the file. + assert_equal(false, g:Xautoload_vars_autoload) + + def F(): number + return f2.val + enddef + # Verify compile does not load the file. + defcompile F + assert_equal(false, g:Xautoload_vars_autoload) + + # load the file by accessing the exported variable + assert_equal(42, F()) + assert_equal(true, g:Xautoload_vars_autoload) + unlet g:Xautoload_vars_autoload + + assert_equal(42, f2.val) + f2.val = 17 + assert_equal(17, f2.val) + + def G() + f2.val = 19 + enddef + G() + assert_equal(19, f2.val) + END + v9.CheckScriptSuccess(lines) + + # Test const var is not modifiable. + lines =<< trim END + vim9script + export const val = 11 + val = 42 + END + writefile(lines, 'Xautoload_vars/autoload/Xauto_vars_f3.vim', 'D') + lines =<< trim END + vim9script + + import autoload './Xautoload_vars/autoload/Xauto_vars_f3.vim' as f3 + + var x = f3.val + END + v9.CheckScriptFailure(lines, 'E46:') + + # Test const var is not modifiable from importing script. + lines =<< trim END + vim9script + export const val = 11 + END + writefile(lines, 'Xautoload_vars/autoload/Xauto_vars_f4.vim', 'D') + lines =<< trim END + vim9script + + import autoload './Xautoload_vars/autoload/Xauto_vars_f4.vim' as f4 + + f4.val = 13 + END + v9.CheckScriptFailure(lines, 'E46:') + + # Test const var is not modifiable from importing script from :def. + # Github issue: #14606 + lines =<< trim END + vim9script + export const val = 11 + END + writefile(lines, 'Xautoload_vars/autoload/Xauto_vars_f5.vim', 'D') + lines =<< trim END + vim9script + + import autoload './Xautoload_vars/autoload/Xauto_vars_f5.vim' as f5 + + def F() + f5.val = 13 + enddef + F() + END + v9.CheckScriptFailure(lines, 'E741:') + + # Still part of Github issue: #14606 + lines =<< trim END + vim9script + export var val = 11 + END + writefile(lines, 'Xautoload_vars/autoload/Xauto_vars_f6.vim', 'D') + lines =<< trim END + vim9script + + import autoload './Xautoload_vars/autoload/Xauto_vars_f6.vim' as f6 + + def F() + f6.val = 13 + enddef + F() + assert_equal(13, f6.val) + END + v9.CheckScriptSuccess(lines) +enddef + def Test_autoload_import_relative_autoload_dir() mkdir('autoload', 'pR') var lines =<< trim END @@ -2054,6 +2230,13 @@ def Test_import_vim9_from_legacy() export def GetText(): string return 'text' enddef + export var exported_nr: number = 22 + def AddNum(n: number) + exported_nr += n + enddef + export var exportedDict: dict<func> = {Fn: AddNum} + export const CONST = 10 + export final finalVar = 'abc' END writefile(vim9_lines, 'Xvim9_export.vim', 'D') @@ -2072,6 +2255,13 @@ def Test_import_vim9_from_legacy() " imported symbol is script-local call assert_equal('exported', s:vim9.exported) call assert_equal('text', s:vim9.GetText()) + call s:vim9.exportedDict.Fn(5) + call assert_equal(27, s:vim9.exported_nr) + call call(s:vim9.exportedDict.Fn, [3]) + call assert_equal(30, s:vim9.exported_nr) + call assert_fails('let s:vim9.CONST = 20', 'E46: Cannot change read-only variable "CONST"') + call assert_fails('let s:vim9.finalVar = ""', 'E46: Cannot change read-only variable "finalVar"') + call assert_fails('let s:vim9.non_existing_var = 20', 'E1048: Item not found in script: non_existing_var') END writefile(legacy_lines, 'Xlegacy_script.vim', 'D') @@ -2916,6 +3106,33 @@ def Test_vim9_import_symlink() unlet g:resultValue &rtp = save_rtp delete('Xfrom', 'rf') + + # Access item from :def imported through symbolic linked directory. #14536 + mkdir('Xto/real_dir', 'pR') + lines =<< trim END + vim9script + export const val = 17 + export def F(): number + return 23 + enddef + END + writefile(lines, 'Xto/real_dir/real_file.vim') + system('ln -s real_dir Xto/syml_dir') + defer delete('Xto/syml_dir') + lines =<< trim END + vim9script + import autoload './Xto/syml_dir/real_file.vim' + + def Fmain() + assert_equal(17, real_file.val) + enddef + def F2() + assert_equal(23, real_file.F()) + enddef + Fmain() + F2() + END + v9.CheckScriptSuccess(lines) endif enddef @@ -2979,4 +3196,30 @@ def Test_import_autloaded_script() &rtp = save_rtp enddef +" Test for autoloading an imported dict func +def Test_autoload_import_dict_func() + mkdir('Xdir/autoload', 'pR') + var lines =<< trim END + vim9script + export var al_exported_nr: number = 33 + def Al_AddNum(n: number) + al_exported_nr += n + enddef + export var al_exportedDict: dict<func> = {Fn: Al_AddNum} + END + writefile(lines, 'Xdir/autoload/Xdictfunc.vim') + + var save_rtp = &rtp + exe 'set rtp^=' .. getcwd() .. '/Xdir' + lines =<< trim END + import './Xdir/autoload/Xdictfunc.vim' + call Xdictfunc#al_exportedDict.Fn(5) + call assert_equal(38, Xdictfunc#al_exported_nr) + call call(Xdictfunc#al_exportedDict.Fn, [3]) + call assert_equal(41, Xdictfunc#al_exported_nr) + END + v9.CheckScriptSuccess(lines) + &rtp = save_rtp +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 77b8831..a3f21be 100644 --- a/src/testdir/test_vim9_script.vim +++ b/src/testdir/test_vim9_script.vim @@ -458,7 +458,7 @@ func s:InvokeSomeCommand() SomeCommand endfunc -def Test_autocommand_block() +def Test_command_block() com SomeCommand { g:someVar = 'some' } @@ -469,7 +469,121 @@ def Test_autocommand_block() unlet g:someVar enddef -def Test_command_block() +" Test for using heredoc in a :command command block +def Test_command_block_heredoc() + var lines =<< trim CODE + vim9script + com SomeCommand { + g:someVar =<< trim END + aaa + bbb + END + } + SomeCommand + assert_equal(['aaa', 'bbb'], g:someVar) + def Foo() + g:someVar = [] + SomeCommand + assert_equal(['aaa', 'bbb'], g:someVar) + enddef + Foo() + delcommand SomeCommand + unlet g:someVar + CODE + v9.CheckSourceSuccess( lines) + + # Execute a command with heredoc in a block + lines =<< trim CODE + vim9script + com SomeCommand { + g:someVar =<< trim END + aaa + bbb + END + } + execute('SomeCommand') + assert_equal(['aaa', 'bbb'], g:someVar) + delcommand SomeCommand + unlet g:someVar + CODE + v9.CheckSourceSuccess(lines) + + # Heredoc with comment + lines =<< trim CODE + vim9script + com SomeCommand { + g:someVar =<< trim END # comment + aaa + bbb + END + } + execute('SomeCommand') + assert_equal(['aaa', 'bbb'], g:someVar) + delcommand SomeCommand + unlet g:someVar + CODE + v9.CheckSourceSuccess(lines) + + # heredoc evaluation + lines =<< trim CODE + vim9script + com SomeCommand { + var suffix = '---' + g:someVar =<< trim eval END + ccc{suffix} + ddd + END + } + SomeCommand + assert_equal(['ccc---', 'ddd'], g:someVar) + def Foo() + g:someVar = [] + SomeCommand + assert_equal(['ccc---', 'ddd'], g:someVar) + enddef + Foo() + delcommand SomeCommand + unlet g:someVar + CODE + v9.CheckSourceSuccess(lines) + + # command following heredoc + lines =<< trim CODE + vim9script + com SomeCommand { + var l =<< trim END + eee + fff + END + g:someVar = l + } + SomeCommand + assert_equal(['eee', 'fff'], g:someVar) + delcommand SomeCommand + unlet g:someVar + CODE + v9.CheckSourceSuccess(lines) + + # Error in heredoc + lines =<< trim CODE + vim9script + com SomeCommand { + g:someVar =<< trim END + eee + fff + } + try + SomeCommand + catch + assert_match("E990: Missing end marker 'END'", v:exception) + endtry + delcommand SomeCommand + unlet g:someVar + CODE + v9.CheckSourceSuccess(lines) +enddef + +def Test_autocommand_block() au BufNew *.xml { g:otherVar = 'other' } @@ -4906,7 +5020,7 @@ def Test_for_stmt_space_before_type() v9.CheckSourceFailure(lines, 'E1059: No white space allowed before colon: :number in range(10)', 2) enddef -" This test used to cause an use-after-free memory access +" This test used to cause a use-after-free memory access def Test_for_empty_line_after_lambda() var lines =<< trim END vim9script @@ -4931,6 +5045,16 @@ def Test_for_empty_line_after_lambda() v9.CheckSourceSuccess(lines) enddef +" Test for evaluating a lambda block from a string +def Test_eval_lambda_block() + var lines =<< trim END + vim9script + var Fn = eval("(x: number): number => {\nreturn x * 2\n}") + assert_equal(6, Fn(3)) + END + v9.CheckSourceSuccess(lines) +enddef + " Keep this last, it messes up highlighting. def Test_substitute_cmd() new diff --git a/src/testdir/test_visual.vim b/src/testdir/test_visual.vim index fd174a9..adcc3e9 100644 --- a/src/testdir/test_visual.vim +++ b/src/testdir/test_visual.vim @@ -1149,7 +1149,7 @@ func Test_visual_inner_block() " try to select non-existing inner block call cursor(5, 1) call assert_beeps('normal ViBiBiB') - " try to select a unclosed inner block + " try to select an unclosed inner block 8,9d call cursor(5, 1) call assert_beeps('normal ViBiB') diff --git a/src/testdir/test_winfixbuf.vim b/src/testdir/test_winfixbuf.vim index 04043f8..f800338 100644 --- a/src/testdir/test_winfixbuf.vim +++ b/src/testdir/test_winfixbuf.vim @@ -1,6 +1,7 @@ " Test 'winfixbuf' source check.vim +source shared.vim " Find the number of open windows in the current tab func s:get_windows_count() @@ -199,10 +200,7 @@ func s:reset_all_buffers() set nowinfixbuf call setqflist([]) - - for l:window_info in getwininfo() - call setloclist(l:window_info["winid"], []) - endfor + call setloclist(0, [], 'f') delmarks A-Z0-9 endfunc @@ -641,7 +639,7 @@ func Test_caddexpr() call s:reset_all_buffers() let l:file_path = tempname() - call writefile(["Error - bad-thing-found"], l:file_path) + call writefile(["Error - bad-thing-found"], l:file_path, 'D') execute "edit " . l:file_path let l:file_buffer = bufnr() let l:current = bufnr() @@ -657,8 +655,6 @@ func Test_caddexpr() execute 'caddexpr expand("%") .. ":" .. line(".") .. ":" .. getline(".")' call assert_equal(l:current, bufnr()) - - call delete(l:file_path) endfunc " Fail :cbuffer but :cbuffer! is allowed @@ -667,7 +663,7 @@ func Test_cbuffer() call s:reset_all_buffers() let l:file_path = tempname() - call writefile(["first.unittest:1:Error - bad-thing-found"], l:file_path) + call writefile(["first.unittest:1:Error - bad-thing-found"], l:file_path, 'D') execute "edit " . l:file_path let l:file_buffer = bufnr() let l:current = bufnr() @@ -686,8 +682,6 @@ func Test_cbuffer() execute "cbuffer! " . l:file_buffer call assert_equal("first.unittest", expand("%:t")) - - call delete(l:file_path) endfunc " Allow :cc but the 'nowinfixbuf' window is selected, instead @@ -1125,6 +1119,150 @@ func Test_edit() call assert_equal(l:other, bufnr()) endfunc +" Fail :e when selecting a buffer from a relative path if in a different folder +" +" In this tests there's 2 buffers +" +" foo - lives on disk, in some folder. e.g. /tmp/foo +" foo - an in-memory buffer that has not been saved to disk. If saved, it +" would live in a different folder, /other/foo. +" +" The 'winfixbuf' is looking at the in-memory buffer and trying to switch to +" the buffer on-disk (and fails, because it's a different buffer) +func Test_edit_different_buffer_on_disk_and_relative_path_to_disk() + call s:reset_all_buffers() + + let l:file_on_disk = tempname() + let l:directory_on_disk1 = fnamemodify(l:file_on_disk, ":p:h") + let l:name = fnamemodify(l:file_on_disk, ":t") + execute "edit " . l:file_on_disk + write! + + let l:directory_on_disk2 = l:directory_on_disk1 . "_something_else" + + if !isdirectory(l:directory_on_disk2) + call mkdir(l:directory_on_disk2) + endif + + execute "cd " . l:directory_on_disk2 + execute "edit " l:name + + let l:current = bufnr() + + call assert_equal(l:current, bufnr()) + set winfixbuf + call assert_fails("edit " . l:file_on_disk, "E1513:") + call assert_equal(l:current, bufnr()) + + call delete(l:directory_on_disk1) + call delete(l:directory_on_disk2) +endfunc + +" Fail :e when selecting a buffer from a relative path if in a different folder +" +" In this tests there's 2 buffers +" +" foo - lives on disk, in some folder. e.g. /tmp/foo +" foo - an in-memory buffer that has not been saved to disk. If saved, it +" would live in a different folder, /other/foo. +" +" The 'winfixbuf' is looking at the on-disk buffer and trying to switch to +" the in-memory buffer (and fails, because it's a different buffer) +func Test_edit_different_buffer_on_disk_and_relative_path_to_memory() + call s:reset_all_buffers() + + let l:file_on_disk = tempname() + let l:directory_on_disk1 = fnamemodify(l:file_on_disk, ":p:h") + let l:name = fnamemodify(l:file_on_disk, ":t") + execute "edit " . l:file_on_disk + write! + + let l:directory_on_disk2 = l:directory_on_disk1 . "_something_else" + + if !isdirectory(l:directory_on_disk2) + call mkdir(l:directory_on_disk2) + endif + + execute "cd " . l:directory_on_disk2 + execute "edit " l:name + execute "cd " . l:directory_on_disk1 + execute "edit " l:file_on_disk + execute "cd " . l:directory_on_disk2 + + let l:current = bufnr() + + call assert_equal(l:current, bufnr()) + set winfixbuf + call assert_fails("edit " . l:name, "E1513:") + call assert_equal(l:current, bufnr()) + + call delete(l:directory_on_disk1) + call delete(l:directory_on_disk2) +endfunc + +" Fail to call `:e first` if called from a starting, in-memory buffer +func Test_edit_first_buffer() + call s:reset_all_buffers() + + set winfixbuf + let l:current = bufnr() + + call assert_fails("edit first", "E1513:") + call assert_equal(l:current, bufnr()) + + edit! first + call assert_equal(l:current, bufnr()) + edit! somewhere_else + call assert_notequal(l:current, bufnr()) +endfunc + +" Allow reloading a buffer using :e +func Test_edit_no_arguments() + call s:reset_all_buffers() + + let l:current = bufnr() + file some_buffer + + call assert_equal(l:current, bufnr()) + set winfixbuf + edit + call assert_equal(l:current, bufnr()) +endfunc + +" Allow :e selecting the current buffer +func Test_edit_same_buffer_in_memory() + call s:reset_all_buffers() + + let current = bufnr() + file same_buffer + + call assert_equal(current, bufnr()) + set winfixbuf + edit same_buffer + call assert_equal(current, bufnr()) + set nowinfixbuf +endfunc + +" Allow :e selecting the current buffer as a full path +func Test_edit_same_buffer_on_disk_absolute_path() + call s:reset_all_buffers() + + let file = tempname() + " file must exist for expansion of 8.3 paths to succeed + call writefile([], file, 'D') + let file = fnamemodify(file, ':p') + let current = bufnr() + execute "edit " . file + write! + + call assert_equal(current, bufnr()) + set winfixbuf + execute "edit " file + call assert_equal(current, bufnr()) + + set nowinfixbuf +endfunc + " Fail :enew but :enew! is allowed func Test_enew() call s:reset_all_buffers() @@ -1160,7 +1298,7 @@ func Test_find() let l:current = bufnr() let l:file = tempname() - call writefile([], l:file) + call writefile([], l:file, 'D') let l:file = fnamemodify(l:file, ':p') " In case it's Windows 8.3-style. let l:directory = fnamemodify(l:file, ":p:h") let l:name = fnamemodify(l:file, ":p:t") @@ -1177,7 +1315,6 @@ func Test_find() call assert_equal(l:file, expand("%:p")) execute "set path=" . l:original_path - call delete(l:file) endfunc " Fail :first but :first! is allowed @@ -1238,8 +1375,8 @@ func Test_ijump() call writefile([ \ '#include "' . l:include_file . '"' \ ], - \ "main.c") - call writefile(["#define min(X, Y) ((X) < (Y) ? (X) : (Y))"], l:include_file) + \ "main.c", 'D') + call writefile(["#define min(X, Y) ((X) < (Y) ? (X) : (Y))"], l:include_file, 'D') edit main.c set winfixbuf @@ -1261,8 +1398,6 @@ func Test_ijump() set define& set include& set path& - call delete("main.c") - call delete(l:include_file) endfunc " Fail :lNext but :lNext! is allowed @@ -1327,7 +1462,7 @@ func Test_laddexpr() call s:reset_all_buffers() let l:file_path = tempname() - call writefile(["Error - bad-thing-found"], l:file_path) + call writefile(["Error - bad-thing-found"], l:file_path, 'D') execute "edit " . l:file_path let l:file_buffer = bufnr() let l:current = bufnr() @@ -1343,8 +1478,6 @@ func Test_laddexpr() execute 'laddexpr expand("%") .. ":" .. line(".") .. ":" .. getline(".")' call assert_equal(l:current, bufnr()) - - call delete(l:file_path) endfunc " Fail :last but :last! is allowed @@ -1367,7 +1500,7 @@ func Test_lbuffer() call s:reset_all_buffers() let l:file_path = tempname() - call writefile(["first.unittest:1:Error - bad-thing-found"], l:file_path) + call writefile(["first.unittest:1:Error - bad-thing-found"], l:file_path, 'D') execute "edit " . l:file_path let l:file_buffer = bufnr() let l:current = bufnr() @@ -1386,8 +1519,6 @@ func Test_lbuffer() execute "lbuffer! " . l:file_buffer call assert_equal("first.unittest", expand("%:t")) - - call delete(l:file_path) endfunc " Fail :ldo but :ldo! is allowed @@ -1451,7 +1582,7 @@ func Test_lfile() write let l:file = tempname() - call writefile(["first.unittest:1:Error - bad-thing-found was detected"], l:file) + call writefile(["first.unittest:1:Error - bad-thing-found was detected"], l:file, 'D') let l:current = bufnr() @@ -1463,7 +1594,6 @@ func Test_lfile() execute ":lfile! " . l:file call assert_equal(l:first, bufnr()) - call delete(l:file) call delete("first.unittest") call delete("second.unittest") endfunc @@ -1603,9 +1733,9 @@ func Test_ltag() \ "one\tXfile\t1", \ "three\tXfile\t3", \ "two\tXfile\t2"], - \ "Xtags") - call writefile(["one", "two", "three"], "Xfile") - call writefile(["one"], "Xother") + \ "Xtags", 'D') + call writefile(["one", "two", "three"], "Xfile", 'D') + call writefile(["one"], "Xother", 'D') edit Xother execute "normal \<C-]>" @@ -1618,9 +1748,6 @@ func Test_ltag() ltag! one set tags& - call delete("Xtags") - call delete("Xfile") - call delete("Xother") endfunc " Fail vim.command if we try to change buffers while 'winfixbuf' is set @@ -1826,9 +1953,9 @@ func Test_normal_g_ctrl_square_bracket_right() \ "one\tXfile\t1", \ "three\tXfile\t3", \ "two\tXfile\t2"], - \ "Xtags") - call writefile(["one", "two", "three"], "Xfile") - call writefile(["one"], "Xother") + \ "Xtags", 'D') + call writefile(["one", "two", "three"], "Xfile", 'D') + call writefile(["one"], "Xother", 'D') edit Xother set winfixbuf @@ -1839,9 +1966,6 @@ func Test_normal_g_ctrl_square_bracket_right() call assert_equal(l:current, bufnr()) set tags& - call delete("Xtags") - call delete("Xfile") - call delete("Xother") endfunc " Fail to jump to a tag with g<RightMouse> if 'winfixbuf' is enabled @@ -1854,9 +1978,9 @@ func Test_normal_g_rightmouse() \ "one\tXfile\t1", \ "three\tXfile\t3", \ "two\tXfile\t2"], - \ "Xtags") - call writefile(["one", "two", "three"], "Xfile") - call writefile(["one"], "Xother") + \ "Xtags", 'D') + call writefile(["one", "two", "three"], "Xfile", 'D') + call writefile(["one"], "Xother", 'D') edit Xother execute "normal \<C-]>" @@ -1869,9 +1993,6 @@ func Test_normal_g_rightmouse() set tags& set mouse& - call delete("Xtags") - call delete("Xfile") - call delete("Xother") endfunc " Fail to jump to a tag with g] if 'winfixbuf' is enabled @@ -1883,9 +2004,9 @@ func Test_normal_g_square_bracket_right() \ "one\tXfile\t1", \ "three\tXfile\t3", \ "two\tXfile\t2"], - \ "Xtags") - call writefile(["one", "two", "three"], "Xfile") - call writefile(["one"], "Xother") + \ "Xtags", 'D') + call writefile(["one", "two", "three"], "Xfile", 'D') + call writefile(["one"], "Xother", 'D') edit Xother set winfixbuf @@ -1896,9 +2017,6 @@ func Test_normal_g_square_bracket_right() call assert_equal(l:current, bufnr()) set tags& - call delete("Xtags") - call delete("Xfile") - call delete("Xother") endfunc " Fail to jump to a tag with <C-RightMouse> if 'winfixbuf' is enabled @@ -1911,9 +2029,9 @@ func Test_normal_ctrl_rightmouse() \ "one\tXfile\t1", \ "three\tXfile\t3", \ "two\tXfile\t2"], - \ "Xtags") - call writefile(["one", "two", "three"], "Xfile") - call writefile(["one"], "Xother") + \ "Xtags", 'D') + call writefile(["one", "two", "three"], "Xfile", 'D') + call writefile(["one"], "Xother", 'D') edit Xother execute "normal \<C-]>" @@ -1926,9 +2044,6 @@ func Test_normal_ctrl_rightmouse() set tags& set mouse& - call delete("Xtags") - call delete("Xfile") - call delete("Xother") endfunc " Fail to jump to a tag with <C-t> if 'winfixbuf' is enabled @@ -1940,9 +2055,9 @@ func Test_normal_ctrl_t() \ "one\tXfile\t1", \ "three\tXfile\t3", \ "two\tXfile\t2"], - \ "Xtags") - call writefile(["one", "two", "three"], "Xfile") - call writefile(["one"], "Xother") + \ "Xtags", 'D') + call writefile(["one", "two", "three"], "Xfile", 'D') + call writefile(["one"], "Xother", 'D') edit Xother execute "normal \<C-]>" @@ -1954,9 +2069,6 @@ func Test_normal_ctrl_t() call assert_equal(l:current, bufnr()) set tags& - call delete("Xtags") - call delete("Xfile") - call delete("Xother") endfunc " Disallow <C-^> in 'winfixbuf' windows @@ -2058,9 +2170,9 @@ func Test_normal_ctrl_square_bracket_right() \ "one\tXfile\t1", \ "three\tXfile\t3", \ "two\tXfile\t2"], - \ "Xtags") - call writefile(["one", "two", "three"], "Xfile") - call writefile(["one"], "Xother") + \ "Xtags", 'D') + call writefile(["one", "two", "three"], "Xfile", 'D') + call writefile(["one"], "Xother", 'D') edit Xother set winfixbuf @@ -2071,9 +2183,6 @@ func Test_normal_ctrl_square_bracket_right() call assert_equal(l:current, bufnr()) set tags& - call delete("Xtags") - call delete("Xfile") - call delete("Xother") endfunc " Allow <C-w><C-]> with 'winfixbuf' enabled because it runs in a new, split window @@ -2085,9 +2194,9 @@ func Test_normal_ctrl_w_ctrl_square_bracket_right() \ "one\tXfile\t1", \ "three\tXfile\t3", \ "two\tXfile\t2"], - \ "Xtags") - call writefile(["one", "two", "three"], "Xfile") - call writefile(["one"], "Xother") + \ "Xtags", 'D') + call writefile(["one", "two", "three"], "Xfile", 'D') + call writefile(["one"], "Xother", 'D') edit Xother set winfixbuf @@ -2097,9 +2206,6 @@ func Test_normal_ctrl_w_ctrl_square_bracket_right() call assert_equal(l:current_windows + 1, s:get_windows_count()) set tags& - call delete("Xtags") - call delete("Xfile") - call delete("Xother") endfunc " Allow <C-w>g<C-]> with 'winfixbuf' enabled because it runs in a new, split window @@ -2111,9 +2217,9 @@ func Test_normal_ctrl_w_g_ctrl_square_bracket_right() \ "one\tXfile\t1", \ "three\tXfile\t3", \ "two\tXfile\t2"], - \ "Xtags") - call writefile(["one", "two", "three"], "Xfile") - call writefile(["one"], "Xother") + \ "Xtags", 'D') + call writefile(["one", "two", "three"], "Xfile", 'D') + call writefile(["one"], "Xother", 'D') edit Xother set winfixbuf @@ -2123,9 +2229,6 @@ func Test_normal_ctrl_w_g_ctrl_square_bracket_right() call assert_equal(l:current_windows + 1, s:get_windows_count()) set tags& - call delete("Xtags") - call delete("Xfile") - call delete("Xother") endfunc " Fail to jump to a tag with <C-]> if 'winfixbuf' is enabled @@ -2137,9 +2240,9 @@ func Test_normal_gt() \ "one\tXfile\t1", \ "three\tXfile\t3", \ "two\tXfile\t2"], - \ "Xtags") - call writefile(["one", "two", "three"], "Xfile") - call writefile(["one", "two", "three"], "Xother") + \ "Xtags", 'D') + call writefile(["one", "two", "three"], "Xfile", 'D') + call writefile(["one", "two", "three"], "Xother", 'D') edit Xother set winfixbuf @@ -2150,9 +2253,6 @@ func Test_normal_gt() call assert_equal(l:current, bufnr()) set tags& - call delete("Xtags") - call delete("Xfile") - call delete("Xother") endfunc " Prevent gF from switching a 'winfixbuf' window's buffer @@ -2161,7 +2261,7 @@ func Test_normal_gF() let l:file = tempname() call append(0, [l:file]) - call writefile([], l:file) + call writefile([], l:file, 'D') " Place the cursor onto the line that has `l:file` normal gg " Prevent Vim from erroring with "No write since last change @ command @@ -2180,7 +2280,7 @@ func Test_normal_gF() normal gF call assert_notequal(l:buffer, bufnr()) - call delete(l:file) + set nohidden endfunc " Prevent gf from switching a 'winfixbuf' window's buffer @@ -2189,7 +2289,7 @@ func Test_normal_gf() let l:file = tempname() call append(0, [l:file]) - call writefile([], l:file) + call writefile([], l:file, 'D') " Place the cursor onto the line that has `l:file` normal gg " Prevent Vim from erroring with "No write since last change @ command @@ -2208,7 +2308,7 @@ func Test_normal_gf() normal gf call assert_notequal(l:buffer, bufnr()) - call delete(l:file) + set nohidden endfunc " Fail "goto file under the cursor" (using [f, which is the same as `:normal gf`) @@ -2217,7 +2317,7 @@ func Test_normal_square_bracket_left_f() let l:file = tempname() call append(0, [l:file]) - call writefile([], l:file) + call writefile([], l:file, 'D') " Place the cursor onto the line that has `l:file` normal gg " Prevent Vim from erroring with "No write since last change @ command @@ -2236,7 +2336,7 @@ func Test_normal_square_bracket_left_f() normal [f call assert_notequal(l:buffer, bufnr()) - call delete(l:file) + set nohidden endfunc " Fail to go to a C macro with [<C-d> if 'winfixbuf' is enabled @@ -2247,8 +2347,8 @@ func Test_normal_square_bracket_left_ctrl_d() call writefile(["min(1, 12);", \ '#include "' . l:include_file . '"' \ ], - \ "main.c") - call writefile(["#define min(X, Y) ((X) < (Y) ? (X) : (Y))"], l:include_file) + \ "main.c", 'D') + call writefile(["#define min(X, Y) ((X) < (Y) ? (X) : (Y))"], l:include_file, 'D') edit main.c normal ]\<C-d> @@ -2263,9 +2363,6 @@ func Test_normal_square_bracket_left_ctrl_d() execute "normal [\<C-d>" call assert_notequal(l:current, bufnr()) - - call delete("main.c") - call delete(l:include_file) endfunc " Fail to go to a C macro with ]<C-d> if 'winfixbuf' is enabled @@ -2276,8 +2373,8 @@ func Test_normal_square_bracket_right_ctrl_d() call writefile(["min(1, 12);", \ '#include "' . l:include_file . '"' \ ], - \ "main.c") - call writefile(["#define min(X, Y) ((X) < (Y) ? (X) : (Y))"], l:include_file) + \ "main.c", 'D') + call writefile(["#define min(X, Y) ((X) < (Y) ? (X) : (Y))"], l:include_file, 'D') edit main.c set winfixbuf @@ -2291,9 +2388,6 @@ func Test_normal_square_bracket_right_ctrl_d() execute "normal ]\<C-d>" call assert_notequal(l:current, bufnr()) - - call delete("main.c") - call delete(l:include_file) endfunc " Fail to go to a C macro with [<C-i> if 'winfixbuf' is enabled @@ -2304,8 +2398,8 @@ func Test_normal_square_bracket_left_ctrl_i() call writefile(['#include "' . l:include_file . '"', \ "min(1, 12);", \ ], - \ "main.c") - call writefile(["#define min(X, Y) ((X) < (Y) ? (X) : (Y))"], l:include_file) + \ "main.c", 'D') + call writefile(["#define min(X, Y) ((X) < (Y) ? (X) : (Y))"], l:include_file, 'D') edit main.c " Move to the line with `min(1, 12);` on it" normal j @@ -2328,8 +2422,6 @@ func Test_normal_square_bracket_left_ctrl_i() set define& set include& set path& - call delete("main.c") - call delete(l:include_file) endfunc " Fail to go to a C macro with ]<C-i> if 'winfixbuf' is enabled @@ -2340,8 +2432,8 @@ func Test_normal_square_bracket_right_ctrl_i() call writefile(["min(1, 12);", \ '#include "' . l:include_file . '"' \ ], - \ "main.c") - call writefile(["#define min(X, Y) ((X) < (Y) ? (X) : (Y))"], l:include_file) + \ "main.c", 'D') + call writefile(["#define min(X, Y) ((X) < (Y) ? (X) : (Y))"], l:include_file, 'D') edit main.c set winfixbuf @@ -2363,8 +2455,6 @@ func Test_normal_square_bracket_right_ctrl_i() set define& set include& set path& - call delete("main.c") - call delete(l:include_file) endfunc " Fail "goto file under the cursor" (using ]f, which is the same as `:normal gf`) @@ -2373,7 +2463,7 @@ func Test_normal_square_bracket_right_f() let l:file = tempname() call append(0, [l:file]) - call writefile([], l:file) + call writefile([], l:file, 'D') " Place the cursor onto the line that has `l:file` normal gg " Prevent Vim from erroring with "No write since last change @ command @@ -2392,7 +2482,7 @@ func Test_normal_square_bracket_right_f() normal ]f call assert_notequal(l:buffer, bufnr()) - call delete(l:file) + set nohidden endfunc " Fail to jump to a tag with v<C-]> if 'winfixbuf' is enabled @@ -2404,9 +2494,9 @@ func Test_normal_v_ctrl_square_bracket_right() \ "one\tXfile\t1", \ "three\tXfile\t3", \ "two\tXfile\t2"], - \ "Xtags") - call writefile(["one", "two", "three"], "Xfile") - call writefile(["one"], "Xother") + \ "Xtags", 'D') + call writefile(["one", "two", "three"], "Xfile", 'D') + call writefile(["one"], "Xother", 'D') edit Xother set winfixbuf @@ -2417,9 +2507,6 @@ func Test_normal_v_ctrl_square_bracket_right() call assert_equal(l:current, bufnr()) set tags& - call delete("Xtags") - call delete("Xfile") - call delete("Xother") endfunc " Fail to jump to a tag with vg<C-]> if 'winfixbuf' is enabled @@ -2431,9 +2518,9 @@ func Test_normal_v_g_ctrl_square_bracket_right() \ "one\tXfile\t1", \ "three\tXfile\t3", \ "two\tXfile\t2"], - \ "Xtags") - call writefile(["one", "two", "three"], "Xfile") - call writefile(["one"], "Xother") + \ "Xtags", 'D') + call writefile(["one", "two", "three"], "Xfile", 'D') + call writefile(["one"], "Xother", 'D') edit Xother set winfixbuf @@ -2444,9 +2531,6 @@ func Test_normal_v_g_ctrl_square_bracket_right() call assert_equal(l:current, bufnr()) set tags& - call delete("Xtags") - call delete("Xfile") - call delete("Xother") endfunc " Allow :pedit because, unlike :edit, it uses a separate window @@ -2471,9 +2555,9 @@ func Test_pop() \ "thesame\tXfile\t2;\"\td\tfile:", \ "thesame\tXfile\t3;\"\td\tfile:", \ ], - \ "Xtags") - call writefile(["thesame one", "thesame two", "thesame three"], "Xfile") - call writefile(["thesame one"], "Xother") + \ "Xtags", 'D') + call writefile(["thesame one", "thesame two", "thesame three"], "Xfile", 'D') + call writefile(["thesame one"], "Xother", 'D') edit Xother tag thesame @@ -2489,9 +2573,6 @@ func Test_pop() call assert_notequal(l:current, bufnr()) set tags& - call delete("Xtags") - call delete("Xfile") - call delete("Xother") endfunc " Fail :previous but :previous! is allowed @@ -2559,7 +2640,7 @@ func Test_pythonx_pyxfile() \ "buffer = vim.vars['_previous_buffer']", \ "vim.current.buffer = vim.buffers[buffer]", \ ], - \ "file.py") + \ "file.py", 'D') try pyxfile file.py @@ -2569,7 +2650,6 @@ func Test_pythonx_pyxfile() call assert_equal(1, l:caught) - call delete("file.py") unlet g:_previous_buffer endfunc @@ -2696,11 +2776,11 @@ func Test_short_option() call s:make_buffer_pairs() set winfixbuf - call assert_fails("edit something_else", "E1513") + call assert_fails("edit something_else", "E1513:") set nowinfixbuf set wfb - call assert_fails("edit another_place", "E1513") + call assert_fails("edit another_place", "E1513:") set nowfb edit last_place @@ -2747,9 +2827,9 @@ func Test_tNext() \ "thesame\tXfile\t2;\"\td\tfile:", \ "thesame\tXfile\t3;\"\td\tfile:", \ ], - \ "Xtags") - call writefile(["thesame one", "thesame two", "thesame three"], "Xfile") - call writefile(["thesame one"], "Xother") + \ "Xtags", 'D') + call writefile(["thesame one", "thesame two", "thesame three"], "Xfile", 'D') + call writefile(["thesame one"], "Xother", 'D') edit Xother tag thesame @@ -2766,9 +2846,6 @@ func Test_tNext() tNext! set tags& - call delete("Xtags") - call delete("Xfile") - call delete("Xother") endfunc " Call :tabdo and choose the next available 'nowinfixbuf' window. @@ -2826,9 +2903,9 @@ func Test_tag() \ "one\tXfile\t1", \ "three\tXfile\t3", \ "two\tXfile\t2"], - \ "Xtags") - call writefile(["one", "two", "three"], "Xfile") - call writefile(["one"], "Xother") + \ "Xtags", 'D') + call writefile(["one", "two", "three"], "Xfile", 'D') + call writefile(["one"], "Xother", 'D') edit Xother set winfixbuf @@ -2842,9 +2919,6 @@ func Test_tag() call assert_notequal(l:current, bufnr()) set tags& - call delete("Xtags") - call delete("Xfile") - call delete("Xother") endfunc @@ -2857,9 +2931,9 @@ func Test_tfirst() \ "one\tXfile\t1", \ "three\tXfile\t3", \ "two\tXfile\t2"], - \ "Xtags") - call writefile(["one", "two", "three"], "Xfile") - call writefile(["one"], "Xother") + \ "Xtags", 'D') + call writefile(["one", "two", "three"], "Xfile", 'D') + call writefile(["one"], "Xother", 'D') edit Xother set winfixbuf @@ -2873,9 +2947,6 @@ func Test_tfirst() call assert_notequal(l:current, bufnr()) set tags& - call delete("Xtags") - call delete("Xfile") - call delete("Xother") endfunc " Fail :tjump but :tjump! is allowed @@ -2887,9 +2958,9 @@ func Test_tjump() \ "one\tXfile\t1", \ "three\tXfile\t3", \ "two\tXfile\t2"], - \ "Xtags") - call writefile(["one", "two", "three"], "Xfile") - call writefile(["one"], "Xother") + \ "Xtags", 'D') + call writefile(["one", "two", "three"], "Xfile", 'D') + call writefile(["one"], "Xother", 'D') edit Xother set winfixbuf @@ -2903,9 +2974,6 @@ func Test_tjump() call assert_notequal(l:current, bufnr()) set tags& - call delete("Xtags") - call delete("Xfile") - call delete("Xother") endfunc " Fail :tlast but :tlast! is allowed @@ -2917,8 +2985,8 @@ func Test_tlast() \ "one\tXfile\t1", \ "three\tXfile\t3", \ "two\tXfile\t2"], - \ "Xtags") - call writefile(["one", "two", "three"], "Xfile") + \ "Xtags", 'D') + call writefile(["one", "two", "three"], "Xfile", 'D') edit Xfile tjump one edit Xfile @@ -2934,8 +3002,6 @@ func Test_tlast() call assert_equal(l:current, bufnr()) set tags& - call delete("Xtags") - call delete("Xfile") endfunc " Fail :tnext but :tnext! is allowed @@ -2948,9 +3014,9 @@ func Test_tnext() \ "thesame\tXfile\t2;\"\td\tfile:", \ "thesame\tXfile\t3;\"\td\tfile:", \ ], - \ "Xtags") - call writefile(["thesame one", "thesame two", "thesame three"], "Xfile") - call writefile(["thesame one"], "Xother") + \ "Xtags", 'D') + call writefile(["thesame one", "thesame two", "thesame three"], "Xfile", 'D') + call writefile(["thesame one"], "Xother", 'D') edit Xother tag thesame @@ -2967,9 +3033,6 @@ func Test_tnext() call assert_notequal(l:current, bufnr()) set tags& - call delete("Xtags") - call delete("Xfile") - call delete("Xother") endfunc " Fail :tprevious but :tprevious! is allowed @@ -2982,9 +3045,9 @@ func Test_tprevious() \ "thesame\tXfile\t2;\"\td\tfile:", \ "thesame\tXfile\t3;\"\td\tfile:", \ ], - \ "Xtags") - call writefile(["thesame one", "thesame two", "thesame three"], "Xfile") - call writefile(["thesame one"], "Xother") + \ "Xtags", 'D') + call writefile(["thesame one", "thesame two", "thesame three"], "Xfile", 'D') + call writefile(["thesame one"], "Xother", 'D') edit Xother tag thesame @@ -3001,9 +3064,6 @@ func Test_tprevious() tprevious! set tags& - call delete("Xtags") - call delete("Xfile") - call delete("Xother") endfunc " Fail :view but :view! is allowed @@ -3283,4 +3343,15 @@ func Test_bufdo_cnext_splitwin_fails() set winminheight&vim winheight&vim endfunc +" Test that exiting with 'winfixbuf' and EXITFREE doesn't cause an error. +func Test_exitfree_no_error() + let lines =<< trim END + set winfixbuf + qall! + END + call writefile(lines, 'Xwfb_exitfree', 'D') + call assert_notmatch('E1513:', + \ system(GetVimCommandClean() .. ' --not-a-term -X -S Xwfb_exitfree')) +endfunc + " vim: shiftwidth=2 sts=2 expandtab diff --git a/src/testdir/test_xdg.vim b/src/testdir/test_xdg.vim new file mode 100644 index 0000000..6f35b72 --- /dev/null +++ b/src/testdir/test_xdg.vim @@ -0,0 +1,295 @@ +" Tests for the XDG feature + +source check.vim +source shared.vim + +func s:get_rcs() + let rcs = { + \ 'file1': { 'path': '~/.vimrc' }, + \ 'file2': { 'path': '~/.vim/vimrc' }, + \ 'xdg': { 'path': exists('$XDG_CONFIG_HOME') ? '$XDG_CONFIG_HOME' : "~/.config" }, + \} + for v in values(rcs) + let v.exists = filereadable(expand(v.path)) + endfor + return rcs +endfunc + +func Test_xdg_rc_detection() + CheckUnix + let rc = s:get_rcs() + let before =<< trim CODE + call writefile([expand('$MYVIMRC')], "XMY_VIMRC") + quit! + CODE + call RunVim(before, [], "") + let my_rc = readfile("XMY_VIMRC") + if rc.file1.exists + call assert_equal(rc.file1.path, my_rc) + elseif !rc.file1.exists && rc.file2.exists + call assert_equal(rc.file2.path, my_rc) + elseif !rc.file1.exists && !rc.file2.exists && rc.xdg.exists + call assert_equal(rc.xdg.path, my_rc) + endif + call delete("XMY_VIMRC") +endfunc + +func Test_xdg_runtime_files() + " This tests, that the initialization file from + " ~/.vimrc, ~/.vim/vimrc and ~/.config/vim/vimrc (or + " $XDG_CONFIG_HOME/vim/vimrc) are sourced in that order + CheckUnix + call mkdir(expand('~/.vim/'), 'pD') + call mkdir(expand('~/.config/vim/'), 'pD') + call mkdir(expand('~/xdg/vim/'), 'pD') + + let rc1=expand('~/.vimrc') + let rc2=expand('~/.vim/vimrc') + let rc3=expand('~/.config/vim/vimrc') + let rc4=expand('~/xdg/vim/vimrc') + + " g:rc_one|two|three|four is to verify, that the other + " init files are not sourced + " g:rc is to verify which rc file has been loaded. + let file1 =<< trim CODE + let g:rc_one = 'one' + let g:rc = '.vimrc' + CODE + let file2 =<< trim CODE + let g:rc_two = 'two' + let g:rc = '.vim/vimrc' + CODE + let file3 =<< trim CODE + let g:rc_three = 'three' + let g:rc = '.config/vim/vimrc' + CODE + let file4 =<< trim CODE + let g:rc_four = 'four' + let g:rc = 'xdg/vim/vimrc' + CODE + call writefile(file1, rc1) + call writefile(file2, rc2) + call writefile(file3, rc3) + call writefile(file4, rc4) + + " Get the Vim command to run without the '-u NONE' argument + let vimcmd = substitute(GetVimCommand(), '-u NONE', '', '') + + " Test for ~/.vimrc + let lines =<< trim END + call assert_match('XfakeHOME/\.vimrc', $MYVIMRC) + call filter(g:, {idx, _ -> idx =~ '^rc'}) + call assert_equal(#{rc_one: 'one', rc: '.vimrc'}, g:) + call writefile(v:errors, 'Xresult') + quit + END + call writefile(lines, 'Xscript', 'D') + call system($'{vimcmd} -S Xscript') + call assert_equal([], readfile('Xresult')) + + call delete(rc1) + + " Test for ~/.vim/vimrc + let lines =<< trim END + call assert_match('XfakeHOME/\.vim/vimrc', $MYVIMRC) + call filter(g:, {idx, _ -> idx =~ '^rc'}) + call assert_equal(#{rc_two: 'two', rc: '.vim/vimrc'}, g:) + call writefile(v:errors, 'Xresult') + quit + END + call writefile(lines, 'Xscript', 'D') + call system($'{vimcmd} -S Xscript') + call assert_equal([], readfile('Xresult')) + + call delete(rc2) + + " XDG_CONFIG_HOME is set in Github CI runners + unlet $XDG_CONFIG_HOME + + " Test for ~/.config/vim/vimrc + let lines =<< trim END + let msg = $'HOME="{$HOME}", ~="{expand("~")}"' + call assert_match('XfakeHOME/\.config/vim/vimrc', $MYVIMRC, msg) + call filter(g:, {idx, _ -> idx =~ '^rc'}) + call assert_equal(#{rc_three: 'three', rc: '.config/vim/vimrc'}, g:) + call writefile(v:errors, 'Xresult') + quit + END + call writefile(lines, 'Xscript', 'D') + call system($'{vimcmd} -S Xscript') + call assert_equal([], readfile('Xresult')) + + call delete(rc3) + + " Test for ~/xdg/vim/vimrc + let $XDG_CONFIG_HOME=expand('~/xdg/') + let lines =<< trim END + let msg = $'HOME="{$HOME}", XDG_CONFIG_HOME="{$XDG_CONFIG_HOME}"' + call assert_match('XfakeHOME/xdg/vim/vimrc', $MYVIMRC, msg) + call filter(g:, {idx, _ -> idx =~ '^rc'}) + call assert_equal(#{rc_four: 'four', rc: 'xdg/vim/vimrc'}, g:) + call writefile(v:errors, 'Xresult') + quit + END + call writefile(lines, 'Xscript', 'D') + call system($'{vimcmd} -S Xscript') + call assert_equal([], readfile('Xresult')) + + call delete(rc4) + unlet $XDG_CONFIG_HOME +endfunc + +func Test_xdg_version() + CheckUnix + let $HOME = getcwd() .. '/XfakeHOME' + unlet $XDG_CONFIG_HOME + let a = execute(':version')->split('\n') + let a = filter(a, { _, val -> val =~ '\.config\|XDG_CONFIG_HOME' }) + " There should be 1 entry for gvimrc and 1 entry for vimrc, + " but only if Vim was compiled with gui support + call assert_equal(1 + has("gui"), len(a)) + call assert_match('\~/\.config/vim/vimrc', a[0]) + if has("gui") + call assert_match('\~/\.config/vim/gvimrc', a[1]) + endif + + let $XDG_CONFIG_HOME = expand('~/.xdg') + let a = execute(':version')->split('\n') + let a = filter(a, { _, val -> val =~ '\.config\|XDG_CONFIG_HOME' }) + call assert_equal(1 + has("gui"), len(a)) + call assert_match('XDG_CONFIG_HOME/vim/vimrc', a[0]) + if has("gui") + call assert_match('XDG_CONFIG_HOME/vim/gvimrc', a[1]) + endif + unlet $XDG_CONFIG_HOME +endfunc + +" Test for gvimrc, must be last, since it starts the GUI +" and sources a few extra test files +func Test_zzz_xdg_runtime_files() + CheckCanRunGui + CheckUnix + + " Is setup in Github Runner + unlet $XDG_CONFIG_HOME + source setup_gui.vim + call GUISetUpCommon() + + " This tests, that the GUI initialization file from + " ~/.gvimrc, ~/.vim/gvimrc, ~/.config/vim/gvimrc + " and ~/XDG_CONFIG_HOME/vim/gvimrc is sourced + " when starting GUI mode + call mkdir(expand('~/.vim/'), 'pD') + call mkdir(expand('~/.config/vim/'), 'pD') + call mkdir(expand('~/xdg/vim/'), 'pD') + + let rc1=expand('~/.gvimrc') + let rc2=expand('~/.vim/gvimrc') + let rc3=expand('~/.config/vim/gvimrc') + let rc4=expand('~/xdg/vim/gvimrc') + + " g:rc_one|two|three|four is to verify, that the other + " init files are not sourced + " g:rc is to verify which rc file has been loaded. + let file1 =<< trim CODE + let g:rc_one = 'one' + let g:rc = '.gvimrc' + CODE + let file2 =<< trim CODE + let g:rc_two = 'two' + let g:rc = '.vim/gvimrc' + CODE + let file3 =<< trim CODE + let g:rc_three = 'three' + let g:rc = '.config/vim/gvimrc' + CODE + let file4 =<< trim CODE + let g:rc_four = 'four' + let g:rc = 'xdg/vim/gvimrc' + CODE + call writefile(file1, rc1) + call writefile(file2, rc2) + call writefile(file3, rc3) + call writefile(file4, rc4) + + " Get the Vim command to run without the '-u NONE' argument + let vimcmd = substitute(GetVimCommand(), '-u NONE', '', '') + + " Test for ~/.gvimrc + let lines =<< trim END + " Ignore the "failed to create input context" error. + call test_ignore_error('E285') + gui -f + call assert_match('Xhome/\.gvimrc', $MYGVIMRC) + call filter(g:, {idx, _ -> idx =~ '^rc'}) + call assert_equal(#{rc_one: 'one', rc: '.gvimrc'}, g:) + call writefile(v:errors, 'Xresult') + quit + END + call writefile(lines, 'Xscript', 'D') + call system($'{vimcmd} -S Xscript') + call assert_equal([], readfile('Xresult')) + + call delete(rc1) + + " Test for ~/.vim/gvimrc + let lines =<< trim END + " Ignore the "failed to create input context" error. + call test_ignore_error('E285') + gui -f + call assert_match('Xhome/\.vim/gvimrc', $MYGVIMRC) + call filter(g:, {idx, _ -> idx =~ '^rc'}) + call assert_equal(#{rc_two: 'two', rc: '.vim/gvimrc'}, g:) + call writefile(v:errors, 'Xresult') + quit + END + call writefile(lines, 'Xscript', 'D') + call system($'{vimcmd} -S Xscript') + call assert_equal([], readfile('Xresult')) + + call delete(rc2) + + " Test for ~/.config/vim/gvimrc + let lines =<< trim END + " Ignore the "failed to create input context" error. + call test_ignore_error('E285') + gui -f + let msg = $'HOME="{$HOME}", ~="{expand("~")}"' + call assert_match('Xhome/\.config/vim/gvimrc', $MYGVIMRC, msg) + call filter(g:, {idx, _ -> idx =~ '^rc'}) + call assert_equal(#{rc_three: 'three', rc: '.config/vim/gvimrc'}, g:) + call writefile(v:errors, 'Xresult') + quit + END + call writefile(lines, 'Xscript', 'D') + call system($'{vimcmd} -S Xscript') + call assert_equal([], readfile('Xresult')) + + call delete(rc3) + + " Test for ~/xdg/vim/gvimrc + let $XDG_CONFIG_HOME=expand('~/xdg/') + let lines =<< trim END + " Ignore the "failed to create input context" error. + call test_ignore_error('E285') + gui -f + let msg = $'HOME="{$HOME}", XDG_CONFIG_HOME="{$XDG_CONFIG_HOME}"' + call assert_match('Xhome/xdg/vim/gvimrc', $MYGVIMRC, msg) + call filter(g:, {idx, _ -> idx =~ '^rc'}) + call assert_equal(#{rc_four: 'four', rc: 'xdg/vim/gvimrc'}, g:) + call writefile(v:errors, 'Xresult') + quit + END + call writefile(lines, 'Xscript', 'D') + call system($'{vimcmd} -S Xscript') + call assert_equal([], readfile('Xresult')) + + call delete(rc4) + + " Clean up + unlet $XDG_CONFIG_HOME + call GUITearDownCommon() + call delete('Xhome', 'rf') +endfunc + +" vim: shiftwidth=2 sts=2 expandtab diff --git a/src/testdir/vim9.vim b/src/testdir/vim9.vim index 782809b..ff4db7b 100644 --- a/src/testdir/vim9.vim +++ b/src/testdir/vim9.vim @@ -110,40 +110,6 @@ export def CheckScriptSuccess(lines: list<string>) endtry enddef -# :source a list of "lines" and check whether it fails with "error" -export def CheckSourceFailure(lines: list<string>, error: string, lnum = -3) - new - setline(1, lines) - try - assert_fails('source', error, lines, lnum) - finally - bw! - endtry -enddef - -# :source a list of "lines" and check whether it fails with the list of -# "errors" -export def CheckSourceFailureList(lines: list<string>, errors: list<string>, lnum = -3) - new - setline(1, lines) - try - assert_fails('source', errors, lines, lnum) - finally - bw! - endtry -enddef - -# :source a list of "lines" and check whether it succeeds -export def CheckSourceSuccess(lines: list<string>) - new - setline(1, lines) - try - :source - finally - bw! - endtry -enddef - export def CheckDefAndScriptSuccess(lines: list<string>) CheckDefSuccess(lines) CheckScriptSuccess(['vim9script'] + lines) @@ -307,3 +273,177 @@ export def CheckLegacyAndVim9Failure(lines: list<string>, error: any) CheckDefExecFailure(vim9lines, defError) CheckScriptFailure(['vim9script'] + vim9lines, scriptError) enddef + +# :source a list of "lines" and check whether it fails with "error" +export def CheckSourceScriptFailure(lines: list<string>, error: string, lnum = -3) + var cwd = getcwd() + new + setline(1, lines) + var bnr = bufnr() + try + assert_fails('source', error, lines, lnum) + finally + chdir(cwd) + exe $':bw! {bnr}' + endtry +enddef + +# :source a list of "lines" and check whether it fails with the list of +# "errors" +export def CheckSourceScriptFailureList(lines: list<string>, errors: list<string>, lnum = -3) + var cwd = getcwd() + new + var bnr = bufnr() + setline(1, lines) + try + assert_fails('source', errors, lines, lnum) + finally + chdir(cwd) + exe $':bw! {bnr}' + endtry +enddef + +# :source a list of "lines" and check whether it succeeds +export def CheckSourceScriptSuccess(lines: list<string>) + var cwd = getcwd() + new + var bnr = bufnr() + setline(1, lines) + try + :source + finally + chdir(cwd) + exe $':bw! {bnr}' + endtry +enddef + +export def CheckSourceSuccess(lines: list<string>) + CheckSourceScriptSuccess(lines) +enddef + +export def CheckSourceFailure(lines: list<string>, error: string, lnum = -3) + CheckSourceScriptFailure(lines, error, lnum) +enddef + +export def CheckSourceFailureList(lines: list<string>, errors: list<string>, lnum = -3) + CheckSourceScriptFailureList(lines, errors, lnum) +enddef + +# :source a List of "lines" inside a ":def" function and check that no error +# occurs when called. +export func CheckSourceDefSuccess(lines) + let cwd = getcwd() + new + let bnr = bufnr() + call setline(1, ['def Func()'] + a:lines + ['enddef', 'defcompile']) + try + source + call Func() + finally + call chdir(cwd) + delfunc! Func + exe $'bw! {bnr}' + endtry +endfunc + +export def CheckSourceDefAndScriptSuccess(lines: list<string>) + CheckSourceDefSuccess(lines) + CheckSourceScriptSuccess(['vim9script'] + lines) +enddef + +# Check that "lines" inside a ":def" function has no error when compiled. +export func CheckSourceDefCompileSuccess(lines) + let cwd = getcwd() + new + let bnr = bufnr() + call setline(1, ['def Func()', '# comment'] + a:lines + ['#comment', 'enddef', 'defcompile']) + try + source + finally + call chdir(cwd) + delfunc! Func + exe $':bw! {bnr}' + endtry +endfunc + +# Check that "lines" inside ":def" results in an "error" message. +# If "lnum" is given check that the error is reported for this line. +# Add a line before and after to make it less likely that the line number is +# accidentally correct. +export func CheckSourceDefFailure(lines, error, lnum = -3) + let cwd = getcwd() + new + let bnr = bufnr() + call setline(1, ['def Func()', '# comment'] + a:lines + ['#comment', 'enddef', 'defcompile']) + try + call assert_fails('source', a:error, a:lines, a:lnum + 1) + finally + call chdir(cwd) + delfunc! Func + exe $':bw! {bnr}' + endtry +endfunc + +# Check that "lines" inside ":def" results in an "error" message when executed. +# If "lnum" is given check that the error is reported for this line. +# Add a line before and after to make it less likely that the line number is +# accidentally correct. +export func CheckSourceDefExecFailure(lines, error, lnum = -3) + let cwd = getcwd() + new + let bnr = bufnr() + call setline(1, ['def Func()', '# comment'] + a:lines + ['#comment', 'enddef']) + try + source + call assert_fails('call Func()', a:error, a:lines, a:lnum + 1) + finally + call chdir(cwd) + delfunc! Func + exe $':bw! {bnr}' + endtry +endfunc + +# Check that a command fails when used in a :def function and when used in +# Vim9 script. +# When "error" is a string, both with the same error. +# When "error" is a list, the :def function fails with "error[0]" , the script +# fails with "error[1]". +export def CheckSourceDefAndScriptFailure(lines: list<string>, error: any, lnum = -3) + var errorDef: string + var errorScript: string + if type(error) == v:t_string + errorDef = error + errorScript = error + elseif type(error) == v:t_list && len(error) == 2 + errorDef = error[0] + errorScript = error[1] + else + echoerr 'error argument must be a string or a list with two items' + return + endif + CheckSourceDefFailure(lines, errorDef, lnum) + CheckSourceScriptFailure(['vim9script'] + lines, errorScript, lnum + 1) +enddef + +# Check that a command fails when executed in a :def function and when used in +# Vim9 script. +# When "error" is a string, both with the same error. +# When "error" is a list, the :def function fails with "error[0]" , the script +# fails with "error[1]". +export def CheckSourceDefExecAndScriptFailure(lines: list<string>, error: any, lnum = -3) + var errorDef: string + var errorScript: string + if type(error) == v:t_string + errorDef = error + errorScript = error + elseif type(error) == v:t_list && len(error) == 2 + errorDef = error[0] + errorScript = error[1] + else + echoerr 'error argument must be a string or a list with two items' + return + endif + CheckSourceDefExecFailure(lines, errorDef, lnum) + CheckSourceScriptFailure(['vim9script'] + lines, errorScript, lnum + 1) +enddef + diff --git a/src/testing.c b/src/testing.c index 0d731da..33de3a5 100644 --- a/src/testing.c +++ b/src/testing.c @@ -1091,9 +1091,8 @@ f_test_refcount(typval_T *argvars, typval_T *rettv) case VAR_SPECIAL: case VAR_STRING: case VAR_INSTR: - case VAR_CLASS: - case VAR_OBJECT: break; + case VAR_JOB: #ifdef FEAT_JOB_CHANNEL if (argvars[0].vval.v_job != NULL) @@ -1132,6 +1131,14 @@ f_test_refcount(typval_T *argvars, typval_T *rettv) if (argvars[0].vval.v_dict != NULL) retval = argvars[0].vval.v_dict->dv_refcount - 1; break; + case VAR_CLASS: + if (argvars[0].vval.v_class != NULL) + retval = argvars[0].vval.v_class->class_refcount - 1; + break; + case VAR_OBJECT: + if (argvars[0].vval.v_object != NULL) + retval = argvars[0].vval.v_object->obj_refcount - 1; + break; case VAR_TYPEALIAS: if (argvars[0].vval.v_typealias != NULL) retval = argvars[0].vval.v_typealias->ta_refcount - 1; diff --git a/src/textformat.c b/src/textformat.c index 14acc53..41ec2cf 100644 --- a/src/textformat.c +++ b/src/textformat.c @@ -56,6 +56,7 @@ internal_format( colnr_T leader_len; int no_leader = FALSE; int do_comments = (flags & INSCHAR_DO_COM); + int safe_tw = trim_to_int(8 * (vimlong_T)textwidth); #ifdef FEAT_LINEBREAK int has_lbr = curwin->w_p_lbr; @@ -95,7 +96,7 @@ internal_format( // Cursor is currently at the end of line. No need to format // if line length is less than textwidth (8 * textwidth for // utf safety) - if (curwin->w_cursor.col < 8 * textwidth) + if (curwin->w_cursor.col < safe_tw) { virtcol = get_nolist_virtcol() + char2cells(c != NUL ? c : gchar_cursor()); @@ -156,8 +157,7 @@ internal_format( // line to textwidth border every time for each line break. // // Ceil to 8 * textwidth to optimize. - curwin->w_cursor.col = startcol < 8 * textwidth ? startcol : - 8 * textwidth; + curwin->w_cursor.col = startcol < safe_tw ? startcol : safe_tw; foundcol = 0; skip_pos = 0; diff --git a/src/textprop.c b/src/textprop.c index a976570..83c42a3 100644 --- a/src/textprop.c +++ b/src/textprop.c @@ -672,16 +672,10 @@ prop_count_above_below(buf_T *buf, linenr_T lnum) mch_memmove(&prop, props + i * sizeof(prop), sizeof(prop)); if (prop.tp_col == MAXCOL && text_prop_type_valid(buf, &prop)) { - if ((prop.tp_flags & TP_FLAG_ALIGN_BELOW) + if ((prop.tp_flags & (TP_FLAG_ALIGN_ABOVE | TP_FLAG_ALIGN_BELOW)) || (next_right_goes_below && (prop.tp_flags & TP_FLAG_ALIGN_RIGHT))) { - next_right_goes_below = TRUE; - ++result; - } - else if (prop.tp_flags & TP_FLAG_ALIGN_ABOVE) - { - next_right_goes_below = FALSE; ++result; } else if (prop.tp_flags & TP_FLAG_ALIGN_RIGHT) diff --git a/src/typval.c b/src/typval.c index 62958f6..6a73719 100644 --- a/src/typval.c +++ b/src/typval.c @@ -266,7 +266,13 @@ tv_get_bool_or_number_chk( check_typval_is_value(varp); break; case VAR_OBJECT: - emsg(_(e_using_object_as_number)); + { + class_T *cl = varp->vval.v_object->obj_class; + if (cl != NULL && IS_ENUM(cl)) + semsg(_(e_using_enum_str_as_number), cl->class_name); + else + emsg(_(e_using_object_as_number)); + } break; case VAR_VOID: emsg(_(e_cannot_use_void_value)); @@ -1139,7 +1145,13 @@ tv_get_string_buf_chk_strict(typval_T *varp, char_u *buf, int strict) check_typval_is_value(varp); break; case VAR_OBJECT: - emsg(_(e_using_object_as_string)); + { + class_T *cl = varp->vval.v_object->obj_class; + if (cl != NULL && IS_ENUM(cl)) + semsg(_(e_using_enum_str_as_string), cl->class_name); + else + emsg(_(e_using_object_as_string)); + } break; case VAR_JOB: #ifdef FEAT_JOB_CHANNEL diff --git a/src/userfunc.c b/src/userfunc.c index ce144a3..71b3983 100644 --- a/src/userfunc.c +++ b/src/userfunc.c @@ -555,7 +555,9 @@ parse_argument_types( type = &t_any; for (int om = 0; om < obj_member_count; ++om) { - if (STRCMP(aname, obj_members[om].ocm_name) == 0) + if (obj_members != NULL + && STRCMP(aname, + obj_members[om].ocm_name) == 0) { type = obj_members[om].ocm_type; break; @@ -570,10 +572,16 @@ parse_argument_types( fp->uf_arg_types[i] = type; if (i < fp->uf_args.ga_len && (type->tt_type == VAR_FUNC - || type->tt_type == VAR_PARTIAL) - && var_wrong_func_name( - ((char_u **)fp->uf_args.ga_data)[i], TRUE)) - return FAIL; + || type->tt_type == VAR_PARTIAL)) + { + char_u *name = ((char_u **)fp->uf_args.ga_data)[i]; + if (obj_members != NULL && *name == '_') + // protected object method + name++; + + if (var_wrong_func_name(name, TRUE)) + return FAIL; + } } } } @@ -1219,13 +1227,18 @@ get_function_body( || checkforcmd(&arg, "const", 5) || vim9_function) { - while (vim_strchr((char_u *)"$@&", *arg) != NULL) - ++arg; - arg = skipwhite(find_name_end(arg, NULL, NULL, - FNE_INCL_BR | FNE_ALLOW_CURLY)); - if (vim9_function && *arg == ':') - arg = skipwhite(skip_type(skipwhite(arg + 1), FALSE)); - if (arg[0] == '=' && arg[1] == '<' && arg[2] =='<') + int save_sc_version = current_sctx.sc_version; + int var_count = 0; + int semicolon = 0; + + current_sctx.sc_version + = vim9_function ? SCRIPT_VERSION_VIM9 : 1; + arg = skip_var_list(arg, TRUE, &var_count, &semicolon, + TRUE); + if (arg != NULL) + arg = skipwhite(arg); + current_sctx.sc_version = save_sc_version; + if (arg != NULL && STRNCMP(arg, "=<<", 3) == 0) { p = skipwhite(arg + 3); while (TRUE) @@ -1329,6 +1342,7 @@ lambda_function_body( char_u *name; int lnum_save = -1; linenr_T sourcing_lnum_top = SOURCING_LNUM; + char_u *line_arg = NULL; *arg = skipwhite(*arg + 1); if (**arg == '|' || !ends_excmd2(start, *arg)) @@ -1337,6 +1351,12 @@ lambda_function_body( return FAIL; } + // When there is a line break use what follows for the lambda body. + // Makes lambda body initializers work for object and enum member + // variables. + if (**arg == '\n') + line_arg = *arg + 1; + CLEAR_FIELD(eap); eap.cmdidx = CMD_block; eap.forceit = FALSE; @@ -1351,7 +1371,7 @@ lambda_function_body( } ga_init2(&newlines, sizeof(char_u *), 10); - if (get_function_body(&eap, &newlines, NULL, + if (get_function_body(&eap, &newlines, line_arg, &evalarg->eval_tofree_ga) == FAIL) goto erret; @@ -1366,7 +1386,12 @@ lambda_function_body( for (idx = 0; idx < newlines.ga_len; ++idx) { - char_u *p = skipwhite(((char_u **)newlines.ga_data)[idx]); + char_u *p = ((char_u **)newlines.ga_data)[idx]; + if (p == NULL) + // comment line in the lambda body + continue; + + p = skipwhite(p); if (ga_grow(gap, 1) == FAIL || ga_grow(freegap, 1) == FAIL) goto erret; diff --git a/src/version.c b/src/version.c index 32037e3..2bd0667 100644 --- a/src/version.c +++ b/src/version.c @@ -705,6 +705,356 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 374, +/**/ + 373, +/**/ + 372, +/**/ + 371, +/**/ + 370, +/**/ + 369, +/**/ + 368, +/**/ + 367, +/**/ + 366, +/**/ + 365, +/**/ + 364, +/**/ + 363, +/**/ + 362, +/**/ + 361, +/**/ + 360, +/**/ + 359, +/**/ + 358, +/**/ + 357, +/**/ + 356, +/**/ + 355, +/**/ + 354, +/**/ + 353, +/**/ + 352, +/**/ + 351, +/**/ + 350, +/**/ + 349, +/**/ + 348, +/**/ + 347, +/**/ + 346, +/**/ + 345, +/**/ + 344, +/**/ + 343, +/**/ + 342, +/**/ + 341, +/**/ + 340, +/**/ + 339, +/**/ + 338, +/**/ + 337, +/**/ + 336, +/**/ + 335, +/**/ + 334, +/**/ + 333, +/**/ + 332, +/**/ + 331, +/**/ + 330, +/**/ + 329, +/**/ + 328, +/**/ + 327, +/**/ + 326, +/**/ + 325, +/**/ + 324, +/**/ + 323, +/**/ + 322, +/**/ + 321, +/**/ + 320, +/**/ + 319, +/**/ + 318, +/**/ + 317, +/**/ + 316, +/**/ + 315, +/**/ + 314, +/**/ + 313, +/**/ + 312, +/**/ + 311, +/**/ + 310, +/**/ + 309, +/**/ + 308, +/**/ + 307, +/**/ + 306, +/**/ + 305, +/**/ + 304, +/**/ + 303, +/**/ + 302, +/**/ + 301, +/**/ + 300, +/**/ + 299, +/**/ + 298, +/**/ + 297, +/**/ + 296, +/**/ + 295, +/**/ + 294, +/**/ + 293, +/**/ + 292, +/**/ + 291, +/**/ + 290, +/**/ + 289, +/**/ + 288, +/**/ + 287, +/**/ + 286, +/**/ + 285, +/**/ + 284, +/**/ + 283, +/**/ + 282, +/**/ + 281, +/**/ + 280, +/**/ + 279, +/**/ + 278, +/**/ + 277, +/**/ + 276, +/**/ + 275, +/**/ + 274, +/**/ + 273, +/**/ + 272, +/**/ + 271, +/**/ + 270, +/**/ + 269, +/**/ + 268, +/**/ + 267, +/**/ + 266, +/**/ + 265, +/**/ + 264, +/**/ + 263, +/**/ + 262, +/**/ + 261, +/**/ + 260, +/**/ + 259, +/**/ + 258, +/**/ + 257, +/**/ + 256, +/**/ + 255, +/**/ + 254, +/**/ + 253, +/**/ + 252, +/**/ + 251, +/**/ + 250, +/**/ + 249, +/**/ + 248, +/**/ + 247, +/**/ + 246, +/**/ + 245, +/**/ + 244, +/**/ + 243, +/**/ + 242, +/**/ + 241, +/**/ + 240, +/**/ + 239, +/**/ + 238, +/**/ + 237, +/**/ + 236, +/**/ + 235, +/**/ + 234, +/**/ + 233, +/**/ + 232, +/**/ + 231, +/**/ + 230, +/**/ + 229, +/**/ + 228, +/**/ + 227, +/**/ + 226, +/**/ + 225, +/**/ + 224, +/**/ + 223, +/**/ + 222, +/**/ + 221, +/**/ + 220, +/**/ + 219, +/**/ + 218, +/**/ + 217, +/**/ + 216, +/**/ + 215, +/**/ + 214, +/**/ + 213, +/**/ + 212, +/**/ + 211, +/**/ + 210, +/**/ + 209, +/**/ + 208, +/**/ + 207, +/**/ + 206, +/**/ + 205, +/**/ + 204, +/**/ + 203, +/**/ + 202, +/**/ + 201, +/**/ + 200, +/**/ 199, /**/ 198, @@ -1469,10 +1819,21 @@ list_version(void) version_msg(USR_VIMRC_FILE2); version_msg("\"\n"); #endif -#ifdef USR_VIMRC_FILE3 +#if defined(USR_VIMRC_FILE3) && defined(XDG_VIMRC_FILE) version_msg(_(" 3rd user vimrc file: \"")); version_msg(USR_VIMRC_FILE3); version_msg("\"\n"); + version_msg(_(" 4th user vimrc file: \"")); + version_msg((char *)(XDG_VIMRC_FILE)); + version_msg("\"\n"); +#elif defined(USR_VIMRC_FILE3) + version_msg(_(" 3rd user vimrc file: \"")); + version_msg(USR_VIMRC_FILE3); + version_msg("\"\n"); +#elif defined(XDG_VIMRC_FILE) + version_msg(_(" 3rd user vimrc file: \"")); + version_msg((char *)(XDG_VIMRC_FILE)); + version_msg("\"\n"); #endif #ifdef USR_EXRC_FILE version_msg(_(" user exrc file: \"")); diff --git a/src/version.h b/src/version.h index b9c6d83..13f3bac 100644 --- a/src/version.h +++ b/src/version.h @@ -31,7 +31,22 @@ #ifndef VIM_VERSION_PATCHLEVEL # define VIM_VERSION_PATCHLEVEL 0 #endif -#define VIM_VERSION_PATCHLEVEL_STR VIM_TOSTR(VIM_VERSION_PATCHLEVEL) + +// Patchlevel with leading zeros +// For compatibility with the installer from "vim-win32-installer" and WinGet. +// For details see https://github.com/vim/vim-win32-installer/pull/277 +// and https://github.com/vim/vim-win32-installer/pull/285 +#if VIM_VERSION_PATCHLEVEL < 10 +#define LEADZERO(x) 000 ## x +#elif VIM_VERSION_PATCHLEVEL < 100 +#define LEADZERO(x) 00 ## x +#elif VIM_VERSION_PATCHLEVEL < 1000 +#define LEADZERO(x) 0 ## x +#else +#define LEADZERO(x) x +#endif + +#define VIM_VERSION_PATCHLEVEL_STR VIM_TOSTR(LEADZERO(VIM_VERSION_PATCHLEVEL)) // Used by MacOS port; should be one of: development, alpha, beta, final #define VIM_VERSION_RELEASE final @@ -36,7 +36,7 @@ # error configure did not run properly. Check auto/config.log. # endif -# if (defined(__linux__) && !defined(__ANDROID__)) || defined(__CYGWIN__) +# if (defined(__linux__) && !defined(__ANDROID__)) || defined(__CYGWIN__) || defined(__GNU__) // Needed for strptime(). Needs to be done early, since header files can // include other header files and end up including time.h, where these symbols // matter for Vim. @@ -656,8 +656,8 @@ extern int (*dyn_libintl_wputenv)(const wchar_t *envstring); #define VALID_VIRTCOL 0x04 // w_virtcol (file col) is valid #define VALID_CHEIGHT 0x08 // w_cline_height and w_cline_folded valid #define VALID_CROW 0x10 // w_cline_row is valid -#define VALID_BOTLINE 0x20 // w_botine and w_empty_rows are valid -#define VALID_BOTLINE_AP 0x40 // w_botine is approximated +#define VALID_BOTLINE 0x20 // w_botline and w_empty_rows are valid +#define VALID_BOTLINE_AP 0x40 // w_botline is approximated #define VALID_TOPLINE 0x80 // w_topline is valid (for cursor position) // Values for w_popup_flags. @@ -1404,6 +1404,7 @@ enum auto_event EVENT_SAFESTATE, // going to wait for a character EVENT_SAFESTATEAGAIN, // still waiting for a character EVENT_SESSIONLOADPOST, // after loading a session file + EVENT_SESSIONWRITEPOST, // after writing a session file EVENT_SHELLCMDPOST, // after ":!cmd" EVENT_SHELLFILTERPOST, // after ":1,2!cmd", ":w !cmd", ":r !cmd". EVENT_SIGUSR1, // after the SIGUSR1 signal @@ -1514,6 +1515,7 @@ typedef enum , HLF_QFL // quickfix window line currently selected , HLF_ST // status lines of terminal windows , HLF_STNC // status lines of not-current terminal windows + , HLF_MSG // message area , HLF_COUNT // MUST be the last one } hlf_T; @@ -1525,7 +1527,7 @@ typedef enum 'B', 'P', 'R', 'L', \ '+', '=', '[', ']', '{', '}', 'x', 'X', \ '*', '#', '_', '!', '.', 'o', 'q', \ - 'z', 'Z'} + 'z', 'Z', 'g'} /* * Boolean constants @@ -2163,7 +2165,9 @@ typedef int sock_T; #define VV_MAXCOL 105 #define VV_PYTHON3_VERSION 106 #define VV_TYPE_TYPEALIAS 107 -#define VV_LEN 108 // number of v: vars +#define VV_TYPE_ENUM 108 +#define VV_TYPE_ENUMVALUE 109 +#define VV_LEN 110 // number of v: vars // used for v_number in VAR_BOOL and VAR_SPECIAL #define VVAL_FALSE 0L // VAR_BOOL @@ -2187,6 +2191,8 @@ typedef int sock_T; #define VAR_TYPE_CLASS 12 #define VAR_TYPE_OBJECT 13 #define VAR_TYPE_TYPEALIAS 14 +#define VAR_TYPE_ENUM 15 +#define VAR_TYPE_ENUMVALUE 16 #define DICT_MAXNEST 100 // maximum nesting of lists and dicts @@ -2812,7 +2818,6 @@ typedef int (*opt_expand_cb_T)(optexpand_T *args, int *numMatches, char_u ***mat // flags for find_name_end() #define FNE_INCL_BR 1 // include [] in name #define FNE_CHECK_START 2 // check name starts with valid character -#define FNE_ALLOW_CURLY 4 // always allow curly braces name // BSD is supposed to cover FreeBSD and similar systems. #if (defined(SUN_SYSTEM) || defined(BSD) || defined(__FreeBSD_kernel__)) \ @@ -460,7 +460,7 @@ typedef struct { // arguments to ISN_2STRING and ISN_2STRING_ANY typedef struct { int offset; - int tolerant; + int flags; } tostring_T; // arguments to ISN_2BOOL @@ -780,6 +780,7 @@ typedef enum { dest_vimvar, dest_class_member, dest_script, + dest_script_v9, dest_reg, dest_expr, } assign_dest_T; @@ -880,3 +881,10 @@ typedef enum { // flags for call_def_function() #define DEF_USE_PT_ARGV 1 // use the partial arguments + +// Flag used for conversion to string by may_generate_2STRING() +#define TOSTRING_NONE 0x0 +// Convert a List to series of values separated by newline +#define TOSTRING_INTERPOLATE 0x1 +// Convert a List to a textual representation of the list "[...]" +#define TOSTRING_TOLERANT 0x2 diff --git a/src/vim9class.c b/src/vim9class.c index 7227c3d..52c2f76 100644 --- a/src/vim9class.c +++ b/src/vim9class.c @@ -168,7 +168,8 @@ struct oc_newmember_S /* * Add a member to an object or a class. * Returns OK when successful, "init_expr" will be consumed then. - * Returns FAIL otherwise, caller might need to free "init_expr". + * Returns OK on success and FAIL on memory allocation failure (caller might + * need to free "init_expr"). */ static int add_member( @@ -323,13 +324,15 @@ validate_extends_class( } if (tv.v_type != VAR_CLASS || tv.vval.v_class == NULL - || (is_class - && (tv.vval.v_class->class_flags & CLASS_INTERFACE) != 0) - || (!is_class - && (tv.vval.v_class->class_flags & CLASS_INTERFACE) == 0)) - // a interface cannot extend a class and a class cannot extend an - // interface. + || (is_class && IS_INTERFACE(tv.vval.v_class)) + || (!is_class && !IS_INTERFACE(tv.vval.v_class)) + || (is_class && IS_ENUM(tv.vval.v_class))) + { + // a class cannot extend an interface + // an interface cannot extend a class + // a class cannot extend an enum. semsg(_(e_cannot_extend_str), extends_name); + } else { class_T *extends_cl = tv.vval.v_class; @@ -793,7 +796,7 @@ validate_implements_classes( if (tv.v_type != VAR_CLASS || tv.vval.v_class == NULL - || (tv.vval.v_class->class_flags & CLASS_INTERFACE) == 0) + || !IS_INTERFACE(tv.vval.v_class)) { semsg(_(e_not_valid_interface_str), impl); success = FALSE; @@ -1234,14 +1237,14 @@ add_lookup_tables(class_T *cl, class_T *extends_cl, garray_T *objmethods_gap) * Add class members to a new class. Allocate a typval for each class member * and initialize it. */ - static void + static int add_class_members(class_T *cl, exarg_T *eap, garray_T *type_list_gap) { // Allocate a typval for each class member and initialize it. cl->class_members_tv = ALLOC_CLEAR_MULT(typval_T, cl->class_class_member_count); if (cl->class_members_tv == NULL) - return; + return FAIL; for (int i = 0; i < cl->class_class_member_count; ++i) { @@ -1250,19 +1253,19 @@ add_class_members(class_T *cl, exarg_T *eap, garray_T *type_list_gap) if (m->ocm_init != NULL) { typval_T *etv = eval_expr(m->ocm_init, eap); - if (etv != NULL) - { - if (m->ocm_type->tt_type == VAR_ANY - && !(m->ocm_flags & OCMFLAG_HAS_TYPE) - && etv->v_type != VAR_SPECIAL) - // If the member variable type is not yet set, then use - // the initialization expression type. - m->ocm_type = typval2type(etv, get_copyID(), - type_list_gap, - TVTT_DO_MEMBER|TVTT_MORE_SPECIFIC); - *tv = *etv; - vim_free(etv); - } + if (etv == NULL) + return FAIL; + + if (m->ocm_type->tt_type == VAR_ANY + && !(m->ocm_flags & OCMFLAG_HAS_TYPE) + && etv->v_type != VAR_SPECIAL) + // If the member variable type is not yet set, then use + // the initialization expression type. + m->ocm_type = typval2type(etv, get_copyID(), + type_list_gap, + TVTT_DO_MEMBER|TVTT_MORE_SPECIFIC); + *tv = *etv; + vim_free(etv); } else { @@ -1273,6 +1276,8 @@ add_class_members(class_T *cl, exarg_T *eap, garray_T *type_list_gap) if (m->ocm_flags & OCMFLAG_CONST) item_lock(tv, DICT_MAXNEST, TRUE, TRUE); } + + return OK; } /* @@ -1284,13 +1289,21 @@ add_default_constructor( garray_T *classfunctions_gap, garray_T *type_list_gap) { - garray_T fga; + garray_T fga; + int is_enum = IS_ENUM(cl); ga_init2(&fga, 1, 1000); ga_concat(&fga, (char_u *)"new("); for (int i = 0; i < cl->class_obj_member_count; ++i) { - if (i > 0) + if (i < 2 && is_enum) + // The first two object variables in an enum are the enum value + // name and ordinal. Don't initialize these object variables in + // the default constructor as they are already initialized right + // after creating the object. + continue; + + if (i > (is_enum ? 2 : 0)) ga_concat(&fga, (char_u *)", "); ga_concat(&fga, (char_u *)"this."); ocmember_T *m = cl->class_obj_members + i; @@ -1336,6 +1349,7 @@ add_default_constructor( * Add the class methods and object methods to the new class "cl". * When extending a class "extends_cl", add the instance methods from the * parent class also. + * Returns OK on success and FAIL on memory allocation failure. */ static int add_classfuncs_objmethods( @@ -1373,7 +1387,7 @@ add_classfuncs_objmethods( if (gap->ga_len != 0) mch_memmove(*fup, gap->ga_data, sizeof(ufunc_T *) * gap->ga_len); - vim_free(gap->ga_data); + VIM_CLEAR(gap->ga_data); if (loop == 1) cl->class_class_function_count_child = gap->ga_len; else @@ -1422,6 +1436,8 @@ add_classfuncs_objmethods( if (loop == 2) fp->uf_flags |= FC_OBJECT; } + + ga_clear(gap); } return OK; @@ -1471,6 +1487,246 @@ find_class_name_end(char_u *arg) return end; } +/* + * Returns TRUE if the enum value "varname" is already defined. + */ + static int +is_duplicate_enum( + garray_T *enum_gap, + char_u *varname, + char_u *varname_end) +{ + char_u *name = vim_strnsave(varname, varname_end - varname); + int dup = FALSE; + + for (int i = 0; i < enum_gap->ga_len; ++i) + { + ocmember_T *m = ((ocmember_T *)enum_gap->ga_data) + i; + if (STRCMP(name, m->ocm_name) == 0) + { + semsg(_(e_duplicate_enum_str), name); + dup = TRUE; + break; + } + } + + vim_free(name); + return dup; +} + +/* + * Parse the enum values in "line" separated by comma and add them to "gap". + * If the last enum value is found, then "enum_end" is set to TRUE. + */ + static int +enum_parse_values( + exarg_T *eap, + class_T *en, + char_u *line, + garray_T *gap, + int *num_enum_values, + int *enum_end) +{ + evalarg_T evalarg; + char_u *p = line; + char initexpr_buf[1024]; + char_u last_char = NUL; + int rc = OK; + + fill_evalarg_from_eap(&evalarg, eap, FALSE); + + int did_emsg_before = did_emsg; + while (*p != NUL) + { + // ignore comment + if (*p == '#') + break; + + if (!eval_isnamec1(*p)) + { + semsg(_(e_invalid_enum_value_declaration_str), p); + break; + } + + char_u *eni_name_start = p; + char_u *eni_name_end = to_name_end(p, FALSE); + + if (is_duplicate_enum(gap, eni_name_start, eni_name_end)) + break; + + p = skipwhite(eni_name_end); + + char_u *init_expr = NULL; + if (*p == '(') + { + if (VIM_ISWHITE(p[-1])) + { + semsg(_(e_no_white_space_allowed_before_str_str), "(", line); + break; + } + + char_u *expr_start, *expr_end; + + p = eni_name_start; + (void)skip_expr_concatenate(&p, &expr_start, &expr_end, &evalarg); + + while (*expr_start && *expr_start != '(') + expr_start++; + + if (expr_end > expr_start) + init_expr = vim_strnsave(expr_start, expr_end - expr_start); + } + + if (init_expr == NULL) + vim_snprintf(initexpr_buf, sizeof(initexpr_buf), "%s.new()", + en->class_name); + else + { + vim_snprintf(initexpr_buf, sizeof(initexpr_buf), "%s.new%s", + en->class_name, init_expr); + vim_free(init_expr); + } + if (add_member(gap, eni_name_start, eni_name_end, FALSE, + TRUE, TRUE, TRUE, &en->class_object_type, + vim_strsave((char_u *)initexpr_buf)) == FAIL) + break; + + ++*num_enum_values; + + if (*p != '#') + last_char = *p; + + if (*p != NUL && *p != ',') + break; + + if (*p == ',') + { + if (!IS_WHITE_OR_NUL(p[1])) + { + semsg(_(e_white_space_required_after_str_str), ",", line); + break; + } + if (VIM_ISWHITE(p[-1])) + { + semsg(_(e_no_white_space_allowed_before_str_str), ",", line); + break; + } + p = skipwhite(p + 1); + } + } + + if (*p != NUL && *p != '#') + { + if (did_emsg == did_emsg_before) + semsg(_(e_missing_comma_before_argument_str), p); + rc = FAIL; + } + + if (last_char != ',') + // last enum value should not be terminated by "," + *enum_end = TRUE; + + // Free the memory pointed by expr_start. + clear_evalarg(&evalarg, NULL); + + return rc; +} + +/* + * Add the "values" class variable (List of enum value objects) to the enum + * class "en" + */ + static int +enum_add_values_member( + class_T *en, + garray_T *gap, + int num_enum_values, + garray_T *type_list_gap) +{ + garray_T fga; + int rc = FAIL; + + ga_init2(&fga, 1, 1000); + ga_concat(&fga, (char_u *)"["); + for (int i = 0; i < num_enum_values; ++i) + { + ocmember_T *m = ((ocmember_T *)gap->ga_data) + i; + + if (i > 0) + ga_concat(&fga, (char_u *)", "); + ga_concat(&fga, en->class_name); + ga_concat(&fga, (char_u *)"."); + ga_concat(&fga, (char_u *)m->ocm_name); + } + ga_concat(&fga, (char_u *)"]"); + ga_append(&fga, NUL); + + char_u *varname = (char_u *)"values"; + + type_T *type = get_type_ptr(type_list_gap); + if (type == NULL) + goto done; + + type->tt_type = VAR_LIST; + type->tt_member = get_type_ptr(type_list_gap); + if (type->tt_member != NULL) + { + type->tt_member->tt_type = VAR_OBJECT; + type->tt_member->tt_class = en; + } + + rc = add_member(gap, varname, varname + 6, FALSE, FALSE, TRUE, TRUE, type, + vim_strsave((char_u *)fga.ga_data)); + +done: + vim_free(fga.ga_data); + + return rc; +} + +/* + * Clear the constructor method names in a enum class, so that an enum class + * cannot be instantiated. + */ + static void +enum_clear_constructors(class_T *en) +{ + for (int i = 0; i < en->class_class_function_count; ++i) + { + ufunc_T *fp = en->class_class_functions[i]; + + if (fp->uf_flags & FC_NEW) + *fp->uf_name = NUL; + } +} + +/* + * Initialize the name and ordinal object variable in the enum value "enval" in + * the enum "en". These values are set during the enum value object creation. + */ + void +enum_set_internal_obj_vars(class_T *en, object_T *enval) +{ + int i; + + for (i = 0; i < en->class_class_member_count; ++i) + { + typval_T *en_tv = en->class_members_tv + i; + if (en_tv != NULL && en_tv->v_type == VAR_UNKNOWN) + break; + } + + // First object variable is the name + ocmember_T *value_ocm = en->class_class_members + i; + typval_T *name_tv = (typval_T *)(enval + 1); + name_tv->v_type = VAR_STRING; + name_tv->vval.v_string = vim_strsave(value_ocm->ocm_name); + + // Second object variable is the ordinal + typval_T *ord_tv = (typval_T *)(name_tv + 1); + ord_tv->v_type = VAR_NUMBER; + ord_tv->vval.v_number = i; +} /* * Handle ":class" and ":abstract class" up to ":endclass". @@ -1479,10 +1735,12 @@ find_class_name_end(char_u *arg) void ex_class(exarg_T *eap) { - int is_class = eap->cmdidx == CMD_class; // FALSE for :interface + int is_class = eap->cmdidx == CMD_class; + int is_abstract = eap->cmdidx == CMD_abstract; + int is_enum = eap->cmdidx == CMD_enum; + int is_interface; long start_lnum = SOURCING_LNUM; char_u *arg = eap->arg; - int is_abstract = eap->cmdidx == CMD_abstract; if (is_abstract) { @@ -1495,12 +1753,16 @@ ex_class(exarg_T *eap) is_class = TRUE; } + is_interface = !is_class && !is_enum; + if (!current_script_is_vim9() || (cmdmod.cmod_flags & CMOD_LEGACY) || !getline_equal(eap->ea_getline, eap->cookie, getsourceline)) { if (is_class) emsg(_(e_class_can_only_be_defined_in_vim9_script)); + else if (is_enum) + emsg(_(e_enum_can_only_be_defined_in_vim9_script)); else emsg(_(e_interface_can_only_be_defined_in_vim9_script)); return; @@ -1510,6 +1772,8 @@ ex_class(exarg_T *eap) { if (is_class) semsg(_(e_class_name_must_start_with_uppercase_letter_str), arg); + else if (is_enum) + semsg(_(e_enum_name_must_start_with_uppercase_letter_str), arg); else semsg(_(e_interface_name_must_start_with_uppercase_letter_str), arg); @@ -1523,11 +1787,6 @@ ex_class(exarg_T *eap) } char_u *name_start = arg; - // "export class" gets used when creating the class, don't use "is_export" - // for the items inside the class. - int class_export = is_export; - is_export = FALSE; - // TODO: // generics: <Tkey, Tentry> @@ -1545,6 +1804,11 @@ ex_class(exarg_T *eap) // specifies SomeInterface if (STRNCMP(arg, "extends", 7) == 0 && IS_WHITE_OR_NUL(arg[7])) { + if (is_enum) + { + emsg(_(e_enum_cannot_extend_class)); + goto early_ret; + } if (extends != NULL) { emsg(_(e_duplicate_extends)); @@ -1567,7 +1831,7 @@ ex_class(exarg_T *eap) else if (STRNCMP(arg, "implements", 10) == 0 && IS_WHITE_OR_NUL(arg[10])) { - if (!is_class) + if (is_interface) { emsg(_(e_interface_cannot_use_implements)); goto early_ret; @@ -1652,11 +1916,15 @@ early_ret: class_T *cl = NULL; class_T *extends_cl = NULL; // class from "extends" argument class_T **intf_classes = NULL; + int num_enum_values = 0; cl = ALLOC_CLEAR_ONE(class_T); if (cl == NULL) goto cleanup; - if (!is_class) + + if (is_enum) + cl->class_flags = CLASS_ENUM; + else if (is_interface) cl->class_flags = CLASS_INTERFACE; else if (is_abstract) cl->class_flags = CLASS_ABSTRACT; @@ -1666,22 +1934,48 @@ early_ret: if (cl->class_name == NULL) goto cleanup; + cl->class_type.tt_type = VAR_CLASS; + cl->class_type.tt_class = cl; + cl->class_object_type.tt_type = VAR_OBJECT; + cl->class_object_type.tt_class = cl; + // Add the class to the script-local variables. // TODO: handle other context, e.g. in a function // TODO: does uf_hash need to be cleared? typval_T tv; tv.v_type = VAR_CLASS; tv.vval.v_class = cl; - is_export = class_export; SOURCING_LNUM = start_lnum; int rc = set_var_const(cl->class_name, current_sctx.sc_sid, NULL, &tv, FALSE, 0, 0); if (rc == FAIL) goto cleanup; + if (is_enum) + { + // All the enum classes have the name and ordinal object variables. + char_u *varname = (char_u *)"name"; + if (add_member(&objmembers, varname, varname + 4, FALSE, FALSE, TRUE, + TRUE, &t_string, NULL) == FAIL) + goto cleanup; + + varname = (char_u *)"ordinal"; + if (add_member(&objmembers, varname, varname + 7, FALSE, FALSE, TRUE, + TRUE, &t_number, NULL) == FAIL) + goto cleanup; + } + + // "export class" gets used when creating the class, don't use "is_export" + // for the items inside the class. + is_export = FALSE; + + // When parsing an enum definition, this denotes whether all the enumerated + // values are parsed or not. + int enum_end = FALSE; + /* * Go over the body of the class/interface until "endclass" or - * "endinterface" is found. + * "endinterface" or "endenum" is found. */ char_u *theline = NULL; int success = FALSE; @@ -1704,10 +1998,32 @@ early_ret: } char_u *p = line; - char *end_name = is_class ? "endclass" : "endinterface"; - if (checkforcmd(&p, end_name, is_class ? 4 : 5)) + + char *end_name; + int shortlen; + int fullen; + if (is_class) + { + end_name = "endclass"; + shortlen = 4; + fullen = 8; + } + else if (is_enum) + { + end_name = "endenum"; + shortlen = 4; + fullen = 7; + } + else + { + end_name = "endinterface"; + shortlen = 5; + fullen = 12; + } + + if (checkforcmd(&p, end_name, shortlen)) { - if (STRNCMP(line, end_name, is_class ? 8 : 12) != 0) + if (STRNCMP(line, end_name, fullen) != 0) semsg(_(e_command_cannot_be_shortened_str), line); else if (*p == '|' || !ends_excmd2(line, p)) semsg(_(e_trailing_characters_str), p); @@ -1715,13 +2031,39 @@ early_ret: success = TRUE; break; } - char *wrong_name = is_class ? "endinterface" : "endclass"; - if (checkforcmd(&p, wrong_name, is_class ? 5 : 4)) + + int wrong_endname = FALSE; + if (is_class) + wrong_endname = checkforcmd(&p, "endinterface", 5) + || checkforcmd(&p, "endenum", 4); + else if (is_enum) + wrong_endname = checkforcmd(&p, "endclass", 4) + || checkforcmd(&p, "endinterface", 5); + else + wrong_endname = checkforcmd(&p, "endclass", 4) + || checkforcmd(&p, "endenum", 4); + if (wrong_endname) { semsg(_(e_invalid_command_str_expected_str), line, end_name); break; } + if (is_enum && !enum_end) + { + // In an enum, all the enumerated values are at the beginning + // separated by comma. The class and object variables/methods + // follow the values. + if (enum_parse_values(eap, cl, line, &classmembers, + &num_enum_values, &enum_end) == FAIL) + break; + + if (enum_end) + // Add the enum "values" class variable. + enum_add_values_member(cl, &classmembers, num_enum_values, + &type_list); + continue; + } + int has_public = FALSE; if (checkforcmd(&p, "public", 3)) { @@ -1730,7 +2072,7 @@ early_ret: semsg(_(e_command_cannot_be_shortened_str), line); break; } - if (!is_class) + if (is_interface) { emsg(_(e_public_variable_not_supported_in_interface)); break; @@ -1738,6 +2080,12 @@ early_ret: has_public = TRUE; p = skipwhite(line + 6); + if (STRNCMP(p, "def", 3) == 0) + { + emsg(_(e_public_keyword_not_supported_for_method)); + break; + } + if (STRNCMP(p, "var", 3) != 0 && STRNCMP(p, "static", 6) != 0 && STRNCMP(p, "final", 5) != 0 && STRNCMP(p, "const", 5) != 0) { @@ -1756,7 +2104,14 @@ early_ret: break; } - if (!is_class) + if (is_enum) + { + // "abstract" not supported in an enum + emsg(_(e_abstract_cannot_be_used_in_enum)); + break; + } + + if (is_interface) { // "abstract" not supported in an interface emsg(_(e_abstract_cannot_be_used_in_interface)); @@ -1789,7 +2144,7 @@ early_ret: break; } - if (!is_class) + if (is_interface) { emsg(_(e_static_member_not_supported_in_interface)); break; @@ -1812,7 +2167,7 @@ early_ret: has_var = TRUE; else if (checkforcmd(&p, "final", 5)) { - if (!is_class) + if (is_interface) { emsg(_(e_final_variable_not_supported_in_interface)); break; @@ -1821,7 +2176,7 @@ early_ret: } else if (checkforcmd(&p, "const", 5)) { - if (!is_class) + if (is_interface) { emsg(_(e_const_variable_not_supported_in_interface)); break; @@ -1867,7 +2222,7 @@ early_ret: break; } - if (!is_class && *varname == '_') + if (is_interface && *varname == '_') { // private variables are not supported in an interface semsg(_(e_protected_variable_not_supported_in_interface), @@ -1877,7 +2232,7 @@ early_ret: if (parse_member(eap, line, varname, has_public, &varname_end, &has_type, &type_list, &type, - is_class ? &init_expr: NULL) == FAIL) + !is_interface ? &init_expr: NULL) == FAIL) break; if (is_reserved_varname(varname, varname_end) @@ -1930,7 +2285,7 @@ early_ret: break; } - if (!is_class && *p == '_') + if (is_interface && *p == '_') { // private methods are not supported in an interface semsg(_(e_protected_method_not_supported_in_interface), p); @@ -1953,10 +2308,10 @@ early_ret: ga_init2(&lines_to_free, sizeof(char_u *), 50); int class_flags; - if (is_class) - class_flags = abstract_method ? CF_ABSTRACT_METHOD : CF_CLASS; - else + if (is_interface) class_flags = CF_INTERFACE; + else + class_flags = abstract_method ? CF_ABSTRACT_METHOD : CF_CLASS; ufunc_T *uf = define_function(&ea, NULL, &lines_to_free, class_flags, objmembers.ga_data, objmembers.ga_len); ga_clear_strings(&lines_to_free); @@ -2011,15 +2366,25 @@ early_ret: { if (is_class) semsg(_(e_not_valid_command_in_class_str), line); + else if (is_enum) + semsg(_(e_not_valid_command_in_enum_str), line); else semsg(_(e_not_valid_command_in_interface_str), line); break; } } + + if (theline == NULL && !success && is_enum) + emsg(_(e_missing_endenum)); + vim_free(theline); + if (success && is_enum && num_enum_values == 0) + // Empty enum statement. Add an empty "values" class variable + enum_add_values_member(cl, &classmembers, 0, &type_list); + /* - * Check a few things before defining the class. + * Check a few things */ // Check the "extends" class is valid. @@ -2067,7 +2432,8 @@ early_ret: if (success) { - // "endclass" encountered without failures: Create the class. + // "endclass" or "endinterface" or "endenum" encountered without any + // failures if (extends_cl != NULL) { @@ -2114,10 +2480,6 @@ early_ret: goto cleanup; } - // Allocate a typval for each class member and initialize it. - if (is_class && cl->class_class_member_count > 0) - add_class_members(cl, eap, &type_list); - int have_new = FALSE; ufunc_T *class_func = NULL; for (int i = 0; i < classfunctions.ga_len; ++i) @@ -2133,7 +2495,7 @@ early_ret: if (have_new) // The return type of new() is an object of class "cl" class_func->uf_ret_type->tt_class = cl; - else if (is_class && !is_abstract && !have_new) + else if ((is_class || is_enum) && !is_abstract && !have_new) // No new() method was defined, add the default constructor. add_default_constructor(cl, &classfunctions, &type_list); @@ -2144,13 +2506,21 @@ early_ret: update_builtin_method_index(cl); - cl->class_type.tt_type = VAR_CLASS; - cl->class_type.tt_class = cl; - cl->class_object_type.tt_type = VAR_OBJECT; - cl->class_object_type.tt_class = cl; + class_created(cl); + + // Allocate a typval for each class member and initialize it. + if ((is_class || is_enum) && cl->class_class_member_count > 0) + if (add_class_members(cl, eap, &type_list) == FAIL) + goto cleanup; + cl->class_type_list = type_list; - class_created(cl); + if (is_enum) + { + // clear the constructor method names, so that an enum class cannot + // be instantiated + enum_clear_constructors(cl); + } // TODO: // - Fill hashtab with object members and methods ? @@ -2265,15 +2635,6 @@ oc_member_type_by_idx( } /* - * Handle ":enum" up to ":endenum". - */ - void -ex_enum(exarg_T *eap UNUSED) -{ - // TODO -} - -/* * Type aliases (:type) */ @@ -2480,6 +2841,14 @@ call_oc_method( return FAIL; } + if (*name == '_') + { + // Protected object or class funcref variable + semsg(_(e_cannot_access_protected_variable_str), ocm->ocm_name, + cl->class_name); + return FAIL; + } + if (rettv->v_type == VAR_OBJECT) { // funcref object variable @@ -3334,8 +3703,14 @@ member_not_found_msg(class_T *cl, vartype_T v_type, char_u *name, size_t len) semsg(_(e_object_variable_str_accessible_only_using_object_str), varname, cl->class_name); else - semsg(_(e_class_variable_str_not_found_in_class_str), - varname, cl->class_name); + { + if (IS_ENUM(cl)) + semsg(_(e_enum_value_str_not_found_in_enum_str), + varname, cl->class_name); + else + semsg(_(e_class_variable_str_not_found_in_class_str), + varname, cl->class_name); + } } vim_free(varname); } @@ -3354,7 +3729,9 @@ defcompile_class(class_T *cl) { ufunc_T *ufunc = loop == 1 ? cl->class_class_functions[i] : cl->class_obj_methods[i]; - defcompile_function(ufunc, cl); + // Don't compile abstract methods + if (!IS_ABSTRACT_METHOD(ufunc)) + defcompile_function(ufunc, cl); } } } @@ -3426,7 +3803,7 @@ object_call_builtin_method( } /* - * Calls the object "empty()" method and returns the method retun value. In + * Calls the object "empty()" method and returns the method return value. In * case of an error, returns TRUE. */ int @@ -3480,10 +3857,21 @@ object_string( garray_T ga; ga_init2(&ga, 1, 50); - ga_concat(&ga, (char_u *)"object of "); class_T *cl = obj == NULL ? NULL : obj->obj_class; - ga_concat(&ga, cl == NULL ? (char_u *)"[unknown]" - : cl->class_name); + if (cl != NULL && IS_ENUM(cl)) + { + ga_concat(&ga, (char_u *)"enum "); + ga_concat(&ga, cl->class_name); + char_u *enum_name = ((typval_T *)(obj + 1))->vval.v_string; + ga_concat(&ga, (char_u *)"."); + ga_concat(&ga, enum_name); + } + else + { + ga_concat(&ga, (char_u *)"object of "); + ga_concat(&ga, cl == NULL ? (char_u *)"[unknown]" + : cl->class_name); + } if (cl != NULL) { ga_concat(&ga, (char_u *)" {"); diff --git a/src/vim9cmds.c b/src/vim9cmds.c index ad245b9..694bb33 100644 --- a/src/vim9cmds.c +++ b/src/vim9cmds.c @@ -1931,7 +1931,7 @@ compile_throw(char_u *arg, cctx_T *cctx UNUSED) return NULL; if (cctx->ctx_skip == SKIP_YES) return p; - if (may_generate_2STRING(-1, FALSE, cctx) == FAIL) + if (may_generate_2STRING(-1, TOSTRING_NONE, cctx) == FAIL) return NULL; if (generate_instr_drop(cctx, ISN_THROW, 1) == NULL) return NULL; @@ -2359,7 +2359,7 @@ compile_exec(char_u *line_arg, exarg_T *eap, cctx_T *cctx) p += 2; if (compile_expr0(&p, cctx) == FAIL) return NULL; - may_generate_2STRING(-1, TRUE, cctx); + may_generate_2STRING(-1, TOSTRING_TOLERANT, cctx); ++count; p = skipwhite(p); if (*p != '`') diff --git a/src/vim9compile.c b/src/vim9compile.c index 8f67d8a..8e6f6e2 100644 --- a/src/vim9compile.c +++ b/src/vim9compile.c @@ -1222,7 +1222,7 @@ compile_one_expr_in_str(char_u *p, cctx_T *cctx) } if (compile_expr0(&block_start, cctx) == FAIL) return NULL; - may_generate_2STRING(-1, TRUE, cctx); + may_generate_2STRING(-1, TOSTRING_INTERPOLATE, cctx); return block_end + 1; } @@ -1367,6 +1367,7 @@ generate_loadvar(cctx_T *cctx, lhs_T *lhs) generate_LOAD(cctx, ISN_LOADT, 0, name + 2, type); break; case dest_script: + case dest_script_v9: res = compile_load_scriptvar(cctx, name + (name[1] == ':' ? 2 : 0), NULL, NULL); break; @@ -1614,6 +1615,13 @@ lhs_class_member_modifiable(lhs_T *lhs, char_u *var_start, cctx_T *cctx) return FALSE; } + if (IS_ENUM(cl)) + { + semsg(_(e_enumvalue_str_cannot_be_modified), cl->class_name, + m->ocm_name); + return FALSE; + } + // If it is private member variable, then accessing it outside the // class is not allowed. // If it is a read only class variable, then it can be modified @@ -1783,10 +1791,11 @@ compile_lhs( return FAIL; lhs->lhs_dest = dest_class_member; - lhs->lhs_class = cctx->ctx_ufunc->uf_class; - lhs->lhs_type = - oc_member_type_by_idx(cctx->ctx_ufunc->uf_class, - FALSE, lhs->lhs_classmember_idx); + // The class variable is defined either in the current class or + // in one of the parent class in the hierarchy. + lhs->lhs_class = defcl; + lhs->lhs_type = oc_member_type_by_idx(defcl, FALSE, + lhs->lhs_classmember_idx); } else { @@ -1830,7 +1839,8 @@ compile_lhs( return FAIL; } - lhs->lhs_dest = dest_script; + lhs->lhs_dest = current_script_is_vim9() + ? dest_script_v9 : dest_script; // existing script-local variables should have a type lhs->lhs_scriptvar_sid = current_sctx.sc_sid; @@ -2037,6 +2047,25 @@ compile_lhs( return FAIL; } + if (IS_ENUM(cl)) + { + if (!inside_class(cctx, cl)) + { + semsg(_(e_enumvalue_str_cannot_be_modified), + cl->class_name, m->ocm_name); + return FALSE; + } + if (lhs->lhs_type->tt_type == VAR_OBJECT && + lhs->lhs_member_idx < 2) + { + char *msg = lhs->lhs_member_idx == 0 ? + e_enum_str_name_cannot_be_modified : + e_enum_str_ordinal_cannot_be_modified; + semsg(_(msg), cl->class_name); + return FALSE; + } + } + // If it is private member variable, then accessing it outside the // class is not allowed. // If it is a read only class variable, then it can be modified @@ -2304,7 +2333,7 @@ compile_load_lhs_with_index(lhs_T *lhs, char_u *var_start, cctx_T *cctx) if (compile_load_lhs(lhs, var_start, lhs->lhs_type, cctx) == FAIL) return FAIL; } - if (cl->class_flags & CLASS_INTERFACE) + if (IS_INTERFACE(cl)) return generate_GET_ITF_MEMBER(cctx, cl, lhs->lhs_member_idx, type); return generate_GET_OBJ_MEMBER(cctx, lhs->lhs_member_idx, type); } @@ -2394,7 +2423,7 @@ compile_assign_unlet( return FAIL; } if (dest_type == VAR_DICT - && may_generate_2STRING(-1, FALSE, cctx) == FAIL) + && may_generate_2STRING(-1, TOSTRING_NONE, cctx) == FAIL) return FAIL; if (dest_type == VAR_LIST || dest_type == VAR_BLOB) { @@ -2453,7 +2482,7 @@ compile_assign_unlet( { class_T *cl = lhs->lhs_type->tt_class; - if (cl->class_flags & CLASS_INTERFACE) + if (IS_INTERFACE(cl)) { // "this.value": load "this" object and get the value // at index for an object or class member get the type @@ -2948,7 +2977,7 @@ compile_assignment( if (*op == '.') { - if (may_generate_2STRING(-1, FALSE, cctx) == FAIL) + if (may_generate_2STRING(-1, TOSTRING_NONE, cctx) == FAIL) goto theend; } else @@ -2999,8 +3028,9 @@ compile_assignment( else { if (is_decl && cmdidx == CMD_const && (lhs.lhs_dest == dest_script - || lhs.lhs_dest == dest_global - || lhs.lhs_dest == dest_local)) + || lhs.lhs_dest == dest_script_v9 + || lhs.lhs_dest == dest_global + || lhs.lhs_dest == dest_local)) // ":const var": lock the value, but not referenced variables generate_LOCKCONST(cctx); @@ -3244,254 +3274,185 @@ add_def_function(ufunc_T *ufunc) } /* - * After ex_function() has collected all the function lines: parse and compile - * the lines into instructions. - * Adds the function to "def_functions". - * When "check_return_type" is set then set ufunc->uf_ret_type to the type of - * the return statement (used for lambda). When uf_ret_type is already set - * then check that it matches. - * When "profiling" is true add ISN_PROF_START instructions. - * "outer_cctx" is set for a nested function. - * This can be used recursively through compile_lambda(), which may reallocate - * "def_functions". - * Returns OK or FAIL. + * For an object constructor, generate instruction to setup "this" (the first + * local variable) and to initialize the object variables. */ - int -compile_def_function( - ufunc_T *ufunc, - int check_return_type, - compiletype_T compile_type, - cctx_T *outer_cctx) + static int +obj_constructor_prologue(ufunc_T *ufunc, cctx_T *cctx) { - char_u *line = NULL; - garray_T lines_to_free; - char_u *p; - char *errormsg = NULL; // error message - cctx_T cctx; - garray_T *instr; - int did_emsg_before = did_emsg; - int did_emsg_silent_before = did_emsg_silent; - int ret = FAIL; - sctx_T save_current_sctx = current_sctx; - int save_estack_compiling = estack_compiling; - int save_cmod_flags = cmdmod.cmod_flags; - int do_estack_push; - int new_def_function = FALSE; -#ifdef FEAT_PROFILE - int prof_lnum = -1; -#endif - int debug_lnum = -1; - - // allocated lines are freed at the end - ga_init2(&lines_to_free, sizeof(char_u *), 50); + generate_CONSTRUCT(cctx, ufunc->uf_class); - // When using a function that was compiled before: Free old instructions. - // The index is reused. Otherwise add a new entry in "def_functions". - if (ufunc->uf_dfunc_idx > 0) + for (int i = 0; i < ufunc->uf_class->class_obj_member_count; ++i) { - dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data) - + ufunc->uf_dfunc_idx; - isn_T *instr_dest = NULL; + ocmember_T *m = &ufunc->uf_class->class_obj_members[i]; - switch (compile_type) + if (i < 2 && IS_ENUM(ufunc->uf_class)) + // The first two object variables in an enum are the name + // and the ordinal. These are set by the ISN_CONSTRUCT + // instruction. So don't generate instructions to set + // these variables. + continue; + + if (m->ocm_init != NULL) { - case CT_PROFILE: -#ifdef FEAT_PROFILE - instr_dest = dfunc->df_instr_prof; break; -#endif - case CT_NONE: instr_dest = dfunc->df_instr; break; - case CT_DEBUG: instr_dest = dfunc->df_instr_debug; break; + char_u *expr = m->ocm_init; + + if (compile_expr0(&expr, cctx) == FAIL) + return FAIL; + + if (!ends_excmd2(m->ocm_init, expr)) + { + semsg(_(e_trailing_characters_str), expr); + return FAIL; + } + + type_T *type = get_type_on_stack(cctx, 0); + if (m->ocm_type->tt_type == VAR_ANY + && !(m->ocm_flags & OCMFLAG_HAS_TYPE) + && type->tt_type != VAR_SPECIAL) + { + // If the member variable type is not yet set, then use + // the initialization expression type. + m->ocm_type = type; + } + else if (m->ocm_type->tt_type != type->tt_type) + { + // The type of the member initialization expression is + // determined at run time. Add a runtime type check. + where_T where = WHERE_INIT; + where.wt_kind = WT_MEMBER; + where.wt_func_name = (char *)m->ocm_name; + if (need_type_where(type, m->ocm_type, FALSE, -1, + where, cctx, FALSE, FALSE) == FAIL) + return FAIL; + } } - if (instr_dest != NULL) - // Was compiled in this mode before: Free old instructions. - delete_def_function_contents(dfunc, FALSE); - ga_clear_strings(&dfunc->df_var_names); - dfunc->df_defer_var_idx = 0; - } - else - { - if (add_def_function(ufunc) == FAIL) - return FAIL; - new_def_function = TRUE; - } + else + push_default_value(cctx, m->ocm_type->tt_type, FALSE, NULL); - if ((ufunc->uf_flags & FC_CLOSURE) && outer_cctx == NULL) - { - semsg(_(e_compiling_closure_without_context_str), - printable_func_name(ufunc)); - return FAIL; + generate_STORE_THIS(cctx, i); } - ufunc->uf_def_status = UF_COMPILING; - - CLEAR_FIELD(cctx); + return OK; +} - cctx.ctx_compile_type = compile_type; - cctx.ctx_ufunc = ufunc; - cctx.ctx_lnum = -1; - cctx.ctx_outer = outer_cctx; - ga_init2(&cctx.ctx_locals, sizeof(lvar_T), 10); - // Each entry on the type stack consists of two type pointers. - ga_init2(&cctx.ctx_type_stack, sizeof(type2_T), 50); - cctx.ctx_type_list = &ufunc->uf_type_list; - ga_init2(&cctx.ctx_instr, sizeof(isn_T), 50); - instr = &cctx.ctx_instr; +/* + * For an object method and an constructor, generate instruction to setup + * "this" (the first local variable). For a constructor, generate instructions + * to initialize the object variables. + */ + static int +obj_method_prologue(ufunc_T *ufunc, cctx_T *cctx) +{ + dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data) + ufunc->uf_dfunc_idx; - // Set the context to the function, it may be compiled when called from - // another script. Set the script version to the most modern one. - // The line number will be set in next_line_from_context(). - current_sctx = ufunc->uf_script_ctx; - current_sctx.sc_version = SCRIPT_VERSION_VIM9; + if (GA_GROW_FAILS(&dfunc->df_var_names, 1)) + return FAIL; - // Don't use the flag from ":legacy" here. - cmdmod.cmod_flags &= ~CMOD_LEGACY; + ((char_u **)dfunc->df_var_names.ga_data)[0] = + vim_strsave((char_u *)"this"); + ++dfunc->df_var_names.ga_len; - // Make sure error messages are OK. - do_estack_push = !estack_top_is_ufunc(ufunc, 1); - if (do_estack_push) - estack_push_ufunc(ufunc, 1); - estack_compiling = TRUE; + // In the constructor allocate memory for the object and initialize the + // object members. + if (IS_CONSTRUCTOR_METHOD(ufunc)) + return obj_constructor_prologue(ufunc, cctx); - if (check_args_shadowing(ufunc, &cctx) == FAIL) - goto erret; + return OK; +} - // For an object method and constructor "this" is the first local variable. - if (ufunc->uf_flags & (FC_OBJECT|FC_NEW)) +/* + * Produce instructions for the default values of optional arguments. + */ + static int +compile_def_function_default_args( + ufunc_T *ufunc, + cctx_T *cctx, + garray_T *instr) +{ + int count = ufunc->uf_def_args.ga_len; + int first_def_arg = ufunc->uf_args.ga_len - count; + int i; + int off = STACK_FRAME_SIZE + (ufunc->uf_va_name != NULL ? 1 : 0); + int did_set_arg_type = FALSE; + + // Produce instructions for the default values of optional arguments. + SOURCING_LNUM = 0; // line number unknown + for (i = 0; i < count; ++i) { - dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data) - + ufunc->uf_dfunc_idx; - if (GA_GROW_FAILS(&dfunc->df_var_names, 1)) - goto erret; - ((char_u **)dfunc->df_var_names.ga_data)[0] = - vim_strsave((char_u *)"this"); - ++dfunc->df_var_names.ga_len; + char_u *arg = ((char_u **)(ufunc->uf_def_args.ga_data))[i]; + if (STRCMP(arg, "v:none") == 0) + // "arg = v:none" means the argument is optional without + // setting a value when the argument is missing. + continue; - // In the constructor allocate memory for the object and initialize the - // object members. - if (IS_CONSTRUCTOR_METHOD(ufunc)) - { - generate_CONSTRUCT(&cctx, ufunc->uf_class); + type_T *val_type; + int arg_idx = first_def_arg + i; + where_T where = WHERE_INIT; + int jump_instr_idx = instr->ga_len; + isn_T *isn; - for (int i = 0; i < ufunc->uf_class->class_obj_member_count; ++i) - { - ocmember_T *m = &ufunc->uf_class->class_obj_members[i]; - if (m->ocm_init != NULL) - { - char_u *expr = m->ocm_init; - if (compile_expr0(&expr, &cctx) == FAIL) - goto erret; - if (!ends_excmd2(m->ocm_init, expr)) - { - semsg(_(e_trailing_characters_str), expr); - goto erret; - } + // Use a JUMP_IF_ARG_SET instruction to skip if the value was given. + if (generate_JUMP_IF_ARG(cctx, ISN_JUMP_IF_ARG_SET, + i - count - off) == FAIL) + return FAIL; - type_T *type = get_type_on_stack(&cctx, 0); - if (m->ocm_type->tt_type == VAR_ANY - && !(m->ocm_flags & OCMFLAG_HAS_TYPE) - && type->tt_type != VAR_SPECIAL) - { - // If the member variable type is not yet set, then use - // the initialization expression type. - m->ocm_type = type; - } - else if (m->ocm_type->tt_type != type->tt_type) - { - // The type of the member initialization expression is - // determined at run time. Add a runtime type check. - where_T where = WHERE_INIT; - where.wt_kind = WT_MEMBER; - where.wt_func_name = (char *)m->ocm_name; - if (need_type_where(type, m->ocm_type, FALSE, -1, - where, &cctx, FALSE, FALSE) == FAIL) - goto erret; - } - } - else - push_default_value(&cctx, m->ocm_type->tt_type, - FALSE, NULL); - generate_STORE_THIS(&cctx, i); - } - } - } + // Make sure later arguments are not found. + ufunc->uf_args_visible = arg_idx; - if (ufunc->uf_def_args.ga_len > 0) - { - int count = ufunc->uf_def_args.ga_len; - int first_def_arg = ufunc->uf_args.ga_len - count; - int i; - int off = STACK_FRAME_SIZE + (ufunc->uf_va_name != NULL ? 1 : 0); - int did_set_arg_type = FALSE; - - // Produce instructions for the default values of optional arguments. - SOURCING_LNUM = 0; // line number unknown - for (i = 0; i < count; ++i) + int r = compile_expr0(&arg, cctx); + if (r == FAIL) + return FAIL; + + // If no type specified use the type of the default value. + // Otherwise check that the default value type matches the + // specified type. + val_type = get_type_on_stack(cctx, 0); + where.wt_index = arg_idx + 1; + where.wt_kind = WT_ARGUMENT; + if (ufunc->uf_arg_types[arg_idx] == &t_unknown) { - char_u *arg = ((char_u **)(ufunc->uf_def_args.ga_data))[i]; - if (STRCMP(arg, "v:none") == 0) - // "arg = v:none" means the argument is optional without - // setting a value when the argument is missing. - continue; + did_set_arg_type = TRUE; + ufunc->uf_arg_types[arg_idx] = val_type; + } + else if (need_type_where(val_type, ufunc->uf_arg_types[arg_idx], + FALSE, -1, where, cctx, FALSE, FALSE) == FAIL) + return FAIL; - type_T *val_type; - int arg_idx = first_def_arg + i; - where_T where = WHERE_INIT; - int jump_instr_idx = instr->ga_len; - isn_T *isn; - - // Use a JUMP_IF_ARG_SET instruction to skip if the value was given. - if (generate_JUMP_IF_ARG(&cctx, ISN_JUMP_IF_ARG_SET, - i - count - off) == FAIL) - goto erret; - - // Make sure later arguments are not found. - ufunc->uf_args_visible = arg_idx; - - int r = compile_expr0(&arg, &cctx); - if (r == FAIL) - goto erret; - - // If no type specified use the type of the default value. - // Otherwise check that the default value type matches the - // specified type. - val_type = get_type_on_stack(&cctx, 0); - where.wt_index = arg_idx + 1; - where.wt_kind = WT_ARGUMENT; - if (ufunc->uf_arg_types[arg_idx] == &t_unknown) - { - did_set_arg_type = TRUE; - ufunc->uf_arg_types[arg_idx] = val_type; - } - else if (need_type_where(val_type, ufunc->uf_arg_types[arg_idx], - FALSE, -1, where, &cctx, FALSE, FALSE) == FAIL) - goto erret; + if (generate_STORE(cctx, ISN_STORE, i - count - off, NULL) == FAIL) + return FAIL; - if (generate_STORE(&cctx, ISN_STORE, i - count - off, NULL) == FAIL) - goto erret; + // set instruction index in JUMP_IF_ARG_SET to here + isn = ((isn_T *)instr->ga_data) + jump_instr_idx; + isn->isn_arg.jumparg.jump_where = instr->ga_len; + } - // set instruction index in JUMP_IF_ARG_SET to here - isn = ((isn_T *)instr->ga_data) + jump_instr_idx; - isn->isn_arg.jumparg.jump_where = instr->ga_len; - } + if (did_set_arg_type) + set_function_type(ufunc); - if (did_set_arg_type) - set_function_type(ufunc); - } - ufunc->uf_args_visible = ufunc->uf_args.ga_len; + return OK; +} - // Compiling a function in an interface is done to get the function type. - // No code is actually compiled. - if (ufunc->uf_class != NULL - && (ufunc->uf_class->class_flags & CLASS_INTERFACE)) - { - ufunc->uf_def_status = UF_NOT_COMPILED; - ret = OK; - goto erret; - } +/* + * Compile def function body. Loop over all the lines in the function and + * generate instructions. + */ + static int +compile_def_function_body( + cctx_T *cctx, + int last_func_lnum, + int check_return_type, + garray_T *lines_to_free, + char **errormsg) +{ + char_u *line = NULL; + char_u *p; + int did_emsg_before = did_emsg; +#ifdef FEAT_PROFILE + int prof_lnum = -1; +#endif + int debug_lnum = -1; - /* - * Loop over all the lines of the function and generate instructions. - */ for (;;) { exarg_T ea; @@ -3502,29 +3463,29 @@ compile_def_function( // Bail out on the first error to avoid a flood of errors and report // the right line number when inside try/catch. if (did_emsg_before != did_emsg) - goto erret; + return FAIL; if (line != NULL && *line == '|') // the line continues after a '|' ++line; else if (line != NULL && *skipwhite(line) != NUL - && !(*line == '#' && (line == cctx.ctx_line_start + && !(*line == '#' && (line == cctx->ctx_line_start || VIM_ISWHITE(line[-1])))) { semsg(_(e_trailing_characters_str), line); - goto erret; + return FAIL; } else if (line != NULL && vim9_bad_comment(skipwhite(line))) - goto erret; + return FAIL; else { - line = next_line_from_context(&cctx, FALSE); - if (cctx.ctx_lnum >= ufunc->uf_lines.ga_len) + line = next_line_from_context(cctx, FALSE); + if (cctx->ctx_lnum >= last_func_lnum) { // beyond the last line #ifdef FEAT_PROFILE - if (cctx.ctx_skip != SKIP_YES) - may_generate_prof_end(&cctx, prof_lnum); + if (cctx->ctx_skip != SKIP_YES) + may_generate_prof_end(cctx, prof_lnum); #endif break; } @@ -3533,42 +3494,42 @@ compile_def_function( if (line != NULL) { line = vim_strsave(line); - if (ga_add_string(&lines_to_free, line) == FAIL) - goto erret; + if (ga_add_string(lines_to_free, line) == FAIL) + return FAIL; } } CLEAR_FIELD(ea); ea.cmdlinep = &line; ea.cmd = skipwhite(line); - ea.skip = cctx.ctx_skip == SKIP_YES; + ea.skip = cctx->ctx_skip == SKIP_YES; if (*ea.cmd == '#') { // "#" starts a comment, but "#{" is an error if (vim9_bad_comment(ea.cmd)) - goto erret; + return FAIL; line = (char_u *)""; continue; } #ifdef FEAT_PROFILE - if (cctx.ctx_compile_type == CT_PROFILE && cctx.ctx_lnum != prof_lnum - && cctx.ctx_skip != SKIP_YES) + if (cctx->ctx_compile_type == CT_PROFILE && cctx->ctx_lnum != prof_lnum + && cctx->ctx_skip != SKIP_YES) { - may_generate_prof_end(&cctx, prof_lnum); + may_generate_prof_end(cctx, prof_lnum); - prof_lnum = cctx.ctx_lnum; - generate_instr(&cctx, ISN_PROF_START); + prof_lnum = cctx->ctx_lnum; + generate_instr(cctx, ISN_PROF_START); } #endif - if (cctx.ctx_compile_type == CT_DEBUG && cctx.ctx_lnum != debug_lnum - && cctx.ctx_skip != SKIP_YES) + if (cctx->ctx_compile_type == CT_DEBUG && cctx->ctx_lnum != debug_lnum + && cctx->ctx_skip != SKIP_YES) { - debug_lnum = cctx.ctx_lnum; - generate_instr_debug(&cctx); + debug_lnum = cctx->ctx_lnum; + generate_instr_debug(cctx); } - cctx.ctx_prev_lnum = cctx.ctx_lnum + 1; + cctx->ctx_prev_lnum = cctx->ctx_lnum + 1; // Some things can be recognized by the first character. switch (*ea.cmd) @@ -3576,18 +3537,18 @@ compile_def_function( case '}': { // "}" ends a block scope - scopetype_T stype = cctx.ctx_scope == NULL - ? NO_SCOPE : cctx.ctx_scope->se_type; + scopetype_T stype = cctx->ctx_scope == NULL + ? NO_SCOPE : cctx->ctx_scope->se_type; if (stype == BLOCK_SCOPE) { - compile_endblock(&cctx); + compile_endblock(cctx); line = ea.cmd; } else { emsg(_(e_using_rcurly_outside_if_block_scope)); - goto erret; + return FAIL; } if (line != NULL) line = skipwhite(ea.cmd + 1); @@ -3599,7 +3560,7 @@ compile_def_function( // "{'a': 1}->func() is something else if (ends_excmd(*skipwhite(ea.cmd + 1))) { - line = compile_block(ea.cmd, &cctx); + line = compile_block(ea.cmd, cctx); continue; } break; @@ -3608,11 +3569,11 @@ compile_def_function( /* * COMMAND MODIFIERS */ - cctx.ctx_has_cmdmod = FALSE; - if (parse_command_modifiers(&ea, &errormsg, &local_cmdmod, FALSE) + cctx->ctx_has_cmdmod = FALSE; + if (parse_command_modifiers(&ea, errormsg, &local_cmdmod, FALSE) == FAIL) - goto erret; - generate_cmdmods(&cctx, &local_cmdmod); + return FAIL; + generate_cmdmods(cctx, &local_cmdmod); undo_cmdmod(&local_cmdmod); // Check if there was a colon after the last command modifier or before @@ -3643,11 +3604,11 @@ compile_def_function( int assign; // Check for assignment after command modifiers. - assign = may_compile_assignment(&ea, &line, &cctx); + assign = may_compile_assignment(&ea, &line, cctx); if (assign == OK) goto nextline; if (assign == FAIL) - goto erret; + return FAIL; } } @@ -3675,13 +3636,13 @@ compile_def_function( && !(local_cmdmod.cmod_flags & CMOD_LEGACY)) { semsg(_(e_colon_required_before_range_str), cmd); - goto erret; + return FAIL; } ea.addr_count = 1; if (ends_excmd2(line, ea.cmd)) { // A range without a command: jump to the line. - generate_EXEC(&cctx, ISN_EXECRANGE, + generate_EXEC(cctx, ISN_EXECRANGE, vim_strnsave(cmd, ea.cmd - cmd)); line = ea.cmd; goto nextline; @@ -3690,13 +3651,13 @@ compile_def_function( } p = find_ex_command(&ea, NULL, starts_with_colon || (local_cmdmod.cmod_flags & CMOD_LEGACY) - ? NULL : item_exists, &cctx); + ? NULL : item_exists, cctx); if (p == NULL) { - if (cctx.ctx_skip != SKIP_YES) + if (cctx->ctx_skip != SKIP_YES) semsg(_(e_ambiguous_use_of_user_defined_command_str), ea.cmd); - goto erret; + return FAIL; } // When using ":legacy cmd" always use compile_exec(). @@ -3721,7 +3682,7 @@ compile_def_function( case CMD_finally: case CMD_endtry: semsg(_(e_cannot_use_legacy_with_command_str), ea.cmd); - goto erret; + return FAIL; default: break; } @@ -3738,7 +3699,7 @@ compile_def_function( // "p" is equal to "ea.cmd" for a valid command. if (ea.cmdidx == CMD_eval || ea.cmdidx == CMD_var) ; - else if (cctx.ctx_skip == SKIP_YES) + else if (cctx->ctx_skip == SKIP_YES) { line += STRLEN(line); goto nextline; @@ -3746,11 +3707,11 @@ compile_def_function( else { semsg(_(e_command_not_recognized_str), ea.cmd); - goto erret; + return FAIL; } } - if ((cctx.ctx_had_return || cctx.ctx_had_throw) + if ((cctx->ctx_had_return || cctx->ctx_had_throw) && ea.cmdidx != CMD_elseif && ea.cmdidx != CMD_else && ea.cmdidx != CMD_endif @@ -3762,10 +3723,10 @@ compile_def_function( && !ignore_unreachable_code_for_testing) { semsg(_(e_unreachable_code_after_str), - cctx.ctx_had_return ? "return" : "throw"); - goto erret; + cctx->ctx_had_return ? "return" : "throw"); + return FAIL; } - cctx.ctx_had_throw = FALSE; + cctx->ctx_had_throw = FALSE; p = skipwhite(p); if (ea.cmdidx != CMD_SIZE @@ -3781,7 +3742,7 @@ compile_def_function( if ((ea.argt & EX_RANGE) == 0 && ea.addr_count > 0) { emsg(_(e_no_range_allowed)); - goto erret; + return FAIL; } } @@ -3790,13 +3751,13 @@ compile_def_function( case CMD_def: case CMD_function: ea.arg = p; - line = compile_nested_function(&ea, &cctx, &lines_to_free); + line = compile_nested_function(&ea, cctx, lines_to_free); break; case CMD_return: line = compile_return(p, check_return_type, - local_cmdmod.cmod_flags & CMOD_LEGACY, &cctx); - cctx.ctx_had_return = TRUE; + local_cmdmod.cmod_flags & CMOD_LEGACY, cctx); + cctx->ctx_had_return = TRUE; break; case CMD_let: @@ -3807,7 +3768,7 @@ compile_def_function( case CMD_const: case CMD_increment: case CMD_decrement: - line = compile_assignment(p, &ea, ea.cmdidx, &cctx); + line = compile_assignment(p, &ea, ea.cmdidx, cctx); if (line == p) { emsg(_(e_invalid_assignment)); @@ -3818,7 +3779,7 @@ compile_def_function( case CMD_unlet: case CMD_unlockvar: case CMD_lockvar: - line = compile_unletlock(p, &ea, &cctx); + line = compile_unletlock(p, &ea, cctx); break; case CMD_import: @@ -3827,67 +3788,67 @@ compile_def_function( break; case CMD_if: - line = compile_if(p, &cctx); + line = compile_if(p, cctx); break; case CMD_elseif: - line = compile_elseif(p, &cctx); - cctx.ctx_had_return = FALSE; + line = compile_elseif(p, cctx); + cctx->ctx_had_return = FALSE; break; case CMD_else: - line = compile_else(p, &cctx); - cctx.ctx_had_return = FALSE; + line = compile_else(p, cctx); + cctx->ctx_had_return = FALSE; break; case CMD_endif: - line = compile_endif(p, &cctx); + line = compile_endif(p, cctx); break; case CMD_while: - line = compile_while(p, &cctx); + line = compile_while(p, cctx); break; case CMD_endwhile: - line = compile_endwhile(p, &cctx); - cctx.ctx_had_return = FALSE; + line = compile_endwhile(p, cctx); + cctx->ctx_had_return = FALSE; break; case CMD_for: - line = compile_for(p, &cctx); + line = compile_for(p, cctx); break; case CMD_endfor: - line = compile_endfor(p, &cctx); - cctx.ctx_had_return = FALSE; + line = compile_endfor(p, cctx); + cctx->ctx_had_return = FALSE; break; case CMD_continue: - line = compile_continue(p, &cctx); + line = compile_continue(p, cctx); break; case CMD_break: - line = compile_break(p, &cctx); + line = compile_break(p, cctx); break; case CMD_try: - line = compile_try(p, &cctx); + line = compile_try(p, cctx); break; case CMD_catch: - line = compile_catch(p, &cctx); - cctx.ctx_had_return = FALSE; + line = compile_catch(p, cctx); + cctx->ctx_had_return = FALSE; break; case CMD_finally: - line = compile_finally(p, &cctx); - cctx.ctx_had_return = FALSE; + line = compile_finally(p, cctx); + cctx->ctx_had_return = FALSE; break; case CMD_endtry: - line = compile_endtry(p, &cctx); + line = compile_endtry(p, cctx); break; case CMD_throw: - line = compile_throw(p, &cctx); - cctx.ctx_had_throw = TRUE; + line = compile_throw(p, cctx); + cctx->ctx_had_throw = TRUE; break; case CMD_eval: - line = compile_eval(p, &cctx); + line = compile_eval(p, cctx); break; case CMD_defer: - line = compile_defer(p, &cctx); + line = compile_defer(p, cctx); break; #ifdef HAS_MESSAGE_WINDOW @@ -3898,7 +3859,7 @@ compile_def_function( line = NULL; else line = compile_mult_expr(p, ea.cmdidx, - cmd_count, &cctx); + cmd_count, cctx); } break; #endif @@ -3908,29 +3869,29 @@ compile_def_function( case CMD_echoerr: case CMD_echomsg: case CMD_execute: - line = compile_mult_expr(p, ea.cmdidx, 0, &cctx); + line = compile_mult_expr(p, ea.cmdidx, 0, cctx); break; case CMD_put: ea.cmd = cmd; - line = compile_put(p, &ea, &cctx); + line = compile_put(p, &ea, cctx); break; case CMD_substitute: if (check_global_and_subst(ea.cmd, p) == FAIL) - goto erret; - if (cctx.ctx_skip == SKIP_YES) + return FAIL; + if (cctx->ctx_skip == SKIP_YES) line = (char_u *)""; else { ea.arg = p; - line = compile_substitute(line, &ea, &cctx); + line = compile_substitute(line, &ea, cctx); } break; case CMD_redir: ea.arg = p; - line = compile_redir(line, &ea, &cctx); + line = compile_redir(line, &ea, cctx); break; case CMD_cexpr: @@ -3941,7 +3902,7 @@ compile_def_function( case CMD_lgetexpr: #ifdef FEAT_QUICKFIX ea.arg = p; - line = compile_cexpr(line, &ea, &cctx); + line = compile_cexpr(line, &ea, cctx); #else ex_ni(&ea); line = NULL; @@ -3955,13 +3916,13 @@ compile_def_function( case CMD_t: case CMD_xit: not_in_vim9(&ea); - goto erret; + return FAIL; case CMD_SIZE: - if (cctx.ctx_skip != SKIP_YES) + if (cctx->ctx_skip != SKIP_YES) { semsg(_(e_invalid_command_str), ea.cmd); - goto erret; + return FAIL; } // We don't check for a next command here. line = (char_u *)""; @@ -3978,52 +3939,189 @@ compile_def_function( case CMD_tcl: ea.arg = p; if (vim_strchr(line, '\n') == NULL) - line = compile_exec(line, &ea, &cctx); + line = compile_exec(line, &ea, cctx); else // heredoc lines have been concatenated with NL // characters in get_function_body() - line = compile_script(line, &cctx); + line = compile_script(line, cctx); break; case CMD_vim9script: - if (cctx.ctx_skip != SKIP_YES) + if (cctx->ctx_skip != SKIP_YES) { emsg(_(e_vim9script_can_only_be_used_in_script)); - goto erret; + return FAIL; } line = (char_u *)""; break; + case CMD_class: + emsg(_(e_class_can_only_be_used_in_script)); + return FAIL; + case CMD_type: emsg(_(e_type_can_only_be_used_in_script)); - goto erret; - break; + return FAIL; case CMD_global: if (check_global_and_subst(ea.cmd, p) == FAIL) - goto erret; + return FAIL; // FALLTHROUGH default: // Not recognized, execute with do_cmdline_cmd(). ea.arg = p; - line = compile_exec(line, &ea, &cctx); + line = compile_exec(line, &ea, cctx); break; } nextline: if (line == NULL) - goto erret; + return FAIL; line = skipwhite(line); // Undo any command modifiers. - generate_undo_cmdmods(&cctx); + generate_undo_cmdmods(cctx); - if (cctx.ctx_type_stack.ga_len < 0) + if (cctx->ctx_type_stack.ga_len < 0) { iemsg("Type stack underflow"); - goto erret; + return FAIL; } } // END of the loop over all the function body lines. + return OK; +} + +/* + * After ex_function() has collected all the function lines: parse and compile + * the lines into instructions. + * Adds the function to "def_functions". + * When "check_return_type" is set then set ufunc->uf_ret_type to the type of + * the return statement (used for lambda). When uf_ret_type is already set + * then check that it matches. + * When "profiling" is true add ISN_PROF_START instructions. + * "outer_cctx" is set for a nested function. + * This can be used recursively through compile_lambda(), which may reallocate + * "def_functions". + * Returns OK or FAIL. + */ + int +compile_def_function( + ufunc_T *ufunc, + int check_return_type, + compiletype_T compile_type, + cctx_T *outer_cctx) +{ + garray_T lines_to_free; + char *errormsg = NULL; // error message + cctx_T cctx; + garray_T *instr; + int did_emsg_before = did_emsg; + int did_emsg_silent_before = did_emsg_silent; + int ret = FAIL; + sctx_T save_current_sctx = current_sctx; + int save_estack_compiling = estack_compiling; + int save_cmod_flags = cmdmod.cmod_flags; + int do_estack_push; + int new_def_function = FALSE; + + // allocated lines are freed at the end + ga_init2(&lines_to_free, sizeof(char_u *), 50); + + // When using a function that was compiled before: Free old instructions. + // The index is reused. Otherwise add a new entry in "def_functions". + if (ufunc->uf_dfunc_idx > 0) + { + dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data) + + ufunc->uf_dfunc_idx; + isn_T *instr_dest = NULL; + + switch (compile_type) + { + case CT_PROFILE: +#ifdef FEAT_PROFILE + instr_dest = dfunc->df_instr_prof; break; +#endif + case CT_NONE: instr_dest = dfunc->df_instr; break; + case CT_DEBUG: instr_dest = dfunc->df_instr_debug; break; + } + if (instr_dest != NULL) + // Was compiled in this mode before: Free old instructions. + delete_def_function_contents(dfunc, FALSE); + ga_clear_strings(&dfunc->df_var_names); + dfunc->df_defer_var_idx = 0; + } + else + { + if (add_def_function(ufunc) == FAIL) + return FAIL; + new_def_function = TRUE; + } + + if ((ufunc->uf_flags & FC_CLOSURE) && outer_cctx == NULL) + { + semsg(_(e_compiling_closure_without_context_str), + printable_func_name(ufunc)); + return FAIL; + } + + ufunc->uf_def_status = UF_COMPILING; + + CLEAR_FIELD(cctx); + + cctx.ctx_compile_type = compile_type; + cctx.ctx_ufunc = ufunc; + cctx.ctx_lnum = -1; + cctx.ctx_outer = outer_cctx; + ga_init2(&cctx.ctx_locals, sizeof(lvar_T), 10); + // Each entry on the type stack consists of two type pointers. + ga_init2(&cctx.ctx_type_stack, sizeof(type2_T), 50); + cctx.ctx_type_list = &ufunc->uf_type_list; + ga_init2(&cctx.ctx_instr, sizeof(isn_T), 50); + instr = &cctx.ctx_instr; + + // Set the context to the function, it may be compiled when called from + // another script. Set the script version to the most modern one. + // The line number will be set in next_line_from_context(). + current_sctx = ufunc->uf_script_ctx; + current_sctx.sc_version = SCRIPT_VERSION_VIM9; + + // Don't use the flag from ":legacy" here. + cmdmod.cmod_flags &= ~CMOD_LEGACY; + + // Make sure error messages are OK. + do_estack_push = !estack_top_is_ufunc(ufunc, 1); + if (do_estack_push) + estack_push_ufunc(ufunc, 1); + estack_compiling = TRUE; + + if (check_args_shadowing(ufunc, &cctx) == FAIL) + goto erret; + + // For an object method and a constructor generate instructions to + // initialize "this" and the object variables. + if (ufunc->uf_flags & (FC_OBJECT|FC_NEW)) + if (obj_method_prologue(ufunc, &cctx) == FAIL) + goto erret; + + if (ufunc->uf_def_args.ga_len > 0) + if (compile_def_function_default_args(ufunc, &cctx, instr) == FAIL) + goto erret; + ufunc->uf_args_visible = ufunc->uf_args.ga_len; + + // Compiling a function in an interface is done to get the function type. + // No code is actually compiled. + if (ufunc->uf_class != NULL && IS_INTERFACE(ufunc->uf_class)) + { + ufunc->uf_def_status = UF_NOT_COMPILED; + ret = OK; + goto erret; + } + + // compile the function body + if (compile_def_function_body(&cctx, ufunc->uf_lines.ga_len, + check_return_type, &lines_to_free, &errormsg) == FAIL) + goto erret; + if (cctx.ctx_scope != NULL) { if (cctx.ctx_scope->se_type == IF_SCOPE) diff --git a/src/vim9execute.c b/src/vim9execute.c index 1efed35..3a3960a 100644 --- a/src/vim9execute.c +++ b/src/vim9execute.c @@ -260,7 +260,10 @@ exe_newdict(int count, ectx_T *ectx) if (count > 0) ectx->ec_stack.ga_len -= 2 * count - 1; else if (GA_GROW_FAILS(&ectx->ec_stack, 1)) + { + dict_unref(dict); return FAIL; + } else ++ectx->ec_stack.ga_len; tv = STACK_TV_BOT(-1); @@ -1635,7 +1638,7 @@ store_var(char_u *name, typval_T *tv) * Return FAIL if not allowed. */ static int -do_2string(typval_T *tv, int is_2string_any, int tolerant) +do_2string(typval_T *tv, int is_2string_any, int tostring_flags) { if (tv->v_type == VAR_STRING) return OK; @@ -1650,10 +1653,11 @@ do_2string(typval_T *tv, int is_2string_any, int tolerant) case VAR_BOOL: case VAR_NUMBER: case VAR_FLOAT: + case VAR_DICT: case VAR_BLOB: break; case VAR_LIST: - if (tolerant) + if (tostring_flags & TOSTRING_TOLERANT) { char_u *s, *e, *p; garray_T ga; @@ -1686,6 +1690,8 @@ do_2string(typval_T *tv, int is_2string_any, int tolerant) tv->vval.v_string = ga.ga_data; return OK; } + if (tostring_flags & TOSTRING_INTERPOLATE) + break; // FALLTHROUGH default: to_string_error(tv->v_type); return FAIL; @@ -3255,6 +3261,12 @@ exec_instructions(ectx_T *ectx) ++tv->vval.v_object->obj_class->class_refcount; tv->vval.v_object->obj_refcount = 1; object_created(tv->vval.v_object); + + // When creating an enum value object, initialize the name and + // ordinal object variables. + class_T *en = tv->vval.v_object->obj_class; + if (IS_ENUM(en)) + enum_set_internal_obj_vars(en, tv->vval.v_object); break; // execute Ex command line @@ -3830,11 +3842,19 @@ exec_instructions(ectx_T *ectx) case ISN_STOREEXPORT: { int sid = iptr->isn_arg.loadstore.ls_sid; - hashtab_T *ht = &SCRIPT_VARS(sid); char_u *name = iptr->isn_arg.loadstore.ls_name; - dictitem_T *di = find_var_in_ht(ht, 0, - iptr->isn_type == ISN_STORES + dictitem_T *di = NULL; + // First check for a variable from an exported autoload + // with an autoload_prefix; it would be in globals. + if (iptr->isn_type == ISN_STOREEXPORT) + di = find_var_autoload_prefix(name, sid, NULL, NULL); + // Then look for a variable in the script's variables. + if (di == NULL) + { + hashtab_T *ht = &SCRIPT_VARS(sid); + di = find_var_in_ht(ht, 0, STRNCMP("s:", name, 2) == 0 ? name + 2 : name, TRUE); + } --ectx->ec_stack.ga_len; SOURCING_LNUM = iptr->isn_lnum; @@ -4564,6 +4584,7 @@ exec_instructions(ectx_T *ectx) { SOURCING_LNUM = iptr->isn_lnum; iemsg("ufunc unexpectedly NULL for FUNCREF"); + vim_free(pt); goto theend; } if (fill_partial_and_closure(pt, ufunc, @@ -5674,7 +5695,7 @@ exec_instructions(ectx_T *ectx) SOURCING_LNUM = iptr->isn_lnum; if (do_2string(STACK_TV_BOT(iptr->isn_arg.tostring.offset), iptr->isn_type == ISN_2STRING_ANY, - iptr->isn_arg.tostring.tolerant) == FAIL) + iptr->isn_arg.tostring.flags) == FAIL) goto on_error; break; diff --git a/src/vim9expr.c b/src/vim9expr.c index 9d67aea..8c412b8 100644 --- a/src/vim9expr.c +++ b/src/vim9expr.c @@ -142,7 +142,7 @@ compile_member(int is_slice, int *keeping_dict, cctx_T *cctx) typep->type_curr = &t_any; typep->type_decl = &t_any; } - if (may_generate_2STRING(-1, FALSE, cctx) == FAIL + if (may_generate_2STRING(-1, TOSTRING_NONE, cctx) == FAIL || generate_instr_drop(cctx, ISN_MEMBER, 1) == FAIL) return FAIL; if (keeping_dict != NULL) @@ -446,7 +446,7 @@ compile_class_object_index(cctx_T *cctx, char_u **arg, type_T *type) if (m_idx >= 0) { ufunc_T *fp = cl->class_obj_methods[m_idx]; - // Private methods are not accessible outside the class + // Private object methods are not accessible outside the class if (*name == '_' && !inside_class(cctx, cl)) { semsg(_(e_cannot_access_protected_method_str), fp->uf_name); @@ -488,7 +488,7 @@ compile_class_object_index(cctx_T *cctx, char_u **arg, type_T *type) if (m_idx >= 0) { ufunc_T *fp = cl->class_class_functions[m_idx]; - // Private methods are not accessible outside the class + // Private class methods are not accessible outside the class if (*name == '_' && !inside_class(cctx, cl)) { semsg(_(e_cannot_access_protected_method_str), fp->uf_name); @@ -546,6 +546,9 @@ compile_load_scriptvar( int done = FALSE; int res = OK; + check_script_symlink(import->imp_sid); + import_check_sourced_sid(&import->imp_sid); + // Need to lookup the member. if (*p != '.') { @@ -1561,7 +1564,10 @@ compile_dict(char_u **arg, cctx_T *cctx, ppconst_T *ppconst) if (d == NULL) return FAIL; if (generate_ppconst(cctx, ppconst) == FAIL) + { + dict_unref(d); return FAIL; + } for (;;) { char_u *key = NULL; @@ -1595,7 +1601,7 @@ compile_dict(char_u **arg, cctx_T *cctx, ppconst_T *ppconst) } if (isn->isn_type == ISN_PUSHS) key = isn->isn_arg.string; - else if (may_generate_2STRING(-1, FALSE, cctx) == FAIL) + else if (may_generate_2STRING(-1, TOSTRING_NONE, cctx) == FAIL) return FAIL; *arg = skipwhite(*arg); if (**arg != ']') @@ -2462,7 +2468,8 @@ compile_subscript( return FAIL; ppconst->pp_is_const = FALSE; - if ((type = get_type_on_stack(cctx, 0)) != &t_unknown + type = get_type_on_stack(cctx, 0); + if (type != &t_unknown && (type->tt_type == VAR_CLASS || type->tt_type == VAR_OBJECT)) { @@ -3010,8 +3017,8 @@ compile_expr6(char_u **arg, cctx_T *cctx, ppconst_T *ppconst) ppconst->pp_is_const = FALSE; if (*op == '.') { - if (may_generate_2STRING(-2, FALSE, cctx) == FAIL - || may_generate_2STRING(-1, FALSE, cctx) == FAIL) + if (may_generate_2STRING(-2, TOSTRING_NONE, cctx) == FAIL + || may_generate_2STRING(-1, TOSTRING_NONE, cctx) == FAIL) return FAIL; if (generate_CONCAT(cctx, 2) == FAIL) return FAIL; diff --git a/src/vim9instr.c b/src/vim9instr.c index a2179f3..ad8beb1 100644 --- a/src/vim9instr.c +++ b/src/vim9instr.c @@ -191,10 +191,12 @@ generate_STORE_THIS(cctx_T *cctx, int idx) /* * If type at "offset" isn't already VAR_STRING then generate ISN_2STRING. * But only for simple types. - * When "tolerant" is TRUE convert most types to string, e.g. a List. + * When tostring_flags has TOSTRING_TOLERANT, convert a List to a series of + * strings. When tostring_flags has TOSTRING_INTERPOLATE, convert a List or a + * Dict to the corresponding textual representation. */ int -may_generate_2STRING(int offset, int tolerant, cctx_T *cctx) +may_generate_2STRING(int offset, int tostring_flags, cctx_T *cctx) { isn_T *isn; isntype_T isntype = ISN_2STRING; @@ -222,11 +224,14 @@ may_generate_2STRING(int offset, int tolerant, cctx_T *cctx) // conversion possible when tolerant case VAR_LIST: - if (tolerant) + case VAR_DICT: + if (tostring_flags & TOSTRING_TOLERANT) { isntype = ISN_2STRING_ANY; break; } + if (tostring_flags & TOSTRING_INTERPOLATE) + break; // FALLTHROUGH // conversion not possible @@ -234,7 +239,6 @@ may_generate_2STRING(int offset, int tolerant, cctx_T *cctx) case VAR_BLOB: case VAR_FUNC: case VAR_PARTIAL: - case VAR_DICT: case VAR_JOB: case VAR_CHANNEL: case VAR_INSTR: @@ -249,7 +253,7 @@ may_generate_2STRING(int offset, int tolerant, cctx_T *cctx) if ((isn = generate_instr(cctx, isntype)) == NULL) return FAIL; isn->isn_arg.tostring.offset = offset; - isn->isn_arg.tostring.tolerant = tolerant; + isn->isn_arg.tostring.flags = tostring_flags; return OK; } @@ -2390,6 +2394,7 @@ generate_store_var( case dest_vimvar: return generate_STORE(cctx, ISN_STOREV, vimvaridx, NULL); case dest_script: + case dest_script_v9: { int scriptvar_idx = lhs->lhs_scriptvar_idx; int scriptvar_sid = lhs->lhs_scriptvar_sid; @@ -2397,10 +2402,14 @@ generate_store_var( { isntype_T isn_type = ISN_STORES; + // If "sn_import_autoload", generate ISN_STOREEXPORT (not + // ISN_STORES) if destination is in a vim9script or if + // there is no "sn_autoload_prefix". if (SCRIPT_ID_VALID(scriptvar_sid) && SCRIPT_ITEM(scriptvar_sid)->sn_import_autoload - && SCRIPT_ITEM(scriptvar_sid)->sn_autoload_prefix - == NULL) + && ((SCRIPT_ITEM(scriptvar_sid) + ->sn_autoload_prefix == NULL) + || lhs->lhs_dest == dest_script_v9)) { // "import autoload './dir/script.vim'" - load script // first diff --git a/src/vim9script.c b/src/vim9script.c index a64ce72..3035889 100644 --- a/src/vim9script.c +++ b/src/vim9script.c @@ -456,15 +456,24 @@ handle_import( scriptitem_T *si = SCRIPT_ITEM(current_sctx.sc_sid); char_u *tail = gettail(si->sn_name); char_u *from_name; + int sourced_from_nofile_buf = FALSE; - // Relative to current script: "./name.vim", "../../name.vim". - len = STRLEN(si->sn_name) - STRLEN(tail) + STRLEN(tv.vval.v_string) + 2; - from_name = alloc((int)len); - if (from_name == NULL) - goto erret; - vim_strncpy(from_name, si->sn_name, tail - si->sn_name); - add_pathsep(from_name); - STRCAT(from_name, tv.vval.v_string); + if (STRNCMP(si->sn_name, ":source buffer=", 15) == 0) + sourced_from_nofile_buf = TRUE; + + if (!sourced_from_nofile_buf) + { + // Relative to current script: "./name.vim", "../../name.vim". + len = STRLEN(si->sn_name) - STRLEN(tail) + STRLEN(tv.vval.v_string) + 2; + from_name = alloc((int)len); + if (from_name == NULL) + goto erret; + vim_strncpy(from_name, si->sn_name, tail - si->sn_name); + add_pathsep(from_name); + STRCAT(from_name, tv.vval.v_string); + } + else + from_name = vim_strsave(tv.vval.v_string); simplify_filename(from_name); res = handle_import_fname(from_name, is_autoload, &sid); diff --git a/src/vim9type.c b/src/vim9type.c index 0d004c8..775291e 100644 --- a/src/vim9type.c +++ b/src/vim9type.c @@ -209,6 +209,59 @@ set_tv_type_recurse(type_T *type) } /* + * Set the type of Dict "d" to "type" + */ + static void +set_tv_type_dict(dict_T *d, type_T *type) +{ + if (d->dv_type == type) + return; + + free_type(d->dv_type); + d->dv_type = alloc_type(type); + + // Need to recursively set the type of dict items? + if (!set_tv_type_recurse(type)) + return; + + int todo = (int)d->dv_hashtab.ht_used; + hashitem_T *hi; + dictitem_T *di; + + FOR_ALL_HASHTAB_ITEMS(&d->dv_hashtab, hi, todo) + { + if (!HASHITEM_EMPTY(hi)) + { + --todo; + di = HI2DI(hi); + set_tv_type(&di->di_tv, type->tt_member); + } + } +} + +/* + * Set the type of List "l" to "type" + */ + static void +set_tv_type_list(list_T *l, type_T *type) +{ + if (l->lv_type == type) + return; + + free_type(l->lv_type); + l->lv_type = alloc_type(type); + + // Need to recursively set the type of list items? + if (l->lv_first == &range_list_item || !set_tv_type_recurse(type)) + return; + + listitem_T *li; + + FOR_ALL_LIST_ITEMS(l, li) + set_tv_type(&li->li_tv, type->tt_member); +} + +/* * Set the type of "tv" to "type" if it is a list or dict. */ void @@ -218,49 +271,11 @@ set_tv_type(typval_T *tv, type_T *type) // If the variable type is "any", then keep the value type. // e.g. var x: any = [1, 2] or var y: any = {v: 1} return; - if (tv->v_type == VAR_DICT && tv->vval.v_dict != NULL) - { - dict_T *d = tv->vval.v_dict; - - if (d->dv_type != type) - { - free_type(d->dv_type); - d->dv_type = alloc_type(type); - if (set_tv_type_recurse(type)) - { - int todo = (int)d->dv_hashtab.ht_used; - hashitem_T *hi; - dictitem_T *di; - FOR_ALL_HASHTAB_ITEMS(&d->dv_hashtab, hi, todo) - { - if (!HASHITEM_EMPTY(hi)) - { - --todo; - di = HI2DI(hi); - set_tv_type(&di->di_tv, type->tt_member); - } - } - } - } - } + if (tv->v_type == VAR_DICT && tv->vval.v_dict != NULL) + set_tv_type_dict(tv->vval.v_dict, type); else if (tv->v_type == VAR_LIST && tv->vval.v_list != NULL) - { - list_T *l = tv->vval.v_list; - - if (l->lv_type != type) - { - free_type(l->lv_type); - l->lv_type = alloc_type(type); - if (l->lv_first != &range_list_item && set_tv_type_recurse(type)) - { - listitem_T *li; - - FOR_ALL_LIST_ITEMS(l, li) - set_tv_type(&li->li_tv, type->tt_member); - } - } - } + set_tv_type_list(tv->vval.v_list, type); } type_T * @@ -414,192 +429,238 @@ func_type_add_arg_types( type_any_or_unknown(type_T *type) { return type == NULL || type->tt_type == VAR_ANY - || type->tt_type == VAR_UNKNOWN; + || type->tt_type == VAR_UNKNOWN; } /* - * Get a type_T for a typval_T. - * "type_gap" is used to temporarily create types in. - * When "flags" has TVTT_DO_MEMBER also get the member type, otherwise use - * "any". - * When "flags" has TVTT_MORE_SPECIFIC get the more specific member type if it - * is "any". + * Get a type_T for a "special" typval in "tv". */ static type_T * -typval2type_int(typval_T *tv, int copyID, garray_T *type_gap, int flags) +special_typval2type(typval_T *tv) { - type_T *type; - type_T *member_type = NULL; - class_T *class_type = NULL; - int argcount = 0; - int min_argcount = 0; - - if (tv->v_type == VAR_NUMBER) - return &t_number; - if (tv->v_type == VAR_BOOL) - return &t_bool; - if (tv->v_type == VAR_SPECIAL) + switch (tv->vval.v_number) { - if (tv->vval.v_number == VVAL_NULL) + case VVAL_NULL: return &t_null; - if (tv->vval.v_number == VVAL_NONE) + + case VVAL_NONE: return &t_none; - if (tv->vval.v_number == VVAL_TRUE - || tv->vval.v_number == VVAL_FALSE) + + case VVAL_TRUE: + case VVAL_FALSE: return &t_bool; - return &t_unknown; + + default: + return &t_unknown; } - if (tv->v_type == VAR_STRING) - return &t_string; - if (tv->v_type == VAR_BLOB) +} + +/* + * Get a type_T for a List typval in "tv". + * When "flags" has TVTT_DO_MEMBER also get the member type, otherwise use + * "any". + * When "flags" has TVTT_MORE_SPECIFIC get the more specific member type if it + * is "any". + */ + static type_T * +list_typval2type(typval_T *tv, int copyID, garray_T *type_gap, int flags) +{ + list_T *l = tv->vval.v_list; + listitem_T *li; + type_T *member_type = NULL; + + // An empty list has type list<unknown>, unless the type was specified + // and is not list<any>. This matters when assigning to a variable + // with a specific list type. + if (l == NULL || (l->lv_first == NULL + && (l->lv_type == NULL || l->lv_type->tt_member == &t_any))) + return &t_list_empty; + + if ((flags & TVTT_DO_MEMBER) == 0) + return &t_list_any; + + // If the type is list<any> go through the members, it may end up a + // more specific type. + if (l->lv_type != NULL && (l->lv_first == NULL + || (flags & TVTT_MORE_SPECIFIC) == 0 + || l->lv_type->tt_member != &t_any)) + // make a copy, lv_type may be freed if the list is freed + return copy_type_deep(l->lv_type, type_gap); + + if (l->lv_first == &range_list_item) + return &t_list_number; + + if (l->lv_copyID == copyID) + // avoid recursion + return &t_list_any; + + l->lv_copyID = copyID; + + // Use the common type of all members. + member_type = typval2type(&l->lv_first->li_tv, copyID, type_gap, + TVTT_DO_MEMBER); + for (li = l->lv_first->li_next; li != NULL; li = li->li_next) + common_type(typval2type(&li->li_tv, copyID, type_gap, TVTT_DO_MEMBER), + member_type, &member_type, type_gap); + + return get_list_type(member_type, type_gap); +} + +/* + * Get a type_T for a Dict typval in "tv". + * When "flags" has TVTT_DO_MEMBER also get the member type, otherwise use + * "any". + * When "flags" has TVTT_MORE_SPECIFIC get the more specific member type if it + * is "any". + */ + static type_T * +dict_typval2type(typval_T *tv, int copyID, garray_T *type_gap, int flags) +{ + dict_iterator_T iter; + typval_T *value; + dict_T *d = tv->vval.v_dict; + type_T *member_type = NULL; + + if (d == NULL || (d->dv_hashtab.ht_used == 0 && d->dv_type == NULL)) + return &t_dict_empty; + + if ((flags & TVTT_DO_MEMBER) == 0) + return &t_dict_any; + + // If the type is dict<any> go through the members, it may end up a + // more specific type. + if (d->dv_type != NULL && (d->dv_hashtab.ht_used == 0 + || (flags & TVTT_MORE_SPECIFIC) == 0 + || d->dv_type->tt_member != &t_any)) + return d->dv_type; + + if (d->dv_copyID == copyID) + // avoid recursion + return &t_dict_any; + + d->dv_copyID = copyID; + + // Use the common type of all values. + dict_iterate_start(tv, &iter); + dict_iterate_next(&iter, &value); + member_type = typval2type(value, copyID, type_gap, TVTT_DO_MEMBER); + + while (dict_iterate_next(&iter, &value) != NULL) + common_type(typval2type(value, copyID, type_gap, TVTT_DO_MEMBER), + member_type, &member_type, type_gap); + + return get_dict_type(member_type, type_gap); +} + +/* + * Get a type_T for a "partial" typval in "tv". + */ + static type_T * +partial_typval2type(typval_T *tv, ufunc_T *ufunc, garray_T *type_gap) +{ + partial_T *pt = tv->vval.v_partial; + type_T *type; + + type = get_type_ptr(type_gap); + if (type == NULL) + return NULL; + + *type = *ufunc->uf_func_type; + if (type->tt_argcount >= 0 && pt->pt_argc > 0) { - if (tv->vval.v_blob == NULL) - return &t_blob_null; - return &t_blob; + type->tt_argcount -= pt->pt_argc; + type->tt_min_argcount -= pt->pt_argc; + if (type->tt_argcount > 0 && func_type_add_arg_types(type, + type->tt_argcount, type_gap) == OK) + for (int i = 0; i < type->tt_argcount; ++i) + type->tt_args[i] = + ufunc->uf_func_type->tt_args[i + pt->pt_argc]; } + if (pt->pt_func != NULL) + type->tt_member = pt->pt_func->uf_ret_type; + + return type; +} - if (tv->v_type == VAR_LIST) +/* + * Get a type_T for a "class" or an "object" typval in "tv". + */ + static type_T * +oc_typval2type(typval_T *tv) +{ + if (tv->v_type == VAR_CLASS) { - list_T *l = tv->vval.v_list; - listitem_T *li; - - // An empty list has type list<unknown>, unless the type was specified - // and is not list<any>. This matters when assigning to a variable - // with a specific list type. - if (l == NULL || (l->lv_first == NULL - && (l->lv_type == NULL || l->lv_type->tt_member == &t_any))) - return &t_list_empty; - if ((flags & TVTT_DO_MEMBER) == 0) - return &t_list_any; - // If the type is list<any> go through the members, it may end up a - // more specific type. - if (l->lv_type != NULL && (l->lv_first == NULL - || (flags & TVTT_MORE_SPECIFIC) == 0 - || l->lv_type->tt_member != &t_any)) - // make a copy, lv_type may be freed if the list is freed - return copy_type_deep(l->lv_type, type_gap); - if (l->lv_first == &range_list_item) - return &t_list_number; - if (l->lv_copyID == copyID) - // avoid recursion - return &t_list_any; - l->lv_copyID = copyID; - - // Use the common type of all members. - member_type = typval2type(&l->lv_first->li_tv, copyID, type_gap, - TVTT_DO_MEMBER); - for (li = l->lv_first->li_next; li != NULL; li = li->li_next) - common_type(typval2type(&li->li_tv, copyID, type_gap, - TVTT_DO_MEMBER), - member_type, &member_type, type_gap); - return get_list_type(member_type, type_gap); + if (tv->vval.v_class == NULL) + return &t_class; + + return &tv->vval.v_class->class_type; } - if (tv->v_type == VAR_DICT) + if (tv->vval.v_object != NULL) + return &tv->vval.v_object->obj_class->class_object_type; + + return &t_object; +} + +/* + * Get a type_T for a "function" or a "partial" + */ + static type_T * +fp_typval2type(typval_T *tv, garray_T *type_gap) +{ + char_u *name = NULL; + ufunc_T *ufunc = NULL; + type_T *type; + type_T *member_type = NULL; + int argcount = 0; + int min_argcount = 0; + + if (tv->v_type == VAR_PARTIAL && tv->vval.v_partial != NULL) { - dict_iterator_T iter; - typval_T *value; - dict_T *d = tv->vval.v_dict; - - if (d == NULL || (d->dv_hashtab.ht_used == 0 && d->dv_type == NULL)) - return &t_dict_empty; - if ((flags & TVTT_DO_MEMBER) == 0) - return &t_dict_any; - // If the type is dict<any> go through the members, it may end up a - // more specific type. - if (d->dv_type != NULL && (d->dv_hashtab.ht_used == 0 - || (flags & TVTT_MORE_SPECIFIC) == 0 - || d->dv_type->tt_member != &t_any)) - return d->dv_type; - if (d->dv_copyID == copyID) - // avoid recursion - return &t_dict_any; - d->dv_copyID = copyID; - - // Use the common type of all values. - dict_iterate_start(tv, &iter); - dict_iterate_next(&iter, &value); - member_type = typval2type(value, copyID, type_gap, TVTT_DO_MEMBER); - while (dict_iterate_next(&iter, &value) != NULL) - common_type(typval2type(value, copyID, type_gap, TVTT_DO_MEMBER), - member_type, &member_type, type_gap); - return get_dict_type(member_type, type_gap); + 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 (tv->v_type == VAR_FUNC || tv->v_type == VAR_PARTIAL) + if (name == NULL && ufunc == NULL) + return &t_func_unknown; + + if (name != NULL) { - char_u *name = NULL; - ufunc_T *ufunc = NULL; + int idx = find_internal_func(name); - if (tv->v_type == VAR_PARTIAL && tv->vval.v_partial != NULL) + if (idx >= 0) { - 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 && ufunc == NULL) - return &t_func_unknown; - if (name != NULL) - { - int idx = find_internal_func(name); - - if (idx >= 0) - { - type_T *decl_type; // unused + type_T *decl_type; // unused - internal_func_get_argcount(idx, &argcount, &min_argcount); - member_type = internal_func_ret_type(idx, 0, NULL, &decl_type, - type_gap); - } - else - ufunc = find_func(name, FALSE); + internal_func_get_argcount(idx, &argcount, &min_argcount); + member_type = internal_func_ret_type(idx, 0, NULL, &decl_type, + type_gap); } - if (ufunc != NULL) + else + ufunc = find_func(name, FALSE); + } + 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, CT_NONE, NULL) + == FAIL) + return NULL; + if (ufunc->uf_func_type == NULL) + set_function_type(ufunc); + if (ufunc->uf_func_type != 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, CT_NONE, NULL) - == FAIL) - return NULL; - if (ufunc->uf_func_type == NULL) - set_function_type(ufunc); - if (ufunc->uf_func_type != NULL) - { - if (tv->v_type == VAR_PARTIAL && tv->vval.v_partial != NULL - && tv->vval.v_partial->pt_argc > 0) - { - type = get_type_ptr(type_gap); - if (type == NULL) - return NULL; - *type = *ufunc->uf_func_type; - if (type->tt_argcount >= 0) - { - type->tt_argcount -= tv->vval.v_partial->pt_argc; - type->tt_min_argcount -= tv->vval.v_partial->pt_argc; - if (type->tt_argcount > 0 - && func_type_add_arg_types(type, - type->tt_argcount, type_gap) == OK) - for (int i = 0; i < type->tt_argcount; ++i) - type->tt_args[i] = - ufunc->uf_func_type->tt_args[ - i + tv->vval.v_partial->pt_argc]; - } - return type; - } - return ufunc->uf_func_type; - } + if (tv->v_type == VAR_PARTIAL && tv->vval.v_partial != NULL) + return partial_typval2type(tv, ufunc, type_gap); + return ufunc->uf_func_type; } } - if (tv->v_type == VAR_CLASS) - class_type = tv->vval.v_class; - else if (tv->v_type == VAR_OBJECT && tv->vval.v_object != NULL) - class_type = tv->vval.v_object->obj_class; - type = get_type_ptr(type_gap); if (type == NULL) return NULL; @@ -607,18 +668,90 @@ typval2type_int(typval_T *tv, int copyID, garray_T *type_gap, int flags) type->tt_argcount = argcount; type->tt_min_argcount = min_argcount; if (tv->v_type == VAR_PARTIAL && tv->vval.v_partial != NULL - && tv->vval.v_partial->pt_argc > 0) + && tv->vval.v_partial->pt_argc > 0) { type->tt_argcount -= tv->vval.v_partial->pt_argc; type->tt_min_argcount -= tv->vval.v_partial->pt_argc; } type->tt_member = member_type; - type->tt_class = class_type; return type; } /* + * Get a type_T for a typval_T. + * "type_gap" is used to temporarily create types in. + * When "flags" has TVTT_DO_MEMBER also get the member type, otherwise use + * "any". + * When "flags" has TVTT_MORE_SPECIFIC get the more specific member type if it + * is "any". + */ + static type_T * +typval2type_int(typval_T *tv, int copyID, garray_T *type_gap, int flags) +{ + switch (tv->v_type) + { + case VAR_UNKNOWN: + return &t_unknown; + + case VAR_ANY: + return &t_any; + + case VAR_VOID: + return &t_void; + + case VAR_BOOL: + return &t_bool; + + case VAR_SPECIAL: + return special_typval2type(tv); + + case VAR_NUMBER: + return &t_number; + + case VAR_FLOAT: + return &t_float; + + case VAR_STRING: + return &t_string; + + case VAR_BLOB: + if (tv->vval.v_blob == NULL) + return &t_blob_null; + return &t_blob; + + case VAR_LIST: + return list_typval2type(tv, copyID, type_gap, flags); + + case VAR_DICT: + return dict_typval2type(tv, copyID, type_gap, flags); + + case VAR_JOB: + return &t_job; + + case VAR_CHANNEL: + return &t_channel; + + case VAR_CLASS: + case VAR_OBJECT: + return oc_typval2type(tv); + + case VAR_TYPEALIAS: + return &t_typealias; + + case VAR_FUNC: + case VAR_PARTIAL: + return fp_typval2type(tv, type_gap); + + case VAR_INSTR: + default: + break; + } + + return NULL; +} + +/* * Return TRUE if "tv" is not a bool but should be converted to bool. */ int @@ -719,7 +852,7 @@ check_typval_type(type_T *expected, typval_T *actual_tv, where_T where) if (expected == NULL) return OK; // didn't expect anything. - // + ga_init2(&type_list, sizeof(type_T *), 10); // A null_function and null_partial are special cases, they can be used to @@ -737,12 +870,14 @@ check_typval_type(type_T *expected, typval_T *actual_tv, where_T where) { res = check_type_maybe(expected, actual_type, TRUE, where); if (res == MAYBE && !(actual_type->tt_type == VAR_FUNC - && actual_type->tt_member == &t_unknown)) + && (actual_type->tt_member == &t_unknown + || actual_type->tt_member == NULL))) { // If a type check is needed that means assigning "any" or // "unknown" to a more specific type, which fails here. // Except when it looks like a lambda, since they have an - // incomplete type. + // incomplete type. A legacy lambda function has a NULL return + // type. type_mismatch_where(expected, actual_type, where); res = FAIL; } @@ -1149,6 +1284,194 @@ parse_type_member( } /* + * Parse a "func" type at "*arg" and advance over it. + * When "give_error" is TRUE give error messages, otherwise be quiet. + * Return NULL for failure. + */ + static type_T * +parse_type_func(char_u **arg, size_t len, garray_T *type_gap, int give_error) +{ + char_u *p; + 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) + { + if (give_error) + emsg(_(e_mandatory_argument_after_optional_argument)); + return NULL; + } + + type = parse_type(&p, type_gap, give_error); + if (type == NULL) + return NULL; + if ((flags & TTFLAG_VARARGS) != 0 && type->tt_type != VAR_LIST) + { + char *tofree; + semsg(_(e_variable_arguments_type_must_be_list_str), + type_name(type, &tofree)); + vim_free(tofree); + return NULL; + } + arg_type[argcount++] = type; + + // Nothing comes after "...{type}". + if (flags & TTFLAG_VARARGS) + break; + + if (*p != ',' && *skipwhite(p) == ',') + { + if (give_error) + semsg(_(e_no_white_space_allowed_before_str_str), + ",", p); + return NULL; + } + if (*p == ',') + { + ++p; + if (!VIM_ISWHITE(*p)) + { + if (give_error) + semsg(_(e_white_space_required_after_str_str), + ",", p - 1); + return NULL; + } + } + p = skipwhite(p); + if (argcount == MAX_FUNC_ARGS) + { + if (give_error) + emsg(_(e_too_many_argument_types)); + return NULL; + } + } + + p = skipwhite(p); + if (*p != ')') + { + if (give_error) + emsg(_(e_missing_closing_paren)); + return NULL; + } + *arg = p + 1; + } + if (**arg == ':') + { + // parse return type + ++*arg; + if (!VIM_ISWHITE(**arg) && give_error) + semsg(_(e_white_space_required_after_str_str), ":", *arg - 1); + *arg = skipwhite(*arg); + ret_type = parse_type(arg, type_gap, give_error); + if (ret_type == NULL) + return NULL; + } + 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 NULL; + mch_memmove(type->tt_args, arg_type, sizeof(type_T *) * argcount); + } + } + + return type; +} + +/* + * Parse a user defined type at "*arg" and advance over it. + * It can be a class or an interface or a typealias name, possibly imported. + * Return NULL if a type is not found. + */ + static type_T * +parse_type_user_defined( + char_u **arg, + size_t len, + garray_T *type_gap, + int give_error) +{ + int did_emsg_before = did_emsg; + typval_T tv; + + tv.v_type = VAR_UNKNOWN; + if (eval_variable_import(*arg, &tv) == OK) + { + if (tv.v_type == VAR_CLASS && tv.vval.v_class != NULL) + { + type_T *type = get_type_ptr(type_gap); + if (type != NULL) + { + // Although the name is that of a class or interface, the type + // uses will be an object. + type->tt_type = VAR_OBJECT; + type->tt_class = tv.vval.v_class; + clear_tv(&tv); + + *arg += len; + // Skip over ".ClassName". + while (ASCII_ISALNUM(**arg) || **arg == '_' || **arg == '.') + ++*arg; + + return type; + } + } + else if (tv.v_type == VAR_TYPEALIAS) + { + // user defined type + type_T *type = copy_type(tv.vval.v_typealias->ta_type, type_gap); + *arg += len; + clear_tv(&tv); + // Skip over ".TypeName". + while (ASCII_ISALNUM(**arg) || **arg == '_' || **arg == '.') + ++*arg; + return type; + } + + clear_tv(&tv); + } + + if (give_error && (did_emsg == did_emsg_before)) + semsg(_(e_type_not_recognized_str), *arg); + + return NULL; +} + +/* * Parse a type at "arg" and advance over it. * When "give_error" is TRUE give error messages, otherwise be quiet. * Return NULL for failure. @@ -1207,130 +1530,7 @@ parse_type(char_u **arg, garray_T *type_gap, int give_error) return &t_float; } 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) - { - if (give_error) - emsg(_(e_mandatory_argument_after_optional_argument)); - return NULL; - } - - type = parse_type(&p, type_gap, give_error); - if (type == NULL) - return NULL; - if ((flags & TTFLAG_VARARGS) != 0 - && type->tt_type != VAR_LIST) - { - char *tofree; - semsg(_(e_variable_arguments_type_must_be_list_str), - type_name(type, &tofree)); - vim_free(tofree); - return NULL; - } - arg_type[argcount++] = type; - - // Nothing comes after "...{type}". - if (flags & TTFLAG_VARARGS) - break; - - if (*p != ',' && *skipwhite(p) == ',') - { - if (give_error) - semsg(_(e_no_white_space_allowed_before_str_str), - ",", p); - return NULL; - } - if (*p == ',') - { - ++p; - if (!VIM_ISWHITE(*p)) - { - if (give_error) - semsg(_(e_white_space_required_after_str_str), - ",", p - 1); - return NULL; - } - } - p = skipwhite(p); - if (argcount == MAX_FUNC_ARGS) - { - if (give_error) - emsg(_(e_too_many_argument_types)); - return NULL; - } - } - - p = skipwhite(p); - if (*p != ')') - { - if (give_error) - emsg(_(e_missing_closing_paren)); - return NULL; - } - *arg = p + 1; - } - if (**arg == ':') - { - // parse return type - ++*arg; - if (!VIM_ISWHITE(**arg) && give_error) - semsg(_(e_white_space_required_after_str_str), - ":", *arg - 1); - *arg = skipwhite(*arg); - ret_type = parse_type(arg, type_gap, give_error); - if (ret_type == NULL) - return NULL; - } - 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 NULL; - mch_memmove(type->tt_args, arg_type, - sizeof(type_T *) * argcount); - } - } - return type; - } + return parse_type_func(arg, len, type_gap, give_error); break; case 'j': if (len == 3 && STRNCMP(*arg, "job", len) == 0) @@ -1370,50 +1570,8 @@ parse_type(char_u **arg, garray_T *type_gap, int give_error) break; } - // It can be a class or interface name, possibly imported. - int did_emsg_before = did_emsg; - typval_T tv; - - tv.v_type = VAR_UNKNOWN; - if (eval_variable_import(*arg, &tv) == OK) - { - if (tv.v_type == VAR_CLASS && tv.vval.v_class != NULL) - { - type_T *type = get_type_ptr(type_gap); - if (type != NULL) - { - // Although the name is that of a class or interface, the type - // uses will be an object. - type->tt_type = VAR_OBJECT; - type->tt_class = tv.vval.v_class; - clear_tv(&tv); - - *arg += len; - // Skip over ".ClassName". - while (ASCII_ISALNUM(**arg) || **arg == '_' || **arg == '.') - ++*arg; - - return type; - } - } - else if (tv.v_type == VAR_TYPEALIAS) - { - // user defined type - type_T *type = copy_type(tv.vval.v_typealias->ta_type, type_gap); - *arg += len; - clear_tv(&tv); - // Skip over ".TypeName". - while (ASCII_ISALNUM(**arg) || **arg == '_' || **arg == '.') - ++*arg; - return type; - } - - clear_tv(&tv); - } - - if (give_error && (did_emsg == did_emsg_before)) - semsg(_(e_type_not_recognized_str), *arg); - return NULL; + // User defined type + return parse_type_user_defined(arg, len, type_gap, give_error); } /* @@ -1470,6 +1628,60 @@ equal_type(type_T *type1, type_T *type2, int flags) } /* + * Find the common type of "type1" (VAR_FUNC) and "type2" (VAR_FUNC) and put it + * in "dest". "type2" and "dest" may be the same. + */ + static void +common_type_var_func( + type_T *type1, + type_T *type2, + type_T **dest, + garray_T *type_gap) +{ + type_T *common; + + // When one of the types is t_func_unknown return the other one. + // Useful if a list or dict item is null_func. + if (type1 == &t_func_unknown) + { + *dest = type2; + return; + } + if (type2 == &t_func_unknown) + { + *dest = type1; + return; + } + + 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 + // Use -1 for "tt_argcount" to indicate an unknown number of + // arguments. + *dest = alloc_func_type(common, -1, type_gap); + + // Use the minimum of min_argcount. + (*dest)->tt_min_argcount = + type1->tt_min_argcount < type2->tt_min_argcount + ? type1->tt_min_argcount : type2->tt_min_argcount; +} + +/* * Find the common type of "type1" and "type2" and put it in "dest". * "type2" and "dest" may be the same. */ @@ -1508,49 +1720,10 @@ common_type(type_T *type1, type_T *type2, type_T **dest, garray_T *type_gap) *dest = get_dict_type(common, type_gap); return; } + if (type1->tt_type == VAR_FUNC) { - type_T *common; - - // When one of the types is t_func_unknown return the other one. - // Useful if a list or dict item is null_func. - if (type1 == &t_func_unknown) - { - *dest = type2; - return; - } - if (type2 == &t_func_unknown) - { - *dest = type1; - return; - } - - 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 - // Use -1 for "tt_argcount" to indicate an unknown number of - // arguments. - *dest = alloc_func_type(common, -1, type_gap); - - // Use the minimum of min_argcount. - (*dest)->tt_min_argcount = - type1->tt_min_argcount < type2->tt_min_argcount - ? type1->tt_min_argcount : type2->tt_min_argcount; + common_type_var_func(type1, type2, dest, type_gap); return; } } @@ -1705,113 +1878,156 @@ vartype_name(vartype_T type) } /* - * Return the name of a type. + * Return the type name of a List (list<type>) or Dict (dict<type>). * The result may be in allocated memory, in which case "tofree" is set. */ - char * -type_name(type_T *type, char **tofree) + static char * +type_name_list_or_dict(char *name, type_T *type, char **tofree) { - char *name; - char *arg_free = NULL; + char *member_free; + char *member_name; - *tofree = NULL; - if (type == NULL) - return "[unknown]"; - name = vartype_name(type->tt_type); + if (type->tt_member->tt_type == VAR_UNKNOWN) + member_name = type_name(&t_any, &member_free); + else + member_name = type_name(type->tt_member, &member_free); + + size_t len = STRLEN(name) + STRLEN(member_name) + 3; + *tofree = alloc(len); + if (*tofree == NULL) + return name; + + vim_snprintf(*tofree, len, "%s<%s>", name, member_name); + vim_free(member_free); + return *tofree; +} + +/* + * Return the type name of a Class (class<name>) or Object (object<name>). + * The result may be in allocated memory, in which case "tofree" is set. + */ + static char * +type_name_class_or_obj(char *name, type_T *type, char **tofree) +{ + char_u *class_name; - if (type->tt_type == VAR_LIST || type->tt_type == VAR_DICT) + if (type->tt_class != NULL) { - char *member_free; - char *member_name; - if (type->tt_member->tt_type == VAR_UNKNOWN) - member_name = type_name(&t_any, &member_free); - else - member_name = type_name(type->tt_member, &member_free); - size_t 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; - } + class_name = type->tt_class->class_name; + if (IS_ENUM(type->tt_class)) + name = "enum"; } + else + class_name = (char_u *)"Unknown"; - if (type->tt_type == VAR_OBJECT || type->tt_type == VAR_CLASS) + size_t len = STRLEN(name) + STRLEN(class_name) + 3; + *tofree = alloc(len); + if (*tofree == NULL) + return name; + + vim_snprintf(*tofree, len, "%s<%s>", name, class_name); + return *tofree; +} + +/* + * Return the type name of a function. + * The result may be in allocated memory, in which case "tofree" is set. + */ + static char * +type_name_func(type_T *type, char **tofree) +{ + garray_T ga; + int i; + int varargs = (type->tt_flags & TTFLAG_VARARGS) ? 1 : 0; + char *arg_free = NULL; + + ga_init2(&ga, 1, 100); + if (ga_grow(&ga, 20) == FAIL) + goto failed; + STRCPY(ga.ga_data, "func("); + ga.ga_len += 5; + + for (i = 0; i < type->tt_argcount; ++i) { - char_u *class_name = type->tt_class == NULL ? (char_u *)"Unknown" - : type->tt_class->class_name; - size_t len = STRLEN(name) + STRLEN(class_name) + 3; - *tofree = alloc(len); - if (*tofree != NULL) + 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) { - vim_snprintf(*tofree, len, "%s<%s>", name, class_name); - return *tofree; + STRCPY((char *)ga.ga_data + ga.ga_len, ", "); + ga.ga_len += 2; } + len = (int)STRLEN(arg_type); + if (ga_grow(&ga, len + 8) == FAIL) + goto failed; + if (varargs && i == type->tt_argcount - 1) + ga_concat(&ga, (char_u *)"..."); + else if (i >= type->tt_min_argcount) + *((char *)ga.ga_data + ga.ga_len++) = '?'; + ga_concat(&ga, (char_u *)arg_type); + VIM_CLEAR(arg_free); } + if (type->tt_argcount < 0) + // any number of arguments + ga_concat(&ga, (char_u *)"..."); - if (type->tt_type == VAR_FUNC) + if (type->tt_member == &t_void) + STRCPY((char *)ga.ga_data + ga.ga_len, ")"); + else { - garray_T ga; - int i; - int varargs = (type->tt_flags & TTFLAG_VARARGS) ? 1 : 0; + char *ret_free; + char *ret_name = type_name(type->tt_member, &ret_free); + int len; - ga_init2(&ga, 1, 100); - if (ga_grow(&ga, 20) == FAIL) + len = (int)STRLEN(ret_name) + 4; + if (ga_grow(&ga, len) == FAIL) goto failed; - STRCPY(ga.ga_data, "func("); - ga.ga_len += 5; - - for (i = 0; i < type->tt_argcount; ++i) - { - char *arg_type; - int len; + STRCPY((char *)ga.ga_data + ga.ga_len, "): "); + STRCPY((char *)ga.ga_data + ga.ga_len + 3, ret_name); + vim_free(ret_free); + } + *tofree = ga.ga_data; + return ga.ga_data; - 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) - goto failed; - if (varargs && i == type->tt_argcount - 1) - ga_concat(&ga, (char_u *)"..."); - else if (i >= type->tt_min_argcount) - *((char *)ga.ga_data + ga.ga_len++) = '?'; - ga_concat(&ga, (char_u *)arg_type); - VIM_CLEAR(arg_free); - } - if (type->tt_argcount < 0) - // any number of arguments - ga_concat(&ga, (char_u *)"..."); +failed: + vim_free(arg_free); + ga_clear(&ga); + return "[unknown]"; +} - 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) - goto failed; - STRCPY((char *)ga.ga_data + ga.ga_len, "): "); - STRCPY((char *)ga.ga_data + ga.ga_len + 3, ret_name); - vim_free(ret_free); - } - *tofree = ga.ga_data; - return ga.ga_data; +/* + * 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; -failed: - vim_free(arg_free); - ga_clear(&ga); + *tofree = NULL; + if (type == NULL) return "[unknown]"; + name = vartype_name(type->tt_type); + + switch (type->tt_type) + { + case VAR_LIST: + case VAR_DICT: + return type_name_list_or_dict(name, type, tofree); + + case VAR_CLASS: + case VAR_OBJECT: + return type_name_class_or_obj(name, type, tofree); + + case VAR_FUNC: + return type_name_func(type, tofree); + + default: + break; } return name; @@ -1869,18 +2085,26 @@ check_typval_is_value(typval_T *tv) { if (tv == NULL) return OK; - if (tv->v_type == VAR_CLASS) - { - if (tv->vval.v_class != NULL) - semsg(_(e_using_class_as_value_str), tv->vval.v_class->class_name); - else - emsg(e_using_class_as_var_val); - return FAIL; - } - else if (tv->v_type == VAR_TYPEALIAS) + + switch (tv->v_type) { - semsg(_(e_using_typealias_as_value_str), tv->vval.v_typealias->ta_name); - return FAIL; + case VAR_CLASS: + { + class_T *cl = tv->vval.v_class; + if (IS_ENUM(cl)) + semsg(_(e_using_enum_as_value_str), cl->class_name); + else + semsg(_(e_using_class_as_value_str), cl->class_name); + } + return FAIL; + + case VAR_TYPEALIAS: + semsg(_(e_using_typealias_as_value_str), + tv->vval.v_typealias->ta_name); + return FAIL; + + default: + break; } return OK; } @@ -1893,17 +2117,25 @@ check_type_is_value(type_T *type) { if (type == NULL) return OK; - if (type->tt_type == VAR_CLASS) + switch (type->tt_type) { - semsg(_(e_using_class_as_value_str), type->tt_class->class_name); - return FAIL; - } - else if (type->tt_type == VAR_TYPEALIAS) - { - // TODO: Not sure what could be done here to get a name. - // Maybe an optional argument? - emsg(_(e_using_typealias_as_var_val)); - return FAIL; + case VAR_CLASS: + if (IS_ENUM(type->tt_class)) + semsg(_(e_using_enum_as_value_str), + type->tt_class->class_name); + else + semsg(_(e_using_class_as_value_str), + type->tt_class->class_name); + return FAIL; + + case VAR_TYPEALIAS: + // TODO: Not sure what could be done here to get a name. + // Maybe an optional argument? + emsg(_(e_using_typealias_as_var_val)); + return FAIL; + + default: + break; } return OK; } diff --git a/src/window.c b/src/window.c index 9ffca77..7322905 100644 --- a/src/window.c +++ b/src/window.c @@ -2475,6 +2475,7 @@ win_init_empty(win_T *wp) wp->w_topfill = 0; #endif wp->w_botline = 2; + wp->w_valid = 0; #if defined(FEAT_SYN_HL) || defined(FEAT_SPELL) wp->w_s = &wp->w_buffer->b_s; #endif @@ -4437,8 +4438,7 @@ win_init_popup_win(win_T *wp, buf_T *buf) ++buf->b_nwindows; win_init_empty(wp); // set cursor and topline to safe values - // Make sure w_localdir and globaldir are NULL to avoid a chdir() in - // win_enter_ext(). + // Make sure w_localdir is NULL to avoid a chdir() in win_enter_ext(). VIM_CLEAR(wp->w_localdir); } @@ -5445,8 +5445,8 @@ win_enter(win_T *wp, int undo_sync) * Used after making another window the current one: change directory if * needed. */ - static void -fix_current_dir(void) + void +win_fix_current_dir(void) { if (curwin->w_localdir != NULL || curtab->tp_localdir != NULL) { @@ -5567,7 +5567,7 @@ win_enter_ext(win_T *wp, int flags) } #endif - fix_current_dir(); + win_fix_current_dir(); #ifdef FEAT_JOB_CHANNEL entering_window(curwin); |