mirror of
https://github.com/vim/vim
synced 2025-07-22 06:12:36 +00:00
Compare commits
16 Commits
Author | SHA1 | Date | |
---|---|---|---|
3a53ec8bdd | |||
38ddf333f6 | |||
4d4d1cd5c8 | |||
f4ee528086 | |||
9d48956681 | |||
ea2d8d2571 | |||
c7e44a7e4c | |||
696ba23149 | |||
1040956292 | |||
7b7f78f51d | |||
33afa2447b | |||
ac7bf8c4bf | |||
ed3c7e6339 | |||
f9a343f8bd | |||
b61ef01cce | |||
45df2a01a7 |
223
.github/workflows/ci-windows.yaml
vendored
Normal file
223
.github/workflows/ci-windows.yaml
vendored
Normal file
@ -0,0 +1,223 @@
|
|||||||
|
name: GitHub CI
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- '*'
|
||||||
|
pull_request:
|
||||||
|
|
||||||
|
env:
|
||||||
|
VCVARSALL: C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Auxiliary\Build\vcvarsall.bat
|
||||||
|
|
||||||
|
# Interfaces
|
||||||
|
# Lua
|
||||||
|
LUA_VER: 54
|
||||||
|
LUA_VER_DOT: '5.4'
|
||||||
|
LUA_RELEASE: 5.4.0
|
||||||
|
LUA32_URL: https://downloads.sourceforge.net/luabinaries/lua-%LUA_RELEASE%_Win32_dllw6_lib.zip
|
||||||
|
LUA64_URL: https://downloads.sourceforge.net/luabinaries/lua-%LUA_RELEASE%_Win64_dllw6_lib.zip
|
||||||
|
LUA_DIR: D:\Lua
|
||||||
|
# Python 2
|
||||||
|
PYTHON_VER: 27
|
||||||
|
PYTHON_VER_DOT: '2.7'
|
||||||
|
# Python 3
|
||||||
|
PYTHON3_VER: 38
|
||||||
|
PYTHON3_VER_DOT: '3.8'
|
||||||
|
|
||||||
|
# Other dependencies
|
||||||
|
# winpty
|
||||||
|
WINPTY_URL: https://github.com/rprichard/winpty/releases/download/0.4.3/winpty-0.4.3-msvc2015.zip
|
||||||
|
|
||||||
|
# Escape sequences
|
||||||
|
COL_RED: "\x1b[31m"
|
||||||
|
COL_GREEN: "\x1b[32m"
|
||||||
|
COL_YELLOW: "\x1b[33m"
|
||||||
|
COL_RESET: "\x1b[m"
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
runs-on: windows-latest
|
||||||
|
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
toolchain: [msvc, mingw]
|
||||||
|
arch: [x64, x86]
|
||||||
|
features: [HUGE, NORMAL]
|
||||||
|
include:
|
||||||
|
- arch: x64
|
||||||
|
vcarch: amd64
|
||||||
|
warch: x64
|
||||||
|
bits: 64
|
||||||
|
msystem: MINGW64
|
||||||
|
cygreg: registry
|
||||||
|
pyreg: ""
|
||||||
|
- arch: x86
|
||||||
|
vcarch: x86
|
||||||
|
warch: ia32
|
||||||
|
bits: 32
|
||||||
|
msystem: MINGW32
|
||||||
|
cygreg: registry32
|
||||||
|
pyreg: "-32"
|
||||||
|
exclude:
|
||||||
|
- toolchain: msvc
|
||||||
|
arch: x64
|
||||||
|
features: NORMAL
|
||||||
|
- toolchain: mingw
|
||||||
|
arch: x86
|
||||||
|
features: NORMAL
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Initalize
|
||||||
|
id: init
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
git config --global core.autocrlf input
|
||||||
|
python_dir=$(cat "/proc/${{ matrix.cygreg }}/HKEY_LOCAL_MACHINE/SOFTWARE/Python/PythonCore/${PYTHON_VER_DOT}/InstallPath/@")
|
||||||
|
python3_dir=$(cat "/proc/${{ matrix.cygreg }}/HKEY_LOCAL_MACHINE/SOFTWARE/Python/PythonCore/${PYTHON3_VER_DOT}${{ matrix.pyreg }}/InstallPath/@")
|
||||||
|
echo "::set-env name=PYTHON_DIR::$python_dir"
|
||||||
|
echo "::set-env name=PYTHON3_DIR::$python3_dir"
|
||||||
|
|
||||||
|
- uses: msys2/setup-msys2@v2
|
||||||
|
if: matrix.toolchain == 'mingw'
|
||||||
|
with:
|
||||||
|
msystem: ${{ matrix.msystem }}
|
||||||
|
release: false
|
||||||
|
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
|
||||||
|
- name: Create a list of download URLs
|
||||||
|
shell: cmd
|
||||||
|
run: |
|
||||||
|
type NUL > urls.txt
|
||||||
|
echo %LUA_RELEASE%>> urls.txt
|
||||||
|
echo %WINPTY_URL%>> urls.txt
|
||||||
|
|
||||||
|
- name: Cache downloaded files
|
||||||
|
uses: actions/cache@v2
|
||||||
|
with:
|
||||||
|
path: downloads
|
||||||
|
key: ${{ runner.os }}-${{ matrix.bits }}-${{ hashFiles('urls.txt') }}
|
||||||
|
|
||||||
|
- name: Download dependencies
|
||||||
|
shell: cmd
|
||||||
|
run: |
|
||||||
|
path C:\Program Files\7-Zip;%path%
|
||||||
|
if not exist downloads mkdir downloads
|
||||||
|
|
||||||
|
echo %COL_GREEN%Download Lua%COL_RESET%
|
||||||
|
call :downloadfile %LUA${{ matrix.bits }}_URL% downloads\lua.zip
|
||||||
|
7z x downloads\lua.zip -o%LUA_DIR% > nul || exit 1
|
||||||
|
|
||||||
|
echo %COL_GREEN%Download winpty%COL_RESET%
|
||||||
|
call :downloadfile %WINPTY_URL% downloads\winpty.zip
|
||||||
|
7z x -y downloads\winpty.zip -oD:\winpty > nul || exit 1
|
||||||
|
copy /Y D:\winpty\${{ matrix.warch }}\bin\winpty.dll src\winpty${{ matrix.bits }}.dll
|
||||||
|
copy /Y D:\winpty\${{ matrix.warch }}\bin\winpty-agent.exe src\
|
||||||
|
|
||||||
|
goto :eof
|
||||||
|
|
||||||
|
:downloadfile
|
||||||
|
:: call :downloadfile <URL> <localfile>
|
||||||
|
if not exist %2 (
|
||||||
|
curl -f -L %1 -o %2
|
||||||
|
)
|
||||||
|
if ERRORLEVEL 1 (
|
||||||
|
rem Retry once.
|
||||||
|
curl -f -L %1 -o %2 || exit 1
|
||||||
|
)
|
||||||
|
goto :eof
|
||||||
|
|
||||||
|
- name: Build (MSVC)
|
||||||
|
if: matrix.toolchain == 'msvc'
|
||||||
|
shell: cmd
|
||||||
|
run: |
|
||||||
|
call "%VCVARSALL%" ${{ matrix.vcarch }}
|
||||||
|
cd src
|
||||||
|
:: Filter out the progress bar from the build log
|
||||||
|
sed -e "s/@<<$/@<< | sed -e 's#.*\\\\r.*##'/" Make_mvc.mak > Make_mvc2.mak
|
||||||
|
if "${{ matrix.features }}"=="HUGE" (
|
||||||
|
nmake -nologo -f Make_mvc2.mak ^
|
||||||
|
FEATURES=${{ matrix.features }} ^
|
||||||
|
GUI=yes IME=yes ICONV=yes VIMDLL=yes ^
|
||||||
|
DYNAMIC_LUA=yes LUA=%LUA_DIR% ^
|
||||||
|
DYNAMIC_PYTHON=yes PYTHON=%PYTHON_DIR% ^
|
||||||
|
DYNAMIC_PYTHON3=yes PYTHON3=%PYTHON3_DIR%
|
||||||
|
) else (
|
||||||
|
nmake -nologo -f Make_mvc2.mak ^
|
||||||
|
FEATURES=${{ matrix.features }} ^
|
||||||
|
GUI=yes IME=yes ICONV=yes VIMDLL=yes
|
||||||
|
)
|
||||||
|
if not exist vim${{ matrix.bits }}.dll (
|
||||||
|
echo %COL_RED%Build failure.%COL_RESET%
|
||||||
|
exit 1
|
||||||
|
)
|
||||||
|
|
||||||
|
- name: Build (MinGW)
|
||||||
|
if: matrix.toolchain == 'mingw'
|
||||||
|
shell: msys2 {0}
|
||||||
|
run: |
|
||||||
|
cd src
|
||||||
|
if [ "${{ matrix.features }}" = "HUGE" ]; then
|
||||||
|
mingw32-make -f Make_ming.mak -j2 \
|
||||||
|
FEATURES=${{ matrix.features }} \
|
||||||
|
GUI=yes IME=yes ICONV=yes VIMDLL=yes \
|
||||||
|
DYNAMIC_LUA=yes LUA=${LUA_DIR} \
|
||||||
|
DYNAMIC_PYTHON=yes PYTHON=${PYTHON_DIR} \
|
||||||
|
DYNAMIC_PYTHON3=yes PYTHON3=${PYTHON3_DIR} \
|
||||||
|
STATIC_STDCPLUS=yes
|
||||||
|
else
|
||||||
|
mingw32-make -f Make_ming.mak -j2 \
|
||||||
|
FEATURES=${{ matrix.features }} \
|
||||||
|
GUI=yes IME=yes ICONV=yes VIMDLL=yes \
|
||||||
|
STATIC_STDCPLUS=yes
|
||||||
|
fi
|
||||||
|
|
||||||
|
# - name: Prepare Artifact
|
||||||
|
# shell: cmd
|
||||||
|
# run: |
|
||||||
|
# mkdir artifacts
|
||||||
|
# copy src\*vim.exe artifacts
|
||||||
|
# copy src\vim*.dll artifacts
|
||||||
|
#
|
||||||
|
# - name: Upload Artifact
|
||||||
|
# uses: actions/upload-artifact@v1
|
||||||
|
# with:
|
||||||
|
# name: vim${{ matrix.bits }}-${{ matrix.toolchain }}
|
||||||
|
# path: ./artifacts
|
||||||
|
|
||||||
|
- name: Test
|
||||||
|
shell: cmd
|
||||||
|
timeout-minutes: 20
|
||||||
|
run: |
|
||||||
|
PATH %LUA_DIR%;C:\msys64\${{ matrix.msystem }}\bin;%PATH%;%PYTHON3_DIR%
|
||||||
|
call "%VCVARSALL%" ${{ matrix.vcarch }}
|
||||||
|
cd src
|
||||||
|
echo.
|
||||||
|
echo %COL_GREEN%vim version:%COL_RESET%
|
||||||
|
.\vim --version || exit 1
|
||||||
|
|
||||||
|
mkdir ..\src2
|
||||||
|
xcopy testdir ..\src2\testdir\ /E > nul || exit 1
|
||||||
|
copy evalfunc.c ..\src2 > nul
|
||||||
|
|
||||||
|
echo %COL_GREEN%Start testing vim in background.%COL_RESET%
|
||||||
|
start cmd /c "cd ..\src2\testdir & nmake -nologo -f Make_dos.mak VIMPROG=..\..\src\vim > nul & echo done>done.txt"
|
||||||
|
|
||||||
|
echo %COL_GREEN%Test gvim:%COL_RESET%
|
||||||
|
cd testdir
|
||||||
|
nmake -nologo -f Make_dos.mak VIMPROG=..\gvim || exit 1
|
||||||
|
cd ..
|
||||||
|
|
||||||
|
echo %COL_GREEN%Wait for vim tests to finish.%COL_RESET%
|
||||||
|
cd ..\src2\testdir
|
||||||
|
:: Wait about 5 minutes.
|
||||||
|
for /L %%i in (1,1,300) do (
|
||||||
|
if exist done.txt goto exitloop
|
||||||
|
ping -n 2 localhost > nul
|
||||||
|
)
|
||||||
|
echo %COL_RED%Timed out.%COL_RESET%
|
||||||
|
:exitloop
|
||||||
|
|
||||||
|
echo %COL_GREEN%Test results of vim:%COL_RESET%
|
||||||
|
if exist messages type messages
|
||||||
|
nmake -nologo -f Make_dos.mak report VIMPROG=..\..\src\vim || exit 1
|
1
Filelist
1
Filelist
@ -9,6 +9,7 @@ SRC_ALL = \
|
|||||||
.lgtm.yml \
|
.lgtm.yml \
|
||||||
.travis.yml \
|
.travis.yml \
|
||||||
.cirrus.yml \
|
.cirrus.yml \
|
||||||
|
.github/workflows/ci-windows.yaml \
|
||||||
appveyor.yml \
|
appveyor.yml \
|
||||||
ci/appveyor.bat \
|
ci/appveyor.bat \
|
||||||
ci/if_ver*.vim \
|
ci/if_ver*.vim \
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
[](https://travis-ci.org/vim/vim)
|
[](https://travis-ci.org/vim/vim)
|
||||||
[](https://ci.appveyor.com/project/chrisbra/vim)
|
[](https://ci.appveyor.com/project/chrisbra/vim)
|
||||||
|
[](https://github.com/vim/vim/actions?query=workflow%3A%22GitHub+CI%22)
|
||||||
[](https://cirrus-ci.com/github/vim/vim)
|
[](https://cirrus-ci.com/github/vim/vim)
|
||||||
[](https://codecov.io/gh/vim/vim?branch=master)
|
[](https://codecov.io/gh/vim/vim?branch=master)
|
||||||
[](https://scan.coverity.com/projects/vim)
|
[](https://scan.coverity.com/projects/vim)
|
||||||
|
@ -5,16 +5,17 @@ skip_tags: true
|
|||||||
environment:
|
environment:
|
||||||
matrix:
|
matrix:
|
||||||
- FEATURE: HUGE
|
- FEATURE: HUGE
|
||||||
- FEATURE: NORMAL
|
|
||||||
# disabled
|
# disabled
|
||||||
# - FEATURE: TINY
|
# - FEATURE: TINY
|
||||||
# - FEATURE: SMALL
|
# - FEATURE: SMALL
|
||||||
|
# - FEATURE: NORMAL
|
||||||
# - FEATURE: BIG
|
# - FEATURE: BIG
|
||||||
|
|
||||||
matrix:
|
matrix:
|
||||||
fast_finish: true
|
fast_finish: true
|
||||||
|
|
||||||
before_build:
|
before_build:
|
||||||
|
# Use Windows SDK 7.1 (= MSVC 2010)
|
||||||
- '"C:\Program Files\Microsoft SDKs\Windows\v7.1\Bin\SetEnv.cmd" /x64 /release'
|
- '"C:\Program Files\Microsoft SDKs\Windows\v7.1\Bin\SetEnv.cmd" /x64 /release'
|
||||||
- 'set INCLUDE=%INCLUDE%C:\Program Files (x86)\Windows Kits\8.1\Include\um'
|
- 'set INCLUDE=%INCLUDE%C:\Program Files (x86)\Windows Kits\8.1\Include\um'
|
||||||
|
|
||||||
@ -25,9 +26,9 @@ test_script:
|
|||||||
- cd src/testdir
|
- cd src/testdir
|
||||||
# Testing with MSVC gvim
|
# Testing with MSVC gvim
|
||||||
- path C:\Python35-x64;%PATH%
|
- path C:\Python35-x64;%PATH%
|
||||||
- nmake -f Make_dos.mak POSTSCRIPT=yes VIMPROG=..\gvim
|
- nmake -f Make_dos.mak VIMPROG=..\gvim
|
||||||
- nmake -f Make_dos.mak clean
|
- nmake -f Make_dos.mak clean
|
||||||
# Testing with MingW console version
|
# Testing with MSVC console version
|
||||||
- nmake -f Make_dos.mak POSTSCRIPT=yes VIMPROG=..\vim
|
- nmake -f Make_dos.mak VIMPROG=..\vim
|
||||||
|
|
||||||
# vim: sw=2 sts=2 et ts=8 sr
|
# vim: sw=2 sts=2 et ts=8 sr
|
||||||
|
@ -5,48 +5,32 @@ setlocal ENABLEDELAYEDEXPANSION
|
|||||||
cd %APPVEYOR_BUILD_FOLDER%
|
cd %APPVEYOR_BUILD_FOLDER%
|
||||||
|
|
||||||
cd src
|
cd src
|
||||||
echo "Building MinGW 32bit console version"
|
|
||||||
set PATH=c:\msys64\mingw32\bin;%PATH%
|
|
||||||
mingw32-make.exe -f Make_ming.mak GUI=no OPTIMIZE=speed IME=yes ICONV=yes DEBUG=no FEATURES=%FEATURE% || exit 1
|
|
||||||
.\vim -u NONE -c "redir @a | ver |0put a | wq" ver_ming.txt
|
|
||||||
:: Save vim.exe before Make clean, moved back below.
|
|
||||||
copy vim.exe testdir
|
|
||||||
mingw32-make.exe -f Make_ming.mak clean
|
|
||||||
|
|
||||||
:: Build Mingw huge version with python and channel support, or
|
|
||||||
:: with specified features without python.
|
|
||||||
echo "Building MinGW 32bit GUI version"
|
|
||||||
if "%FEATURE%" == "HUGE" (
|
|
||||||
mingw32-make.exe -f Make_ming.mak OPTIMIZE=speed CHANNEL=yes GUI=yes IME=yes ICONV=yes DEBUG=no PYTHON_VER=27 DYNAMIC_PYTHON=yes PYTHON=C:\Python27 PYTHON3_VER=35 DYNAMIC_PYTHON3=yes PYTHON3=C:\Python35 FEATURES=%FEATURE% || exit 1
|
|
||||||
) ELSE (
|
|
||||||
mingw32-make.exe -f Make_ming.mak OPTIMIZE=speed GUI=yes IME=yes ICONV=yes DEBUG=no FEATURES=%FEATURE% || exit 1
|
|
||||||
)
|
|
||||||
.\gvim -u NONE -c "redir @a | ver |0put a | wq" ver_ming_gui.txt
|
|
||||||
|
|
||||||
:: Filter out the progress bar from the build log
|
:: Filter out the progress bar from the build log
|
||||||
sed -e "s/@<<$/@<< | sed -e 's#.*\\\\r.*##'/" Make_mvc.mak > Make_mvc2.mak
|
sed -e "s/@<<$/@<< | sed -e 's#.*\\\\r.*##'/" Make_mvc.mak > Make_mvc2.mak
|
||||||
|
|
||||||
echo "Building MSVC 64bit console Version"
|
echo "Building MSVC 64bit console Version"
|
||||||
nmake -f Make_mvc2.mak CPU=AMD64 OLE=no GUI=no IME=yes ICONV=yes DEBUG=no FEATURES=%FEATURE% || exit 1
|
nmake -f Make_mvc2.mak CPU=AMD64 ^
|
||||||
:: The executable is not used
|
OLE=no GUI=no IME=yes ICONV=yes DEBUG=no ^
|
||||||
nmake -f Make_mvc2.mak clean
|
FEATURES=%FEATURE% || exit 1
|
||||||
|
|
||||||
:: build MSVC huge version with python and channel support
|
:: build MSVC huge version with python and channel support
|
||||||
:: GUI needs to be last, so that testing works
|
:: GUI needs to be last, so that testing works
|
||||||
echo "Building MSVC 64bit GUI Version"
|
echo "Building MSVC 64bit GUI Version"
|
||||||
if "%FEATURE%" == "HUGE" (
|
if "%FEATURE%" == "HUGE" (
|
||||||
nmake -f Make_mvc2.mak DIRECTX=yes CPU=AMD64 CHANNEL=yes OLE=no GUI=yes IME=yes ICONV=yes DEBUG=no PYTHON_VER=27 DYNAMIC_PYTHON=yes PYTHON=C:\Python27-x64 PYTHON3_VER=35 DYNAMIC_PYTHON3=yes PYTHON3=C:\Python35-x64 FEATURES=%FEATURE% || exit 1
|
nmake -f Make_mvc2.mak CPU=AMD64 ^
|
||||||
|
OLE=no GUI=yes IME=yes ICONV=yes DEBUG=no POSTSCRIPT=yes ^
|
||||||
|
PYTHON_VER=27 DYNAMIC_PYTHON=yes PYTHON=C:\Python27-x64 ^
|
||||||
|
PYTHON3_VER=35 DYNAMIC_PYTHON3=yes PYTHON3=C:\Python35-x64 ^
|
||||||
|
FEATURES=%FEATURE% || exit 1
|
||||||
) ELSE (
|
) ELSE (
|
||||||
nmake -f Make_mvc2.mak CPU=AMD64 OLE=no GUI=yes IME=yes ICONV=yes DEBUG=no FEATURES=%FEATURE% || exit 1
|
nmake -f Make_mvc2.mak CPU=AMD64 ^
|
||||||
|
OLE=no GUI=yes IME=yes ICONV=yes DEBUG=no ^
|
||||||
|
FEATURES=%FEATURE% || exit 1
|
||||||
)
|
)
|
||||||
.\gvim -u NONE -c "redir @a | ver |0put a | wq" ver_msvc.txt
|
.\gvim -u NONE -c "redir @a | ver |0put a | wq" ver_msvc.txt
|
||||||
|
|
||||||
:: Restore vim.exe, tests will run with this.
|
echo "version output MSVC console"
|
||||||
move /Y testdir\vim.exe .
|
.\vim --version
|
||||||
echo "version output MinGW"
|
echo "version output MSVC GUI"
|
||||||
type ver_ming.txt
|
|
||||||
echo "version output MinGW GUI"
|
|
||||||
type ver_ming_gui.txt
|
|
||||||
echo "version output MVC"
|
|
||||||
type ver_msvc.txt
|
type ver_msvc.txt
|
||||||
cd ..
|
cd ..
|
||||||
|
@ -118,9 +118,13 @@ Functions and variables are script-local by default ~
|
|||||||
*vim9-scopes*
|
*vim9-scopes*
|
||||||
When using `:function` or `:def` to specify a new function at the script level
|
When using `:function` or `:def` to specify a new function at the script level
|
||||||
in a Vim9 script, the function is local to the script, as if "s:" was
|
in a Vim9 script, the function is local to the script, as if "s:" was
|
||||||
prefixed. Using the "s:" prefix is optional.
|
prefixed. Using the "s:" prefix is optional. To define or use a global
|
||||||
|
function or variable the "g:" prefix must be used. For functions in an
|
||||||
To define or use a global function or variable the "g:" prefix must be used.
|
autoload script the "name#" prefix is sufficient. >
|
||||||
|
def ThisFunction() # script-local
|
||||||
|
def s:ThisFunction() # script-local
|
||||||
|
def g:ThatFunction() # global
|
||||||
|
def scriptname#function() # autoload
|
||||||
|
|
||||||
When using `:function` or `:def` to specify a new function inside a function,
|
When using `:function` or `:def` to specify a new function inside a function,
|
||||||
the function is local to the function. It is not possible to define a
|
the function is local to the function. It is not possible to define a
|
||||||
|
@ -2310,7 +2310,7 @@ test_libvterm:
|
|||||||
|
|
||||||
# Run individual OLD style test.
|
# Run individual OLD style test.
|
||||||
# These do not depend on the executable, compile it when needed.
|
# These do not depend on the executable, compile it when needed.
|
||||||
test1 test42 test49 test59:
|
test1 test49 test59:
|
||||||
cd testdir; rm -f $@.out; $(MAKE) -f Makefile $@.out VIMPROG=../$(VIMTESTTARGET) $(GUI_TESTARG) SCRIPTSOURCE=../$(SCRIPTSOURCE)
|
cd testdir; rm -f $@.out; $(MAKE) -f Makefile $@.out VIMPROG=../$(VIMTESTTARGET) $(GUI_TESTARG) SCRIPTSOURCE=../$(SCRIPTSOURCE)
|
||||||
|
|
||||||
# Run individual NEW style test.
|
# Run individual NEW style test.
|
||||||
|
5
src/auto/configure
vendored
5
src/auto/configure
vendored
@ -7417,7 +7417,7 @@ $as_echo_n "checking for location of Tcl include... " >&6; }
|
|||||||
if test "x$MACOS_X" != "xyes"; then
|
if test "x$MACOS_X" != "xyes"; then
|
||||||
tclinc="$tclloc/include $tclloc/include/tcl $tclloc/include/tcl$tclver /usr/local/include /usr/local/include/tcl$tclver /usr/include /usr/include/tcl$tclver"
|
tclinc="$tclloc/include $tclloc/include/tcl $tclloc/include/tcl$tclver /usr/local/include /usr/local/include/tcl$tclver /usr/include /usr/include/tcl$tclver"
|
||||||
else
|
else
|
||||||
tclinc="/System/Library/Frameworks/Tcl.framework/Headers"
|
tclinc="$tclloc/include $tclloc/include/tcl $tclloc/include/tcl$tclver /System/Library/Frameworks/Tcl.framework/Headers `xcrun --show-sdk-path`/System/Library/Frameworks/Tcl.framework/Versions/Current/Headers"
|
||||||
fi
|
fi
|
||||||
TCL_INC=
|
TCL_INC=
|
||||||
for try in $tclinc; do
|
for try in $tclinc; do
|
||||||
@ -7440,7 +7440,8 @@ $as_echo_n "checking for location of tclConfig.sh script... " >&6; }
|
|||||||
tclcnf=`echo $tclinc | sed s/include/lib/g`
|
tclcnf=`echo $tclinc | sed s/include/lib/g`
|
||||||
tclcnf="$tclcnf `echo $tclinc | sed s/include/lib64/g`"
|
tclcnf="$tclcnf `echo $tclinc | sed s/include/lib64/g`"
|
||||||
else
|
else
|
||||||
tclcnf="/System/Library/Frameworks/Tcl.framework"
|
tclcnf=`echo $tclinc | sed s/include/lib/g`
|
||||||
|
tclcnf="$tclcnf /System/Library/Frameworks/Tcl.framework `xcrun --show-sdk-path`/System/Library/Frameworks/Tcl.framework"
|
||||||
fi
|
fi
|
||||||
for try in $tclcnf; do
|
for try in $tclcnf; do
|
||||||
if test -f "$try/tclConfig.sh"; then
|
if test -f "$try/tclConfig.sh"; then
|
||||||
|
@ -1820,8 +1820,10 @@ if test "$enable_tclinterp" = "yes" -o "$enable_tclinterp" = "dynamic"; then
|
|||||||
if test "x$MACOS_X" != "xyes"; then
|
if test "x$MACOS_X" != "xyes"; then
|
||||||
tclinc="$tclloc/include $tclloc/include/tcl $tclloc/include/tcl$tclver /usr/local/include /usr/local/include/tcl$tclver /usr/include /usr/include/tcl$tclver"
|
tclinc="$tclloc/include $tclloc/include/tcl $tclloc/include/tcl$tclver /usr/local/include /usr/local/include/tcl$tclver /usr/include /usr/include/tcl$tclver"
|
||||||
else
|
else
|
||||||
|
dnl For all macOS, use the value from TCL in case use of, say, homebrew
|
||||||
dnl For Mac OS X 10.3, use the OS-provided framework location
|
dnl For Mac OS X 10.3, use the OS-provided framework location
|
||||||
tclinc="/System/Library/Frameworks/Tcl.framework/Headers"
|
dnl For Mac OS X 10.14, the OS-provided framework location doesn't contain the headers, so also check the Xcode SDK
|
||||||
|
tclinc="$tclloc/include $tclloc/include/tcl $tclloc/include/tcl$tclver /System/Library/Frameworks/Tcl.framework/Headers `xcrun --show-sdk-path`/System/Library/Frameworks/Tcl.framework/Versions/Current/Headers"
|
||||||
fi
|
fi
|
||||||
TCL_INC=
|
TCL_INC=
|
||||||
for try in $tclinc; do
|
for try in $tclinc; do
|
||||||
@ -1841,8 +1843,11 @@ if test "$enable_tclinterp" = "yes" -o "$enable_tclinterp" = "dynamic"; then
|
|||||||
tclcnf=`echo $tclinc | sed s/include/lib/g`
|
tclcnf=`echo $tclinc | sed s/include/lib/g`
|
||||||
tclcnf="$tclcnf `echo $tclinc | sed s/include/lib64/g`"
|
tclcnf="$tclcnf `echo $tclinc | sed s/include/lib64/g`"
|
||||||
else
|
else
|
||||||
|
dnl For all macOS, use the value from TCL in case use of, say, homebrew
|
||||||
dnl For Mac OS X 10.3, use the OS-provided framework location
|
dnl For Mac OS X 10.3, use the OS-provided framework location
|
||||||
tclcnf="/System/Library/Frameworks/Tcl.framework"
|
dnl For Mac OS X 10.14, the OS-provided framework location doesn't contain the headers, so also check the Xcode SDK
|
||||||
|
tclcnf=`echo $tclinc | sed s/include/lib/g`
|
||||||
|
tclcnf="$tclcnf /System/Library/Frameworks/Tcl.framework `xcrun --show-sdk-path`/System/Library/Frameworks/Tcl.framework"
|
||||||
fi
|
fi
|
||||||
for try in $tclcnf; do
|
for try in $tclcnf; do
|
||||||
if test -f "$try/tclConfig.sh"; then
|
if test -f "$try/tclConfig.sh"; then
|
||||||
|
@ -838,6 +838,10 @@ eval_dict(char_u **arg, typval_T *rettv, evalarg_T *evalarg, int literal)
|
|||||||
: eval1(arg, &tvkey, evalarg)) == FAIL) // recursive!
|
: eval1(arg, &tvkey, evalarg)) == FAIL) // recursive!
|
||||||
goto failret;
|
goto failret;
|
||||||
|
|
||||||
|
// the colon should come right after the key, but this wasn't checked
|
||||||
|
// previously, so only require it in Vim9 script.
|
||||||
|
if (!vim9script)
|
||||||
|
*arg = skipwhite(*arg);
|
||||||
if (**arg != ':')
|
if (**arg != ':')
|
||||||
{
|
{
|
||||||
if (evaluate)
|
if (evaluate)
|
||||||
@ -891,7 +895,10 @@ eval_dict(char_u **arg, typval_T *rettv, evalarg_T *evalarg, int literal)
|
|||||||
}
|
}
|
||||||
clear_tv(&tvkey);
|
clear_tv(&tvkey);
|
||||||
|
|
||||||
// the comma must come after the value
|
// the comma should come right after the value, but this wasn't checked
|
||||||
|
// previously, so only require it in Vim9 script.
|
||||||
|
if (!vim9script)
|
||||||
|
*arg = skipwhite(*arg);
|
||||||
had_comma = **arg == ',';
|
had_comma = **arg == ',';
|
||||||
if (had_comma)
|
if (had_comma)
|
||||||
{
|
{
|
||||||
|
89
src/eval.c
89
src/eval.c
@ -1913,27 +1913,28 @@ eval_func(
|
|||||||
char_u *
|
char_u *
|
||||||
eval_next_non_blank(char_u *arg, evalarg_T *evalarg, int *getnext)
|
eval_next_non_blank(char_u *arg, evalarg_T *evalarg, int *getnext)
|
||||||
{
|
{
|
||||||
|
char_u *p = skipwhite(arg);
|
||||||
|
|
||||||
*getnext = FALSE;
|
*getnext = FALSE;
|
||||||
if (in_vim9script()
|
if (in_vim9script()
|
||||||
&& evalarg != NULL
|
&& evalarg != NULL
|
||||||
&& (evalarg->eval_cookie != NULL || evalarg->eval_cctx != NULL)
|
&& (evalarg->eval_cookie != NULL || evalarg->eval_cctx != NULL)
|
||||||
&& (*arg == NUL || (VIM_ISWHITE(arg[-1])
|
&& (*p == NUL || (VIM_ISWHITE(p[-1]) && vim9_comment_start(p))))
|
||||||
&& vim9_comment_start(arg))))
|
|
||||||
{
|
{
|
||||||
char_u *p;
|
char_u *next;
|
||||||
|
|
||||||
if (evalarg->eval_cookie != NULL)
|
if (evalarg->eval_cookie != NULL)
|
||||||
p = getline_peek(evalarg->eval_getline, evalarg->eval_cookie);
|
next = getline_peek(evalarg->eval_getline, evalarg->eval_cookie);
|
||||||
else
|
else
|
||||||
p = peek_next_line_from_context(evalarg->eval_cctx);
|
next = peek_next_line_from_context(evalarg->eval_cctx);
|
||||||
|
|
||||||
if (p != NULL)
|
if (next != NULL)
|
||||||
{
|
{
|
||||||
*getnext = TRUE;
|
*getnext = TRUE;
|
||||||
return skipwhite(p);
|
return skipwhite(next);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return arg;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -2039,6 +2040,7 @@ eval0(
|
|||||||
|
|
||||||
p = skipwhite(arg);
|
p = skipwhite(arg);
|
||||||
ret = eval1(&p, rettv, evalarg);
|
ret = eval1(&p, rettv, evalarg);
|
||||||
|
p = skipwhite(p);
|
||||||
|
|
||||||
if (ret == FAIL || !ends_excmd2(arg, p))
|
if (ret == FAIL || !ends_excmd2(arg, p))
|
||||||
{
|
{
|
||||||
@ -2107,6 +2109,8 @@ eval1(char_u **arg, typval_T *rettv, evalarg_T *evalarg)
|
|||||||
|
|
||||||
if (getnext)
|
if (getnext)
|
||||||
*arg = eval_next_line(evalarg_used);
|
*arg = eval_next_line(evalarg_used);
|
||||||
|
else
|
||||||
|
*arg = p;
|
||||||
|
|
||||||
result = FALSE;
|
result = FALSE;
|
||||||
if (evaluate)
|
if (evaluate)
|
||||||
@ -2142,6 +2146,8 @@ eval1(char_u **arg, typval_T *rettv, evalarg_T *evalarg)
|
|||||||
}
|
}
|
||||||
if (getnext)
|
if (getnext)
|
||||||
*arg = eval_next_line(evalarg_used);
|
*arg = eval_next_line(evalarg_used);
|
||||||
|
else
|
||||||
|
*arg = p;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Get the third variable. Recursive!
|
* Get the third variable. Recursive!
|
||||||
@ -2234,6 +2240,8 @@ eval2(char_u **arg, typval_T *rettv, evalarg_T *evalarg)
|
|||||||
{
|
{
|
||||||
if (getnext)
|
if (getnext)
|
||||||
*arg = eval_next_line(evalarg_used);
|
*arg = eval_next_line(evalarg_used);
|
||||||
|
else
|
||||||
|
*arg = p;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Get the second variable.
|
* Get the second variable.
|
||||||
@ -2349,6 +2357,8 @@ eval3(char_u **arg, typval_T *rettv, evalarg_T *evalarg)
|
|||||||
{
|
{
|
||||||
if (getnext)
|
if (getnext)
|
||||||
*arg = eval_next_line(evalarg_used);
|
*arg = eval_next_line(evalarg_used);
|
||||||
|
else
|
||||||
|
*arg = p;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Get the second variable.
|
* Get the second variable.
|
||||||
@ -2420,9 +2430,9 @@ eval4(char_u **arg, typval_T *rettv, evalarg_T *evalarg)
|
|||||||
{
|
{
|
||||||
char_u *p;
|
char_u *p;
|
||||||
int getnext;
|
int getnext;
|
||||||
int i;
|
|
||||||
exptype_T type = EXPR_UNKNOWN;
|
exptype_T type = EXPR_UNKNOWN;
|
||||||
int len = 2;
|
int len = 2;
|
||||||
|
int type_is = FALSE;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Get the first variable.
|
* Get the first variable.
|
||||||
@ -2431,44 +2441,7 @@ eval4(char_u **arg, typval_T *rettv, evalarg_T *evalarg)
|
|||||||
return FAIL;
|
return FAIL;
|
||||||
|
|
||||||
p = eval_next_non_blank(*arg, evalarg, &getnext);
|
p = eval_next_non_blank(*arg, evalarg, &getnext);
|
||||||
switch (p[0])
|
type = get_compare_type(p, &len, &type_is);
|
||||||
{
|
|
||||||
case '=': if (p[1] == '=')
|
|
||||||
type = EXPR_EQUAL;
|
|
||||||
else if (p[1] == '~')
|
|
||||||
type = EXPR_MATCH;
|
|
||||||
break;
|
|
||||||
case '!': if (p[1] == '=')
|
|
||||||
type = EXPR_NEQUAL;
|
|
||||||
else if (p[1] == '~')
|
|
||||||
type = EXPR_NOMATCH;
|
|
||||||
break;
|
|
||||||
case '>': if (p[1] != '=')
|
|
||||||
{
|
|
||||||
type = EXPR_GREATER;
|
|
||||||
len = 1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
type = EXPR_GEQUAL;
|
|
||||||
break;
|
|
||||||
case '<': if (p[1] != '=')
|
|
||||||
{
|
|
||||||
type = EXPR_SMALLER;
|
|
||||||
len = 1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
type = EXPR_SEQUAL;
|
|
||||||
break;
|
|
||||||
case 'i': if (p[1] == 's')
|
|
||||||
{
|
|
||||||
if (p[2] == 'n' && p[3] == 'o' && p[4] == 't')
|
|
||||||
len = 5;
|
|
||||||
i = p[len];
|
|
||||||
if (!isalnum(i) && i != '_')
|
|
||||||
type = len == 2 ? EXPR_IS : EXPR_ISNOT;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If there is a comparative operator, use it.
|
* If there is a comparative operator, use it.
|
||||||
@ -2482,6 +2455,13 @@ eval4(char_u **arg, typval_T *rettv, evalarg_T *evalarg)
|
|||||||
if (getnext)
|
if (getnext)
|
||||||
*arg = eval_next_line(evalarg);
|
*arg = eval_next_line(evalarg);
|
||||||
|
|
||||||
|
if (vim9script && type_is && (p[len] == '?' || p[len] == '#'))
|
||||||
|
{
|
||||||
|
semsg(_(e_invexpr2), p);
|
||||||
|
clear_tv(rettv);
|
||||||
|
return FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
// extra question mark appended: ignore case
|
// extra question mark appended: ignore case
|
||||||
if (p[len] == '?')
|
if (p[len] == '?')
|
||||||
{
|
{
|
||||||
@ -2605,6 +2585,8 @@ eval5(char_u **arg, typval_T *rettv, evalarg_T *evalarg)
|
|||||||
|
|
||||||
if (getnext)
|
if (getnext)
|
||||||
*arg = eval_next_line(evalarg);
|
*arg = eval_next_line(evalarg);
|
||||||
|
else
|
||||||
|
*arg = p;
|
||||||
evaluate = evalarg == NULL ? 0 : (evalarg->eval_flags & EVAL_EVALUATE);
|
evaluate = evalarg == NULL ? 0 : (evalarg->eval_flags & EVAL_EVALUATE);
|
||||||
if ((op != '+' || (rettv->v_type != VAR_LIST
|
if ((op != '+' || (rettv->v_type != VAR_LIST
|
||||||
&& rettv->v_type != VAR_BLOB))
|
&& rettv->v_type != VAR_BLOB))
|
||||||
@ -2786,6 +2768,7 @@ eval6(
|
|||||||
int evaluate;
|
int evaluate;
|
||||||
int getnext;
|
int getnext;
|
||||||
typval_T var2;
|
typval_T var2;
|
||||||
|
char_u *p;
|
||||||
int op;
|
int op;
|
||||||
varnumber_T n1, n2;
|
varnumber_T n1, n2;
|
||||||
#ifdef FEAT_FLOAT
|
#ifdef FEAT_FLOAT
|
||||||
@ -2793,12 +2776,15 @@ eval6(
|
|||||||
#endif
|
#endif
|
||||||
int error;
|
int error;
|
||||||
|
|
||||||
op = *eval_next_non_blank(*arg, evalarg, &getnext);
|
p = eval_next_non_blank(*arg, evalarg, &getnext);
|
||||||
|
op = *p;
|
||||||
if (op != '*' && op != '/' && op != '%')
|
if (op != '*' && op != '/' && op != '%')
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (getnext)
|
if (getnext)
|
||||||
*arg = eval_next_line(evalarg);
|
*arg = eval_next_line(evalarg);
|
||||||
|
else
|
||||||
|
*arg = p;
|
||||||
|
|
||||||
#ifdef FEAT_FLOAT
|
#ifdef FEAT_FLOAT
|
||||||
f1 = 0;
|
f1 = 0;
|
||||||
@ -3145,8 +3131,6 @@ eval7(
|
|||||||
vim_free(alias);
|
vim_free(alias);
|
||||||
}
|
}
|
||||||
|
|
||||||
*arg = skipwhite(*arg);
|
|
||||||
|
|
||||||
// Handle following '[', '(' and '.' for expr[expr], expr.name,
|
// Handle following '[', '(' and '.' for expr[expr], expr.name,
|
||||||
// expr(expr), expr->name(expr)
|
// expr(expr), expr->name(expr)
|
||||||
if (ret == OK)
|
if (ret == OK)
|
||||||
@ -5182,7 +5166,7 @@ handle_subscript(
|
|||||||
p = eval_next_non_blank(*arg, evalarg, &getnext);
|
p = eval_next_non_blank(*arg, evalarg, &getnext);
|
||||||
if (getnext
|
if (getnext
|
||||||
&& ((rettv->v_type == VAR_DICT && *p == '.' && eval_isdictc(p[1]))
|
&& ((rettv->v_type == VAR_DICT && *p == '.' && eval_isdictc(p[1]))
|
||||||
|| (*p == '-' && p[1] == '>'
|
|| (p[0] == '-' && p[1] == '>'
|
||||||
&& (p[2] == '{' || ASCII_ISALPHA(p[2])))))
|
&& (p[2] == '{' || ASCII_ISALPHA(p[2])))))
|
||||||
{
|
{
|
||||||
*arg = eval_next_line(evalarg);
|
*arg = eval_next_line(evalarg);
|
||||||
@ -5208,8 +5192,9 @@ handle_subscript(
|
|||||||
dict_unref(selfdict);
|
dict_unref(selfdict);
|
||||||
selfdict = NULL;
|
selfdict = NULL;
|
||||||
}
|
}
|
||||||
else if (**arg == '-' && (*arg)[1] == '>')
|
else if (p[0] == '-' && p[1] == '>')
|
||||||
{
|
{
|
||||||
|
*arg = p;
|
||||||
if (ret == OK)
|
if (ret == OK)
|
||||||
{
|
{
|
||||||
if ((*arg)[2] == '{')
|
if ((*arg)[2] == '{')
|
||||||
|
@ -801,13 +801,13 @@ ex_let(exarg_T *eap)
|
|||||||
else
|
else
|
||||||
++expr;
|
++expr;
|
||||||
|
|
||||||
if (vim9script && (!VIM_ISWHITE(*argend) || !VIM_ISWHITE(*expr)))
|
if (vim9script && (!VIM_ISWHITE(*argend)
|
||||||
|
|| !IS_WHITE_OR_NUL(*expr)))
|
||||||
{
|
{
|
||||||
vim_strncpy(op, expr - len, len);
|
vim_strncpy(op, expr - len, len);
|
||||||
semsg(_(e_white_both), op);
|
semsg(_(e_white_both), op);
|
||||||
i = FAIL;
|
i = FAIL;
|
||||||
}
|
}
|
||||||
expr = skipwhite(expr);
|
|
||||||
|
|
||||||
if (eap->skip)
|
if (eap->skip)
|
||||||
++emsg_skip;
|
++emsg_skip;
|
||||||
@ -818,6 +818,7 @@ ex_let(exarg_T *eap)
|
|||||||
evalarg.eval_getline = eap->getline;
|
evalarg.eval_getline = eap->getline;
|
||||||
evalarg.eval_cookie = eap->cookie;
|
evalarg.eval_cookie = eap->cookie;
|
||||||
}
|
}
|
||||||
|
expr = skipwhite_and_linebreak(expr, &evalarg);
|
||||||
i = eval0(expr, &rettv, eap, &evalarg);
|
i = eval0(expr, &rettv, eap, &evalarg);
|
||||||
if (eap->skip)
|
if (eap->skip)
|
||||||
--emsg_skip;
|
--emsg_skip;
|
||||||
|
@ -3277,7 +3277,7 @@ find_ex_command(
|
|||||||
char_u *pskip = (*eap->cmd == '&' || *eap->cmd == '$'
|
char_u *pskip = (*eap->cmd == '&' || *eap->cmd == '$'
|
||||||
|| *eap->cmd == '@') ? eap->cmd + 1 : eap->cmd;
|
|| *eap->cmd == '@') ? eap->cmd + 1 : eap->cmd;
|
||||||
|
|
||||||
if (vim_strchr((char_u *)"{('[", *p) != NULL
|
if (vim_strchr((char_u *)"{('[\"", *p) != NULL
|
||||||
|| ((p = to_name_const_end(pskip)) > eap->cmd && *p != NUL))
|
|| ((p = to_name_const_end(pskip)) > eap->cmd && *p != NUL))
|
||||||
{
|
{
|
||||||
int oplen;
|
int oplen;
|
||||||
@ -3293,6 +3293,8 @@ find_ex_command(
|
|||||||
*eap->cmd == '{'
|
*eap->cmd == '{'
|
||||||
// "'string'->func()" is an expression.
|
// "'string'->func()" is an expression.
|
||||||
|| *eap->cmd == '\''
|
|| *eap->cmd == '\''
|
||||||
|
// '"string"->func()' is an expression.
|
||||||
|
|| *eap->cmd == '"'
|
||||||
// "g:varname" is an expression.
|
// "g:varname" is an expression.
|
||||||
|| eap->cmd[1] == ':'
|
|| eap->cmd[1] == ':'
|
||||||
)
|
)
|
||||||
|
@ -1194,12 +1194,15 @@ eval_list(char_u **arg, typval_T *rettv, evalarg_T *evalarg, int do_error)
|
|||||||
else
|
else
|
||||||
clear_tv(&tv);
|
clear_tv(&tv);
|
||||||
}
|
}
|
||||||
|
// Legacy Vim script allowed a space before the comma.
|
||||||
|
if (!vim9script)
|
||||||
|
*arg = skipwhite(*arg);
|
||||||
|
|
||||||
// the comma must come after the value
|
// the comma must come after the value
|
||||||
had_comma = **arg == ',';
|
had_comma = **arg == ',';
|
||||||
if (had_comma)
|
if (had_comma)
|
||||||
{
|
{
|
||||||
if (vim9script && (*arg)[1] != NUL && !VIM_ISWHITE((*arg)[1]))
|
if (vim9script && !IS_WHITE_OR_NUL((*arg)[1]))
|
||||||
{
|
{
|
||||||
semsg(_(e_white_after), ",");
|
semsg(_(e_white_after), ",");
|
||||||
goto failret;
|
goto failret;
|
||||||
@ -1231,7 +1234,7 @@ failret:
|
|||||||
return FAIL;
|
return FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
*arg = skipwhite(*arg + 1);
|
*arg += 1;
|
||||||
if (evaluate)
|
if (evaluate)
|
||||||
rettv_list_set(rettv, l);
|
rettv_list_set(rettv, l);
|
||||||
|
|
||||||
|
35
src/misc2.c
35
src/misc2.c
@ -2027,6 +2027,41 @@ ga_clear_strings(garray_T *gap)
|
|||||||
ga_clear(gap);
|
ga_clear(gap);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copy a growing array that contains a list of strings.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
ga_copy_strings(garray_T *from, garray_T *to)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
ga_init2(to, sizeof(char_u *), 1);
|
||||||
|
if (ga_grow(to, from->ga_len) == FAIL)
|
||||||
|
return FAIL;
|
||||||
|
|
||||||
|
for (i = 0; i < from->ga_len; ++i)
|
||||||
|
{
|
||||||
|
char_u *orig = ((char_u **)from->ga_data)[i];
|
||||||
|
char_u *copy;
|
||||||
|
|
||||||
|
if (orig == NULL)
|
||||||
|
copy = NULL;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
copy = vim_strsave(orig);
|
||||||
|
if (copy == NULL)
|
||||||
|
{
|
||||||
|
to->ga_len = i;
|
||||||
|
ga_clear_strings(to);
|
||||||
|
return FAIL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
((char_u **)to->ga_data)[i] = copy;
|
||||||
|
}
|
||||||
|
to->ga_len = from->ga_len;
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Initialize a growing array. Don't forget to set ga_itemsize and
|
* Initialize a growing array. Don't forget to set ga_itemsize and
|
||||||
* ga_growsize! Or use ga_init2().
|
* ga_growsize! Or use ga_init2().
|
||||||
|
@ -56,6 +56,7 @@ char_u *vim_strrchr(char_u *string, int c);
|
|||||||
int vim_isspace(int x);
|
int vim_isspace(int x);
|
||||||
void ga_clear(garray_T *gap);
|
void ga_clear(garray_T *gap);
|
||||||
void ga_clear_strings(garray_T *gap);
|
void ga_clear_strings(garray_T *gap);
|
||||||
|
int ga_copy_strings(garray_T *from, garray_T *to);
|
||||||
void ga_init(garray_T *gap);
|
void ga_init(garray_T *gap);
|
||||||
void ga_init2(garray_T *gap, int itemsize, int growsize);
|
void ga_init2(garray_T *gap, int itemsize, int growsize);
|
||||||
int ga_grow(garray_T *gap, int n);
|
int ga_grow(garray_T *gap, int n);
|
||||||
|
@ -5,6 +5,7 @@ int get_function_args(char_u **argp, char_u endchar, garray_T *newargs, garray_T
|
|||||||
char_u *get_lambda_name(void);
|
char_u *get_lambda_name(void);
|
||||||
char_u *register_cfunc(cfunc_T cb, cfunc_free_T cb_free, void *state);
|
char_u *register_cfunc(cfunc_T cb, cfunc_free_T cb_free, void *state);
|
||||||
int get_lambda_tv(char_u **arg, typval_T *rettv, evalarg_T *evalarg);
|
int get_lambda_tv(char_u **arg, typval_T *rettv, evalarg_T *evalarg);
|
||||||
|
void copy_func(char_u *lambda, char_u *global);
|
||||||
char_u *deref_func_name(char_u *name, int *lenp, partial_T **partialp, int no_autoload);
|
char_u *deref_func_name(char_u *name, int *lenp, partial_T **partialp, int no_autoload);
|
||||||
void emsg_funcname(char *ermsg, char_u *name);
|
void emsg_funcname(char *ermsg, char_u *name);
|
||||||
int get_func_tv(char_u *name, int len, typval_T *rettv, char_u **arg, evalarg_T *evalarg, funcexe_T *funcexe);
|
int get_func_tv(char_u *name, int len, typval_T *rettv, char_u **arg, evalarg_T *evalarg, funcexe_T *funcexe);
|
||||||
|
@ -16,6 +16,7 @@ int vim9_comment_start(char_u *p);
|
|||||||
char_u *peek_next_line_from_context(cctx_T *cctx);
|
char_u *peek_next_line_from_context(cctx_T *cctx);
|
||||||
char_u *next_line_from_context(cctx_T *cctx, int skip_comment);
|
char_u *next_line_from_context(cctx_T *cctx, int skip_comment);
|
||||||
char_u *to_name_const_end(char_u *arg);
|
char_u *to_name_const_end(char_u *arg);
|
||||||
|
exptype_T get_compare_type(char_u *p, int *len, int *type_is);
|
||||||
int assignment_len(char_u *p, int *heredoc);
|
int assignment_len(char_u *p, int *heredoc);
|
||||||
void vim9_declare_error(char_u *name);
|
void vim9_declare_error(char_u *name);
|
||||||
int check_vim9_unlet(char_u *name);
|
int check_vim9_unlet(char_u *name);
|
||||||
|
@ -1546,6 +1546,7 @@ typedef enum {
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* Structure to hold info for a user function.
|
* Structure to hold info for a user function.
|
||||||
|
* When adding a field check copy_func().
|
||||||
*/
|
*/
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
@ -1618,6 +1619,7 @@ typedef struct
|
|||||||
#define FC_NOARGS 0x200 // no a: variables in lambda
|
#define FC_NOARGS 0x200 // no a: variables in lambda
|
||||||
#define FC_VIM9 0x400 // defined in vim9 script file
|
#define FC_VIM9 0x400 // defined in vim9 script file
|
||||||
#define FC_CFUNC 0x800 // defined as Lua C func
|
#define FC_CFUNC 0x800 // defined as Lua C func
|
||||||
|
#define FC_COPY 0x1000 // copy of another function by copy_func()
|
||||||
|
|
||||||
#define MAX_FUNC_ARGS 20 // maximum number of function arguments
|
#define MAX_FUNC_ARGS 20 // maximum number of function arguments
|
||||||
#define VAR_SHORT_LEN 20 // short variable name length
|
#define VAR_SHORT_LEN 20 // short variable name length
|
||||||
|
@ -11,7 +11,7 @@ NO_INITS = -U NONE $(NO_PLUGINS)
|
|||||||
SCRIPTS_FIRST = test1.out
|
SCRIPTS_FIRST = test1.out
|
||||||
|
|
||||||
# Tests that run on all systems.
|
# Tests that run on all systems.
|
||||||
SCRIPTS_ALL = test42.out
|
SCRIPTS_ALL =
|
||||||
|
|
||||||
# Tests that run on most systems, but not on Amiga.
|
# Tests that run on most systems, but not on Amiga.
|
||||||
SCRIPTS_MORE1 =
|
SCRIPTS_MORE1 =
|
||||||
|
@ -10,10 +10,7 @@ default: nongui
|
|||||||
!include Make_all.mak
|
!include Make_all.mak
|
||||||
|
|
||||||
# Omitted:
|
# Omitted:
|
||||||
# test2 "\\tmp" doesn't work.
|
|
||||||
# test10 'errorformat' is different
|
|
||||||
# test49 fails in various ways
|
# test49 fails in various ways
|
||||||
# test97 \{ and \$ are not escaped characters.
|
|
||||||
|
|
||||||
SCRIPTS = $(SCRIPTS_ALL) $(SCRIPTS_MORE1) $(SCRIPTS_MORE4)
|
SCRIPTS = $(SCRIPTS_ALL) $(SCRIPTS_MORE1) $(SCRIPTS_MORE4)
|
||||||
|
|
||||||
|
@ -28,11 +28,6 @@ default: vimall
|
|||||||
|
|
||||||
include Make_all.mak
|
include Make_all.mak
|
||||||
|
|
||||||
# Omitted:
|
|
||||||
# test2 "\\tmp" doesn't work.
|
|
||||||
# test10 'errorformat' is different
|
|
||||||
# test97 \{ and \$ are not escaped characters
|
|
||||||
|
|
||||||
SCRIPTS = $(SCRIPTS_ALL) $(SCRIPTS_MORE1) $(SCRIPTS_MORE4) $(SCRIPTS_WIN32)
|
SCRIPTS = $(SCRIPTS_ALL) $(SCRIPTS_MORE1) $(SCRIPTS_MORE4) $(SCRIPTS_WIN32)
|
||||||
|
|
||||||
SCRIPTS_BENCH = test_bench_regexp.res
|
SCRIPTS_BENCH = test_bench_regexp.res
|
||||||
|
@ -73,8 +73,7 @@ VIMPROG = <->vim.exe
|
|||||||
|
|
||||||
.SUFFIXES : .out .in
|
.SUFFIXES : .out .in
|
||||||
|
|
||||||
SCRIPT = test1.out \
|
SCRIPT = test1.out test49.out test77a.out
|
||||||
test42.out test49.out test77a.out
|
|
||||||
|
|
||||||
# Known problems:
|
# Known problems:
|
||||||
#
|
#
|
||||||
|
@ -123,6 +123,12 @@ let s:srcdir = expand('%:p:h:h')
|
|||||||
if has('win32')
|
if has('win32')
|
||||||
" avoid prompt that is long or contains a line break
|
" avoid prompt that is long or contains a line break
|
||||||
let $PROMPT = '$P$G'
|
let $PROMPT = '$P$G'
|
||||||
|
" On MS-Windows t_md and t_me are Vim specific escape sequences.
|
||||||
|
let s:t_bold = "\x1b[1m"
|
||||||
|
let s:t_normal = "\x1b[m"
|
||||||
|
else
|
||||||
|
let s:t_bold = &t_md
|
||||||
|
let s:t_normal = &t_me
|
||||||
endif
|
endif
|
||||||
|
|
||||||
" Prepare for calling test_garbagecollect_now().
|
" Prepare for calling test_garbagecollect_now().
|
||||||
@ -239,11 +245,11 @@ func RunTheTest(test)
|
|||||||
let message ..= repeat(' ', 50 - len(message))
|
let message ..= repeat(' ', 50 - len(message))
|
||||||
let time = reltime(func_start)
|
let time = reltime(func_start)
|
||||||
if has('float') && reltimefloat(time) > 0.1
|
if has('float') && reltimefloat(time) > 0.1
|
||||||
let message = &t_md .. message
|
let message = s:t_bold .. message
|
||||||
endif
|
endif
|
||||||
let message ..= ' in ' .. reltimestr(time) .. ' seconds'
|
let message ..= ' in ' .. reltimestr(time) .. ' seconds'
|
||||||
if has('float') && reltimefloat(time) > 0.1
|
if has('float') && reltimefloat(time) > 0.1
|
||||||
let message ..= &t_me
|
let message ..= s:t_normal
|
||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
call add(s:messages, message)
|
call add(s:messages, message)
|
||||||
@ -312,9 +318,9 @@ func FinishTesting()
|
|||||||
let message = 'Executed ' . s:done . (s:done > 1 ? ' tests' : ' test')
|
let message = 'Executed ' . s:done . (s:done > 1 ? ' tests' : ' test')
|
||||||
endif
|
endif
|
||||||
if s:done > 0 && has('reltime')
|
if s:done > 0 && has('reltime')
|
||||||
let message = &t_md .. message .. repeat(' ', 40 - len(message))
|
let message = s:t_bold .. message .. repeat(' ', 40 - len(message))
|
||||||
let message ..= ' in ' .. reltimestr(reltime(s:start_time)) .. ' seconds'
|
let message ..= ' in ' .. reltimestr(reltime(s:start_time)) .. ' seconds'
|
||||||
let message ..= &t_me
|
let message ..= s:t_normal
|
||||||
endif
|
endif
|
||||||
echo message
|
echo message
|
||||||
call add(s:messages, message)
|
call add(s:messages, message)
|
||||||
|
9
src/testdir/sautest/autoload/auto9.vim
Normal file
9
src/testdir/sautest/autoload/auto9.vim
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
vim9script
|
||||||
|
|
||||||
|
func auto9#getsome()
|
||||||
|
return 'some'
|
||||||
|
endfunc
|
||||||
|
|
||||||
|
def auto9#add42(count: number): number
|
||||||
|
return count + 42
|
||||||
|
enddef
|
Binary file not shown.
Binary file not shown.
@ -17,3 +17,8 @@ func Test_source_autoload()
|
|||||||
source sautest/autoload/sourced.vim
|
source sautest/autoload/sourced.vim
|
||||||
call assert_equal(1, g:loaded_sourced_vim)
|
call assert_equal(1, g:loaded_sourced_vim)
|
||||||
endfunc
|
endfunc
|
||||||
|
|
||||||
|
func Test_autoload_vim9script()
|
||||||
|
call assert_equal('some', auto9#getsome())
|
||||||
|
call assert_equal(49, auto9#add42(7))
|
||||||
|
endfunc
|
||||||
|
@ -1355,7 +1355,7 @@ func Test_input_func()
|
|||||||
func! Tcomplete(arglead, cmdline, pos)
|
func! Tcomplete(arglead, cmdline, pos)
|
||||||
return "item1\nitem2\nitem3"
|
return "item1\nitem2\nitem3"
|
||||||
endfunc
|
endfunc
|
||||||
call feedkeys(":let c = input('Q? ', '' , 'custom,Tcomplete')\<CR>"
|
call feedkeys(":let c = input('Q? ', '', 'custom,Tcomplete')\<CR>"
|
||||||
\ .. "\<C-A>\<CR>", 'xt')
|
\ .. "\<C-A>\<CR>", 'xt')
|
||||||
delfunc Tcomplete
|
delfunc Tcomplete
|
||||||
call assert_equal('item1 item2 item3', c)
|
call assert_equal('item1 item2 item3', c)
|
||||||
|
@ -120,7 +120,7 @@ func Test_gn_command()
|
|||||||
sil! %d_
|
sil! %d_
|
||||||
|
|
||||||
" search using the \zs atom
|
" search using the \zs atom
|
||||||
call setline(1, [' nnoremap', '' , 'nnoremap'])
|
call setline(1, [' nnoremap', '', 'nnoremap'])
|
||||||
set wrapscan&vim
|
set wrapscan&vim
|
||||||
let @/ = '\_s\zsnnoremap'
|
let @/ = '\_s\zsnnoremap'
|
||||||
$
|
$
|
||||||
|
@ -23,6 +23,9 @@ func Test_list_create()
|
|||||||
call assert_equal(10, x)
|
call assert_equal(10, x)
|
||||||
endfunc
|
endfunc
|
||||||
|
|
||||||
|
" This was allowed in legacy Vim script
|
||||||
|
let s:list_with_spaces = [1 , 2 , 3]
|
||||||
|
|
||||||
" List slices
|
" List slices
|
||||||
func Test_list_slice()
|
func Test_list_slice()
|
||||||
let l = [1, 'as''d', [1, 2, function("strlen")], {'a': 1},]
|
let l = [1, 'as''d', [1, 2, function("strlen")], {'a': 1},]
|
||||||
@ -202,6 +205,10 @@ func Test_dict()
|
|||||||
call assert_fails("let d={'k' : i}", 'E121:')
|
call assert_fails("let d={'k' : i}", 'E121:')
|
||||||
endfunc
|
endfunc
|
||||||
|
|
||||||
|
" This was allowed in legacy Vim script
|
||||||
|
let s:dict_with_spaces = {'one' : 1 , 'two' : 2 , 'three' : 3}
|
||||||
|
let s:dict_with_spaces_lit = #{one : 1 , two : 2 , three : 3}
|
||||||
|
|
||||||
" Dictionary identity
|
" Dictionary identity
|
||||||
func Test_dict_identity()
|
func Test_dict_identity()
|
||||||
let d = {001: 'asd', 'b': [1, 2, function('strlen')], -1: {'a': 1},}
|
let d = {001: 'asd', 'b': [1, 2, function('strlen')], -1: {'a': 1},}
|
||||||
|
@ -588,7 +588,7 @@ func Test_popup_drag_termwin()
|
|||||||
call setline(1, range(100))
|
call setline(1, range(100))
|
||||||
for nr in range(7)
|
for nr in range(7)
|
||||||
call setline(nr * 12 + 1, "fold {{{")
|
call setline(nr * 12 + 1, "fold {{{")
|
||||||
call setline(nr * 12 + 11 , "end }}}")
|
call setline(nr * 12 + 11, "end }}}")
|
||||||
endfor
|
endfor
|
||||||
%foldclose
|
%foldclose
|
||||||
set shell=/bin/sh noruler
|
set shell=/bin/sh noruler
|
||||||
|
@ -350,7 +350,7 @@ function Test_tabpage_with_tabprevious()
|
|||||||
call Check_tab_count(6, cmd . ' 3', 3)
|
call Check_tab_count(6, cmd . ' 3', 3)
|
||||||
call Check_tab_count(6, cmd . ' 8', 4)
|
call Check_tab_count(6, cmd . ' 8', 4)
|
||||||
for n in range(2)
|
for n in range(2)
|
||||||
for c in ['0', '.+3', '+', '+2' , '-', '-2' , '$', '+99', '-99']
|
for c in ['0', '.+3', '+', '+2', '-', '-2', '$', '+99', '-99']
|
||||||
if n == 0 " pre count
|
if n == 0 " pre count
|
||||||
let entire_cmd = c . cmd
|
let entire_cmd = c . cmd
|
||||||
let err_code = 'E16:'
|
let err_code = 'E16:'
|
||||||
|
@ -201,28 +201,28 @@ func Test_match()
|
|||||||
call assert_equal("c", matchstr("abcd", ".", 2, 0))
|
call assert_equal("c", matchstr("abcd", ".", 2, 0))
|
||||||
call assert_equal("a", matchstr("abcd", ".", 0, -1))
|
call assert_equal("a", matchstr("abcd", ".", 0, -1))
|
||||||
call assert_equal(-1, match("abcd", ".", 0, 5))
|
call assert_equal(-1, match("abcd", ".", 0, 5))
|
||||||
call assert_equal(0 , match("abcd", ".", 0, -1))
|
call assert_equal(0, match("abcd", ".", 0, -1))
|
||||||
call assert_equal(0 , match('abc', '.', 0, 1))
|
call assert_equal(0, match('abc', '.', 0, 1))
|
||||||
call assert_equal(1 , match('abc', '.', 0, 2))
|
call assert_equal(1, match('abc', '.', 0, 2))
|
||||||
call assert_equal(2 , match('abc', '.', 0, 3))
|
call assert_equal(2, match('abc', '.', 0, 3))
|
||||||
call assert_equal(-1, match('abc', '.', 0, 4))
|
call assert_equal(-1, match('abc', '.', 0, 4))
|
||||||
call assert_equal(1 , match('abc', '.', 1, 1))
|
call assert_equal(1, match('abc', '.', 1, 1))
|
||||||
call assert_equal(2 , match('abc', '.', 2, 1))
|
call assert_equal(2, match('abc', '.', 2, 1))
|
||||||
call assert_equal(-1, match('abc', '.', 3, 1))
|
call assert_equal(-1, match('abc', '.', 3, 1))
|
||||||
call assert_equal(3 , match('abc', '$', 0, 1))
|
call assert_equal(3, match('abc', '$', 0, 1))
|
||||||
call assert_equal(-1, match('abc', '$', 0, 2))
|
call assert_equal(-1, match('abc', '$', 0, 2))
|
||||||
call assert_equal(3 , match('abc', '$', 1, 1))
|
call assert_equal(3, match('abc', '$', 1, 1))
|
||||||
call assert_equal(3 , match('abc', '$', 2, 1))
|
call assert_equal(3, match('abc', '$', 2, 1))
|
||||||
call assert_equal(3 , match('abc', '$', 3, 1))
|
call assert_equal(3, match('abc', '$', 3, 1))
|
||||||
call assert_equal(-1, match('abc', '$', 4, 1))
|
call assert_equal(-1, match('abc', '$', 4, 1))
|
||||||
call assert_equal(0 , match('abc', '\zs', 0, 1))
|
call assert_equal(0, match('abc', '\zs', 0, 1))
|
||||||
call assert_equal(1 , match('abc', '\zs', 0, 2))
|
call assert_equal(1, match('abc', '\zs', 0, 2))
|
||||||
call assert_equal(2 , match('abc', '\zs', 0, 3))
|
call assert_equal(2, match('abc', '\zs', 0, 3))
|
||||||
call assert_equal(3 , match('abc', '\zs', 0, 4))
|
call assert_equal(3, match('abc', '\zs', 0, 4))
|
||||||
call assert_equal(-1, match('abc', '\zs', 0, 5))
|
call assert_equal(-1, match('abc', '\zs', 0, 5))
|
||||||
call assert_equal(1 , match('abc', '\zs', 1, 1))
|
call assert_equal(1, match('abc', '\zs', 1, 1))
|
||||||
call assert_equal(2 , match('abc', '\zs', 2, 1))
|
call assert_equal(2, match('abc', '\zs', 2, 1))
|
||||||
call assert_equal(3 , match('abc', '\zs', 3, 1))
|
call assert_equal(3, match('abc', '\zs', 3, 1))
|
||||||
call assert_equal(-1, match('abc', '\zs', 4, 1))
|
call assert_equal(-1, match('abc', '\zs', 4, 1))
|
||||||
endfunc
|
endfunc
|
||||||
|
|
||||||
|
@ -1219,7 +1219,7 @@ func Test_prop_func_invalid_args()
|
|||||||
call assert_fails('call prop_find({}, "x")', 'E474:')
|
call assert_fails('call prop_find({}, "x")', 'E474:')
|
||||||
call assert_fails('call prop_find({"lnum" : -2})', 'E16:')
|
call assert_fails('call prop_find({"lnum" : -2})', 'E16:')
|
||||||
call assert_fails('call prop_list(1, [])', 'E715:')
|
call assert_fails('call prop_list(1, [])', 'E715:')
|
||||||
call assert_fails('call prop_list(-1 , {})', 'E16:')
|
call assert_fails('call prop_list(-1, {})', 'E16:')
|
||||||
call assert_fails('call prop_remove([])', 'E474:')
|
call assert_fails('call prop_remove([])', 'E474:')
|
||||||
call assert_fails('call prop_remove({}, -2)', 'E16:')
|
call assert_fails('call prop_remove({}, -2)', 'E16:')
|
||||||
call assert_fails('call prop_remove({})', 'E968:')
|
call assert_fails('call prop_remove({})', 'E968:')
|
||||||
|
@ -699,6 +699,24 @@ def Test_disassemble_lambda()
|
|||||||
instr)
|
instr)
|
||||||
enddef
|
enddef
|
||||||
|
|
||||||
|
def NestedOuter()
|
||||||
|
def g:Inner()
|
||||||
|
echomsg "inner"
|
||||||
|
enddef
|
||||||
|
enddef
|
||||||
|
|
||||||
|
def Test_nested_func()
|
||||||
|
let instr = execute('disassemble NestedOuter')
|
||||||
|
assert_match('NestedOuter\_s*' ..
|
||||||
|
'def g:Inner()\_s*' ..
|
||||||
|
'echomsg "inner"\_s*' ..
|
||||||
|
'enddef\_s*' ..
|
||||||
|
'\d NEWFUNC <lambda>\d\+ Inner\_s*' ..
|
||||||
|
'\d PUSHNR 0\_s*' ..
|
||||||
|
'\d RETURN',
|
||||||
|
instr)
|
||||||
|
enddef
|
||||||
|
|
||||||
def AndOr(arg: any): string
|
def AndOr(arg: any): string
|
||||||
if arg == 1 && arg != 2 || arg == 4
|
if arg == 1 && arg != 2 || arg == 4
|
||||||
return 'yes'
|
return 'yes'
|
||||||
|
@ -831,7 +831,7 @@ def Test_expr5()
|
|||||||
enddef
|
enddef
|
||||||
|
|
||||||
def Test_expr5_vim9script()
|
def Test_expr5_vim9script()
|
||||||
# only checks line continuation
|
# check line continuation
|
||||||
let lines =<< trim END
|
let lines =<< trim END
|
||||||
vim9script
|
vim9script
|
||||||
let var = 11
|
let var = 11
|
||||||
@ -848,6 +848,30 @@ def Test_expr5_vim9script()
|
|||||||
assert_equal('onetwo', var)
|
assert_equal('onetwo', var)
|
||||||
END
|
END
|
||||||
CheckScriptSuccess(lines)
|
CheckScriptSuccess(lines)
|
||||||
|
|
||||||
|
lines =<< trim END
|
||||||
|
vim9script
|
||||||
|
echo 'abc' is# 'abc'
|
||||||
|
END
|
||||||
|
CheckScriptFailure(lines, 'E15:')
|
||||||
|
|
||||||
|
lines =<< trim END
|
||||||
|
vim9script
|
||||||
|
echo 'abc' is? 'abc'
|
||||||
|
END
|
||||||
|
CheckScriptFailure(lines, 'E15:')
|
||||||
|
|
||||||
|
lines =<< trim END
|
||||||
|
vim9script
|
||||||
|
echo 'abc' isnot# 'abc'
|
||||||
|
END
|
||||||
|
CheckScriptFailure(lines, 'E15:')
|
||||||
|
|
||||||
|
lines =<< trim END
|
||||||
|
vim9script
|
||||||
|
echo 'abc' isnot? 'abc'
|
||||||
|
END
|
||||||
|
CheckScriptFailure(lines, 'E15:')
|
||||||
enddef
|
enddef
|
||||||
|
|
||||||
def Test_expr5_float()
|
def Test_expr5_float()
|
||||||
@ -1638,8 +1662,9 @@ enddef
|
|||||||
def Test_expr7_method_call()
|
def Test_expr7_method_call()
|
||||||
new
|
new
|
||||||
setline(1, ['first', 'last'])
|
setline(1, ['first', 'last'])
|
||||||
eval 'second'->append(1)
|
'second'->append(1)
|
||||||
assert_equal(['first', 'second', 'last'], getline(1, '$'))
|
"third"->append(2)
|
||||||
|
assert_equal(['first', 'second', 'third', 'last'], getline(1, '$'))
|
||||||
bwipe!
|
bwipe!
|
||||||
|
|
||||||
let bufnr = bufnr()
|
let bufnr = bufnr()
|
||||||
|
@ -133,6 +133,28 @@ def Test_nested_function()
|
|||||||
CheckDefFailure(['func Nested()', 'endfunc'], 'E1086:')
|
CheckDefFailure(['func Nested()', 'endfunc'], 'E1086:')
|
||||||
enddef
|
enddef
|
||||||
|
|
||||||
|
def Test_nested_global_function()
|
||||||
|
let lines =<< trim END
|
||||||
|
vim9script
|
||||||
|
def Outer()
|
||||||
|
def g:Inner(): string
|
||||||
|
return 'inner'
|
||||||
|
enddef
|
||||||
|
enddef
|
||||||
|
disass Outer
|
||||||
|
Outer()
|
||||||
|
assert_equal('inner', g:Inner())
|
||||||
|
delfunc g:Inner
|
||||||
|
Outer()
|
||||||
|
assert_equal('inner', g:Inner())
|
||||||
|
delfunc g:Inner
|
||||||
|
Outer()
|
||||||
|
assert_equal('inner', g:Inner())
|
||||||
|
delfunc g:Inner
|
||||||
|
END
|
||||||
|
CheckScriptSuccess(lines)
|
||||||
|
enddef
|
||||||
|
|
||||||
func Test_call_default_args_from_func()
|
func Test_call_default_args_from_func()
|
||||||
call assert_equal('string', MyDefaultArgs())
|
call assert_equal('string', MyDefaultArgs())
|
||||||
call assert_equal('one', MyDefaultArgs('one'))
|
call assert_equal('one', MyDefaultArgs('one'))
|
||||||
@ -502,8 +524,11 @@ def Test_vim9script_call()
|
|||||||
assert_equal('some', var)
|
assert_equal('some', var)
|
||||||
|
|
||||||
# line starting with single quote is not a mark
|
# line starting with single quote is not a mark
|
||||||
|
# line starting with double quote can be a method call
|
||||||
'asdfasdf'->MyFunc()
|
'asdfasdf'->MyFunc()
|
||||||
assert_equal('asdfasdf', var)
|
assert_equal('asdfasdf', var)
|
||||||
|
"xyz"->MyFunc()
|
||||||
|
assert_equal('xyz', var)
|
||||||
|
|
||||||
def UseString()
|
def UseString()
|
||||||
'xyork'->MyFunc()
|
'xyork'->MyFunc()
|
||||||
@ -511,6 +536,12 @@ def Test_vim9script_call()
|
|||||||
UseString()
|
UseString()
|
||||||
assert_equal('xyork', var)
|
assert_equal('xyork', var)
|
||||||
|
|
||||||
|
def UseString2()
|
||||||
|
"knife"->MyFunc()
|
||||||
|
enddef
|
||||||
|
UseString2()
|
||||||
|
assert_equal('knife', var)
|
||||||
|
|
||||||
# prepending a colon makes it a mark
|
# prepending a colon makes it a mark
|
||||||
new
|
new
|
||||||
setline(1, ['aaa', 'bbb', 'ccc'])
|
setline(1, ['aaa', 'bbb', 'ccc'])
|
||||||
|
@ -109,6 +109,9 @@ def Test_assignment()
|
|||||||
call CheckDefFailure(['&ts = 3', 'let asdf'], 'E1022:')
|
call CheckDefFailure(['&ts = 3', 'let asdf'], 'E1022:')
|
||||||
&ts = 8
|
&ts = 8
|
||||||
|
|
||||||
|
call CheckDefFailure(['let s:var = 123'], 'E1101:')
|
||||||
|
call CheckDefFailure(['let s:var: number'], 'E1101:')
|
||||||
|
|
||||||
g:inc_counter += 1
|
g:inc_counter += 1
|
||||||
assert_equal(2, g:inc_counter)
|
assert_equal(2, g:inc_counter)
|
||||||
|
|
||||||
@ -136,6 +139,28 @@ def Test_assignment()
|
|||||||
assert_equal('noneagain', v:errmsg)
|
assert_equal('noneagain', v:errmsg)
|
||||||
call CheckDefFailure(['v:errmsg += "more"'], 'E1013:')
|
call CheckDefFailure(['v:errmsg += "more"'], 'E1013:')
|
||||||
call CheckDefFailure(['v:errmsg += 123'], 'E1013:')
|
call CheckDefFailure(['v:errmsg += 123'], 'E1013:')
|
||||||
|
|
||||||
|
# single letter variables
|
||||||
|
a = 123
|
||||||
|
assert_equal(123, a)
|
||||||
|
let b: number
|
||||||
|
b = 123
|
||||||
|
assert_equal(123, b)
|
||||||
|
let g: number
|
||||||
|
g = 123
|
||||||
|
assert_equal(123, g)
|
||||||
|
let s: number
|
||||||
|
s = 123
|
||||||
|
assert_equal(123, s)
|
||||||
|
let t: number
|
||||||
|
t = 123
|
||||||
|
assert_equal(123, t)
|
||||||
|
let v: number
|
||||||
|
v = 123
|
||||||
|
assert_equal(123, v)
|
||||||
|
let w: number
|
||||||
|
w = 123
|
||||||
|
assert_equal(123, w)
|
||||||
enddef
|
enddef
|
||||||
|
|
||||||
def Test_vim9_single_char_vars()
|
def Test_vim9_single_char_vars()
|
||||||
@ -333,6 +358,25 @@ def Test_assignment_var_list()
|
|||||||
assert_equal(['three'], vrem)
|
assert_equal(['three'], vrem)
|
||||||
enddef
|
enddef
|
||||||
|
|
||||||
|
def Test_assignment_vim9script()
|
||||||
|
let lines =<< trim END
|
||||||
|
vim9script
|
||||||
|
def Func(): list<number>
|
||||||
|
return [1, 2]
|
||||||
|
enddef
|
||||||
|
let var1: number
|
||||||
|
let var2: number
|
||||||
|
[var1, var2] =
|
||||||
|
Func()
|
||||||
|
assert_equal(1, var1)
|
||||||
|
assert_equal(2, var2)
|
||||||
|
let ll =
|
||||||
|
Func()
|
||||||
|
assert_equal([1, 2], ll)
|
||||||
|
END
|
||||||
|
CheckScriptSuccess(lines)
|
||||||
|
enddef
|
||||||
|
|
||||||
def Mess(): string
|
def Mess(): string
|
||||||
v:foldstart = 123
|
v:foldstart = 123
|
||||||
return 'xxx'
|
return 'xxx'
|
||||||
|
@ -556,4 +556,132 @@ func Test_write_file_encoding()
|
|||||||
%bw!
|
%bw!
|
||||||
endfunc
|
endfunc
|
||||||
|
|
||||||
|
" Test for writing and reading a file starting with a BOM.
|
||||||
|
" Byte Order Mark (BOM) character for various encodings is below:
|
||||||
|
" UTF-8 : EF BB BF
|
||||||
|
" UTF-16 (BE): FE FF
|
||||||
|
" UTF-16 (LE): FF FE
|
||||||
|
" UTF-32 (BE): 00 00 FE FF
|
||||||
|
" UTF-32 (LE): FF FE 00 00
|
||||||
|
func Test_readwrite_file_with_bom()
|
||||||
|
let utf8_bom = "\xEF\xBB\xBF"
|
||||||
|
let utf16be_bom = "\xFE\xFF"
|
||||||
|
let utf16le_bom = "\xFF\xFE"
|
||||||
|
let utf32be_bom = "\n\n\xFE\xFF"
|
||||||
|
let utf32le_bom = "\xFF\xFE\n\n"
|
||||||
|
let save_fileencoding = &fileencoding
|
||||||
|
set cpoptions+=S
|
||||||
|
|
||||||
|
" Check that editing a latin1 file doesn't see a BOM
|
||||||
|
call writefile(["\xFE\xFElatin-1"], 'Xtest1')
|
||||||
|
edit Xtest1
|
||||||
|
call assert_equal('latin1', &fileencoding)
|
||||||
|
call assert_equal(0, &bomb)
|
||||||
|
set fenc=latin1
|
||||||
|
write Xfile2
|
||||||
|
call assert_equal(["\xFE\xFElatin-1", ''], readfile('Xfile2', 'b'))
|
||||||
|
set bomb fenc=latin1
|
||||||
|
write Xtest3
|
||||||
|
call assert_equal(["\xFE\xFElatin-1", ''], readfile('Xtest3', 'b'))
|
||||||
|
set bomb&
|
||||||
|
|
||||||
|
" Check utf-8 BOM
|
||||||
|
%bw!
|
||||||
|
call writefile([utf8_bom .. "utf-8"], 'Xtest1')
|
||||||
|
edit! Xtest1
|
||||||
|
call assert_equal('utf-8', &fileencoding)
|
||||||
|
call assert_equal(1, &bomb)
|
||||||
|
call assert_equal('utf-8', getline(1))
|
||||||
|
set fenc=latin1
|
||||||
|
write! Xfile2
|
||||||
|
call assert_equal(['utf-8', ''], readfile('Xfile2', 'b'))
|
||||||
|
set fenc=utf-8
|
||||||
|
w! Xtest3
|
||||||
|
call assert_equal([utf8_bom .. "utf-8", ''], readfile('Xtest3', 'b'))
|
||||||
|
|
||||||
|
" Check utf-8 with an error (will fall back to latin-1)
|
||||||
|
%bw!
|
||||||
|
call writefile([utf8_bom .. "utf-8\x80err"], 'Xtest1')
|
||||||
|
edit! Xtest1
|
||||||
|
call assert_equal('latin1', &fileencoding)
|
||||||
|
call assert_equal(0, &bomb)
|
||||||
|
call assert_equal("\xC3\xAF\xC2\xBB\xC2\xBFutf-8\xC2\x80err", getline(1))
|
||||||
|
set fenc=latin1
|
||||||
|
write! Xfile2
|
||||||
|
call assert_equal([utf8_bom .. "utf-8\x80err", ''], readfile('Xfile2', 'b'))
|
||||||
|
set fenc=utf-8
|
||||||
|
w! Xtest3
|
||||||
|
call assert_equal(["\xC3\xAF\xC2\xBB\xC2\xBFutf-8\xC2\x80err", ''],
|
||||||
|
\ readfile('Xtest3', 'b'))
|
||||||
|
|
||||||
|
" Check ucs-2 BOM
|
||||||
|
%bw!
|
||||||
|
call writefile([utf16be_bom .. "\nu\nc\ns\n-\n2\n"], 'Xtest1')
|
||||||
|
edit! Xtest1
|
||||||
|
call assert_equal('utf-16', &fileencoding)
|
||||||
|
call assert_equal(1, &bomb)
|
||||||
|
call assert_equal('ucs-2', getline(1))
|
||||||
|
set fenc=latin1
|
||||||
|
write! Xfile2
|
||||||
|
call assert_equal(["ucs-2", ''], readfile('Xfile2', 'b'))
|
||||||
|
set fenc=ucs-2
|
||||||
|
w! Xtest3
|
||||||
|
call assert_equal([utf16be_bom .. "\nu\nc\ns\n-\n2\n", ''],
|
||||||
|
\ readfile('Xtest3', 'b'))
|
||||||
|
|
||||||
|
" Check ucs-2le BOM
|
||||||
|
%bw!
|
||||||
|
call writefile([utf16le_bom .. "u\nc\ns\n-\n2\nl\ne\n"], 'Xtest1')
|
||||||
|
" Need to add a NUL byte after the NL byte
|
||||||
|
call writefile(0z00, 'Xtest1', 'a')
|
||||||
|
edit! Xtest1
|
||||||
|
call assert_equal('utf-16le', &fileencoding)
|
||||||
|
call assert_equal(1, &bomb)
|
||||||
|
call assert_equal('ucs-2le', getline(1))
|
||||||
|
set fenc=latin1
|
||||||
|
write! Xfile2
|
||||||
|
call assert_equal(["ucs-2le", ''], readfile('Xfile2', 'b'))
|
||||||
|
set fenc=ucs-2le
|
||||||
|
w! Xtest3
|
||||||
|
call assert_equal([utf16le_bom .. "u\nc\ns\n-\n2\nl\ne\n", "\n"],
|
||||||
|
\ readfile('Xtest3', 'b'))
|
||||||
|
|
||||||
|
" Check ucs-4 BOM
|
||||||
|
%bw!
|
||||||
|
call writefile([utf32be_bom .. "\n\n\nu\n\n\nc\n\n\ns\n\n\n-\n\n\n4\n\n\n"], 'Xtest1')
|
||||||
|
edit! Xtest1
|
||||||
|
call assert_equal('ucs-4', &fileencoding)
|
||||||
|
call assert_equal(1, &bomb)
|
||||||
|
call assert_equal('ucs-4', getline(1))
|
||||||
|
set fenc=latin1
|
||||||
|
write! Xfile2
|
||||||
|
call assert_equal(["ucs-4", ''], readfile('Xfile2', 'b'))
|
||||||
|
set fenc=ucs-4
|
||||||
|
w! Xtest3
|
||||||
|
call assert_equal([utf32be_bom .. "\n\n\nu\n\n\nc\n\n\ns\n\n\n-\n\n\n4\n\n\n", ''], readfile('Xtest3', 'b'))
|
||||||
|
|
||||||
|
" Check ucs-4le BOM
|
||||||
|
%bw!
|
||||||
|
call writefile([utf32le_bom .. "u\n\n\nc\n\n\ns\n\n\n-\n\n\n4\n\n\nl\n\n\ne\n\n\n"], 'Xtest1')
|
||||||
|
" Need to add three NUL bytes after the NL byte
|
||||||
|
call writefile(0z000000, 'Xtest1', 'a')
|
||||||
|
edit! Xtest1
|
||||||
|
call assert_equal('ucs-4le', &fileencoding)
|
||||||
|
call assert_equal(1, &bomb)
|
||||||
|
call assert_equal('ucs-4le', getline(1))
|
||||||
|
set fenc=latin1
|
||||||
|
write! Xfile2
|
||||||
|
call assert_equal(["ucs-4le", ''], readfile('Xfile2', 'b'))
|
||||||
|
set fenc=ucs-4le
|
||||||
|
w! Xtest3
|
||||||
|
call assert_equal([utf32le_bom .. "u\n\n\nc\n\n\ns\n\n\n-\n\n\n4\n\n\nl\n\n\ne\n\n\n", "\n\n\n"], readfile('Xtest3', 'b'))
|
||||||
|
|
||||||
|
set cpoptions-=S
|
||||||
|
let &fileencoding = save_fileencoding
|
||||||
|
call delete('Xtest1')
|
||||||
|
call delete('Xtest2')
|
||||||
|
call delete('Xtest3')
|
||||||
|
%bw!
|
||||||
|
endfunc
|
||||||
|
|
||||||
" vim: shiftwidth=2 sts=2 expandtab
|
" vim: shiftwidth=2 sts=2 expandtab
|
||||||
|
@ -366,7 +366,7 @@ register_cfunc(cfunc_T cb, cfunc_free_T cb_free, void *state)
|
|||||||
if (fp == NULL)
|
if (fp == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
fp->uf_dfunc_idx = UF_NOT_COMPILED;
|
fp->uf_def_status = UF_NOT_COMPILED;
|
||||||
fp->uf_refcount = 1;
|
fp->uf_refcount = 1;
|
||||||
fp->uf_varargs = TRUE;
|
fp->uf_varargs = TRUE;
|
||||||
fp->uf_flags = FC_CFUNC;
|
fp->uf_flags = FC_CFUNC;
|
||||||
@ -642,6 +642,10 @@ get_func_tv(
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
++argcount;
|
++argcount;
|
||||||
|
// The comma should come right after the argument, but this wasn't
|
||||||
|
// checked previously, thus only enforce it in Vim9 script.
|
||||||
|
if (!in_vim9script())
|
||||||
|
argp = skipwhite(argp);
|
||||||
if (*argp != ',')
|
if (*argp != ',')
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -1065,7 +1069,8 @@ func_remove(ufunc_T *fp)
|
|||||||
{
|
{
|
||||||
// When there is a def-function index do not actually remove the
|
// When there is a def-function index do not actually remove the
|
||||||
// function, so we can find the index when defining the function again.
|
// function, so we can find the index when defining the function again.
|
||||||
if (fp->uf_def_status == UF_COMPILED)
|
// Do remove it when it's a copy.
|
||||||
|
if (fp->uf_def_status == UF_COMPILED && (fp->uf_flags & FC_COPY) == 0)
|
||||||
fp->uf_flags |= FC_DEAD;
|
fp->uf_flags |= FC_DEAD;
|
||||||
else
|
else
|
||||||
hash_remove(&func_hashtab, hi);
|
hash_remove(&func_hashtab, hi);
|
||||||
@ -1118,7 +1123,8 @@ func_clear(ufunc_T *fp, int force)
|
|||||||
// clear this function
|
// clear this function
|
||||||
func_clear_items(fp);
|
func_clear_items(fp);
|
||||||
funccal_unref(fp->uf_scoped, fp, force);
|
funccal_unref(fp->uf_scoped, fp, force);
|
||||||
clear_def_function(fp);
|
if ((fp->uf_flags & FC_COPY) == 0)
|
||||||
|
clear_def_function(fp);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -1146,12 +1152,83 @@ func_free(ufunc_T *fp, int force)
|
|||||||
func_clear_free(ufunc_T *fp, int force)
|
func_clear_free(ufunc_T *fp, int force)
|
||||||
{
|
{
|
||||||
func_clear(fp, force);
|
func_clear(fp, force);
|
||||||
if (force || fp->uf_dfunc_idx == 0)
|
if (force || fp->uf_dfunc_idx == 0 || (fp->uf_flags & FC_COPY))
|
||||||
func_free(fp, force);
|
func_free(fp, force);
|
||||||
else
|
else
|
||||||
fp->uf_flags |= FC_DEAD;
|
fp->uf_flags |= FC_DEAD;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copy already defined function "lambda" to a new function with name "global".
|
||||||
|
* This is for when a compiled function defines a global function.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
copy_func(char_u *lambda, char_u *global)
|
||||||
|
{
|
||||||
|
ufunc_T *ufunc = find_func_even_dead(lambda, TRUE, NULL);
|
||||||
|
ufunc_T *fp;
|
||||||
|
|
||||||
|
if (ufunc == NULL)
|
||||||
|
semsg(_("E1102: lambda function not found: %s"), lambda);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// TODO: handle ! to overwrite
|
||||||
|
fp = find_func(global, TRUE, NULL);
|
||||||
|
if (fp != NULL)
|
||||||
|
{
|
||||||
|
semsg(_(e_funcexts), global);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
fp = alloc_clear(offsetof(ufunc_T, uf_name) + STRLEN(global) + 1);
|
||||||
|
if (fp == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
fp->uf_varargs = ufunc->uf_varargs;
|
||||||
|
fp->uf_flags = (ufunc->uf_flags & ~FC_VIM9) | FC_COPY;
|
||||||
|
fp->uf_def_status = ufunc->uf_def_status;
|
||||||
|
fp->uf_dfunc_idx = ufunc->uf_dfunc_idx;
|
||||||
|
if (ga_copy_strings(&fp->uf_args, &ufunc->uf_args) == FAIL
|
||||||
|
|| ga_copy_strings(&fp->uf_def_args, &ufunc->uf_def_args)
|
||||||
|
== FAIL
|
||||||
|
|| ga_copy_strings(&fp->uf_lines, &ufunc->uf_lines) == FAIL)
|
||||||
|
goto failed;
|
||||||
|
|
||||||
|
fp->uf_name_exp = ufunc->uf_name_exp == NULL ? NULL
|
||||||
|
: vim_strsave(ufunc->uf_name_exp);
|
||||||
|
if (ufunc->uf_arg_types != NULL)
|
||||||
|
{
|
||||||
|
fp->uf_arg_types = ALLOC_MULT(type_T *, fp->uf_args.ga_len);
|
||||||
|
if (fp->uf_arg_types == NULL)
|
||||||
|
goto failed;
|
||||||
|
mch_memmove(fp->uf_arg_types, ufunc->uf_arg_types,
|
||||||
|
sizeof(type_T *) * fp->uf_args.ga_len);
|
||||||
|
}
|
||||||
|
if (ufunc->uf_def_arg_idx != NULL)
|
||||||
|
{
|
||||||
|
fp->uf_def_arg_idx = ALLOC_MULT(int, fp->uf_def_args.ga_len + 1);
|
||||||
|
if (fp->uf_def_arg_idx == NULL)
|
||||||
|
goto failed;
|
||||||
|
mch_memmove(fp->uf_def_arg_idx, ufunc->uf_def_arg_idx,
|
||||||
|
sizeof(int) * fp->uf_def_args.ga_len + 1);
|
||||||
|
}
|
||||||
|
if (ufunc->uf_va_name != NULL)
|
||||||
|
{
|
||||||
|
fp->uf_va_name = vim_strsave(ufunc->uf_va_name);
|
||||||
|
if (fp->uf_va_name == NULL)
|
||||||
|
goto failed;
|
||||||
|
}
|
||||||
|
|
||||||
|
fp->uf_refcount = 1;
|
||||||
|
STRCPY(fp->uf_name, global);
|
||||||
|
hash_add(&func_hashtab, UF2HIKEY(fp));
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
|
||||||
|
failed:
|
||||||
|
func_clear_free(fp, TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Call a user function.
|
* Call a user function.
|
||||||
@ -2517,6 +2594,8 @@ list_functions(regmatch_T *regmatch)
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* ":function" also supporting nested ":def".
|
* ":function" also supporting nested ":def".
|
||||||
|
* When "name_arg" is not NULL this is a nested function, using "name_arg" for
|
||||||
|
* the function name.
|
||||||
* Returns a pointer to the function or NULL if no function defined.
|
* Returns a pointer to the function or NULL if no function defined.
|
||||||
*/
|
*/
|
||||||
ufunc_T *
|
ufunc_T *
|
||||||
|
@ -754,6 +754,38 @@ static char *(features[]) =
|
|||||||
|
|
||||||
static int included_patches[] =
|
static int included_patches[] =
|
||||||
{ /* Add new patch number below this line */
|
{ /* Add new patch number below this line */
|
||||||
|
/**/
|
||||||
|
1330,
|
||||||
|
/**/
|
||||||
|
1329,
|
||||||
|
/**/
|
||||||
|
1328,
|
||||||
|
/**/
|
||||||
|
1327,
|
||||||
|
/**/
|
||||||
|
1326,
|
||||||
|
/**/
|
||||||
|
1325,
|
||||||
|
/**/
|
||||||
|
1324,
|
||||||
|
/**/
|
||||||
|
1323,
|
||||||
|
/**/
|
||||||
|
1322,
|
||||||
|
/**/
|
||||||
|
1321,
|
||||||
|
/**/
|
||||||
|
1320,
|
||||||
|
/**/
|
||||||
|
1319,
|
||||||
|
/**/
|
||||||
|
1318,
|
||||||
|
/**/
|
||||||
|
1317,
|
||||||
|
/**/
|
||||||
|
1316,
|
||||||
|
/**/
|
||||||
|
1315,
|
||||||
/**/
|
/**/
|
||||||
1314,
|
1314,
|
||||||
/**/
|
/**/
|
||||||
|
@ -79,6 +79,7 @@ typedef enum {
|
|||||||
ISN_PCALL_END, // cleanup after ISN_PCALL with cpf_top set
|
ISN_PCALL_END, // cleanup after ISN_PCALL with cpf_top set
|
||||||
ISN_RETURN, // return, result is on top of stack
|
ISN_RETURN, // return, result is on top of stack
|
||||||
ISN_FUNCREF, // push a function ref to dfunc isn_arg.funcref
|
ISN_FUNCREF, // push a function ref to dfunc isn_arg.funcref
|
||||||
|
ISN_NEWFUNC, // create a global function from a lambda function
|
||||||
|
|
||||||
// expression operations
|
// expression operations
|
||||||
ISN_JUMP, // jump if condition is matched isn_arg.jump
|
ISN_JUMP, // jump if condition is matched isn_arg.jump
|
||||||
@ -237,6 +238,12 @@ typedef struct {
|
|||||||
int fr_var_idx; // variable to store partial
|
int fr_var_idx; // variable to store partial
|
||||||
} funcref_T;
|
} funcref_T;
|
||||||
|
|
||||||
|
// arguments to ISN_NEWFUNC
|
||||||
|
typedef struct {
|
||||||
|
char_u *nf_lambda; // name of the lambda already defined
|
||||||
|
char_u *nf_global; // name of the global function to be created
|
||||||
|
} newfunc_T;
|
||||||
|
|
||||||
// arguments to ISN_CHECKLEN
|
// arguments to ISN_CHECKLEN
|
||||||
typedef struct {
|
typedef struct {
|
||||||
int cl_min_len; // minimum length
|
int cl_min_len; // minimum length
|
||||||
@ -281,6 +288,7 @@ struct isn_S {
|
|||||||
script_T script;
|
script_T script;
|
||||||
unlet_T unlet;
|
unlet_T unlet;
|
||||||
funcref_T funcref;
|
funcref_T funcref;
|
||||||
|
newfunc_T newfunc;
|
||||||
checklen_T checklen;
|
checklen_T checklen;
|
||||||
shuffle_T shuffle;
|
shuffle_T shuffle;
|
||||||
} isn_arg;
|
} isn_arg;
|
||||||
|
@ -1522,6 +1522,27 @@ generate_FUNCREF(cctx_T *cctx, int dfunc_idx)
|
|||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Generate an ISN_NEWFUNC instruction.
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
generate_NEWFUNC(cctx_T *cctx, char_u *lambda_name, char_u *func_name)
|
||||||
|
{
|
||||||
|
isn_T *isn;
|
||||||
|
char_u *name;
|
||||||
|
|
||||||
|
RETURN_OK_IF_SKIP(cctx);
|
||||||
|
name = vim_strsave(lambda_name);
|
||||||
|
if (name == NULL)
|
||||||
|
return FAIL;
|
||||||
|
if ((isn = generate_instr(cctx, ISN_NEWFUNC)) == NULL)
|
||||||
|
return FAIL;
|
||||||
|
isn->isn_arg.newfunc.nf_lambda = name;
|
||||||
|
isn->isn_arg.newfunc.nf_global = func_name;
|
||||||
|
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Generate an ISN_JUMP instruction.
|
* Generate an ISN_JUMP instruction.
|
||||||
*/
|
*/
|
||||||
@ -3633,7 +3654,7 @@ get_vim_constant(char_u **arg, typval_T *rettv)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static exptype_T
|
exptype_T
|
||||||
get_compare_type(char_u *p, int *len, int *type_is)
|
get_compare_type(char_u *p, int *len, int *type_is)
|
||||||
{
|
{
|
||||||
exptype_T type = EXPR_UNKNOWN;
|
exptype_T type = EXPR_UNKNOWN;
|
||||||
@ -4875,11 +4896,13 @@ exarg_getline(
|
|||||||
static char_u *
|
static char_u *
|
||||||
compile_nested_function(exarg_T *eap, cctx_T *cctx)
|
compile_nested_function(exarg_T *eap, cctx_T *cctx)
|
||||||
{
|
{
|
||||||
|
int is_global = *eap->arg == 'g' && eap->arg[1] == ':';
|
||||||
char_u *name_start = eap->arg;
|
char_u *name_start = eap->arg;
|
||||||
char_u *name_end = to_name_end(eap->arg, FALSE);
|
char_u *name_end = to_name_end(eap->arg, is_global);
|
||||||
char_u *name = get_lambda_name();
|
char_u *name = get_lambda_name();
|
||||||
lvar_T *lvar;
|
lvar_T *lvar;
|
||||||
ufunc_T *ufunc;
|
ufunc_T *ufunc;
|
||||||
|
int r;
|
||||||
|
|
||||||
eap->arg = name_end;
|
eap->arg = name_end;
|
||||||
eap->getline = exarg_getline;
|
eap->getline = exarg_getline;
|
||||||
@ -4894,16 +4917,28 @@ compile_nested_function(exarg_T *eap, cctx_T *cctx)
|
|||||||
&& compile_def_function(ufunc, TRUE, cctx) == FAIL)
|
&& compile_def_function(ufunc, TRUE, cctx) == FAIL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
// Define a local variable for the function reference.
|
if (is_global)
|
||||||
lvar = reserve_local(cctx, name_start, name_end - name_start,
|
{
|
||||||
TRUE, ufunc->uf_func_type);
|
char_u *func_name = vim_strnsave(name_start + 2,
|
||||||
|
name_end - name_start - 2);
|
||||||
|
|
||||||
if (generate_FUNCREF(cctx, ufunc->uf_dfunc_idx) == FAIL
|
if (func_name == NULL)
|
||||||
|| generate_STORE(cctx, ISN_STORE, lvar->lv_idx, NULL) == FAIL)
|
r = FAIL;
|
||||||
return NULL;
|
else
|
||||||
|
r = generate_NEWFUNC(cctx, name, func_name);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Define a local variable for the function reference.
|
||||||
|
lvar = reserve_local(cctx, name_start, name_end - name_start,
|
||||||
|
TRUE, ufunc->uf_func_type);
|
||||||
|
if (generate_FUNCREF(cctx, ufunc->uf_dfunc_idx) == FAIL)
|
||||||
|
return NULL;
|
||||||
|
r = generate_STORE(cctx, ISN_STORE, lvar->lv_idx, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: warning for trailing text?
|
// TODO: warning for trailing text?
|
||||||
return (char_u *)"";
|
return r == FAIL ? NULL : (char_u *)"";
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -5237,7 +5272,7 @@ compile_assignment(char_u *arg, exarg_T *eap, cmdidx_T cmdidx, cctx_T *cctx)
|
|||||||
goto theend;
|
goto theend;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (STRNCMP(var_start, "g:", 2) == 0)
|
else if (varlen > 1 && STRNCMP(var_start, "g:", 2) == 0)
|
||||||
{
|
{
|
||||||
dest = dest_global;
|
dest = dest_global;
|
||||||
if (is_decl)
|
if (is_decl)
|
||||||
@ -5246,7 +5281,7 @@ compile_assignment(char_u *arg, exarg_T *eap, cmdidx_T cmdidx, cctx_T *cctx)
|
|||||||
goto theend;
|
goto theend;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (STRNCMP(var_start, "b:", 2) == 0)
|
else if (varlen > 1 && STRNCMP(var_start, "b:", 2) == 0)
|
||||||
{
|
{
|
||||||
dest = dest_buffer;
|
dest = dest_buffer;
|
||||||
if (is_decl)
|
if (is_decl)
|
||||||
@ -5255,7 +5290,7 @@ compile_assignment(char_u *arg, exarg_T *eap, cmdidx_T cmdidx, cctx_T *cctx)
|
|||||||
goto theend;
|
goto theend;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (STRNCMP(var_start, "w:", 2) == 0)
|
else if (varlen > 1 && STRNCMP(var_start, "w:", 2) == 0)
|
||||||
{
|
{
|
||||||
dest = dest_window;
|
dest = dest_window;
|
||||||
if (is_decl)
|
if (is_decl)
|
||||||
@ -5264,7 +5299,7 @@ compile_assignment(char_u *arg, exarg_T *eap, cmdidx_T cmdidx, cctx_T *cctx)
|
|||||||
goto theend;
|
goto theend;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (STRNCMP(var_start, "t:", 2) == 0)
|
else if (varlen > 1 && STRNCMP(var_start, "t:", 2) == 0)
|
||||||
{
|
{
|
||||||
dest = dest_tab;
|
dest = dest_tab;
|
||||||
if (is_decl)
|
if (is_decl)
|
||||||
@ -5273,7 +5308,7 @@ compile_assignment(char_u *arg, exarg_T *eap, cmdidx_T cmdidx, cctx_T *cctx)
|
|||||||
goto theend;
|
goto theend;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (STRNCMP(var_start, "v:", 2) == 0)
|
else if (varlen > 1 && STRNCMP(var_start, "v:", 2) == 0)
|
||||||
{
|
{
|
||||||
typval_T *vtv;
|
typval_T *vtv;
|
||||||
int di_flags;
|
int di_flags;
|
||||||
@ -5337,14 +5372,18 @@ compile_assignment(char_u *arg, exarg_T *eap, cmdidx_T cmdidx, cctx_T *cctx)
|
|||||||
goto theend;
|
goto theend;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (STRNCMP(var_start, "s:", 2) == 0
|
else if ((varlen > 1 && STRNCMP(var_start, "s:", 2) == 0)
|
||||||
|| lookup_script(var_start, varlen) == OK
|
|| lookup_script(var_start, varlen) == OK
|
||||||
|| find_imported(var_start, varlen, cctx) != NULL)
|
|| find_imported(var_start, varlen, cctx) != NULL)
|
||||||
{
|
{
|
||||||
dest = dest_script;
|
dest = dest_script;
|
||||||
if (is_decl)
|
if (is_decl)
|
||||||
{
|
{
|
||||||
semsg(_("E1054: Variable already declared in the script: %s"),
|
if ((varlen > 1 && STRNCMP(var_start, "s:", 2) == 0))
|
||||||
|
semsg(_("E1101: Cannot declare a script variable in a function: %s"),
|
||||||
|
name);
|
||||||
|
else
|
||||||
|
semsg(_("E1054: Variable already declared in the script: %s"),
|
||||||
name);
|
name);
|
||||||
goto theend;
|
goto theend;
|
||||||
}
|
}
|
||||||
@ -7637,6 +7676,11 @@ delete_instr(isn_T *isn)
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case ISN_NEWFUNC:
|
||||||
|
vim_free(isn->isn_arg.newfunc.nf_lambda);
|
||||||
|
vim_free(isn->isn_arg.newfunc.nf_global);
|
||||||
|
break;
|
||||||
|
|
||||||
case ISN_2BOOL:
|
case ISN_2BOOL:
|
||||||
case ISN_2STRING:
|
case ISN_2STRING:
|
||||||
case ISN_ADDBLOB:
|
case ISN_ADDBLOB:
|
||||||
|
@ -723,7 +723,10 @@ call_def_function(
|
|||||||
dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data)
|
dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data)
|
||||||
+ ufunc->uf_dfunc_idx;
|
+ ufunc->uf_dfunc_idx;
|
||||||
if (dfunc->df_instr == NULL)
|
if (dfunc->df_instr == NULL)
|
||||||
|
{
|
||||||
|
iemsg("using call_def_function() on not compiled function");
|
||||||
return FAIL;
|
return FAIL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
CLEAR_FIELD(ectx);
|
CLEAR_FIELD(ectx);
|
||||||
@ -1726,6 +1729,15 @@ call_def_function(
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
// Create a global function from a lambda.
|
||||||
|
case ISN_NEWFUNC:
|
||||||
|
{
|
||||||
|
newfunc_T *newfunc = &iptr->isn_arg.newfunc;
|
||||||
|
|
||||||
|
copy_func(newfunc->nf_lambda, newfunc->nf_global);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
// jump if a condition is met
|
// jump if a condition is met
|
||||||
case ISN_JUMP:
|
case ISN_JUMP:
|
||||||
{
|
{
|
||||||
@ -2912,6 +2924,15 @@ ex_disassemble(exarg_T *eap)
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case ISN_NEWFUNC:
|
||||||
|
{
|
||||||
|
newfunc_T *newfunc = &iptr->isn_arg.newfunc;
|
||||||
|
|
||||||
|
smsg("%4d NEWFUNC %s %s", current,
|
||||||
|
newfunc->nf_lambda, newfunc->nf_global);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
case ISN_JUMP:
|
case ISN_JUMP:
|
||||||
{
|
{
|
||||||
char *when = "?";
|
char *when = "?";
|
||||||
|
Reference in New Issue
Block a user