aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.ci/build.bat (renamed from .ci/msys_build_deps.bat)21
-rw-r--r--.ci/msys_build.bat22
-rw-r--r--CMakeLists.txt16
-rw-r--r--appveyor.yml22
-rw-r--r--cmake/RunTests.cmake1
-rw-r--r--runtime/CMakeLists.txt4
-rw-r--r--runtime/autoload/health.vim49
-rw-r--r--runtime/autoload/health/nvim.vim377
-rw-r--r--runtime/autoload/health/provider.vim382
-rw-r--r--runtime/autoload/man.vim157
-rw-r--r--runtime/doc/api.txt33
-rw-r--r--runtime/doc/develop.txt50
-rw-r--r--runtime/doc/eval.txt29
-rw-r--r--runtime/doc/filetype.txt9
-rw-r--r--runtime/doc/map.txt21
-rw-r--r--runtime/doc/msgpack_rpc.txt225
-rw-r--r--runtime/doc/quickfix.txt18
-rw-r--r--runtime/ftplugin/c.vim2
-rw-r--r--runtime/ftplugin/man.vim8
-rw-r--r--runtime/plugin/man.vim4
-rw-r--r--runtime/syntax/man.vim6
-rw-r--r--scripts/gendispatch.lua (renamed from scripts/msgpack-gen.lua)230
-rw-r--r--scripts/geneval.lua66
-rw-r--r--scripts/genvimvim.lua27
-rwxr-xr-xscripts/release.sh16
-rwxr-xr-xscripts/vim-patch.sh137
-rw-r--r--src/nvim/CMakeLists.txt48
-rw-r--r--src/nvim/api/buffer.c180
-rw-r--r--src/nvim/api/dispatch_deprecated.lua69
-rw-r--r--src/nvim/api/private/defs.h7
-rw-r--r--src/nvim/api/private/dispatch.h23
-rw-r--r--src/nvim/api/private/handle.c16
-rw-r--r--src/nvim/api/private/handle.h3
-rw-r--r--src/nvim/api/private/helpers.c73
-rw-r--r--src/nvim/api/tabpage.c59
-rw-r--r--src/nvim/api/ui.c105
-rw-r--r--src/nvim/api/vim.c136
-rw-r--r--src/nvim/api/window.c73
-rw-r--r--src/nvim/buffer.c22
-rw-r--r--src/nvim/buffer_defs.h48
-rw-r--r--src/nvim/charset.c8
-rw-r--r--src/nvim/cursor.c1
-rw-r--r--src/nvim/cursor.h1
-rw-r--r--src/nvim/cursor_shape.c1
-rw-r--r--src/nvim/diff.c1
-rw-r--r--src/nvim/digraph.c1
-rw-r--r--src/nvim/edit.c9
-rw-r--r--src/nvim/eval.c1275
-rw-r--r--src/nvim/eval.lua331
-rw-r--r--src/nvim/event/process.c3
-rw-r--r--src/nvim/ex_cmds.c23
-rw-r--r--src/nvim/ex_cmds2.c4
-rw-r--r--src/nvim/ex_cmds_defs.h83
-rw-r--r--src/nvim/ex_docmd.c175
-rw-r--r--src/nvim/ex_eval.c1
-rw-r--r--src/nvim/ex_getln.c1
-rw-r--r--src/nvim/farsi.c1
-rw-r--r--src/nvim/file_search.c113
-rw-r--r--src/nvim/fileio.c127
-rw-r--r--src/nvim/fileio.h2
-rw-r--r--src/nvim/fold.c9
-rw-r--r--src/nvim/func_attr.h1
-rw-r--r--src/nvim/garray.c1
-rw-r--r--src/nvim/getchar.c2
-rw-r--r--src/nvim/hardcopy.c1
-rw-r--r--src/nvim/hashtab.c1
-rw-r--r--src/nvim/iconv.h2
-rw-r--r--src/nvim/if_cscope.c1
-rw-r--r--src/nvim/indent.c1
-rw-r--r--src/nvim/indent_c.c1
-rw-r--r--src/nvim/main.c3
-rw-r--r--src/nvim/map.c7
-rw-r--r--src/nvim/map.h3
-rw-r--r--src/nvim/mark.c1
-rw-r--r--src/nvim/mbyte.c1
-rw-r--r--src/nvim/memfile.c1
-rw-r--r--src/nvim/memline.c95
-rw-r--r--src/nvim/memory.c10
-rw-r--r--src/nvim/memory.h1
-rw-r--r--src/nvim/menu.c2
-rw-r--r--src/nvim/message.c1
-rw-r--r--src/nvim/misc1.c68
-rw-r--r--src/nvim/misc2.c486
-rw-r--r--src/nvim/misc2.h12
-rw-r--r--src/nvim/mouse.c1
-rw-r--r--src/nvim/move.c1
-rw-r--r--src/nvim/msgpack_rpc/channel.c3
-rw-r--r--src/nvim/msgpack_rpc/defs.h28
-rw-r--r--src/nvim/msgpack_rpc/helpers.c6
-rw-r--r--src/nvim/normal.c30
-rw-r--r--src/nvim/ops.c29
-rw-r--r--src/nvim/option.c151
-rw-r--r--src/nvim/option.h2
-rw-r--r--src/nvim/os/env.c1
-rw-r--r--src/nvim/os/fs.c1
-rw-r--r--src/nvim/os/input.c2
-rw-r--r--src/nvim/os/shell.c43
-rw-r--r--src/nvim/os/signal.c14
-rw-r--r--src/nvim/os/users.c1
-rw-r--r--src/nvim/os_unix.c1
-rw-r--r--src/nvim/path.c1
-rw-r--r--src/nvim/popupmnu.c110
-rw-r--r--src/nvim/quickfix.c25
-rw-r--r--src/nvim/regexp.c1
-rw-r--r--src/nvim/regexp_nfa.c7
-rw-r--r--src/nvim/screen.c35
-rw-r--r--src/nvim/search.c1
-rw-r--r--src/nvim/shada.c3
-rw-r--r--src/nvim/spell.c1
-rw-r--r--src/nvim/state.c34
-rw-r--r--src/nvim/strings.c1
-rw-r--r--src/nvim/syntax.c35
-rw-r--r--src/nvim/tag.c1
-rw-r--r--src/nvim/terminal.c13
-rw-r--r--src/nvim/testdir/Makefile1
-rw-r--r--src/nvim/testdir/test_alot.vim2
-rw-r--r--src/nvim/testdir/test_feedkeys.vim10
-rw-r--r--src/nvim/testdir/test_help_tagjump.vim10
-rw-r--r--src/nvim/testdir/test_syn_attr.vim24
-rw-r--r--src/nvim/testdir/test_usercommands.vim48
-rw-r--r--src/nvim/testdir/test_window_id.vim8
-rw-r--r--src/nvim/tui/input.c5
-rw-r--r--src/nvim/tui/tui.c8
-rw-r--r--src/nvim/types.h1
-rw-r--r--src/nvim/ui.c17
-rw-r--r--src/nvim/ui.h5
-rw-r--r--src/nvim/ui_bridge.c1
-rw-r--r--src/nvim/undo.c1
-rw-r--r--src/nvim/version.c19
-rw-r--r--src/nvim/window.c44
-rw-r--r--test/functional/api/buffer_spec.lua152
-rw-r--r--test/functional/api/server_requests_spec.lua13
-rw-r--r--test/functional/api/tabpage_spec.lua35
-rw-r--r--test/functional/api/vim_spec.lua82
-rw-r--r--test/functional/api/window_spec.lua77
-rw-r--r--test/functional/autocmd/tabnew_spec.lua2
-rw-r--r--test/functional/autocmd/tabnewentered_spec.lua2
-rw-r--r--test/functional/autocmd/termclose_spec.lua4
-rw-r--r--test/functional/clipboard/clipboard_provider_spec.lua2
-rw-r--r--test/functional/core/job_spec.lua7
-rw-r--r--test/functional/eval/api_functions_spec.lua148
-rw-r--r--test/functional/eval/server_spec.lua2
-rw-r--r--test/functional/ex_cmds/cd_spec.lua41
-rw-r--r--test/functional/ex_cmds/profile_spec.lua4
-rw-r--r--test/functional/ex_cmds/recover_spec.lua2
-rw-r--r--test/functional/ex_cmds/write_spec.lua2
-rw-r--r--test/functional/helpers.lua107
-rw-r--r--test/functional/legacy/011_autocommands_spec.lua2
-rw-r--r--test/functional/legacy/025_jump_tag_hidden_spec.lua2
-rw-r--r--test/functional/legacy/030_fileformats_spec.lua2
-rw-r--r--test/functional/legacy/036_regexp_character_classes_spec.lua12
-rw-r--r--test/functional/legacy/051_highlight_spec.lua2
-rw-r--r--test/functional/legacy/059_utf8_spell_checking_spec.lua2
-rw-r--r--test/functional/legacy/093_mksession_cursor_cols_latin1_spec.lua2
-rw-r--r--test/functional/legacy/097_glob_path_spec.lua2
-rw-r--r--test/functional/legacy/107_adjust_window_and_contents_spec.lua2
-rw-r--r--test/functional/legacy/arglist_spec.lua2
-rw-r--r--test/functional/legacy/delete_spec.lua2
-rw-r--r--test/functional/legacy/file_perm_spec.lua2
-rw-r--r--test/functional/legacy/fixeol_spec.lua2
-rw-r--r--test/functional/legacy/fnamemodify_spec.lua2
-rw-r--r--test/functional/legacy/getcwd_spec.lua2
-rw-r--r--test/functional/legacy/packadd_spec.lua2
-rw-r--r--test/functional/legacy/wordcount_spec.lua2
-rw-r--r--test/functional/normal/K_spec.lua2
-rw-r--r--test/functional/options/autochdir_spec.lua2
-rw-r--r--test/functional/options/defaults_spec.lua2
-rw-r--r--test/functional/options/shortmess_spec.lua2
-rw-r--r--test/functional/plugin/health_spec.lua20
-rw-r--r--test/functional/plugin/shada_spec.lua14
-rw-r--r--test/functional/shada/buffers_spec.lua6
-rw-r--r--test/functional/shada/helpers.lua10
-rw-r--r--test/functional/shada/marks_spec.lua2
-rw-r--r--test/functional/shada/shada_spec.lua21
-rw-r--r--test/functional/shell/bang_filter_spec.lua2
-rw-r--r--test/functional/shell/viml_system_spec.lua1
-rw-r--r--test/functional/terminal/altscreen_spec.lua2
-rw-r--r--test/functional/terminal/buffer_spec.lua1
-rw-r--r--test/functional/terminal/cursor_spec.lua3
-rw-r--r--test/functional/terminal/edit_spec.lua2
-rw-r--r--test/functional/terminal/ex_terminal_spec.lua4
-rw-r--r--test/functional/terminal/helpers.lua2
-rw-r--r--test/functional/terminal/highlight_spec.lua69
-rw-r--r--test/functional/terminal/mouse_spec.lua2
-rw-r--r--test/functional/terminal/scrollback_spec.lua4
-rw-r--r--test/functional/terminal/tui_spec.lua2
-rw-r--r--test/functional/terminal/window_spec.lua2
-rw-r--r--test/functional/terminal/window_split_tab_spec.lua2
-rw-r--r--test/functional/ui/bufhl_spec.lua7
-rw-r--r--test/functional/ui/highlight_spec.lua3
-rw-r--r--test/functional/ui/input_spec.lua2
-rw-r--r--test/functional/ui/mouse_spec.lua228
-rw-r--r--test/functional/ui/output_spec.lua7
-rw-r--r--test/functional/ui/screen.lua32
-rw-r--r--test/functional/ui/screen_basic_spec.lua2
-rw-r--r--test/functional/ui/searchhl_spec.lua2
-rw-r--r--test/functional/ui/sign_spec.lua2
-rw-r--r--test/functional/ui/syntax_conceal_spec.lua2
-rw-r--r--test/functional/ui/wildmode_spec.lua2
-rw-r--r--test/functional/viml/completion_spec.lua104
-rw-r--r--test/functional/viml/function_spec.lua9
-rw-r--r--test/unit/buffer_spec.lua26
-rw-r--r--test/unit/option_spec.lua51
-rw-r--r--test/unit/os/shell_spec.lua61
-rw-r--r--third-party/CMakeLists.txt21
-rw-r--r--third-party/cmake/BuildGperf.cmake51
-rw-r--r--third-party/cmake/BuildLuarocks.cmake19
207 files changed, 4948 insertions, 3040 deletions
diff --git a/.ci/msys_build_deps.bat b/.ci/build.bat
index 67e7c69883..c2f560fb7c 100644
--- a/.ci/msys_build_deps.bat
+++ b/.ci/build.bat
@@ -2,7 +2,7 @@
:: MSYS2, this allows using all the dependencies and tools available
:: in MSYS2, but we cannot build inside the MSYS2 shell.
echo on
-if "%TARGET%" == "MINGW_32" (
+if "%CONFIGURATION%" == "MINGW_32" (
set ARCH=i686
set BITS=32
) else (
@@ -12,9 +12,12 @@ if "%TARGET%" == "MINGW_32" (
:: We cannot have sh.exe in the PATH (MinGW)
set PATH=%PATH:C:\Program Files\Git\usr\bin;=%
set PATH=C:\msys64\mingw%BITS%\bin;C:\Windows\System32;C:\Windows;%PATH%
+:: The default cpack in the PATH is not CMake
+set PATH=C:\Program Files (x86)\CMake\bin\cpack.exe;%PATH%
+:: Build third-party dependencies
C:\msys64\usr\bin\bash -lc "pacman --verbose --noconfirm -Su" || goto :error
-C:\msys64\usr\bin\bash -lc "pacman --verbose --noconfirm --needed -S mingw-w64-%ARCH%-cmake mingw-w64-%ARCH%-perl mingw-w64-%ARCH%-python2 mingw-w64-%ARCH%-diffutils" || goto :error
+C:\msys64\usr\bin\bash -lc "pacman --verbose --noconfirm --needed -S mingw-w64-%ARCH%-cmake mingw-w64-%ARCH%-perl mingw-w64-%ARCH%-python2 mingw-w64-%ARCH%-diffutils gperf" || goto :error
mkdir .deps
cd .deps
@@ -22,6 +25,20 @@ cmake -G "MinGW Makefiles" -DCMAKE_BUILD_TYPE=Release ..\third-party\ || goto :e
mingw32-make VERBOSE=1 || goto :error
cd ..
+:: Build Neovim
+mkdir build
+cd build
+cmake -G "MinGW Makefiles" -DCMAKE_BUILD_TYPE=Release -DBUSTED_OUTPUT_TYPE=gtest -DGPERF_PRG="C:\msys64\usr\bin\gperf.exe" .. || goto :error
+mingw32-make VERBOSE=1 || goto :error
+bin\nvim --version || goto :error
+
+:: Functional tests
+mingw32-make functionaltest VERBOSE=1 || goto :error
+
+:: Build artifacts
+cpack -G ZIP -C Release
+if defined APPVEYOR_REPO_TAG_NAME cpack -G NSIS -C Release
+
goto :EOF
:error
exit /b %errorlevel%
diff --git a/.ci/msys_build.bat b/.ci/msys_build.bat
deleted file mode 100644
index 490c8b6830..0000000000
--- a/.ci/msys_build.bat
+++ /dev/null
@@ -1,22 +0,0 @@
-echo on
-if "%TARGET%" == "MINGW_32" (
- set ARCH=i686
- set BITS=32
-) else (
- set ARCH=x86_64
- set BITS=64
-)
-:: We cannot have sh.exe in the PATH (MinGW)
-set PATH=%PATH:C:\Program Files\Git\usr\bin;=%
-set PATH=C:\msys64\mingw%BITS%\bin;C:\Windows\System32;C:\Windows;%PATH%
-
-mkdir build
-cd build
-cmake -G "MinGW Makefiles" -DCMAKE_BUILD_TYPE=Release .. || goto :error
-mingw32-make VERBOSE=1 || goto :error
-bin\nvim --version || goto :error
-cd ..
-
-goto :EOF
-:error
-exit /b %errorlevel%
diff --git a/CMakeLists.txt b/CMakeLists.txt
index cb044d521c..0a6a9accea 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -328,7 +328,12 @@ if((CLANG_ASAN_UBSAN OR CLANG_MSAN OR CLANG_TSAN) AND NOT CMAKE_C_COMPILER_ID MA
message(FATAL_ERROR "Sanitizers are only supported for Clang.")
endif()
-option(ENABLE_JEMALLOC "enable jemalloc" ON)
+if(CMAKE_SYSTEM_NAME STREQUAL "OpenBSD")
+ message(STATUS "detected OpenBSD; disabled jemalloc. #5318")
+ option(ENABLE_JEMALLOC "enable jemalloc" OFF)
+else()
+ option(ENABLE_JEMALLOC "enable jemalloc" ON)
+endif()
if (ENABLE_JEMALLOC)
if(CLANG_ASAN_UBSAN OR CLANG_MSAN OR CLANG_TSAN)
@@ -395,7 +400,7 @@ endif()
message(STATUS "Using the Lua interpreter ${LUA_PRG}.")
# Setup busted.
-find_program(BUSTED_PRG busted)
+find_program(BUSTED_PRG NAMES busted busted.bat)
find_program(BUSTED_LUA_PRG busted-lua)
if(NOT BUSTED_OUTPUT_TYPE)
if(WIN32)
@@ -407,6 +412,8 @@ endif()
find_program(LUACHECK_PRG luacheck)
+find_program(GPERF_PRG gperf)
+
include(InstallHelpers)
file(GLOB MANPAGES
@@ -498,6 +505,7 @@ if(BUSTED_PRG)
-DTEST_DIR=${CMAKE_CURRENT_SOURCE_DIR}/test
-DBUILD_DIR=${CMAKE_BINARY_DIR}
-DTEST_TYPE=unit
+ -DSYSTEM_NAME=${CMAKE_SYSTEM_NAME}
-P ${PROJECT_SOURCE_DIR}/cmake/RunTests.cmake
DEPENDS ${UNITTEST_PREREQS}
${TEST_TARGET_ARGS})
@@ -516,6 +524,7 @@ if(BUSTED_PRG)
-DTEST_DIR=${CMAKE_CURRENT_SOURCE_DIR}/test
-DBUILD_DIR=${CMAKE_BINARY_DIR}
-DTEST_TYPE=functional
+ -DSYSTEM_NAME=${CMAKE_SYSTEM_NAME}
-P ${PROJECT_SOURCE_DIR}/cmake/RunTests.cmake
DEPENDS ${FUNCTIONALTEST_PREREQS}
${TEST_TARGET_ARGS})
@@ -530,6 +539,7 @@ if(BUSTED_PRG)
-DTEST_DIR=${CMAKE_CURRENT_SOURCE_DIR}/test
-DBUILD_DIR=${CMAKE_BINARY_DIR}
-DTEST_TYPE=benchmark
+ -DCMAKE_SYSTEM_NAME=${CMAKE_SYSTEM_NAME}
-P ${PROJECT_SOURCE_DIR}/cmake/RunTests.cmake
DEPENDS ${BENCHMARK_PREREQS}
${TEST_TARGET_ARGS})
@@ -546,6 +556,7 @@ if(BUSTED_LUA_PRG)
-DTEST_DIR=${CMAKE_CURRENT_SOURCE_DIR}/test
-DBUILD_DIR=${CMAKE_BINARY_DIR}
-DTEST_TYPE=functional
+ -DCMAKE_SYSTEM_NAME=${CMAKE_SYSTEM_NAME}
-P ${PROJECT_SOURCE_DIR}/cmake/RunTests.cmake
DEPENDS ${FUNCTIONALTEST_PREREQS}
${TEST_TARGET_ARGS})
@@ -556,6 +567,7 @@ if(LUACHECK_PRG)
COMMAND ${CMAKE_COMMAND}
-DLUACHECK_PRG=${LUACHECK_PRG}
-DTEST_DIR=${CMAKE_CURRENT_SOURCE_DIR}/test
+ -DCMAKE_SYSTEM_NAME=${CMAKE_SYSTEM_NAME}
-P ${PROJECT_SOURCE_DIR}/cmake/RunTestsLint.cmake)
endif()
diff --git a/appveyor.yml b/appveyor.yml
index 53a0ca5eb3..600b246be2 100644
--- a/appveyor.yml
+++ b/appveyor.yml
@@ -1,22 +1,10 @@
version: '{build}'
-skip_tags: true
-environment:
- # The default cpack in the PATH is not CMake
- CPACK: C:\Program Files (x86)\CMake\bin\cpack.exe
- matrix:
- - TARGET: MINGW_64
- BUILD_DEPS_SCRIPT: .ci\msys_build_deps.bat
- BUILD_SCRIPT: .ci\msys_build.bat
- - TARGET: MINGW_32
- BUILD_DEPS_SCRIPT: .ci\msys_build_deps.bat
- BUILD_SCRIPT: .ci\msys_build.bat
+configuration:
+- MINGW_64
+- MINGW_32
install: []
build_script:
-- if defined BUILD_DEPS_SCRIPT call %BUILD_DEPS_SCRIPT%
-- call %BUILD_SCRIPT%
-# Build artifacts
-- cd build
-- '"%CPACK%" -G NSIS -C Release'
-- '"%CPACK%" -G ZIP -C Release'
+- call .ci\build.bat
artifacts:
- path: build/Neovim.zip
+- path: build/Neovim.exe
diff --git a/cmake/RunTests.cmake b/cmake/RunTests.cmake
index a045f9f982..58f19b6fa5 100644
--- a/cmake/RunTests.cmake
+++ b/cmake/RunTests.cmake
@@ -28,6 +28,7 @@ if(DEFINED ENV{TEST_FILTER})
set(TEST_TAG "--filter=$ENV{TEST_FILTER}")
endif()
+set(ENV{SYSTEM_NAME} ${SYSTEM_NAME})
execute_process(
COMMAND ${BUSTED_PRG} ${TEST_TAG} ${TEST_FILTER} -v -o ${BUSTED_OUTPUT_TYPE}
--lua=${LUA_PRG} --lazy --helper=${TEST_DIR}/${TEST_TYPE}/preload.lua
diff --git a/runtime/CMakeLists.txt b/runtime/CMakeLists.txt
index 0dd8b07b7a..cced1a8d04 100644
--- a/runtime/CMakeLists.txt
+++ b/runtime/CMakeLists.txt
@@ -3,6 +3,7 @@ set(GENERATED_RUNTIME_DIR ${PROJECT_BINARY_DIR}/runtime)
set(GENERATED_SYN_VIM ${GENERATED_RUNTIME_DIR}/syntax/vim/generated.vim)
set(GENERATED_HELP_TAGS ${GENERATED_RUNTIME_DIR}/doc/tags)
set(GENERATED_PACKAGE_DIR ${GENERATED_RUNTIME_DIR}/pack/dist/opt)
+set(FUNCS_DATA ${PROJECT_BINARY_DIR}/funcs_data.mpack)
file(MAKE_DIRECTORY ${GENERATED_RUNTIME_DIR})
file(MAKE_DIRECTORY ${GENERATED_RUNTIME_DIR}/syntax)
@@ -10,13 +11,14 @@ file(MAKE_DIRECTORY ${GENERATED_RUNTIME_DIR}/syntax/vim)
add_custom_command(OUTPUT ${GENERATED_SYN_VIM}
COMMAND ${LUA_PRG} ${SYN_VIM_GENERATOR}
- ${PROJECT_SOURCE_DIR}/src/nvim ${GENERATED_SYN_VIM}
+ ${PROJECT_SOURCE_DIR}/src/nvim ${GENERATED_SYN_VIM} ${FUNCS_DATA}
DEPENDS
${SYN_VIM_GENERATOR}
${PROJECT_SOURCE_DIR}/src/nvim/ex_cmds.lua
${PROJECT_SOURCE_DIR}/src/nvim/auevents.lua
${PROJECT_SOURCE_DIR}/src/nvim/options.lua
${PROJECT_SOURCE_DIR}/src/nvim/eval.c
+ ${FUNCS_DATA}
)
if(POLICY CMP0054)
diff --git a/runtime/autoload/health.vim b/runtime/autoload/health.vim
index 6ba9405e0a..783c30cbf6 100644
--- a/runtime/autoload/health.vim
+++ b/runtime/autoload/health.vim
@@ -11,47 +11,50 @@ function! s:enhance_syntax() abort
syntax keyword healthSuccess SUCCESS
highlight link healthSuccess Function
- syntax keyword healthSuggestion SUGGESTION
+ syntax keyword healthSuggestion SUGGESTIONS
highlight link healthSuggestion String
endfunction
" Runs the specified healthchecks.
" Runs all discovered healthchecks if a:plugin_names is empty.
function! health#check(plugin_names) abort
- let report = ''
-
let healthchecks = empty(a:plugin_names)
\ ? s:discover_health_checks()
\ : s:to_fn_names(a:plugin_names)
+ tabnew
+ setlocal filetype=markdown bufhidden=wipe
+ call s:enhance_syntax()
+
if empty(healthchecks)
- let report = "ERROR: No healthchecks found."
+ call setline(1, 'ERROR: No healthchecks found.')
else
+ redraw|echo 'Running healthchecks...'
for c in healthchecks
- let report .= printf("\n%s\n%s", c, repeat('=',80))
+ let output = ''
+ call append('$', split(printf("\n%s\n%s", c, repeat('=',80)), "\n"))
try
- let report .= execute('call '.c.'()')
- catch /^Vim\%((\a\+)\)\=:E117/
- let report .= execute(
- \ 'call health#report_error(''No healthcheck found for "'
- \ .s:to_plugin_name(c)
- \ .'" plugin.'')')
+ let output = "\n\n".execute('call '.c.'()')
catch
- let report .= execute(
- \ 'call health#report_error(''Failed to run healthcheck for "'
- \ .s:to_plugin_name(c)
- \ .'" plugin. Exception:''."\n".v:exception)')
+ if v:exception =~# '^Vim\%((\a\+)\)\=:E117.*\V'.c
+ let output = execute(
+ \ 'call health#report_error(''No healthcheck found for "'
+ \ .s:to_plugin_name(c)
+ \ .'" plugin.'')')
+ else
+ let output = execute(
+ \ 'call health#report_error(''Failed to run healthcheck for "'
+ \ .s:to_plugin_name(c)
+ \ .'" plugin. Exception:''."\n".v:exception)')
+ endif
endtry
- let report .= "\n"
+ call append('$', split(output, "\n") + [''])
+ redraw
endfor
endif
- tabnew
- setlocal bufhidden=wipe
- set filetype=markdown
- call s:enhance_syntax()
- call setline(1, split(report, "\n"))
setlocal nomodified
+ redraw|echo ''
endfunction
" Starts a new report.
@@ -86,10 +89,10 @@ function! s:format_report_message(status, msg, ...) abort " {{{
" Report each suggestion
if len(suggestions) > 0
- let output .= "\n - SUGGESTIONS:"
+ let output .= "\n - SUGGESTIONS:"
endif
for suggestion in suggestions
- let output .= "\n - " . s:indent_after_line1(suggestion, 10)
+ let output .= "\n - " . s:indent_after_line1(suggestion, 10)
endfor
return output
diff --git a/runtime/autoload/health/nvim.vim b/runtime/autoload/health/nvim.vim
index 7865634313..d769525373 100644
--- a/runtime/autoload/health/nvim.vim
+++ b/runtime/autoload/health/nvim.vim
@@ -1,150 +1,3 @@
-let s:bad_responses = [
- \ 'unable to parse python response',
- \ 'unable to parse',
- \ 'unable to get pypi response',
- \ 'unable to get neovim executable',
- \ 'unable to find neovim version'
- \ ]
-
-function! s:is_bad_response(s) abort
- return index(s:bad_responses, a:s) >= 0
-endfunction
-
-function! s:trim(s) abort
- return substitute(a:s, '^\_s*\|\_s*$', '', 'g')
-endfunction
-
-" Simple version comparison.
-function! s:version_cmp(a, b) abort
- let a = split(a:a, '\.')
- let b = split(a:b, '\.')
-
- for i in range(len(a))
- if a[i] > b[i]
- return 1
- elseif a[i] < b[i]
- return -1
- endif
- endfor
-
- return 0
-endfunction
-
-" Fetch the contents of a URL.
-function! s:download(url) abort
- let content = ''
- if executable('curl')
- let content = system(['curl', '-sL', "'", a:url, "'"])
- endif
-
- if empty(content) && executable('python')
- let script = "
- \try:\n
- \ from urllib.request import urlopen\n
- \except ImportError:\n
- \ from urllib2 import urlopen\n
- \\n
- \try:\n
- \ response = urlopen('".a:url."')\n
- \ print(response.read().decode('utf8'))\n
- \except Exception:\n
- \ pass\n
- \"
- let content = system(['python', '-c', "'", script, "'", '2>/dev/null'])
- endif
-
- return content
-endfunction
-
-
-" Get the latest Neovim Python client version from PyPI. Result is cached.
-function! s:latest_pypi_version() abort
- if exists('s:pypi_version')
- return s:pypi_version
- endif
-
- let s:pypi_version = 'unable to get pypi response'
- let pypi_info = s:download('https://pypi.python.org/pypi/neovim/json')
- if !empty(pypi_info)
- let pypi_data = json_decode(pypi_info)
- let s:pypi_version = get(get(pypi_data, 'info', {}), 'version', 'unable to parse')
- return s:pypi_version
- endif
-endfunction
-
-" Get version information using the specified interpreter. The interpreter is
-" used directly in case breaking changes were introduced since the last time
-" Neovim's Python client was updated.
-"
-" Returns [
-" python executable version,
-" current nvim version,
-" current pypi nvim status,
-" installed version status
-" ]
-function! s:version_info(python) abort
- let pypi_version = s:latest_pypi_version()
- let python_version = s:trim(system([
- \ a:python,
- \ '-c',
- \ 'import sys; print(".".join(str(x) for x in sys.version_info[:3]))',
- \ ]))
-
- if empty(python_version)
- let python_version = 'unable to parse python response'
- endif
-
- let nvim_path = s:trim(system([
- \ a:python,
- \ '-c',
- \ 'import neovim; print(neovim.__file__)',
- \ '2>/dev/null']))
-
- let nvim_path = s:trim(system([
- \ 'python3',
- \ '-c',
- \ 'import neovim; print(neovim.__file__)'
- \ ]))
- " \ '2>/dev/null']))
-
- if empty(nvim_path)
- return [python_version, 'unable to find neovim executable', pypi_version, 'unable to get neovim executable']
- endif
-
- let nvim_version = 'unable to find neovim version'
- let base = fnamemodify(nvim_path, ':h')
- for meta in glob(base.'-*/METADATA', 1, 1) + glob(base.'-*/PKG-INFO', 1, 1)
- for meta_line in readfile(meta)
- if meta_line =~# '^Version:'
- let nvim_version = matchstr(meta_line, '^Version: \zs\S\+')
- endif
- endfor
- endfor
-
- let version_status = 'unknown'
- if !s:is_bad_response(nvim_version) && !s:is_bad_response(pypi_version)
- if s:version_cmp(nvim_version, pypi_version) == -1
- let version_status = 'outdated'
- else
- let version_status = 'up to date'
- endif
- endif
-
- return [python_version, nvim_version, pypi_version, version_status]
-endfunction
-
-" Check the Python interpreter's usability.
-function! s:check_bin(bin) abort
- if !filereadable(a:bin)
- call health#report_error(printf('"%s" was not found.', a:bin))
- return 0
- elseif executable(a:bin) != 1
- call health#report_error(printf('"%s" is not executable.', a:bin))
- return 0
- endif
- return 1
-endfunction
-
" Load the remote plugin manifest file and check for unregistered plugins
function! s:check_manifest() abort
call health#report_start('Remote Plugins')
@@ -204,236 +57,6 @@ function! s:check_manifest() abort
endif
endfunction
-
-function! s:check_python(version) abort
- call health#report_start('Python ' . a:version . ' provider')
-
- let python_bin_name = 'python'.(a:version == 2 ? '2' : '3')
- let pyenv = resolve(exepath('pyenv'))
- let pyenv_root = exists('$PYENV_ROOT') ? resolve($PYENV_ROOT) : 'n'
- let venv = exists('$VIRTUAL_ENV') ? resolve($VIRTUAL_ENV) : ''
- let host_prog_var = python_bin_name.'_host_prog'
- let host_skip_var = python_bin_name.'_host_skip_check'
- let python_bin = ''
- let python_multiple = []
-
- if exists('g:'.host_prog_var)
- call health#report_info(printf('Using: g:%s = "%s"', host_prog_var, get(g:, host_prog_var)))
- endif
-
- let [python_bin_name, pythonx_errs] = provider#pythonx#Detect(a:version)
- if empty(python_bin_name)
- call health#report_warn('No Python interpreter was found with the neovim '
- \ . 'module. Using the first available for diagnostics.')
- if !empty(pythonx_errs)
- call health#report_warn(pythonx_errs)
- endif
- let old_skip = get(g:, host_skip_var, 0)
- let g:[host_skip_var] = 1
- let [python_bin_name, pythonx_errs] = provider#pythonx#Detect(a:version)
- let g:[host_skip_var] = old_skip
- endif
-
- if !empty(python_bin_name)
- if exists('g:'.host_prog_var)
- let python_bin = exepath(python_bin_name)
- endif
- let python_bin_name = fnamemodify(python_bin_name, ':t')
- endif
-
- if !empty(pythonx_errs)
- call health#report_error('Python provider error', pythonx_errs)
- endif
-
- if !empty(python_bin_name) && empty(python_bin) && empty(pythonx_errs)
- if !exists('g:'.host_prog_var)
- call health#report_info(printf('`g:%s` is not set. Searching for '
- \ . '%s in the environment.', host_prog_var, python_bin_name))
- endif
-
- if !empty(pyenv)
- if empty(pyenv_root)
- call health#report_warn(
- \ 'pyenv was found, but $PYENV_ROOT is not set.',
- \ ['Did you follow the final install instructions?']
- \ )
- else
- call health#report_ok(printf('pyenv found: "%s"', pyenv))
- endif
-
- let python_bin = s:trim(system(
- \ printf('"%s" which %s 2>/dev/null', pyenv, python_bin_name)))
-
- if empty(python_bin)
- call health#report_warn(printf('pyenv couldn''t find %s.', python_bin_name))
- endif
- endif
-
- if empty(python_bin)
- let python_bin = exepath(python_bin_name)
-
- if exists('$PATH')
- for path in split($PATH, ':')
- let path_bin = path.'/'.python_bin_name
- if path_bin != python_bin && index(python_multiple, path_bin) == -1
- \ && executable(path_bin)
- call add(python_multiple, path_bin)
- endif
- endfor
-
- if len(python_multiple)
- " This is worth noting since the user may install something
- " that changes $PATH, like homebrew.
- call health#report_info(printf('There are multiple %s executables found. '
- \ . 'Set "g:%s" to avoid surprises.', python_bin_name, host_prog_var))
- endif
-
- if python_bin =~# '\<shims\>'
- call health#report_warn(printf('"%s" appears to be a pyenv shim.', python_bin), [
- \ 'The "pyenv" executable is not in $PATH,',
- \ 'Your pyenv installation is broken. You should set '
- \ . '"g:'.host_prog_var.'" to avoid surprises.',
- \ ])
- endif
- endif
- endif
- endif
-
- if !empty(python_bin)
- if empty(venv) && !empty(pyenv) && !exists('g:'.host_prog_var)
- \ && !empty(pyenv_root) && resolve(python_bin) !~# '^'.pyenv_root.'/'
- call health#report_warn('pyenv is not set up optimally.', [
- \ printf('Suggestion: Create a virtualenv specifically '
- \ . 'for Neovim using pyenv and use "g:%s". This will avoid '
- \ . 'the need to install Neovim''s Python client in each '
- \ . 'version/virtualenv.', host_prog_var)
- \ ])
- elseif !empty(venv) && exists('g:'.host_prog_var)
- if !empty(pyenv_root)
- let venv_root = pyenv_root
- else
- let venv_root = fnamemodify(venv, ':h')
- endif
-
- if resolve(python_bin) !~# '^'.venv_root.'/'
- call health#report_warn('Your virtualenv is not set up optimally.', [
- \ printf('Suggestion: Create a virtualenv specifically '
- \ . 'for Neovim and use "g:%s". This will avoid '
- \ . 'the need to install Neovim''s Python client in each '
- \ . 'virtualenv.', host_prog_var)
- \ ])
- endif
- endif
- endif
-
- if empty(python_bin) && !empty(python_bin_name)
- " An error message should have already printed.
- call health#report_error(printf('"%s" was not found.', python_bin_name))
- elseif !empty(python_bin) && !s:check_bin(python_bin)
- let python_bin = ''
- endif
-
- " Check if $VIRTUAL_ENV is active
- let virtualenv_inactive = 0
-
- if exists('$VIRTUAL_ENV')
- if !empty(pyenv)
- let pyenv_prefix = resolve(s:trim(system([pyenv, 'prefix'])))
- if $VIRTUAL_ENV != pyenv_prefix
- let virtualenv_inactive = 1
- endif
- elseif !empty(python_bin_name) && exepath(python_bin_name) !~# '^'.$VIRTUAL_ENV.'/'
- let virtualenv_inactive = 1
- endif
- endif
-
- if virtualenv_inactive
- let suggestions = [
- \ 'If you are using Zsh, see: http://vi.stackexchange.com/a/7654/5229',
- \ ]
- call health#report_warn(
- \ '$VIRTUAL_ENV exists but appears to be inactive. '
- \ . 'This could lead to unexpected results.',
- \ suggestions)
- endif
-
- " Diagnostic output
- call health#report_info('Executable: ' . (empty(python_bin) ? 'Not found' : python_bin))
- if len(python_multiple)
- for path_bin in python_multiple
- call health#report_info('Other python executable: ' . path_bin)
- endfor
- endif
-
- if !empty(python_bin)
- let [pyversion, current, latest, status] = s:version_info(python_bin)
- if a:version != str2nr(pyversion)
- call health#report_warn('Got an unexpected version of Python.' .
- \ ' This could lead to confusing error messages.')
- endif
- if a:version == 3 && str2float(pyversion) < 3.3
- call health#report_warn('Python 3.3+ is recommended.')
- endif
-
- call health#report_info('Python'.a:version.' version: ' . pyversion)
- call health#report_info(printf('%s-neovim Version: %s', python_bin_name, current))
-
- if s:is_bad_response(current)
- let suggestions = [
- \ 'Error found was: ' . current,
- \ 'Use the command `$ pip' . a:version . ' install neovim`',
- \ ]
- call health#report_error(
- \ 'Neovim Python client is not installed.',
- \ suggestions)
- endif
-
- if s:is_bad_response(latest)
- call health#report_warn('Unable to fetch latest Neovim Python client version.')
- endif
-
- if s:is_bad_response(status)
- call health#report_warn('Latest Neovim Python client versions: ('.latest.')')
- else
- call health#report_ok('Latest Neovim Python client is installed: ('.status.')')
- endif
- endif
-
-endfunction
-
-function! s:check_ruby() abort
- call health#report_start('Ruby provider')
- let min_version = "0.2.4"
- let ruby_version = systemlist('ruby -v')[0]
- let ruby_prog = provider#ruby#Detect()
- let suggestions =
- \ ['Install or upgrade the neovim RubyGem using `gem install neovim`.']
-
- if empty(ruby_prog)
- let ruby_prog = 'not found'
- let prog_vers = 'not found'
- call health#report_error('Missing Neovim RubyGem', suggestions)
- else
- silent let prog_vers = systemlist(ruby_prog . ' --version')[0]
- if v:shell_error
- let prog_vers = 'outdated'
- call health#report_warn('Neovim RubyGem is not up-to-date', suggestions)
- elseif s:version_cmp(prog_vers, min_version) == -1
- let prog_vers .= ' (outdated)'
- call health#report_warn('Neovim RubyGem is not up-to-date', suggestions)
- else
- call health#report_ok('Found Neovim RubyGem')
- endif
- endif
-
- call health#report_info('Ruby Version: ' . ruby_version)
- call health#report_info('Host Executable: ' . ruby_prog)
- call health#report_info('Host Version: ' . prog_vers)
-endfunction
-
function! health#nvim#check() abort
call s:check_manifest()
- call s:check_python(2)
- call s:check_python(3)
- call s:check_ruby()
endfunction
diff --git a/runtime/autoload/health/provider.vim b/runtime/autoload/health/provider.vim
new file mode 100644
index 0000000000..8fa281e7e3
--- /dev/null
+++ b/runtime/autoload/health/provider.vim
@@ -0,0 +1,382 @@
+let s:bad_responses = [
+ \ 'unable to parse python response',
+ \ 'unable to parse',
+ \ 'unable to get pypi response',
+ \ 'unable to get neovim executable',
+ \ 'unable to find neovim version'
+ \ ]
+
+function! s:is_bad_response(s) abort
+ return index(s:bad_responses, a:s) >= 0
+endfunction
+
+function! s:trim(s) abort
+ return substitute(a:s, '^\_s*\|\_s*$', '', 'g')
+endfunction
+
+" Simple version comparison.
+function! s:version_cmp(a, b) abort
+ let a = split(a:a, '\.')
+ let b = split(a:b, '\.')
+
+ for i in range(len(a))
+ if a[i] > b[i]
+ return 1
+ elseif a[i] < b[i]
+ return -1
+ endif
+ endfor
+
+ return 0
+endfunction
+
+" Fetch the contents of a URL.
+function! s:download(url) abort
+ let content = ''
+ if executable('curl')
+ let content = system(['curl', '-sL', "'", a:url, "'"])
+ endif
+
+ if empty(content) && executable('python')
+ let script = "
+ \try:\n
+ \ from urllib.request import urlopen\n
+ \except ImportError:\n
+ \ from urllib2 import urlopen\n
+ \\n
+ \try:\n
+ \ response = urlopen('".a:url."')\n
+ \ print(response.read().decode('utf8'))\n
+ \except Exception:\n
+ \ pass\n
+ \"
+ let content = system(['python', '-c', "'", script, "'", '2>/dev/null'])
+ endif
+
+ return content
+endfunction
+
+
+" Get the latest Neovim Python client version from PyPI. Result is cached.
+function! s:latest_pypi_version() abort
+ if exists('s:pypi_version')
+ return s:pypi_version
+ endif
+
+ let s:pypi_version = 'unable to get pypi response'
+ let pypi_info = s:download('https://pypi.python.org/pypi/neovim/json')
+ if !empty(pypi_info)
+ let pypi_data = json_decode(pypi_info)
+ let s:pypi_version = get(get(pypi_data, 'info', {}), 'version', 'unable to parse')
+ return s:pypi_version
+ endif
+endfunction
+
+" Get version information using the specified interpreter. The interpreter is
+" used directly in case breaking changes were introduced since the last time
+" Neovim's Python client was updated.
+"
+" Returns: [
+" {python executable version},
+" {current nvim version},
+" {current pypi nvim status},
+" {installed version status}
+" ]
+function! s:version_info(python) abort
+ let pypi_version = s:latest_pypi_version()
+ let python_version = s:trim(system([
+ \ a:python,
+ \ '-c',
+ \ 'import sys; print(".".join(str(x) for x in sys.version_info[:3]))',
+ \ ]))
+
+ if empty(python_version)
+ let python_version = 'unable to parse python response'
+ endif
+
+ let nvim_path = s:trim(system([
+ \ a:python,
+ \ '-c',
+ \ 'import neovim; print(neovim.__file__)',
+ \ '2>/dev/null']))
+
+ let nvim_path = s:trim(system([
+ \ 'python3',
+ \ '-c',
+ \ 'import neovim; print(neovim.__file__)'
+ \ ]))
+ " \ '2>/dev/null']))
+
+ if empty(nvim_path)
+ return [python_version, 'unable to find neovim executable', pypi_version, 'unable to get neovim executable']
+ endif
+
+ let nvim_version = 'unable to find neovim version'
+ let base = fnamemodify(nvim_path, ':h')
+ for meta in glob(base.'-*/METADATA', 1, 1) + glob(base.'-*/PKG-INFO', 1, 1)
+ for meta_line in readfile(meta)
+ if meta_line =~# '^Version:'
+ let nvim_version = matchstr(meta_line, '^Version: \zs\S\+')
+ endif
+ endfor
+ endfor
+
+ let version_status = 'unknown'
+ if !s:is_bad_response(nvim_version) && !s:is_bad_response(pypi_version)
+ if s:version_cmp(nvim_version, pypi_version) == -1
+ let version_status = 'outdated'
+ else
+ let version_status = 'up to date'
+ endif
+ endif
+
+ return [python_version, nvim_version, pypi_version, version_status]
+endfunction
+
+" Check the Python interpreter's usability.
+function! s:check_bin(bin) abort
+ if !filereadable(a:bin)
+ call health#report_error(printf('"%s" was not found.', a:bin))
+ return 0
+ elseif executable(a:bin) != 1
+ call health#report_error(printf('"%s" is not executable.', a:bin))
+ return 0
+ endif
+ return 1
+endfunction
+
+function! s:check_python(version) abort
+ call health#report_start('Python ' . a:version . ' provider')
+
+ let python_bin_name = 'python'.(a:version == 2 ? '2' : '3')
+ let pyenv = resolve(exepath('pyenv'))
+ let pyenv_root = exists('$PYENV_ROOT') ? resolve($PYENV_ROOT) : 'n'
+ let venv = exists('$VIRTUAL_ENV') ? resolve($VIRTUAL_ENV) : ''
+ let host_prog_var = python_bin_name.'_host_prog'
+ let host_skip_var = python_bin_name.'_host_skip_check'
+ let python_bin = ''
+ let python_multiple = []
+
+ if exists('g:'.host_prog_var)
+ call health#report_info(printf('Using: g:%s = "%s"', host_prog_var, get(g:, host_prog_var)))
+ endif
+
+ let [python_bin_name, pythonx_errs] = provider#pythonx#Detect(a:version)
+ if empty(python_bin_name)
+ call health#report_warn('No Python interpreter was found with the neovim '
+ \ . 'module. Using the first available for diagnostics.')
+ if !empty(pythonx_errs)
+ call health#report_warn(pythonx_errs)
+ endif
+ let old_skip = get(g:, host_skip_var, 0)
+ let g:[host_skip_var] = 1
+ let [python_bin_name, pythonx_errs] = provider#pythonx#Detect(a:version)
+ let g:[host_skip_var] = old_skip
+ endif
+
+ if !empty(python_bin_name)
+ if exists('g:'.host_prog_var)
+ let python_bin = exepath(python_bin_name)
+ endif
+ let python_bin_name = fnamemodify(python_bin_name, ':t')
+ endif
+
+ if !empty(pythonx_errs)
+ call health#report_error('Python provider error', pythonx_errs)
+ endif
+
+ if !empty(python_bin_name) && empty(python_bin) && empty(pythonx_errs)
+ if !exists('g:'.host_prog_var)
+ call health#report_info(printf('`g:%s` is not set. Searching for '
+ \ . '%s in the environment.', host_prog_var, python_bin_name))
+ endif
+
+ if !empty(pyenv)
+ if empty(pyenv_root)
+ call health#report_warn(
+ \ 'pyenv was found, but $PYENV_ROOT is not set.',
+ \ ['Did you follow the final install instructions?']
+ \ )
+ else
+ call health#report_ok(printf('pyenv found: "%s"', pyenv))
+ endif
+
+ let python_bin = s:trim(system(
+ \ printf('"%s" which %s 2>/dev/null', pyenv, python_bin_name)))
+
+ if empty(python_bin)
+ call health#report_warn(printf('pyenv couldn''t find %s.', python_bin_name))
+ endif
+ endif
+
+ if empty(python_bin)
+ let python_bin = exepath(python_bin_name)
+
+ if exists('$PATH')
+ for path in split($PATH, ':')
+ let path_bin = path.'/'.python_bin_name
+ if path_bin != python_bin && index(python_multiple, path_bin) == -1
+ \ && executable(path_bin)
+ call add(python_multiple, path_bin)
+ endif
+ endfor
+
+ if len(python_multiple)
+ " This is worth noting since the user may install something
+ " that changes $PATH, like homebrew.
+ call health#report_info(printf('There are multiple %s executables found. '
+ \ . 'Set "g:%s" to avoid surprises.', python_bin_name, host_prog_var))
+ endif
+
+ if python_bin =~# '\<shims\>'
+ call health#report_warn(printf('"%s" appears to be a pyenv shim.', python_bin), [
+ \ 'The "pyenv" executable is not in $PATH,',
+ \ 'Your pyenv installation is broken. You should set '
+ \ . '"g:'.host_prog_var.'" to avoid surprises.',
+ \ ])
+ endif
+ endif
+ endif
+ endif
+
+ if !empty(python_bin)
+ if empty(venv) && !empty(pyenv) && !exists('g:'.host_prog_var)
+ \ && !empty(pyenv_root) && resolve(python_bin) !~# '^'.pyenv_root.'/'
+ call health#report_warn('pyenv is not set up optimally.', [
+ \ printf('Suggestion: Create a virtualenv specifically '
+ \ . 'for Neovim using pyenv and use "g:%s". This will avoid '
+ \ . 'the need to install Neovim''s Python client in each '
+ \ . 'version/virtualenv.', host_prog_var)
+ \ ])
+ elseif !empty(venv) && exists('g:'.host_prog_var)
+ if !empty(pyenv_root)
+ let venv_root = pyenv_root
+ else
+ let venv_root = fnamemodify(venv, ':h')
+ endif
+
+ if resolve(python_bin) !~# '^'.venv_root.'/'
+ call health#report_warn('Your virtualenv is not set up optimally.', [
+ \ printf('Suggestion: Create a virtualenv specifically '
+ \ . 'for Neovim and use "g:%s". This will avoid '
+ \ . 'the need to install Neovim''s Python client in each '
+ \ . 'virtualenv.', host_prog_var)
+ \ ])
+ endif
+ endif
+ endif
+
+ if empty(python_bin) && !empty(python_bin_name)
+ " An error message should have already printed.
+ call health#report_error(printf('"%s" was not found.', python_bin_name))
+ elseif !empty(python_bin) && !s:check_bin(python_bin)
+ let python_bin = ''
+ endif
+
+ " Check if $VIRTUAL_ENV is active
+ let virtualenv_inactive = 0
+
+ if exists('$VIRTUAL_ENV')
+ if !empty(pyenv)
+ let pyenv_prefix = resolve(s:trim(system([pyenv, 'prefix'])))
+ if $VIRTUAL_ENV != pyenv_prefix
+ let virtualenv_inactive = 1
+ endif
+ elseif !empty(python_bin_name) && exepath(python_bin_name) !~# '^'.$VIRTUAL_ENV.'/'
+ let virtualenv_inactive = 1
+ endif
+ endif
+
+ if virtualenv_inactive
+ let suggestions = [
+ \ 'If you are using Zsh, see: http://vi.stackexchange.com/a/7654/5229',
+ \ ]
+ call health#report_warn(
+ \ '$VIRTUAL_ENV exists but appears to be inactive. '
+ \ . 'This could lead to unexpected results.',
+ \ suggestions)
+ endif
+
+ " Diagnostic output
+ call health#report_info('Executable: ' . (empty(python_bin) ? 'Not found' : python_bin))
+ if len(python_multiple)
+ for path_bin in python_multiple
+ call health#report_info('Other python executable: ' . path_bin)
+ endfor
+ endif
+
+ if !empty(python_bin)
+ let [pyversion, current, latest, status] = s:version_info(python_bin)
+ if a:version != str2nr(pyversion)
+ call health#report_warn('Got an unexpected version of Python.' .
+ \ ' This could lead to confusing error messages.')
+ endif
+ if a:version == 3 && str2float(pyversion) < 3.3
+ call health#report_warn('Python 3.3+ is recommended.')
+ endif
+
+ call health#report_info('Python'.a:version.' version: ' . pyversion)
+ call health#report_info(printf('%s-neovim Version: %s', python_bin_name, current))
+
+ if s:is_bad_response(current)
+ let suggestions = [
+ \ 'Error found was: ' . current,
+ \ 'Use the command `$ pip' . a:version . ' install neovim`',
+ \ ]
+ call health#report_error(
+ \ 'Neovim Python client is not installed.',
+ \ suggestions)
+ endif
+
+ if s:is_bad_response(latest)
+ call health#report_warn('Unable to fetch latest Neovim Python client version.')
+ endif
+
+ if s:is_bad_response(status)
+ call health#report_warn('Latest Neovim Python client versions: ('.latest.')')
+ else
+ call health#report_ok('Latest Neovim Python client is installed: ('.status.')')
+ endif
+ endif
+
+endfunction
+
+function! s:check_ruby() abort
+ call health#report_start('Ruby provider')
+ let ruby_version = systemlist('ruby -v')[0]
+ let ruby_prog = provider#ruby#Detect()
+ let suggestions =
+ \ ['Install or upgrade the neovim RubyGem using `gem install neovim`.']
+
+ if empty(ruby_prog)
+ let ruby_prog = 'not found'
+ let prog_vers = 'not found'
+ call health#report_error('Missing Neovim RubyGem', suggestions)
+ else
+ silent let latest_gem = get(systemlist("gem list -ra '^neovim$' 2>/dev/null | " .
+ \ "awk -F'[()]' '{print $2}' | " .
+ \ 'cut -d, -f1'), 0, 'not found')
+ let latest_desc = ' (latest: ' . latest_gem . ')'
+
+ silent let prog_vers = systemlist(ruby_prog . ' --version')[0]
+ if v:shell_error
+ let prog_vers = 'not found' . latest_desc
+ call health#report_warn('Neovim RubyGem is not up-to-date.', suggestions)
+ elseif s:version_cmp(prog_vers, latest_gem) == -1
+ let prog_vers .= latest_desc
+ call health#report_warn('Neovim RubyGem is not up-to-date.', suggestions)
+ else
+ call health#report_ok('Found up-to-date neovim RubyGem')
+ endif
+ endif
+
+ call health#report_info('Ruby Version: ' . ruby_version)
+ call health#report_info('Host Executable: ' . ruby_prog)
+ call health#report_info('Host Version: ' . prog_vers)
+endfunction
+
+function! health#provider#check() abort
+ call s:check_python(2)
+ call s:check_python(3)
+ call s:check_ruby()
+endfunction
diff --git a/runtime/autoload/man.vim b/runtime/autoload/man.vim
index 6c2d4eae8e..bac88fc99e 100644
--- a/runtime/autoload/man.vim
+++ b/runtime/autoload/man.vim
@@ -1,19 +1,15 @@
" Maintainer: Anmol Sethi <anmol@aubble.com>
-" Ensure Vim is not recursively invoked (man-db does this)
-" by forcing man to use cat as the pager.
-" More info here http://comments.gmane.org/gmane.editors.vim.devel/29085
if &shell =~# 'fish$'
- let s:man_cmd = 'man -P cat ^/dev/null'
+ let s:man_cmd = 'man ^/dev/null'
else
- let s:man_cmd = 'man -P cat 2>/dev/null'
+ let s:man_cmd = 'man 2>/dev/null'
endif
let s:man_find_arg = "-w"
-" TODO(nhooyr) I do not think completion will work on SunOS because I'm not sure if `man -l`
-" displays the list of directories that are searched by man for manpages.
-" I also do not think Solaris supports the '-P' flag used above and uses only $PAGER.
+" TODO(nhooyr) Completion may work on SunOS; I'm not sure if `man -l` displays
+" the list of searched directories.
try
if !has('win32') && $OSTYPE !~? 'cygwin\|linux' && system('uname -s') =~? 'SunOS' && system('uname -r') =~# '^5'
let s:man_find_arg = '-l'
@@ -22,77 +18,71 @@ catch /E145:/
" Ignore the error in restricted mode
endtry
-" We need count and count1 to ensure the section was explicitly set
-" by the user. count defaults to 0 which is a valid section and
-" count1 defaults to 1 which is also a valid section. Only when they
-" are equal was the count explicitly set.
-function! man#open_page(count, count1, ...) abort
+function! man#open_page(count, count1, mods, ...) abort
if a:0 > 2
call s:error('too many arguments')
return
- elseif a:0 ==# 1
- if empty(a:1)
+ elseif a:0 == 0
+ let ref = &filetype ==# 'man' ? expand('<cWORD>') : expand('<cword>')
+ if empty(ref)
call s:error('no identifier under cursor')
return
endif
+ elseif a:0 ==# 1
let ref = a:1
else
- " We combine the name and sect into a manpage reference so that all
+ " Combine the name and sect into a manpage reference so that all
" verification/extraction can be kept in a single function.
" If a:2 is a reference as well, that is fine because it is the only
" reference that will match.
let ref = a:2.'('.a:1.')'
endif
try
- let [sect, name] = s:extract_sect_and_name_ref(ref)
+ let [sect, name] = man#extract_sect_and_name_ref(ref)
if a:count ==# a:count1
- " user explicitly set a count
+ " v:count defaults to 0 which is a valid section, and v:count1 defaults to
+ " 1, also a valid section. If they are equal, count explicitly set.
let sect = string(a:count)
endif
- let [sect, name] = s:verify_exists(sect, name)
+ let [sect, name, path] = s:verify_exists(sect, name)
catch
call s:error(v:exception)
return
endtry
call s:push_tag()
let bufname = 'man://'.name.(empty(sect)?'':'('.sect.')')
- let found_man = s:find_man()
- if getbufvar(bufname, 'manwidth') ==# s:manwidth()
- if found_man
- silent execute 'buf' bufnr(bufname)
- else
- execute 'split' bufname
- endif
- keepjumps 1
- return
- endif
- if found_man
- noautocmd execute 'edit' bufname
+ if a:mods !~# 'tab' && s:find_man()
+ noautocmd execute 'silent edit' bufname
else
- noautocmd execute 'split' bufname
+ noautocmd execute 'silent' a:mods 'split' bufname
endif
- call s:read_page(sect, name)
+ let b:man_sect = sect
+ call s:read_page(path)
endfunction
function! man#read_page(ref) abort
try
- let [sect, name] = s:extract_sect_and_name_ref(a:ref)
- let [sect, name] = s:verify_exists(sect, name)
+ let [sect, name] = man#extract_sect_and_name_ref(a:ref)
+ let [b:man_sect, name, path] = s:verify_exists(sect, name)
catch
- call s:error(v:exception)
+ " call to s:error() is unnecessary
return
endtry
- call s:read_page(sect, name)
+ call s:read_page(path)
endfunction
-function! s:read_page(sect, name) abort
+function! s:read_page(path) abort
setlocal modifiable
setlocal noreadonly
- keepjumps %delete _
- let b:manwidth = s:manwidth()
- silent execute 'read!env MANWIDTH='.b:manwidth s:man_cmd s:man_args(a:sect, a:name)
+ silent keepjumps %delete _
+ " Force MANPAGER=cat to ensure Vim is not recursively invoked (by man-db).
+ " http://comments.gmane.org/gmane.editors.vim.devel/29085
+ " Respect $MANWIDTH, or default to window width.
+ let cmd = 'env MANPAGER=cat'.(empty($MANWIDTH) ? ' MANWIDTH='.winwidth(0) : '')
+ let cmd .= ' '.s:man_cmd.' '.shellescape(a:path)
+ silent put =system(cmd)
" remove all the backspaced text
- silent execute 'keeppatterns keepjumps %substitute,.\b,,e'.(&gdefault?'':'g')
+ execute 'silent keeppatterns keepjumps %substitute,.\b,,e'.(&gdefault?'':'g')
while getline(1) =~# '^\s*$'
silent keepjumps 1delete _
endwhile
@@ -101,17 +91,17 @@ endfunction
" attempt to extract the name and sect out of 'name(sect)'
" otherwise just return the largest string of valid characters in ref
-function! s:extract_sect_and_name_ref(ref) abort
+function! man#extract_sect_and_name_ref(ref) abort
if a:ref[0] ==# '-' " try ':Man -pandoc' with this disabled.
- throw 'manpage name starts with ''-'''
+ throw 'manpage name cannot start with ''-'''
endif
let ref = matchstr(a:ref, '[^()]\+([^()]\+)')
if empty(ref)
let name = matchstr(a:ref, '[^()]\+')
if empty(name)
- throw 'manpage reference contains only parantheses'
+ throw 'manpage reference cannot contain only parentheses'
endif
- return ['', name]
+ return [get(b:, 'man_default_sects', ''), name]
endif
let left = split(ref, '(')
" see ':Man 3X curses' on why tolower.
@@ -120,21 +110,29 @@ function! s:extract_sect_and_name_ref(ref) abort
return [tolower(split(left[1], ')')[0]), left[0]]
endfunction
-function! s:verify_exists(sect, name) abort
- let path = system(s:man_cmd.' '.s:man_find_arg.' '.s:man_args(a:sect, a:name))
- if path !~# '^\/'
- if empty(a:sect)
- throw 'no manual entry for '.a:name
- endif
+function! s:get_path(sect, name) abort
+ if empty(a:sect)
let path = system(s:man_cmd.' '.s:man_find_arg.' '.shellescape(a:name))
if path !~# '^\/'
- throw 'no manual entry for '.a:name.'('.a:sect.') or '.a:name
+ throw 'no manual entry for '.a:name
endif
+ return path
endif
- if a:name =~# '\/'
- " We do not need to extract the section/name from the path if the name is
- " just a path.
- return ['', a:name]
+ " '-s' flag handles:
+ " - tokens like 'printf(echo)'
+ " - sections starting with '-'
+ " - 3pcap section (found on macOS)
+ " - commas between sections (for section priority)
+ return system(s:man_cmd.' '.s:man_find_arg.' -s '.shellescape(a:sect).' '.shellescape(a:name))
+endfunction
+
+function! s:verify_exists(sect, name) abort
+ let path = s:get_path(a:sect, a:name)
+ if path !~# '^\/'
+ let path = s:get_path(get(b:, 'man_default_sects', ''), a:name)
+ if path !~# '^\/'
+ let path = s:get_path('', a:name)
+ endif
endif
" We need to extract the section from the path because sometimes
" the actual section of the manpage is more specific than the section
@@ -142,7 +140,8 @@ function! s:verify_exists(sect, name) abort
" Also on linux, it seems that the name is case insensitive. So if one does
" ':Man PRIntf', we still want the name of the buffer to be 'printf' or
" whatever the correct capitilization is.
- return s:extract_sect_and_name_path(path[:len(path)-2])
+ let path = path[:len(path)-2]
+ return s:extract_sect_and_name_path(path) + [path]
endfunction
let s:tag_stack = []
@@ -158,7 +157,7 @@ endfunction
function! man#pop_tag() abort
if !empty(s:tag_stack)
let tag = remove(s:tag_stack, -1)
- execute tag['buf'].'b'
+ silent execute tag['buf'].'buffer'
call cursor(tag['lnum'], tag['col'])
endif
endfunction
@@ -170,13 +169,15 @@ function! s:extract_sect_and_name_path(path) abort
let tail = fnamemodify(tail, ':r')
endif
let sect = matchstr(tail, '\.\zs[^.]\+$')
- let name = matchstr(tail, '^.\+\ze\.[^.]\+$')
+ let name = matchstr(tail, '^.\+\ze\.')
return [sect, name]
endfunction
function! s:find_man() abort
if &filetype ==# 'man'
return 1
+ elseif winnr('$') ==# 1
+ return 0
endif
let thiswin = winnr()
while 1
@@ -189,32 +190,6 @@ function! s:find_man() abort
endwhile
endfunction
-function! s:manwidth() abort
- " The reason for respecting $MANWIDTH even if it is wider/smaller than the
- " current window is that the current window might only be temporarily
- " narrow/wide. Since we don't reflow, we should just assume the
- " user knows what they're doing and respect $MANWIDTH.
- if empty($MANWIDTH)
- " If $MANWIDTH is not set, we do not assign directly to $MANWIDTH because
- " then $MANWIDTH will always stay the same value as we only use
- " winwidth(0) when $MANWIDTH is empty. Instead we set it locally for the command.
- return winwidth(0)
- endif
- return $MANWIDTH
-endfunction
-
-function! s:man_args(sect, name) abort
- if empty(a:sect)
- return shellescape(a:name)
- endif
- " The '-s' flag is very useful.
- " We do not need to worry about stuff like 'printf(echo)'
- " (two manpages would be interpreted by man without -s)
- " We do not need to check if the sect starts with '-'
- " Lastly, the 3pcap section on macOS doesn't work without -s
- return '-s '.shellescape(a:sect).' '.shellescape(a:name)
-endfunction
-
function! s:error(msg) abort
redraw
echohl ErrorMsg
@@ -224,7 +199,7 @@ endfunction
let s:mandirs = join(split(system(s:man_cmd.' '.s:man_find_arg), ':\|\n'), ',')
-" see s:extract_sect_and_name_ref on why tolower(sect)
+" see man#extract_sect_and_name_ref on why tolower(sect)
function! man#complete(arg_lead, cmd_line, cursor_pos) abort
let args = split(a:cmd_line)
let l = len(args)
@@ -271,14 +246,14 @@ function! man#complete(arg_lead, cmd_line, cursor_pos) abort
return uniq(sort(map(globpath(s:mandirs,'man?/'.name.'*.'.sect.'*', 0, 1), 's:format_candidate(v:val, sect)'), 'i'))
endfunction
-function! s:format_candidate(c, sect) abort
- if a:c =~# '\.\%(pdf\|in\)$' " invalid extensions
+function! s:format_candidate(path, sect) abort
+ if a:path =~# '\.\%(pdf\|in\)$' " invalid extensions
return
endif
- let [sect, name] = s:extract_sect_and_name_path(a:c)
+ let [sect, name] = s:extract_sect_and_name_path(a:path)
if sect ==# a:sect
return name
- elseif sect =~# a:sect.'[^.]\+$'
+ elseif sect =~# a:sect.'.\+$'
" We include the section if the user provided section is a prefix
" of the actual section.
return name.'('.sect.')'
diff --git a/runtime/doc/api.txt b/runtime/doc/api.txt
index bdeca367b1..c3d7fdb35b 100644
--- a/runtime/doc/api.txt
+++ b/runtime/doc/api.txt
@@ -14,13 +14,13 @@ C API for Nvim *API* *api*
==============================================================================
1. Introduction *api-intro*
-Nvim exposes a public API for external code to interact with the Nvim core. In
-the present version of Nvim the API is primarily used by external processes to
-interact with Nvim using the msgpack-rpc protocol, see |msgpack-rpc|. The API
-will also be used from vimscript to access new Nvim core features, but this is
-not implemented yet. Later on, Nvim might be embeddable in C applications as
-libnvim, and the application will then control the embedded instance by
-calling the C API directly.
+Nvim exposes a public API for external code to interact with the Nvim core.
+The API is used by external processes to interact with Nvim using the
+msgpack-rpc protocol, see |msgpack-rpc|. The API is used from vimscript to
+access some new Nvim core features. See |eval-api| for how api functions are
+called from vimscript. Later on, Nvim might be embeddable in C applications as
+libnvim, and the application will then control the embedded instance by calling
+the C API directly.
==============================================================================
2. API Types *api-types*
@@ -73,10 +73,10 @@ Another use case are plugins that show output in an append-only buffer, and
want to add highlights to the outputs. Highlight data cannot be preserved
on writing and loading a buffer to file, nor in undo/redo cycles.
-Highlights are registered using the |buffer_add_highlight| function, see the
+Highlights are registered using the |nvim_buf_add_highlight| function, see the
generated API documentation for details. If an external highlighter plugin is
adding a large number of highlights in a batch, performance can be improved by
-calling |buffer_add_highlight| as an asynchronous notification, after first
+calling |nvim_buf_add_highlight| as an asynchronous notification, after first
(synchronously) reqesting a source id. Here is an example using wrapper
functions in the python client:
>
@@ -91,10 +91,19 @@ functions in the python client:
buf.clear_highlight(src)
<
If the highlights don't need to be deleted or updated, just pass -1 as
-src_id (this is the default in python). |buffer_clear_highlight| can be used
-to clear highligts from a specific source, in a specific line range or the
-entire buffer by passing in the line range 0, -1 (the later is the default
+src_id (this is the default in python). |nvim_buf_clear_highlight| can be used
+to clear highlights from a specific source, in a specific line range or the
+entire buffer by passing in the line range 0, -1 (the latter is the default
in python as used above).
+An example of calling the api from vimscript: >
+
+ call nvim_buf_set_lines(0, 0, 0, v:true, ["test text"])
+ let src = nvim_buf_add_highlight(0, 0, "String", 1, 0, 4)
+ call nvim_buf_add_highlight(0, src, "Identifier", 0, 5, -1)
+
+ " later
+ call nvim_buf_clear_highlight(0, src, 0, -1)
+>
==============================================================================
vim:tw=78:ts=8:noet:ft=help:norl:
diff --git a/runtime/doc/develop.txt b/runtime/doc/develop.txt
index 6ecbf9fb0d..ddec137079 100644
--- a/runtime/doc/develop.txt
+++ b/runtime/doc/develop.txt
@@ -124,13 +124,26 @@ include the kitchen sink... but you can use it for plumbing."
==============================================================================
2. Design decisions *design-decisions*
-Jargon *dev-jargon*
+JARGON *dev-jargon*
+
+API client ~
+All external UIs and remote plugins (as opposed to regular Vim plugins) are
+"clients" in general; but we call something an "API client" if its purpose is
+to abstract or wrap the RPC API for the convenience of other applications
+(just like a REST client or SDK such as boto3 for AWS: you can speak AWS REST
+using an HTTP client like curl, but boto3 wraps that in a convenient python
+interface). For example, the Nvim lua-client is an API client:
+ https://github.com/neovim/lua-client
Host ~
A plugin "host" is both a client (of the Nvim API) and a server (of an
external platform, e.g. python). It is a remote plugin that hosts other
plugins.
+Remote plugin ~
+Arbitrary code registered via |:UpdateRemotePlugins|, that runs in a separate
+process and communicates with Nvim via the |api|.
+
Window ~
The word "window" is commonly used for several things: A window on the screen,
the xterm window, a window inside Vim to view a buffer.
@@ -145,7 +158,7 @@ window View on a buffer. There can be several windows in Vim,
together with the command line, menubar, toolbar, etc. they
fit in the shell.
-Providers *dev-provider*
+PROVIDERS *dev-provider*
A goal of Nvim is to allow extension of the editor without special knowledge
in the core. But some Vim components are too tightly coupled; in those cases
@@ -189,8 +202,35 @@ Python host isn't installed then the plugin will "think" it is running in
a Vim compiled without the |+python| feature.
-RPC API
-API client
-remote plugin
+API *dev-api*
+
+Use this pattern to name new API functions:
+ nvim_{thing}_{action}_{arbitrary-qualifiers}
+
+If the function acts on an object then {thing} is the name of that object
+(e.g. "buf" or "win"). If the function operates in a "global" context then
+{thing} is usually omitted (but consider "namespacing" your global operations
+with a {thing} that groups functions under a common concept).
+
+Use existing common {action} names if possible:
+ add append to, or insert into, a collection
+ get get a thing (or subset of things by some query)
+ set set a thing
+ del delete a thing (or group of things)
+ list get all things
+
+Use consistent names for {thing} in all API function. E.g. a buffer is called
+"buf" everywhere, not "buffer" in some places and "buf" in others.
+
+Example: `nvim_get_current_line` acts on the global editor state; the common
+{action} "get" is used but {thing} is omitted.
+
+Example: `nvim_buf_add_highlight` acts on a `Buffer` object (the first
+parameter) and uses the common {action} "add".
+
+Example: `nvim_list_bufs` operates in a global context (first parameter is
+_not_ a Buffer). The common {action} "list" indicates that it lists all
+bufs (plural) in the global context.
+
vim:tw=78:ts=8:ft=help:norl:
diff --git a/runtime/doc/eval.txt b/runtime/doc/eval.txt
index 03d8f84aa6..d97a1400ce 100644
--- a/runtime/doc/eval.txt
+++ b/runtime/doc/eval.txt
@@ -2009,6 +2009,7 @@ msgpackdump({list}) List dump a list of objects to msgpack
msgpackparse({list}) List parse msgpack to a list of objects
nextnonblank({lnum}) Number line nr of non-blank line >= {lnum}
nr2char({expr}[, {utf8}]) String single char with ASCII/UTF8 value {expr}
+nvim_...({args}...) any call nvim |api| functions
or({expr}, {expr}) Number bitwise OR
pathshorten({expr}) String shorten directory names in a path
pow({x}, {y}) Float {x} to the power of {y}
@@ -2147,6 +2148,7 @@ values({dict}) List values in {dict}
virtcol({expr}) Number screen column of cursor or mark
visualmode([expr]) String last visual mode used
wildmenumode() Number whether 'wildmenu' mode is active
+win_findbuf( {bufnr}) List find windows containing {bufnr}
win_getid( [{win} [, {tab}]]) Number get window ID for {win} in {tab}
win_gotoid( {expr}) Number go to window with ID {expr}
win_id2tabwin( {expr}) List get tab window nr from window ID
@@ -2208,11 +2210,9 @@ and({expr}, {expr}) *and()*
Example: >
:let flag = and(bits, 0x80)
-
api_info() *api_info()*
Returns Dictionary of |api-metadata|.
-
append({lnum}, {expr}) *append()*
When {expr} is a |List|: Append each item of the |List| as a
text line below line {lnum} in the current buffer.
@@ -5172,6 +5172,17 @@ nr2char({expr}[, {utf8}]) *nr2char()*
characters. nr2char(0) is a real NUL and terminates the
string, thus results in an empty string.
+nvim_...({...}) *nvim_...()* *eval-api*
+ Call nvim |api| functions. The type checking of arguments will
+ be stricter than for most other builtins. For instance,
+ if Integer is expected, a |Number| must be passed in, a
+ |String| will not be autoconverted.
+ Buffer numbers, as returned by |bufnr()| could be used as
+ first argument to nvim_buf_... functions. All functions
+ expecting an object (buffer, window or tabpage) can
+ also take the numerical value 0 to indicate the current
+ (focused) object.
+
or({expr}, {expr}) *or()*
Bitwise OR on the two arguments. The arguments are converted
to a number. A List, Dict or Float argument causes an error.
@@ -5470,14 +5481,20 @@ reltime([{start} [, {end}]]) *reltime()*
the item depends on the system. It can be passed to
|reltimestr()| to convert it to a string or |reltimefloat()|
to convert to a float.
- Without an argument it returns the current time.
- With one argument is returns the time passed since the time
+
+ Without an argument it returns the current "relative time", an
+ implementation-defined value meaningful only when used as an
+ argument to |reltime()|, |reltimestr()| and |reltimefloat()|.
+
+ With one argument it returns the time passed since the time
specified in the argument.
With two arguments it returns the time passed between {start}
and {end}.
The {start} and {end} arguments must be values returned by
reltime().
+ Note: |localtime()| returns the current (non-relative) time.
+
reltimefloat({time}) *reltimefloat()*
Return a Float that represents the time value of {time}.
Unit of time is seconds.
@@ -7218,6 +7235,10 @@ wildmenumode() *wildmenumode()*
(Note, this needs the 'wildcharm' option set appropriately).
+win_findbuf({bufnr}) *win_findbuf()*
+ Returns a list with window IDs for windows that contain buffer
+ {bufnr}. When there is none the list is empty.
+
win_getid([{win} [, {tab}]]) *win_getid()*
Get the window ID for the specified window.
When {win} is missing use the current window.
diff --git a/runtime/doc/filetype.txt b/runtime/doc/filetype.txt
index bbe2bbe50f..df6b55cfe7 100644
--- a/runtime/doc/filetype.txt
+++ b/runtime/doc/filetype.txt
@@ -529,14 +529,12 @@ Man {sect} {name}({sect}) Used during completion to show the real section of
when the provided section is a prefix, e.g. 1m vs 1.
Man {path} Open the manpage specified by path. Prepend "./" if
page is in the current directory.
+Man Open the manpage for the <cWORD> (man buffers)
+ or <cword> (non-man buffers) under the cursor.
|:Man| accepts command modifiers. For example, to use a vertical split: >
:vertical Man printf
-Global Mappings:
-<Plug>(Man) Jump to the manpage for the <cWORD> under the
- cursor. Takes a count for the section.
-
Local mappings:
K or CTRL-] Jump to the manpage for the <cWORD> under the
cursor. Takes a count for the section.
@@ -547,6 +545,9 @@ q :quit if invoked as $MANPAGER, otherwise :close.
Variables:
*g:no_man_maps* Do not create mappings in manpage buffers.
*g:ft_man_folding_enable* Fold manpages with foldmethod=indent foldnestmax=1.
+*b:man_default_sects* Comma-separated, ordered list of preferred sections.
+ For example in C one usually wants section 3 or 2: >
+ :let b:man_default_sections = '3,2'
PDF *ft-pdf-plugin*
diff --git a/runtime/doc/map.txt b/runtime/doc/map.txt
index c1eef398e2..4561020d22 100644
--- a/runtime/doc/map.txt
+++ b/runtime/doc/map.txt
@@ -1406,6 +1406,27 @@ The valid escape sequences are
<bang> (See the '-bang' attribute) Expands to a ! if the
command was executed with a ! modifier, otherwise
expands to nothing.
+ *<mods>*
+ <mods> The command modifiers, if specified. Otherwise, expands to
+ nothing. Supported modifiers are |aboveleft|, |belowright|,
+ |botright|, |browse|, |confirm|, |hide|, |keepalt|,
+ |keepjumps|, |keepmarks|, |keeppatterns|, |lockmarks|,
+ |noswapfile|, |silent|, |tab|, |topleft|, |verbose|, and
+ |vertical|.
+ Examples: >
+ command! -nargs=+ -complete=file MyEdit
+ \ for f in expand(<q-args>, 0, 1) |
+ \ exe '<mods> split ' . f |
+ \ endfor
+
+ function! SpecialEdit(files, mods)
+ for f in expand(a:files, 0, 1)
+ exe a:mods . ' split ' . f
+ endfor
+ endfunction
+ command! -nargs=+ -complete=file Sedit
+ \ call SpecialEdit(<q-args>, <q-mods>)
+<
*<reg>* *<register>*
<reg> (See the '-register' attribute) The optional register,
if specified. Otherwise, expands to nothing. <register>
diff --git a/runtime/doc/msgpack_rpc.txt b/runtime/doc/msgpack_rpc.txt
index 18c0ff8a58..b3fed9e756 100644
--- a/runtime/doc/msgpack_rpc.txt
+++ b/runtime/doc/msgpack_rpc.txt
@@ -11,6 +11,7 @@ RPC API for Nvim *RPC* *rpc* *msgpack-rpc*
3. Connecting |rpc-connecting|
4. Clients |rpc-api-client|
5. Types |rpc-types|
+6. Remote UIs |rpc-remote-ui|
==============================================================================
1. Introduction *rpc-intro*
@@ -46,7 +47,7 @@ instance.
There are three ways to obtain API metadata:
- 1. Connect to a running Nvim instance and call `vim_get_api_info` via
+ 1. Connect to a running Nvim instance and call `nvim_get_api_info` via
msgpack-rpc. This is best for clients written in dynamic languages which
can define functions at runtime.
@@ -104,7 +105,7 @@ Nvim instance:
require 'msgpack/rpc/transport/unix'
nvim = MessagePack::RPC::Client.new(MessagePack::RPC::UNIXTransport.new, ENV['NVIM_LISTEN_ADDRESS'])
- result = nvim.call(:vim_command, 'echo "hello world!"')
+ result = nvim.call(:nvim_command, 'echo "hello world!"')
<
A better way is to use the Python REPL with the `neovim` package, where API
functions can be called interactively:
@@ -116,24 +117,23 @@ functions can be called interactively:
You can also embed an Nvim instance via |jobstart()|, and communicate using
|rpcrequest()| and |rpcnotify()|:
>
- let vim = jobstart(['nvim', '--embed'], {'rpc': v:true})
- echo rpcrequest(vim, 'vim_eval', '"Hello " . "world!"')
- call jobstop(vim)
+ let nvim = jobstart(['nvim', '--embed'], {'rpc': v:true})
+ echo rpcrequest(nvim, 'nvim_eval', '"Hello " . "world!"')
+ call jobstop(nvim)
<
==============================================================================
4. Implementing API clients *rpc-api-client* *api-client*
-All external UIs and remote plugins (as opposed to regular Vim plugins) are
-"clients" in general; but we call something an "API client" if its purpose is
-to abstract or wrap the RPC API for the convenience of other applications
-(just like a REST client or SDK such as boto3 for AWS: you can speak AWS REST
-using an HTTP client like curl, but boto3 wraps that in a convenient python
-interface). For example, the lua-client is an API client:
- https://github.com/neovim/lua-client
-
-The Python client (pip package "neovim") is the reference implementation of an
-API client. It is always up-to-date with the Nvim API, so its source code and
-test suite are an authoritative reference.
+"API clients" wrap the Nvim API to provide idiomatic "SDKs" for their
+respective platforms (see |dev-jargon|). You can build a new API client for
+your favorite platform or programming language.
+
+Existing API clients are listed here:
+ https://github.com/neovim/neovim/wiki/Related-projects#api-clients
+
+The Python client is the reference implementation for API clients. It is
+always up-to-date with the Nvim API, so its source code and test suite are
+authoritative references.
https://github.com/neovim/python-client
API client implementation guidelines ~
@@ -176,15 +176,20 @@ contains information that makes this task easier (see also |rpc-types|):
- Container types may be decorated with type/size constraints, e.g.
ArrayOf(Buffer) or ArrayOf(Integer, 2). This can be useful to generate
even more strongly-typed APIs.
- - Methods that operate on instances of Nvim special types (msgpack EXT) are
- prefixed with the type name in lower case, e.g. `buffer_get_line`
- represents the `get_line` method of a Buffer instance.
- - Global methods are prefixed with `vim`, e.g. `vim_get_buffers`.
+ - Functions that are considered to be methods that operate on instances of
+ Nvim special types (msgpack EXT) will have the `"method"` attribute set to
+ `true`. The reciever type is the type of the first argument. The method
+ names are prefixed with `nvim_` plus a shortened type name, e.g.
+ `nvim_buf_get_lines` represents the `get_lines` method of a Buffer instance.
+ - Global functions have `"method"` set to `false` and are prefixed with just
+ `nvim_`, e.g. `nvim_get_buffers`.
So for an object-oriented language, an API client contains the classes
representing Nvim special types, and the methods of each class could be
-defined by inspecting the method name prefix. There could also be a singleton
-Vim class with methods mapped to functions prefixed with `vim_`.
+defined by stripping the prefix for the type as defined in the `types` metadata
+(this will always be the first two "_"-separated parts of the function name).
+There could also be a singleton Vim class with methods where the `nvim_`
+prefix is stripped off.
==============================================================================
5. Types *rpc-types*
@@ -218,18 +223,21 @@ an integer, but not a Window or Tabpage.
The most reliable way of determining the type codes for the special Nvim types
is to inspect the `types` key of metadata dictionary returned by the
-`vim_get_api_info` method at runtime. Here's a sample JSON representation of
+`nvim_get_api_info` method at runtime. Here's a sample JSON representation of
the `types` object:
>
"types": {
"Buffer": {
- "id": 0
+ "id": 0,
+ "prefix": "nvim_buf_"
},
"Window": {
- "id": 1
+ "id": 1,
+ "prefix": "nvim_win_"
},
"Tabpage": {
- "id": 2
+ "id": 2,
+ "prefix": "nvim_tabpage_"
}
}
<
@@ -238,4 +246,169 @@ the type codes, because a client may be built against one Nvim version but
connect to another with different type codes.
==============================================================================
+6. Remote UIs *rpc-remote-ui*
+
+Nvim allows Graphical user interfaces to be implemented by separate processes
+communicating with Nvim over the RPC API. Currently the ui model conists of a
+terminal-like grid with one single, monospace font size, with a few elements
+that could be drawn separately from the grid (for the momemnt only the popup
+menu)
+
+After connecting to a nvim instance (typically a spawned, embedded instance)
+use the |nvim_ui_attach|(width, height, options) API method to tell nvim that your
+program wants to draw the nvim screen on a grid with "width" times
+"height" cells. "options" should be a dictionary with the following (all
+optional) keys:
+ `rgb`: Controls what color format to use.
+ Set to true (default) to use 24-bit rgb
+ colors.
+ Set to false to use terminal color codes (at
+ most 256 different colors).
+ `popupmenu_external`: Instead of drawing the completion popupmenu on
+ the grid, Nvim will send higher-level events to
+ the ui and let it draw the popupmenu.
+ Defaults to false.
+
+Nvim will then send msgpack-rpc notifications, with the method name "redraw"
+and a single argument, an array of screen updates (described below).
+These should be processed in order. Preferably the user should only be able to
+see the screen state after all updates are processed (not any intermediate
+state after processing only a part of the array).
+
+Screen updates are arrays. The first element a string describing the kind
+of update.
+
+["resize", width, height]
+ The grid is resized to `width` and `height` cells.
+
+["clear"]
+ Clear the screen.
+
+["eol_clear"]
+ Clear from the cursor position to the end of the current line.
+
+["cursor_goto", row, col]
+ Move the cursor to position (row, col). Currently, the same cursor is
+ used to define the position for text insertion and the visible cursor.
+ However, only the last cursor position, after processing the entire
+ array in the "redraw" event, is intended to be a visible cursor
+ position.
+
+["update_fg", color]
+["update_bg", color]
+["update_sp", color]
+ Set the default foreground, background and special colors
+ respectively.
+
+["highlight_set", attrs]
+ Set the attributes that the next text put on the screen will have.
+ `attrs` is a dict with the keys below. Any absent key is reset
+ to its default value. Color defaults are set by the `update_fg` etc
+ updates. All boolean keys default to false.
+
+ `foreground`: foreground color.
+ `background`: backround color.
+ `special`: color to use for underline and undercurl, when present.
+ `reverse`: reverse video. Foreground and background colors are
+ switched.
+ `italic`: italic text.
+ `bold`: bold text.
+ `underline`: underlined text. The line has `special` color.
+ `undercurl`: undercurled text. The curl has `special` color.
+
+["put", text]
+ The (utf-8 encoded) string `text` is put at the cursor position
+ (and the cursor is advanced), with the highlights as set by the
+ last `highlight_set` update.
+
+["set_scroll_region", top, bot, left, right]
+ Define the scroll region used by `scroll` below.
+
+["scroll", count]
+ Scroll the text in the scroll region. The diagrams below illustrate
+ what will happen, depending on the scroll direction. "=" is used to
+ represent the SR(scroll region) boundaries and "-" the moved rectangles.
+ Note that dst and src share a common region.
+
+ If count is bigger than 0, move a rectangle in the SR up, this can
+ happen while scrolling down.
+>
+ +-------------------------+
+ | (clipped above SR) | ^
+ |=========================| dst_top |
+ | dst (still in SR) | |
+ +-------------------------+ src_top |
+ | src (moved up) and dst | |
+ |-------------------------| dst_bot |
+ | src (cleared) | |
+ +=========================+ src_bot
+<
+ If count is less than zero, move a rectangle in the SR down, this can
+ happen while scrolling up.
+>
+ +=========================+ src_top
+ | src (cleared) | |
+ |------------------------ | dst_top |
+ | src (moved down) and dst| |
+ +-------------------------+ src_bot |
+ | dst (still in SR) | |
+ |=========================| dst_bot |
+ | (clipped below SR) | v
+ +-------------------------+
+<
+["set_title", title]
+["set_icon", icon]
+ Set the window title, and icon (minimized) window title, respectively.
+ In windowing systems not distinguishing between the two, "set_icon"
+ can be ignored.
+
+["mouse_on"]
+["mouse_off"]
+ Tells the client whether mouse support, as determined by |'mouse'|
+ option, is considered to be active in the current mode. This is mostly
+ useful for a terminal frontend, or other situations where nvim mouse
+ would conflict with other usages of the mouse. It is safe for a client
+ to ignore this and always send mouse events.
+
+["busy_on"]
+["busy_off"]
+ Nvim started or stopped being busy, and possibly not responsible to user
+ input. This could be indicated to the user by hiding the cursor.
+
+["suspend"]
+ |:suspend| command or |Ctrl-Z| mapping is used. A terminal client (or other
+ client where it makes sense) could suspend itself. Other clients can
+ safely ignore it.
+
+["bell"]
+["visual_bell"]
+ Notify the user with an audible or visual bell, respectively.
+
+["update_menu"]
+ The menu mappings changed.
+
+["mode_change", mode]
+ The mode changed. Currently sent when "insert", "replace" and "normal"
+ modes are entered. A client could for instance change the cursor shape.
+
+["popupmenu_show", items, selected, row, col]
+ When `popupmenu_external` is set to true, nvim will not draw the
+ popupmenu on the grid, instead when the popupmenu is to be displayed
+ this update is sent. `items` is an array of the items to show, the
+ items are themselves arrays of the form [word, kind, menu, info]
+ as defined at |complete-items|, except that `word` is replaced by
+ `abbr` if present. `selected` is the initially selected item, either a
+ zero-based index into the array of items, or -1 if no item is
+ selected. `row` and `col` is the anchor position, where the first
+ character of the completed word will be.
+
+["popupmenu_select", selected]
+ An item in the currently displayed popupmenu is selected. `selected`
+ is either a zero-based index into the array of items from the last
+ `popupmenu_show` event, or -1 if no item is selected.
+
+["popupmenu_hide"]
+ The popupmenu is hidden.
+
+==============================================================================
vim:tw=78:ts=8:noet:ft=help:norl:
diff --git a/runtime/doc/quickfix.txt b/runtime/doc/quickfix.txt
index 3b54faf18e..e2a44541ae 100644
--- a/runtime/doc/quickfix.txt
+++ b/runtime/doc/quickfix.txt
@@ -1,4 +1,4 @@
-*quickfix.txt* For Vim version 7.4. Last change: 2016 Mar 19
+*quickfix.txt* For Vim version 7.4. Last change: 2016 Jul 01
VIM REFERENCE MANUAL by Bram Moolenaar
@@ -259,9 +259,23 @@ location list command, it will be aborted.
The 'switchbuf' settings are respected when jumping
to a buffer.
+:cl[ist] +{count} List the current and next {count} valid errors. This
+ is similar to ":clist from from+count", where "from"
+ is the current error position.
+
:cl[ist]! [from] [, [to]]
List all errors.
+:cl[ist]! +{count} List the current and next {count} error lines. This
+ is useful to see unrecognized lines after the current
+ one. For example, if ":clist" shows:
+ 8384 testje.java:252: error: cannot find symbol ~
+ Then using ":cl! +3" shows the reason:
+ 8384 testje.java:252: error: cannot find symbol ~
+ 8385: ZexitCode = Fmainx(); ~
+ 8386: ^ ~
+ 8387: symbol: method Fmainx() ~
+
*:lli* *:llist*
:lli[st] [from] [, [to]]
Same as ":clist", except the location list for the
@@ -306,7 +320,7 @@ EXECUTE A COMMAND IN ALL THE BUFFERS IN QUICKFIX OR LOCATION LIST:
etc.
< When the current file can't be |abandon|ed and the [!]
is not present, the command fails.
- When an error is detected excecution stops.
+ When an error is detected execution stops.
The last buffer (or where an error occurred) becomes
the current buffer.
{cmd} can contain '|' to concatenate several commands.
diff --git a/runtime/ftplugin/c.vim b/runtime/ftplugin/c.vim
index 487ce7a165..d1b2a4941e 100644
--- a/runtime/ftplugin/c.vim
+++ b/runtime/ftplugin/c.vim
@@ -55,5 +55,7 @@ if (has("gui_win32") || has("gui_gtk")) && !exists("b:browsefilter")
endif
endif
+let b:man_default_sects = '3,2'
+
let &cpo = s:cpo_save
unlet s:cpo_save
diff --git a/runtime/ftplugin/man.vim b/runtime/ftplugin/man.vim
index 6a9ad27956..02d2b4e557 100644
--- a/runtime/ftplugin/man.vim
+++ b/runtime/ftplugin/man.vim
@@ -19,7 +19,9 @@ if has('vim_starting')
endif
" This is not perfect. See `man glDrawArraysInstanced`. Since the title is
" all caps it is impossible to tell what the original capitilization was.
- execute 'file man://'.tolower(matchstr(getline(1), '^\S\+'))
+ let ref = tolower(matchstr(getline(1), '^\S\+'))
+ let b:man_sect = man#extract_sect_and_name_ref(ref)[0]
+ execute 'file man://'.ref
endif
setlocal buftype=nofile
@@ -41,8 +43,8 @@ setlocal nolist
setlocal nofoldenable
if !exists('g:no_plugin_maps') && !exists('g:no_man_maps')
- nmap <silent> <buffer> <C-]> <Plug>(Man)
- nmap <silent> <buffer> K <Plug>(Man)
+ nmap <silent> <buffer> <C-]> :Man<CR>
+ nmap <silent> <buffer> K :Man<CR>
nnoremap <silent> <buffer> <C-T> :call man#pop_tag()<CR>
if s:pager
nnoremap <silent> <buffer> <nowait> q :q<CR>
diff --git a/runtime/plugin/man.vim b/runtime/plugin/man.vim
index d49276047f..63faa15213 100644
--- a/runtime/plugin/man.vim
+++ b/runtime/plugin/man.vim
@@ -5,9 +5,7 @@ if exists('g:loaded_man')
endif
let g:loaded_man = 1
-command! -range=0 -complete=customlist,man#complete -nargs=+ Man call man#open_page(v:count, v:count1, <f-args>)
-
-nnoremap <silent> <Plug>(Man) :<C-U>call man#open_page(v:count, v:count1, &filetype ==# 'man' ? expand('<cWORD>') : expand('<cword>'))<CR>
+command! -range=0 -complete=customlist,man#complete -nargs=* Man call man#open_page(v:count, v:count1, <q-mods>, <f-args>)
augroup man
autocmd!
diff --git a/runtime/syntax/man.vim b/runtime/syntax/man.vim
index 5dd41b3af5..4a527dd350 100644
--- a/runtime/syntax/man.vim
+++ b/runtime/syntax/man.vim
@@ -7,10 +7,10 @@ endif
syntax case ignore
syntax match manReference display '[^()[:space:]]\+([0-9nx][a-z]*)'
-syntax match manSectionHeading display '^\%(\S.*\)\=\S$'
+syntax match manSectionHeading display '^\S.*$'
syntax match manTitle display '^\%1l.*$'
syntax match manSubHeading display '^ \{3\}\S.*$'
-syntax match manOptionDesc display '^\s\+\%(+\|--\=\)\S\+'
+syntax match manOptionDesc display '^\s\+\%(+\|-\)\S\+'
highlight default link manTitle Title
highlight default link manSectionHeading Statement
@@ -18,7 +18,7 @@ highlight default link manOptionDesc Constant
highlight default link manReference PreProc
highlight default link manSubHeading Function
-if getline(1) =~# '^[^()[:space:]]\+([23].*'
+if b:man_sect =~# '^[23]'
syntax include @c $VIMRUNTIME/syntax/c.vim
syntax match manCFuncDefinition display '\<\h\w*\>\ze\(\s\|\n\)*(' contained
syntax region manSynopsis start='^\%(
diff --git a/scripts/msgpack-gen.lua b/scripts/gendispatch.lua
index 2da3c174f9..40507d0afe 100644
--- a/scripts/msgpack-gen.lua
+++ b/scripts/gendispatch.lua
@@ -37,22 +37,31 @@ c_proto = Ct(
Cg(Cc(false), 'async') *
(fill * Cg((P('FUNC_API_ASYNC') * Cc(true)), 'async') ^ -1) *
(fill * Cg((P('FUNC_API_NOEXPORT') * Cc(true)), 'noexport') ^ -1) *
+ (fill * Cg((P('FUNC_API_NOEVAL') * Cc(true)), 'noeval') ^ -1) *
fill * P(';')
)
grammar = Ct((c_proto + c_comment + c_preproc + ws) ^ 1)
--- we need at least 2 arguments since the last one is the output file
-assert(#arg >= 1)
+-- we need at least 4 arguments since the last two are output files
+assert(#arg >= 3)
functions = {}
+local nvimsrcdir = arg[1]
+package.path = nvimsrcdir .. '/?.lua;' .. package.path
+
-- names of all headers relative to the source root (for inclusion in the
-- generated file)
headers = {}
--- output file(dispatch function + metadata serialized with msgpack)
-outputf = arg[#arg]
+-- output c file(dispatch function + metadata serialized with msgpack)
+outputf = arg[#arg-1]
+-- output mpack file (metadata)
+mpack_outputf = arg[#arg]
+
+-- set of function names, used to detect duplicates
+function_names = {}
-- read each input file, parse and append to the api metadata
-for i = 1, #arg - 1 do
+for i = 2, #arg - 2 do
local full_path = arg[i]
local parts = {}
for part in string.gmatch(full_path, '[^/]+') do
@@ -66,6 +75,7 @@ for i = 1, #arg - 1 do
local fn = tmp[i]
if not fn.noexport then
functions[#functions + 1] = tmp[i]
+ function_names[fn.name] = true
if #fn.parameters ~= 0 and fn.parameters[1][2] == 'channel_id' then
-- this function should receive the channel id
fn.receives_channel_id = true
@@ -84,6 +94,52 @@ for i = 1, #arg - 1 do
input:close()
end
+local function shallowcopy(orig)
+ local copy = {}
+ for orig_key, orig_value in pairs(orig) do
+ copy[orig_key] = orig_value
+ end
+ return copy
+end
+
+local function startswith(String,Start)
+ return string.sub(String,1,string.len(Start))==Start
+end
+
+-- Export functions under older deprecated names.
+-- These will be removed eventually.
+local deprecated_aliases = require("api.dispatch_deprecated")
+for i,f in ipairs(shallowcopy(functions)) do
+ local ismethod = false
+ if startswith(f.name, "nvim_buf_") then
+ ismethod = true
+ elseif startswith(f.name, "nvim_win_") then
+ ismethod = true
+ elseif startswith(f.name, "nvim_tabpage_") then
+ ismethod = true
+ elseif not startswith(f.name, "nvim_") then
+ f.noeval = true
+ f.deprecated_since = 1
+ end
+ f.method = ismethod
+ local newname = deprecated_aliases[f.name]
+ if newname ~= nil then
+ if function_names[newname] then
+ -- duplicate
+ print("Function "..f.name.." has deprecated alias\n"
+ ..newname.." which has a separate implementation.\n"..
+ "Please remove it from src/nvim/api/dispatch_deprecated.lua")
+ os.exit(1)
+ end
+ local newf = shallowcopy(f)
+ newf.name = newname
+ newf.impl_name = f.name
+ newf.noeval = true
+ newf.deprecated_since = 1
+ functions[#functions+1] = newf
+ end
+end
+
-- start building the output
output = io.open(outputf, 'wb')
@@ -99,7 +155,7 @@ output:write([[
#include "nvim/log.h"
#include "nvim/vim.h"
#include "nvim/msgpack_rpc/helpers.h"
-#include "nvim/msgpack_rpc/defs.h"
+#include "nvim/api/private/dispatch.h"
#include "nvim/api/private/helpers.h"
#include "nvim/api/private/defs.h"
]])
@@ -163,99 +219,95 @@ end
-- the real API.
for i = 1, #functions do
local fn = functions[i]
- local args = {}
-
- output:write('static Object handle_'..fn.name..'(uint64_t channel_id, uint64_t request_id, Array args, Error *error)')
- output:write('\n{')
- output:write('\n Object ret = NIL;')
- -- Declare/initialize variables that will hold converted arguments
- for j = 1, #fn.parameters do
- local param = fn.parameters[j]
- local converted = 'arg_'..j
- output:write('\n '..param[1]..' '..converted..' api_init_'..string.lower(real_type(param[1]))..';')
- end
- output:write('\n')
- output:write('\n if (args.size != '..#fn.parameters..') {')
- output:write('\n snprintf(error->msg, sizeof(error->msg), "Wrong number of arguments: expecting '..#fn.parameters..' but got %zu", args.size);')
- output:write('\n error->set = true;')
- output:write('\n goto cleanup;')
- output:write('\n }\n')
-
- -- Validation/conversion for each argument
- for j = 1, #fn.parameters do
- local converted, convert_arg, param, arg
- param = fn.parameters[j]
- converted = 'arg_'..j
- local rt = real_type(param[1])
- if rt ~= 'Object' then
- output:write('\n if (args.items['..(j - 1)..'].type == kObjectType'..rt..') {')
- output:write('\n '..converted..' = args.items['..(j - 1)..'].data.'..rt:lower()..';')
- if rt:match('^Buffer$') or rt:match('^Window$') or rt:match('^Tabpage$') or rt:match('^Boolean$') then
- -- accept positive integers for Buffers, Windows and Tabpages
- output:write('\n } else if (args.items['..(j - 1)..'].type == kObjectTypeInteger && args.items['..(j - 1)..'].data.integer > 0) {')
- output:write('\n '..converted..' = (unsigned)args.items['..(j - 1)..'].data.integer;')
- end
- output:write('\n } else {')
- output:write('\n snprintf(error->msg, sizeof(error->msg), "Wrong type for argument '..j..', expecting '..param[1]..'");')
- output:write('\n error->set = true;')
- output:write('\n goto cleanup;')
- output:write('\n }\n')
- else
- output:write('\n '..converted..' = args.items['..(j - 1)..'];\n')
+ if fn.impl_name == nil then
+ local args = {}
+
+ output:write('Object handle_'..fn.name..'(uint64_t channel_id, uint64_t request_id, Array args, Error *error)')
+ output:write('\n{')
+ output:write('\n Object ret = NIL;')
+ -- Declare/initialize variables that will hold converted arguments
+ for j = 1, #fn.parameters do
+ local param = fn.parameters[j]
+ local converted = 'arg_'..j
+ output:write('\n '..param[1]..' '..converted..';')
end
+ output:write('\n')
+ output:write('\n if (args.size != '..#fn.parameters..') {')
+ output:write('\n snprintf(error->msg, sizeof(error->msg), "Wrong number of arguments: expecting '..#fn.parameters..' but got %zu", args.size);')
+ output:write('\n error->set = true;')
+ output:write('\n goto cleanup;')
+ output:write('\n }\n')
- args[#args + 1] = converted
- end
+ -- Validation/conversion for each argument
+ for j = 1, #fn.parameters do
+ local converted, convert_arg, param, arg
+ param = fn.parameters[j]
+ converted = 'arg_'..j
+ local rt = real_type(param[1])
+ if rt ~= 'Object' then
+ output:write('\n if (args.items['..(j - 1)..'].type == kObjectType'..rt..') {')
+ output:write('\n '..converted..' = args.items['..(j - 1)..'].data.'..rt:lower()..';')
+ if rt:match('^Buffer$') or rt:match('^Window$') or rt:match('^Tabpage$') or rt:match('^Boolean$') then
+ -- accept nonnegative integers for Booleans, Buffers, Windows and Tabpages
+ output:write('\n } else if (args.items['..(j - 1)..'].type == kObjectTypeInteger && args.items['..(j - 1)..'].data.integer >= 0) {')
+ output:write('\n '..converted..' = (handle_T)args.items['..(j - 1)..'].data.integer;')
+ end
+ output:write('\n } else {')
+ output:write('\n snprintf(error->msg, sizeof(error->msg), "Wrong type for argument '..j..', expecting '..param[1]..'");')
+ output:write('\n error->set = true;')
+ output:write('\n goto cleanup;')
+ output:write('\n }\n')
+ else
+ output:write('\n '..converted..' = args.items['..(j - 1)..'];\n')
+ end
- -- function call
- local call_args = table.concat(args, ', ')
- output:write('\n ')
- if fn.return_type ~= 'void' then
- -- has a return value, prefix the call with a declaration
- output:write(fn.return_type..' rv = ')
- end
+ args[#args + 1] = converted
+ end
- -- write the function name and the opening parenthesis
- output:write(fn.name..'(')
+ -- function call
+ local call_args = table.concat(args, ', ')
+ output:write('\n ')
+ if fn.return_type ~= 'void' then
+ -- has a return value, prefix the call with a declaration
+ output:write(fn.return_type..' rv = ')
+ end
+
+ -- write the function name and the opening parenthesis
+ output:write(fn.name..'(')
- if fn.receives_channel_id then
- -- if the function receives the channel id, pass it as first argument
- if #args > 0 or fn.can_fail then
- output:write('channel_id, '..call_args)
+ if fn.receives_channel_id then
+ -- if the function receives the channel id, pass it as first argument
+ if #args > 0 or fn.can_fail then
+ output:write('channel_id, '..call_args)
+ else
+ output:write('channel_id')
+ end
else
- output:write('channel_id')
+ output:write(call_args)
end
- else
- output:write(call_args)
- end
- if fn.can_fail then
- -- if the function can fail, also pass a pointer to the local error object
- if #args > 0 then
- output:write(', error);\n')
+ if fn.can_fail then
+ -- if the function can fail, also pass a pointer to the local error object
+ if #args > 0 then
+ output:write(', error);\n')
+ else
+ output:write('error);\n')
+ end
+ -- and check for the error
+ output:write('\n if (error->set) {')
+ output:write('\n goto cleanup;')
+ output:write('\n }\n')
else
- output:write('error);\n')
+ output:write(');\n')
end
- -- and check for the error
- output:write('\n if (error->set) {')
- output:write('\n goto cleanup;')
- output:write('\n }\n')
- else
- output:write(');\n')
- end
- if fn.return_type ~= 'void' then
- output:write('\n ret = '..string.upper(real_type(fn.return_type))..'_OBJ(rv);')
- end
- -- Now generate the cleanup label for freeing memory allocated for the
- -- arguments
- output:write('\n\ncleanup:');
+ if fn.return_type ~= 'void' then
+ output:write('\n ret = '..string.upper(real_type(fn.return_type))..'_OBJ(rv);')
+ end
+ output:write('\n\ncleanup:');
- for j = 1, #fn.parameters do
- local param = fn.parameters[j]
- output:write('\n api_free_'..string.lower(real_type(param[1]))..'(arg_'..j..');')
+ output:write('\n return ret;\n}\n\n');
end
- output:write('\n return ret;\n}\n\n');
end
-- Generate a function that initializes method names with handler functions
@@ -281,7 +333,7 @@ for i = 1, #functions do
output:write(' msgpack_rpc_add_method_handler('..
'(String) {.data = "'..fn.name..'", '..
'.size = sizeof("'..fn.name..'") - 1}, '..
- '(MsgpackRpcRequestHandler) {.fn = handle_'.. fn.name..
+ '(MsgpackRpcRequestHandler) {.fn = handle_'.. (fn.impl_name or fn.name)..
', .async = '..tostring(fn.async)..'});\n')
if #fn.name > max_fname_len then
@@ -311,3 +363,7 @@ MsgpackRpcRequestHandler msgpack_rpc_get_handler_for(const char *name,
]])
output:close()
+
+mpack_output = io.open(mpack_outputf, 'wb')
+mpack_output:write(packed)
+mpack_output:close()
diff --git a/scripts/geneval.lua b/scripts/geneval.lua
new file mode 100644
index 0000000000..b1ba76296c
--- /dev/null
+++ b/scripts/geneval.lua
@@ -0,0 +1,66 @@
+mpack = require('mpack')
+
+local nvimsrcdir = arg[1]
+local autodir = arg[2]
+local metadata_file = arg[3]
+local funcs_file = arg[4]
+
+if nvimsrcdir == '--help' then
+ print([[
+Usage:
+ lua geneval.lua src/nvim build/src/nvim/auto
+
+Will generate build/src/nvim/auto/funcs.generated.h with definition of functions
+static const array.
+]])
+ os.exit(0)
+end
+
+package.path = nvimsrcdir .. '/?.lua;' .. package.path
+
+local funcsfname = autodir .. '/funcs.generated.h'
+
+local gperfpipe = io.open(funcsfname .. '.gperf', 'wb')
+
+local funcs = require('eval').funcs
+local metadata = mpack.unpack(io.open(arg[3], 'rb'):read("*all"))
+for i,fun in ipairs(metadata) do
+ if not fun.noeval then
+ funcs[fun.name] = {
+ args=#fun.parameters,
+ func='api_wrapper',
+ data='&handle_'..fun.name,
+ }
+ end
+end
+
+local funcsdata = io.open(funcs_file, 'w')
+funcsdata:write(mpack.pack(funcs))
+funcsdata:close()
+
+gperfpipe:write([[
+%language=ANSI-C
+%global-table
+%define initializer-suffix ,0,0,NULL,NULL
+%define word-array-name functions
+%define hash-function-name hash_internal_func_gperf
+%define lookup-function-name find_internal_func_gperf
+%omit-struct-type
+%struct-type
+VimLFuncDef;
+%%
+]])
+
+for name, def in pairs(funcs) do
+ args = def.args or 0
+ if type(args) == 'number' then
+ args = {args, args}
+ elseif #args == 1 then
+ args[2] = 'MAX_FUNC_ARGS'
+ end
+ func = def.func or ('f_' .. name)
+ data = def.data or "NULL"
+ gperfpipe:write(('%s, %s, %s, &%s, (FunPtr)%s\n')
+ :format(name, args[1], args[2], func, data))
+end
+gperfpipe:close()
diff --git a/scripts/genvimvim.lua b/scripts/genvimvim.lua
index 667af7be6c..24c147b811 100644
--- a/scripts/genvimvim.lua
+++ b/scripts/genvimvim.lua
@@ -1,3 +1,5 @@
+mpack = require('mpack')
+
if arg[1] == '--help' then
print('Usage: lua genvimvim.lua src/nvim runtime/syntax/vim/generated.vim')
os.exit(0)
@@ -5,6 +7,7 @@ end
local nvimsrcdir = arg[1]
local syntax_file = arg[2]
+local funcs_file = arg[3]
package.path = nvimsrcdir .. '/?.lua;' .. package.path
@@ -111,28 +114,16 @@ end
w('\n\nsyn case match')
local vimfun_start = 'syn keyword vimFuncName contained '
w('\n\n' .. vimfun_start)
-eval_fd = io.open(nvimsrcdir .. '/eval.c', 'r')
+funcs = mpack.unpack(io.open(funcs_file):read("*all"))
local started = 0
-for line in eval_fd:lines() do
- if line == '} functions[] =' then
- started = 1
- elseif started == 1 then
- assert (line == '{')
- started = 2
- elseif started == 2 then
- if line == '};' then
- break
- end
- local func_name = line:match('^ { "([%w_]+)",')
- if func_name then
- if lld.line_length > 850 then
- w('\n' .. vimfun_start)
- end
- w(' ' .. func_name)
+for name, def in pairs(funcs) do
+ if name then
+ if lld.line_length > 850 then
+ w('\n' .. vimfun_start)
end
+ w(' ' .. name)
end
end
-eval_fd:close()
w('\n')
syn_fd:close()
diff --git a/scripts/release.sh b/scripts/release.sh
index 9bd1b2b950..5a5b5a6498 100755
--- a/scripts/release.sh
+++ b/scripts/release.sh
@@ -17,16 +17,18 @@ set -e
set -u
set -o pipefail
+__sed=$( [ "$(uname)" = Darwin ] && echo 'sed -E' || echo 'sed -r' )
+
cd "$(git rev-parse --show-toplevel)"
__LAST_TAG=$(git describe --abbrev=0)
[ -z "$__LAST_TAG" ] && { echo 'ERROR: no tag found'; exit 1; }
__VERSION_MAJOR=$(grep 'set(NVIM_VERSION_MAJOR' CMakeLists.txt\
- |sed -r 's/.*NVIM_VERSION_MAJOR ([[:digit:]]).*/\1/')
+ |$__sed 's/.*NVIM_VERSION_MAJOR ([[:digit:]]).*/\1/')
__VERSION_MINOR=$(grep 'set(NVIM_VERSION_MINOR' CMakeLists.txt\
- |sed -r 's/.*NVIM_VERSION_MINOR ([[:digit:]]).*/\1/')
+ |$__sed 's/.*NVIM_VERSION_MINOR ([[:digit:]]).*/\1/')
__VERSION_PATCH=$(grep 'set(NVIM_VERSION_PATCH' CMakeLists.txt\
- |sed -r 's/.*NVIM_VERSION_PATCH ([[:digit:]]).*/\1/')
+ |$__sed 's/.*NVIM_VERSION_PATCH ([[:digit:]]).*/\1/')
__VERSION="${__VERSION_MAJOR}.${__VERSION_MINOR}.${__VERSION_PATCH}"
{ [ -z "$__VERSION_MAJOR" ] || [ -z "$__VERSION_MINOR" ] || [ -z "$__VERSION_PATCH" ]; } \
&& { echo "ERROR: version parse failed: '${__VERSION}'"; exit 1; }
@@ -43,16 +45,16 @@ __BUMP_MSG="version bump"
echo "Most recent tag: ${__LAST_TAG}"
echo "Release version: ${__VERSION}"
-sed -i -r 's/(NVIM_VERSION_PRERELEASE) "-dev"/\1 ""/' CMakeLists.txt
+$__sed -i.bk 's/(NVIM_VERSION_PRERELEASE) "-dev"/\1 ""/' CMakeLists.txt
echo "Building changelog since ${__LAST_TAG}..."
__CHANGELOG="$(./scripts/git-log-pretty-since.sh "$__LAST_TAG" 'vim-patch:\S')"
git add CMakeLists.txt
git commit --edit -m "${__RELEASE_MSG} ${__CHANGELOG}"
-git tag -a v"${__VERSION}" -m "NVIM v${__VERSION}"
+git tag --sign -a v"${__VERSION}" -m "NVIM v${__VERSION}"
-sed -i -r 's/(NVIM_VERSION_PRERELEASE) ""/\1 "-dev"/' CMakeLists.txt
-sed -i -r 's/set\((NVIM_VERSION_PATCH) [[:digit:]]/set(\1 ?/' CMakeLists.txt
+$__sed -i.bk 's/(NVIM_VERSION_PRERELEASE) ""/\1 "-dev"/' CMakeLists.txt
+$__sed -i.bk 's/set\((NVIM_VERSION_PATCH) [[:digit:]]/set(\1 ?/' CMakeLists.txt
nvim +'/NVIM_VERSION' +10new +'exe "norm! iUpdate version numbers!!!\<CR>"' \
+'norm! 10.' CMakeLists.txt
diff --git a/scripts/vim-patch.sh b/scripts/vim-patch.sh
index 9e28643d8e..a2750105c3 100755
--- a/scripts/vim-patch.sh
+++ b/scripts/vim-patch.sh
@@ -6,8 +6,8 @@ set -o pipefail
# Use privileged mode, which e.g. skips using CDPATH.
set -p
-readonly NEOVIM_SOURCE_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
-readonly VIM_SOURCE_DIR_DEFAULT="${NEOVIM_SOURCE_DIR}/.vim-src"
+readonly NVIM_SOURCE_DIR="${NVIM_SOURCE_DIR:-$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)}"
+readonly VIM_SOURCE_DIR_DEFAULT="${NVIM_SOURCE_DIR}/.vim-src"
readonly VIM_SOURCE_DIR="${VIM_SOURCE_DIR:-${VIM_SOURCE_DIR_DEFAULT}}"
readonly BASENAME="$(basename "${0}")"
readonly BRANCH_PREFIX="vim-"
@@ -124,6 +124,28 @@ assign_commit_details() {
patch_file="vim-${vim_version}.patch"
}
+# Patch surgery:
+preprocess_patch() {
+ local file="$1"
+ local nvim="nvim -u NORC -i NONE --headless"
+
+ # Remove *.proto, Make*, gui_*, some if_*
+ local na_src='proto\|Make*\|gui_*'
+ na_src="$na_src"'\|if_lua\|if_mzsch\|if_olepp\|if_ole\|if_perl\|if_py\|if_ruby\|if_tcl\|if_xcmdsrv'
+ 2>/dev/null $nvim --cmd 'set dir=/tmp' +'g@^diff --git a/src/\S*\<'${na_src}'@norm! d/\v(^diff)|%$ ' +w +q "$file"
+
+ # Remove todo.txt, version*.txt, tags
+ local na_doc='todo\.txt\|version\d\.txt\|tags'
+ 2>/dev/null $nvim --cmd 'set dir=/tmp' +'g@^diff --git a/runtime/doc/'${na_doc}'@norm! d/\v(^diff)|%$ ' +w +q "$file"
+
+ # Remove some testdir/Make_*.mak files
+ local na_src_testdir='Make_amiga.mak\|Make_dos.mak\|Make_ming.mak\|Make_vms.mms'
+ 2>/dev/null $nvim --cmd 'set dir=/tmp' +'g@^diff --git a/src/testdir/'${na_src_testdir}'@norm! d/\v(^diff)|%$ ' +w +q "$file"
+
+ # Rename src/ paths to src/nvim/
+ LC_ALL=C sed -e 's/\( [ab]\/src\)/\1\/nvim/g' "$file" > "$file".tmp && mv "$file".tmp "$file"
+}
+
get_vim_patch() {
get_vim_sources
@@ -133,17 +155,13 @@ get_vim_patch() {
>&2 echo "✘ Couldn't find Vim revision '${vim_commit}'."
exit 3
}
- echo
echo "✔ Found Vim revision '${vim_commit}'."
- # Patch surgery: preprocess the patch.
- # - transform src/ paths to src/nvim/
- local vim_full
- vim_full="$(git --no-pager show --color=never -1 --pretty=medium "${vim_commit}" \
- | LC_ALL=C sed -e 's/\( [ab]\/src\)/\1\/nvim/g')"
- local neovim_branch="${BRANCH_PREFIX}${vim_version}"
+ local patch_content
+ patch_content="$(git --no-pager show --color=never -1 --pretty=medium "${vim_commit}")"
+ local nvim_branch="${BRANCH_PREFIX}${vim_version}"
- cd "${NEOVIM_SOURCE_DIR}"
+ cd "${NVIM_SOURCE_DIR}"
local git_remote
git_remote="$(find_git_remote)"
local checked_out_branch
@@ -153,51 +171,48 @@ get_vim_patch() {
echo "✔ Current branch '${checked_out_branch}' seems to be a vim-patch"
echo " branch; not creating a new branch."
else
- echo
- echo "Fetching '${git_remote}/master'."
+ printf "\nFetching '${git_remote}/master'.\n"
output="$(git fetch "${git_remote}" master 2>&1)" &&
echo "✔ ${output}" ||
(echo "✘ ${output}"; false)
echo
- echo "Creating new branch '${neovim_branch}' based on '${git_remote}/master'."
- cd "${NEOVIM_SOURCE_DIR}"
- output="$(git checkout -b "${neovim_branch}" "${git_remote}/master" 2>&1)" &&
+ echo "Creating new branch '${nvim_branch}' based on '${git_remote}/master'."
+ cd "${NVIM_SOURCE_DIR}"
+ output="$(git checkout -b "${nvim_branch}" "${git_remote}/master" 2>&1)" &&
echo "✔ ${output}" ||
(echo "✘ ${output}"; false)
fi
- echo
- echo "Creating empty commit with correct commit message."
+ printf "\nCreating empty commit with correct commit message.\n"
output="$(commit_message | git commit --allow-empty --file 2>&1 -)" &&
echo "✔ ${output}" ||
(echo "✘ ${output}"; false)
- echo
- echo "Creating files."
- echo "${vim_full}" > "${NEOVIM_SOURCE_DIR}/${patch_file}"
- echo "✔ Saved full commit details to '${NEOVIM_SOURCE_DIR}/${patch_file}'."
+ printf "Creating patch...\n"
+ echo "$patch_content" > "${NVIM_SOURCE_DIR}/${patch_file}"
- echo
- echo "Instructions:"
- echo
- echo " Proceed to port the patch."
- echo " You might want to try 'patch -p1 < ${patch_file}' first."
- echo
- echo " If the patch contains a new test, consider porting it to Lua."
- echo " You might want to try 'scripts/legacy2luatest.pl'."
- echo
- echo " Stage your changes ('git add ...') and use 'git commit --amend' to commit."
- echo
- echo " To port additional patches related to ${vim_version} and add them to the current"
- echo " branch, call '${BASENAME} -p' again. Please use this only if it wouldn't make"
- echo " sense to send in each patch individually, as it will increase the size of the"
- echo " pull request and make it harder to review."
- echo
- echo " When you are finished, use '${BASENAME} -s' to submit a pull request."
- echo
- echo " See https://github.com/neovim/neovim/wiki/Merging-patches-from-upstream-vim"
- echo " for more information."
+ printf "Pre-processing patch...\n"
+ preprocess_patch "${NVIM_SOURCE_DIR}/${patch_file}"
+
+ printf "✔ Saved patch to '${NVIM_SOURCE_DIR}/${patch_file}'.\n"
+
+ printf "\nInstructions:
+ Proceed to port the patch. This may help:
+ patch -p1 < ${patch_file}
+
+ Stage your changes ('git add ...') and use 'git commit --amend' to commit.
+
+ To port additional patches related to ${vim_version} and add them to the
+ current branch, call '${BASENAME} -p' again.
+ * Do this only for _related_ patches (otherwise it increases the
+ size of the pull request, making it harder to review)
+
+ When you're done, try '${BASENAME} -s' to create the pull request.
+
+ See the wiki for more information:
+ * https://github.com/neovim/neovim/wiki/Merging-patches-from-upstream-vim
+ "
}
hub_pr() {
@@ -223,7 +238,7 @@ submit_pr() {
exit 1
fi
- cd "${NEOVIM_SOURCE_DIR}"
+ cd "${NVIM_SOURCE_DIR}"
local checked_out_branch
checked_out_branch="$(git rev-parse --abbrev-ref HEAD)"
if [[ "${checked_out_branch}" != ${BRANCH_PREFIX}* ]]; then
@@ -263,11 +278,11 @@ submit_pr() {
local patch_file
for patch_file in "${patches[@]}"; do
patch_file="vim-${patch_file}.patch"
- if [[ ! -f "${NEOVIM_SOURCE_DIR}/${patch_file}" ]]; then
+ if [[ ! -f "${NVIM_SOURCE_DIR}/${patch_file}" ]]; then
continue
fi
- rm -- "${NEOVIM_SOURCE_DIR}/${patch_file}"
- echo "✔ Removed '${NEOVIM_SOURCE_DIR}/${patch_file}'."
+ rm -- "${NVIM_SOURCE_DIR}/${patch_file}"
+ echo "✔ Removed '${NVIM_SOURCE_DIR}/${patch_file}'."
done
}
@@ -289,7 +304,7 @@ list_vim_patches() {
if [[ -n "${vim_tag}" ]]; then
local patch_number="${vim_tag:5}" # Remove prefix like "v7.4."
# Tagged Vim patch, check version.c:
- is_missing="$(sed -n '/static int included_patches/,/}/p' "${NEOVIM_SOURCE_DIR}/src/nvim/version.c" |
+ is_missing="$(sed -n '/static int included_patches/,/}/p' "${NVIM_SOURCE_DIR}/src/nvim/version.c" |
grep -x -e "[[:space:]]*//[[:space:]]${patch_number} NA.*" -e "[[:space:]]*${patch_number}," >/dev/null && echo "false" || echo "true")"
vim_commit="${vim_tag#v}"
if (cd "${VIM_SOURCE_DIR}" && git --no-pager show --color=never --name-only "v${vim_commit}" 2>/dev/null) | grep -q ^runtime; then
@@ -297,7 +312,7 @@ list_vim_patches() {
fi
else
# Untagged Vim patch (e.g. runtime updates), check the Neovim git log:
- is_missing="$(cd "${NEOVIM_SOURCE_DIR}" &&
+ is_missing="$(cd "${NVIM_SOURCE_DIR}" &&
git log -1 --no-merges --grep="vim\-patch:${vim_commit:0:7}" --pretty=format:false)"
fi
@@ -321,14 +336,14 @@ list_vim_patches() {
}
review_commit() {
- local neovim_commit_url="${1}"
- local neovim_patch_url="${neovim_commit_url}.patch"
+ local nvim_commit_url="${1}"
+ local nvim_patch_url="${nvim_commit_url}.patch"
local git_patch_prefix='Subject: \[PATCH\] '
- local neovim_patch
- neovim_patch="$(curl -Ssf "${neovim_patch_url}")"
+ local nvim_patch
+ nvim_patch="$(curl -Ssf "${nvim_patch_url}")"
local vim_version
- vim_version="$(head -n 4 <<< "${neovim_patch}" | sed -n "s/${git_patch_prefix}vim-patch:\([a-z0-9.]*\)$/\1/p")"
+ vim_version="$(head -n 4 <<< "${nvim_patch}" | sed -n "s/${git_patch_prefix}vim-patch:\([a-z0-9.]*\)$/\1/p")"
echo
if [[ -n "${vim_version}" ]]; then
@@ -349,7 +364,7 @@ review_commit() {
local message_length
message_length="$(wc -l <<< "${expected_commit_message}")"
local commit_message
- commit_message="$(tail -n +4 <<< "${neovim_patch}" | head -n "${message_length}")"
+ commit_message="$(tail -n +4 <<< "${nvim_patch}" | head -n "${message_length}")"
if [[ "${commit_message#${git_patch_prefix}}" == "${expected_commit_message}" ]]; then
echo "✔ Found expected commit message."
else
@@ -362,18 +377,18 @@ review_commit() {
echo
echo "Creating files."
- echo "${neovim_patch}" > "${NEOVIM_SOURCE_DIR}/n${patch_file}"
- echo "✔ Saved pull request diff to '${NEOVIM_SOURCE_DIR}/n${patch_file}'."
- CREATED_FILES+=("${NEOVIM_SOURCE_DIR}/n${patch_file}")
+ echo "${nvim_patch}" > "${NVIM_SOURCE_DIR}/n${patch_file}"
+ echo "✔ Saved pull request diff to '${NVIM_SOURCE_DIR}/n${patch_file}'."
+ CREATED_FILES+=("${NVIM_SOURCE_DIR}/n${patch_file}")
- curl -Ssfo "${NEOVIM_SOURCE_DIR}/${patch_file}" "${vim_patch_url}"
- echo "✔ Saved Vim diff to '${NEOVIM_SOURCE_DIR}/${patch_file}'."
- CREATED_FILES+=("${NEOVIM_SOURCE_DIR}/${patch_file}")
+ curl -Ssfo "${NVIM_SOURCE_DIR}/${patch_file}" "${vim_patch_url}"
+ echo "✔ Saved Vim diff to '${NVIM_SOURCE_DIR}/${patch_file}'."
+ CREATED_FILES+=("${NVIM_SOURCE_DIR}/${patch_file}")
echo
echo "Launching nvim."
- nvim -c "cd ${NEOVIM_SOURCE_DIR}" \
- -O "${NEOVIM_SOURCE_DIR}/${patch_file}" "${NEOVIM_SOURCE_DIR}/n${patch_file}"
+ nvim -c "cd ${NVIM_SOURCE_DIR}" \
+ -O "${NVIM_SOURCE_DIR}/${patch_file}" "${NVIM_SOURCE_DIR}/n${patch_file}"
}
review_pr() {
diff --git a/src/nvim/CMakeLists.txt b/src/nvim/CMakeLists.txt
index 5c4df1be0b..7c2c2feebc 100644
--- a/src/nvim/CMakeLists.txt
+++ b/src/nvim/CMakeLists.txt
@@ -11,22 +11,28 @@ endif()
endif()
set(GENERATED_DIR ${PROJECT_BINARY_DIR}/src/nvim/auto)
-set(DISPATCH_GENERATOR ${PROJECT_SOURCE_DIR}/scripts/msgpack-gen.lua)
+set(DISPATCH_GENERATOR ${PROJECT_SOURCE_DIR}/scripts/gendispatch.lua)
file(GLOB API_HEADERS api/*.h)
file(GLOB MSGPACK_RPC_HEADERS msgpack_rpc/*.h)
-set(MSGPACK_DISPATCH ${GENERATED_DIR}/msgpack_dispatch.c)
+set(API_METADATA ${PROJECT_BINARY_DIR}/api_metadata.mpack)
+set(FUNCS_DATA ${PROJECT_BINARY_DIR}/funcs_data.mpack)
set(HEADER_GENERATOR ${PROJECT_SOURCE_DIR}/scripts/gendeclarations.lua)
set(GENERATED_INCLUDES_DIR ${PROJECT_BINARY_DIR}/include)
+set(GENERATED_API_DISPATCH ${GENERATED_DIR}/api/private/dispatch.c)
set(GENERATED_EX_CMDS_ENUM ${GENERATED_INCLUDES_DIR}/ex_cmds_enum.generated.h)
set(GENERATED_EX_CMDS_DEFS ${GENERATED_DIR}/ex_cmds_defs.generated.h)
+set(GENERATED_FUNCS_HASH_INPUT ${GENERATED_DIR}/funcs.generated.h.gperf)
+set(GENERATED_FUNCS ${GENERATED_DIR}/funcs.generated.h)
set(GENERATED_EVENTS_ENUM ${GENERATED_INCLUDES_DIR}/auevents_enum.generated.h)
set(GENERATED_EVENTS_NAMES_MAP ${GENERATED_DIR}/auevents_name_map.generated.h)
set(GENERATED_OPTIONS ${GENERATED_DIR}/options.generated.h)
set(EX_CMDS_GENERATOR ${PROJECT_SOURCE_DIR}/scripts/genex_cmds.lua)
+set(FUNCS_GENERATOR ${PROJECT_SOURCE_DIR}/scripts/geneval.lua)
set(EVENTS_GENERATOR ${PROJECT_SOURCE_DIR}/scripts/gen_events.lua)
set(OPTIONS_GENERATOR ${PROJECT_SOURCE_DIR}/scripts/genoptions.lua)
set(EVENTS_LIST_FILE ${PROJECT_SOURCE_DIR}/src/nvim/auevents.lua)
set(EX_CMDS_DEFS_FILE ${PROJECT_SOURCE_DIR}/src/nvim/ex_cmds.lua)
+set(EVAL_DEFS_FILE ${PROJECT_SOURCE_DIR}/src/nvim/eval.lua)
set(OPTIONS_LIST_FILE ${PROJECT_SOURCE_DIR}/src/nvim/options.lua)
set(UNICODE_TABLES_GENERATOR ${PROJECT_SOURCE_DIR}/scripts/genunicodetables.lua)
set(UNICODE_DIR ${PROJECT_SOURCE_DIR}/unicode)
@@ -36,6 +42,7 @@ set(EASTASIANWIDTH_FILE ${UNICODE_DIR}/EastAsianWidth.txt)
set(GENERATED_UNICODE_TABLES ${GENERATED_DIR}/unicode_tables.generated.h)
include_directories(${GENERATED_DIR})
+include_directories(${CACHED_GENERATED_DIR})
include_directories(${GENERATED_INCLUDES_DIR})
file(MAKE_DIRECTORY ${GENERATED_DIR})
@@ -82,7 +89,7 @@ endforeach()
list(REMOVE_ITEM NEOVIM_SOURCES ${to_remove})
-# Handle legacy files that don't yet pass -Wconversion.
+# Legacy files that do not yet pass -Wconversion.
set(CONV_SOURCES
buffer.c
diff.c
@@ -112,6 +119,15 @@ endforeach()
if(NOT MSVC)
set_source_files_properties(
${CONV_SOURCES} PROPERTIES COMPILE_FLAGS "${COMPILE_FLAGS} -Wno-conversion")
+ # gperf generates ANSI-C with incorrect linkage, ignore it.
+ check_c_compiler_flag(-Wno-static-in-inline HAS_WNO_STATIC_IN_INLINE_FLAG)
+ if(HAS_WNO_STATIC_IN_INLINE_FLAG)
+ set_source_files_properties(
+ eval.c PROPERTIES COMPILE_FLAGS "${COMPILE_FLAGS} -Wno-static-in-inline -Wno-conversion")
+ else()
+ set_source_files_properties(
+ eval.c PROPERTIES COMPILE_FLAGS "${COMPILE_FLAGS} -Wno-conversion")
+ endif()
endif()
if(DEFINED MIN_LOG_LEVEL)
@@ -138,9 +154,13 @@ separate_arguments(C_FLAGS_${build_type}_ARRAY UNIX_COMMAND ${CMAKE_C_FLAGS_${bu
set(gen_cflags ${gen_cflags} ${C_FLAGS_${build_type}_ARRAY} ${C_FLAGS_ARRAY})
foreach(sfile ${NEOVIM_SOURCES}
- "${PROJECT_SOURCE_DIR}/src/nvim/regexp_nfa.c")
+ "${PROJECT_SOURCE_DIR}/src/nvim/regexp_nfa.c"
+ ${GENERATED_API_DISPATCH})
get_filename_component(full_d ${sfile} PATH)
file(RELATIVE_PATH d "${PROJECT_SOURCE_DIR}/src/nvim" "${full_d}")
+ if(${d} MATCHES "^[.][.]")
+ file(RELATIVE_PATH d "${GENERATED_DIR}" "${full_d}")
+ endif()
get_filename_component(f ${sfile} NAME)
get_filename_component(r ${sfile} NAME_WE)
if(NOT ${d} EQUAL ".")
@@ -183,17 +203,18 @@ add_custom_command(OUTPUT ${GENERATED_UNICODE_TABLES}
${EASTASIANWIDTH_FILE}
)
-add_custom_command(OUTPUT ${MSGPACK_DISPATCH}
- COMMAND ${LUA_PRG} ${DISPATCH_GENERATOR} ${API_HEADERS} ${MSGPACK_DISPATCH}
+add_custom_command(OUTPUT ${GENERATED_API_DISPATCH} ${API_METADATA}
+ COMMAND ${LUA_PRG} ${DISPATCH_GENERATOR} ${CMAKE_CURRENT_LIST_DIR} ${API_HEADERS} ${GENERATED_API_DISPATCH} ${API_METADATA}
DEPENDS
${API_HEADERS}
${MSGPACK_RPC_HEADERS}
${DISPATCH_GENERATOR}
+ ${CMAKE_CURRENT_LIST_DIR}/api/dispatch_deprecated.lua
)
list(APPEND NEOVIM_GENERATED_SOURCES
"${PROJECT_BINARY_DIR}/config/auto/pathdef.c"
- "${MSGPACK_DISPATCH}"
+ "${GENERATED_API_DISPATCH}"
"${GENERATED_EX_CMDS_ENUM}"
"${GENERATED_EX_CMDS_DEFS}"
"${GENERATED_EVENTS_ENUM}"
@@ -208,6 +229,19 @@ add_custom_command(OUTPUT ${GENERATED_EX_CMDS_ENUM} ${GENERATED_EX_CMDS_DEFS}
DEPENDS ${EX_CMDS_GENERATOR} ${EX_CMDS_DEFS_FILE}
)
+if(NOT GPERF_PRG)
+ message(FATAL_ERROR "gperf was not found.")
+endif()
+add_custom_command(OUTPUT ${GENERATED_FUNCS} ${FUNCS_DATA}
+ COMMAND ${LUA_PRG} ${FUNCS_GENERATOR}
+ ${PROJECT_SOURCE_DIR}/src/nvim ${GENERATED_DIR} ${API_METADATA} ${FUNCS_DATA}
+ COMMAND ${GPERF_PRG}
+ ${GENERATED_FUNCS_HASH_INPUT} --output-file=${GENERATED_FUNCS}
+ DEPENDS ${FUNCS_GENERATOR} ${EVAL_DEFS_FILE} ${API_METADATA}
+)
+list(APPEND NEOVIM_GENERATED_SOURCES
+ "${GENERATED_FUNCS}")
+
add_custom_command(OUTPUT ${GENERATED_EVENTS_ENUM} ${GENERATED_EVENTS_NAMES_MAP}
COMMAND ${LUA_PRG} ${EVENTS_GENERATOR}
${PROJECT_SOURCE_DIR}/src/nvim ${GENERATED_EVENTS_ENUM} ${GENERATED_EVENTS_NAMES_MAP}
diff --git a/src/nvim/api/buffer.c b/src/nvim/api/buffer.c
index c3bc1f52af..c4415ddf94 100644
--- a/src/nvim/api/buffer.c
+++ b/src/nvim/api/buffer.c
@@ -14,7 +14,6 @@
#include "nvim/memline.h"
#include "nvim/memory.h"
#include "nvim/misc1.h"
-#include "nvim/misc2.h"
#include "nvim/ex_cmds.h"
#include "nvim/mark.h"
#include "nvim/fileio.h"
@@ -32,7 +31,7 @@
/// @param buffer The buffer handle
/// @param[out] err Details of an error that may have occurred
/// @return The line count
-Integer buffer_line_count(Buffer buffer, Error *err)
+Integer nvim_buf_line_count(Buffer buffer, Error *err)
{
buf_T *buf = find_buffer_by_handle(buffer, err);
@@ -45,11 +44,11 @@ Integer buffer_line_count(Buffer buffer, Error *err)
/// Gets a buffer line
///
-/// @deprecated use buffer_get_lines instead.
+/// @deprecated use nvim_buf_get_lines instead.
/// for positive indices (including 0) use
-/// "buffer_get_lines(buffer, index, index+1, true)"
+/// "nvim_buf_get_lines(buffer, index, index+1, true)"
/// for negative indices use
-/// "buffer_get_lines(buffer, index-1, index, true)"
+/// "nvim_buf_get_lines(buffer, index-1, index, true)"
///
/// @param buffer The buffer handle
/// @param index The line index
@@ -60,7 +59,7 @@ String buffer_get_line(Buffer buffer, Integer index, Error *err)
String rv = { .size = 0 };
index = convert_index(index);
- Array slice = buffer_get_lines(buffer, index, index+1, true, err);
+ Array slice = nvim_buf_get_lines(0, buffer, index, index+1, true, err);
if (!err->set && slice.size) {
rv = slice.items[0].data.string;
@@ -73,11 +72,11 @@ String buffer_get_line(Buffer buffer, Integer index, Error *err)
/// Sets a buffer line
///
-/// @deprecated use buffer_set_lines instead.
+/// @deprecated use nvim_buf_set_lines instead.
/// for positive indices use
-/// "buffer_set_lines(buffer, index, index+1, true, [line])"
+/// "nvim_buf_set_lines(buffer, index, index+1, true, [line])"
/// for negative indices use
-/// "buffer_set_lines(buffer, index-1, index, true, [line])"
+/// "nvim_buf_set_lines(buffer, index-1, index, true, [line])"
///
/// @param buffer The buffer handle
/// @param index The line index
@@ -88,16 +87,16 @@ void buffer_set_line(Buffer buffer, Integer index, String line, Error *err)
Object l = STRING_OBJ(line);
Array array = { .items = &l, .size = 1 };
index = convert_index(index);
- buffer_set_lines(buffer, index, index+1, true, array, err);
+ nvim_buf_set_lines(0, buffer, index, index+1, true, array, err);
}
/// Deletes a buffer line
///
-/// @deprecated use buffer_set_lines instead.
+/// @deprecated use nvim_buf_set_lines instead.
/// for positive indices use
-/// "buffer_set_lines(buffer, index, index+1, true, [])"
+/// "nvim_buf_set_lines(buffer, index, index+1, true, [])"
/// for negative indices use
-/// "buffer_set_lines(buffer, index-1, index, true, [])"
+/// "nvim_buf_set_lines(buffer, index-1, index, true, [])"
/// @param buffer The buffer handle
/// @param index The line index
/// @param[out] err Details of an error that may have occurred
@@ -105,12 +104,12 @@ void buffer_del_line(Buffer buffer, Integer index, Error *err)
{
Array array = ARRAY_DICT_INIT;
index = convert_index(index);
- buffer_set_lines(buffer, index, index+1, true, array, err);
+ nvim_buf_set_lines(0, buffer, index, index+1, true, array, err);
}
/// Retrieves a line range from the buffer
///
-/// @deprecated use buffer_get_lines(buffer, newstart, newend, false)
+/// @deprecated use nvim_buf_get_lines(buffer, newstart, newend, false)
/// where newstart = start + int(not include_start) - int(start < 0)
/// newend = end + int(include_end) - int(end < 0)
/// int(bool) = 1 if bool is true else 0
@@ -122,15 +121,15 @@ void buffer_del_line(Buffer buffer, Integer index, Error *err)
/// @param[out] err Details of an error that may have occurred
/// @return An array of lines
ArrayOf(String) buffer_get_line_slice(Buffer buffer,
- Integer start,
- Integer end,
- Boolean include_start,
- Boolean include_end,
- Error *err)
+ Integer start,
+ Integer end,
+ Boolean include_start,
+ Boolean include_end,
+ Error *err)
{
start = convert_index(start) + !include_start;
end = convert_index(end) + include_end;
- return buffer_get_lines(buffer, start , end, false, err);
+ return nvim_buf_get_lines(0, buffer, start , end, false, err);
}
@@ -149,11 +148,12 @@ ArrayOf(String) buffer_get_line_slice(Buffer buffer,
/// @param strict_indexing whether out-of-bounds should be an error.
/// @param[out] err Details of an error that may have occurred
/// @return An array of lines
-ArrayOf(String) buffer_get_lines(Buffer buffer,
- Integer start,
- Integer end,
- Boolean strict_indexing,
- Error *err)
+ArrayOf(String) nvim_buf_get_lines(uint64_t channel_id,
+ Buffer buffer,
+ Integer start,
+ Integer end,
+ Boolean strict_indexing,
+ Error *err)
{
Array rv = ARRAY_DICT_INIT;
buf_T *buf = find_buffer_by_handle(buffer, err);
@@ -191,7 +191,9 @@ ArrayOf(String) buffer_get_lines(Buffer buffer,
Object str = STRING_OBJ(cstr_to_string(bufstr));
// Vim represents NULs as NLs, but this may confuse clients.
- strchrsub(str.data.string.data, '\n', '\0');
+ if (channel_id != INVALID_CHANNEL) {
+ strchrsub(str.data.string.data, '\n', '\0');
+ }
rv.items[i] = str;
}
@@ -212,7 +214,7 @@ end:
/// Replaces a line range on the buffer
///
-/// @deprecated use buffer_set_lines(buffer, newstart, newend, false, lines)
+/// @deprecated use nvim_buf_set_lines(buffer, newstart, newend, false, lines)
/// where newstart = start + int(not include_start) + int(start < 0)
/// newend = end + int(include_end) + int(end < 0)
/// int(bool) = 1 if bool is true else 0
@@ -226,16 +228,16 @@ end:
// array will simply delete the line range)
/// @param[out] err Details of an error that may have occurred
void buffer_set_line_slice(Buffer buffer,
- Integer start,
- Integer end,
- Boolean include_start,
- Boolean include_end,
- ArrayOf(String) replacement,
- Error *err)
+ Integer start,
+ Integer end,
+ Boolean include_start,
+ Boolean include_end,
+ ArrayOf(String) replacement, // NOLINT
+ Error *err)
{
start = convert_index(start) + !include_start;
end = convert_index(end) + include_end;
- buffer_set_lines(buffer, start, end, false, replacement, err);
+ nvim_buf_set_lines(0, buffer, start, end, false, replacement, err);
}
@@ -257,12 +259,13 @@ void buffer_set_line_slice(Buffer buffer,
/// @param strict_indexing whether out-of-bounds should be an error.
/// @param replacement An array of lines to use as replacement
/// @param[out] err Details of an error that may have occurred
-void buffer_set_lines(Buffer buffer,
- Integer start,
- Integer end,
- Boolean strict_indexing,
- ArrayOf(String) replacement,
- Error *err)
+void nvim_buf_set_lines(uint64_t channel_id,
+ Buffer buffer,
+ Integer start,
+ Integer end,
+ Boolean strict_indexing,
+ ArrayOf(String) replacement, // NOLINT
+ Error *err)
{
buf_T *buf = find_buffer_by_handle(buffer, err);
@@ -309,7 +312,7 @@ void buffer_set_lines(Buffer buffer,
// line and convert NULs to newlines to avoid truncation.
lines[i] = xmallocz(l.size);
for (size_t j = 0; j < l.size; j++) {
- if (l.data[j] == '\n') {
+ if (l.data[j] == '\n' && channel_id != INVALID_CHANNEL) {
api_set_error(err, Exception, _("string cannot contain newlines"));
new_len = i + 1;
goto end;
@@ -412,7 +415,7 @@ end:
/// @param name The variable name
/// @param[out] err Details of an error that may have occurred
/// @return The variable value
-Object buffer_get_var(Buffer buffer, String name, Error *err)
+Object nvim_buf_get_var(Buffer buffer, String name, Error *err)
{
buf_T *buf = find_buffer_by_handle(buffer, err);
@@ -429,6 +432,41 @@ Object buffer_get_var(Buffer buffer, String name, Error *err)
/// @param name The variable name
/// @param value The variable value
/// @param[out] err Details of an error that may have occurred
+void nvim_buf_set_var(Buffer buffer, String name, Object value, Error *err)
+{
+ buf_T *buf = find_buffer_by_handle(buffer, err);
+
+ if (!buf) {
+ return;
+ }
+
+ dict_set_value(buf->b_vars, name, value, false, false, err);
+}
+
+/// Removes a buffer-scoped (b:) variable
+///
+/// @param buffer The buffer handle
+/// @param name The variable name
+/// @param[out] err Details of an error that may have occurred
+void nvim_buf_del_var(Buffer buffer, String name, Error *err)
+{
+ buf_T *buf = find_buffer_by_handle(buffer, err);
+
+ if (!buf) {
+ return;
+ }
+
+ dict_set_value(buf->b_vars, name, NIL, true, false, err);
+}
+
+/// Sets a buffer-scoped (b:) variable
+///
+/// @deprecated
+///
+/// @param buffer The buffer handle
+/// @param name The variable name
+/// @param value The variable value
+/// @param[out] err Details of an error that may have occurred
/// @return The old value or nil if there was no previous value.
///
/// @warning It may return nil if there was no previous value
@@ -441,18 +479,17 @@ Object buffer_set_var(Buffer buffer, String name, Object value, Error *err)
return (Object) OBJECT_INIT;
}
- return dict_set_value(buf->b_vars, name, value, false, err);
+ return dict_set_value(buf->b_vars, name, value, false, true, err);
}
/// Removes a buffer-scoped (b:) variable
///
+/// @deprecated
+///
/// @param buffer The buffer handle
/// @param name The variable name
/// @param[out] err Details of an error that may have occurred
-/// @return The old value or nil if there was no previous value.
-///
-/// @warning It may return nil if there was no previous value
-/// or if previous value was `v:null`.
+/// @return The old value
Object buffer_del_var(Buffer buffer, String name, Error *err)
{
buf_T *buf = find_buffer_by_handle(buffer, err);
@@ -461,16 +498,17 @@ Object buffer_del_var(Buffer buffer, String name, Error *err)
return (Object) OBJECT_INIT;
}
- return dict_set_value(buf->b_vars, name, NIL, true, err);
+ return dict_set_value(buf->b_vars, name, NIL, true, true, err);
}
+
/// Gets a buffer option value
///
/// @param buffer The buffer handle
/// @param name The option name
/// @param[out] err Details of an error that may have occurred
/// @return The option value
-Object buffer_get_option(Buffer buffer, String name, Error *err)
+Object nvim_buf_get_option(Buffer buffer, String name, Error *err)
{
buf_T *buf = find_buffer_by_handle(buffer, err);
@@ -488,7 +526,7 @@ Object buffer_get_option(Buffer buffer, String name, Error *err)
/// @param name The option name
/// @param value The option value
/// @param[out] err Details of an error that may have occurred
-void buffer_set_option(Buffer buffer, String name, Object value, Error *err)
+void nvim_buf_set_option(Buffer buffer, String name, Object value, Error *err)
{
buf_T *buf = find_buffer_by_handle(buffer, err);
@@ -504,7 +542,7 @@ void buffer_set_option(Buffer buffer, String name, Object value, Error *err)
/// @param buffer The buffer handle
/// @param[out] err Details of an error that may have occurred
/// @return The buffer number
-Integer buffer_get_number(Buffer buffer, Error *err)
+Integer nvim_buf_get_number(Buffer buffer, Error *err)
{
Integer rv = 0;
buf_T *buf = find_buffer_by_handle(buffer, err);
@@ -521,7 +559,7 @@ Integer buffer_get_number(Buffer buffer, Error *err)
/// @param buffer The buffer handle
/// @param[out] err Details of an error that may have occurred
/// @return The buffer name
-String buffer_get_name(Buffer buffer, Error *err)
+String nvim_buf_get_name(Buffer buffer, Error *err)
{
String rv = STRING_INIT;
buf_T *buf = find_buffer_by_handle(buffer, err);
@@ -538,7 +576,7 @@ String buffer_get_name(Buffer buffer, Error *err)
/// @param buffer The buffer handle
/// @param name The buffer name
/// @param[out] err Details of an error that may have occurred
-void buffer_set_name(Buffer buffer, String name, Error *err)
+void nvim_buf_set_name(Buffer buffer, String name, Error *err)
{
buf_T *buf = find_buffer_by_handle(buffer, err);
@@ -567,7 +605,7 @@ void buffer_set_name(Buffer buffer, String name, Error *err)
///
/// @param buffer The buffer handle
/// @return true if the buffer is valid, false otherwise
-Boolean buffer_is_valid(Buffer buffer)
+Boolean nvim_buf_is_valid(Buffer buffer)
{
Error stub = ERROR_INIT;
return find_buffer_by_handle(buffer, &stub) != NULL;
@@ -575,7 +613,7 @@ Boolean buffer_is_valid(Buffer buffer)
/// Inserts a sequence of lines to a buffer at a certain index
///
-/// @deprecated use buffer_set_lines(buffer, lnum, lnum, true, lines)
+/// @deprecated use nvim_buf_set_lines(buffer, lnum, lnum, true, lines)
///
/// @param buffer The buffer handle
/// @param lnum Insert the lines after `lnum`. If negative, it will append
@@ -589,7 +627,7 @@ void buffer_insert(Buffer buffer,
{
// "lnum" will be the index of the line after inserting,
// no matter if it is negative or not
- buffer_set_lines(buffer, lnum, lnum, true, lines, err);
+ nvim_buf_set_lines(0, buffer, lnum, lnum, true, lines, err);
}
/// Return a tuple (row,col) representing the position of the named mark
@@ -598,7 +636,7 @@ void buffer_insert(Buffer buffer,
/// @param name The mark's name
/// @param[out] err Details of an error that may have occurred
/// @return The (row, col) tuple
-ArrayOf(Integer, 2) buffer_get_mark(Buffer buffer, String name, Error *err)
+ArrayOf(Integer, 2) nvim_buf_get_mark(Buffer buffer, String name, Error *err)
{
Array rv = ARRAY_DICT_INIT;
buf_T *buf = find_buffer_by_handle(buffer, err);
@@ -648,7 +686,7 @@ ArrayOf(Integer, 2) buffer_get_mark(Buffer buffer, String name, Error *err)
/// called with src_id = 0, an unique source id is generated and returned.
/// Succesive calls can pass in it as "src_id" to add new highlights to the same
/// source group. All highlights in the same group can then be cleared with
-/// buffer_clear_highlight. If the highlight never will be manually deleted
+/// nvim_buf_clear_highlight. If the highlight never will be manually deleted
/// pass in -1 for "src_id".
///
/// If "hl_group" is the empty string no highlight is added, but a new src_id
@@ -666,13 +704,13 @@ ArrayOf(Integer, 2) buffer_get_mark(Buffer buffer, String name, Error *err)
/// or -1 to highlight to end of line
/// @param[out] err Details of an error that may have occurred
/// @return The src_id that was used
-Integer buffer_add_highlight(Buffer buffer,
- Integer src_id,
- String hl_group,
- Integer line,
- Integer col_start,
- Integer col_end,
- Error *err)
+Integer nvim_buf_add_highlight(Buffer buffer,
+ Integer src_id,
+ String hl_group,
+ Integer line,
+ Integer col_start,
+ Integer col_end,
+ Error *err)
{
buf_T *buf = find_buffer_by_handle(buffer, err);
if (!buf) {
@@ -708,11 +746,11 @@ Integer buffer_add_highlight(Buffer buffer,
/// @param line_end End of range of lines to clear (exclusive)
/// or -1 to clear to end of file.
/// @param[out] err Details of an error that may have occurred
-void buffer_clear_highlight(Buffer buffer,
- Integer src_id,
- Integer line_start,
- Integer line_end,
- Error *err)
+void nvim_buf_clear_highlight(Buffer buffer,
+ Integer src_id,
+ Integer line_start,
+ Integer line_end,
+ Error *err)
{
buf_T *buf = find_buffer_by_handle(buffer, err);
if (!buf) {
diff --git a/src/nvim/api/dispatch_deprecated.lua b/src/nvim/api/dispatch_deprecated.lua
new file mode 100644
index 0000000000..5650a77ac0
--- /dev/null
+++ b/src/nvim/api/dispatch_deprecated.lua
@@ -0,0 +1,69 @@
+local deprecated_aliases = {
+ nvim_buf_add_highlight="buffer_add_highlight",
+ nvim_buf_clear_highlight="buffer_clear_highlight",
+ nvim_buf_get_lines="buffer_get_lines",
+ nvim_buf_get_mark="buffer_get_mark",
+ nvim_buf_get_name="buffer_get_name",
+ nvim_buf_get_number="buffer_get_number",
+ nvim_buf_get_option="buffer_get_option",
+ nvim_buf_get_var="buffer_get_var",
+ nvim_buf_is_valid="buffer_is_valid",
+ nvim_buf_line_count="buffer_line_count",
+ nvim_buf_set_lines="buffer_set_lines",
+ nvim_buf_set_name="buffer_set_name",
+ nvim_buf_set_option="buffer_set_option",
+ nvim_call_function="vim_call_function",
+ nvim_command="vim_command",
+ nvim_command_output="vim_command_output",
+ nvim_del_current_line="vim_del_current_line",
+ nvim_err_write="vim_err_write",
+ nvim_err_writeln="vim_report_error",
+ nvim_eval="vim_eval",
+ nvim_feedkeys="vim_feedkeys",
+ nvim_get_api_info="vim_get_api_info",
+ nvim_get_color_by_name="vim_name_to_color",
+ nvim_get_color_map="vim_get_color_map",
+ nvim_get_current_buf="vim_get_current_buffer",
+ nvim_get_current_line="vim_get_current_line",
+ nvim_get_current_tabpage="vim_get_current_tabpage",
+ nvim_get_current_win="vim_get_current_window",
+ nvim_get_option="vim_get_option",
+ nvim_get_var="vim_get_var",
+ nvim_get_vvar="vim_get_vvar",
+ nvim_input="vim_input",
+ nvim_list_bufs="vim_get_buffers",
+ nvim_list_runtime_paths="vim_list_runtime_paths",
+ nvim_list_tabpages="vim_get_tabpages",
+ nvim_list_wins="vim_get_windows",
+ nvim_out_write="vim_out_write",
+ nvim_replace_termcodes="vim_replace_termcodes",
+ nvim_set_current_buf="vim_set_current_buffer",
+ nvim_set_current_dir="vim_change_directory",
+ nvim_set_current_line="vim_set_current_line",
+ nvim_set_current_tabpage="vim_set_current_tabpage",
+ nvim_set_current_win="vim_set_current_window",
+ nvim_set_option="vim_set_option",
+ nvim_strwidth="vim_strwidth",
+ nvim_subscribe="vim_subscribe",
+ nvim_tabpage_get_var="tabpage_get_var",
+ nvim_tabpage_get_win="tabpage_get_window",
+ nvim_tabpage_is_valid="tabpage_is_valid",
+ nvim_tabpage_list_wins="tabpage_get_windows",
+ nvim_ui_detach="ui_detach",
+ nvim_ui_try_resize="ui_try_resize",
+ nvim_unsubscribe="vim_unsubscribe",
+ nvim_win_get_buf="window_get_buffer",
+ nvim_win_get_cursor="window_get_cursor",
+ nvim_win_get_height="window_get_height",
+ nvim_win_get_option="window_get_option",
+ nvim_win_get_position="window_get_position",
+ nvim_win_get_tabpage="window_get_tabpage",
+ nvim_win_get_var="window_get_var",
+ nvim_win_get_width="window_get_width",
+ nvim_win_is_valid="window_is_valid",
+ nvim_win_set_cursor="window_set_cursor",
+ nvim_win_set_height="window_set_height",
+ nvim_win_set_option="window_set_option",
+ nvim_win_set_width="window_set_width",
+}
+return deprecated_aliases
diff --git a/src/nvim/api/private/defs.h b/src/nvim/api/private/defs.h
index 5fb95a163f..a6710193ff 100644
--- a/src/nvim/api/private/defs.h
+++ b/src/nvim/api/private/defs.h
@@ -9,13 +9,15 @@
#define STRING_INIT {.data = NULL, .size = 0}
#define OBJECT_INIT { .type = kObjectTypeNil }
#define ERROR_INIT { .set = false }
-#define REMOTE_TYPE(type) typedef uint64_t type
+#define REMOTE_TYPE(type) typedef handle_T type
#ifdef INCLUDE_GENERATED_DECLARATIONS
# define ArrayOf(...) Array
# define DictionaryOf(...) Dictionary
#endif
+typedef int handle_T;
+
// Basic types
typedef enum {
kErrorTypeException,
@@ -31,6 +33,9 @@ typedef enum {
/// Used as the message ID of notifications.
#define NO_RESPONSE UINT64_MAX
+/// Used as channel_id when the call is local
+#define INVALID_CHANNEL UINT64_MAX
+
typedef struct {
ErrorType type;
char msg[1024];
diff --git a/src/nvim/api/private/dispatch.h b/src/nvim/api/private/dispatch.h
new file mode 100644
index 0000000000..d91456c306
--- /dev/null
+++ b/src/nvim/api/private/dispatch.h
@@ -0,0 +1,23 @@
+#ifndef NVIM_API_PRIVATE_DISPATCH_H
+#define NVIM_API_PRIVATE_DISPATCH_H
+
+#include "nvim/api/private/defs.h"
+
+typedef Object (*ApiDispatchWrapper)(uint64_t channel_id,
+ uint64_t request_id,
+ Array args,
+ Error *error);
+
+/// The rpc_method_handlers table, used in msgpack_rpc_dispatch(), stores
+/// functions of this type.
+typedef struct {
+ ApiDispatchWrapper fn;
+ bool async; // function is always safe to run immediately instead of being
+ // put in a request queue for handling when nvim waits for input.
+} MsgpackRpcRequestHandler;
+
+#ifdef INCLUDE_GENERATED_DECLARATIONS
+# include "api/private/dispatch.h.generated.h"
+#endif
+
+#endif // NVIM_API_PRIVATE_DISPATCH_H
diff --git a/src/nvim/api/private/handle.c b/src/nvim/api/private/handle.c
index 69df7294ad..acb0fb332a 100644
--- a/src/nvim/api/private/handle.c
+++ b/src/nvim/api/private/handle.c
@@ -5,30 +5,26 @@
#include "nvim/map.h"
#include "nvim/api/private/handle.h"
-#define HANDLE_INIT(name) name##_handles = pmap_new(uint64_t)()
+#define HANDLE_INIT(name) name##_handles = pmap_new(handle_T)()
#define HANDLE_IMPL(type, name) \
- static PMap(uint64_t) *name##_handles = NULL; \
+ static PMap(handle_T) *name##_handles = NULL; /* NOLINT */ \
\
- type *handle_get_##name(uint64_t handle) \
+ type *handle_get_##name(handle_T handle) \
{ \
- return pmap_get(uint64_t)(name##_handles, handle); \
+ return pmap_get(handle_T)(name##_handles, handle); \
} \
\
void handle_register_##name(type *name) \
{ \
- assert(!name->handle); \
- name->handle = next_handle++; \
- pmap_put(uint64_t)(name##_handles, name->handle, name); \
+ pmap_put(handle_T)(name##_handles, name->handle, name); \
} \
\
void handle_unregister_##name(type *name) \
{ \
- pmap_del(uint64_t)(name##_handles, name->handle); \
+ pmap_del(handle_T)(name##_handles, name->handle); \
}
-static uint64_t next_handle = 1;
-
HANDLE_IMPL(buf_T, buffer)
HANDLE_IMPL(win_T, window)
HANDLE_IMPL(tabpage_T, tabpage)
diff --git a/src/nvim/api/private/handle.h b/src/nvim/api/private/handle.h
index 804e266dc3..30bbfbee1b 100644
--- a/src/nvim/api/private/handle.h
+++ b/src/nvim/api/private/handle.h
@@ -3,9 +3,10 @@
#include "nvim/vim.h"
#include "nvim/buffer_defs.h"
+#include "nvim/api/private/defs.h"
#define HANDLE_DECLS(type, name) \
- type *handle_get_##name(uint64_t handle); \
+ type *handle_get_##name(handle_T handle); \
void handle_register_##name(type *name); \
void handle_unregister_##name(type *name);
diff --git a/src/nvim/api/private/helpers.c b/src/nvim/api/private/helpers.c
index c88bf2127a..fc114bae16 100644
--- a/src/nvim/api/private/helpers.c
+++ b/src/nvim/api/private/helpers.c
@@ -104,10 +104,11 @@ Object dict_get_value(dict_T *dict, String key, Error *err)
/// @param value The new value
/// @param del Delete key in place of setting it. Argument `value` is ignored in
/// this case.
+/// @param retval If true the old value will be converted and returned.
/// @param[out] err Details of an error that may have occurred
-/// @return the old value, if any
+/// @return The old value if `retval` is true and the key was present, else NIL
Object dict_set_value(dict_T *dict, String key, Object value, bool del,
- Error *err)
+ bool retval, Error *err)
{
Object rv = OBJECT_INIT;
@@ -135,7 +136,9 @@ Object dict_set_value(dict_T *dict, String key, Object value, bool del,
api_set_error(err, Validation, _("Key \"%s\" doesn't exist"), key.data);
} else {
// Return the old value
- rv = vim_to_object(&di->di_tv);
+ if (retval) {
+ rv = vim_to_object(&di->di_tv);
+ }
// Delete the entry
hashitem_T *hi = hash_find(&dict->dv_hashtab, di->di_key);
hash_remove(&dict->dv_hashtab, hi);
@@ -156,7 +159,9 @@ Object dict_set_value(dict_T *dict, String key, Object value, bool del,
dict_add(dict, di);
} else {
// Return the old value
- rv = vim_to_object(&di->di_tv);
+ if (retval) {
+ rv = vim_to_object(&di->di_tv);
+ }
clear_tv(&di->di_tv);
}
@@ -507,6 +512,10 @@ Object vim_to_object(typval_T *obj)
buf_T *find_buffer_by_handle(Buffer buffer, Error *err)
{
+ if (buffer == 0) {
+ return curbuf;
+ }
+
buf_T *rv = handle_get_buffer(buffer);
if (!rv) {
@@ -518,6 +527,10 @@ buf_T *find_buffer_by_handle(Buffer buffer, Error *err)
win_T * find_window_by_handle(Window window, Error *err)
{
+ if (window == 0) {
+ return curwin;
+ }
+
win_T *rv = handle_get_window(window);
if (!rv) {
@@ -529,6 +542,10 @@ win_T * find_window_by_handle(Window window, Error *err)
tabpage_T * find_tab_by_handle(Tabpage tabpage, Error *err)
{
+ if (tabpage == 0) {
+ return curtab;
+ }
+
tabpage_T *rv = handle_get_tabpage(tabpage);
if (!rv) {
@@ -572,10 +589,16 @@ String cstr_as_string(char *str) FUNC_ATTR_PURE
return (String) {.data = str, .size = strlen(str)};
}
+/// Converts from type Object to a VimL value.
+///
+/// @param obj Object to convert from.
+/// @param tv Conversion result is placed here. On failure member v_type is
+/// set to VAR_UNKNOWN (no allocation was made for this variable).
+/// returns true if conversion is successful, otherwise false.
bool object_to_vim(Object obj, typval_T *tv, Error *err)
{
tv->v_type = VAR_UNKNOWN;
- tv->v_lock = 0;
+ tv->v_lock = VAR_UNLOCKED;
switch (obj.type) {
case kObjectTypeNil:
@@ -616,9 +639,8 @@ bool object_to_vim(Object obj, typval_T *tv, Error *err)
}
break;
- case kObjectTypeArray:
- tv->v_type = VAR_LIST;
- tv->vval.v_list = list_alloc();
+ case kObjectTypeArray: {
+ list_T *list = list_alloc();
for (uint32_t i = 0; i < obj.data.array.size; i++) {
Object item = obj.data.array.items[i];
@@ -627,45 +649,51 @@ bool object_to_vim(Object obj, typval_T *tv, Error *err)
if (!object_to_vim(item, &li->li_tv, err)) {
// cleanup
listitem_free(li);
- list_free(tv->vval.v_list, true);
+ list_free(list, true);
return false;
}
- list_append(tv->vval.v_list, li);
+ list_append(list, li);
}
- tv->vval.v_list->lv_refcount++;
+ list->lv_refcount++;
+
+ tv->v_type = VAR_LIST;
+ tv->vval.v_list = list;
break;
+ }
- case kObjectTypeDictionary:
- tv->v_type = VAR_DICT;
- tv->vval.v_dict = dict_alloc();
+ case kObjectTypeDictionary: {
+ dict_T *dict = dict_alloc();
for (uint32_t i = 0; i < obj.data.dictionary.size; i++) {
KeyValuePair item = obj.data.dictionary.items[i];
String key = item.key;
if (key.size == 0) {
- api_set_error(err,
- Validation,
+ api_set_error(err, Validation,
_("Empty dictionary keys aren't allowed"));
// cleanup
- dict_free(tv->vval.v_dict, true);
+ dict_free(dict, true);
return false;
}
- dictitem_T *di = dictitem_alloc((uint8_t *) key.data);
+ dictitem_T *di = dictitem_alloc((uint8_t *)key.data);
if (!object_to_vim(item.value, &di->di_tv, err)) {
// cleanup
dictitem_free(di);
- dict_free(tv->vval.v_dict, true);
+ dict_free(dict, true);
return false;
}
- dict_add(tv->vval.v_dict, di);
+ dict_add(dict, di);
}
- tv->vval.v_dict->dv_refcount++;
+ dict->dv_refcount++;
+
+ tv->v_type = VAR_DICT;
+ tv->vval.v_dict = dict;
break;
+ }
default:
abort();
}
@@ -764,12 +792,15 @@ static void init_type_metadata(Dictionary *metadata)
Dictionary buffer_metadata = ARRAY_DICT_INIT;
PUT(buffer_metadata, "id", INTEGER_OBJ(kObjectTypeBuffer));
+ PUT(buffer_metadata, "prefix", STRING_OBJ(cstr_to_string("nvim_buf_")));
Dictionary window_metadata = ARRAY_DICT_INIT;
PUT(window_metadata, "id", INTEGER_OBJ(kObjectTypeWindow));
+ PUT(window_metadata, "prefix", STRING_OBJ(cstr_to_string("nvim_win_")));
Dictionary tabpage_metadata = ARRAY_DICT_INIT;
PUT(tabpage_metadata, "id", INTEGER_OBJ(kObjectTypeTabpage));
+ PUT(tabpage_metadata, "prefix", STRING_OBJ(cstr_to_string("nvim_tabpage_")));
PUT(types, "Buffer", DICTIONARY_OBJ(buffer_metadata));
PUT(types, "Window", DICTIONARY_OBJ(window_metadata));
diff --git a/src/nvim/api/tabpage.c b/src/nvim/api/tabpage.c
index c8311b0aa0..8b1fb041e2 100644
--- a/src/nvim/api/tabpage.c
+++ b/src/nvim/api/tabpage.c
@@ -14,7 +14,7 @@
/// @param tabpage The tabpage
/// @param[out] err Details of an error that may have occurred
/// @return The windows in `tabpage`
-ArrayOf(Window) tabpage_get_windows(Tabpage tabpage, Error *err)
+ArrayOf(Window) nvim_tabpage_list_wins(Tabpage tabpage, Error *err)
{
Array rv = ARRAY_DICT_INIT;
tabpage_T *tab = find_tab_by_handle(tabpage, err);
@@ -43,7 +43,7 @@ ArrayOf(Window) tabpage_get_windows(Tabpage tabpage, Error *err)
/// @param name The variable name
/// @param[out] err Details of an error that may have occurred
/// @return The variable value
-Object tabpage_get_var(Tabpage tabpage, String name, Error *err)
+Object nvim_tabpage_get_var(Tabpage tabpage, String name, Error *err)
{
tabpage_T *tab = find_tab_by_handle(tabpage, err);
@@ -60,6 +60,44 @@ Object tabpage_get_var(Tabpage tabpage, String name, Error *err)
/// @param name The variable name
/// @param value The variable value
/// @param[out] err Details of an error that may have occurred
+void nvim_tabpage_set_var(Tabpage tabpage,
+ String name,
+ Object value,
+ Error *err)
+{
+ tabpage_T *tab = find_tab_by_handle(tabpage, err);
+
+ if (!tab) {
+ return;
+ }
+
+ dict_set_value(tab->tp_vars, name, value, false, false, err);
+}
+
+/// Removes a tab-scoped (t:) variable
+///
+/// @param tabpage handle
+/// @param name The variable name
+/// @param[out] err Details of an error that may have occurred
+void nvim_tabpage_del_var(Tabpage tabpage, String name, Error *err)
+{
+ tabpage_T *tab = find_tab_by_handle(tabpage, err);
+
+ if (!tab) {
+ return;
+ }
+
+ dict_set_value(tab->tp_vars, name, NIL, true, false, err);
+}
+
+/// Sets a tab-scoped (t:) variable
+///
+/// @deprecated
+///
+/// @param tabpage handle
+/// @param name The variable name
+/// @param value The variable value
+/// @param[out] err Details of an error that may have occurred
/// @return The old value or nil if there was no previous value.
///
/// @warning It may return nil if there was no previous value
@@ -72,18 +110,17 @@ Object tabpage_set_var(Tabpage tabpage, String name, Object value, Error *err)
return (Object) OBJECT_INIT;
}
- return dict_set_value(tab->tp_vars, name, value, false, err);
+ return dict_set_value(tab->tp_vars, name, value, false, true, err);
}
/// Removes a tab-scoped (t:) variable
///
+/// @deprecated
+///
/// @param tabpage handle
/// @param name The variable name
/// @param[out] err Details of an error that may have occurred
-/// @return The old value or nil if there was no previous value.
-///
-/// @warning It may return nil if there was no previous value
-/// or if previous value was `v:null`.
+/// @return The old value
Object tabpage_del_var(Tabpage tabpage, String name, Error *err)
{
tabpage_T *tab = find_tab_by_handle(tabpage, err);
@@ -92,7 +129,7 @@ Object tabpage_del_var(Tabpage tabpage, String name, Error *err)
return (Object) OBJECT_INIT;
}
- return dict_set_value(tab->tp_vars, name, NIL, true, err);
+ return dict_set_value(tab->tp_vars, name, NIL, true, true, err);
}
/// Gets the current window in a tab page
@@ -100,7 +137,7 @@ Object tabpage_del_var(Tabpage tabpage, String name, Error *err)
/// @param tabpage The tab page handle
/// @param[out] err Details of an error that may have occurred
/// @return The Window handle
-Window tabpage_get_window(Tabpage tabpage, Error *err)
+Window nvim_tabpage_get_win(Tabpage tabpage, Error *err)
{
Window rv = 0;
tabpage_T *tab = find_tab_by_handle(tabpage, err);
@@ -110,7 +147,7 @@ Window tabpage_get_window(Tabpage tabpage, Error *err)
}
if (tab == curtab) {
- return vim_get_current_window();
+ return nvim_get_current_win();
} else {
FOR_ALL_WINDOWS_IN_TAB(wp, tab) {
if (wp == tab->tp_curwin) {
@@ -126,7 +163,7 @@ Window tabpage_get_window(Tabpage tabpage, Error *err)
///
/// @param tabpage The tab page handle
/// @return true if the tab page is valid, false otherwise
-Boolean tabpage_is_valid(Tabpage tabpage)
+Boolean nvim_tabpage_is_valid(Tabpage tabpage)
{
Error stub = ERROR_INIT;
return find_tab_by_handle(tabpage, &stub) != NULL;
diff --git a/src/nvim/api/ui.c b/src/nvim/api/ui.c
index 1703d49296..56b41f1eea 100644
--- a/src/nvim/api/ui.c
+++ b/src/nvim/api/ui.c
@@ -8,8 +8,10 @@
#include "nvim/memory.h"
#include "nvim/map.h"
#include "nvim/msgpack_rpc/channel.h"
+#include "nvim/api/ui.h"
#include "nvim/api/private/defs.h"
#include "nvim/api/private/helpers.h"
+#include "nvim/popupmnu.h"
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "api/ui.c.generated.h"
@@ -44,8 +46,9 @@ void remote_ui_disconnect(uint64_t channel_id)
xfree(ui);
}
-void ui_attach(uint64_t channel_id, Integer width, Integer height,
- Boolean enable_rgb, Error *err)
+void nvim_ui_attach(uint64_t channel_id, Integer width, Integer height,
+ Dictionary options, Error *err)
+ FUNC_API_NOEVAL
{
if (pmap_has(uint64_t)(connected_uis, channel_id)) {
api_set_error(err, Exception, _("UI already attached for channel"));
@@ -57,14 +60,11 @@ void ui_attach(uint64_t channel_id, Integer width, Integer height,
_("Expected width > 0 and height > 0"));
return;
}
- UIData *data = xmalloc(sizeof(UIData));
- data->channel_id = channel_id;
- data->buffer = (Array)ARRAY_DICT_INIT;
UI *ui = xcalloc(1, sizeof(UI));
ui->width = (int)width;
ui->height = (int)height;
- ui->rgb = enable_rgb;
- ui->data = data;
+ ui->rgb = true;
+ ui->pum_external = false;
ui->resize = remote_ui_resize;
ui->clear = remote_ui_clear;
ui->eol_clear = remote_ui_eol_clear;
@@ -88,37 +88,100 @@ void ui_attach(uint64_t channel_id, Integer width, Integer height,
ui->suspend = remote_ui_suspend;
ui->set_title = remote_ui_set_title;
ui->set_icon = remote_ui_set_icon;
+ ui->event = remote_ui_event;
+
+ for (size_t i = 0; i < options.size; i++) {
+ ui_set_option(ui, options.items[i].key, options.items[i].value, err);
+ if (err->set) {
+ xfree(ui);
+ return;
+ }
+ }
+
+ UIData *data = xmalloc(sizeof(UIData));
+ data->channel_id = channel_id;
+ data->buffer = (Array)ARRAY_DICT_INIT;
+ ui->data = data;
+
pmap_put(uint64_t)(connected_uis, channel_id, ui);
ui_attach_impl(ui);
- return;
}
-void ui_detach(uint64_t channel_id, Error *err)
+/// @deprecated
+void ui_attach(uint64_t channel_id, Integer width, Integer height,
+ Boolean enable_rgb, Error *err)
+{
+ Dictionary opts = ARRAY_DICT_INIT;
+ PUT(opts, "rgb", BOOLEAN_OBJ(enable_rgb));
+ nvim_ui_attach(channel_id, width, height, opts, err);
+ api_free_dictionary(opts);
+}
+
+void nvim_ui_detach(uint64_t channel_id, Error *err)
+ FUNC_API_NOEVAL
{
if (!pmap_has(uint64_t)(connected_uis, channel_id)) {
api_set_error(err, Exception, _("UI is not attached for channel"));
+ return;
}
remote_ui_disconnect(channel_id);
}
-Object ui_try_resize(uint64_t channel_id, Integer width,
- Integer height, Error *err)
+
+void nvim_ui_try_resize(uint64_t channel_id, Integer width,
+ Integer height, Error *err)
+ FUNC_API_NOEVAL
{
if (!pmap_has(uint64_t)(connected_uis, channel_id)) {
api_set_error(err, Exception, _("UI is not attached for channel"));
+ return;
}
if (width <= 0 || height <= 0) {
api_set_error(err, Validation,
_("Expected width > 0 and height > 0"));
- return NIL;
+ return;
}
UI *ui = pmap_get(uint64_t)(connected_uis, channel_id);
ui->width = (int)width;
ui->height = (int)height;
ui_refresh();
- return NIL;
+}
+
+void nvim_ui_set_option(uint64_t channel_id, String name,
+ Object value, Error *error)
+ FUNC_API_NOEVAL
+{
+ if (!pmap_has(uint64_t)(connected_uis, channel_id)) {
+ api_set_error(error, Exception, _("UI is not attached for channel"));
+ return;
+ }
+ UI *ui = pmap_get(uint64_t)(connected_uis, channel_id);
+
+ ui_set_option(ui, name, value, error);
+ if (!error->set) {
+ ui_refresh();
+ }
+}
+
+static void ui_set_option(UI *ui, String name, Object value, Error *error) {
+ if (strcmp(name.data, "rgb") == 0) {
+ if (value.type != kObjectTypeBoolean) {
+ api_set_error(error, Validation, _("rgb must be a Boolean"));
+ return;
+ }
+ ui->rgb = value.data.boolean;
+ } else if (strcmp(name.data, "popupmenu_external") == 0) {
+ if (value.type != kObjectTypeBoolean) {
+ api_set_error(error, Validation,
+ _("popupmenu_external must be a Boolean"));
+ return;
+ }
+ ui->pum_external = value.data.boolean;
+ } else {
+ api_set_error(error, Validation, _("No such ui option"));
+ }
}
static void push_call(UI *ui, char *name, Array args)
@@ -341,3 +404,19 @@ static void remote_ui_set_icon(UI *ui, char *icon)
ADD(args, STRING_OBJ(cstr_to_string(icon)));
push_call(ui, "set_icon", args);
}
+
+static void remote_ui_event(UI *ui, char *name, Array args, bool *args_consumed)
+{
+ Array my_args = ARRAY_DICT_INIT;
+ // Objects are currently single-reference
+ // make a copy, but only if necessary
+ if (*args_consumed) {
+ for (size_t i = 0; i < args.size; i++) {
+ ADD(my_args, copy_object(args.items[i]));
+ }
+ } else {
+ my_args = args;
+ *args_consumed = true;
+ }
+ push_call(ui, name, my_args);
+}
diff --git a/src/nvim/api/vim.c b/src/nvim/api/vim.c
index ac7cc65ee4..d8cdad961b 100644
--- a/src/nvim/api/vim.c
+++ b/src/nvim/api/vim.c
@@ -14,6 +14,7 @@
#include "nvim/msgpack_rpc/channel.h"
#include "nvim/vim.h"
#include "nvim/buffer.h"
+#include "nvim/file_search.h"
#include "nvim/window.h"
#include "nvim/types.h"
#include "nvim/ex_docmd.h"
@@ -21,7 +22,7 @@
#include "nvim/memory.h"
#include "nvim/message.h"
#include "nvim/eval.h"
-#include "nvim/misc2.h"
+#include "nvim/option.h"
#include "nvim/syntax.h"
#include "nvim/getchar.h"
#include "nvim/os/input.h"
@@ -36,7 +37,7 @@
///
/// @param str The command str
/// @param[out] err Details of an error that may have occurred
-void vim_command(String str, Error *err)
+void nvim_command(String str, Error *err)
{
// Run the command
try_start();
@@ -52,17 +53,13 @@ void vim_command(String str, Error *err)
/// @param escape_csi the string needs escaping for K_SPECIAL/CSI bytes
/// @see feedkeys()
/// @see vim_strsave_escape_csi
-void vim_feedkeys(String keys, String mode, Boolean escape_csi)
+void nvim_feedkeys(String keys, String mode, Boolean escape_csi)
{
bool remap = true;
bool insert = false;
bool typed = false;
bool execute = false;
- if (keys.size == 0) {
- return;
- }
-
for (size_t i = 0; i < mode.size; ++i) {
switch (mode.data[i]) {
case 'n': remap = false; break;
@@ -73,6 +70,10 @@ void vim_feedkeys(String keys, String mode, Boolean escape_csi)
}
}
+ if (keys.size == 0 && !execute) {
+ return;
+ }
+
char *keys_esc;
if (escape_csi) {
// Need to escape K_SPECIAL and CSI before putting the string in the
@@ -92,18 +93,23 @@ void vim_feedkeys(String keys, String mode, Boolean escape_csi)
typebuf_was_filled = true;
}
if (execute) {
+ int save_msg_scroll = msg_scroll;
+
+ /* Avoid a 1 second delay when the keys start Insert mode. */
+ msg_scroll = false;
exec_normal(true);
+ msg_scroll |= save_msg_scroll;
}
}
-/// Passes input keys to Neovim. Unlike `vim_feedkeys`, this will use a
+/// Passes input keys to Neovim. Unlike `nvim_feedkeys`, this will use a
/// lower-level input buffer and the call is not deferred.
/// This is the most reliable way to emulate real user input.
///
/// @param keys to be typed
/// @return The number of bytes actually written, which can be lower than
/// requested if the buffer becomes full.
-Integer vim_input(String keys)
+Integer nvim_input(String keys)
FUNC_API_ASYNC
{
return (Integer)input_enqueue(keys);
@@ -113,7 +119,7 @@ Integer vim_input(String keys)
///
/// @see replace_termcodes
/// @see cpoptions
-String vim_replace_termcodes(String str, Boolean from_part, Boolean do_lt,
+String nvim_replace_termcodes(String str, Boolean from_part, Boolean do_lt,
Boolean special)
{
if (str.size == 0) {
@@ -133,10 +139,10 @@ String vim_replace_termcodes(String str, Boolean from_part, Boolean do_lt,
return cstr_as_string(ptr);
}
-String vim_command_output(String str, Error *err)
+String nvim_command_output(String str, Error *err)
{
do_cmdline_cmd("redir => v:command_output");
- vim_command(str, err);
+ nvim_command(str, err);
do_cmdline_cmd("redir END");
if (err->set) {
@@ -153,7 +159,7 @@ String vim_command_output(String str, Error *err)
/// @param str The expression str
/// @param[out] err Details of an error that may have occurred
/// @return The expanded object
-Object vim_eval(String str, Error *err)
+Object nvim_eval(String str, Error *err)
{
Object rv = OBJECT_INIT;
// Evaluate the expression
@@ -180,7 +186,7 @@ Object vim_eval(String str, Error *err)
/// @param args Functions arguments packed in an Array
/// @param[out] err Details of an error that may have occurred
/// @return Result of the function call
-Object vim_call_function(String fname, Array args, Error *err)
+Object nvim_call_function(String fname, Array args, Error *err)
{
Object rv = OBJECT_INIT;
if (args.size > MAX_FUNC_ARGS) {
@@ -229,7 +235,7 @@ free_vim_args:
/// @param str Some text
/// @param[out] err Details of an error that may have occurred
/// @return The number of cells
-Integer vim_strwidth(String str, Error *err)
+Integer nvim_strwidth(String str, Error *err)
{
if (str.size > INT_MAX) {
api_set_error(err, Validation, _("String length is too high"));
@@ -242,7 +248,7 @@ Integer vim_strwidth(String str, Error *err)
/// Gets a list of paths contained in 'runtimepath'
///
/// @return The list of paths
-ArrayOf(String) vim_list_runtime_paths(void)
+ArrayOf(String) nvim_list_runtime_paths(void)
{
Array rv = ARRAY_DICT_INIT;
uint8_t *rtp = p_rtp;
@@ -283,7 +289,7 @@ ArrayOf(String) vim_list_runtime_paths(void)
///
/// @param dir The new working directory
/// @param[out] err Details of an error that may have occurred
-void vim_change_directory(String dir, Error *err)
+void nvim_set_current_dir(String dir, Error *err)
{
if (dir.size >= MAXPATHL) {
api_set_error(err, Validation, _("Directory string is too long"));
@@ -311,7 +317,7 @@ void vim_change_directory(String dir, Error *err)
///
/// @param[out] err Details of an error that may have occurred
/// @return The current line string
-String vim_get_current_line(Error *err)
+String nvim_get_current_line(Error *err)
{
return buffer_get_line(curbuf->handle, curwin->w_cursor.lnum - 1, err);
}
@@ -320,7 +326,7 @@ String vim_get_current_line(Error *err)
///
/// @param line The line contents
/// @param[out] err Details of an error that may have occurred
-void vim_set_current_line(String line, Error *err)
+void nvim_set_current_line(String line, Error *err)
{
buffer_set_line(curbuf->handle, curwin->w_cursor.lnum - 1, line, err);
}
@@ -328,7 +334,7 @@ void vim_set_current_line(String line, Error *err)
/// Deletes the current line
///
/// @param[out] err Details of an error that may have occurred
-void vim_del_current_line(Error *err)
+void nvim_del_current_line(Error *err)
{
buffer_del_line(curbuf->handle, curwin->w_cursor.lnum - 1, err);
}
@@ -338,7 +344,7 @@ void vim_del_current_line(Error *err)
/// @param name The variable name
/// @param[out] err Details of an error that may have occurred
/// @return The variable value
-Object vim_get_var(String name, Error *err)
+Object nvim_get_var(String name, Error *err)
{
return dict_get_value(&globvardict, name, err);
}
@@ -348,26 +354,46 @@ Object vim_get_var(String name, Error *err)
/// @param name The variable name
/// @param value The variable value
/// @param[out] err Details of an error that may have occurred
+void nvim_set_var(String name, Object value, Error *err)
+{
+ dict_set_value(&globvardict, name, value, false, false, err);
+}
+
+/// Removes a global variable
+///
+/// @param name The variable name
+/// @param[out] err Details of an error that may have occurred
+void nvim_del_var(String name, Error *err)
+{
+ dict_set_value(&globvardict, name, NIL, true, false, err);
+}
+
+/// Sets a global variable
+///
+/// @deprecated
+///
+/// @param name The variable name
+/// @param value The variable value
+/// @param[out] err Details of an error that may have occurred
/// @return The old value or nil if there was no previous value.
///
/// @warning It may return nil if there was no previous value
/// or if previous value was `v:null`.
Object vim_set_var(String name, Object value, Error *err)
{
- return dict_set_value(&globvardict, name, value, false, err);
+ return dict_set_value(&globvardict, name, value, false, true, err);
}
/// Removes a global variable
///
+/// @deprecated
+///
/// @param name The variable name
/// @param[out] err Details of an error that may have occurred
-/// @return The old value or nil if there was no previous value.
-///
-/// @warning It may return nil if there was no previous value
-/// or if previous value was `v:null`.
+/// @return The old value
Object vim_del_var(String name, Error *err)
{
- return dict_set_value(&globvardict, name, NIL, true, err);
+ return dict_set_value(&globvardict, name, NIL, true, true, err);
}
/// Gets a vim variable
@@ -375,7 +401,7 @@ Object vim_del_var(String name, Error *err)
/// @param name The variable name
/// @param[out] err Details of an error that may have occurred
/// @return The variable value
-Object vim_get_vvar(String name, Error *err)
+Object nvim_get_vvar(String name, Error *err)
{
return dict_get_value(&vimvardict, name, err);
}
@@ -385,7 +411,7 @@ Object vim_get_vvar(String name, Error *err)
/// @param name The option name
/// @param[out] err Details of an error that may have occurred
/// @return The option value
-Object vim_get_option(String name, Error *err)
+Object nvim_get_option(String name, Error *err)
{
return get_option_from(NULL, SREQ_GLOBAL, name, err);
}
@@ -395,7 +421,7 @@ Object vim_get_option(String name, Error *err)
/// @param name The option name
/// @param value The new option value
/// @param[out] err Details of an error that may have occurred
-void vim_set_option(String name, Object value, Error *err)
+void nvim_set_option(String name, Object value, Error *err)
{
set_option_to(NULL, SREQ_GLOBAL, name, value, err);
}
@@ -403,7 +429,7 @@ void vim_set_option(String name, Object value, Error *err)
/// Writes a message to vim output buffer
///
/// @param str The message
-void vim_out_write(String str)
+void nvim_out_write(String str)
{
write_msg(str, false);
}
@@ -411,25 +437,25 @@ void vim_out_write(String str)
/// Writes a message to vim error buffer
///
/// @param str The message
-void vim_err_write(String str)
+void nvim_err_write(String str)
{
write_msg(str, true);
}
/// Higher level error reporting function that ensures all str contents
-/// are written by sending a trailing linefeed to `vim_err_write`
+/// are written by sending a trailing linefeed to `nvim_err_write`
///
/// @param str The message
-void vim_report_error(String str)
+void nvim_err_writeln(String str)
{
- vim_err_write(str);
- vim_err_write((String) {.data = "\n", .size = 1});
+ nvim_err_write(str);
+ nvim_err_write((String) { .data = "\n", .size = 1 });
}
/// Gets the current list of buffer handles
///
/// @return The number of buffers
-ArrayOf(Buffer) vim_get_buffers(void)
+ArrayOf(Buffer) nvim_list_bufs(void)
{
Array rv = ARRAY_DICT_INIT;
@@ -450,7 +476,7 @@ ArrayOf(Buffer) vim_get_buffers(void)
/// Gets the current buffer
///
/// @reqturn The buffer handle
-Buffer vim_get_current_buffer(void)
+Buffer nvim_get_current_buf(void)
{
return curbuf->handle;
}
@@ -459,7 +485,7 @@ Buffer vim_get_current_buffer(void)
///
/// @param id The buffer handle
/// @param[out] err Details of an error that may have occurred
-void vim_set_current_buffer(Buffer buffer, Error *err)
+void nvim_set_current_buf(Buffer buffer, Error *err)
{
buf_T *buf = find_buffer_by_handle(buffer, err);
@@ -472,7 +498,7 @@ void vim_set_current_buffer(Buffer buffer, Error *err)
if (!try_end(err) && result == FAIL) {
api_set_error(err,
Exception,
- _("Failed to switch to buffer %" PRIu64),
+ _("Failed to switch to buffer %d"),
buffer);
}
}
@@ -480,7 +506,7 @@ void vim_set_current_buffer(Buffer buffer, Error *err)
/// Gets the current list of window handles
///
/// @return The number of windows
-ArrayOf(Window) vim_get_windows(void)
+ArrayOf(Window) nvim_list_wins(void)
{
Array rv = ARRAY_DICT_INIT;
@@ -501,7 +527,7 @@ ArrayOf(Window) vim_get_windows(void)
/// Gets the current window
///
/// @return The window handle
-Window vim_get_current_window(void)
+Window nvim_get_current_win(void)
{
return curwin->handle;
}
@@ -509,7 +535,7 @@ Window vim_get_current_window(void)
/// Sets the current window
///
/// @param handle The window handle
-void vim_set_current_window(Window window, Error *err)
+void nvim_set_current_win(Window window, Error *err)
{
win_T *win = find_window_by_handle(window, err);
@@ -522,7 +548,7 @@ void vim_set_current_window(Window window, Error *err)
if (!try_end(err) && win != curwin) {
api_set_error(err,
Exception,
- _("Failed to switch to window %" PRIu64),
+ _("Failed to switch to window %d"),
window);
}
}
@@ -530,7 +556,7 @@ void vim_set_current_window(Window window, Error *err)
/// Gets the current list of tabpage handles
///
/// @return The number of tab pages
-ArrayOf(Tabpage) vim_get_tabpages(void)
+ArrayOf(Tabpage) nvim_list_tabpages(void)
{
Array rv = ARRAY_DICT_INIT;
@@ -551,7 +577,7 @@ ArrayOf(Tabpage) vim_get_tabpages(void)
/// Gets the current tab page
///
/// @return The tab page handle
-Tabpage vim_get_current_tabpage(void)
+Tabpage nvim_get_current_tabpage(void)
{
return curtab->handle;
}
@@ -560,7 +586,7 @@ Tabpage vim_get_current_tabpage(void)
///
/// @param handle The tab page handle
/// @param[out] err Details of an error that may have occurred
-void vim_set_current_tabpage(Tabpage tabpage, Error *err)
+void nvim_set_current_tabpage(Tabpage tabpage, Error *err)
{
tabpage_T *tp = find_tab_by_handle(tabpage, err);
@@ -573,7 +599,7 @@ void vim_set_current_tabpage(Tabpage tabpage, Error *err)
if (!try_end(err) && tp != curtab) {
api_set_error(err,
Exception,
- _("Failed to switch to tabpage %" PRIu64),
+ _("Failed to switch to tabpage %d"),
tabpage);
}
}
@@ -582,7 +608,8 @@ void vim_set_current_tabpage(Tabpage tabpage, Error *err)
///
/// @param channel_id The channel id (passed automatically by the dispatcher)
/// @param event The event type string
-void vim_subscribe(uint64_t channel_id, String event)
+void nvim_subscribe(uint64_t channel_id, String event)
+ FUNC_API_NOEVAL
{
size_t length = (event.size < METHOD_MAXLEN ? event.size : METHOD_MAXLEN);
char e[METHOD_MAXLEN + 1];
@@ -595,7 +622,8 @@ void vim_subscribe(uint64_t channel_id, String event)
///
/// @param channel_id The channel id (passed automatically by the dispatcher)
/// @param event The event type string
-void vim_unsubscribe(uint64_t channel_id, String event)
+void nvim_unsubscribe(uint64_t channel_id, String event)
+ FUNC_API_NOEVAL
{
size_t length = (event.size < METHOD_MAXLEN ?
event.size :
@@ -606,12 +634,12 @@ void vim_unsubscribe(uint64_t channel_id, String event)
channel_unsubscribe(channel_id, e);
}
-Integer vim_name_to_color(String name)
+Integer nvim_get_color_by_name(String name)
{
return name_to_color((uint8_t *)name.data);
}
-Dictionary vim_get_color_map(void)
+Dictionary nvim_get_color_map(void)
{
Dictionary colors = ARRAY_DICT_INIT;
@@ -623,8 +651,8 @@ Dictionary vim_get_color_map(void)
}
-Array vim_get_api_info(uint64_t channel_id)
- FUNC_API_ASYNC
+Array nvim_get_api_info(uint64_t channel_id)
+ FUNC_API_ASYNC FUNC_API_NOEVAL
{
Array rv = ARRAY_DICT_INIT;
diff --git a/src/nvim/api/window.c b/src/nvim/api/window.c
index f644453358..166e43f698 100644
--- a/src/nvim/api/window.c
+++ b/src/nvim/api/window.c
@@ -11,7 +11,6 @@
#include "nvim/window.h"
#include "nvim/screen.h"
#include "nvim/move.h"
-#include "nvim/misc2.h"
/// Gets the current buffer in a window
@@ -19,7 +18,7 @@
/// @param window The window handle
/// @param[out] err Details of an error that may have occurred
/// @return The buffer handle
-Buffer window_get_buffer(Window window, Error *err)
+Buffer nvim_win_get_buf(Window window, Error *err)
{
win_T *win = find_window_by_handle(window, err);
@@ -35,7 +34,7 @@ Buffer window_get_buffer(Window window, Error *err)
/// @param window The window handle
/// @param[out] err Details of an error that may have occurred
/// @return the (row, col) tuple
-ArrayOf(Integer, 2) window_get_cursor(Window window, Error *err)
+ArrayOf(Integer, 2) nvim_win_get_cursor(Window window, Error *err)
{
Array rv = ARRAY_DICT_INIT;
win_T *win = find_window_by_handle(window, err);
@@ -53,7 +52,7 @@ ArrayOf(Integer, 2) window_get_cursor(Window window, Error *err)
/// @param window The window handle
/// @param pos the (row, col) tuple representing the new position
/// @param[out] err Details of an error that may have occurred
-void window_set_cursor(Window window, ArrayOf(Integer, 2) pos, Error *err)
+void nvim_win_set_cursor(Window window, ArrayOf(Integer, 2) pos, Error *err)
{
win_T *win = find_window_by_handle(window, err);
@@ -99,7 +98,7 @@ void window_set_cursor(Window window, ArrayOf(Integer, 2) pos, Error *err)
/// @param window The window handle
/// @param[out] err Details of an error that may have occurred
/// @return the height in rows
-Integer window_get_height(Window window, Error *err)
+Integer nvim_win_get_height(Window window, Error *err)
{
win_T *win = find_window_by_handle(window, err);
@@ -116,7 +115,7 @@ Integer window_get_height(Window window, Error *err)
/// @param window The window handle
/// @param height the new height in rows
/// @param[out] err Details of an error that may have occurred
-void window_set_height(Window window, Integer height, Error *err)
+void nvim_win_set_height(Window window, Integer height, Error *err)
{
win_T *win = find_window_by_handle(window, err);
@@ -142,7 +141,7 @@ void window_set_height(Window window, Integer height, Error *err)
/// @param window The window handle
/// @param[out] err Details of an error that may have occurred
/// @return the width in columns
-Integer window_get_width(Window window, Error *err)
+Integer nvim_win_get_width(Window window, Error *err)
{
win_T *win = find_window_by_handle(window, err);
@@ -159,7 +158,7 @@ Integer window_get_width(Window window, Error *err)
/// @param window The window handle
/// @param width the new width in columns
/// @param[out] err Details of an error that may have occurred
-void window_set_width(Window window, Integer width, Error *err)
+void nvim_win_set_width(Window window, Integer width, Error *err)
{
win_T *win = find_window_by_handle(window, err);
@@ -186,7 +185,7 @@ void window_set_width(Window window, Integer width, Error *err)
/// @param name The variable name
/// @param[out] err Details of an error that may have occurred
/// @return The variable value
-Object window_get_var(Window window, String name, Error *err)
+Object nvim_win_get_var(Window window, String name, Error *err)
{
win_T *win = find_window_by_handle(window, err);
@@ -203,6 +202,41 @@ Object window_get_var(Window window, String name, Error *err)
/// @param name The variable name
/// @param value The variable value
/// @param[out] err Details of an error that may have occurred
+void nvim_win_set_var(Window window, String name, Object value, Error *err)
+{
+ win_T *win = find_window_by_handle(window, err);
+
+ if (!win) {
+ return;
+ }
+
+ dict_set_value(win->w_vars, name, value, false, false, err);
+}
+
+/// Removes a window-scoped (w:) variable
+///
+/// @param window The window handle
+/// @param name The variable name
+/// @param[out] err Details of an error that may have occurred
+void nvim_win_del_var(Window window, String name, Error *err)
+{
+ win_T *win = find_window_by_handle(window, err);
+
+ if (!win) {
+ return;
+ }
+
+ dict_set_value(win->w_vars, name, NIL, true, false, err);
+}
+
+/// Sets a window-scoped (w:) variable
+///
+/// @deprecated
+///
+/// @param window The window handle
+/// @param name The variable name
+/// @param value The variable value
+/// @param[out] err Details of an error that may have occurred
/// @return The old value or nil if there was no previous value.
///
/// @warning It may return nil if there was no previous value
@@ -215,18 +249,17 @@ Object window_set_var(Window window, String name, Object value, Error *err)
return (Object) OBJECT_INIT;
}
- return dict_set_value(win->w_vars, name, value, false, err);
+ return dict_set_value(win->w_vars, name, value, false, true, err);
}
/// Removes a window-scoped (w:) variable
///
+/// @deprecated
+///
/// @param window The window handle
/// @param name The variable name
/// @param[out] err Details of an error that may have occurred
-/// @return The old value or nil if there was no previous value.
-///
-/// @warning It may return nil if there was no previous value
-/// or if previous value was `v:null`.
+/// @return The old value
Object window_del_var(Window window, String name, Error *err)
{
win_T *win = find_window_by_handle(window, err);
@@ -235,7 +268,7 @@ Object window_del_var(Window window, String name, Error *err)
return (Object) OBJECT_INIT;
}
- return dict_set_value(win->w_vars, name, NIL, true, err);
+ return dict_set_value(win->w_vars, name, NIL, true, true, err);
}
/// Gets a window option value
@@ -244,7 +277,7 @@ Object window_del_var(Window window, String name, Error *err)
/// @param name The option name
/// @param[out] err Details of an error that may have occurred
/// @return The option value
-Object window_get_option(Window window, String name, Error *err)
+Object nvim_win_get_option(Window window, String name, Error *err)
{
win_T *win = find_window_by_handle(window, err);
@@ -262,7 +295,7 @@ Object window_get_option(Window window, String name, Error *err)
/// @param name The option name
/// @param value The option value
/// @param[out] err Details of an error that may have occurred
-void window_set_option(Window window, String name, Object value, Error *err)
+void nvim_win_set_option(Window window, String name, Object value, Error *err)
{
win_T *win = find_window_by_handle(window, err);
@@ -278,7 +311,7 @@ void window_set_option(Window window, String name, Object value, Error *err)
/// @param window The window handle
/// @param[out] err Details of an error that may have occurred
/// @return The (row, col) tuple with the window position
-ArrayOf(Integer, 2) window_get_position(Window window, Error *err)
+ArrayOf(Integer, 2) nvim_win_get_position(Window window, Error *err)
{
Array rv = ARRAY_DICT_INIT;
win_T *win = find_window_by_handle(window, err);
@@ -296,7 +329,7 @@ ArrayOf(Integer, 2) window_get_position(Window window, Error *err)
/// @param window The window handle
/// @param[out] err Details of an error that may have occurred
/// @return The tab page that contains the window
-Tabpage window_get_tabpage(Window window, Error *err)
+Tabpage nvim_win_get_tabpage(Window window, Error *err)
{
Tabpage rv = 0;
win_T *win = find_window_by_handle(window, err);
@@ -312,7 +345,7 @@ Tabpage window_get_tabpage(Window window, Error *err)
///
/// @param window The window handle
/// @return true if the window is valid, false otherwise
-Boolean window_is_valid(Window window)
+Boolean nvim_win_is_valid(Window window)
{
Error stub = ERROR_INIT;
return find_window_by_handle(window, &stub) != NULL;
diff --git a/src/nvim/buffer.c b/src/nvim/buffer.c
index c934d44e70..b42ad1c18a 100644
--- a/src/nvim/buffer.c
+++ b/src/nvim/buffer.c
@@ -36,6 +36,7 @@
#include "nvim/ex_eval.h"
#include "nvim/ex_getln.h"
#include "nvim/fileio.h"
+#include "nvim/file_search.h"
#include "nvim/fold.h"
#include "nvim/getchar.h"
#include "nvim/hashtab.h"
@@ -48,7 +49,6 @@
#include "nvim/memory.h"
#include "nvim/message.h"
#include "nvim/misc1.h"
-#include "nvim/misc2.h"
#include "nvim/garray.h"
#include "nvim/move.h"
#include "nvim/option.h"
@@ -1397,8 +1397,7 @@ buflist_new (
}
if (buf != curbuf || curbuf == NULL) {
buf = xcalloc(1, sizeof(buf_T));
- handle_register_buffer(buf);
- /* init b: variables */
+ // init b: variables
buf->b_vars = dict_alloc();
init_var_dict(buf->b_vars, &buf->b_bufvar, VAR_SCOPE);
}
@@ -1451,11 +1450,12 @@ buflist_new (
lastbuf = buf;
buf->b_fnum = top_file_num++;
- if (top_file_num < 0) { /* wrap around (may cause duplicates) */
+ handle_register_buffer(buf);
+ if (top_file_num < 0) { // wrap around (may cause duplicates)
EMSG(_("W14: Warning: List of file names overflow"));
if (emsg_silent == 0) {
ui_flush();
- os_delay(3000L, true); /* make sure it is noticed */
+ os_delay(3000L, true); // make sure it is noticed
}
top_file_num = 1;
}
@@ -5231,12 +5231,12 @@ wipe_buffer (
int aucmd /* When TRUE trigger autocommands. */
)
{
- if (buf->b_fnum == top_file_num - 1)
- --top_file_num;
-
- if (!aucmd) /* Don't trigger BufDelete autocommands here. */
+ if (!aucmd) {
+ // Don't trigger BufDelete autocommands here.
block_autocmds();
- close_buffer(NULL, buf, DOBUF_WIPE, FALSE);
- if (!aucmd)
+ }
+ close_buffer(NULL, buf, DOBUF_WIPE, false);
+ if (!aucmd) {
unblock_autocmds();
+ }
}
diff --git a/src/nvim/buffer_defs.h b/src/nvim/buffer_defs.h
index 46687f344c..ab5987612c 100644
--- a/src/nvim/buffer_defs.h
+++ b/src/nvim/buffer_defs.h
@@ -461,9 +461,10 @@ typedef struct {
*/
struct file_buffer {
- uint64_t handle; // unique identifier for the buffer
- memline_T b_ml; /* associated memline (also contains line
- count) */
+ handle_T handle; // unique id for the buffer (buffer number)
+#define b_fnum handle
+
+ memline_T b_ml; // associated memline (also contains line count
buf_T *b_next; /* links in list of buffers */
buf_T *b_prev;
@@ -487,8 +488,6 @@ struct file_buffer {
bool file_id_valid;
FileID file_id;
- int b_fnum; /* buffer number for this file. */
-
bool b_changed; /* 'modified': Set to true if something in the
file has been changed and not written out. */
int b_changedtick; /* incremented for each change, also for undo */
@@ -799,28 +798,27 @@ struct diffblock_S {
# define SNAP_AUCMD_IDX 1
# define SNAP_COUNT 2
-/*
- * Tab pages point to the top frame of each tab page.
- * Note: Most values are NOT valid for the current tab page! Use "curwin",
- * "firstwin", etc. for that. "tp_topframe" is always valid and can be
- * compared against "topframe" to find the current tab page.
- */
+/// Tab pages point to the top frame of each tab page.
+/// Note: Most values are NOT valid for the current tab page! Use "curwin",
+/// "firstwin", etc. for that. "tp_topframe" is always valid and can be
+/// compared against "topframe" to find the current tab page.
typedef struct tabpage_S tabpage_T;
struct tabpage_S {
- uint64_t handle;
- tabpage_T *tp_next; /* next tabpage or NULL */
- frame_T *tp_topframe; /* topframe for the windows */
- win_T *tp_curwin; /* current window in this Tab page */
- win_T *tp_prevwin; /* previous window in this Tab page */
- win_T *tp_firstwin; /* first window in this Tab page */
- win_T *tp_lastwin; /* last window in this Tab page */
- long tp_old_Rows; /* Rows when Tab page was left */
- long tp_old_Columns; /* Columns when Tab page was left */
- long tp_ch_used; /* value of 'cmdheight' when frame size
- was set */
+ handle_T handle;
+ tabpage_T *tp_next; ///< next tabpage or NULL
+ frame_T *tp_topframe; ///< topframe for the windows
+ win_T *tp_curwin; ///< current window in this Tab page
+ win_T *tp_prevwin; ///< previous window in this Tab page
+ win_T *tp_firstwin; ///< first window in this Tab page
+ win_T *tp_lastwin; ///< last window in this Tab page
+ long tp_old_Rows; ///< Rows when Tab page was left
+ long tp_old_Columns; ///< Columns when Tab page was left
+ long tp_ch_used; ///< value of 'cmdheight' when frame size
+ ///< was set
+
diff_T *tp_first_diff;
buf_T *(tp_diffbuf[DB_COUNT]);
- int tp_diff_invalid; ///< list of diffs is outdated */
+ int tp_diff_invalid; ///< list of diffs is outdated
frame_T *(tp_snapshot[SNAP_COUNT]); ///< window layout snapshots
dictitem_T tp_winvar; ///< variable for "t:" Dictionary
dict_T *tp_vars; ///< internal variables, local to tab page
@@ -936,8 +934,8 @@ struct matchitem {
* All row numbers are relative to the start of the window, except w_winrow.
*/
struct window_S {
- uint64_t handle;
- int w_id; ///< unique window ID
+ handle_T handle; ///< unique identifier for the window
+
buf_T *w_buffer; ///< buffer we are a window into (used
///< often, keep it the first item!)
diff --git a/src/nvim/charset.c b/src/nvim/charset.c
index 22ca0fb0cc..78f5d96fc7 100644
--- a/src/nvim/charset.c
+++ b/src/nvim/charset.c
@@ -19,10 +19,11 @@
#include "nvim/memline.h"
#include "nvim/memory.h"
#include "nvim/misc1.h"
-#include "nvim/misc2.h"
#include "nvim/garray.h"
#include "nvim/move.h"
+#include "nvim/option.h"
#include "nvim/os_unix.h"
+#include "nvim/state.h"
#include "nvim/strings.h"
#include "nvim/path.h"
@@ -1739,8 +1740,11 @@ char_u* skiptowhite_esc(char_u *p) {
/// @return Number read from the string.
intmax_t getdigits(char_u **pp)
{
+ errno = 0;
intmax_t number = strtoimax((char *)*pp, (char **)pp, 10);
- assert(errno != ERANGE);
+ if (number == INTMAX_MAX || number == INTMAX_MIN) {
+ assert(errno != ERANGE);
+ }
return number;
}
diff --git a/src/nvim/cursor.c b/src/nvim/cursor.c
index afaa6022c9..3ba9da34f2 100644
--- a/src/nvim/cursor.c
+++ b/src/nvim/cursor.c
@@ -9,6 +9,7 @@
#include "nvim/misc1.h"
#include "nvim/move.h"
#include "nvim/screen.h"
+#include "nvim/state.h"
#include "nvim/vim.h"
#include "nvim/ascii.h"
diff --git a/src/nvim/cursor.h b/src/nvim/cursor.h
index 09cc5a813c..1cbe8a609e 100644
--- a/src/nvim/cursor.h
+++ b/src/nvim/cursor.h
@@ -4,7 +4,6 @@
#include <stdbool.h>
#include "nvim/vim.h"
-#include "nvim/misc2.h"
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "cursor.h.generated.h"
diff --git a/src/nvim/cursor_shape.c b/src/nvim/cursor_shape.c
index 87425ca567..b50462664c 100644
--- a/src/nvim/cursor_shape.c
+++ b/src/nvim/cursor_shape.c
@@ -3,7 +3,6 @@
#include "nvim/vim.h"
#include "nvim/ascii.h"
#include "nvim/cursor_shape.h"
-#include "nvim/misc2.h"
#include "nvim/ex_getln.h"
#include "nvim/charset.h"
#include "nvim/strings.h"
diff --git a/src/nvim/diff.c b/src/nvim/diff.c
index 4826e70727..ef5acf4845 100644
--- a/src/nvim/diff.c
+++ b/src/nvim/diff.c
@@ -21,7 +21,6 @@
#include "nvim/memline.h"
#include "nvim/message.h"
#include "nvim/misc1.h"
-#include "nvim/misc2.h"
#include "nvim/memory.h"
#include "nvim/move.h"
#include "nvim/normal.h"
diff --git a/src/nvim/digraph.c b/src/nvim/digraph.c
index 4512b97967..6ba6e659a6 100644
--- a/src/nvim/digraph.c
+++ b/src/nvim/digraph.c
@@ -17,7 +17,6 @@
#include "nvim/getchar.h"
#include "nvim/mbyte.h"
#include "nvim/message.h"
-#include "nvim/misc2.h"
#include "nvim/memory.h"
#include "nvim/garray.h"
#include "nvim/normal.h"
diff --git a/src/nvim/edit.c b/src/nvim/edit.c
index a71104cfb6..18d5ea533d 100644
--- a/src/nvim/edit.c
+++ b/src/nvim/edit.c
@@ -29,7 +29,6 @@
#include "nvim/memory.h"
#include "nvim/message.h"
#include "nvim/misc1.h"
-#include "nvim/misc2.h"
#include "nvim/keymap.h"
#include "nvim/move.h"
#include "nvim/normal.h"
@@ -463,6 +462,8 @@ static void insert_enter(InsertState *s)
o_lnum = curwin->w_cursor.lnum;
}
+ foldUpdateAll(curwin);
+ foldOpenCursor();
if (s->cmdchar != 'r' && s->cmdchar != 'v') {
apply_autocmds(EVENT_INSERTLEAVE, NULL, NULL, false, curbuf);
}
@@ -2472,6 +2473,7 @@ void ins_compl_show_pum(void)
int cur = -1;
colnr_T col;
int lead_len = 0;
+ bool array_changed = false;
if (!pum_wanted() || !pum_enough_matches())
return;
@@ -2483,7 +2485,8 @@ void ins_compl_show_pum(void)
update_screen(0);
if (compl_match_array == NULL) {
- /* Need to build the popup menu list. */
+ array_changed = true;
+ // Need to build the popup menu list.
compl_match_arraysize = 0;
compl = compl_first_match;
/*
@@ -2586,7 +2589,7 @@ void ins_compl_show_pum(void)
// Use the cursor to get all wrapping and other settings right.
col = curwin->w_cursor.col;
curwin->w_cursor.col = compl_col;
- pum_display(compl_match_array, compl_match_arraysize, cur);
+ pum_display(compl_match_array, compl_match_arraysize, cur, array_changed);
curwin->w_cursor.col = col;
}
diff --git a/src/nvim/eval.c b/src/nvim/eval.c
index bb46898135..c762ce9fff 100644
--- a/src/nvim/eval.c
+++ b/src/nvim/eval.c
@@ -44,7 +44,6 @@
#include "nvim/memory.h"
#include "nvim/message.h"
#include "nvim/misc1.h"
-#include "nvim/misc2.h"
#include "nvim/keymap.h"
#include "nvim/map.h"
#include "nvim/file_search.h"
@@ -63,6 +62,7 @@
#include "nvim/search.h"
#include "nvim/sha256.h"
#include "nvim/spell.h"
+#include "nvim/state.h"
#include "nvim/strings.h"
#include "nvim/syntax.h"
#include "nvim/tag.h"
@@ -90,6 +90,8 @@
#include "nvim/os/dl.h"
#include "nvim/os/input.h"
#include "nvim/event/loop.h"
+#include "nvim/lib/kvec.h"
+#include "nvim/lib/khash.h"
#include "nvim/lib/queue.h"
#include "nvim/eval/typval_encode.h"
@@ -442,6 +444,22 @@ typedef struct {
ufunc_T *callback;
} timer_T;
+typedef void (*FunPtr)(void);
+
+/// Prototype of C function that implements VimL function
+typedef void (*VimLFunc)(typval_T *args, typval_T *rvar, FunPtr data);
+
+/// Structure holding VimL function definition
+typedef struct fst {
+ char *name; ///< Name of the function.
+ uint8_t min_argc; ///< Minimal number of arguments.
+ uint8_t max_argc; ///< Maximal number of arguments.
+ VimLFunc func; ///< Function implementation.
+ FunPtr data; ///< Userdata for function implementation.
+} VimLFuncDef;
+
+KHASH_MAP_INIT_STR(functions, VimLFuncDef)
+
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "eval.c.generated.h"
#endif
@@ -6681,331 +6699,9 @@ static int get_env_tv(char_u **arg, typval_T *rettv, int evaluate)
return OK;
}
-/*
- * Array with names and number of arguments of all internal functions
- * MUST BE KEPT SORTED IN strcmp() ORDER FOR BINARY SEARCH!
- */
-static struct fst {
- char *f_name; /* function name */
- char f_min_argc; /* minimal number of arguments */
- char f_max_argc; /* maximal number of arguments */
- void (*f_func)(typval_T *args, typval_T *rvar);
- /* implementation of function */
-} functions[] =
-{
- { "abs", 1, 1, f_abs },
- { "acos", 1, 1, f_acos }, // WJMc
- { "add", 2, 2, f_add },
- { "and", 2, 2, f_and },
- { "api_info", 0, 0, f_api_info },
- { "append", 2, 2, f_append },
- { "argc", 0, 0, f_argc },
- { "argidx", 0, 0, f_argidx },
- { "arglistid", 0, 2, f_arglistid },
- { "argv", 0, 1, f_argv },
- { "asin", 1, 1, f_asin }, // WJMc
- { "assert_equal", 2, 3, f_assert_equal },
- { "assert_exception", 1, 2, f_assert_exception },
- { "assert_fails", 1, 2, f_assert_fails },
- { "assert_false", 1, 2, f_assert_false },
- { "assert_match", 2, 3, f_assert_match },
- { "assert_notequal", 2, 3, f_assert_notequal },
- { "assert_notmatch", 2, 3, f_assert_notmatch },
- { "assert_true", 1, 2, f_assert_true },
- { "atan", 1, 1, f_atan },
- { "atan2", 2, 2, f_atan2 },
- { "browse", 4, 4, f_browse },
- { "browsedir", 2, 2, f_browsedir },
- { "bufexists", 1, 1, f_bufexists },
- { "buffer_exists", 1, 1, f_bufexists }, // obsolete
- { "buffer_name", 1, 1, f_bufname }, // obsolete
- { "buffer_number", 1, 1, f_bufnr }, // obsolete
- { "buflisted", 1, 1, f_buflisted },
- { "bufloaded", 1, 1, f_bufloaded },
- { "bufname", 1, 1, f_bufname },
- { "bufnr", 1, 2, f_bufnr },
- { "bufwinnr", 1, 1, f_bufwinnr },
- { "byte2line", 1, 1, f_byte2line },
- { "byteidx", 2, 2, f_byteidx },
- { "byteidxcomp", 2, 2, f_byteidxcomp },
- { "call", 2, 3, f_call },
- { "ceil", 1, 1, f_ceil },
- { "changenr", 0, 0, f_changenr },
- { "char2nr", 1, 2, f_char2nr },
- { "cindent", 1, 1, f_cindent },
- { "clearmatches", 0, 0, f_clearmatches },
- { "col", 1, 1, f_col },
- { "complete", 2, 2, f_complete },
- { "complete_add", 1, 1, f_complete_add },
- { "complete_check", 0, 0, f_complete_check },
- { "confirm", 1, 4, f_confirm },
- { "copy", 1, 1, f_copy },
- { "cos", 1, 1, f_cos },
- { "cosh", 1, 1, f_cosh },
- { "count", 2, 4, f_count },
- { "cscope_connection", 0, 3, f_cscope_connection },
- { "cursor", 1, 3, f_cursor },
- { "deepcopy", 1, 2, f_deepcopy },
- { "delete", 1, 2, f_delete },
- { "dictwatcheradd", 3, 3, f_dictwatcheradd },
- { "dictwatcherdel", 3, 3, f_dictwatcherdel },
- { "did_filetype", 0, 0, f_did_filetype },
- { "diff_filler", 1, 1, f_diff_filler },
- { "diff_hlID", 2, 2, f_diff_hlID },
- { "empty", 1, 1, f_empty },
- { "escape", 2, 2, f_escape },
- { "eval", 1, 1, f_eval },
- { "eventhandler", 0, 0, f_eventhandler },
- { "executable", 1, 1, f_executable },
- { "execute", 1, 1, f_execute },
- { "exepath", 1, 1, f_exepath },
- { "exists", 1, 1, f_exists },
- { "exp", 1, 1, f_exp },
- { "expand", 1, 3, f_expand },
- { "extend", 2, 3, f_extend },
- { "feedkeys", 1, 2, f_feedkeys },
- { "file_readable", 1, 1, f_filereadable }, // obsolete
- { "filereadable", 1, 1, f_filereadable },
- { "filewritable", 1, 1, f_filewritable },
- { "filter", 2, 2, f_filter },
- { "finddir", 1, 3, f_finddir },
- { "findfile", 1, 3, f_findfile },
- { "float2nr", 1, 1, f_float2nr },
- { "floor", 1, 1, f_floor },
- { "fmod", 2, 2, f_fmod },
- { "fnameescape", 1, 1, f_fnameescape },
- { "fnamemodify", 2, 2, f_fnamemodify },
- { "foldclosed", 1, 1, f_foldclosed },
- { "foldclosedend", 1, 1, f_foldclosedend },
- { "foldlevel", 1, 1, f_foldlevel },
- { "foldtext", 0, 0, f_foldtext },
- { "foldtextresult", 1, 1, f_foldtextresult },
- { "foreground", 0, 0, f_foreground },
- { "function", 1, 1, f_function },
- { "garbagecollect", 0, 1, f_garbagecollect },
- { "get", 2, 3, f_get },
- { "getbufline", 2, 3, f_getbufline },
- { "getbufvar", 2, 3, f_getbufvar },
- { "getchar", 0, 1, f_getchar },
- { "getcharmod", 0, 0, f_getcharmod },
- { "getcharsearch", 0, 0, f_getcharsearch },
- { "getcmdline", 0, 0, f_getcmdline },
- { "getcmdpos", 0, 0, f_getcmdpos },
- { "getcmdtype", 0, 0, f_getcmdtype },
- { "getcmdwintype", 0, 0, f_getcmdwintype },
- { "getcompletion", 2, 2, f_getcompletion },
- { "getcurpos", 0, 0, f_getcurpos },
- { "getcwd", 0, 2, f_getcwd },
- { "getfontname", 0, 1, f_getfontname },
- { "getfperm", 1, 1, f_getfperm },
- { "getfsize", 1, 1, f_getfsize },
- { "getftime", 1, 1, f_getftime },
- { "getftype", 1, 1, f_getftype },
- { "getline", 1, 2, f_getline },
- { "getloclist", 1, 1, f_getqflist },
- { "getmatches", 0, 0, f_getmatches },
- { "getpid", 0, 0, f_getpid },
- { "getpos", 1, 1, f_getpos },
- { "getqflist", 0, 0, f_getqflist },
- { "getreg", 0, 3, f_getreg },
- { "getregtype", 0, 1, f_getregtype },
- { "gettabvar", 2, 3, f_gettabvar },
- { "gettabwinvar", 3, 4, f_gettabwinvar },
- { "getwinposx", 0, 0, f_getwinposx },
- { "getwinposy", 0, 0, f_getwinposy },
- { "getwinvar", 2, 3, f_getwinvar },
- { "glob", 1, 4, f_glob },
- { "glob2regpat", 1, 1, f_glob2regpat },
- { "globpath", 2, 5, f_globpath },
- { "has", 1, 1, f_has },
- { "has_key", 2, 2, f_has_key },
- { "haslocaldir", 0, 2, f_haslocaldir },
- { "hasmapto", 1, 3, f_hasmapto },
- { "highlightID", 1, 1, f_hlID }, // obsolete
- { "highlight_exists", 1, 1, f_hlexists }, // obsolete
- { "histadd", 2, 2, f_histadd },
- { "histdel", 1, 2, f_histdel },
- { "histget", 1, 2, f_histget },
- { "histnr", 1, 1, f_histnr },
- { "hlID", 1, 1, f_hlID },
- { "hlexists", 1, 1, f_hlexists },
- { "hostname", 0, 0, f_hostname },
- { "iconv", 3, 3, f_iconv },
- { "indent", 1, 1, f_indent },
- { "index", 2, 4, f_index },
- { "input", 1, 3, f_input },
- { "inputdialog", 1, 3, f_inputdialog },
- { "inputlist", 1, 1, f_inputlist },
- { "inputrestore", 0, 0, f_inputrestore },
- { "inputsave", 0, 0, f_inputsave },
- { "inputsecret", 1, 2, f_inputsecret },
- { "insert", 2, 3, f_insert },
- { "invert", 1, 1, f_invert },
- { "isdirectory", 1, 1, f_isdirectory },
- { "islocked", 1, 1, f_islocked },
- { "items", 1, 1, f_items },
- { "jobclose", 1, 2, f_jobclose },
- { "jobpid", 1, 1, f_jobpid },
- { "jobresize", 3, 3, f_jobresize },
- { "jobsend", 2, 2, f_jobsend },
- { "jobstart", 1, 2, f_jobstart },
- { "jobstop", 1, 1, f_jobstop },
- { "jobwait", 1, 2, f_jobwait },
- { "join", 1, 2, f_join },
- { "json_decode", 1, 1, f_json_decode },
- { "json_encode", 1, 1, f_json_encode },
- { "keys", 1, 1, f_keys },
- { "last_buffer_nr", 0, 0, f_last_buffer_nr }, // obsolete
- { "len", 1, 1, f_len },
- { "libcall", 3, 3, f_libcall },
- { "libcallnr", 3, 3, f_libcallnr },
- { "line", 1, 1, f_line },
- { "line2byte", 1, 1, f_line2byte },
- { "lispindent", 1, 1, f_lispindent },
- { "localtime", 0, 0, f_localtime },
- { "log", 1, 1, f_log },
- { "log10", 1, 1, f_log10 },
- { "map", 2, 2, f_map },
- { "maparg", 1, 4, f_maparg },
- { "mapcheck", 1, 3, f_mapcheck },
- { "match", 2, 4, f_match },
- { "matchadd", 2, 5, f_matchadd },
- { "matchaddpos", 2, 5, f_matchaddpos },
- { "matcharg", 1, 1, f_matcharg },
- { "matchdelete", 1, 1, f_matchdelete },
- { "matchend", 2, 4, f_matchend },
- { "matchlist", 2, 4, f_matchlist },
- { "matchstr", 2, 4, f_matchstr },
- { "max", 1, 1, f_max },
- { "min", 1, 1, f_min },
- { "mkdir", 1, 3, f_mkdir },
- { "mode", 0, 1, f_mode },
- { "msgpackdump", 1, 1, f_msgpackdump },
- { "msgpackparse", 1, 1, f_msgpackparse },
- { "nextnonblank", 1, 1, f_nextnonblank },
- { "nr2char", 1, 2, f_nr2char },
- { "or", 2, 2, f_or },
- { "pathshorten", 1, 1, f_pathshorten },
- { "pow", 2, 2, f_pow },
- { "prevnonblank", 1, 1, f_prevnonblank },
- { "printf", 2, MAX_FUNC_ARGS, f_printf },
- { "pumvisible", 0, 0, f_pumvisible },
- { "py3eval", 1, 1, f_py3eval },
- { "pyeval", 1, 1, f_pyeval },
- { "range", 1, 3, f_range },
- { "readfile", 1, 3, f_readfile },
- { "reltime", 0, 2, f_reltime },
- { "reltimefloat", 1, 1, f_reltimefloat },
- { "reltimestr", 1, 1, f_reltimestr },
- { "remove", 2, 3, f_remove },
- { "rename", 2, 2, f_rename },
- { "repeat", 2, 2, f_repeat },
- { "resolve", 1, 1, f_resolve },
- { "reverse", 1, 1, f_reverse },
- { "round", 1, 1, f_round },
- { "rpcnotify", 2, MAX_FUNC_ARGS, f_rpcnotify },
- { "rpcrequest", 2, MAX_FUNC_ARGS, f_rpcrequest },
- { "rpcstart", 1, 2, f_rpcstart },
- { "rpcstop", 1, 1, f_rpcstop },
- { "screenattr", 2, 2, f_screenattr },
- { "screenchar", 2, 2, f_screenchar },
- { "screencol", 0, 0, f_screencol },
- { "screenrow", 0, 0, f_screenrow },
- { "search", 1, 4, f_search },
- { "searchdecl", 1, 3, f_searchdecl },
- { "searchpair", 3, 7, f_searchpair },
- { "searchpairpos", 3, 7, f_searchpairpos },
- { "searchpos", 1, 4, f_searchpos },
- { "serverlist", 0, 0, f_serverlist },
- { "serverstart", 0, 1, f_serverstart },
- { "serverstop", 1, 1, f_serverstop },
- { "setbufvar", 3, 3, f_setbufvar },
- { "setcharsearch", 1, 1, f_setcharsearch },
- { "setcmdpos", 1, 1, f_setcmdpos },
- { "setfperm", 2, 2, f_setfperm },
- { "setline", 2, 2, f_setline },
- { "setloclist", 2, 4, f_setloclist },
- { "setmatches", 1, 1, f_setmatches },
- { "setpos", 2, 2, f_setpos },
- { "setqflist", 1, 3, f_setqflist },
- { "setreg", 2, 3, f_setreg },
- { "settabvar", 3, 3, f_settabvar },
- { "settabwinvar", 4, 4, f_settabwinvar },
- { "setwinvar", 3, 3, f_setwinvar },
- { "sha256", 1, 1, f_sha256 },
- { "shellescape", 1, 2, f_shellescape },
- { "shiftwidth", 0, 0, f_shiftwidth },
- { "simplify", 1, 1, f_simplify },
- { "sin", 1, 1, f_sin },
- { "sinh", 1, 1, f_sinh },
- { "sort", 1, 3, f_sort },
- { "soundfold", 1, 1, f_soundfold },
- { "spellbadword", 0, 1, f_spellbadword },
- { "spellsuggest", 1, 3, f_spellsuggest },
- { "split", 1, 3, f_split },
- { "sqrt", 1, 1, f_sqrt },
- { "str2float", 1, 1, f_str2float },
- { "str2nr", 1, 2, f_str2nr },
- { "strchars", 1, 2, f_strchars },
- { "strdisplaywidth", 1, 2, f_strdisplaywidth },
- { "strftime", 1, 2, f_strftime },
- { "stridx", 2, 3, f_stridx },
- { "string", 1, 1, f_string },
- { "strlen", 1, 1, f_strlen },
- { "strpart", 2, 3, f_strpart },
- { "strridx", 2, 3, f_strridx },
- { "strtrans", 1, 1, f_strtrans },
- { "strwidth", 1, 1, f_strwidth },
- { "submatch", 1, 2, f_submatch },
- { "substitute", 4, 4, f_substitute },
- { "synID", 3, 3, f_synID },
- { "synIDattr", 2, 3, f_synIDattr },
- { "synIDtrans", 1, 1, f_synIDtrans },
- { "synconcealed", 2, 2, f_synconcealed },
- { "synstack", 2, 2, f_synstack },
- { "system", 1, 2, f_system },
- { "systemlist", 1, 3, f_systemlist },
- { "tabpagebuflist", 0, 1, f_tabpagebuflist },
- { "tabpagenr", 0, 1, f_tabpagenr },
- { "tabpagewinnr", 1, 2, f_tabpagewinnr },
- { "tagfiles", 0, 0, f_tagfiles },
- { "taglist", 1, 1, f_taglist },
- { "tan", 1, 1, f_tan },
- { "tanh", 1, 1, f_tanh },
- { "tempname", 0, 0, f_tempname },
- { "termopen", 1, 2, f_termopen },
- { "test", 1, 1, f_test },
- { "timer_start", 2, 3, f_timer_start },
- { "timer_stop", 1, 1, f_timer_stop },
- { "tolower", 1, 1, f_tolower },
- { "toupper", 1, 1, f_toupper },
- { "tr", 3, 3, f_tr },
- { "trunc", 1, 1, f_trunc },
- { "type", 1, 1, f_type },
- { "undofile", 1, 1, f_undofile },
- { "undotree", 0, 0, f_undotree },
- { "uniq", 1, 3, f_uniq },
- { "values", 1, 1, f_values },
- { "virtcol", 1, 1, f_virtcol },
- { "visualmode", 0, 1, f_visualmode },
- { "wildmenumode", 0, 0, f_wildmenumode },
- { "win_getid", 0, 2, f_win_getid },
- { "win_gotoid", 1, 1, f_win_gotoid },
- { "win_id2tabwin", 1, 1, f_win_id2tabwin },
- { "win_id2win", 1, 1, f_win_id2win },
- { "winbufnr", 1, 1, f_winbufnr },
- { "wincol", 0, 0, f_wincol },
- { "winheight", 1, 1, f_winheight },
- { "winline", 0, 0, f_winline },
- { "winnr", 0, 1, f_winnr },
- { "winrestcmd", 0, 0, f_winrestcmd },
- { "winrestview", 1, 1, f_winrestview },
- { "winsaveview", 0, 0, f_winsaveview },
- { "winwidth", 1, 1, f_winwidth },
- { "wordcount", 0, 0, f_wordcount },
- { "writefile", 2, 3, f_writefile },
- { "xor", 2, 2, f_xor },
-};
+#ifdef INCLUDE_GENERATED_DECLARATIONS
+# include "funcs.generated.h"
+#endif
/*
@@ -7024,15 +6720,25 @@ char_u *get_function_name(expand_T *xp, int idx)
if (name != NULL)
return name;
}
- if (++intidx < (int)ARRAY_SIZE(functions)) {
- STRCPY(IObuff, functions[intidx].f_name);
- STRCAT(IObuff, "(");
- if (functions[intidx].f_max_argc == 0)
- STRCAT(IObuff, ")");
- return IObuff;
+ while ( (size_t)++intidx < ARRAY_SIZE(functions)
+ && functions[intidx].name[0] == '\0') {
}
- return NULL;
+ if ((size_t)intidx >= ARRAY_SIZE(functions)) {
+ return NULL;
+ }
+
+ const char *const key = functions[intidx].name;
+ const size_t key_len = strlen(key);
+ memcpy(IObuff, key, key_len);
+ IObuff[key_len] = '(';
+ if (functions[intidx].max_argc == 0) {
+ IObuff[key_len + 1] = ')';
+ IObuff[key_len + 2] = NUL;
+ } else {
+ IObuff[key_len + 1] = NUL;
+ }
+ return IObuff;
}
/*
@@ -7057,32 +6763,16 @@ char_u *get_expr_name(expand_T *xp, int idx)
-/*
- * Find internal function in table above.
- * Return index, or -1 if not found
- */
-static int
-find_internal_func (
- char_u *name /* name of the function */
-)
+/// Find internal function in hash functions
+///
+/// @param[in] name Name of the function.
+///
+/// Returns pointer to the function definition or NULL if not found.
+static VimLFuncDef *find_internal_func(const char *const name)
+ FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_PURE FUNC_ATTR_NONNULL_ALL
{
- int first = 0;
- int last = (int)ARRAY_SIZE(functions) - 1;
-
- /*
- * Find the function name in the table. Binary search.
- */
- while (first <= last) {
- int x = first + ((unsigned)(last - first)) / 2;
- int cmp = STRCMP(name, functions[x].f_name);
- if (cmp < 0)
- last = x - 1;
- else if (cmp > 0)
- first = x + 1;
- else
- return x;
- }
- return -1;
+ size_t len = strlen(name);
+ return find_internal_func_gperf(name, len);
}
/*
@@ -7200,7 +6890,6 @@ call_func (
#define ERROR_NONE 5
#define ERROR_OTHER 6
int error = ERROR_NONE;
- int i;
int llen;
ufunc_T *fp;
#define FLEN_FIXED 40
@@ -7222,12 +6911,13 @@ call_func (
fname_buf[0] = K_SPECIAL;
fname_buf[1] = KS_EXTRA;
fname_buf[2] = (int)KE_SNR;
- i = 3;
- if (eval_fname_sid(name)) { /* "<SID>" or "s:" */
- if (current_SID <= 0)
+ int i = 3;
+ if (eval_fname_sid(name)) { // "<SID>" or "s:"
+ if (current_SID <= 0) {
error = ERROR_SCRIPT;
- else {
- sprintf((char *)fname_buf + 3, "%" PRId64 "_", (int64_t)current_SID);
+ } else {
+ vim_snprintf((char *)fname_buf + 3, ARRAY_SIZE(fname_buf) - 3,
+ "%" PRId64 "_", (int64_t)current_SID);
i = (int)STRLEN(fname_buf);
}
}
@@ -7294,18 +6984,16 @@ call_func (
}
}
} else {
- /*
- * Find the function name in the table, call its implementation.
- */
- i = find_internal_func(fname);
- if (i >= 0) {
- if (argcount < functions[i].f_min_argc)
+ // Find the function name in the table, call its implementation.
+ VimLFuncDef *const fdef = find_internal_func((char *)fname);
+ if (fdef != NULL) {
+ if (argcount < fdef->min_argc) {
error = ERROR_TOOFEW;
- else if (argcount > functions[i].f_max_argc)
+ } else if (argcount > fdef->max_argc) {
error = ERROR_TOOMANY;
- else {
+ } else {
argvars[argcount].v_type = VAR_UNKNOWN;
- functions[i].f_func(argvars, rettv);
+ fdef->func(argvars, rettv, fdef->data);
error = ERROR_NONE;
}
}
@@ -7416,13 +7104,10 @@ static inline int get_float_arg(typval_T *argvars, float_T *f)
// Some versions of glibc on i386 have an optimization that makes it harder to
// call math functions indirectly from inside an inlined function, causing
// compile-time errors. Avoid `inline` in that case. #3072
-#ifndef ARCH_32
-inline
-#endif
-static void float_op_wrapper(typval_T *argvars, typval_T *rettv,
- float_T (*function)(float_T))
+static void float_op_wrapper(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
float_T f;
+ float_T (*function)(float_T) = (float_T (*)(float_T))fptr;
rettv->v_type = VAR_FLOAT;
if (get_float_arg(argvars, &f) == OK) {
@@ -7432,13 +7117,40 @@ static void float_op_wrapper(typval_T *argvars, typval_T *rettv,
}
}
+static void api_wrapper(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+{
+ ApiDispatchWrapper fn = (ApiDispatchWrapper)fptr;
+
+ Array args = ARRAY_DICT_INIT;
+
+ for (typval_T *tv = argvars; tv->v_type != VAR_UNKNOWN; tv++) {
+ ADD(args, vim_to_object(tv));
+ }
+
+ Error err = ERROR_INIT;
+ Object result = fn(INVALID_CHANNEL, NO_RESPONSE, args, &err);
+
+ if (err.set) {
+ nvim_err_writeln(cstr_as_string(err.msg));
+ goto end;
+ }
+
+ if (!object_to_vim(result, rettv, &err)) {
+ EMSG2(_("Error converting the call result: %s"), err.msg);
+ }
+
+end:
+ api_free_array(args);
+ api_free_object(result);
+}
+
/*
* "abs(expr)" function
*/
-static void f_abs(typval_T *argvars, typval_T *rettv)
+static void f_abs(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
if (argvars[0].v_type == VAR_FLOAT) {
- float_op_wrapper(argvars, rettv, &fabs);
+ float_op_wrapper(argvars, rettv, (FunPtr)&fabs);
} else {
varnumber_T n;
int error = FALSE;
@@ -7454,17 +7166,9 @@ static void f_abs(typval_T *argvars, typval_T *rettv)
}
/*
- * "acos()" function
- */
-static void f_acos(typval_T *argvars, typval_T *rettv)
-{
- float_op_wrapper(argvars, rettv, &acos);
-}
-
-/*
* "add(list, item)" function
*/
-static void f_add(typval_T *argvars, typval_T *rettv)
+static void f_add(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
list_T *l;
@@ -7483,7 +7187,7 @@ static void f_add(typval_T *argvars, typval_T *rettv)
/*
* "and(expr, expr)" function
*/
-static void f_and(typval_T *argvars, typval_T *rettv)
+static void f_and(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
rettv->vval.v_number = get_tv_number_chk(&argvars[0], NULL)
& get_tv_number_chk(&argvars[1], NULL);
@@ -7491,7 +7195,7 @@ static void f_and(typval_T *argvars, typval_T *rettv)
/// "api_info()" function
-static void f_api_info(typval_T *argvars, typval_T *rettv)
+static void f_api_info(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
Dictionary metadata = api_metadata();
(void)object_to_vim(DICTIONARY_OBJ(metadata), rettv, NULL);
@@ -7501,7 +7205,7 @@ static void f_api_info(typval_T *argvars, typval_T *rettv)
/*
* "append(lnum, string/list)" function
*/
-static void f_append(typval_T *argvars, typval_T *rettv)
+static void f_append(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
long lnum;
char_u *line;
@@ -7556,7 +7260,7 @@ static void f_append(typval_T *argvars, typval_T *rettv)
/*
* "argc()" function
*/
-static void f_argc(typval_T *argvars, typval_T *rettv)
+static void f_argc(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
rettv->vval.v_number = ARGCOUNT;
}
@@ -7564,13 +7268,13 @@ static void f_argc(typval_T *argvars, typval_T *rettv)
/*
* "argidx()" function
*/
-static void f_argidx(typval_T *argvars, typval_T *rettv)
+static void f_argidx(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
rettv->vval.v_number = curwin->w_arg_idx;
}
/// "arglistid" function
-static void f_arglistid(typval_T *argvars, typval_T *rettv)
+static void f_arglistid(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
rettv->vval.v_number = -1;
win_T *wp = find_tabwin(&argvars[0], &argvars[1]);
@@ -7582,7 +7286,7 @@ static void f_arglistid(typval_T *argvars, typval_T *rettv)
/*
* "argv(nr)" function
*/
-static void f_argv(typval_T *argvars, typval_T *rettv)
+static void f_argv(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
int idx;
@@ -7689,19 +7393,19 @@ static void assert_equal_common(typval_T *argvars, assert_type_T atype)
}
// "assert_equal(expected, actual[, msg])" function
-static void f_assert_equal(typval_T *argvars, typval_T *rettv)
+static void f_assert_equal(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
assert_equal_common(argvars, ASSERT_EQUAL);
}
// "assert_notequal(expected, actual[, msg])" function
-static void f_assert_notequal(typval_T *argvars, typval_T *rettv)
+static void f_assert_notequal(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
assert_equal_common(argvars, ASSERT_NOTEQUAL);
}
/// "assert_exception(string[, msg])" function
-static void f_assert_exception(typval_T *argvars, typval_T *rettv)
+static void f_assert_exception(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
garray_T ga;
@@ -7722,7 +7426,7 @@ static void f_assert_exception(typval_T *argvars, typval_T *rettv)
}
/// "assert_fails(cmd [, error])" function
-static void f_assert_fails(typval_T *argvars, typval_T *rettv)
+static void f_assert_fails(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
char_u *cmd = get_tv_string_chk(&argvars[0]);
garray_T ga;
@@ -7782,7 +7486,7 @@ static void assert_bool(typval_T *argvars, bool is_true)
}
// "assert_false(actual[, msg])" function
-static void f_assert_false(typval_T *argvars, typval_T *rettv)
+static void f_assert_false(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
assert_bool(argvars, false);
}
@@ -7806,43 +7510,27 @@ static void assert_match_common(typval_T *argvars, assert_type_T atype)
}
/// "assert_match(pattern, actual[, msg])" function
-static void f_assert_match(typval_T *argvars, typval_T *rettv)
+static void f_assert_match(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
assert_match_common(argvars, ASSERT_MATCH);
}
/// "assert_notmatch(pattern, actual[, msg])" function
-static void f_assert_notmatch(typval_T *argvars, typval_T *rettv)
+static void f_assert_notmatch(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
assert_match_common(argvars, ASSERT_NOTMATCH);
}
// "assert_true(actual[, msg])" function
-static void f_assert_true(typval_T *argvars, typval_T *rettv)
+static void f_assert_true(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
assert_bool(argvars, true);
}
/*
- * "asin()" function
- */
-static void f_asin(typval_T *argvars, typval_T *rettv)
-{
- float_op_wrapper(argvars, rettv, &asin);
-}
-
-/*
- * "atan()" function
- */
-static void f_atan(typval_T *argvars, typval_T *rettv)
-{
- float_op_wrapper(argvars, rettv, &atan);
-}
-
-/*
* "atan2()" function
*/
-static void f_atan2(typval_T *argvars, typval_T *rettv)
+static void f_atan2(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
float_T fx, fy;
@@ -7857,7 +7545,7 @@ static void f_atan2(typval_T *argvars, typval_T *rettv)
/*
* "browse(save, title, initdir, default)" function
*/
-static void f_browse(typval_T *argvars, typval_T *rettv)
+static void f_browse(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
rettv->vval.v_string = NULL;
rettv->v_type = VAR_STRING;
@@ -7866,9 +7554,9 @@ static void f_browse(typval_T *argvars, typval_T *rettv)
/*
* "browsedir(title, initdir)" function
*/
-static void f_browsedir(typval_T *argvars, typval_T *rettv)
+static void f_browsedir(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
- f_browse(argvars, rettv);
+ f_browse(argvars, rettv, NULL);
}
@@ -7904,7 +7592,7 @@ static buf_T *find_buffer(typval_T *avar)
/*
* "bufexists(expr)" function
*/
-static void f_bufexists(typval_T *argvars, typval_T *rettv)
+static void f_bufexists(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
rettv->vval.v_number = (find_buffer(&argvars[0]) != NULL);
}
@@ -7912,7 +7600,7 @@ static void f_bufexists(typval_T *argvars, typval_T *rettv)
/*
* "buflisted(expr)" function
*/
-static void f_buflisted(typval_T *argvars, typval_T *rettv)
+static void f_buflisted(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
buf_T *buf;
@@ -7923,7 +7611,7 @@ static void f_buflisted(typval_T *argvars, typval_T *rettv)
/*
* "bufloaded(expr)" function
*/
-static void f_bufloaded(typval_T *argvars, typval_T *rettv)
+static void f_bufloaded(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
buf_T *buf;
@@ -7973,7 +7661,7 @@ static buf_T *get_buf_tv(typval_T *tv, int curtab_only)
/*
* "bufname(expr)" function
*/
-static void f_bufname(typval_T *argvars, typval_T *rettv)
+static void f_bufname(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
buf_T *buf;
@@ -7991,7 +7679,7 @@ static void f_bufname(typval_T *argvars, typval_T *rettv)
/*
* "bufnr(expr)" function
*/
-static void f_bufnr(typval_T *argvars, typval_T *rettv)
+static void f_bufnr(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
buf_T *buf;
int error = FALSE;
@@ -8021,7 +7709,7 @@ static void f_bufnr(typval_T *argvars, typval_T *rettv)
/*
* "bufwinnr(nr)" function
*/
-static void f_bufwinnr(typval_T *argvars, typval_T *rettv)
+static void f_bufwinnr(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
(void)get_tv_number(&argvars[0]); /* issue errmsg if type error */
++emsg_off;
@@ -8043,7 +7731,7 @@ static void f_bufwinnr(typval_T *argvars, typval_T *rettv)
/*
* "byte2line(byte)" function
*/
-static void f_byte2line(typval_T *argvars, typval_T *rettv)
+static void f_byte2line(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
long boff = 0;
@@ -8082,7 +7770,7 @@ static void byteidx(typval_T *argvars, typval_T *rettv, int comp)
/*
* "byteidx()" function
*/
-static void f_byteidx(typval_T *argvars, typval_T *rettv)
+static void f_byteidx(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
byteidx(argvars, rettv, FALSE);
}
@@ -8090,7 +7778,7 @@ static void f_byteidx(typval_T *argvars, typval_T *rettv)
/*
* "byteidxcomp()" function
*/
-static void f_byteidxcomp(typval_T *argvars, typval_T *rettv)
+static void f_byteidxcomp(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
byteidx(argvars, rettv, TRUE);
}
@@ -8130,7 +7818,7 @@ int func_call(char_u *name, typval_T *args, dict_T *selfdict, typval_T *rettv)
/*
* "call(func, arglist)" function
*/
-static void f_call(typval_T *argvars, typval_T *rettv)
+static void f_call(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
char_u *func;
dict_T *selfdict = NULL;
@@ -8161,17 +7849,9 @@ static void f_call(typval_T *argvars, typval_T *rettv)
}
/*
- * "ceil({float})" function
- */
-static void f_ceil(typval_T *argvars, typval_T *rettv)
-{
- float_op_wrapper(argvars, rettv, &ceil);
-}
-
-/*
* "changenr()" function
*/
-static void f_changenr(typval_T *argvars, typval_T *rettv)
+static void f_changenr(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
rettv->vval.v_number = curbuf->b_u_seq_cur;
}
@@ -8179,7 +7859,7 @@ static void f_changenr(typval_T *argvars, typval_T *rettv)
/*
* "char2nr(string)" function
*/
-static void f_char2nr(typval_T *argvars, typval_T *rettv)
+static void f_char2nr(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
if (has_mbyte) {
int utf8 = 0;
@@ -8198,7 +7878,7 @@ static void f_char2nr(typval_T *argvars, typval_T *rettv)
/*
* "cindent(lnum)" function
*/
-static void f_cindent(typval_T *argvars, typval_T *rettv)
+static void f_cindent(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
pos_T pos;
linenr_T lnum;
@@ -8216,7 +7896,7 @@ static void f_cindent(typval_T *argvars, typval_T *rettv)
/*
* "clearmatches()" function
*/
-static void f_clearmatches(typval_T *argvars, typval_T *rettv)
+static void f_clearmatches(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
clear_matches(curwin);
}
@@ -8224,7 +7904,7 @@ static void f_clearmatches(typval_T *argvars, typval_T *rettv)
/*
* "col(string)" function
*/
-static void f_col(typval_T *argvars, typval_T *rettv)
+static void f_col(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
colnr_T col = 0;
pos_T *fp;
@@ -8261,7 +7941,7 @@ static void f_col(typval_T *argvars, typval_T *rettv)
/*
* "complete()" function
*/
-static void f_complete(typval_T *argvars, typval_T *rettv)
+static void f_complete(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
int startcol;
@@ -8290,7 +7970,7 @@ static void f_complete(typval_T *argvars, typval_T *rettv)
/*
* "complete_add()" function
*/
-static void f_complete_add(typval_T *argvars, typval_T *rettv)
+static void f_complete_add(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
rettv->vval.v_number = ins_compl_add_tv(&argvars[0], 0);
}
@@ -8298,7 +7978,7 @@ static void f_complete_add(typval_T *argvars, typval_T *rettv)
/*
* "complete_check()" function
*/
-static void f_complete_check(typval_T *argvars, typval_T *rettv)
+static void f_complete_check(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
int saved = RedrawingDisabled;
@@ -8311,7 +7991,7 @@ static void f_complete_check(typval_T *argvars, typval_T *rettv)
/*
* "confirm(message, buttons[, default [, type]])" function
*/
-static void f_confirm(typval_T *argvars, typval_T *rettv)
+static void f_confirm(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
char_u *message;
char_u *buttons = NULL;
@@ -8359,31 +8039,15 @@ static void f_confirm(typval_T *argvars, typval_T *rettv)
/*
* "copy()" function
*/
-static void f_copy(typval_T *argvars, typval_T *rettv)
+static void f_copy(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
var_item_copy(NULL, &argvars[0], rettv, false, 0);
}
/*
- * "cos()" function
- */
-static void f_cos(typval_T *argvars, typval_T *rettv)
-{
- float_op_wrapper(argvars, rettv, &cos);
-}
-
-/*
- * "cosh()" function
- */
-static void f_cosh(typval_T *argvars, typval_T *rettv)
-{
- float_op_wrapper(argvars, rettv, &cosh);
-}
-
-/*
* "count()" function
*/
-static void f_count(typval_T *argvars, typval_T *rettv)
+static void f_count(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
long n = 0;
int ic = FALSE;
@@ -8448,7 +8112,7 @@ static void f_count(typval_T *argvars, typval_T *rettv)
*
* Checks the existence of a cscope connection.
*/
-static void f_cscope_connection(typval_T *argvars, typval_T *rettv)
+static void f_cscope_connection(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
int num = 0;
char_u *dbpath = NULL;
@@ -8472,7 +8136,7 @@ static void f_cscope_connection(typval_T *argvars, typval_T *rettv)
/// Moves the cursor to the specified line and column.
///
/// @returns 0 when the position could be set, -1 otherwise.
-static void f_cursor(typval_T *argvars, typval_T *rettv)
+static void f_cursor(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
long line, col;
long coladd = 0;
@@ -8528,7 +8192,7 @@ static void f_cursor(typval_T *argvars, typval_T *rettv)
/*
* "deepcopy()" function
*/
-static void f_deepcopy(typval_T *argvars, typval_T *rettv)
+static void f_deepcopy(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
int noref = 0;
@@ -8544,7 +8208,7 @@ static void f_deepcopy(typval_T *argvars, typval_T *rettv)
}
// "delete()" function
-static void f_delete(typval_T *argvars, typval_T *rettv)
+static void f_delete(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
char_u nbuf[NUMBUFLEN];
char_u *name;
@@ -8582,7 +8246,7 @@ static void f_delete(typval_T *argvars, typval_T *rettv)
}
// dictwatcheradd(dict, key, funcref) function
-static void f_dictwatcheradd(typval_T *argvars, typval_T *rettv)
+static void f_dictwatcheradd(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
if (check_restricted() || check_secure()) {
return;
@@ -8627,7 +8291,7 @@ static void f_dictwatcheradd(typval_T *argvars, typval_T *rettv)
}
// dictwatcherdel(dict, key, funcref) function
-static void f_dictwatcherdel(typval_T *argvars, typval_T *rettv)
+static void f_dictwatcherdel(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
if (check_restricted() || check_secure()) {
return;
@@ -8688,7 +8352,7 @@ static void f_dictwatcherdel(typval_T *argvars, typval_T *rettv)
/*
* "did_filetype()" function
*/
-static void f_did_filetype(typval_T *argvars, typval_T *rettv)
+static void f_did_filetype(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
rettv->vval.v_number = did_filetype;
}
@@ -8696,7 +8360,7 @@ static void f_did_filetype(typval_T *argvars, typval_T *rettv)
/*
* "diff_filler()" function
*/
-static void f_diff_filler(typval_T *argvars, typval_T *rettv)
+static void f_diff_filler(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
rettv->vval.v_number = diff_check_fill(curwin, get_tv_lnum(argvars));
}
@@ -8704,7 +8368,7 @@ static void f_diff_filler(typval_T *argvars, typval_T *rettv)
/*
* "diff_hlID()" function
*/
-static void f_diff_hlID(typval_T *argvars, typval_T *rettv)
+static void f_diff_hlID(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
linenr_T lnum = get_tv_lnum(argvars);
static linenr_T prev_lnum = 0;
@@ -8753,7 +8417,7 @@ static void f_diff_hlID(typval_T *argvars, typval_T *rettv)
/*
* "empty({expr})" function
*/
-static void f_empty(typval_T *argvars, typval_T *rettv)
+static void f_empty(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
bool n = true;
@@ -8791,7 +8455,7 @@ static void f_empty(typval_T *argvars, typval_T *rettv)
/*
* "escape({string}, {chars})" function
*/
-static void f_escape(typval_T *argvars, typval_T *rettv)
+static void f_escape(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
char_u buf[NUMBUFLEN];
@@ -8803,7 +8467,7 @@ static void f_escape(typval_T *argvars, typval_T *rettv)
/*
* "eval()" function
*/
-static void f_eval(typval_T *argvars, typval_T *rettv)
+static void f_eval(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
char_u *s;
@@ -8827,7 +8491,7 @@ static void f_eval(typval_T *argvars, typval_T *rettv)
/*
* "eventhandler()" function
*/
-static void f_eventhandler(typval_T *argvars, typval_T *rettv)
+static void f_eventhandler(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
rettv->vval.v_number = vgetc_busy;
}
@@ -8835,7 +8499,7 @@ static void f_eventhandler(typval_T *argvars, typval_T *rettv)
/*
* "executable()" function
*/
-static void f_executable(typval_T *argvars, typval_T *rettv)
+static void f_executable(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
char_u *name = get_tv_string(&argvars[0]);
@@ -8845,7 +8509,7 @@ static void f_executable(typval_T *argvars, typval_T *rettv)
}
// "execute(command)" function
-static void f_execute(typval_T *argvars, typval_T *rettv)
+static void f_execute(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
int save_msg_silent = msg_silent;
garray_T *save_capture_ga = capture_ga;
@@ -8877,7 +8541,7 @@ static void f_execute(typval_T *argvars, typval_T *rettv)
}
/// "exepath()" function
-static void f_exepath(typval_T *argvars, typval_T *rettv)
+static void f_exepath(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
char_u *arg = get_tv_string(&argvars[0]);
char_u *path = NULL;
@@ -8891,7 +8555,7 @@ static void f_exepath(typval_T *argvars, typval_T *rettv)
/*
* "exists()" function
*/
-static void f_exists(typval_T *argvars, typval_T *rettv)
+static void f_exists(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
char_u *p;
char_u *name;
@@ -8952,17 +8616,9 @@ static void f_exists(typval_T *argvars, typval_T *rettv)
}
/*
- * "exp()" function
- */
-static void f_exp(typval_T *argvars, typval_T *rettv)
-{
- float_op_wrapper(argvars, rettv, &exp);
-}
-
-/*
* "expand()" function
*/
-static void f_expand(typval_T *argvars, typval_T *rettv)
+static void f_expand(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
char_u *s;
size_t len;
@@ -9091,7 +8747,7 @@ void dict_extend(dict_T *d1, dict_T *d2, char_u *action)
* "extend(list, list [, idx])" function
* "extend(dict, dict [, action])" function
*/
-static void f_extend(typval_T *argvars, typval_T *rettv)
+static void f_extend(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
char_u *arg_errmsg = (char_u *)N_("extend() argument");
@@ -9163,7 +8819,7 @@ static void f_extend(typval_T *argvars, typval_T *rettv)
/*
* "feedkeys()" function
*/
-static void f_feedkeys(typval_T *argvars, typval_T *rettv)
+static void f_feedkeys(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
char_u *keys, *flags = NULL;
char_u nbuf[NUMBUFLEN];
@@ -9175,18 +8831,17 @@ static void f_feedkeys(typval_T *argvars, typval_T *rettv)
return;
keys = get_tv_string(&argvars[0]);
- if (*keys != NUL) {
- if (argvars[1].v_type != VAR_UNKNOWN) {
- flags = get_tv_string_buf(&argvars[1], nbuf);
- }
- vim_feedkeys(cstr_as_string((char *)keys),
- cstr_as_string((char *)flags), true);
+ if (argvars[1].v_type != VAR_UNKNOWN) {
+ flags = get_tv_string_buf(&argvars[1], nbuf);
}
+
+ nvim_feedkeys(cstr_as_string((char *)keys),
+ cstr_as_string((char *)flags), true);
}
/// "filereadable()" function
-static void f_filereadable(typval_T *argvars, typval_T *rettv)
+static void f_filereadable(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
char_u *p = get_tv_string(&argvars[0]);
rettv->vval.v_number =
@@ -9197,7 +8852,7 @@ static void f_filereadable(typval_T *argvars, typval_T *rettv)
* Return 0 for not writable, 1 for writable file, 2 for a dir which we have
* rights to write into.
*/
-static void f_filewritable(typval_T *argvars, typval_T *rettv)
+static void f_filewritable(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
char *filename = (char *)get_tv_string(&argvars[0]);
rettv->vval.v_number = os_file_is_writable(filename);
@@ -9412,7 +9067,7 @@ theend:
/*
* "filter()" function
*/
-static void f_filter(typval_T *argvars, typval_T *rettv)
+static void f_filter(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
filter_map(argvars, rettv, FALSE);
}
@@ -9420,7 +9075,7 @@ static void f_filter(typval_T *argvars, typval_T *rettv)
/*
* "finddir({fname}[, {path}[, {count}]])" function
*/
-static void f_finddir(typval_T *argvars, typval_T *rettv)
+static void f_finddir(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
findfilendir(argvars, rettv, FINDFILE_DIR);
}
@@ -9428,7 +9083,7 @@ static void f_finddir(typval_T *argvars, typval_T *rettv)
/*
* "findfile({fname}[, {path}[, {count}]])" function
*/
-static void f_findfile(typval_T *argvars, typval_T *rettv)
+static void f_findfile(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
findfilendir(argvars, rettv, FINDFILE_FILE);
}
@@ -9436,7 +9091,7 @@ static void f_findfile(typval_T *argvars, typval_T *rettv)
/*
* "float2nr({float})" function
*/
-static void f_float2nr(typval_T *argvars, typval_T *rettv)
+static void f_float2nr(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
float_T f;
@@ -9451,17 +9106,9 @@ static void f_float2nr(typval_T *argvars, typval_T *rettv)
}
/*
- * "floor({float})" function
- */
-static void f_floor(typval_T *argvars, typval_T *rettv)
-{
- float_op_wrapper(argvars, rettv, &floor);
-}
-
-/*
* "fmod()" function
*/
-static void f_fmod(typval_T *argvars, typval_T *rettv)
+static void f_fmod(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
float_T fx, fy;
@@ -9476,7 +9123,7 @@ static void f_fmod(typval_T *argvars, typval_T *rettv)
/*
* "fnameescape({string})" function
*/
-static void f_fnameescape(typval_T *argvars, typval_T *rettv)
+static void f_fnameescape(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
rettv->vval.v_string = vim_strsave_fnameescape(
get_tv_string(&argvars[0]), FALSE);
@@ -9486,7 +9133,7 @@ static void f_fnameescape(typval_T *argvars, typval_T *rettv)
/*
* "fnamemodify({fname}, {mods})" function
*/
-static void f_fnamemodify(typval_T *argvars, typval_T *rettv)
+static void f_fnamemodify(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
char_u *fname;
char_u *mods;
@@ -9537,7 +9184,7 @@ static void foldclosed_both(typval_T *argvars, typval_T *rettv, int end)
/*
* "foldclosed()" function
*/
-static void f_foldclosed(typval_T *argvars, typval_T *rettv)
+static void f_foldclosed(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
foldclosed_both(argvars, rettv, FALSE);
}
@@ -9545,7 +9192,7 @@ static void f_foldclosed(typval_T *argvars, typval_T *rettv)
/*
* "foldclosedend()" function
*/
-static void f_foldclosedend(typval_T *argvars, typval_T *rettv)
+static void f_foldclosedend(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
foldclosed_both(argvars, rettv, TRUE);
}
@@ -9553,7 +9200,7 @@ static void f_foldclosedend(typval_T *argvars, typval_T *rettv)
/*
* "foldlevel()" function
*/
-static void f_foldlevel(typval_T *argvars, typval_T *rettv)
+static void f_foldlevel(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
linenr_T lnum;
@@ -9565,7 +9212,7 @@ static void f_foldlevel(typval_T *argvars, typval_T *rettv)
/*
* "foldtext()" function
*/
-static void f_foldtext(typval_T *argvars, typval_T *rettv)
+static void f_foldtext(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
linenr_T lnum;
char_u *s;
@@ -9618,7 +9265,7 @@ static void f_foldtext(typval_T *argvars, typval_T *rettv)
/*
* "foldtextresult(lnum)" function
*/
-static void f_foldtextresult(typval_T *argvars, typval_T *rettv)
+static void f_foldtextresult(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
linenr_T lnum;
char_u *text;
@@ -9645,14 +9292,14 @@ static void f_foldtextresult(typval_T *argvars, typval_T *rettv)
/*
* "foreground()" function
*/
-static void f_foreground(typval_T *argvars, typval_T *rettv)
+static void f_foreground(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
}
/*
* "function()" function
*/
-static void f_function(typval_T *argvars, typval_T *rettv)
+static void f_function(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
char_u *s;
@@ -9684,7 +9331,7 @@ static void f_function(typval_T *argvars, typval_T *rettv)
/*
* "garbagecollect()" function
*/
-static void f_garbagecollect(typval_T *argvars, typval_T *rettv)
+static void f_garbagecollect(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
/* This is postponed until we are back at the toplevel, because we may be
* using Lists and Dicts internally. E.g.: ":echo [garbagecollect()]". */
@@ -9697,7 +9344,7 @@ static void f_garbagecollect(typval_T *argvars, typval_T *rettv)
/*
* "get()" function
*/
-static void f_get(typval_T *argvars, typval_T *rettv)
+static void f_get(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
listitem_T *li;
list_T *l;
@@ -9773,7 +9420,7 @@ static void get_buffer_lines(buf_T *buf, linenr_T start, linenr_T end, int retli
/*
* "getbufline()" function
*/
-static void f_getbufline(typval_T *argvars, typval_T *rettv)
+static void f_getbufline(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
linenr_T lnum;
linenr_T end;
@@ -9796,7 +9443,7 @@ static void f_getbufline(typval_T *argvars, typval_T *rettv)
/*
* "getbufvar()" function
*/
-static void f_getbufvar(typval_T *argvars, typval_T *rettv)
+static void f_getbufvar(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
buf_T *buf;
buf_T *save_curbuf;
@@ -9849,7 +9496,7 @@ static void f_getbufvar(typval_T *argvars, typval_T *rettv)
/*
* "getchar()" function
*/
-static void f_getchar(typval_T *argvars, typval_T *rettv)
+static void f_getchar(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
varnumber_T n;
int error = FALSE;
@@ -9933,7 +9580,7 @@ static void f_getchar(typval_T *argvars, typval_T *rettv)
/*
* "getcharmod()" function
*/
-static void f_getcharmod(typval_T *argvars, typval_T *rettv)
+static void f_getcharmod(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
rettv->vval.v_number = mod_mask;
}
@@ -9941,7 +9588,7 @@ static void f_getcharmod(typval_T *argvars, typval_T *rettv)
/*
* "getcharsearch()" function
*/
-static void f_getcharsearch(typval_T *argvars, typval_T *rettv)
+static void f_getcharsearch(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
rettv_dict_alloc(rettv);
@@ -9955,7 +9602,7 @@ static void f_getcharsearch(typval_T *argvars, typval_T *rettv)
/*
* "getcmdline()" function
*/
-static void f_getcmdline(typval_T *argvars, typval_T *rettv)
+static void f_getcmdline(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
rettv->v_type = VAR_STRING;
rettv->vval.v_string = get_cmdline_str();
@@ -9964,7 +9611,7 @@ static void f_getcmdline(typval_T *argvars, typval_T *rettv)
/*
* "getcmdpos()" function
*/
-static void f_getcmdpos(typval_T *argvars, typval_T *rettv)
+static void f_getcmdpos(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
rettv->vval.v_number = get_cmdline_pos() + 1;
}
@@ -9972,7 +9619,7 @@ static void f_getcmdpos(typval_T *argvars, typval_T *rettv)
/*
* "getcmdtype()" function
*/
-static void f_getcmdtype(typval_T *argvars, typval_T *rettv)
+static void f_getcmdtype(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
rettv->v_type = VAR_STRING;
rettv->vval.v_string = xmallocz(1);
@@ -9982,7 +9629,7 @@ static void f_getcmdtype(typval_T *argvars, typval_T *rettv)
/*
* "getcmdwintype()" function
*/
-static void f_getcmdwintype(typval_T *argvars, typval_T *rettv)
+static void f_getcmdwintype(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
rettv->v_type = VAR_STRING;
rettv->vval.v_string = NULL;
@@ -9991,7 +9638,7 @@ static void f_getcmdwintype(typval_T *argvars, typval_T *rettv)
}
// "getcompletion()" function
-static void f_getcompletion(typval_T *argvars, typval_T *rettv)
+static void f_getcompletion(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
char_u *pat;
expand_T xpc;
@@ -10021,12 +9668,11 @@ static void f_getcompletion(typval_T *argvars, typval_T *rettv)
}
pat = addstar(xpc.xp_pattern, xpc.xp_pattern_len, xpc.xp_context);
- if ((rettv_list_alloc(rettv) != FAIL) && (pat != NULL)) {
- int i;
-
+ rettv_list_alloc(rettv);
+ if (pat != NULL) {
ExpandOne(&xpc, pat, NULL, options, WILD_ALL_KEEP);
- for (i = 0; i < xpc.xp_numfiles; i++) {
+ for (int i = 0; i < xpc.xp_numfiles; i++) {
list_append_string(rettv->vval.v_list, xpc.xp_files[i], -1);
}
}
@@ -10043,7 +9689,7 @@ static void f_getcompletion(typval_T *argvars, typval_T *rettv)
/// @pre An argument may not be -1 if preceding arguments are not all -1.
///
/// @post The return value will be a string.
-static void f_getcwd(typval_T *argvars, typval_T *rettv)
+static void f_getcwd(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
// Possible scope of working directory to return.
CdScope scope = kCdScopeInvalid;
@@ -10128,26 +9774,20 @@ static void f_getcwd(typval_T *argvars, typval_T *rettv)
if (from) {
break;
}
- case kCdScopeTab: // FALLTHROUGH
+ case kCdScopeTab: // FALLTHROUGH
assert(tp);
from = tp->localdir;
if (from) {
break;
}
- case kCdScopeGlobal: // FALLTHROUGH
- // The `globaldir` variable is not always set.
- if (globaldir) {
+ case kCdScopeGlobal: // FALLTHROUGH
+ if (globaldir) { // `globaldir` is not always set.
from = globaldir;
- } else {
- // We have to copy the OS path directly into output string.
- if (os_dirname(cwd, MAXPATHL) == FAIL) {
- EMSG(_("E41: Could not display path."));
- goto end;
- }
+ } else if (os_dirname(cwd, MAXPATHL) == FAIL) { // Get the OS CWD.
+ from = (char_u *)""; // Return empty string on failure.
}
break;
- case kCdScopeInvalid:
- // We should never get here
+ case kCdScopeInvalid: // We should never get here
assert(false);
}
@@ -10159,14 +9799,14 @@ static void f_getcwd(typval_T *argvars, typval_T *rettv)
#ifdef BACKSLASH_IN_FILENAME
slash_adjust(rettv->vval.v_string);
#endif
-end:
+
xfree(cwd);
}
/*
* "getfontname()" function
*/
-static void f_getfontname(typval_T *argvars, typval_T *rettv)
+static void f_getfontname(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
rettv->v_type = VAR_STRING;
rettv->vval.v_string = NULL;
@@ -10175,7 +9815,7 @@ static void f_getfontname(typval_T *argvars, typval_T *rettv)
/*
* "getfperm({fname})" function
*/
-static void f_getfperm(typval_T *argvars, typval_T *rettv)
+static void f_getfperm(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
char_u *perm = NULL;
char_u flags[] = "rwx";
@@ -10196,7 +9836,7 @@ static void f_getfperm(typval_T *argvars, typval_T *rettv)
/*
* "getfsize({fname})" function
*/
-static void f_getfsize(typval_T *argvars, typval_T *rettv)
+static void f_getfsize(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
char *fname = (char *)get_tv_string(&argvars[0]);
@@ -10223,7 +9863,7 @@ static void f_getfsize(typval_T *argvars, typval_T *rettv)
/*
* "getftime({fname})" function
*/
-static void f_getftime(typval_T *argvars, typval_T *rettv)
+static void f_getftime(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
char *fname = (char *)get_tv_string(&argvars[0]);
@@ -10238,7 +9878,7 @@ static void f_getftime(typval_T *argvars, typval_T *rettv)
/*
* "getftype({fname})" function
*/
-static void f_getftype(typval_T *argvars, typval_T *rettv)
+static void f_getftype(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
char_u *fname;
char_u *type = NULL;
@@ -10314,7 +9954,7 @@ static void f_getftype(typval_T *argvars, typval_T *rettv)
/*
* "getline(lnum, [end])" function
*/
-static void f_getline(typval_T *argvars, typval_T *rettv)
+static void f_getline(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
linenr_T lnum;
linenr_T end;
@@ -10335,7 +9975,7 @@ static void f_getline(typval_T *argvars, typval_T *rettv)
/*
* "getmatches()" function
*/
-static void f_getmatches(typval_T *argvars, typval_T *rettv)
+static void f_getmatches(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
matchitem_T *cur = curwin->w_match_head;
int i;
@@ -10384,7 +10024,7 @@ static void f_getmatches(typval_T *argvars, typval_T *rettv)
/*
* "getpid()" function
*/
-static void f_getpid(typval_T *argvars, typval_T *rettv)
+static void f_getpid(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
rettv->vval.v_number = os_get_pid();
}
@@ -10420,7 +10060,7 @@ static void getpos_both(typval_T *argvars, typval_T *rettv, bool getcurpos)
/*
* "getcurpos(string)" function
*/
-static void f_getcurpos(typval_T *argvars, typval_T *rettv)
+static void f_getcurpos(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
getpos_both(argvars, rettv, true);
}
@@ -10428,7 +10068,7 @@ static void f_getcurpos(typval_T *argvars, typval_T *rettv)
/*
* "getpos(string)" function
*/
-static void f_getpos(typval_T *argvars, typval_T *rettv)
+static void f_getpos(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
getpos_both(argvars, rettv, false);
}
@@ -10436,7 +10076,7 @@ static void f_getpos(typval_T *argvars, typval_T *rettv)
/*
* "getqflist()" and "getloclist()" functions
*/
-static void f_getqflist(typval_T *argvars, typval_T *rettv)
+static void f_getqflist(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
rettv_list_alloc(rettv);
win_T *wp = NULL;
@@ -10450,7 +10090,7 @@ static void f_getqflist(typval_T *argvars, typval_T *rettv)
}
/// "getreg()" function
-static void f_getreg(typval_T *argvars, typval_T *rettv)
+static void f_getreg(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
char_u *strregname;
int regname;
@@ -10496,7 +10136,7 @@ static void f_getreg(typval_T *argvars, typval_T *rettv)
/*
* "getregtype()" function
*/
-static void f_getregtype(typval_T *argvars, typval_T *rettv)
+static void f_getregtype(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
char_u *strregname;
int regname;
@@ -10528,7 +10168,7 @@ static void f_getregtype(typval_T *argvars, typval_T *rettv)
/*
* "gettabvar()" function
*/
-static void f_gettabvar(typval_T *argvars, typval_T *rettv)
+static void f_gettabvar(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
win_T *oldcurwin;
tabpage_T *tp, *oldtabpage;
@@ -10567,7 +10207,7 @@ static void f_gettabvar(typval_T *argvars, typval_T *rettv)
/*
* "gettabwinvar()" function
*/
-static void f_gettabwinvar(typval_T *argvars, typval_T *rettv)
+static void f_gettabwinvar(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
getwinvar(argvars, rettv, 1);
}
@@ -10575,7 +10215,7 @@ static void f_gettabwinvar(typval_T *argvars, typval_T *rettv)
/*
* "getwinposx()" function
*/
-static void f_getwinposx(typval_T *argvars, typval_T *rettv)
+static void f_getwinposx(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
rettv->vval.v_number = -1;
}
@@ -10583,7 +10223,7 @@ static void f_getwinposx(typval_T *argvars, typval_T *rettv)
/*
* "getwinposy()" function
*/
-static void f_getwinposy(typval_T *argvars, typval_T *rettv)
+static void f_getwinposy(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
rettv->vval.v_number = -1;
}
@@ -10647,7 +10287,7 @@ static win_T *find_tabwin(typval_T *wvp, typval_T *tvp)
}
/// "getwinvar()" function
-static void f_getwinvar(typval_T *argvars, typval_T *rettv)
+static void f_getwinvar(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
getwinvar(argvars, rettv, 0);
}
@@ -10718,7 +10358,7 @@ getwinvar (
/*
* "glob()" function
*/
-static void f_glob(typval_T *argvars, typval_T *rettv)
+static void f_glob(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
int options = WILD_SILENT|WILD_USE_NL;
expand_T xpc;
@@ -10762,7 +10402,7 @@ static void f_glob(typval_T *argvars, typval_T *rettv)
}
/// "globpath()" function
-static void f_globpath(typval_T *argvars, typval_T *rettv)
+static void f_globpath(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
int flags = 0; // Flags for globpath.
int error = false;
@@ -10813,7 +10453,7 @@ static void f_globpath(typval_T *argvars, typval_T *rettv)
}
// "glob2regpat()" function
-static void f_glob2regpat(typval_T *argvars, typval_T *rettv)
+static void f_glob2regpat(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
char_u *pat = get_tv_string_chk(&argvars[0]); // NULL on type error
@@ -10826,7 +10466,7 @@ static void f_glob2regpat(typval_T *argvars, typval_T *rettv)
/*
* "has()" function
*/
-static void f_has(typval_T *argvars, typval_T *rettv)
+static void f_has(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
int i;
char_u *name;
@@ -10994,7 +10634,7 @@ static void f_has(typval_T *argvars, typval_T *rettv)
/*
* "has_key()" function
*/
-static void f_has_key(typval_T *argvars, typval_T *rettv)
+static void f_has_key(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
if (argvars[0].v_type != VAR_DICT) {
EMSG(_(e_dictreq));
@@ -11018,7 +10658,7 @@ static void f_has_key(typval_T *argvars, typval_T *rettv)
/// @pre An argument may not be -1 if preceding arguments are not all -1.
///
/// @post The return value will be either the number `1` or `0`.
-static void f_haslocaldir(typval_T *argvars, typval_T *rettv)
+static void f_haslocaldir(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
// Possible scope of working directory to return.
CdScope scope = kCdScopeInvalid;
@@ -11111,7 +10751,7 @@ static void f_haslocaldir(typval_T *argvars, typval_T *rettv)
/*
* "hasmapto()" function
*/
-static void f_hasmapto(typval_T *argvars, typval_T *rettv)
+static void f_hasmapto(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
char_u *name;
char_u *mode;
@@ -11136,7 +10776,7 @@ static void f_hasmapto(typval_T *argvars, typval_T *rettv)
/*
* "histadd()" function
*/
-static void f_histadd(typval_T *argvars, typval_T *rettv)
+static void f_histadd(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
HistoryType histype;
char_u *str;
@@ -11162,7 +10802,7 @@ static void f_histadd(typval_T *argvars, typval_T *rettv)
/*
* "histdel()" function
*/
-static void f_histdel(typval_T *argvars, typval_T *rettv)
+static void f_histdel(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
int n;
char_u buf[NUMBUFLEN];
@@ -11189,7 +10829,7 @@ static void f_histdel(typval_T *argvars, typval_T *rettv)
/*
* "histget()" function
*/
-static void f_histget(typval_T *argvars, typval_T *rettv)
+static void f_histget(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
HistoryType type;
int idx;
@@ -11214,7 +10854,7 @@ static void f_histget(typval_T *argvars, typval_T *rettv)
/*
* "histnr()" function
*/
-static void f_histnr(typval_T *argvars, typval_T *rettv)
+static void f_histnr(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
int i;
@@ -11233,7 +10873,7 @@ static void f_histnr(typval_T *argvars, typval_T *rettv)
/*
* "highlightID(name)" function
*/
-static void f_hlID(typval_T *argvars, typval_T *rettv)
+static void f_hlID(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
rettv->vval.v_number = syn_name2id(get_tv_string(&argvars[0]));
}
@@ -11241,7 +10881,7 @@ static void f_hlID(typval_T *argvars, typval_T *rettv)
/*
* "highlight_exists()" function
*/
-static void f_hlexists(typval_T *argvars, typval_T *rettv)
+static void f_hlexists(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
rettv->vval.v_number = highlight_exists(get_tv_string(&argvars[0]));
}
@@ -11249,7 +10889,7 @@ static void f_hlexists(typval_T *argvars, typval_T *rettv)
/*
* "hostname()" function
*/
-static void f_hostname(typval_T *argvars, typval_T *rettv)
+static void f_hostname(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
char hostname[256];
@@ -11261,7 +10901,7 @@ static void f_hostname(typval_T *argvars, typval_T *rettv)
/*
* iconv() function
*/
-static void f_iconv(typval_T *argvars, typval_T *rettv)
+static void f_iconv(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
char_u buf1[NUMBUFLEN];
char_u buf2[NUMBUFLEN];
@@ -11291,7 +10931,7 @@ static void f_iconv(typval_T *argvars, typval_T *rettv)
/*
* "indent()" function
*/
-static void f_indent(typval_T *argvars, typval_T *rettv)
+static void f_indent(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
linenr_T lnum;
@@ -11305,7 +10945,7 @@ static void f_indent(typval_T *argvars, typval_T *rettv)
/*
* "index()" function
*/
-static void f_index(typval_T *argvars, typval_T *rettv)
+static void f_index(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
list_T *l;
listitem_T *item;
@@ -11436,7 +11076,7 @@ static void get_user_input(typval_T *argvars, typval_T *rettv, int inputdialog)
* "input()" function
* Also handles inputsecret() when inputsecret is set.
*/
-static void f_input(typval_T *argvars, typval_T *rettv)
+static void f_input(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
get_user_input(argvars, rettv, FALSE);
}
@@ -11444,7 +11084,7 @@ static void f_input(typval_T *argvars, typval_T *rettv)
/*
* "inputdialog()" function
*/
-static void f_inputdialog(typval_T *argvars, typval_T *rettv)
+static void f_inputdialog(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
get_user_input(argvars, rettv, TRUE);
}
@@ -11452,7 +11092,7 @@ static void f_inputdialog(typval_T *argvars, typval_T *rettv)
/*
* "inputlist()" function
*/
-static void f_inputlist(typval_T *argvars, typval_T *rettv)
+static void f_inputlist(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
listitem_T *li;
int selected;
@@ -11488,7 +11128,7 @@ static garray_T ga_userinput = {0, 0, sizeof(tasave_T), 4, NULL};
/*
* "inputrestore()" function
*/
-static void f_inputrestore(typval_T *argvars, typval_T *rettv)
+static void f_inputrestore(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
if (!GA_EMPTY(&ga_userinput)) {
--ga_userinput.ga_len;
@@ -11504,7 +11144,7 @@ static void f_inputrestore(typval_T *argvars, typval_T *rettv)
/*
* "inputsave()" function
*/
-static void f_inputsave(typval_T *argvars, typval_T *rettv)
+static void f_inputsave(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
// Add an entry to the stack of typeahead storage.
tasave_T *p = GA_APPEND_VIA_PTR(tasave_T, &ga_userinput);
@@ -11514,19 +11154,19 @@ static void f_inputsave(typval_T *argvars, typval_T *rettv)
/*
* "inputsecret()" function
*/
-static void f_inputsecret(typval_T *argvars, typval_T *rettv)
+static void f_inputsecret(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
- ++cmdline_star;
- ++inputsecret_flag;
- f_input(argvars, rettv);
- --cmdline_star;
- --inputsecret_flag;
+ cmdline_star++;
+ inputsecret_flag++;
+ f_input(argvars, rettv, NULL);
+ cmdline_star--;
+ inputsecret_flag--;
}
/*
* "insert()" function
*/
-static void f_insert(typval_T *argvars, typval_T *rettv)
+static void f_insert(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
long before = 0;
listitem_T *item;
@@ -11565,7 +11205,7 @@ static void f_insert(typval_T *argvars, typval_T *rettv)
/*
* "invert(expr)" function
*/
-static void f_invert(typval_T *argvars, typval_T *rettv)
+static void f_invert(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
rettv->vval.v_number = ~get_tv_number_chk(&argvars[0], NULL);
}
@@ -11573,7 +11213,7 @@ static void f_invert(typval_T *argvars, typval_T *rettv)
/*
* "isdirectory()" function
*/
-static void f_isdirectory(typval_T *argvars, typval_T *rettv)
+static void f_isdirectory(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
rettv->vval.v_number = os_isdir(get_tv_string(&argvars[0]));
}
@@ -11581,7 +11221,7 @@ static void f_isdirectory(typval_T *argvars, typval_T *rettv)
/*
* "islocked()" function
*/
-static void f_islocked(typval_T *argvars, typval_T *rettv)
+static void f_islocked(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
lval_T lv;
char_u *end;
@@ -11693,13 +11333,13 @@ static void dict_list(typval_T *argvars, typval_T *rettv, int what)
/*
* "items(dict)" function
*/
-static void f_items(typval_T *argvars, typval_T *rettv)
+static void f_items(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
dict_list(argvars, rettv, 2);
}
// "jobclose(id[, stream])" function
-static void f_jobclose(typval_T *argvars, typval_T *rettv)
+static void f_jobclose(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
rettv->v_type = VAR_NUMBER;
rettv->vval.v_number = 0;
@@ -11758,7 +11398,7 @@ static void f_jobclose(typval_T *argvars, typval_T *rettv)
}
// "jobpid(id)" function
-static void f_jobpid(typval_T *argvars, typval_T *rettv)
+static void f_jobpid(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
rettv->v_type = VAR_NUMBER;
rettv->vval.v_number = 0;
@@ -11783,7 +11423,7 @@ static void f_jobpid(typval_T *argvars, typval_T *rettv)
}
// "jobsend()" function
-static void f_jobsend(typval_T *argvars, typval_T *rettv)
+static void f_jobsend(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
rettv->v_type = VAR_NUMBER;
rettv->vval.v_number = 0;
@@ -11828,7 +11468,7 @@ static void f_jobsend(typval_T *argvars, typval_T *rettv)
}
// "jobresize(job, width, height)" function
-static void f_jobresize(typval_T *argvars, typval_T *rettv)
+static void f_jobresize(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
rettv->v_type = VAR_NUMBER;
rettv->vval.v_number = 0;
@@ -11915,7 +11555,7 @@ static char **tv_to_argv(typval_T *cmd_tv, char **cmd)
}
// "jobstart()" function
-static void f_jobstart(typval_T *argvars, typval_T *rettv)
+static void f_jobstart(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
rettv->v_type = VAR_NUMBER;
rettv->vval.v_number = 0;
@@ -11999,7 +11639,7 @@ static void f_jobstart(typval_T *argvars, typval_T *rettv)
}
// "jobstop()" function
-static void f_jobstop(typval_T *argvars, typval_T *rettv)
+static void f_jobstop(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
rettv->v_type = VAR_NUMBER;
rettv->vval.v_number = 0;
@@ -12027,7 +11667,7 @@ static void f_jobstop(typval_T *argvars, typval_T *rettv)
}
// "jobwait(ids[, timeout])" function
-static void f_jobwait(typval_T *argvars, typval_T *rettv)
+static void f_jobwait(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
rettv->v_type = VAR_NUMBER;
rettv->vval.v_number = 0;
@@ -12137,7 +11777,7 @@ static void f_jobwait(typval_T *argvars, typval_T *rettv)
/*
* "join()" function
*/
-static void f_join(typval_T *argvars, typval_T *rettv)
+static void f_join(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
garray_T ga;
char_u *sep;
@@ -12165,7 +11805,7 @@ static void f_join(typval_T *argvars, typval_T *rettv)
}
/// json_decode() function
-static void f_json_decode(typval_T *argvars, typval_T *rettv)
+static void f_json_decode(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
char numbuf[NUMBUFLEN];
char *s = NULL;
@@ -12199,7 +11839,7 @@ static void f_json_decode(typval_T *argvars, typval_T *rettv)
}
/// json_encode() function
-static void f_json_encode(typval_T *argvars, typval_T *rettv)
+static void f_json_encode(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
rettv->v_type = VAR_STRING;
rettv->vval.v_string = (char_u *) encode_tv2json(&argvars[0], NULL);
@@ -12208,7 +11848,7 @@ static void f_json_encode(typval_T *argvars, typval_T *rettv)
/*
* "keys()" function
*/
-static void f_keys(typval_T *argvars, typval_T *rettv)
+static void f_keys(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
dict_list(argvars, rettv, 0);
}
@@ -12216,7 +11856,7 @@ static void f_keys(typval_T *argvars, typval_T *rettv)
/*
* "last_buffer_nr()" function.
*/
-static void f_last_buffer_nr(typval_T *argvars, typval_T *rettv)
+static void f_last_buffer_nr(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
int n = 0;
@@ -12232,7 +11872,7 @@ static void f_last_buffer_nr(typval_T *argvars, typval_T *rettv)
/*
* "len()" function
*/
-static void f_len(typval_T *argvars, typval_T *rettv)
+static void f_len(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
switch (argvars[0].v_type) {
case VAR_STRING:
@@ -12303,7 +11943,7 @@ static void libcall_common(typval_T *argvars, typval_T *rettv, int out_type)
/*
* "libcall()" function
*/
-static void f_libcall(typval_T *argvars, typval_T *rettv)
+static void f_libcall(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
libcall_common(argvars, rettv, VAR_STRING);
}
@@ -12311,7 +11951,7 @@ static void f_libcall(typval_T *argvars, typval_T *rettv)
/*
* "libcallnr()" function
*/
-static void f_libcallnr(typval_T *argvars, typval_T *rettv)
+static void f_libcallnr(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
libcall_common(argvars, rettv, VAR_NUMBER);
}
@@ -12319,7 +11959,7 @@ static void f_libcallnr(typval_T *argvars, typval_T *rettv)
/*
* "line(string)" function
*/
-static void f_line(typval_T *argvars, typval_T *rettv)
+static void f_line(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
linenr_T lnum = 0;
pos_T *fp;
@@ -12334,7 +11974,7 @@ static void f_line(typval_T *argvars, typval_T *rettv)
/*
* "line2byte(lnum)" function
*/
-static void f_line2byte(typval_T *argvars, typval_T *rettv)
+static void f_line2byte(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
linenr_T lnum;
@@ -12350,7 +11990,7 @@ static void f_line2byte(typval_T *argvars, typval_T *rettv)
/*
* "lispindent(lnum)" function
*/
-static void f_lispindent(typval_T *argvars, typval_T *rettv)
+static void f_lispindent(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
pos_T pos;
linenr_T lnum;
@@ -12368,7 +12008,7 @@ static void f_lispindent(typval_T *argvars, typval_T *rettv)
/*
* "localtime()" function
*/
-static void f_localtime(typval_T *argvars, typval_T *rettv)
+static void f_localtime(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
rettv->vval.v_number = (varnumber_T)time(NULL);
}
@@ -12444,26 +12084,9 @@ static void get_maparg(typval_T *argvars, typval_T *rettv, int exact)
}
/*
- * "log()" function
- */
-static void f_log(typval_T *argvars, typval_T *rettv)
-{
- float_op_wrapper(argvars, rettv, &log);
-}
-
-/*
- * "log10()" function
- */
-static void f_log10(typval_T *argvars, typval_T *rettv)
-{
- float_op_wrapper(argvars, rettv, &log10);
-}
-
-
-/*
* "map()" function
*/
-static void f_map(typval_T *argvars, typval_T *rettv)
+static void f_map(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
filter_map(argvars, rettv, TRUE);
}
@@ -12471,7 +12094,7 @@ static void f_map(typval_T *argvars, typval_T *rettv)
/*
* "maparg()" function
*/
-static void f_maparg(typval_T *argvars, typval_T *rettv)
+static void f_maparg(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
get_maparg(argvars, rettv, TRUE);
}
@@ -12479,7 +12102,7 @@ static void f_maparg(typval_T *argvars, typval_T *rettv)
/*
* "mapcheck()" function
*/
-static void f_mapcheck(typval_T *argvars, typval_T *rettv)
+static void f_mapcheck(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
get_maparg(argvars, rettv, FALSE);
}
@@ -12644,7 +12267,7 @@ theend:
/*
* "match()" function
*/
-static void f_match(typval_T *argvars, typval_T *rettv)
+static void f_match(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
find_some_match(argvars, rettv, 1);
}
@@ -12652,7 +12275,7 @@ static void f_match(typval_T *argvars, typval_T *rettv)
/*
* "matchadd()" function
*/
-static void f_matchadd(typval_T *argvars, typval_T *rettv)
+static void f_matchadd(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
char_u buf[NUMBUFLEN];
char_u *grp = get_tv_string_buf_chk(&argvars[0], buf); /* group */
@@ -12695,7 +12318,7 @@ static void f_matchadd(typval_T *argvars, typval_T *rettv)
conceal_char);
}
-static void f_matchaddpos(typval_T *argvars, typval_T *rettv) FUNC_ATTR_NONNULL_ALL
+static void f_matchaddpos(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
rettv->vval.v_number = -1;
@@ -12756,7 +12379,7 @@ static void f_matchaddpos(typval_T *argvars, typval_T *rettv) FUNC_ATTR_NONNULL_
/*
* "matcharg()" function
*/
-static void f_matcharg(typval_T *argvars, typval_T *rettv)
+static void f_matcharg(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
rettv_list_alloc(rettv);
@@ -12778,7 +12401,7 @@ static void f_matcharg(typval_T *argvars, typval_T *rettv)
/*
* "matchdelete()" function
*/
-static void f_matchdelete(typval_T *argvars, typval_T *rettv)
+static void f_matchdelete(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
rettv->vval.v_number = match_delete(curwin,
(int)get_tv_number(&argvars[0]), TRUE);
@@ -12787,7 +12410,7 @@ static void f_matchdelete(typval_T *argvars, typval_T *rettv)
/*
* "matchend()" function
*/
-static void f_matchend(typval_T *argvars, typval_T *rettv)
+static void f_matchend(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
find_some_match(argvars, rettv, 0);
}
@@ -12795,7 +12418,7 @@ static void f_matchend(typval_T *argvars, typval_T *rettv)
/*
* "matchlist()" function
*/
-static void f_matchlist(typval_T *argvars, typval_T *rettv)
+static void f_matchlist(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
find_some_match(argvars, rettv, 3);
}
@@ -12803,7 +12426,7 @@ static void f_matchlist(typval_T *argvars, typval_T *rettv)
/*
* "matchstr()" function
*/
-static void f_matchstr(typval_T *argvars, typval_T *rettv)
+static void f_matchstr(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
find_some_match(argvars, rettv, 2);
}
@@ -12863,7 +12486,7 @@ static void max_min(typval_T *argvars, typval_T *rettv, int domax)
/*
* "max()" function
*/
-static void f_max(typval_T *argvars, typval_T *rettv)
+static void f_max(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
max_min(argvars, rettv, TRUE);
}
@@ -12871,7 +12494,7 @@ static void f_max(typval_T *argvars, typval_T *rettv)
/*
* "min()" function
*/
-static void f_min(typval_T *argvars, typval_T *rettv)
+static void f_min(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
max_min(argvars, rettv, FALSE);
}
@@ -12879,7 +12502,7 @@ static void f_min(typval_T *argvars, typval_T *rettv)
/*
* "mkdir()" function
*/
-static void f_mkdir(typval_T *argvars, typval_T *rettv)
+static void f_mkdir(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
char_u *dir;
char_u buf[NUMBUFLEN];
@@ -12921,7 +12544,7 @@ static void f_mkdir(typval_T *argvars, typval_T *rettv)
/*
* "mode()" function
*/
-static void f_mode(typval_T *argvars, typval_T *rettv)
+static void f_mode(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
char_u buf[3];
@@ -12975,7 +12598,7 @@ static void f_mode(typval_T *argvars, typval_T *rettv)
}
/// "msgpackdump()" function
-static void f_msgpackdump(typval_T *argvars, typval_T *rettv)
+static void f_msgpackdump(typval_T *argvars, typval_T *rettv, FunPtr fptr)
FUNC_ATTR_NONNULL_ALL
{
if (argvars[0].v_type != VAR_LIST) {
@@ -13003,7 +12626,7 @@ static void f_msgpackdump(typval_T *argvars, typval_T *rettv)
}
/// "msgpackparse" function
-static void f_msgpackparse(typval_T *argvars, typval_T *rettv)
+static void f_msgpackparse(typval_T *argvars, typval_T *rettv, FunPtr fptr)
FUNC_ATTR_NONNULL_ALL
{
if (argvars[0].v_type != VAR_LIST) {
@@ -13084,7 +12707,7 @@ f_msgpackparse_exit:
/*
* "nextnonblank()" function
*/
-static void f_nextnonblank(typval_T *argvars, typval_T *rettv)
+static void f_nextnonblank(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
linenr_T lnum;
@@ -13102,7 +12725,7 @@ static void f_nextnonblank(typval_T *argvars, typval_T *rettv)
/*
* "nr2char()" function
*/
-static void f_nr2char(typval_T *argvars, typval_T *rettv)
+static void f_nr2char(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
char_u buf[NUMBUFLEN];
@@ -13126,7 +12749,7 @@ static void f_nr2char(typval_T *argvars, typval_T *rettv)
/*
* "or(expr, expr)" function
*/
-static void f_or(typval_T *argvars, typval_T *rettv)
+static void f_or(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
rettv->vval.v_number = get_tv_number_chk(&argvars[0], NULL)
| get_tv_number_chk(&argvars[1], NULL);
@@ -13135,7 +12758,7 @@ static void f_or(typval_T *argvars, typval_T *rettv)
/*
* "pathshorten()" function
*/
-static void f_pathshorten(typval_T *argvars, typval_T *rettv)
+static void f_pathshorten(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
rettv->v_type = VAR_STRING;
rettv->vval.v_string = get_tv_string_chk(&argvars[0]);
@@ -13148,7 +12771,7 @@ static void f_pathshorten(typval_T *argvars, typval_T *rettv)
/*
* "pow()" function
*/
-static void f_pow(typval_T *argvars, typval_T *rettv)
+static void f_pow(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
float_T fx, fy;
@@ -13163,7 +12786,7 @@ static void f_pow(typval_T *argvars, typval_T *rettv)
/*
* "prevnonblank()" function
*/
-static void f_prevnonblank(typval_T *argvars, typval_T *rettv)
+static void f_prevnonblank(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
linenr_T lnum;
@@ -13185,7 +12808,7 @@ static va_list ap;
/*
* "printf()" function
*/
-static void f_printf(typval_T *argvars, typval_T *rettv)
+static void f_printf(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
rettv->v_type = VAR_STRING;
rettv->vval.v_string = NULL;
@@ -13211,7 +12834,7 @@ static void f_printf(typval_T *argvars, typval_T *rettv)
/*
* "pumvisible()" function
*/
-static void f_pumvisible(typval_T *argvars, typval_T *rettv)
+static void f_pumvisible(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
if (pum_visible())
rettv->vval.v_number = 1;
@@ -13220,7 +12843,7 @@ static void f_pumvisible(typval_T *argvars, typval_T *rettv)
/*
* "pyeval()" function
*/
-static void f_pyeval(typval_T *argvars, typval_T *rettv)
+static void f_pyeval(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
script_host_eval("python", argvars, rettv);
}
@@ -13228,7 +12851,7 @@ static void f_pyeval(typval_T *argvars, typval_T *rettv)
/*
* "py3eval()" function
*/
-static void f_py3eval(typval_T *argvars, typval_T *rettv)
+static void f_py3eval(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
script_host_eval("python3", argvars, rettv);
}
@@ -13236,7 +12859,7 @@ static void f_py3eval(typval_T *argvars, typval_T *rettv)
/*
* "range()" function
*/
-static void f_range(typval_T *argvars, typval_T *rettv)
+static void f_range(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
long start;
long end;
@@ -13271,7 +12894,7 @@ static void f_range(typval_T *argvars, typval_T *rettv)
/*
* "readfile()" function
*/
-static void f_readfile(typval_T *argvars, typval_T *rettv)
+static void f_readfile(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
int binary = FALSE;
char_u *fname;
@@ -13470,7 +13093,7 @@ static int list2proftime(typval_T *arg, proftime_T *tm) FUNC_ATTR_NONNULL_ALL
/// one argument it returns the time passed since the argument.
/// With two arguments it returns the time passed between
/// the two arguments.
-static void f_reltime(typval_T *argvars, typval_T *rettv) FUNC_ATTR_NONNULL_ALL
+static void f_reltime(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
proftime_T res;
proftime_T start;
@@ -13516,7 +13139,7 @@ static void f_reltime(typval_T *argvars, typval_T *rettv) FUNC_ATTR_NONNULL_ALL
/// @return The string representation of the argument, the format is the
/// number of seconds followed by a dot, followed by the number
/// of microseconds.
-static void f_reltimestr(typval_T *argvars, typval_T *rettv)
+static void f_reltimestr(typval_T *argvars, typval_T *rettv, FunPtr fptr)
FUNC_ATTR_NONNULL_ALL
{
proftime_T tm;
@@ -13531,7 +13154,7 @@ static void f_reltimestr(typval_T *argvars, typval_T *rettv)
/*
* "remove()" function
*/
-static void f_remove(typval_T *argvars, typval_T *rettv)
+static void f_remove(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
list_T *l;
listitem_T *item, *item2;
@@ -13616,7 +13239,7 @@ static void f_remove(typval_T *argvars, typval_T *rettv)
/*
* "rename({from}, {to})" function
*/
-static void f_rename(typval_T *argvars, typval_T *rettv)
+static void f_rename(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
char_u buf[NUMBUFLEN];
@@ -13630,7 +13253,7 @@ static void f_rename(typval_T *argvars, typval_T *rettv)
/*
* "repeat()" function
*/
-static void f_repeat(typval_T *argvars, typval_T *rettv)
+static void f_repeat(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
char_u *p;
int n;
@@ -13664,7 +13287,7 @@ static void f_repeat(typval_T *argvars, typval_T *rettv)
/*
* "resolve()" function
*/
-static void f_resolve(typval_T *argvars, typval_T *rettv)
+static void f_resolve(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
char_u *p;
#ifdef HAVE_READLINK
@@ -13838,7 +13461,7 @@ fail:
/*
* "reverse({list})" function
*/
-static void f_reverse(typval_T *argvars, typval_T *rettv)
+static void f_reverse(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
list_T *l;
listitem_T *li, *ni;
@@ -14009,16 +13632,8 @@ theend:
return retval;
}
-/*
- * "round({float})" function
- */
-static void f_round(typval_T *argvars, typval_T *rettv)
-{
- float_op_wrapper(argvars, rettv, &round);
-}
-
// "rpcnotify()" function
-static void f_rpcnotify(typval_T *argvars, typval_T *rettv)
+static void f_rpcnotify(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
rettv->v_type = VAR_NUMBER;
rettv->vval.v_number = 0;
@@ -14054,7 +13669,7 @@ static void f_rpcnotify(typval_T *argvars, typval_T *rettv)
}
// "rpcrequest()" function
-static void f_rpcrequest(typval_T *argvars, typval_T *rettv)
+static void f_rpcrequest(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
rettv->v_type = VAR_NUMBER;
rettv->vval.v_number = 0;
@@ -14127,7 +13742,7 @@ static void f_rpcrequest(typval_T *argvars, typval_T *rettv)
}
if (err.set) {
- vim_report_error(cstr_as_string(err.msg));
+ nvim_err_writeln(cstr_as_string(err.msg));
goto end;
}
@@ -14140,7 +13755,7 @@ end:
}
// "rpcstart()" function (DEPRECATED)
-static void f_rpcstart(typval_T *argvars, typval_T *rettv)
+static void f_rpcstart(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
rettv->v_type = VAR_NUMBER;
rettv->vval.v_number = 0;
@@ -14199,8 +13814,15 @@ static void f_rpcstart(typval_T *argvars, typval_T *rettv)
}
// "rpcstop()" function
-static void f_rpcstop(typval_T *argvars, typval_T *rettv)
+static void f_rpcstop(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
+ rettv->v_type = VAR_NUMBER;
+ rettv->vval.v_number = 0;
+
+ if (check_restricted() || check_secure()) {
+ return;
+ }
+
if (argvars[0].v_type != VAR_NUMBER) {
// Wrong argument types
EMSG(_(e_invarg));
@@ -14209,7 +13831,7 @@ static void f_rpcstop(typval_T *argvars, typval_T *rettv)
// if called with a job, stop it, else closes the channel
if (pmap_get(uint64_t)(jobs, argvars[0].vval.v_number)) {
- f_jobstop(argvars, rettv);
+ f_jobstop(argvars, rettv, NULL);
} else {
rettv->vval.v_number = channel_close(argvars[0].vval.v_number);
}
@@ -14218,7 +13840,7 @@ static void f_rpcstop(typval_T *argvars, typval_T *rettv)
/*
* "screenattr()" function
*/
-static void f_screenattr(typval_T *argvars, typval_T *rettv)
+static void f_screenattr(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
int row;
int col;
@@ -14237,7 +13859,7 @@ static void f_screenattr(typval_T *argvars, typval_T *rettv)
/*
* "screenchar()" function
*/
-static void f_screenchar(typval_T *argvars, typval_T *rettv)
+static void f_screenchar(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
int row;
int col;
@@ -14264,7 +13886,7 @@ static void f_screenchar(typval_T *argvars, typval_T *rettv)
*
* First column is 1 to be consistent with virtcol().
*/
-static void f_screencol(typval_T *argvars, typval_T *rettv)
+static void f_screencol(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
rettv->vval.v_number = ui_current_col() + 1;
}
@@ -14272,7 +13894,7 @@ static void f_screencol(typval_T *argvars, typval_T *rettv)
/*
* "screenrow()" function
*/
-static void f_screenrow(typval_T *argvars, typval_T *rettv)
+static void f_screenrow(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
rettv->vval.v_number = ui_current_row() + 1;
}
@@ -14280,7 +13902,7 @@ static void f_screenrow(typval_T *argvars, typval_T *rettv)
/*
* "search()" function
*/
-static void f_search(typval_T *argvars, typval_T *rettv)
+static void f_search(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
int flags = 0;
@@ -14290,7 +13912,7 @@ static void f_search(typval_T *argvars, typval_T *rettv)
/*
* "searchdecl()" function
*/
-static void f_searchdecl(typval_T *argvars, typval_T *rettv)
+static void f_searchdecl(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
int locally = 1;
int thisblock = 0;
@@ -14383,7 +14005,7 @@ theend:
/*
* "searchpair()" function
*/
-static void f_searchpair(typval_T *argvars, typval_T *rettv)
+static void f_searchpair(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
rettv->vval.v_number = searchpair_cmn(argvars, NULL);
}
@@ -14391,7 +14013,7 @@ static void f_searchpair(typval_T *argvars, typval_T *rettv)
/*
* "searchpairpos()" function
*/
-static void f_searchpairpos(typval_T *argvars, typval_T *rettv)
+static void f_searchpairpos(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
pos_T match_pos;
int lnum = 0;
@@ -14556,7 +14178,7 @@ do_searchpair (
/*
* "searchpos()" function
*/
-static void f_searchpos(typval_T *argvars, typval_T *rettv)
+static void f_searchpos(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
pos_T match_pos;
int lnum = 0;
@@ -14579,7 +14201,7 @@ static void f_searchpos(typval_T *argvars, typval_T *rettv)
}
/// "serverlist()" function
-static void f_serverlist(typval_T *argvars, typval_T *rettv)
+static void f_serverlist(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
size_t n;
char **addrs = server_address_list(&n);
@@ -14597,7 +14219,7 @@ static void f_serverlist(typval_T *argvars, typval_T *rettv)
}
/// "serverstart()" function
-static void f_serverstart(typval_T *argvars, typval_T *rettv)
+static void f_serverstart(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
rettv->v_type = VAR_STRING;
rettv->vval.v_string = NULL; // Address of the new server
@@ -14625,7 +14247,7 @@ static void f_serverstart(typval_T *argvars, typval_T *rettv)
}
/// "serverstop()" function
-static void f_serverstop(typval_T *argvars, typval_T *rettv)
+static void f_serverstop(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
if (check_restricted() || check_secure()) {
return;
@@ -14644,7 +14266,7 @@ static void f_serverstop(typval_T *argvars, typval_T *rettv)
/*
* "setbufvar()" function
*/
-static void f_setbufvar(typval_T *argvars, typval_T *rettv)
+static void f_setbufvar(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
buf_T *buf;
aco_save_T aco;
@@ -14686,7 +14308,7 @@ static void f_setbufvar(typval_T *argvars, typval_T *rettv)
}
}
-static void f_setcharsearch(typval_T *argvars, typval_T *rettv)
+static void f_setcharsearch(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
dict_T *d;
dictitem_T *di;
@@ -14723,7 +14345,7 @@ static void f_setcharsearch(typval_T *argvars, typval_T *rettv)
/*
* "setcmdpos()" function
*/
-static void f_setcmdpos(typval_T *argvars, typval_T *rettv)
+static void f_setcmdpos(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
int pos = (int)get_tv_number(&argvars[0]) - 1;
@@ -14733,7 +14355,7 @@ static void f_setcmdpos(typval_T *argvars, typval_T *rettv)
/// "setfperm({fname}, {mode})" function
-static void f_setfperm(typval_T *argvars, typval_T *rettv)
+static void f_setfperm(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
rettv->vval.v_number = 0;
@@ -14766,7 +14388,7 @@ static void f_setfperm(typval_T *argvars, typval_T *rettv)
/*
* "setline()" function
*/
-static void f_setline(typval_T *argvars, typval_T *rettv)
+static void f_setline(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
linenr_T lnum;
char_u *line = NULL;
@@ -14891,7 +14513,7 @@ skip_args:
/*
* "setloclist()" function
*/
-static void f_setloclist(typval_T *argvars, typval_T *rettv)
+static void f_setloclist(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
win_T *win;
@@ -14906,7 +14528,7 @@ static void f_setloclist(typval_T *argvars, typval_T *rettv)
/*
* "setmatches()" function
*/
-static void f_setmatches(typval_T *argvars, typval_T *rettv)
+static void f_setmatches(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
list_T *l;
listitem_T *li;
@@ -14997,7 +14619,7 @@ static void f_setmatches(typval_T *argvars, typval_T *rettv)
/*
* "setpos()" function
*/
-static void f_setpos(typval_T *argvars, typval_T *rettv)
+static void f_setpos(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
pos_T pos;
int fnum;
@@ -15039,7 +14661,7 @@ static void f_setpos(typval_T *argvars, typval_T *rettv)
/*
* "setqflist()" function
*/
-static void f_setqflist(typval_T *argvars, typval_T *rettv)
+static void f_setqflist(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
set_qf_ll_list(NULL, argvars, rettv);
}
@@ -15047,7 +14669,7 @@ static void f_setqflist(typval_T *argvars, typval_T *rettv)
/*
* "setreg()" function
*/
-static void f_setreg(typval_T *argvars, typval_T *rettv)
+static void f_setreg(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
int regname;
char_u *strregname;
@@ -15142,7 +14764,7 @@ free_lstval:
/*
* "settabvar()" function
*/
-static void f_settabvar(typval_T *argvars, typval_T *rettv)
+static void f_settabvar(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
tabpage_T *save_curtab;
tabpage_T *tp;
@@ -15179,7 +14801,7 @@ static void f_settabvar(typval_T *argvars, typval_T *rettv)
/*
* "settabwinvar()" function
*/
-static void f_settabwinvar(typval_T *argvars, typval_T *rettv)
+static void f_settabwinvar(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
setwinvar(argvars, rettv, 1);
}
@@ -15187,7 +14809,7 @@ static void f_settabwinvar(typval_T *argvars, typval_T *rettv)
/*
* "setwinvar()" function
*/
-static void f_setwinvar(typval_T *argvars, typval_T *rettv)
+static void f_setwinvar(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
setwinvar(argvars, rettv, 0);
}
@@ -15247,7 +14869,7 @@ static void setwinvar(typval_T *argvars, typval_T *rettv, int off)
}
/// f_sha256 - sha256({string}) function
-static void f_sha256(typval_T *argvars, typval_T *rettv)
+static void f_sha256(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
char_u *p = get_tv_string(&argvars[0]);
const char_u *hash = sha256_bytes(p, (int) STRLEN(p) , NULL, 0);
@@ -15260,7 +14882,7 @@ static void f_sha256(typval_T *argvars, typval_T *rettv)
/*
* "shellescape({string})" function
*/
-static void f_shellescape(typval_T *argvars, typval_T *rettv)
+static void f_shellescape(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
rettv->vval.v_string = vim_strsave_shellescape(
get_tv_string(&argvars[0]), non_zero_arg(&argvars[1]), true);
@@ -15270,7 +14892,7 @@ static void f_shellescape(typval_T *argvars, typval_T *rettv)
/*
* shiftwidth() function
*/
-static void f_shiftwidth(typval_T *argvars, typval_T *rettv)
+static void f_shiftwidth(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
rettv->vval.v_number = get_sw_value(curbuf);
}
@@ -15278,7 +14900,7 @@ static void f_shiftwidth(typval_T *argvars, typval_T *rettv)
/*
* "simplify()" function
*/
-static void f_simplify(typval_T *argvars, typval_T *rettv)
+static void f_simplify(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
char_u *p;
@@ -15288,22 +14910,6 @@ static void f_simplify(typval_T *argvars, typval_T *rettv)
rettv->v_type = VAR_STRING;
}
-/*
- * "sin()" function
- */
-static void f_sin(typval_T *argvars, typval_T *rettv)
-{
- float_op_wrapper(argvars, rettv, &sin);
-}
-
-/*
- * "sinh()" function
- */
-static void f_sinh(typval_T *argvars, typval_T *rettv)
-{
- float_op_wrapper(argvars, rettv, &sinh);
-}
-
/// struct used in the array that's given to qsort()
typedef struct {
listitem_T *item;
@@ -15651,13 +15257,13 @@ theend:
}
/// "sort"({list})" function
-static void f_sort(typval_T *argvars, typval_T *rettv)
+static void f_sort(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
do_sort_uniq(argvars, rettv, true);
}
/// "uniq({list})" function
-static void f_uniq(typval_T *argvars, typval_T *rettv)
+static void f_uniq(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
do_sort_uniq(argvars, rettv, false);
}
@@ -15665,7 +15271,7 @@ static void f_uniq(typval_T *argvars, typval_T *rettv)
//
// "reltimefloat()" function
//
-static void f_reltimefloat(typval_T *argvars , typval_T *rettv)
+static void f_reltimefloat(typval_T *argvars , typval_T *rettv, FunPtr fptr)
FUNC_ATTR_NONNULL_ALL
{
proftime_T tm;
@@ -15680,7 +15286,7 @@ static void f_reltimefloat(typval_T *argvars , typval_T *rettv)
/*
* "soundfold({word})" function
*/
-static void f_soundfold(typval_T *argvars, typval_T *rettv)
+static void f_soundfold(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
char_u *s;
@@ -15692,7 +15298,7 @@ static void f_soundfold(typval_T *argvars, typval_T *rettv)
/*
* "spellbadword()" function
*/
-static void f_spellbadword(typval_T *argvars, typval_T *rettv)
+static void f_spellbadword(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
char_u *word = (char_u *)"";
hlf_T attr = HLF_COUNT;
@@ -15736,7 +15342,7 @@ static void f_spellbadword(typval_T *argvars, typval_T *rettv)
/*
* "spellsuggest()" function
*/
-static void f_spellsuggest(typval_T *argvars, typval_T *rettv)
+static void f_spellsuggest(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
char_u *str;
int typeerr = FALSE;
@@ -15776,7 +15382,7 @@ static void f_spellsuggest(typval_T *argvars, typval_T *rettv)
}
}
-static void f_split(typval_T *argvars, typval_T *rettv)
+static void f_split(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
char_u *str;
char_u *end;
@@ -15845,17 +15451,9 @@ static void f_split(typval_T *argvars, typval_T *rettv)
}
/*
- * "sqrt()" function
- */
-static void f_sqrt(typval_T *argvars, typval_T *rettv)
-{
- float_op_wrapper(argvars, rettv, &sqrt);
-}
-
-/*
* "str2float()" function
*/
-static void f_str2float(typval_T *argvars, typval_T *rettv)
+static void f_str2float(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
char_u *p = skipwhite(get_tv_string(&argvars[0]));
@@ -15866,7 +15464,7 @@ static void f_str2float(typval_T *argvars, typval_T *rettv)
}
// "str2nr()" function
-static void f_str2nr(typval_T *argvars, typval_T *rettv)
+static void f_str2nr(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
int base = 10;
char_u *p;
@@ -15905,7 +15503,7 @@ static void f_str2nr(typval_T *argvars, typval_T *rettv)
/*
* "strftime({format}[, {time}])" function
*/
-static void f_strftime(typval_T *argvars, typval_T *rettv)
+static void f_strftime(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
char_u result_buf[256];
time_t seconds;
@@ -15956,7 +15554,7 @@ static void f_strftime(typval_T *argvars, typval_T *rettv)
/*
* "stridx()" function
*/
-static void f_stridx(typval_T *argvars, typval_T *rettv)
+static void f_stridx(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
char_u buf[NUMBUFLEN];
char_u *needle;
@@ -15989,7 +15587,7 @@ static void f_stridx(typval_T *argvars, typval_T *rettv)
/*
* "string()" function
*/
-static void f_string(typval_T *argvars, typval_T *rettv)
+static void f_string(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
rettv->v_type = VAR_STRING;
rettv->vval.v_string = (char_u *) encode_tv2string(&argvars[0], NULL);
@@ -15998,7 +15596,7 @@ static void f_string(typval_T *argvars, typval_T *rettv)
/*
* "strlen()" function
*/
-static void f_strlen(typval_T *argvars, typval_T *rettv)
+static void f_strlen(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
rettv->vval.v_number = (varnumber_T)(STRLEN(
get_tv_string(&argvars[0])));
@@ -16007,7 +15605,7 @@ static void f_strlen(typval_T *argvars, typval_T *rettv)
/*
* "strchars()" function
*/
-static void f_strchars(typval_T *argvars, typval_T *rettv)
+static void f_strchars(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
char_u *s = get_tv_string(&argvars[0]);
int skipcc = 0;
@@ -16032,7 +15630,7 @@ static void f_strchars(typval_T *argvars, typval_T *rettv)
/*
* "strdisplaywidth()" function
*/
-static void f_strdisplaywidth(typval_T *argvars, typval_T *rettv)
+static void f_strdisplaywidth(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
char_u *s = get_tv_string(&argvars[0]);
int col = 0;
@@ -16046,7 +15644,7 @@ static void f_strdisplaywidth(typval_T *argvars, typval_T *rettv)
/*
* "strwidth()" function
*/
-static void f_strwidth(typval_T *argvars, typval_T *rettv)
+static void f_strwidth(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
char_u *s = get_tv_string(&argvars[0]);
@@ -16056,7 +15654,7 @@ static void f_strwidth(typval_T *argvars, typval_T *rettv)
/*
* "strpart()" function
*/
-static void f_strpart(typval_T *argvars, typval_T *rettv)
+static void f_strpart(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
char_u *p;
int n;
@@ -16096,7 +15694,7 @@ static void f_strpart(typval_T *argvars, typval_T *rettv)
/*
* "strridx()" function
*/
-static void f_strridx(typval_T *argvars, typval_T *rettv)
+static void f_strridx(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
char_u buf[NUMBUFLEN];
char_u *needle;
@@ -16142,7 +15740,7 @@ static void f_strridx(typval_T *argvars, typval_T *rettv)
/*
* "strtrans()" function
*/
-static void f_strtrans(typval_T *argvars, typval_T *rettv)
+static void f_strtrans(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
rettv->v_type = VAR_STRING;
rettv->vval.v_string = transstr(get_tv_string(&argvars[0]));
@@ -16151,7 +15749,7 @@ static void f_strtrans(typval_T *argvars, typval_T *rettv)
/*
* "submatch()" function
*/
-static void f_submatch(typval_T *argvars, typval_T *rettv)
+static void f_submatch(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
int error = FALSE;
int no = (int)get_tv_number_chk(&argvars[0], &error);
@@ -16180,7 +15778,7 @@ static void f_submatch(typval_T *argvars, typval_T *rettv)
/*
* "substitute()" function
*/
-static void f_substitute(typval_T *argvars, typval_T *rettv)
+static void f_substitute(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
char_u patbuf[NUMBUFLEN];
char_u subbuf[NUMBUFLEN];
@@ -16201,7 +15799,7 @@ static void f_substitute(typval_T *argvars, typval_T *rettv)
/*
* "synID(lnum, col, trans)" function
*/
-static void f_synID(typval_T *argvars, typval_T *rettv)
+static void f_synID(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
int id = 0;
long lnum;
@@ -16223,7 +15821,7 @@ static void f_synID(typval_T *argvars, typval_T *rettv)
/*
* "synIDattr(id, what [, mode])" function
*/
-static void f_synIDattr(typval_T *argvars, typval_T *rettv)
+static void f_synIDattr(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
char_u *p = NULL;
int id;
@@ -16299,7 +15897,7 @@ static void f_synIDattr(typval_T *argvars, typval_T *rettv)
/*
* "synIDtrans(id)" function
*/
-static void f_synIDtrans(typval_T *argvars, typval_T *rettv)
+static void f_synIDtrans(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
int id;
@@ -16316,7 +15914,7 @@ static void f_synIDtrans(typval_T *argvars, typval_T *rettv)
/*
* "synconcealed(lnum, col)" function
*/
-static void f_synconcealed(typval_T *argvars, typval_T *rettv)
+static void f_synconcealed(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
long lnum;
long col;
@@ -16363,7 +15961,7 @@ static void f_synconcealed(typval_T *argvars, typval_T *rettv)
/*
* "synstack(lnum, col)" function
*/
-static void f_synstack(typval_T *argvars, typval_T *rettv)
+static void f_synstack(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
long lnum;
long col;
@@ -16494,12 +16092,12 @@ static void get_system_output_as_rettv(typval_T *argvars, typval_T *rettv,
}
/// f_system - the VimL system() function
-static void f_system(typval_T *argvars, typval_T *rettv)
+static void f_system(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
get_system_output_as_rettv(argvars, rettv, false);
}
-static void f_systemlist(typval_T *argvars, typval_T *rettv)
+static void f_systemlist(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
get_system_output_as_rettv(argvars, rettv, true);
}
@@ -16508,7 +16106,7 @@ static void f_systemlist(typval_T *argvars, typval_T *rettv)
/*
* "tabpagebuflist()" function
*/
-static void f_tabpagebuflist(typval_T *argvars, typval_T *rettv)
+static void f_tabpagebuflist(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
tabpage_T *tp;
win_T *wp = NULL;
@@ -16533,7 +16131,7 @@ static void f_tabpagebuflist(typval_T *argvars, typval_T *rettv)
/*
* "tabpagenr()" function
*/
-static void f_tabpagenr(typval_T *argvars, typval_T *rettv)
+static void f_tabpagenr(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
int nr = 1;
char_u *arg;
@@ -16597,7 +16195,7 @@ static int get_winnr(tabpage_T *tp, typval_T *argvar)
/*
* "tabpagewinnr()" function
*/
-static void f_tabpagewinnr(typval_T *argvars, typval_T *rettv)
+static void f_tabpagewinnr(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
int nr = 1;
tabpage_T *tp;
@@ -16614,7 +16212,7 @@ static void f_tabpagewinnr(typval_T *argvars, typval_T *rettv)
/*
* "tagfiles()" function
*/
-static void f_tagfiles(typval_T *argvars, typval_T *rettv)
+static void f_tagfiles(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
char_u *fname;
tagname_T tn;
@@ -16635,7 +16233,7 @@ static void f_tagfiles(typval_T *argvars, typval_T *rettv)
/*
* "taglist()" function
*/
-static void f_taglist(typval_T *argvars, typval_T *rettv)
+static void f_taglist(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
char_u *tag_pattern;
@@ -16651,14 +16249,14 @@ static void f_taglist(typval_T *argvars, typval_T *rettv)
/*
* "tempname()" function
*/
-static void f_tempname(typval_T *argvars, typval_T *rettv)
+static void f_tempname(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
rettv->v_type = VAR_STRING;
rettv->vval.v_string = vim_tempname();
}
// "termopen(cmd[, cwd])" function
-static void f_termopen(typval_T *argvars, typval_T *rettv)
+static void f_termopen(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
if (check_restricted() || check_secure()) {
return;
@@ -16733,9 +16331,9 @@ static void f_termopen(typval_T *argvars, typval_T *rettv)
// Save the job id and pid in b:terminal_job_{id,pid}
Error err;
dict_set_value(curbuf->b_vars, cstr_as_string("terminal_job_id"),
- INTEGER_OBJ(rettv->vval.v_number), false, &err);
+ INTEGER_OBJ(rettv->vval.v_number), false, false, &err);
dict_set_value(curbuf->b_vars, cstr_as_string("terminal_job_pid"),
- INTEGER_OBJ(pid), false, &err);
+ INTEGER_OBJ(pid), false, false, &err);
Terminal *term = terminal_open(topts);
data->term = term;
@@ -16747,30 +16345,13 @@ static void f_termopen(typval_T *argvars, typval_T *rettv)
/*
* "test(list)" function: Just checking the walls...
*/
-static void f_test(typval_T *argvars, typval_T *rettv)
+static void f_test(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
/* Used for unit testing. Change the code below to your liking. */
}
-/*
- * "tan()" function
- */
-static void f_tan(typval_T *argvars, typval_T *rettv)
-{
- float_op_wrapper(argvars, rettv, &tan);
-}
-
-/*
- * "tanh()" function
- */
-static void f_tanh(typval_T *argvars, typval_T *rettv)
-{
- float_op_wrapper(argvars, rettv, &tanh);
-}
-
-
/// "timer_start(timeout, callback, opts)" function
-static void f_timer_start(typval_T *argvars, typval_T *rettv)
+static void f_timer_start(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
long timeout = get_tv_number(&argvars[0]);
timer_T *timer;
@@ -16825,7 +16406,7 @@ static void f_timer_start(typval_T *argvars, typval_T *rettv)
// "timer_stop(timerid)" function
-static void f_timer_stop(typval_T *argvars, typval_T *rettv)
+static void f_timer_stop(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
if (argvars[0].v_type != VAR_NUMBER) {
EMSG(_(e_number_exp));
@@ -16914,7 +16495,7 @@ void timer_teardown(void)
/*
* "tolower(string)" function
*/
-static void f_tolower(typval_T *argvars, typval_T *rettv)
+static void f_tolower(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
char_u *p = vim_strsave(get_tv_string(&argvars[0]));
rettv->v_type = VAR_STRING;
@@ -16945,7 +16526,7 @@ static void f_tolower(typval_T *argvars, typval_T *rettv)
/*
* "toupper(string)" function
*/
-static void f_toupper(typval_T *argvars, typval_T *rettv)
+static void f_toupper(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
rettv->v_type = VAR_STRING;
rettv->vval.v_string = strup_save(get_tv_string(&argvars[0]));
@@ -16954,7 +16535,7 @@ static void f_toupper(typval_T *argvars, typval_T *rettv)
/*
* "tr(string, fromstr, tostr)" function
*/
-static void f_tr(typval_T *argvars, typval_T *rettv)
+static void f_tr(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
char_u *in_str;
char_u *fromstr;
@@ -17052,17 +16633,9 @@ error:
}
/*
- * "trunc({float})" function
- */
-static void f_trunc(typval_T *argvars, typval_T *rettv)
-{
- float_op_wrapper(argvars, rettv, &trunc);
-}
-
-/*
* "type(expr)" function
*/
-static void f_type(typval_T *argvars, typval_T *rettv)
+static void f_type(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
int n = -1;
@@ -17098,7 +16671,7 @@ static void f_type(typval_T *argvars, typval_T *rettv)
/*
* "undofile(name)" function
*/
-static void f_undofile(typval_T *argvars, typval_T *rettv)
+static void f_undofile(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
rettv->v_type = VAR_STRING;
{
@@ -17121,7 +16694,7 @@ static void f_undofile(typval_T *argvars, typval_T *rettv)
/*
* "undotree()" function
*/
-static void f_undotree(typval_T *argvars, typval_T *rettv)
+static void f_undotree(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
rettv_dict_alloc(rettv);
@@ -17144,7 +16717,7 @@ static void f_undotree(typval_T *argvars, typval_T *rettv)
/*
* "values(dict)" function
*/
-static void f_values(typval_T *argvars, typval_T *rettv)
+static void f_values(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
dict_list(argvars, rettv, 1);
}
@@ -17152,7 +16725,7 @@ static void f_values(typval_T *argvars, typval_T *rettv)
/*
* "virtcol(string)" function
*/
-static void f_virtcol(typval_T *argvars, typval_T *rettv)
+static void f_virtcol(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
colnr_T vcol = 0;
pos_T *fp;
@@ -17171,7 +16744,7 @@ static void f_virtcol(typval_T *argvars, typval_T *rettv)
/*
* "visualmode()" function
*/
-static void f_visualmode(typval_T *argvars, typval_T *rettv)
+static void f_visualmode(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
char_u str[2];
@@ -17188,34 +16761,40 @@ static void f_visualmode(typval_T *argvars, typval_T *rettv)
/*
* "wildmenumode()" function
*/
-static void f_wildmenumode(typval_T *argvars, typval_T *rettv)
+static void f_wildmenumode(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
if (wild_menu_showing)
rettv->vval.v_number = 1;
}
+/// "win_findbuf()" function
+static void f_win_findbuf(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+{
+ rettv_list_alloc(rettv);
+ win_findbuf(argvars, rettv->vval.v_list);
+}
+
/// "win_getid()" function
-static void f_win_getid(typval_T *argvars, typval_T *rettv)
+static void f_win_getid(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
rettv->vval.v_number = win_getid(argvars);
}
/// "win_gotoid()" function
-static void f_win_gotoid(typval_T *argvars, typval_T *rettv)
+static void f_win_gotoid(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
rettv->vval.v_number = win_gotoid(argvars);
}
/// "win_id2tabwin()" function
-static void f_win_id2tabwin(typval_T *argvars, typval_T *rettv)
+static void f_win_id2tabwin(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
- if (rettv_list_alloc(rettv) != FAIL) {
- win_id2tabwin(argvars, rettv->vval.v_list);
- }
+ rettv_list_alloc(rettv);
+ win_id2tabwin(argvars, rettv->vval.v_list);
}
/// "win_id2win()" function
-static void f_win_id2win(typval_T *argvars, typval_T *rettv)
+static void f_win_id2win(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
rettv->vval.v_number = win_id2win(argvars);
}
@@ -17223,7 +16802,7 @@ static void f_win_id2win(typval_T *argvars, typval_T *rettv)
/*
* "winbufnr(nr)" function
*/
-static void f_winbufnr(typval_T *argvars, typval_T *rettv)
+static void f_winbufnr(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
win_T *wp;
@@ -17237,7 +16816,7 @@ static void f_winbufnr(typval_T *argvars, typval_T *rettv)
/*
* "wincol()" function
*/
-static void f_wincol(typval_T *argvars, typval_T *rettv)
+static void f_wincol(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
validate_cursor();
rettv->vval.v_number = curwin->w_wcol + 1;
@@ -17246,7 +16825,7 @@ static void f_wincol(typval_T *argvars, typval_T *rettv)
/*
* "winheight(nr)" function
*/
-static void f_winheight(typval_T *argvars, typval_T *rettv)
+static void f_winheight(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
win_T *wp;
@@ -17260,7 +16839,7 @@ static void f_winheight(typval_T *argvars, typval_T *rettv)
/*
* "winline()" function
*/
-static void f_winline(typval_T *argvars, typval_T *rettv)
+static void f_winline(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
validate_cursor();
rettv->vval.v_number = curwin->w_wrow + 1;
@@ -17269,7 +16848,7 @@ static void f_winline(typval_T *argvars, typval_T *rettv)
/*
* "winnr()" function
*/
-static void f_winnr(typval_T *argvars, typval_T *rettv)
+static void f_winnr(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
int nr = 1;
@@ -17280,7 +16859,7 @@ static void f_winnr(typval_T *argvars, typval_T *rettv)
/*
* "winrestcmd()" function
*/
-static void f_winrestcmd(typval_T *argvars, typval_T *rettv)
+static void f_winrestcmd(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
int winnr = 1;
garray_T ga;
@@ -17303,7 +16882,7 @@ static void f_winrestcmd(typval_T *argvars, typval_T *rettv)
/*
* "winrestview()" function
*/
-static void f_winrestview(typval_T *argvars, typval_T *rettv)
+static void f_winrestview(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
dict_T *dict;
@@ -17353,7 +16932,7 @@ static void f_winrestview(typval_T *argvars, typval_T *rettv)
/*
* "winsaveview()" function
*/
-static void f_winsaveview(typval_T *argvars, typval_T *rettv)
+static void f_winsaveview(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
dict_T *dict;
@@ -17457,7 +17036,7 @@ static char_u *save_tv_as_string(typval_T *tv, ssize_t *len, bool endnl)
/*
* "winwidth(nr)" function
*/
-static void f_winwidth(typval_T *argvars, typval_T *rettv)
+static void f_winwidth(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
win_T *wp;
@@ -17469,14 +17048,14 @@ static void f_winwidth(typval_T *argvars, typval_T *rettv)
}
/// "wordcount()" function
-static void f_wordcount(typval_T *argvars, typval_T *rettv)
+static void f_wordcount(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
rettv_dict_alloc(rettv);
cursor_pos_info(rettv->vval.v_dict);
}
/// "writefile()" function
-static void f_writefile(typval_T *argvars, typval_T *rettv)
+static void f_writefile(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
rettv->vval.v_number = 0; // Assuming success.
@@ -17521,7 +17100,7 @@ static void f_writefile(typval_T *argvars, typval_T *rettv)
/*
* "xor(expr, expr)" function
*/
-static void f_xor(typval_T *argvars, typval_T *rettv)
+static void f_xor(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
rettv->vval.v_number = get_tv_number_chk(&argvars[0], NULL)
^ get_tv_number_chk(&argvars[1], NULL);
@@ -18603,7 +18182,7 @@ static linenr_T get_tv_lnum(typval_T *argvars)
lnum = get_tv_number_chk(&argvars[0], NULL);
if (lnum == 0) { /* no valid number, try using line() */
rettv.v_type = VAR_NUMBER;
- f_line(argvars, &rettv);
+ f_line(argvars, &rettv, NULL);
lnum = rettv.vval.v_number;
clear_tv(&rettv);
}
@@ -20431,7 +20010,7 @@ void free_all_functions(void)
int translated_function_exists(char_u *name)
{
if (builtin_function(name, -1)) {
- return find_internal_func(name) >= 0;
+ return find_internal_func((char *)name) != NULL;
}
return find_func(name) != NULL;
}
@@ -22190,9 +21769,15 @@ static inline bool common_job_start(TerminalJobData *data, typval_T *rettv)
Process *proc = (Process *)&data->proc;
if (proc->type == kProcessTypePty && proc->detach) {
EMSG2(_(e_invarg2), "terminal/pty job cannot be detached");
+ xfree(data->proc.pty.term_name);
+ shell_free_argv(proc->argv);
+ free_term_job_data_event((void **)&data);
return false;
}
+ data->id = next_chan_id++;
+ pmap_put(uint64_t)(jobs, data->id, data);
+
data->refcount++;
char *cmd = xstrdup(proc->argv[0]);
if (!process_spawn(proc)) {
@@ -22207,7 +21792,6 @@ static inline bool common_job_start(TerminalJobData *data, typval_T *rettv)
}
xfree(cmd);
- data->id = next_chan_id++;
if (data->rpc) {
// the rpc channel takes over the in and out streams
@@ -22224,7 +21808,6 @@ static inline bool common_job_start(TerminalJobData *data, typval_T *rettv)
rstream_init(proc->err, 0);
rstream_start(proc->err, on_job_stderr, data);
}
- pmap_put(uint64_t)(jobs, data->id, data);
rettv->vval.v_number = data->id;
return true;
}
@@ -22246,6 +21829,7 @@ static inline void free_term_job_data_event(void **argv)
dict_unref(data->self);
}
queue_free(data->events);
+ pmap_del(uint64_t)(jobs, data->id);
xfree(data);
}
@@ -22352,7 +21936,6 @@ static void on_process_exit(Process *proc, int status, void *d)
process_job_event(data, data->on_exit, "exit", NULL, 0, status);
- pmap_del(uint64_t)(jobs, data->id);
term_job_data_decref(data);
}
diff --git a/src/nvim/eval.lua b/src/nvim/eval.lua
new file mode 100644
index 0000000000..3c371fc264
--- /dev/null
+++ b/src/nvim/eval.lua
@@ -0,0 +1,331 @@
+-- File containing table with all functions.
+--
+-- Keys:
+--
+-- args Number of arguments, list with maximum and minimum number of arguments
+-- or list with a minimum number of arguments only. Defaults to zero
+-- arguments.
+-- func Name of the C function which implements the VimL function. Defaults to
+-- `f_{funcname}`.
+
+local varargs = function(nr)
+ return {nr}
+end
+
+return {
+ funcs={
+ abs={args=1},
+ acos={args=1, func="float_op_wrapper", data="&acos"}, -- WJMc
+ add={args=2},
+ ['and']={args=2},
+ api_info={},
+ append={args=2},
+ argc={},
+ argidx={},
+ arglistid={args={0, 2}},
+ argv={args={0, 1}},
+ asin={args=1, func="float_op_wrapper", data="&asin"}, -- WJMc
+ assert_equal={args={2, 3}},
+ assert_exception={args={1, 2}},
+ assert_fails={args={1, 2}},
+ assert_false={args={1, 2}},
+ assert_match={args={2, 3}},
+ assert_notequal={args={2, 3}},
+ assert_notmatch={args={2, 3}},
+ assert_true={args={1, 2}},
+ atan={args=1, func="float_op_wrapper", data="&atan"},
+ atan2={args=2},
+ browse={args=4},
+ browsedir={args=2},
+ bufexists={args=1},
+ buffer_exists={args=1, func='f_bufexists'}, -- obsolete
+ buffer_name={args=1, func='f_bufname'}, -- obsolete
+ buffer_number={args=1, func='f_bufnr'}, -- obsolete
+ buflisted={args=1},
+ bufloaded={args=1},
+ bufname={args=1},
+ bufnr={args={1, 2}},
+ bufwinnr={args=1},
+ byte2line={args=1},
+ byteidx={args=2},
+ byteidxcomp={args=2},
+ call={args={2, 3}},
+ ceil={args=1, func="float_op_wrapper", data="&ceil"},
+ changenr={},
+ char2nr={args={1, 2}},
+ cindent={args=1},
+ clearmatches={},
+ col={args=1},
+ complete={args=2},
+ complete_add={args=1},
+ complete_check={},
+ confirm={args={1, 4}},
+ copy={args=1},
+ cos={args=1, func="float_op_wrapper", data="&cos"},
+ cosh={args=1, func="float_op_wrapper", data="&cosh"},
+ count={args={2, 4}},
+ cscope_connection={args={0, 3}},
+ cursor={args={1, 3}},
+ deepcopy={args={1, 2}},
+ delete={args={1,2}},
+ dictwatcheradd={args=3},
+ dictwatcherdel={args=3},
+ did_filetype={},
+ diff_filler={args=1},
+ diff_hlID={args=2},
+ empty={args=1},
+ escape={args=2},
+ eval={args=1},
+ eventhandler={},
+ executable={args=1},
+ execute={args=1},
+ exepath={args=1},
+ exists={args=1},
+ exp={args=1, func="float_op_wrapper", data="&exp"},
+ expand={args={1, 3}},
+ extend={args={2, 3}},
+ feedkeys={args={1, 2}},
+ file_readable={args=1, func='f_filereadable'}, -- obsolete
+ filereadable={args=1},
+ filewritable={args=1},
+ filter={args=2},
+ finddir={args={1, 3}},
+ findfile={args={1, 3}},
+ float2nr={args=1},
+ floor={args=1, func="float_op_wrapper", data="&floor"},
+ fmod={args=2},
+ fnameescape={args=1},
+ fnamemodify={args=2},
+ foldclosed={args=1},
+ foldclosedend={args=1},
+ foldlevel={args=1},
+ foldtext={},
+ foldtextresult={args=1},
+ foreground={},
+ ['function']={args=1},
+ garbagecollect={args={0, 1}},
+ get={args={2, 3}},
+ getbufline={args={2, 3}},
+ getbufvar={args={2, 3}},
+ getchar={args={0, 1}},
+ getcharmod={},
+ getcharsearch={},
+ getcmdline={},
+ getcmdpos={},
+ getcmdtype={},
+ getcmdwintype={},
+ getcompletion={args=2},
+ getcurpos={},
+ getcwd={args={0,2}},
+ getfontname={args={0, 1}},
+ getfperm={args=1},
+ getfsize={args=1},
+ getftime={args=1},
+ getftype={args=1},
+ getline={args={1, 2}},
+ getloclist={args=1, func='f_getqflist'},
+ getmatches={},
+ getpid={},
+ getpos={args=1},
+ getqflist={},
+ getreg={args={0, 3}},
+ getregtype={args={0, 1}},
+ gettabvar={args={2, 3}},
+ gettabwinvar={args={3, 4}},
+ getwinposx={},
+ getwinposy={},
+ getwinvar={args={2, 3}},
+ glob={args={1, 4}},
+ glob2regpat={args=1},
+ globpath={args={2, 5}},
+ has={args=1},
+ has_key={args=2},
+ haslocaldir={args={0,2}},
+ hasmapto={args={1, 3}},
+ highlightID={args=1, func='f_hlID'}, -- obsolete
+ highlight_exists={args=1, func='f_hlexists'}, -- obsolete
+ histadd={args=2},
+ histdel={args={1, 2}},
+ histget={args={1, 2}},
+ histnr={args=1},
+ hlID={args=1},
+ hlexists={args=1},
+ hostname={},
+ iconv={args=3},
+ indent={args=1},
+ index={args={2, 4}},
+ input={args={1, 3}},
+ inputdialog={args={1, 3}},
+ inputlist={args=1},
+ inputrestore={},
+ inputsave={},
+ inputsecret={args={1, 2}},
+ insert={args={2, 3}},
+ invert={args=1},
+ isdirectory={args=1},
+ islocked={args=1},
+ items={args=1},
+ jobclose={args={1, 2}},
+ jobpid={args=1},
+ jobresize={args=3},
+ jobsend={args=2},
+ jobstart={args={1, 2}},
+ jobstop={args=1},
+ jobwait={args={1, 2}},
+ join={args={1, 2}},
+ json_decode={args=1},
+ json_encode={args=1},
+ keys={args=1},
+ last_buffer_nr={}, -- obsolete
+ len={args=1},
+ libcall={args=3},
+ libcallnr={args=3},
+ line={args=1},
+ line2byte={args=1},
+ lispindent={args=1},
+ localtime={},
+ log={args=1, func="float_op_wrapper", data="&log"},
+ log10={args=1, func="float_op_wrapper", data="&log10"},
+ map={args=2},
+ maparg={args={1, 4}},
+ mapcheck={args={1, 3}},
+ match={args={2, 4}},
+ matchadd={args={2, 5}},
+ matchaddpos={args={2, 5}},
+ matcharg={args=1},
+ matchdelete={args=1},
+ matchend={args={2, 4}},
+ matchlist={args={2, 4}},
+ matchstr={args={2, 4}},
+ max={args=1},
+ min={args=1},
+ mkdir={args={1, 3}},
+ mode={args={0, 1}},
+ msgpackdump={args=1},
+ msgpackparse={args=1},
+ nextnonblank={args=1},
+ nr2char={args={1, 2}},
+ ['or']={args=2},
+ pathshorten={args=1},
+ pow={args=2},
+ prevnonblank={args=1},
+ printf={args=varargs(2)},
+ pumvisible={},
+ py3eval={args=1},
+ pyeval={args=1},
+ range={args={1, 3}},
+ readfile={args={1, 3}},
+ reltime={args={0, 2}},
+ reltimefloat={args=1},
+ reltimestr={args=1},
+ remove={args={2, 3}},
+ rename={args=2},
+ ['repeat']={args=2},
+ resolve={args=1},
+ reverse={args=1},
+ round={args=1, func="float_op_wrapper", data="&round"},
+ rpcnotify={args=varargs(2)},
+ rpcrequest={args=varargs(2)},
+ rpcstart={args={1, 2}},
+ rpcstop={args=1},
+ screenattr={args=2},
+ screenchar={args=2},
+ screencol={},
+ screenrow={},
+ search={args={1, 4}},
+ searchdecl={args={1, 3}},
+ searchpair={args={3, 7}},
+ searchpairpos={args={3, 7}},
+ searchpos={args={1, 4}},
+ serverlist={},
+ serverstart={args={0, 1}},
+ serverstop={args=1},
+ setbufvar={args=3},
+ setcharsearch={args=1},
+ setcmdpos={args=1},
+ setfperm={args=2},
+ setline={args=2},
+ setloclist={args={2, 4}},
+ setmatches={args=1},
+ setpos={args=2},
+ setqflist={args={1, 3}},
+ setreg={args={2, 3}},
+ settabvar={args=3},
+ settabwinvar={args=4},
+ setwinvar={args=3},
+ sha256={args=1},
+ shellescape={args={1, 2}},
+ shiftwidth={},
+ simplify={args=1},
+ sin={args=1, func="float_op_wrapper", data="&sin"},
+ sinh={args=1, func="float_op_wrapper", data="&sinh"},
+ sort={args={1, 3}},
+ soundfold={args=1},
+ spellbadword={args={0, 1}},
+ spellsuggest={args={1, 3}},
+ split={args={1, 3}},
+ sqrt={args=1, func="float_op_wrapper", data="&sqrt"},
+ str2float={args=1},
+ str2nr={args={1, 2}},
+ strchars={args={1,2}},
+ strdisplaywidth={args={1, 2}},
+ strftime={args={1, 2}},
+ stridx={args={2, 3}},
+ string={args=1},
+ strlen={args=1},
+ strpart={args={2, 3}},
+ strridx={args={2, 3}},
+ strtrans={args=1},
+ strwidth={args=1},
+ submatch={args={1, 2}},
+ substitute={args=4},
+ synID={args=3},
+ synIDattr={args={2, 3}},
+ synIDtrans={args=1},
+ synconcealed={args=2},
+ synstack={args=2},
+ system={args={1, 2}},
+ systemlist={args={1, 3}},
+ tabpagebuflist={args={0, 1}},
+ tabpagenr={args={0, 1}},
+ tabpagewinnr={args={1, 2}},
+ tagfiles={},
+ taglist={args=1},
+ tan={args=1, func="float_op_wrapper", data="&tan"},
+ tanh={args=1, func="float_op_wrapper", data="&tanh"},
+ tempname={},
+ termopen={args={1, 2}},
+ test={args=1},
+ timer_start={args={2,3}},
+ timer_stop={args=1},
+ tolower={args=1},
+ toupper={args=1},
+ tr={args=3},
+ trunc={args=1, func="float_op_wrapper", data="&trunc"},
+ type={args=1},
+ undofile={args=1},
+ undotree={},
+ uniq={args={1, 3}},
+ values={args=1},
+ virtcol={args=1},
+ visualmode={args={0, 1}},
+ wildmenumode={},
+ win_findbuf={args=1},
+ win_getid={args={0,2}},
+ win_gotoid={args=1},
+ win_id2tabwin={args=1},
+ win_id2win={args=1},
+ winbufnr={args=1},
+ wincol={},
+ winheight={args=1},
+ winline={},
+ winnr={args={0, 1}},
+ winrestcmd={},
+ winrestview={args=1},
+ winsaveview={},
+ winwidth={args=1},
+ wordcount={},
+ writefile={args={2, 3}},
+ xor={args=2},
+ },
+}
diff --git a/src/nvim/event/process.c b/src/nvim/event/process.c
index f507e3d71d..51f20b7eac 100644
--- a/src/nvim/event/process.c
+++ b/src/nvim/event/process.c
@@ -17,8 +17,7 @@
# include "event/process.c.generated.h"
#endif
-// {SIGNAL}_TIMEOUT is the time (in nanoseconds) that a process has to cleanly
-// exit before we send SIGNAL to it
+// Time (ns) for a process to exit cleanly before we send TERM/KILL.
#define TERM_TIMEOUT 1000000000
#define KILL_TIMEOUT (TERM_TIMEOUT * 2)
diff --git a/src/nvim/ex_cmds.c b/src/nvim/ex_cmds.c
index b7691997d7..9cf53f0d73 100644
--- a/src/nvim/ex_cmds.c
+++ b/src/nvim/ex_cmds.c
@@ -1711,11 +1711,11 @@ int do_write(exarg_T *eap)
goto theend;
}
- /* If 'filetype' was empty try detecting it now. */
+ // If 'filetype' was empty try detecting it now.
if (*curbuf->b_p_ft == NUL) {
- if (au_has_group((char_u *)"filetypedetect"))
- (void)do_doautocmd((char_u *)"filetypedetect BufRead",
- TRUE);
+ if (au_has_group((char_u *)"filetypedetect")) {
+ (void)do_doautocmd((char_u *)"filetypedetect BufRead", true, NULL);
+ }
do_modelines(0);
}
@@ -4053,9 +4053,7 @@ void ex_global(exarg_T *eap)
smsg(_("Pattern not found: %s"), pat);
}
} else {
- start_global_changes();
global_exe(cmd);
- end_global_changes();
}
ml_clearmarked(); /* clear rest of the marks */
vim_regfree(regmatch.regprog);
@@ -4565,12 +4563,15 @@ int find_help_tags(char_u *arg, int *num_matches, char_u ***matches, int keep_la
break;
}
- /*
- * If tag starts with ', toss everything after a second '. Fixes
- * CTRL-] on 'option'. (would include the trailing '.').
- */
- if (*s == '\'' && s > arg && *arg == '\'')
+ // If tag starts with ', toss everything after a second '. Fixes
+ // CTRL-] on 'option'. (would include the trailing '.').
+ if (*s == '\'' && s > arg && *arg == '\'') {
break;
+ }
+ // Also '{' and '}'. Fixes CTRL-] on '{address}'.
+ if (*s == '}' && s > arg && *arg == '{') {
+ break;
+ }
}
*d = NUL;
diff --git a/src/nvim/ex_cmds2.c b/src/nvim/ex_cmds2.c
index 6d24ba91f2..f68663c60c 100644
--- a/src/nvim/ex_cmds2.c
+++ b/src/nvim/ex_cmds2.c
@@ -27,7 +27,6 @@
#include "nvim/mbyte.h"
#include "nvim/message.h"
#include "nvim/misc1.h"
-#include "nvim/misc2.h"
#include "nvim/garray.h"
#include "nvim/memory.h"
#include "nvim/move.h"
@@ -1983,8 +1982,6 @@ void ex_listdo(exarg_T *eap)
save_ei = au_event_disable(",Syntax");
}
- start_global_changes();
-
if (eap->cmdidx == CMD_windo
|| eap->cmdidx == CMD_tabdo
|| P_HID(curbuf)
@@ -2181,7 +2178,6 @@ void ex_listdo(exarg_T *eap)
apply_autocmds(EVENT_SYNTAX, curbuf->b_p_syn,
curbuf->b_fname, true, curbuf);
}
- end_global_changes();
}
/// Add files[count] to the arglist of the current window after arg "after".
diff --git a/src/nvim/ex_cmds_defs.h b/src/nvim/ex_cmds_defs.h
index 421c14b495..8148eb5cee 100644
--- a/src/nvim/ex_cmds_defs.h
+++ b/src/nvim/ex_cmds_defs.h
@@ -126,56 +126,53 @@ struct exarg {
struct condstack *cstack; ///< condition stack for ":if" etc.
};
-#define FORCE_BIN 1 /* ":edit ++bin file" */
-#define FORCE_NOBIN 2 /* ":edit ++nobin file" */
-
-/* Values for "flags" */
-#define EXFLAG_LIST 0x01 /* 'l': list */
-#define EXFLAG_NR 0x02 /* '#': number */
-#define EXFLAG_PRINT 0x04 /* 'p': print */
-
-/*
- * used for completion on the command line
- */
-typedef struct expand {
- int xp_context; /* type of expansion */
- char_u *xp_pattern; /* start of item to expand */
- int xp_pattern_len; /* bytes in xp_pattern before cursor */
- char_u *xp_arg; /* completion function */
- int xp_scriptID; /* SID for completion function */
- int xp_backslash; /* one of the XP_BS_ values */
+#define FORCE_BIN 1 // ":edit ++bin file"
+#define FORCE_NOBIN 2 // ":edit ++nobin file"
+
+// Values for "flags"
+#define EXFLAG_LIST 0x01 // 'l': list
+#define EXFLAG_NR 0x02 // '#': number
+#define EXFLAG_PRINT 0x04 // 'p': print
+
+// used for completion on the command line
+struct expand {
+ int xp_context; // type of expansion
+ char_u *xp_pattern; // start of item to expand
+ int xp_pattern_len; // bytes in xp_pattern before cursor
+ char_u *xp_arg; // completion function
+ int xp_scriptID; // SID for completion function
+ int xp_backslash; // one of the XP_BS_ values
#ifndef BACKSLASH_IN_FILENAME
- int xp_shell; /* TRUE for a shell command, more
- characters need to be escaped */
+ int xp_shell; // TRUE for a shell command, more
+ // characters need to be escaped
#endif
- int xp_numfiles; /* number of files found by
- file name completion */
- char_u **xp_files; /* list of files */
- char_u *xp_line; /* text being completed */
- int xp_col; /* cursor position in line */
-} expand_T;
-
-/* values for xp_backslash */
-#define XP_BS_NONE 0 /* nothing special for backslashes */
-#define XP_BS_ONE 1 /* uses one backslash before a space */
-#define XP_BS_THREE 2 /* uses three backslashes before a space */
+ int xp_numfiles; // number of files found by file name completion
+ char_u **xp_files; // list of files
+ char_u *xp_line; // text being completed
+ int xp_col; // cursor position in line
+};
+
+// values for xp_backslash
+#define XP_BS_NONE 0 // nothing special for backslashes
+#define XP_BS_ONE 1 // uses one backslash before a space
+#define XP_BS_THREE 2 // uses three backslashes before a space
/// Command modifiers ":vertical", ":browse", ":confirm", ":hide", etc. set a
/// flag. This needs to be saved for recursive commands, put them in a
/// structure for easy manipulation.
typedef struct {
- int hide; ///< TRUE when ":hide" was used
- int split; ///< flags for win_split()
- int tab; ///< > 0 when ":tab" was used
- int confirm; ///< TRUE to invoke yes/no dialog
- int keepalt; ///< TRUE when ":keepalt" was used
- int keepmarks; ///< TRUE when ":keepmarks" was used
- int keepjumps; ///< TRUE when ":keepjumps" was used
- int lockmarks; ///< TRUE when ":lockmarks" was used
- int keeppatterns; ///< TRUE when ":keeppatterns" was used
- bool noswapfile; ///< true when ":noswapfile" was used
- bool browse; ///< TRUE to invoke file dialog
- char_u *save_ei; ///< saved value of 'eventignore'
+ int split; ///< flags for win_split()
+ int tab; ///< > 0 when ":tab" was used
+ bool browse; ///< true to invoke file dialog
+ bool confirm; ///< true to invoke yes/no dialog
+ bool hide; ///< true when ":hide" was used
+ bool keepalt; ///< true when ":keepalt" was used
+ bool keepjumps; ///< true when ":keepjumps" was used
+ bool keepmarks; ///< true when ":keepmarks" was used
+ bool keeppatterns; ///< true when ":keeppatterns" was used
+ bool lockmarks; ///< true when ":lockmarks" was used
+ bool noswapfile; ///< true when ":noswapfile" was used
+ char_u *save_ei; ///< saved value of 'eventignore'
} cmdmod_T;
#endif // NVIM_EX_CMDS_DEFS_H
diff --git a/src/nvim/ex_docmd.c b/src/nvim/ex_docmd.c
index 1e54f03ba0..45407b7f12 100644
--- a/src/nvim/ex_docmd.c
+++ b/src/nvim/ex_docmd.c
@@ -36,7 +36,6 @@
#include "nvim/menu.h"
#include "nvim/message.h"
#include "nvim/misc1.h"
-#include "nvim/misc2.h"
#include "nvim/keymap.h"
#include "nvim/file_search.h"
#include "nvim/garray.h"
@@ -345,7 +344,8 @@ int do_cmdline(char_u *cmdline, LineGetter fgetline,
msg_list = saved_msg_list;
return FAIL;
}
- ++call_depth;
+ call_depth++;
+ start_batch_changes();
cstack.cs_idx = -1;
cstack.cs_looplevel = 0;
@@ -952,7 +952,8 @@ int do_cmdline(char_u *cmdline, LineGetter fgetline,
did_endif = FALSE; /* in case do_cmdline used recursively */
- --call_depth;
+ call_depth--;
+ end_batch_changes();
return retval;
}
@@ -1325,24 +1326,24 @@ static char_u * do_one_cmd(char_u **cmdlinep,
case 'c': if (!checkforcmd(&ea.cmd, "confirm", 4))
break;
- cmdmod.confirm = TRUE;
+ cmdmod.confirm = true;
continue;
case 'k': if (checkforcmd(&ea.cmd, "keepmarks", 3)) {
- cmdmod.keepmarks = TRUE;
+ cmdmod.keepmarks = true;
continue;
}
if (checkforcmd(&ea.cmd, "keepalt", 5)) {
- cmdmod.keepalt = TRUE;
+ cmdmod.keepalt = true;
continue;
}
if (checkforcmd(&ea.cmd, "keeppatterns", 5)) {
- cmdmod.keeppatterns = TRUE;
+ cmdmod.keeppatterns = true;
continue;
}
if (!checkforcmd(&ea.cmd, "keepjumps", 5))
break;
- cmdmod.keepjumps = TRUE;
+ cmdmod.keepjumps = true;
continue;
/* ":hide" and ":hide | cmd" are not modifiers */
@@ -1350,11 +1351,11 @@ static char_u * do_one_cmd(char_u **cmdlinep,
|| *p == NUL || ends_excmd(*p))
break;
ea.cmd = p;
- cmdmod.hide = TRUE;
+ cmdmod.hide = true;
continue;
case 'l': if (checkforcmd(&ea.cmd, "lockmarks", 3)) {
- cmdmod.lockmarks = TRUE;
+ cmdmod.lockmarks = true;
continue;
}
@@ -4362,12 +4363,15 @@ static void ex_autocmd(exarg_T *eap)
*/
static void ex_doautocmd(exarg_T *eap)
{
- char_u *arg = eap->arg;
+ char_u *arg = eap->arg;
int call_do_modelines = check_nomodeline(&arg);
+ bool did_aucmd;
- (void)do_doautocmd(arg, TRUE);
- if (call_do_modelines) /* Only when there is no <nomodeline>. */
+ (void)do_doautocmd(arg, true, &did_aucmd);
+ // Only when there is no <nomodeline>.
+ if (call_do_modelines && did_aucmd) {
do_modelines(0);
+ }
}
/*
@@ -5154,6 +5158,24 @@ static char_u *uc_split_args(char_u *arg, size_t *lenp)
return buf;
}
+static size_t add_cmd_modifier(char_u *buf, char *mod_str, bool *multi_mods)
+{
+ size_t result = STRLEN(mod_str);
+ if (*multi_mods) {
+ result++;
+ }
+
+ if (buf != NULL) {
+ if (*multi_mods) {
+ STRCAT(buf, " ");
+ }
+ STRCAT(buf, mod_str);
+ }
+
+ *multi_mods = true;
+ return result;
+}
+
/*
* Check for a <> code in a user command.
* "code" points to the '<'. "len" the length of the <> (inclusive).
@@ -5178,8 +5200,8 @@ uc_check_code (
char_u *p = code + 1;
size_t l = len - 2;
int quote = 0;
- enum { ct_ARGS, ct_BANG, ct_COUNT, ct_LINE1, ct_LINE2, ct_REGISTER,
- ct_LT, ct_NONE } type = ct_NONE;
+ enum { ct_ARGS, ct_BANG, ct_COUNT, ct_LINE1, ct_LINE2, ct_MODS,
+ ct_REGISTER, ct_LT, ct_NONE } type = ct_NONE;
if ((vim_strchr((char_u *)"qQfF", *p) != NULL) && p[1] == '-') {
quote = (*p == 'q' || *p == 'Q') ? 1 : 2;
@@ -5187,23 +5209,26 @@ uc_check_code (
l -= 2;
}
- ++l;
- if (l <= 1)
+ l++;
+ if (l <= 1) {
type = ct_NONE;
- else if (STRNICMP(p, "args>", l) == 0)
+ } else if (STRNICMP(p, "args>", l) == 0) {
type = ct_ARGS;
- else if (STRNICMP(p, "bang>", l) == 0)
+ } else if (STRNICMP(p, "bang>", l) == 0) {
type = ct_BANG;
- else if (STRNICMP(p, "count>", l) == 0)
+ } else if (STRNICMP(p, "count>", l) == 0) {
type = ct_COUNT;
- else if (STRNICMP(p, "line1>", l) == 0)
+ } else if (STRNICMP(p, "line1>", l) == 0) {
type = ct_LINE1;
- else if (STRNICMP(p, "line2>", l) == 0)
+ } else if (STRNICMP(p, "line2>", l) == 0) {
type = ct_LINE2;
- else if (STRNICMP(p, "lt>", l) == 0)
+ } else if (STRNICMP(p, "lt>", l) == 0) {
type = ct_LT;
- else if (STRNICMP(p, "reg>", l) == 0 || STRNICMP(p, "register>", l) == 0)
+ } else if (STRNICMP(p, "reg>", l) == 0 || STRNICMP(p, "register>", l) == 0) {
type = ct_REGISTER;
+ } else if (STRNICMP(p, "mods>", l) == 0) {
+ type = ct_MODS;
+ }
switch (type) {
case ct_ARGS:
@@ -5311,6 +5336,87 @@ uc_check_code (
break;
}
+ case ct_MODS:
+ {
+ result = quote ? 2 : 0;
+ if (buf != NULL) {
+ if (quote) {
+ *buf++ = '"';
+ }
+ *buf = '\0';
+ }
+
+ bool multi_mods = false;
+
+ // :aboveleft and :leftabove
+ if (cmdmod.split & WSP_ABOVE) {
+ result += add_cmd_modifier(buf, "aboveleft", &multi_mods);
+ }
+ // :belowright and :rightbelow
+ if (cmdmod.split & WSP_BELOW) {
+ result += add_cmd_modifier(buf, "belowright", &multi_mods);
+ }
+ // :botright
+ if (cmdmod.split & WSP_BOT) {
+ result += add_cmd_modifier(buf, "botright", &multi_mods);
+ }
+
+ typedef struct {
+ bool *set;
+ char *name;
+ } mod_entry_T;
+ static mod_entry_T mod_entries[] = {
+ { &cmdmod.browse, "browse" },
+ { &cmdmod.confirm, "confirm" },
+ { &cmdmod.hide, "hide" },
+ { &cmdmod.keepalt, "keepalt" },
+ { &cmdmod.keepjumps, "keepjumps" },
+ { &cmdmod.keepmarks, "keepmarks" },
+ { &cmdmod.keeppatterns, "keeppatterns" },
+ { &cmdmod.lockmarks, "lockmarks" },
+ { &cmdmod.noswapfile, "noswapfile" }
+ };
+ // the modifiers that are simple flags
+ for (size_t i = 0; i < ARRAY_SIZE(mod_entries); i++) {
+ if (*mod_entries[i].set) {
+ result += add_cmd_modifier(buf, mod_entries[i].name, &multi_mods);
+ }
+ }
+
+ // TODO(vim): How to support :noautocmd?
+ // TODO(vim): How to support :sandbox?
+
+ // :silent
+ if (msg_silent > 0) {
+ result += add_cmd_modifier(buf, emsg_silent > 0 ? "silent!" : "silent",
+ &multi_mods);
+ }
+ // :tab
+ if (cmdmod.tab > 0) {
+ result += add_cmd_modifier(buf, "tab", &multi_mods);
+ }
+ // :topleft
+ if (cmdmod.split & WSP_TOP) {
+ result += add_cmd_modifier(buf, "topleft", &multi_mods);
+ }
+
+ // TODO(vim): How to support :unsilent?
+
+ // :verbose
+ if (p_verbose > 0) {
+ result += add_cmd_modifier(buf, "verbose", &multi_mods);
+ }
+ // :vertical
+ if (cmdmod.split & WSP_VERT) {
+ result += add_cmd_modifier(buf, "vertical", &multi_mods);
+ }
+ if (quote && buf != NULL) {
+ buf += result - 2;
+ *buf = '"';
+ }
+ break;
+ }
+
case ct_REGISTER:
result = eap->regname ? 1 : 0;
if (quote)
@@ -9360,7 +9466,7 @@ static void ex_filetype(exarg_T *eap)
}
}
if (*arg == 'd') {
- (void)do_doautocmd((char_u *)"filetypedetect BufRead", TRUE);
+ (void)do_doautocmd((char_u *)"filetypedetect BufRead", true, NULL);
do_modelines(0);
}
} else if (STRCMP(arg, "off") == 0) {
@@ -9511,20 +9617,15 @@ static void ex_foldopen(exarg_T *eap)
static void ex_folddo(exarg_T *eap)
{
- linenr_T lnum;
-
- start_global_changes();
-
- /* First set the marks for all lines closed/open. */
- for (lnum = eap->line1; lnum <= eap->line2; ++lnum)
- if (hasFolding(lnum, NULL, NULL) == (eap->cmdidx == CMD_folddoclosed))
+ // First set the marks for all lines closed/open.
+ for (linenr_T lnum = eap->line1; lnum <= eap->line2; ++lnum) {
+ if (hasFolding(lnum, NULL, NULL) == (eap->cmdidx == CMD_folddoclosed)) {
ml_setmarked(lnum);
+ }
+ }
- /* Execute the command on the marked lines. */
- global_exe(eap->arg);
- ml_clearmarked(); /* clear rest of the marks */
-
- end_global_changes();
+ global_exe(eap->arg); // Execute the command on the marked lines.
+ ml_clearmarked(); // clear rest of the marks
}
static void ex_terminal(exarg_T *eap)
diff --git a/src/nvim/ex_eval.c b/src/nvim/ex_eval.c
index 82d4c2b2d5..f518fa0d66 100644
--- a/src/nvim/ex_eval.c
+++ b/src/nvim/ex_eval.c
@@ -15,7 +15,6 @@
#include "nvim/ex_cmds2.h"
#include "nvim/ex_docmd.h"
#include "nvim/message.h"
-#include "nvim/misc2.h"
#include "nvim/memory.h"
#include "nvim/regexp.h"
#include "nvim/strings.h"
diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c
index cd28554970..1a97dc3d6f 100644
--- a/src/nvim/ex_getln.c
+++ b/src/nvim/ex_getln.c
@@ -34,7 +34,6 @@
#include "nvim/menu.h"
#include "nvim/message.h"
#include "nvim/misc1.h"
-#include "nvim/misc2.h"
#include "nvim/memory.h"
#include "nvim/cursor_shape.h"
#include "nvim/keymap.h"
diff --git a/src/nvim/farsi.c b/src/nvim/farsi.c
index 61e17128ea..eb22ad1428 100644
--- a/src/nvim/farsi.c
+++ b/src/nvim/farsi.c
@@ -15,7 +15,6 @@
#include "nvim/memline.h"
#include "nvim/message.h"
#include "nvim/misc1.h"
-#include "nvim/misc2.h"
#include "nvim/screen.h"
#include "nvim/strings.h"
#include "nvim/vim.h"
diff --git a/src/nvim/file_search.c b/src/nvim/file_search.c
index 78b224f04c..c6cfba8142 100644
--- a/src/nvim/file_search.c
+++ b/src/nvim/file_search.c
@@ -1,48 +1,44 @@
-/* TODO: make some #ifdef for this */
-/*--------[ file searching ]-------------------------------------------------*/
-/*
- * File searching functions for 'path', 'tags' and 'cdpath' options.
- * External visible functions:
- * vim_findfile_init() creates/initialises the search context
- * vim_findfile_free_visited() free list of visited files/dirs of search
- * context
- * vim_findfile() find a file in the search context
- * vim_findfile_cleanup() cleanup/free search context created by
- * vim_findfile_init()
- *
- * All static functions and variables start with 'ff_'
- *
- * In general it works like this:
- * First you create yourself a search context by calling vim_findfile_init().
- * It is possible to give a search context from a previous call to
- * vim_findfile_init(), so it can be reused. After this you call vim_findfile()
- * until you are satisfied with the result or it returns NULL. On every call it
- * returns the next file which matches the conditions given to
- * vim_findfile_init(). If it doesn't find a next file it returns NULL.
- *
- * It is possible to call vim_findfile_init() again to reinitialise your search
- * with some new parameters. Don't forget to pass your old search context to
- * it, so it can reuse it and especially reuse the list of already visited
- * directories. If you want to delete the list of already visited directories
- * simply call vim_findfile_free_visited().
- *
- * When you are done call vim_findfile_cleanup() to free the search context.
- *
- * The function vim_findfile_init() has a long comment, which describes the
- * needed parameters.
- *
- *
- *
- * ATTENTION:
- * ==========
- * Also we use an allocated search context here, this functions are NOT
- * thread-safe!!!!!
- *
- * To minimize parameter passing (or because I'm to lazy), only the
- * external visible functions get a search context as a parameter. This is
- * then assigned to a static global, which is used throughout the local
- * functions.
- */
+// File searching functions for 'path', 'tags' and 'cdpath' options.
+//
+// External visible functions:
+// vim_findfile_init() creates/initialises the search context
+// vim_findfile_free_visited() free list of visited files/dirs of search
+// context
+// vim_findfile() find a file in the search context
+// vim_findfile_cleanup() cleanup/free search context created by
+// vim_findfile_init()
+//
+// All static functions and variables start with 'ff_'
+//
+// In general it works like this:
+// First you create yourself a search context by calling vim_findfile_init().
+// It is possible to give a search context from a previous call to
+// vim_findfile_init(), so it can be reused. After this you call vim_findfile()
+// until you are satisfied with the result or it returns NULL. On every call it
+// returns the next file which matches the conditions given to
+// vim_findfile_init(). If it doesn't find a next file it returns NULL.
+//
+// It is possible to call vim_findfile_init() again to reinitialise your search
+// with some new parameters. Don't forget to pass your old search context to
+// it, so it can reuse it and especially reuse the list of already visited
+// directories. If you want to delete the list of already visited directories
+// simply call vim_findfile_free_visited().
+//
+// When you are done call vim_findfile_cleanup() to free the search context.
+//
+// The function vim_findfile_init() has a long comment, which describes the
+// needed parameters.
+//
+//
+//
+// ATTENTION:
+// ==========
+// We use an allocated search context, these functions are NOT thread-safe!!!!!
+//
+// To minimize parameter passing (or because I'm too lazy), only the
+// external visible functions get a search context as a parameter. This is
+// then assigned to a static global, which is used throughout the local
+// functions.
#include <assert.h>
#include <string.h>
@@ -59,7 +55,7 @@
#include "nvim/memory.h"
#include "nvim/message.h"
#include "nvim/misc1.h"
-#include "nvim/misc2.h"
+#include "nvim/option.h"
#include "nvim/os_unix.h"
#include "nvim/path.h"
#include "nvim/strings.h"
@@ -1526,3 +1522,28 @@ theend:
return file_name;
}
+/// Change to a file's directory.
+/// Caller must call shorten_fnames()!
+/// @return OK or FAIL
+int vim_chdirfile(char_u *fname)
+{
+ char_u dir[MAXPATHL];
+
+ STRLCPY(dir, fname, MAXPATHL);
+ *path_tail_with_sep(dir) = NUL;
+ return os_chdir((char *)dir) == 0 ? OK : FAIL;
+}
+
+/// Change directory to "new_dir". Search 'cdpath' for relative directory names.
+int vim_chdir(char_u *new_dir)
+{
+ char_u *dir_name = find_directory_in_path(new_dir, STRLEN(new_dir),
+ FNAME_MESS, curbuf->b_ffname);
+ if (dir_name == NULL) {
+ return -1;
+ }
+ int r = os_chdir((char *)dir_name);
+ xfree(dir_name);
+ return r;
+}
+
diff --git a/src/nvim/fileio.c b/src/nvim/fileio.c
index e0b6ae1215..c0d4a71b35 100644
--- a/src/nvim/fileio.c
+++ b/src/nvim/fileio.c
@@ -32,7 +32,6 @@
#include "nvim/memory.h"
#include "nvim/message.h"
#include "nvim/misc1.h"
-#include "nvim/misc2.h"
#include "nvim/garray.h"
#include "nvim/move.h"
#include "nvim/normal.h"
@@ -44,6 +43,7 @@
#include "nvim/screen.h"
#include "nvim/search.h"
#include "nvim/sha256.h"
+#include "nvim/state.h"
#include "nvim/strings.h"
#include "nvim/ui.h"
#include "nvim/types.h"
@@ -3773,8 +3773,9 @@ static int set_rw_fname(char_u *fname, char_u *sfname)
/* Do filetype detection now if 'filetype' is empty. */
if (*curbuf->b_p_ft == NUL) {
- if (au_has_group((char_u *)"filetypedetect"))
- (void)do_doautocmd((char_u *)"filetypedetect BufRead", FALSE);
+ if (au_has_group((char_u *)"filetypedetect")) {
+ (void)do_doautocmd((char_u *)"filetypedetect BufRead", false, NULL);
+ }
do_modelines(0);
}
@@ -4446,11 +4447,95 @@ bool vim_fgets(char_u *buf, int size, FILE *fp) FUNC_ATTR_NONNULL_ALL
return eof == NULL;
}
-/*
- * os_rename() only works if both files are on the same file system, this
- * function will (attempts to?) copy the file across if rename fails -- webb
- * Return -1 for failure, 0 for success.
- */
+/// Read 2 bytes from "fd" and turn them into an int, MSB first.
+int get2c(FILE *fd)
+{
+ int n;
+
+ n = getc(fd);
+ n = (n << 8) + getc(fd);
+ return n;
+}
+
+/// Read 3 bytes from "fd" and turn them into an int, MSB first.
+int get3c(FILE *fd)
+{
+ int n;
+
+ n = getc(fd);
+ n = (n << 8) + getc(fd);
+ n = (n << 8) + getc(fd);
+ return n;
+}
+
+/// Read 4 bytes from "fd" and turn them into an int, MSB first.
+int get4c(FILE *fd)
+{
+ // Use unsigned rather than int otherwise result is undefined
+ // when left-shift sets the MSB.
+ unsigned n;
+
+ n = (unsigned)getc(fd);
+ n = (n << 8) + (unsigned)getc(fd);
+ n = (n << 8) + (unsigned)getc(fd);
+ n = (n << 8) + (unsigned)getc(fd);
+ return (int)n;
+}
+
+/// Read 8 bytes from `fd` and turn them into a time_t, MSB first.
+time_t get8ctime(FILE *fd)
+{
+ time_t n = 0;
+ int i;
+
+ for (i = 0; i < 8; i++) {
+ n = (n << 8) + getc(fd);
+ }
+ return n;
+}
+
+/// Reads a string of length "cnt" from "fd" into allocated memory.
+/// @return pointer to the string or NULL when unable to read that many bytes.
+char *read_string(FILE *fd, size_t cnt)
+{
+ char *str = xmallocz(cnt);
+ for (size_t i = 0; i < cnt; i++) {
+ int c = getc(fd);
+ if (c == EOF) {
+ xfree(str);
+ return NULL;
+ }
+ str[i] = (char)c;
+ }
+ return str;
+}
+
+/// Writes a number to file "fd", most significant bit first, in "len" bytes.
+/// @returns false in case of an error.
+bool put_bytes(FILE *fd, uintmax_t number, size_t len)
+{
+ assert(len > 0);
+ for (size_t i = len - 1; i < len; i--) {
+ if (putc((int)(number >> (i * 8)), fd) == EOF) {
+ return false;
+ }
+ }
+ return true;
+}
+
+/// Writes time_t to file "fd" in 8 bytes.
+/// @returns FAIL when the write failed.
+int put_time(FILE *fd, time_t time_)
+{
+ uint8_t buf[8];
+ time_to_bytes(time_, buf);
+ return fwrite(buf, sizeof(uint8_t), ARRAY_SIZE(buf), fd) == 1 ? OK : FAIL;
+}
+
+/// os_rename() only works if both files are on the same file system, this
+/// function will (attempts to?) copy the file across if rename fails -- webb
+//
+/// @return -1 for failure, 0 for success
int vim_rename(char_u *from, char_u *to)
{
int fd_in;
@@ -6058,13 +6143,18 @@ static int do_autocmd_event(event_T event, char_u *pat, int nested, char_u *cmd,
int
do_doautocmd (
char_u *arg,
- int do_msg /* give message for no matching autocmds? */
+ int do_msg, // give message for no matching autocmds?
+ bool *did_something
)
{
char_u *fname;
int nothing_done = TRUE;
int group;
+ if (did_something != NULL) {
+ *did_something = false;
+ }
+
/*
* Check for a legal group name. If not, use AUGROUP_ALL.
*/
@@ -6093,8 +6183,12 @@ do_doautocmd (
fname, NULL, TRUE, group, curbuf, NULL))
nothing_done = FALSE;
- if (nothing_done && do_msg)
+ if (nothing_done && do_msg) {
MSG(_("No matching autocommands"));
+ }
+ if (did_something != NULL) {
+ *did_something = !nothing_done;
+ }
return aborting() ? FAIL : OK;
}
@@ -6123,13 +6217,14 @@ void ex_doautoall(exarg_T *eap)
/* find a window for this buffer and save some values */
aucmd_prepbuf(&aco, buf);
- /* execute the autocommands for this buffer */
- retval = do_doautocmd(arg, FALSE);
+ bool did_aucmd;
+ // execute the autocommands for this buffer
+ retval = do_doautocmd(arg, false, &did_aucmd);
- if (call_do_modelines) {
- /* Execute the modeline settings, but don't set window-local
- * options if we are using the current window for another
- * buffer. */
+ if (call_do_modelines && did_aucmd) {
+ // Execute the modeline settings, but don't set window-local
+ // options if we are using the current window for another
+ // buffer.
do_modelines(curwin == aucmd_win ? OPT_NOWIN : 0);
}
diff --git a/src/nvim/fileio.h b/src/nvim/fileio.h
index d93f3f3eb3..ceb101167d 100644
--- a/src/nvim/fileio.h
+++ b/src/nvim/fileio.h
@@ -12,6 +12,8 @@
#define READ_DUMMY 0x10 /* reading into a dummy buffer */
#define READ_KEEP_UNDO 0x20 /* keep undo info*/
+#define READ_STRING(x, y) (char_u *)read_string((x), (size_t)(y))
+
/*
* Struct to save values in before executing autocommands for a buffer that is
* not the current buffer.
diff --git a/src/nvim/fold.c b/src/nvim/fold.c
index ac3cf959c8..70030b8525 100644
--- a/src/nvim/fold.c
+++ b/src/nvim/fold.c
@@ -22,7 +22,6 @@
#include "nvim/memory.h"
#include "nvim/message.h"
#include "nvim/misc1.h"
-#include "nvim/misc2.h"
#include "nvim/garray.h"
#include "nvim/move.h"
#include "nvim/option.h"
@@ -762,16 +761,12 @@ void clearFolding(win_T *win)
*/
void foldUpdate(win_T *wp, linenr_T top, linenr_T bot)
{
- if (compl_busy) {
- return;
- }
-
- fold_T *fp;
- if (wp->w_buffer->terminal) {
+ if (compl_busy || State & INSERT) {
return;
}
// Mark all folds from top to bot as maybe-small.
+ fold_T *fp;
(void)foldFind(&wp->w_folds, top, &fp);
while (fp < (fold_T *)wp->w_folds.ga_data + wp->w_folds.ga_len
&& fp->fd_top < bot) {
diff --git a/src/nvim/func_attr.h b/src/nvim/func_attr.h
index ea017ab0c8..d98fe5b22b 100644
--- a/src/nvim/func_attr.h
+++ b/src/nvim/func_attr.h
@@ -185,6 +185,7 @@
#ifdef DEFINE_FUNC_ATTRIBUTES
# define FUNC_API_ASYNC
# define FUNC_API_NOEXPORT
+# define FUNC_API_NOEVAL
# define FUNC_ATTR_MALLOC REAL_FATTR_MALLOC
# define FUNC_ATTR_ALLOC_SIZE(x) REAL_FATTR_ALLOC_SIZE(x)
# define FUNC_ATTR_ALLOC_SIZE_PROD(x, y) REAL_FATTR_ALLOC_SIZE_PROD(x, y)
diff --git a/src/nvim/garray.c b/src/nvim/garray.c
index 98cec69b54..9ed3b901ef 100644
--- a/src/nvim/garray.c
+++ b/src/nvim/garray.c
@@ -8,7 +8,6 @@
#include "nvim/vim.h"
#include "nvim/ascii.h"
#include "nvim/log.h"
-#include "nvim/misc2.h"
#include "nvim/memory.h"
#include "nvim/path.h"
#include "nvim/garray.h"
diff --git a/src/nvim/getchar.c b/src/nvim/getchar.c
index ae1857f318..dad0ac33cd 100644
--- a/src/nvim/getchar.c
+++ b/src/nvim/getchar.c
@@ -29,7 +29,6 @@
#include "nvim/memory.h"
#include "nvim/message.h"
#include "nvim/misc1.h"
-#include "nvim/misc2.h"
#include "nvim/keymap.h"
#include "nvim/garray.h"
#include "nvim/move.h"
@@ -38,6 +37,7 @@
#include "nvim/option.h"
#include "nvim/regexp.h"
#include "nvim/screen.h"
+#include "nvim/state.h"
#include "nvim/strings.h"
#include "nvim/ui.h"
#include "nvim/undo.h"
diff --git a/src/nvim/hardcopy.c b/src/nvim/hardcopy.c
index 1c9b8e18ef..7d4bfd0290 100644
--- a/src/nvim/hardcopy.c
+++ b/src/nvim/hardcopy.c
@@ -23,7 +23,6 @@
#include "nvim/memline.h"
#include "nvim/memory.h"
#include "nvim/message.h"
-#include "nvim/misc2.h"
#include "nvim/garray.h"
#include "nvim/option.h"
#include "nvim/path.h"
diff --git a/src/nvim/hashtab.c b/src/nvim/hashtab.c
index 2da937633e..7d4ae61fc4 100644
--- a/src/nvim/hashtab.c
+++ b/src/nvim/hashtab.c
@@ -28,7 +28,6 @@
#include "nvim/hashtab.h"
#include "nvim/message.h"
#include "nvim/memory.h"
-#include "nvim/misc2.h"
// Magic value for algorithm that walks through the array.
#define PERTURB_SHIFT 5
diff --git a/src/nvim/iconv.h b/src/nvim/iconv.h
index 4ac0d3fdd4..bf29b15247 100644
--- a/src/nvim/iconv.h
+++ b/src/nvim/iconv.h
@@ -24,10 +24,10 @@
// defined, we provide a type shim (pull in errno.h and define iconv_t).
// This enables us to still load and use iconv dynamically at runtime.
#ifdef USE_ICONV
+# include <errno.h>
# ifdef HAVE_ICONV_H
# include <iconv.h>
# else
-# include <errno.h>
typedef void *iconv_t;
# endif
#endif
diff --git a/src/nvim/if_cscope.c b/src/nvim/if_cscope.c
index 8684957393..3ed85677fc 100644
--- a/src/nvim/if_cscope.c
+++ b/src/nvim/if_cscope.c
@@ -20,7 +20,6 @@
#include "nvim/eval.h"
#include "nvim/fileio.h"
#include "nvim/message.h"
-#include "nvim/misc2.h"
#include "nvim/memory.h"
#include "nvim/os/time.h"
#include "nvim/path.h"
diff --git a/src/nvim/indent.c b/src/nvim/indent.c
index f197669a97..7f31bb8c5c 100644
--- a/src/nvim/indent.c
+++ b/src/nvim/indent.c
@@ -10,7 +10,6 @@
#include "nvim/memline.h"
#include "nvim/memory.h"
#include "nvim/misc1.h"
-#include "nvim/misc2.h"
#include "nvim/move.h"
#include "nvim/option.h"
#include "nvim/regexp.h"
diff --git a/src/nvim/indent_c.c b/src/nvim/indent_c.c
index efe8e73a3c..6f03cf6037 100644
--- a/src/nvim/indent_c.c
+++ b/src/nvim/indent_c.c
@@ -12,7 +12,6 @@
#include "nvim/indent_c.h"
#include "nvim/memline.h"
#include "nvim/memory.h"
-#include "nvim/misc2.h"
#include "nvim/option.h"
#include "nvim/search.h"
#include "nvim/strings.h"
diff --git a/src/nvim/main.c b/src/nvim/main.c
index b5c51e3444..a153931d8a 100644
--- a/src/nvim/main.c
+++ b/src/nvim/main.c
@@ -30,7 +30,6 @@
#include "nvim/memline.h"
#include "nvim/message.h"
#include "nvim/misc1.h"
-#include "nvim/misc2.h"
#include "nvim/garray.h"
#include "nvim/log.h"
#include "nvim/memory.h"
@@ -58,13 +57,13 @@
#include "nvim/event/loop.h"
#include "nvim/os/signal.h"
#include "nvim/event/process.h"
-#include "nvim/msgpack_rpc/defs.h"
#include "nvim/msgpack_rpc/helpers.h"
#include "nvim/msgpack_rpc/server.h"
#include "nvim/msgpack_rpc/channel.h"
#include "nvim/api/private/defs.h"
#include "nvim/api/private/helpers.h"
#include "nvim/api/private/handle.h"
+#include "nvim/api/private/dispatch.h"
/* Maximum number of commands from + or -c arguments. */
#define MAX_ARG_CMDS 10
diff --git a/src/nvim/map.c b/src/nvim/map.c
index 398e74268f..73af487f90 100644
--- a/src/nvim/map.c
+++ b/src/nvim/map.c
@@ -6,7 +6,7 @@
#include "nvim/map_defs.h"
#include "nvim/vim.h"
#include "nvim/memory.h"
-#include "nvim/msgpack_rpc/defs.h"
+#include "nvim/api/private/dispatch.h"
#include "nvim/lib/khash.h"
@@ -20,6 +20,8 @@
#define int_eq kh_int_hash_equal
#define linenr_T_hash kh_int_hash_func
#define linenr_T_eq kh_int_hash_equal
+#define handle_T_hash kh_int_hash_func
+#define handle_T_eq kh_int_hash_equal
#if defined(ARCH_64)
@@ -141,7 +143,8 @@ MAP_IMPL(cstr_t, uint64_t, DEFAULT_INITIALIZER)
MAP_IMPL(cstr_t, ptr_t, DEFAULT_INITIALIZER)
MAP_IMPL(ptr_t, ptr_t, DEFAULT_INITIALIZER)
MAP_IMPL(uint64_t, ptr_t, DEFAULT_INITIALIZER)
-#define MSGPACK_HANDLER_INITIALIZER {.fn = NULL, .async = false}
+MAP_IMPL(handle_T, ptr_t, DEFAULT_INITIALIZER)
+#define MSGPACK_HANDLER_INITIALIZER { .fn = NULL, .async = false }
MAP_IMPL(String, MsgpackRpcRequestHandler, MSGPACK_HANDLER_INITIALIZER)
#define KVEC_INITIALIZER { .size = 0, .capacity = 0, .items = NULL }
MAP_IMPL(linenr_T, bufhl_vec_T, KVEC_INITIALIZER)
diff --git a/src/nvim/map.h b/src/nvim/map.h
index c7d9894bd1..ba3e84cb31 100644
--- a/src/nvim/map.h
+++ b/src/nvim/map.h
@@ -5,7 +5,7 @@
#include "nvim/map_defs.h"
#include "nvim/api/private/defs.h"
-#include "nvim/msgpack_rpc/defs.h"
+#include "nvim/api/private/dispatch.h"
#include "nvim/bufhl_defs.h"
#define MAP_DECLS(T, U) \
@@ -29,6 +29,7 @@ MAP_DECLS(cstr_t, uint64_t)
MAP_DECLS(cstr_t, ptr_t)
MAP_DECLS(ptr_t, ptr_t)
MAP_DECLS(uint64_t, ptr_t)
+MAP_DECLS(handle_T, ptr_t)
MAP_DECLS(String, MsgpackRpcRequestHandler)
MAP_DECLS(linenr_T, bufhl_vec_T)
diff --git a/src/nvim/mark.c b/src/nvim/mark.c
index fe802e48ba..2a65cf396b 100644
--- a/src/nvim/mark.c
+++ b/src/nvim/mark.c
@@ -21,7 +21,6 @@
#include "nvim/memline.h"
#include "nvim/memory.h"
#include "nvim/message.h"
-#include "nvim/misc2.h"
#include "nvim/normal.h"
#include "nvim/option.h"
#include "nvim/path.h"
diff --git a/src/nvim/mbyte.c b/src/nvim/mbyte.c
index 26d94aa6fa..f577fd847e 100644
--- a/src/nvim/mbyte.c
+++ b/src/nvim/mbyte.c
@@ -84,7 +84,6 @@
#include "nvim/memline.h"
#include "nvim/message.h"
#include "nvim/misc1.h"
-#include "nvim/misc2.h"
#include "nvim/memory.h"
#include "nvim/option.h"
#include "nvim/screen.h"
diff --git a/src/nvim/memfile.c b/src/nvim/memfile.c
index 9fb03c4ac7..43412e3916 100644
--- a/src/nvim/memfile.c
+++ b/src/nvim/memfile.c
@@ -48,7 +48,6 @@
#include "nvim/fileio.h"
#include "nvim/memline.h"
#include "nvim/message.h"
-#include "nvim/misc2.h"
#include "nvim/memory.h"
#include "nvim/os_unix.h"
#include "nvim/path.h"
diff --git a/src/nvim/memline.c b/src/nvim/memline.c
index 08e82071d7..5505335769 100644
--- a/src/nvim/memline.c
+++ b/src/nvim/memline.c
@@ -55,7 +55,6 @@
#include "nvim/memory.h"
#include "nvim/message.h"
#include "nvim/misc1.h"
-#include "nvim/misc2.h"
#include "nvim/option.h"
#include "nvim/os_unix.h"
#include "nvim/path.h"
@@ -3964,20 +3963,19 @@ long ml_find_line_or_offset(buf_T *buf, linenr_T lnum, long *offp)
return size;
}
-/*
- * Goto byte in buffer with offset 'cnt'.
- */
+/// Goto byte in buffer with offset 'cnt'.
void goto_byte(long cnt)
{
long boff = cnt;
linenr_T lnum;
- ml_flush_line(curbuf); /* cached line may be dirty */
+ ml_flush_line(curbuf); // cached line may be dirty
setpcmark();
- if (boff)
- --boff;
+ if (boff) {
+ boff--;
+ }
lnum = ml_find_line_or_offset(curbuf, (linenr_T)0, &boff);
- if (lnum < 1) { /* past the end */
+ if (lnum < 1) { // past the end
curwin->w_cursor.lnum = curbuf->b_ml.ml_line_count;
curwin->w_curswant = MAXCOL;
coladvance((colnr_T)MAXCOL);
@@ -3989,7 +3987,84 @@ void goto_byte(long cnt)
}
check_cursor();
- /* Make sure the cursor is on the first byte of a multi-byte char. */
- if (has_mbyte)
+ // Make sure the cursor is on the first byte of a multi-byte char.
+ if (has_mbyte) {
mb_adjust_cursor();
+ }
+}
+
+/// Increment the line pointer "lp" crossing line boundaries as necessary.
+/// Return 1 when going to the next line.
+/// Return 2 when moving forward onto a NUL at the end of the line).
+/// Return -1 when at the end of file.
+/// Return 0 otherwise.
+int inc(pos_T *lp)
+{
+ char_u *p = ml_get_pos(lp);
+
+ if (*p != NUL) { // still within line, move to next char (may be NUL)
+ if (has_mbyte) {
+ int l = (*mb_ptr2len)(p);
+
+ lp->col += l;
+ return (p[l] != NUL) ? 0 : 2;
+ }
+ lp->col++;
+ lp->coladd = 0;
+ return (p[1] != NUL) ? 0 : 2;
+ }
+ if (lp->lnum != curbuf->b_ml.ml_line_count) { // there is a next line
+ lp->col = 0;
+ lp->lnum++;
+ lp->coladd = 0;
+ return 1;
+ }
+ return -1;
+}
+
+/// Same as inc(), but skip NUL at the end of non-empty lines.
+int incl(pos_T *lp)
+{
+ int r;
+
+ if ((r = inc(lp)) >= 1 && lp->col) {
+ r = inc(lp);
+ }
+ return r;
+}
+
+int dec(pos_T *lp)
+{
+ char_u *p;
+
+ lp->coladd = 0;
+ if (lp->col > 0) { // still within line
+ lp->col--;
+ if (has_mbyte) {
+ p = ml_get(lp->lnum);
+ lp->col -= (*mb_head_off)(p, p + lp->col);
+ }
+ return 0;
+ }
+ if (lp->lnum > 1) { // there is a prior line
+ lp->lnum--;
+ p = ml_get(lp->lnum);
+ lp->col = (colnr_T)STRLEN(p);
+ if (has_mbyte) {
+ lp->col -= (*mb_head_off)(p, p + lp->col);
+ }
+ return 1;
+ }
+ return -1; // at start of file
+}
+
+/// Same as dec(), but skip NUL at the end of non-empty lines.
+int decl(pos_T *lp)
+{
+ int r;
+
+ if ((r = dec(lp)) == 1 && lp->col) {
+ r = dec(lp);
+ }
+ return r;
}
diff --git a/src/nvim/memory.c b/src/nvim/memory.c
index 8db47b79c1..3e041be4d3 100644
--- a/src/nvim/memory.c
+++ b/src/nvim/memory.c
@@ -440,6 +440,16 @@ void do_outofmem_msg(size_t size)
}
}
+/// Writes time_t to "buf[8]".
+void time_to_bytes(time_t time_, uint8_t buf[8])
+{
+ // time_t can be up to 8 bytes in size, more than uintmax_t in 32 bits
+ // systems, thus we can't use put_bytes() here.
+ for (size_t i = 7, bufi = 0; bufi < 8; i--, bufi++) {
+ buf[bufi] = (uint8_t)((uint64_t)time_ >> (i * 8));
+ }
+}
+
#if defined(EXITFREE)
#include "nvim/file_search.h"
diff --git a/src/nvim/memory.h b/src/nvim/memory.h
index 7b477da2f5..62cc78360c 100644
--- a/src/nvim/memory.h
+++ b/src/nvim/memory.h
@@ -3,6 +3,7 @@
#include <stdint.h> // for uint8_t
#include <stddef.h> // for size_t
+#include <time.h> // for time_t
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "memory.h.generated.h"
diff --git a/src/nvim/menu.c b/src/nvim/menu.c
index 3c2394d579..7c0eee64dd 100644
--- a/src/nvim/menu.c
+++ b/src/nvim/menu.c
@@ -18,9 +18,9 @@
#include "nvim/memory.h"
#include "nvim/message.h"
#include "nvim/misc1.h"
-#include "nvim/misc2.h"
#include "nvim/keymap.h"
#include "nvim/garray.h"
+#include "nvim/state.h"
#include "nvim/strings.h"
#include "nvim/ui.h"
diff --git a/src/nvim/message.c b/src/nvim/message.c
index 725c6b080a..1de2347b12 100644
--- a/src/nvim/message.c
+++ b/src/nvim/message.c
@@ -22,7 +22,6 @@
#include "nvim/mbyte.h"
#include "nvim/memory.h"
#include "nvim/misc1.h"
-#include "nvim/misc2.h"
#include "nvim/keymap.h"
#include "nvim/garray.h"
#include "nvim/ops.h"
diff --git a/src/nvim/misc1.c b/src/nvim/misc1.c
index d72d8e8513..4ab059c923 100644
--- a/src/nvim/misc1.c
+++ b/src/nvim/misc1.c
@@ -31,7 +31,6 @@
#include "nvim/memline.h"
#include "nvim/memory.h"
#include "nvim/message.h"
-#include "nvim/misc2.h"
#include "nvim/garray.h"
#include "nvim/move.h"
#include "nvim/mouse.h"
@@ -41,6 +40,7 @@
#include "nvim/regexp.h"
#include "nvim/screen.h"
#include "nvim/search.h"
+#include "nvim/state.h"
#include "nvim/strings.h"
#include "nvim/tag.h"
#include "nvim/ui.h"
@@ -742,10 +742,14 @@ open_line (
if (ml_append(curwin->w_cursor.lnum, p_extra, (colnr_T)0, FALSE)
== FAIL)
goto theend;
- /* Postpone calling changed_lines(), because it would mess up folding
- * with markers. */
- mark_adjust(curwin->w_cursor.lnum + 1, (linenr_T)MAXLNUM, 1L, 0L);
- did_append = TRUE;
+ // Postpone calling changed_lines(), because it would mess up folding
+ // with markers.
+ // Skip mark_adjust when adding a line after the last one, there can't
+ // be marks there.
+ if (curwin->w_cursor.lnum + 1 < curbuf->b_ml.ml_line_count) {
+ mark_adjust(curwin->w_cursor.lnum + 1, (linenr_T)MAXLNUM, 1L, 0L);
+ }
+ did_append = true;
} else {
/*
* In VREPLACE mode we are starting to replace the next line.
@@ -1742,18 +1746,6 @@ int gchar_pos(pos_T *pos)
}
/*
- * Skip to next part of an option argument: Skip space and comma.
- */
-char_u *skip_to_option_part(char_u *p)
-{
- if (*p == ',')
- ++p;
- while (*p == ' ')
- ++p;
- return p;
-}
-
-/*
* Call this function when something in the current buffer is changed.
*
* Most often called through changed_bytes() and changed_lines(), which also
@@ -1871,7 +1863,11 @@ void appended_lines(linenr_T lnum, long count)
*/
void appended_lines_mark(linenr_T lnum, long count)
{
- mark_adjust(lnum + 1, (linenr_T)MAXLNUM, count, 0L);
+ // Skip mark_adjust when adding a line after the last one, there can't
+ // be marks there.
+ if (lnum + count < curbuf->b_ml.ml_line_count) {
+ mark_adjust(lnum + 1, (linenr_T)MAXLNUM, count, 0L);
+ }
changed_lines(lnum + 1, 0, lnum + 1, count);
}
@@ -2683,6 +2679,42 @@ void fast_breakcheck(void)
}
}
+// Call shell. Calls os_call_shell, with 'shellxquote' added.
+int call_shell(char_u *cmd, ShellOpts opts, char_u *extra_shell_arg)
+{
+ int retval;
+ proftime_T wait_time;
+
+ if (p_verbose > 3) {
+ verbose_enter();
+ smsg(_("Calling shell to execute: \"%s\""),
+ cmd == NULL ? p_sh : cmd);
+ ui_putc('\n');
+ verbose_leave();
+ }
+
+ if (do_profiling == PROF_YES) {
+ prof_child_enter(&wait_time);
+ }
+
+ if (*p_sh == NUL) {
+ EMSG(_(e_shellempty));
+ retval = -1;
+ } else {
+ // The external command may update a tags file, clear cached tags.
+ tag_freematch();
+
+ retval = os_call_shell(cmd, opts, extra_shell_arg);
+ }
+
+ set_vim_var_nr(VV_SHELL_ERROR, (varnumber_T)retval);
+ if (do_profiling == PROF_YES) {
+ prof_child_exit(&wait_time);
+ }
+
+ return retval;
+}
+
/// Get the stdout of an external command.
/// If "ret_len" is NULL replace NUL characters with NL. When "ret_len" is not
/// NULL store the length there.
diff --git a/src/nvim/misc2.c b/src/nvim/misc2.c
deleted file mode 100644
index 368f83cfb5..0000000000
--- a/src/nvim/misc2.c
+++ /dev/null
@@ -1,486 +0,0 @@
-/*
- * misc2.c: Various functions.
- */
-#include <assert.h>
-#include <inttypes.h>
-#include <string.h>
-
-#include "nvim/vim.h"
-#include "nvim/ascii.h"
-#include "nvim/misc2.h"
-#include "nvim/file_search.h"
-#include "nvim/buffer.h"
-#include "nvim/charset.h"
-#include "nvim/cursor.h"
-#include "nvim/diff.h"
-#include "nvim/edit.h"
-#include "nvim/eval.h"
-#include "nvim/ex_cmds.h"
-#include "nvim/ex_docmd.h"
-#include "nvim/ex_getln.h"
-#include "nvim/fileio.h"
-#include "nvim/fold.h"
-#include "nvim/getchar.h"
-#include "nvim/macros.h"
-#include "nvim/mark.h"
-#include "nvim/mbyte.h"
-#include "nvim/memfile.h"
-#include "nvim/memline.h"
-#include "nvim/memory.h"
-#include "nvim/message.h"
-#include "nvim/misc1.h"
-#include "nvim/move.h"
-#include "nvim/option.h"
-#include "nvim/ops.h"
-#include "nvim/os_unix.h"
-#include "nvim/path.h"
-#include "nvim/quickfix.h"
-#include "nvim/regexp.h"
-#include "nvim/screen.h"
-#include "nvim/search.h"
-#include "nvim/spell.h"
-#include "nvim/strings.h"
-#include "nvim/syntax.h"
-#include "nvim/tag.h"
-#include "nvim/ui.h"
-#include "nvim/window.h"
-#include "nvim/os/os.h"
-#include "nvim/os/shell.h"
-
-
-#ifdef INCLUDE_GENERATED_DECLARATIONS
-# include "misc2.c.generated.h"
-#endif
-/*
- * Return TRUE if in the current mode we need to use virtual.
- */
-int virtual_active(void)
-{
- /* While an operator is being executed we return "virtual_op", because
- * VIsual_active has already been reset, thus we can't check for "block"
- * being used. */
- if (virtual_op != MAYBE)
- return virtual_op;
- return ve_flags == VE_ALL
- || ((ve_flags & VE_BLOCK) && VIsual_active && VIsual_mode == Ctrl_V)
- || ((ve_flags & VE_INSERT) && (State & INSERT));
-}
-
-/*
- * Increment the line pointer "lp" crossing line boundaries as necessary.
- * Return 1 when going to the next line.
- * Return 2 when moving forward onto a NUL at the end of the line).
- * Return -1 when at the end of file.
- * Return 0 otherwise.
- */
-int inc(pos_T *lp)
-{
- char_u *p = ml_get_pos(lp);
-
- if (*p != NUL) { /* still within line, move to next char (may be NUL) */
- if (has_mbyte) {
- int l = (*mb_ptr2len)(p);
-
- lp->col += l;
- return (p[l] != NUL) ? 0 : 2;
- }
- lp->col++;
- lp->coladd = 0;
- return (p[1] != NUL) ? 0 : 2;
- }
- if (lp->lnum != curbuf->b_ml.ml_line_count) { /* there is a next line */
- lp->col = 0;
- lp->lnum++;
- lp->coladd = 0;
- return 1;
- }
- return -1;
-}
-
-/*
- * incl(lp): same as inc(), but skip the NUL at the end of non-empty lines
- */
-int incl(pos_T *lp)
-{
- int r;
-
- if ((r = inc(lp)) >= 1 && lp->col)
- r = inc(lp);
- return r;
-}
-
-int dec(pos_T *lp)
-{
- char_u *p;
-
- lp->coladd = 0;
- if (lp->col > 0) { /* still within line */
- lp->col--;
- if (has_mbyte) {
- p = ml_get(lp->lnum);
- lp->col -= (*mb_head_off)(p, p + lp->col);
- }
- return 0;
- }
- if (lp->lnum > 1) { /* there is a prior line */
- lp->lnum--;
- p = ml_get(lp->lnum);
- lp->col = (colnr_T)STRLEN(p);
- if (has_mbyte)
- lp->col -= (*mb_head_off)(p, p + lp->col);
- return 1;
- }
- return -1; /* at start of file */
-}
-
-/*
- * decl(lp): same as dec(), but skip the NUL at the end of non-empty lines
- */
-int decl(pos_T *lp)
-{
- int r;
-
- if ((r = dec(lp)) == 1 && lp->col)
- r = dec(lp);
- return r;
-}
-
-/*
- * Return TRUE when 'shell' has "csh" in the tail.
- */
-int csh_like_shell(void)
-{
- return strstr((char *)path_tail(p_sh), "csh") != NULL;
-}
-
-/*
- * Isolate one part of a string option where parts are separated with
- * "sep_chars".
- * The part is copied into "buf[maxlen]".
- * "*option" is advanced to the next part.
- * The length is returned.
- */
-size_t copy_option_part(char_u **option, char_u *buf, size_t maxlen, char *sep_chars)
-{
- size_t len = 0;
- char_u *p = *option;
-
- /* skip '.' at start of option part, for 'suffixes' */
- if (*p == '.')
- buf[len++] = *p++;
- while (*p != NUL && vim_strchr((char_u *)sep_chars, *p) == NULL) {
- /*
- * Skip backslash before a separator character and space.
- */
- if (p[0] == '\\' && vim_strchr((char_u *)sep_chars, p[1]) != NULL)
- ++p;
- if (len < maxlen - 1)
- buf[len++] = *p;
- ++p;
- }
- buf[len] = NUL;
-
- if (*p != NUL && *p != ',') /* skip non-standard separator */
- ++p;
- p = skip_to_option_part(p); /* p points to next file name */
-
- *option = p;
- return len;
-}
-
-/*
- * Return the current end-of-line type: EOL_DOS, EOL_UNIX or EOL_MAC.
- */
-int get_fileformat(buf_T *buf)
-{
- int c = *buf->b_p_ff;
-
- if (buf->b_p_bin || c == 'u')
- return EOL_UNIX;
- if (c == 'm')
- return EOL_MAC;
- return EOL_DOS;
-}
-
-/*
- * Like get_fileformat(), but override 'fileformat' with "p" for "++opt=val"
- * argument.
- */
-int
-get_fileformat_force (
- buf_T *buf,
- exarg_T *eap /* can be NULL! */
-)
-{
- int c;
-
- if (eap != NULL && eap->force_ff != 0)
- c = eap->cmd[eap->force_ff];
- else {
- if ((eap != NULL && eap->force_bin != 0)
- ? (eap->force_bin == FORCE_BIN) : buf->b_p_bin)
- return EOL_UNIX;
- c = *buf->b_p_ff;
- }
- if (c == 'u')
- return EOL_UNIX;
- if (c == 'm')
- return EOL_MAC;
- return EOL_DOS;
-}
-
-/// Set the current end-of-line type to EOL_UNIX, EOL_MAC, or EOL_DOS.
-///
-/// Sets 'fileformat'.
-///
-/// @param eol_style End-of-line style.
-/// @param opt_flags OPT_LOCAL and/or OPT_GLOBAL
-void set_fileformat(int eol_style, int opt_flags)
-{
- char *p = NULL;
-
- switch (eol_style) {
- case EOL_UNIX:
- p = FF_UNIX;
- break;
- case EOL_MAC:
- p = FF_MAC;
- break;
- case EOL_DOS:
- p = FF_DOS;
- break;
- }
-
- // p is NULL if "eol_style" is EOL_UNKNOWN.
- if (p != NULL) {
- set_string_option_direct((char_u *)"ff",
- -1,
- (char_u *)p,
- OPT_FREE | opt_flags,
- 0);
- }
-
- // This may cause the buffer to become (un)modified.
- check_status(curbuf);
- redraw_tabline = TRUE;
- need_maketitle = TRUE; // Set window title later.
-}
-
-/*
- * Return the default fileformat from 'fileformats'.
- */
-int default_fileformat(void)
-{
- switch (*p_ffs) {
- case 'm': return EOL_MAC;
- case 'd': return EOL_DOS;
- }
- return EOL_UNIX;
-}
-
-// Call shell. Calls os_call_shell, with 'shellxquote' added.
-int call_shell(char_u *cmd, ShellOpts opts, char_u *extra_shell_arg)
-{
- char_u *ncmd;
- int retval;
- proftime_T wait_time;
-
- if (p_verbose > 3) {
- verbose_enter();
- smsg(_("Calling shell to execute: \"%s\""),
- cmd == NULL ? p_sh : cmd);
- ui_putc('\n');
- verbose_leave();
- }
-
- if (do_profiling == PROF_YES)
- prof_child_enter(&wait_time);
-
- if (*p_sh == NUL) {
- EMSG(_(e_shellempty));
- retval = -1;
- } else {
- /* The external command may update a tags file, clear cached tags. */
- tag_freematch();
-
- if (cmd == NULL || *p_sxq == NUL)
- retval = os_call_shell(cmd, opts, extra_shell_arg);
- else {
- char_u *ecmd = cmd;
-
- if (*p_sxe != NUL && STRCMP(p_sxq, "(") == 0) {
- ecmd = vim_strsave_escaped_ext(cmd, p_sxe, '^', FALSE);
- }
- ncmd = xmalloc(STRLEN(ecmd) + STRLEN(p_sxq) * 2 + 1);
- STRCPY(ncmd, p_sxq);
- STRCAT(ncmd, ecmd);
- /* When 'shellxquote' is ( append ).
- * When 'shellxquote' is "( append )". */
- STRCAT(ncmd, STRCMP(p_sxq, "(") == 0 ? (char_u *)")"
- : STRCMP(p_sxq, "\"(") == 0 ? (char_u *)")\""
- : p_sxq);
- retval = os_call_shell(ncmd, opts, extra_shell_arg);
- xfree(ncmd);
-
- if (ecmd != cmd)
- xfree(ecmd);
- }
- }
-
- set_vim_var_nr(VV_SHELL_ERROR, (varnumber_T) retval);
- if (do_profiling == PROF_YES) {
- prof_child_exit(&wait_time);
- }
-
- return retval;
-}
-
-/*
- * VISUAL, SELECTMODE and OP_PENDING State are never set, they are equal to
- * NORMAL State with a condition. This function returns the real State.
- */
-int get_real_state(void)
-{
- if (State & NORMAL) {
- if (VIsual_active) {
- if (VIsual_select)
- return SELECTMODE;
- return VISUAL;
- } else if (finish_op)
- return OP_PENDING;
- }
- return State;
-}
-
-/*
- * Change to a file's directory.
- * Caller must call shorten_fnames()!
- * Return OK or FAIL.
- */
-int vim_chdirfile(char_u *fname)
-{
- char_u dir[MAXPATHL];
-
- STRLCPY(dir, fname, MAXPATHL);
- *path_tail_with_sep(dir) = NUL;
- return os_chdir((char *)dir) == 0 ? OK : FAIL;
-}
-
-/*
- * Change directory to "new_dir". Search 'cdpath' for relative directory names.
- */
-int vim_chdir(char_u *new_dir)
-{
- char_u *dir_name;
- int r;
-
- dir_name = find_directory_in_path(new_dir, STRLEN(new_dir),
- FNAME_MESS, curbuf->b_ffname);
- if (dir_name == NULL)
- return -1;
- r = os_chdir((char *)dir_name);
- xfree(dir_name);
- return r;
-}
-
-/*
- * Read 2 bytes from "fd" and turn them into an int, MSB first.
- */
-int get2c(FILE *fd)
-{
- int n;
-
- n = getc(fd);
- n = (n << 8) + getc(fd);
- return n;
-}
-
-/*
- * Read 3 bytes from "fd" and turn them into an int, MSB first.
- */
-int get3c(FILE *fd)
-{
- int n;
-
- n = getc(fd);
- n = (n << 8) + getc(fd);
- n = (n << 8) + getc(fd);
- return n;
-}
-
-/*
- * Read 4 bytes from "fd" and turn them into an int, MSB first.
- */
-int get4c(FILE *fd)
-{
- /* Use unsigned rather than int otherwise result is undefined
- * when left-shift sets the MSB. */
- unsigned n;
-
- n = (unsigned)getc(fd);
- n = (n << 8) + (unsigned)getc(fd);
- n = (n << 8) + (unsigned)getc(fd);
- n = (n << 8) + (unsigned)getc(fd);
- return (int)n;
-}
-
-/*
- * Read 8 bytes from "fd" and turn them into a time_t, MSB first.
- */
-time_t get8ctime(FILE *fd)
-{
- time_t n = 0;
- int i;
-
- for (i = 0; i < 8; ++i)
- n = (n << 8) + getc(fd);
- return n;
-}
-
-/// Reads a string of length "cnt" from "fd" into allocated memory.
-/// @return pointer to the string or NULL when unable to read that many bytes.
-char *read_string(FILE *fd, size_t cnt)
-{
- uint8_t *str = xmallocz(cnt);
- for (size_t i = 0; i < cnt; i++) {
- int c = getc(fd);
- if (c == EOF) {
- xfree(str);
- return NULL;
- }
- str[i] = (uint8_t)c;
- }
- return (char *)str;
-}
-
-/// Writes a number to file "fd", most significant bit first, in "len" bytes.
-/// @returns false in case of an error.
-bool put_bytes(FILE *fd, uintmax_t number, size_t len)
-{
- assert(len > 0);
- for (size_t i = len - 1; i < len; i--) {
- if (putc((int)(number >> (i * 8)), fd) == EOF) {
- return false;
- }
- }
- return true;
-}
-
-/// Writes time_t to file "fd" in 8 bytes.
-/// @returns FAIL when the write failed.
-int put_time(FILE *fd, time_t time_)
-{
- uint8_t buf[8];
- time_to_bytes(time_, buf);
- return fwrite(buf, sizeof(uint8_t), ARRAY_SIZE(buf), fd) == 1 ? OK : FAIL;
-}
-
-/// Writes time_t to "buf[8]".
-void time_to_bytes(time_t time_, uint8_t buf[8])
-{
- // time_t can be up to 8 bytes in size, more than uintmax_t in 32 bits
- // systems, thus we can't use put_bytes() here.
- for (size_t i = 7, bufi = 0; bufi < 8; i--, bufi++) {
- buf[bufi] = (uint8_t)((uint64_t)time_ >> (i * 8));
- }
-}
diff --git a/src/nvim/misc2.h b/src/nvim/misc2.h
deleted file mode 100644
index 28b5b775d2..0000000000
--- a/src/nvim/misc2.h
+++ /dev/null
@@ -1,12 +0,0 @@
-#ifndef NVIM_MISC2_H
-#define NVIM_MISC2_H
-
-#include "nvim/os/shell.h"
-
-#define READ_STRING(x, y) (char_u *)read_string((x), (size_t)(y))
-
-#ifdef INCLUDE_GENERATED_DECLARATIONS
-# include "misc2.h.generated.h"
-#endif
-
-#endif // NVIM_MISC2_H
diff --git a/src/nvim/mouse.c b/src/nvim/mouse.c
index 5efac2623c..2ebe199f47 100644
--- a/src/nvim/mouse.c
+++ b/src/nvim/mouse.c
@@ -4,6 +4,7 @@
#include "nvim/vim.h"
#include "nvim/ascii.h"
#include "nvim/window.h"
+#include "nvim/state.h"
#include "nvim/strings.h"
#include "nvim/screen.h"
#include "nvim/syntax.h"
diff --git a/src/nvim/move.c b/src/nvim/move.c
index b129c5cb7a..4c814f3ae0 100644
--- a/src/nvim/move.c
+++ b/src/nvim/move.c
@@ -24,7 +24,6 @@
#include "nvim/mbyte.h"
#include "nvim/memline.h"
#include "nvim/misc1.h"
-#include "nvim/misc2.h"
#include "nvim/popupmnu.h"
#include "nvim/screen.h"
#include "nvim/strings.h"
diff --git a/src/nvim/msgpack_rpc/channel.c b/src/nvim/msgpack_rpc/channel.c
index 8b5f212d66..cd12f258b6 100644
--- a/src/nvim/msgpack_rpc/channel.c
+++ b/src/nvim/msgpack_rpc/channel.c
@@ -465,8 +465,7 @@ static void on_request_event(void **argv)
} else {
api_free_object(result);
}
- // All arguments were freed already, but we still need to free the array
- xfree(args.items);
+ api_free_array(args);
decref(channel);
xfree(e);
}
diff --git a/src/nvim/msgpack_rpc/defs.h b/src/nvim/msgpack_rpc/defs.h
deleted file mode 100644
index 5611636d4f..0000000000
--- a/src/nvim/msgpack_rpc/defs.h
+++ /dev/null
@@ -1,28 +0,0 @@
-#ifndef NVIM_MSGPACK_RPC_DEFS_H
-#define NVIM_MSGPACK_RPC_DEFS_H
-
-
-/// The rpc_method_handlers table, used in msgpack_rpc_dispatch(), stores
-/// functions of this type.
-typedef struct {
- Object (*fn)(uint64_t channel_id,
- uint64_t request_id,
- Array args,
- Error *error);
- bool async; // function is always safe to run immediately instead of being
- // put in a request queue for handling when nvim waits for input.
-} MsgpackRpcRequestHandler;
-
-/// Initializes the msgpack-rpc method table
-void msgpack_rpc_init_method_table(void);
-
-// Add a handler to the method table
-void msgpack_rpc_add_method_handler(String method,
- MsgpackRpcRequestHandler handler);
-
-void msgpack_rpc_init_function_metadata(Dictionary *metadata);
-
-MsgpackRpcRequestHandler msgpack_rpc_get_handler_for(const char *name,
- size_t name_len)
- FUNC_ATTR_NONNULL_ARG(1);
-#endif // NVIM_MSGPACK_RPC_DEFS_H
diff --git a/src/nvim/msgpack_rpc/helpers.c b/src/nvim/msgpack_rpc/helpers.c
index 9195b10614..33e9bb1c07 100644
--- a/src/nvim/msgpack_rpc/helpers.c
+++ b/src/nvim/msgpack_rpc/helpers.c
@@ -4,9 +4,9 @@
#include <msgpack.h>
+#include "nvim/api/private/dispatch.h"
#include "nvim/api/private/helpers.h"
#include "nvim/msgpack_rpc/helpers.h"
-#include "nvim/msgpack_rpc/defs.h"
#include "nvim/lib/kvec.h"
#include "nvim/vim.h"
#include "nvim/log.h"
@@ -40,7 +40,7 @@ static msgpack_sbuffer sbuffer;
return false; \
} \
\
- *arg = data.via.u64; \
+ *arg = (handle_T)data.via.i64; \
return true; \
} \
\
@@ -49,7 +49,7 @@ static msgpack_sbuffer sbuffer;
{ \
msgpack_packer pac; \
msgpack_packer_init(&pac, &sbuffer, msgpack_sbuffer_write); \
- msgpack_pack_uint64(&pac, o); \
+ msgpack_pack_int64(&pac, o); \
msgpack_pack_ext(res, sbuffer.size, kObjectType##t); \
msgpack_pack_ext_body(res, sbuffer.data, sbuffer.size); \
msgpack_sbuffer_clear(&sbuffer); \
diff --git a/src/nvim/normal.c b/src/nvim/normal.c
index c95e5e1a15..d0a9d3aca7 100644
--- a/src/nvim/normal.c
+++ b/src/nvim/normal.c
@@ -36,7 +36,6 @@
#include "nvim/memory.h"
#include "nvim/message.h"
#include "nvim/misc1.h"
-#include "nvim/misc2.h"
#include "nvim/keymap.h"
#include "nvim/move.h"
#include "nvim/mouse.h"
@@ -2110,6 +2109,20 @@ static void op_function(oparg_T *oap)
}
}
+// Move the current tab to tab in same column as mouse or to end of the
+// tabline if there is no tab there.
+static void move_tab_to_mouse(void)
+{
+ int tabnr = tab_page_click_defs[mouse_col].tabnr;
+ if (tabnr <= 0) {
+ tabpage_move(9999);
+ } else if (tabnr < tabpage_index(curtab)) {
+ tabpage_move(tabnr - 1);
+ } else {
+ tabpage_move(tabnr);
+ }
+}
+
/*
* Do the appropriate action for the current mouse click in the current mode.
* Not used for Command-line mode.
@@ -2346,12 +2359,7 @@ do_mouse (
if (mouse_row == 0 && firstwin->w_winrow > 0) {
if (is_drag) {
if (in_tab_line) {
- if (tab_page_click_defs[mouse_col].type == kStlClickTabClose) {
- tabpage_move(9999);
- } else {
- int tabnr = tab_page_click_defs[mouse_col].tabnr;
- tabpage_move(tabnr < tabpage_index(curtab) ? tabnr - 1 : tabnr);
- }
+ move_tab_to_mouse();
}
return false;
}
@@ -2466,10 +2474,7 @@ do_mouse (
}
return true;
} else if (is_drag && in_tab_line) {
- tabpage_move(tab_page_click_defs[mouse_col].type == kStlClickTabClose
- ? 9999
- : tab_page_click_defs[mouse_col].tabnr - 1);
- in_tab_line = false;
+ move_tab_to_mouse();
return false;
}
@@ -5919,6 +5924,9 @@ static void nv_replace(cmdarg_T *cap)
curwin->w_set_curswant = true;
set_last_insert(cap->nchar);
}
+
+ foldUpdateAll(curwin);
+ foldOpenCursor();
}
/*
diff --git a/src/nvim/ops.c b/src/nvim/ops.c
index e8a79fa820..388a72adce 100644
--- a/src/nvim/ops.c
+++ b/src/nvim/ops.c
@@ -30,13 +30,13 @@
#include "nvim/memory.h"
#include "nvim/message.h"
#include "nvim/misc1.h"
-#include "nvim/misc2.h"
#include "nvim/move.h"
#include "nvim/normal.h"
#include "nvim/option.h"
#include "nvim/path.h"
#include "nvim/screen.h"
#include "nvim/search.h"
+#include "nvim/state.h"
#include "nvim/strings.h"
#include "nvim/terminal.h"
#include "nvim/ui.h"
@@ -51,10 +51,10 @@ static yankreg_T *y_previous = NULL; /* ptr to last written yankreg */
static bool clipboard_didwarn_unnamed = false;
-// for behavior between start_global_changes() and end_global_changes())
+// for behavior between start_batch_changes() and end_batch_changes())
static bool clipboard_delay_update = false; // delay clipboard update
-static int global_change_count = 0; // if set, inside global changes
-static bool clipboard_needs_update = false; // the clipboard was updated
+static int batch_change_count = 0; // inside a script
+static bool clipboard_needs_update = false; // clipboard was updated
/*
* structure used by block_prep, op_delete and op_yank for blockwise operators
@@ -3110,8 +3110,13 @@ error:
if (dir == FORWARD)
curbuf->b_op_start.lnum++;
}
- mark_adjust(curbuf->b_op_start.lnum + (y_type == kMTCharWise),
- (linenr_T)MAXLNUM, nr_lines, 0L);
+ // Skip mark_adjust when adding lines after the last one, there
+ // can't be marks there.
+ if (curbuf->b_op_start.lnum + (y_type == kMTCharWise) - 1 + nr_lines
+ < curbuf->b_ml.ml_line_count) {
+ mark_adjust(curbuf->b_op_start.lnum + (y_type == kMTCharWise),
+ (linenr_T)MAXLNUM, nr_lines, 0L);
+ }
// note changed text for displaying and folding
if (y_type == kMTCharWise) {
@@ -5630,20 +5635,20 @@ static void set_clipboard(int name, yankreg_T *reg)
(void)eval_call_provider("clipboard", "set", args);
}
-/// Avoid clipboard (slow) during batch operations (:global).
-void start_global_changes(void)
+/// Avoid clipboard (slow) during batch operations (i.e., a script).
+void start_batch_changes(void)
{
- if (++global_change_count > 1) {
+ if (++batch_change_count > 1) {
return;
}
clipboard_delay_update = true;
clipboard_needs_update = false;
}
-/// Update the clipboard after :global changes finished.
-void end_global_changes(void)
+/// Update the clipboard after batch changes finished.
+void end_batch_changes(void)
{
- if (--global_change_count > 0) {
+ if (--batch_change_count > 0) {
// recursive
return;
}
diff --git a/src/nvim/option.c b/src/nvim/option.c
index e53dbfc75a..d8908cca90 100644
--- a/src/nvim/option.c
+++ b/src/nvim/option.c
@@ -6585,10 +6585,8 @@ int get_sw_value(buf_T *buf)
return (int)result;
}
-/*
- * Return the effective softtabstop value for the current buffer, using the
- * 'tabstop' value when 'softtabstop' is negative.
- */
+// Return the effective softtabstop value for the current buffer,
+// using the effective shiftwidth value when 'softtabstop' is negative.
int get_sts_value(void)
{
long result = curbuf->b_p_sts < 0 ? get_sw_value(curbuf) : curbuf->b_p_sts;
@@ -6714,3 +6712,148 @@ unsigned int get_bkc_value(buf_T *buf)
{
return buf->b_bkc_flags ? buf->b_bkc_flags : bkc_flags;
}
+
+/// Return the current end-of-line type: EOL_DOS, EOL_UNIX or EOL_MAC.
+int get_fileformat(buf_T *buf)
+{
+ int c = *buf->b_p_ff;
+
+ if (buf->b_p_bin || c == 'u') {
+ return EOL_UNIX;
+ }
+ if (c == 'm') {
+ return EOL_MAC;
+ }
+ return EOL_DOS;
+}
+
+/// Like get_fileformat(), but override 'fileformat' with "p" for "++opt=val"
+/// argument.
+///
+/// @param eap can be NULL!
+int get_fileformat_force(buf_T *buf, exarg_T *eap)
+{
+ int c;
+
+ if (eap != NULL && eap->force_ff != 0) {
+ c = eap->cmd[eap->force_ff];
+ } else {
+ if ((eap != NULL && eap->force_bin != 0)
+ ? (eap->force_bin == FORCE_BIN) : buf->b_p_bin) {
+ return EOL_UNIX;
+ }
+ c = *buf->b_p_ff;
+ }
+ if (c == 'u') {
+ return EOL_UNIX;
+ }
+ if (c == 'm') {
+ return EOL_MAC;
+ }
+ return EOL_DOS;
+}
+
+/// Return the default fileformat from 'fileformats'.
+int default_fileformat(void)
+{
+ switch (*p_ffs) {
+ case 'm': return EOL_MAC;
+ case 'd': return EOL_DOS;
+ }
+ return EOL_UNIX;
+}
+
+/// Set the current end-of-line type to EOL_UNIX, EOL_MAC, or EOL_DOS.
+///
+/// Sets 'fileformat'.
+///
+/// @param eol_style End-of-line style.
+/// @param opt_flags OPT_LOCAL and/or OPT_GLOBAL
+void set_fileformat(int eol_style, int opt_flags)
+{
+ char *p = NULL;
+
+ switch (eol_style) {
+ case EOL_UNIX:
+ p = FF_UNIX;
+ break;
+ case EOL_MAC:
+ p = FF_MAC;
+ break;
+ case EOL_DOS:
+ p = FF_DOS;
+ break;
+ }
+
+ // p is NULL if "eol_style" is EOL_UNKNOWN.
+ if (p != NULL) {
+ set_string_option_direct((char_u *)"ff",
+ -1,
+ (char_u *)p,
+ OPT_FREE | opt_flags,
+ 0);
+ }
+
+ // This may cause the buffer to become (un)modified.
+ check_status(curbuf);
+ redraw_tabline = true;
+ need_maketitle = true; // Set window title later.
+}
+
+/// Skip to next part of an option argument: Skip space and comma.
+char_u *skip_to_option_part(char_u *p)
+{
+ if (*p == ',') {
+ p++;
+ }
+ while (*p == ' ') {
+ p++;
+ }
+ return p;
+}
+
+/// Isolate one part of a string option separated by `sep_chars`.
+///
+/// @param[in,out] option advanced to the next part
+/// @param[in,out] buf copy of the isolated part
+/// @param[in] maxlen length of `buf`
+/// @param[in] sep_chars chars that separate the option parts
+///
+/// @return length of `*option`
+size_t copy_option_part(char_u **option, char_u *buf, size_t maxlen,
+ char *sep_chars)
+{
+ size_t len = 0;
+ char_u *p = *option;
+
+ // skip '.' at start of option part, for 'suffixes'
+ if (*p == '.') {
+ buf[len++] = *p++;
+ }
+ while (*p != NUL && vim_strchr((char_u *)sep_chars, *p) == NULL) {
+ // Skip backslash before a separator character and space.
+ if (p[0] == '\\' && vim_strchr((char_u *)sep_chars, p[1]) != NULL) {
+ p++;
+ }
+ if (len < maxlen - 1) {
+ buf[len++] = *p;
+ }
+ p++;
+ }
+ buf[len] = NUL;
+
+ if (*p != NUL && *p != ',') { // skip non-standard separator
+ p++;
+ }
+ p = skip_to_option_part(p); // p points to next file name
+
+ *option = p;
+ return len;
+}
+
+/// Return TRUE when 'shell' has "csh" in the tail.
+int csh_like_shell(void)
+{
+ return strstr((char *)path_tail(p_sh), "csh") != NULL;
+}
+
diff --git a/src/nvim/option.h b/src/nvim/option.h
index 3a43b859a8..cf167cdd2c 100644
--- a/src/nvim/option.h
+++ b/src/nvim/option.h
@@ -1,6 +1,8 @@
#ifndef NVIM_OPTION_H
#define NVIM_OPTION_H
+#include "nvim/ex_cmds_defs.h" // for exarg_T
+
/* flags for buf_copy_options() */
#define BCO_ENTER 1 /* going to enter the buffer */
#define BCO_ALWAYS 2 /* always copy the options */
diff --git a/src/nvim/os/env.c b/src/nvim/os/env.c
index edc430410c..83a0262545 100644
--- a/src/nvim/os/env.c
+++ b/src/nvim/os/env.c
@@ -12,7 +12,6 @@
#include "nvim/os/os.h"
#include "nvim/memory.h"
#include "nvim/message.h"
-#include "nvim/misc2.h"
#include "nvim/path.h"
#include "nvim/strings.h"
#include "nvim/eval.h"
diff --git a/src/nvim/os/fs.c b/src/nvim/os/fs.c
index e63b8b6793..008952fa97 100644
--- a/src/nvim/os/fs.c
+++ b/src/nvim/os/fs.c
@@ -21,7 +21,6 @@
#include "nvim/message.h"
#include "nvim/assert.h"
#include "nvim/misc1.h"
-#include "nvim/misc2.h"
#include "nvim/path.h"
#include "nvim/strings.h"
diff --git a/src/nvim/os/input.c b/src/nvim/os/input.c
index c0c73364c0..6873e32f34 100644
--- a/src/nvim/os/input.c
+++ b/src/nvim/os/input.c
@@ -19,7 +19,7 @@
#include "nvim/getchar.h"
#include "nvim/main.h"
#include "nvim/misc1.h"
-#include "nvim/misc2.h"
+#include "nvim/state.h"
#define READ_BUFFER_SIZE 0xfff
#define INPUT_BUFFER_SIZE (READ_BUFFER_SIZE * 4)
diff --git a/src/nvim/os/shell.c b/src/nvim/os/shell.c
index ba52b9f661..661b12accc 100644
--- a/src/nvim/os/shell.c
+++ b/src/nvim/os/shell.c
@@ -19,7 +19,6 @@
#include "nvim/message.h"
#include "nvim/memory.h"
#include "nvim/ui.h"
-#include "nvim/misc2.h"
#include "nvim/screen.h"
#include "nvim/memline.h"
#include "nvim/option_defs.h"
@@ -54,12 +53,12 @@ char **shell_build_argv(const char *cmd, const char *extra_args)
size_t i = tokenize(p_sh, rv);
if (extra_args) {
- rv[i++] = xstrdup(extra_args); // Push a copy of `extra_args`
+ rv[i++] = xstrdup(extra_args); // Push a copy of `extra_args`
}
if (cmd) {
- i += tokenize(p_shcf, rv + i); // Split 'shellcmdflag'
- rv[i++] = xstrdup(cmd); // Push a copy of the command.
+ i += tokenize(p_shcf, rv + i); // Split 'shellcmdflag'
+ rv[i++] = shell_xescape_xquote(cmd); // Copy (and escape) `cmd`.
}
rv[i] = NULL;
@@ -548,3 +547,39 @@ static void shell_write_cb(Stream *stream, void *data, int status)
{
stream_close(stream, NULL, NULL);
}
+
+/// Applies 'shellxescape' (p_sxe) and 'shellxquote' (p_sxq) to a command.
+///
+/// @param cmd Command string
+/// @return Escaped/quoted command string (allocated).
+static char *shell_xescape_xquote(const char *cmd)
+ FUNC_ATTR_NONNULL_ALL FUNC_ATTR_MALLOC FUNC_ATTR_WARN_UNUSED_RESULT
+{
+ if (*p_sxq == NUL) {
+ return xstrdup(cmd);
+ }
+
+ const char *ecmd = cmd;
+ if (*p_sxe != NUL && STRCMP(p_sxq, "(") == 0) {
+ ecmd = (char *)vim_strsave_escaped_ext((char_u *)cmd, p_sxe, '^', false);
+ }
+ size_t ncmd_size = strlen(ecmd) + STRLEN(p_sxq) * 2 + 1;
+ char *ncmd = xmalloc(ncmd_size);
+
+ // When 'shellxquote' is ( append ).
+ // When 'shellxquote' is "( append )".
+ if (STRCMP(p_sxq, "(") == 0) {
+ vim_snprintf(ncmd, ncmd_size, "(%s)", ecmd);
+ } else if (STRCMP(p_sxq, "\"(") == 0) {
+ vim_snprintf(ncmd, ncmd_size, "\"(%s)\"", ecmd);
+ } else {
+ vim_snprintf(ncmd, ncmd_size, "%s%s%s", p_sxq, ecmd, p_sxq);
+ }
+
+ if (ecmd != cmd) {
+ xfree((void *)ecmd);
+ }
+
+ return ncmd;
+}
+
diff --git a/src/nvim/os/signal.c b/src/nvim/os/signal.c
index 4abc9cfc36..1ac6d3f5e1 100644
--- a/src/nvim/os/signal.c
+++ b/src/nvim/os/signal.c
@@ -2,6 +2,9 @@
#include <stdbool.h>
#include <uv.h>
+#ifndef WIN32
+# include <signal.h> // for sigset_t
+#endif
#include "nvim/ascii.h"
#include "nvim/vim.h"
@@ -11,7 +14,6 @@
#include "nvim/main.h"
#include "nvim/memory.h"
#include "nvim/misc1.h"
-#include "nvim/misc2.h"
#include "nvim/event/signal.h"
#include "nvim/os/signal.h"
#include "nvim/event/loop.h"
@@ -29,6 +31,16 @@ static bool rejecting_deadly;
void signal_init(void)
{
+#ifndef WIN32
+ // Ensure a clean slate by unblocking all signals. For example, if SIGCHLD is
+ // blocked, libuv may hang after spawning a subprocess on Linux. #5230
+ sigset_t mask;
+ sigemptyset(&mask);
+ if (pthread_sigmask(SIG_SETMASK, &mask, NULL) != 0) {
+ ELOG("Could not unblock signals, nvim might behave strangely.");
+ }
+#endif
+
signal_watcher_init(&main_loop, &spipe, NULL);
signal_watcher_init(&main_loop, &shup, NULL);
signal_watcher_init(&main_loop, &squit, NULL);
diff --git a/src/nvim/os/users.c b/src/nvim/os/users.c
index 8ebb7562ef..1c94ef0067 100644
--- a/src/nvim/os/users.c
+++ b/src/nvim/os/users.c
@@ -6,7 +6,6 @@
#include "nvim/os/os.h"
#include "nvim/garray.h"
#include "nvim/memory.h"
-#include "nvim/misc2.h"
#include "nvim/strings.h"
#ifdef HAVE_PWD_H
# include <pwd.h>
diff --git a/src/nvim/os_unix.c b/src/nvim/os_unix.c
index def7e3b0e5..08294fa6a0 100644
--- a/src/nvim/os_unix.c
+++ b/src/nvim/os_unix.c
@@ -27,7 +27,6 @@
#include "nvim/memory.h"
#include "nvim/message.h"
#include "nvim/misc1.h"
-#include "nvim/misc2.h"
#include "nvim/mouse.h"
#include "nvim/garray.h"
#include "nvim/path.h"
diff --git a/src/nvim/path.c b/src/nvim/path.c
index a2617973b1..a79b7139f1 100644
--- a/src/nvim/path.c
+++ b/src/nvim/path.c
@@ -18,7 +18,6 @@
#include "nvim/memory.h"
#include "nvim/message.h"
#include "nvim/misc1.h"
-#include "nvim/misc2.h"
#include "nvim/option.h"
#include "nvim/os/os.h"
#include "nvim/os/shell.h"
diff --git a/src/nvim/popupmnu.c b/src/nvim/popupmnu.c
index 5ad621e666..947814de4f 100644
--- a/src/nvim/popupmnu.c
+++ b/src/nvim/popupmnu.c
@@ -7,12 +7,12 @@
#include <stdbool.h>
#include "nvim/vim.h"
+#include "nvim/api/private/helpers.h"
#include "nvim/ascii.h"
#include "nvim/popupmnu.h"
#include "nvim/charset.h"
#include "nvim/ex_cmds.h"
#include "nvim/memline.h"
-#include "nvim/misc2.h"
#include "nvim/move.h"
#include "nvim/option.h"
#include "nvim/screen.h"
@@ -21,6 +21,7 @@
#include "nvim/memory.h"
#include "nvim/window.h"
#include "nvim/edit.h"
+#include "nvim/ui.h"
static pumitem_T *pum_array = NULL; // items of displayed pum
static int pum_size; // nr of items in "pum_array"
@@ -36,8 +37,10 @@ static int pum_scrollbar; // TRUE when scrollbar present
static int pum_row; // top row of pum
static int pum_col; // left column of pum
-static int pum_do_redraw = FALSE; // do redraw anyway
+static bool pum_is_visible = false;
+static bool pum_external = false;
+static bool pum_wants_external = false;
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "popupmnu.c.generated.h"
@@ -53,7 +56,10 @@ static int pum_do_redraw = FALSE; // do redraw anyway
/// @param array
/// @param size
/// @param selected index of initially selected item, none if out of range
-void pum_display(pumitem_T *array, int size, int selected)
+/// @param array_changed if true, array contains different items since last call
+/// if false, a new item is selected, but the array
+/// is the same
+void pum_display(pumitem_T *array, int size, int selected, bool array_changed)
{
int w;
int def_width;
@@ -68,20 +74,55 @@ void pum_display(pumitem_T *array, int size, int selected)
int above_row = cmdline_row;
int redo_count = 0;
+ if (!pum_is_visible) {
+ // To keep the code simple, we only allow changing the
+ // draw mode when the popup menu is not being displayed
+ pum_external = pum_wants_external;
+ }
+
redo:
+ // Mark the pum as visible already here,
+ // to avoid that must_redraw is set when 'cursorcolumn' is on.
+ pum_is_visible = true;
+ validate_cursor_col();
+
+ // anchor position: the start of the completed word
+ row = curwin->w_wrow + curwin->w_winrow;
+ if (curwin->w_p_rl) {
+ col = curwin->w_wincol + curwin->w_width - curwin->w_wcol - 1;
+ } else {
+ col = curwin->w_wincol + curwin->w_wcol;
+ }
+
+ if (pum_external) {
+ Array args = ARRAY_DICT_INIT;
+ if (array_changed) {
+ Array arr = ARRAY_DICT_INIT;
+ for (i = 0; i < size; i++) {
+ Array item = ARRAY_DICT_INIT;
+ ADD(item, STRING_OBJ(cstr_to_string((char *)array[i].pum_text)));
+ ADD(item, STRING_OBJ(cstr_to_string((char *)array[i].pum_kind)));
+ ADD(item, STRING_OBJ(cstr_to_string((char *)array[i].pum_extra)));
+ ADD(item, STRING_OBJ(cstr_to_string((char *)array[i].pum_info)));
+ ADD(arr, ARRAY_OBJ(item));
+ }
+ ADD(args, ARRAY_OBJ(arr));
+ ADD(args, INTEGER_OBJ(selected));
+ ADD(args, INTEGER_OBJ(row));
+ ADD(args, INTEGER_OBJ(col));
+ ui_event("popupmenu_show", args);
+ } else {
+ ADD(args, INTEGER_OBJ(selected));
+ ui_event("popupmenu_select", args);
+ }
+ return;
+ }
+
def_width = PUM_DEF_WIDTH;
max_width = 0;
kind_width = 0;
extra_width = 0;
- // Pretend the pum is already there to avoid that must_redraw is set when
- // 'cuc' is on.
- pum_array = (pumitem_T *)1;
- validate_cursor_col();
- pum_array = NULL;
-
- row = curwin->w_wrow + curwin->w_winrow;
-
if (firstwin->w_p_pvw) {
top_clear = firstwin->w_height;
} else {
@@ -194,13 +235,6 @@ redo:
pum_base_width = max_width;
pum_kind_width = kind_width;
- // Calculate column
- if (curwin->w_p_rl) {
- col = curwin->w_wincol + curwin->w_width - curwin->w_wcol - 1;
- } else {
- col = curwin->w_wincol + curwin->w_wcol;
- }
-
// if there are more items than room we need a scrollbar
if (pum_height < size) {
pum_scrollbar = 1;
@@ -641,9 +675,9 @@ static int pum_set_selected(int n, int repeat)
// Update the screen before drawing the popup menu.
// Enable updating the status lines.
- pum_do_redraw = TRUE;
+ pum_is_visible = false;
update_screen(0);
- pum_do_redraw = FALSE;
+ pum_is_visible = true;
if (!resized && win_valid(curwin_save)) {
no_u_sync++;
@@ -653,9 +687,9 @@ static int pum_set_selected(int n, int repeat)
// May need to update the screen again when there are
// autocommands involved.
- pum_do_redraw = TRUE;
+ pum_is_visible = false;
update_screen(0);
- pum_do_redraw = FALSE;
+ pum_is_visible = true;
}
}
}
@@ -672,10 +706,17 @@ static int pum_set_selected(int n, int repeat)
/// Undisplay the popup menu (later).
void pum_undisplay(void)
{
+ pum_is_visible = false;
pum_array = NULL;
- redraw_all_later(SOME_VALID);
- redraw_tabline = TRUE;
- status_redraw_all();
+
+ if (pum_external) {
+ Array args = ARRAY_DICT_INIT;
+ ui_event("popupmenu_hide", args);
+ } else {
+ redraw_all_later(SOME_VALID);
+ redraw_tabline = true;
+ status_redraw_all();
+ }
}
/// Clear the popup menu. Currently only resets the offset to the first
@@ -685,12 +726,16 @@ void pum_clear(void)
pum_first = 0;
}
-/// Overruled when "pum_do_redraw" is set, used to redraw the status lines.
-///
-/// @return TRUE if the popup menu is displayed.
-int pum_visible(void)
+/// @return true if the popup menu is displayed.
+bool pum_visible(void)
{
- return !pum_do_redraw && pum_array != NULL;
+ return pum_is_visible;
+}
+
+/// @return true if the popup menu is displayed and drawn on the grid.
+bool pum_drawn(void)
+{
+ return pum_visible() && !pum_external;
}
/// Gets the height of the menu.
@@ -701,3 +746,8 @@ int pum_get_height(void)
{
return pum_height;
}
+
+void pum_set_external(bool external)
+{
+ pum_wants_external = external;
+}
diff --git a/src/nvim/quickfix.c b/src/nvim/quickfix.c
index 20bd0a62b8..a7aff15121 100644
--- a/src/nvim/quickfix.c
+++ b/src/nvim/quickfix.c
@@ -27,7 +27,6 @@
#include "nvim/memline.h"
#include "nvim/message.h"
#include "nvim/misc1.h"
-#include "nvim/misc2.h"
#include "nvim/memory.h"
#include "nvim/move.h"
#include "nvim/normal.h"
@@ -1732,15 +1731,29 @@ void qf_list(exarg_T *eap)
EMSG(_(e_quickfix));
return;
}
+
+ bool plus = false;
+ if (*arg == '+') {
+ arg++;
+ plus = true;
+ }
if (!get_list_range(&arg, &idx1, &idx2) || *arg != NUL) {
EMSG(_(e_trailing));
return;
}
- i = qi->qf_lists[qi->qf_curlist].qf_count;
- if (idx1 < 0)
- idx1 = (-idx1 > i) ? 0 : idx1 + i + 1;
- if (idx2 < 0)
- idx2 = (-idx2 > i) ? 0 : idx2 + i + 1;
+ if (plus) {
+ i = qi->qf_lists[qi->qf_curlist].qf_index;
+ idx2 = i + idx1;
+ idx1 = i;
+ } else {
+ i = qi->qf_lists[qi->qf_curlist].qf_count;
+ if (idx1 < 0) {
+ idx1 = (-idx1 > i) ? 0 : idx1 + i + 1;
+ }
+ if (idx2 < 0) {
+ idx2 = (-idx2 > i) ? 0 : idx2 + i + 1;
+ }
+ }
if (qi->qf_lists[qi->qf_curlist].qf_nonevalid)
all = TRUE;
diff --git a/src/nvim/regexp.c b/src/nvim/regexp.c
index f8fd7d4ef8..64a70c295a 100644
--- a/src/nvim/regexp.c
+++ b/src/nvim/regexp.c
@@ -59,7 +59,6 @@
#include "nvim/memory.h"
#include "nvim/message.h"
#include "nvim/misc1.h"
-#include "nvim/misc2.h"
#include "nvim/garray.h"
#include "nvim/strings.h"
diff --git a/src/nvim/regexp_nfa.c b/src/nvim/regexp_nfa.c
index 92dbd693ea..35308b7411 100644
--- a/src/nvim/regexp_nfa.c
+++ b/src/nvim/regexp_nfa.c
@@ -11,7 +11,6 @@
#include <limits.h>
#include "nvim/ascii.h"
-#include "nvim/misc2.h"
#include "nvim/garray.h"
/*
@@ -4855,9 +4854,15 @@ static int nfa_regmatch(nfa_regprog_T *prog, nfa_state_T *start,
// recursive_regmatch(). Allow interrupting them with CTRL-C.
fast_breakcheck();
if (got_int) {
+#ifdef NFA_REGEXP_DEBUG_LOG
+ fclose(debug);
+#endif
return false;
}
if (nfa_time_limit != NULL && profile_passed_limit(*nfa_time_limit)) {
+#ifdef NFA_REGEXP_DEBUG_LOG
+ fclose(debug);
+#endif
return false;
}
diff --git a/src/nvim/screen.c b/src/nvim/screen.c
index 61c88b5875..9a2eeda8b2 100644
--- a/src/nvim/screen.c
+++ b/src/nvim/screen.c
@@ -108,7 +108,6 @@
#include "nvim/menu.h"
#include "nvim/message.h"
#include "nvim/misc1.h"
-#include "nvim/misc2.h"
#include "nvim/garray.h"
#include "nvim/move.h"
#include "nvim/normal.h"
@@ -120,6 +119,7 @@
#include "nvim/regexp.h"
#include "nvim/search.h"
#include "nvim/spell.h"
+#include "nvim/state.h"
#include "nvim/strings.h"
#include "nvim/syntax.h"
#include "nvim/terminal.h"
@@ -420,9 +420,10 @@ void update_screen(int type)
}
}
end_search_hl();
- /* May need to redraw the popup menu. */
- if (pum_visible())
+ // May need to redraw the popup menu.
+ if (pum_drawn()) {
pum_redraw();
+ }
/* Reset b_mod_set flags. Going through all windows is probably faster
* than going through all buffers (there could be many buffers). */
@@ -4827,15 +4828,12 @@ void win_redr_status(win_T *wp)
wp->w_redr_status = FALSE;
if (wp->w_status_height == 0) {
- /* no status line, can only be last window */
- redraw_cmdline = TRUE;
- } else if (!redrawing()
- /* don't update status line when popup menu is visible and may be
- * drawn over it */
- || pum_visible()
- ) {
- /* Don't redraw right now, do it later. */
- wp->w_redr_status = TRUE;
+ // no status line, can only be last window
+ redraw_cmdline = true;
+ } else if (!redrawing() || pum_drawn()) {
+ // Don't redraw right now, do it later. Don't update status line when
+ // popup menu is visible and may be drawn over it
+ wp->w_redr_status = true;
} else if (*p_stl != NUL || *wp->w_p_stl != NUL) {
/* redraw custom status line */
redraw_custom_statusline(wp);
@@ -7081,9 +7079,9 @@ void showruler(int always)
{
if (!always && !redrawing())
return;
- if (pum_visible()) {
- /* Don't redraw right now, do it later. */
- curwin->w_redr_status = TRUE;
+ if (pum_drawn()) {
+ // Don't redraw right now, do it later.
+ curwin->w_redr_status = true;
return;
}
if ((*p_stl != NUL || *curwin->w_p_stl != NUL) && curwin->w_status_height) {
@@ -7119,9 +7117,10 @@ static void win_redr_ruler(win_T *wp, int always)
if (wp == lastwin && lastwin->w_status_height == 0)
if (edit_submode != NULL)
return;
- /* Don't draw the ruler when the popup menu is visible, it may overlap. */
- if (pum_visible())
+ // Don't draw the ruler when the popup menu is visible, it may overlap.
+ if (pum_drawn()) {
return;
+ }
if (*p_ruf) {
int save_called_emsg = called_emsg;
@@ -7371,7 +7370,7 @@ void screen_resize(int width, int height)
redrawcmdline();
} else {
update_topline();
- if (pum_visible()) {
+ if (pum_drawn()) {
redraw_later(NOT_VALID);
ins_compl_show_pum(); /* This includes the redraw. */
} else
diff --git a/src/nvim/search.c b/src/nvim/search.c
index 6e2b69fff7..5f4df3be92 100644
--- a/src/nvim/search.c
+++ b/src/nvim/search.c
@@ -31,7 +31,6 @@
#include "nvim/memory.h"
#include "nvim/message.h"
#include "nvim/misc1.h"
-#include "nvim/misc2.h"
#include "nvim/move.h"
#include "nvim/mouse.h"
#include "nvim/normal.h"
diff --git a/src/nvim/shada.c b/src/nvim/shada.c
index fe62f06e59..01c0807d82 100644
--- a/src/nvim/shada.c
+++ b/src/nvim/shada.c
@@ -27,7 +27,6 @@
#include "nvim/api/private/helpers.h"
#include "nvim/buffer.h"
#include "nvim/buffer_defs.h"
-#include "nvim/misc2.h"
#include "nvim/ex_getln.h"
#include "nvim/search.h"
#include "nvim/regexp.h"
@@ -2976,7 +2975,7 @@ shada_write_file_nomerge: {}
if (sd_writer.cookie == NULL) {
xfree(fname);
xfree(tempname);
- if (sd_reader.close != NULL) {
+ if (sd_reader.cookie != NULL) {
sd_reader.close(&sd_reader);
}
return FAIL;
diff --git a/src/nvim/spell.c b/src/nvim/spell.c
index 610fb660e7..ba7f31be25 100644
--- a/src/nvim/spell.c
+++ b/src/nvim/spell.c
@@ -312,7 +312,6 @@
#include "nvim/memory.h"
#include "nvim/message.h"
#include "nvim/misc1.h"
-#include "nvim/misc2.h"
#include "nvim/garray.h"
#include "nvim/normal.h"
#include "nvim/option.h"
diff --git a/src/nvim/state.c b/src/nvim/state.c
index 30133e2201..f792ec00a4 100644
--- a/src/nvim/state.c
+++ b/src/nvim/state.c
@@ -2,10 +2,12 @@
#include "nvim/lib/kvec.h"
+#include "nvim/ascii.h"
#include "nvim/state.h"
#include "nvim/vim.h"
#include "nvim/main.h"
#include "nvim/getchar.h"
+#include "nvim/option_defs.h"
#include "nvim/ui.h"
#include "nvim/os/input.h"
@@ -61,3 +63,35 @@ getkey:
}
}
}
+
+/// Return TRUE if in the current mode we need to use virtual.
+int virtual_active(void)
+{
+ // While an operator is being executed we return "virtual_op", because
+ // VIsual_active has already been reset, thus we can't check for "block"
+ // being used.
+ if (virtual_op != MAYBE) {
+ return virtual_op;
+ }
+ return ve_flags == VE_ALL
+ || ((ve_flags & VE_BLOCK) && VIsual_active && VIsual_mode == Ctrl_V)
+ || ((ve_flags & VE_INSERT) && (State & INSERT));
+}
+
+/// VISUAL, SELECTMODE and OP_PENDING State are never set, they are equal to
+/// NORMAL State with a condition. This function returns the real State.
+int get_real_state(void)
+{
+ if (State & NORMAL) {
+ if (VIsual_active) {
+ if (VIsual_select) {
+ return SELECTMODE;
+ }
+ return VISUAL;
+ } else if (finish_op) {
+ return OP_PENDING;
+ }
+ }
+ return State;
+}
+
diff --git a/src/nvim/strings.c b/src/nvim/strings.c
index 37a0fb82da..c1800a0639 100644
--- a/src/nvim/strings.c
+++ b/src/nvim/strings.c
@@ -5,7 +5,6 @@
#include "nvim/vim.h"
#include "nvim/ascii.h"
#include "nvim/strings.h"
-#include "nvim/misc2.h"
#include "nvim/file_search.h"
#include "nvim/buffer.h"
#include "nvim/charset.h"
diff --git a/src/nvim/syntax.c b/src/nvim/syntax.c
index f7a8e4f8b9..6fd7603629 100644
--- a/src/nvim/syntax.c
+++ b/src/nvim/syntax.c
@@ -25,7 +25,6 @@
#include "nvim/memory.h"
#include "nvim/message.h"
#include "nvim/misc1.h"
-#include "nvim/misc2.h"
#include "nvim/keymap.h"
#include "nvim/garray.h"
#include "nvim/option.h"
@@ -6598,6 +6597,9 @@ do_highlight (
else {
if (is_normal_group) {
HL_TABLE()[idx].sg_attr = 0;
+ // Need to update all groups, because they might be using "bg" and/or
+ // "fg", which have been changed now.
+ highlight_attr_set_all();
// If the normal group has changed, it is simpler to refresh every UI
ui_refresh();
} else
@@ -6999,11 +7001,15 @@ highlight_color (
if (font || sp)
return NULL;
if (modec == 'c') {
- if (fg)
+ if (fg) {
n = HL_TABLE()[id - 1].sg_cterm_fg - 1;
- else
+ } else {
n = HL_TABLE()[id - 1].sg_cterm_bg - 1;
- sprintf((char *)name, "%d", n);
+ }
+ if (n < 0) {
+ return NULL;
+ }
+ snprintf((char *)name, sizeof(name), "%d", n);
return name;
}
/* term doesn't have color */
@@ -7262,6 +7268,23 @@ int syn_get_final_id(int hl_id)
return hl_id;
}
+/// Refresh the color attributes of all highlight groups.
+static void highlight_attr_set_all(void)
+{
+ for (int idx = 0; idx < highlight_ga.ga_len; idx++) {
+ struct hl_group *sgp = &HL_TABLE()[idx];
+ if (sgp->sg_rgb_bg_name != NULL) {
+ sgp->sg_rgb_bg = name_to_color(sgp->sg_rgb_bg_name);
+ }
+ if (sgp->sg_rgb_fg_name != NULL) {
+ sgp->sg_rgb_fg = name_to_color(sgp->sg_rgb_fg_name);
+ }
+ if (sgp->sg_rgb_sp_name != NULL) {
+ sgp->sg_rgb_sp = name_to_color(sgp->sg_rgb_sp_name);
+ }
+ set_hl_attr(idx);
+ }
+}
/*
* Translate the 'highlight' option into attributes in highlight_attr[] and
@@ -7703,6 +7726,10 @@ RgbValue name_to_color(uint8_t *name)
&& isxdigit(name[6]) && name[7] == NUL) {
// rgb hex string
return strtol((char *)(name + 1), NULL, 16);
+ } else if (!STRICMP(name, "bg") || !STRICMP(name, "background")) {
+ return normal_bg;
+ } else if (!STRICMP(name, "fg") || !STRICMP(name, "foreground")) {
+ return normal_fg;
}
for (int i = 0; color_name_table[i].name != NULL; i++) {
diff --git a/src/nvim/tag.c b/src/nvim/tag.c
index dfecfb776d..81256b4f01 100644
--- a/src/nvim/tag.c
+++ b/src/nvim/tag.c
@@ -26,7 +26,6 @@
#include "nvim/mbyte.h"
#include "nvim/message.h"
#include "nvim/misc1.h"
-#include "nvim/misc2.h"
#include "nvim/file_search.h"
#include "nvim/garray.h"
#include "nvim/memory.h"
diff --git a/src/nvim/terminal.c b/src/nvim/terminal.c
index 90636326a5..ff98dc9f22 100644
--- a/src/nvim/terminal.c
+++ b/src/nvim/terminal.c
@@ -127,7 +127,7 @@ struct terminal {
// we can't store a direct reference to the buffer because the
// refresh_timer_cb may be called after the buffer was freed, and there's
// no way to know if the memory was reused.
- uint64_t buf_handle;
+ handle_T buf_handle;
// program exited
bool closed, destroy;
// some vterm properties
@@ -623,11 +623,12 @@ static void buf_set_term_title(buf_T *buf, char *title)
FUNC_ATTR_NONNULL_ALL
{
Error err;
- api_free_object(dict_set_value(buf->b_vars,
- cstr_as_string("term_title"),
- STRING_OBJ(cstr_as_string(title)),
- false,
- &err));
+ dict_set_value(buf->b_vars,
+ cstr_as_string("term_title"),
+ STRING_OBJ(cstr_as_string(title)),
+ false,
+ false,
+ &err);
}
static int term_settermprop(VTermProp prop, VTermValue *val, void *data)
diff --git a/src/nvim/testdir/Makefile b/src/nvim/testdir/Makefile
index 57c99e9845..ff0f729460 100644
--- a/src/nvim/testdir/Makefile
+++ b/src/nvim/testdir/Makefile
@@ -37,6 +37,7 @@ NEW_TESTS = \
test_help_tagjump.res \
test_langmap.res \
test_syntax.res \
+ test_usercommands.res \
test_timers.res \
test_viml.res \
test_visual.res \
diff --git a/src/nvim/testdir/test_alot.vim b/src/nvim/testdir/test_alot.vim
index daf6f026ba..f0efd6e4ed 100644
--- a/src/nvim/testdir/test_alot.vim
+++ b/src/nvim/testdir/test_alot.vim
@@ -3,8 +3,10 @@
source test_assign.vim
source test_cursor_func.vim
+source test_feedkeys.vim
source test_cmdline.vim
source test_menu.vim
source test_popup.vim
source test_regexp_utf8.vim
+source test_syn_attr.vim
source test_unlet.vim
diff --git a/src/nvim/testdir/test_feedkeys.vim b/src/nvim/testdir/test_feedkeys.vim
new file mode 100644
index 0000000000..33cd58949d
--- /dev/null
+++ b/src/nvim/testdir/test_feedkeys.vim
@@ -0,0 +1,10 @@
+" Test feedkeys() function.
+
+func Test_feedkeys_x_with_empty_string()
+ new
+ call feedkeys("ifoo\<Esc>")
+ call assert_equal('', getline('.'))
+ call feedkeys('', 'x')
+ call assert_equal('foo', getline('.'))
+ quit!
+endfunc
diff --git a/src/nvim/testdir/test_help_tagjump.vim b/src/nvim/testdir/test_help_tagjump.vim
index 9f9207d27d..42f8391aba 100644
--- a/src/nvim/testdir/test_help_tagjump.vim
+++ b/src/nvim/testdir/test_help_tagjump.vim
@@ -37,4 +37,14 @@ func Test_help_tagjump()
call assert_equal("help", &filetype)
call assert_true(getline('.') =~ '\*arglistid()\*')
helpclose
+
+ exec "help! 'autoindent'."
+ call assert_equal("help", &filetype)
+ call assert_true(getline('.') =~ "\\*'autoindent'\\*")
+ helpclose
+
+ exec "help! {address}."
+ call assert_equal("help", &filetype)
+ call assert_true(getline('.') =~ '\*{address}\*')
+ helpclose
endfunc
diff --git a/src/nvim/testdir/test_syn_attr.vim b/src/nvim/testdir/test_syn_attr.vim
new file mode 100644
index 0000000000..809442eb94
--- /dev/null
+++ b/src/nvim/testdir/test_syn_attr.vim
@@ -0,0 +1,24 @@
+" Test syntax highlighting functions.
+
+func Test_missing_attr()
+ hi Mine cterm=italic
+ call assert_equal('Mine', synIDattr(hlID("Mine"), "name"))
+ call assert_equal('1', synIDattr(hlID("Mine"), "italic", 'cterm'))
+ hi Mine cterm=inverse
+ call assert_equal('1', synIDattr(hlID("Mine"), "inverse", 'cterm'))
+ hi Mine cterm=standout gui=undercurl
+ call assert_equal('1', synIDattr(hlID("Mine"), "standout", 'cterm'))
+ call assert_equal('1', synIDattr(hlID("Mine"), "undercurl", 'gui'))
+ hi Mine cterm=NONE gui=NONE
+ call assert_equal('', synIDattr(hlID("Mine"), "italic", 'cterm'))
+ call assert_equal('', synIDattr(hlID("Mine"), "inverse", 'cterm'))
+ call assert_equal('', synIDattr(hlID("Mine"), "standout", 'cterm'))
+ call assert_equal('', synIDattr(hlID("Mine"), "undercurl", 'gui'))
+
+ if has('gui')
+ hi Mine guifg=blue guibg=red font=something
+ call assert_equal('blue', synIDattr(hlID("Mine"), "fg", 'gui'))
+ call assert_equal('red', synIDattr(hlID("Mine"), "bg", 'gui'))
+ call assert_equal('something', synIDattr(hlID("Mine"), "font", 'gui'))
+ endif
+endfunc
diff --git a/src/nvim/testdir/test_usercommands.vim b/src/nvim/testdir/test_usercommands.vim
new file mode 100644
index 0000000000..f593d16dbf
--- /dev/null
+++ b/src/nvim/testdir/test_usercommands.vim
@@ -0,0 +1,48 @@
+" Tests for user defined commands
+
+" Test for <mods> in user defined commands
+function Test_cmdmods()
+ let g:mods = ''
+
+ command! -nargs=* MyCmd let g:mods .= '<mods> '
+
+ MyCmd
+ aboveleft MyCmd
+ belowright MyCmd
+ botright MyCmd
+ browse MyCmd
+ confirm MyCmd
+ hide MyCmd
+ keepalt MyCmd
+ keepjumps MyCmd
+ keepmarks MyCmd
+ keeppatterns MyCmd
+ lockmarks MyCmd
+ noswapfile MyCmd
+ silent MyCmd
+ tab MyCmd
+ topleft MyCmd
+ verbose MyCmd
+ vertical MyCmd
+
+ aboveleft belowright botright browse confirm hide keepalt keepjumps
+ \ keepmarks keeppatterns lockmarks noswapfile silent tab
+ \ topleft verbose vertical MyCmd
+
+ call assert_equal(' aboveleft belowright botright browse confirm ' .
+ \ 'hide keepalt keepjumps keepmarks keeppatterns lockmarks ' .
+ \ 'noswapfile silent tab topleft verbose vertical aboveleft ' .
+ \ 'belowright botright browse confirm hide keepalt keepjumps ' .
+ \ 'keepmarks keeppatterns lockmarks noswapfile silent tab topleft ' .
+ \ 'verbose vertical ', g:mods)
+
+ let g:mods = ''
+ command! -nargs=* MyQCmd let g:mods .= '<q-mods> '
+
+ vertical MyQCmd
+ call assert_equal('"vertical" ', g:mods)
+
+ delcommand MyCmd
+ delcommand MyQCmd
+ unlet g:mods
+endfunction
diff --git a/src/nvim/testdir/test_window_id.vim b/src/nvim/testdir/test_window_id.vim
index b9e9f45c49..fa3ebd757e 100644
--- a/src/nvim/testdir/test_window_id.vim
+++ b/src/nvim/testdir/test_window_id.vim
@@ -5,6 +5,7 @@ func Test_win_getid()
let id1 = win_getid()
split two
let id2 = win_getid()
+ let bufnr2 = bufnr('%')
split three
let id3 = win_getid()
tabnew
@@ -12,6 +13,7 @@ func Test_win_getid()
let id4 = win_getid()
split five
let id5 = win_getid()
+ let bufnr5 = bufnr('%')
tabnext
wincmd w
@@ -67,5 +69,11 @@ func Test_win_getid()
call assert_equal([1, nr2], win_id2tabwin(id2))
call assert_equal([2, nr4], win_id2tabwin(id4))
+ call assert_equal([], win_findbuf(9999))
+ call assert_equal([id2], win_findbuf(bufnr2))
+ call win_gotoid(id5)
+ split
+ call assert_equal(sort([id5, win_getid()]), sort(win_findbuf(bufnr5)))
+
only!
endfunc
diff --git a/src/nvim/tui/input.c b/src/nvim/tui/input.c
index 3ef4d34c9a..68ea00ee63 100644
--- a/src/nvim/tui/input.c
+++ b/src/nvim/tui/input.c
@@ -5,7 +5,6 @@
#include "nvim/api/private/helpers.h"
#include "nvim/ascii.h"
#include "nvim/main.h"
-#include "nvim/misc2.h"
#include "nvim/os/os.h"
#include "nvim/os/input.h"
#include "nvim/event/rstream.h"
@@ -216,8 +215,8 @@ static int get_key_code_timeout(void)
// Check 'ttimeout' to determine if we should send ESC after 'ttimeoutlen'.
// See :help 'ttimeout' for more information
Error err = ERROR_INIT;
- if (vim_get_option(cstr_as_string("ttimeout"), &err).data.boolean) {
- ms = vim_get_option(cstr_as_string("ttimeoutlen"), &err).data.integer;
+ if (nvim_get_option(cstr_as_string("ttimeout"), &err).data.boolean) {
+ ms = nvim_get_option(cstr_as_string("ttimeoutlen"), &err).data.integer;
}
return (int)ms;
diff --git a/src/nvim/tui/tui.c b/src/nvim/tui/tui.c
index d220df508a..bfc03dfb81 100644
--- a/src/nvim/tui/tui.c
+++ b/src/nvim/tui/tui.c
@@ -83,6 +83,7 @@ UI *tui_start(void)
UI *ui = xcalloc(1, sizeof(UI));
ui->stop = tui_stop;
ui->rgb = p_tgc;
+ ui->pum_external = false;
ui->resize = tui_resize;
ui->clear = tui_clear;
ui->eol_clear = tui_eol_clear;
@@ -106,6 +107,7 @@ UI *tui_start(void)
ui->suspend = tui_suspend;
ui->set_title = tui_set_title;
ui->set_icon = tui_set_icon;
+ ui->event = tui_event;
return ui_bridge_attach(ui, tui_main, tui_scheduler);
}
@@ -650,6 +652,12 @@ static void tui_set_icon(UI *ui, char *icon)
{
}
+// NB: if we start to use this, the ui_bridge must be updated
+// to make a copy for the tui thread
+static void tui_event(UI *ui, char *name, Array args, bool *args_consumed)
+{
+}
+
static void invalidate(UI *ui, int top, int bot, int left, int right)
{
TUIData *data = ui->data;
diff --git a/src/nvim/types.h b/src/nvim/types.h
index bfe8be2091..35a5d1e2bd 100644
--- a/src/nvim/types.h
+++ b/src/nvim/types.h
@@ -13,4 +13,5 @@ typedef unsigned char char_u;
// Can hold one decoded UTF-8 character.
typedef uint32_t u8char_T;
+typedef struct expand expand_T;
#endif // NVIM_TYPES_H
diff --git a/src/nvim/ui.c b/src/nvim/ui.c
index d968cbc390..dd278893c2 100644
--- a/src/nvim/ui.c
+++ b/src/nvim/ui.c
@@ -12,10 +12,8 @@
#include "nvim/ex_cmds2.h"
#include "nvim/fold.h"
#include "nvim/main.h"
-#include "nvim/mbyte.h"
#include "nvim/ascii.h"
#include "nvim/misc1.h"
-#include "nvim/misc2.h"
#include "nvim/mbyte.h"
#include "nvim/garray.h"
#include "nvim/memory.h"
@@ -27,6 +25,7 @@
#include "nvim/os/time.h"
#include "nvim/os/input.h"
#include "nvim/os/signal.h"
+#include "nvim/popupmnu.h"
#include "nvim/screen.h"
#include "nvim/syntax.h"
#include "nvim/window.h"
@@ -35,6 +34,7 @@
#else
# include "nvim/msgpack_rpc/server.h"
#endif
+#include "nvim/api/private/helpers.h"
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "ui.c.generated.h"
@@ -143,6 +143,15 @@ void ui_set_icon(char *icon)
UI_CALL(flush);
}
+void ui_event(char *name, Array args)
+{
+ bool args_consumed = false;
+ UI_CALL(event, name, args, &args_consumed);
+ if (!args_consumed) {
+ api_free_array(args);
+ }
+}
+
// May update the shape of the cursor.
void ui_cursor_shape(void)
{
@@ -156,15 +165,18 @@ void ui_refresh(void)
}
int width = INT_MAX, height = INT_MAX;
+ bool pum_external = true;
for (size_t i = 0; i < ui_count; i++) {
UI *ui = uis[i];
width = ui->width < width ? ui->width : width;
height = ui->height < height ? ui->height : height;
+ pum_external &= ui->pum_external;
}
row = col = 0;
screen_resize(width, height);
+ pum_set_external(pum_external);
}
void ui_resize(int new_width, int new_height)
@@ -519,3 +531,4 @@ static void ui_mode_change(void)
UI_CALL(mode_change, mode);
conceal_check_cursur_line();
}
+
diff --git a/src/nvim/ui.h b/src/nvim/ui.h
index 5934d2fee9..d14bc5812c 100644
--- a/src/nvim/ui.h
+++ b/src/nvim/ui.h
@@ -5,6 +5,8 @@
#include <stdbool.h>
#include <stdint.h>
+#include "api/private/defs.h"
+
typedef struct {
bool bold, underline, undercurl, italic, reverse;
int foreground, background, special;
@@ -13,7 +15,7 @@ typedef struct {
typedef struct ui_t UI;
struct ui_t {
- bool rgb;
+ bool rgb, pum_external;
int width, height;
void *data;
void (*resize)(UI *ui, int rows, int columns);
@@ -39,6 +41,7 @@ struct ui_t {
void (*suspend)(UI *ui);
void (*set_title)(UI *ui, char *title);
void (*set_icon)(UI *ui, char *icon);
+ void (*event)(UI *ui, char *name, Array args, bool *args_consumed);
void (*stop)(UI *ui);
};
diff --git a/src/nvim/ui_bridge.c b/src/nvim/ui_bridge.c
index 6290fb3d87..34b95baf6c 100644
--- a/src/nvim/ui_bridge.c
+++ b/src/nvim/ui_bridge.c
@@ -31,6 +31,7 @@ UI *ui_bridge_attach(UI *ui, ui_main_fn ui_main, event_scheduler scheduler)
UIBridgeData *rv = xcalloc(1, sizeof(UIBridgeData));
rv->ui = ui;
rv->bridge.rgb = ui->rgb;
+ rv->bridge.pum_external = ui->pum_external;
rv->bridge.stop = ui_bridge_stop;
rv->bridge.resize = ui_bridge_resize;
rv->bridge.clear = ui_bridge_clear;
diff --git a/src/nvim/undo.c b/src/nvim/undo.c
index fc5d6acaa4..d80aaf443a 100644
--- a/src/nvim/undo.c
+++ b/src/nvim/undo.c
@@ -99,6 +99,7 @@
#include "nvim/quickfix.h"
#include "nvim/screen.h"
#include "nvim/sha256.h"
+#include "nvim/state.h"
#include "nvim/strings.h"
#include "nvim/types.h"
#include "nvim/os/os.h"
diff --git a/src/nvim/version.c b/src/nvim/version.c
index f28bffa91d..c2f9ed49e7 100644
--- a/src/nvim/version.c
+++ b/src/nvim/version.c
@@ -15,7 +15,6 @@
#include "nvim/memline.h"
#include "nvim/memory.h"
#include "nvim/message.h"
-#include "nvim/misc2.h"
#include "nvim/screen.h"
#include "nvim/strings.h"
@@ -306,7 +305,7 @@ static int included_patches[] = {
// 1974 NA
1973,
// 1972,
- // 1971,
+ 1971,
// 1970,
// 1969 NA
// 1968,
@@ -364,7 +363,7 @@ static int included_patches[] = {
// 1916 NA
// 1915 NA
// 1914,
- // 1913,
+ 1913,
// 1912,
// 1911,
// 1910,
@@ -377,11 +376,11 @@ static int included_patches[] = {
// 1903,
// 1902 NA
// 1901 NA
- // 1900,
+ 1900,
// 1899 NA
- // 1898,
+ 1898,
// 1897,
- // 1896,
+ 1896,
// 1895,
// 1894 NA
// 1893,
@@ -721,7 +720,7 @@ static int included_patches[] = {
// 1561 NA
// 1560 NA
// 1559,
- // 1558,
+ 1558,
1557,
// 1556 NA
// 1555 NA
@@ -732,7 +731,7 @@ static int included_patches[] = {
1550,
// 1549,
1548,
- // 1547,
+ 1547,
1546,
// 1545 NA
// 1544 NA
@@ -744,9 +743,9 @@ static int included_patches[] = {
// 1538 NA
// 1537 NA
// 1536 NA
- // 1535,
+ 1535,
// 1534 NA
- // 1533,
+ 1533,
// 1532 NA
// 1531 NA
// 1530 NA
diff --git a/src/nvim/window.c b/src/nvim/window.c
index 350b54d595..e9a66ad907 100644
--- a/src/nvim/window.c
+++ b/src/nvim/window.c
@@ -28,7 +28,6 @@
#include "nvim/memory.h"
#include "nvim/message.h"
#include "nvim/misc1.h"
-#include "nvim/misc2.h"
#include "nvim/file_search.h"
#include "nvim/garray.h"
#include "nvim/move.h"
@@ -41,6 +40,7 @@
#include "nvim/regexp.h"
#include "nvim/screen.h"
#include "nvim/search.h"
+#include "nvim/state.h"
#include "nvim/strings.h"
#include "nvim/syntax.h"
#include "nvim/terminal.h"
@@ -2926,7 +2926,9 @@ void win_init_size(void)
*/
static tabpage_T *alloc_tabpage(void)
{
+ static int last_tp_handle = 0;
tabpage_T *tp = xcalloc(1, sizeof(tabpage_T));
+ tp->handle = ++last_tp_handle;
handle_register_tabpage(tp);
/* init t: variables */
@@ -2976,6 +2978,9 @@ int win_new_tabpage(int after, char_u *filename)
xfree(newtp);
return FAIL;
}
+
+ newtp->localdir = tp->localdir ? vim_strsave(tp->localdir) : NULL;
+
curtab = newtp;
/* Create a new empty window. */
@@ -3683,21 +3688,20 @@ win_T *buf_jump_open_tab(buf_T *buf)
return NULL;
}
-static int last_win_id = 0;
-
/*
* Allocate a window structure and link it in the window list when "hidden" is
* FALSE.
*/
static win_T *win_alloc(win_T *after, int hidden)
{
- /*
- * allocate window structure and linesizes arrays
- */
+ static int last_win_id = 0;
+
+ // allocate window structure and linesizes arrays
win_T *new_wp = xcalloc(1, sizeof(win_T));
- handle_register_window(new_wp);
win_alloc_lines(new_wp);
- new_wp->w_id = ++last_win_id;
+
+ new_wp->handle = ++last_win_id;
+ handle_register_window(new_wp);
/* init w: variables */
new_wp->w_vars = dict_alloc();
@@ -5681,7 +5685,7 @@ static bool frame_check_width(frame_T *topfrp, int width)
int win_getid(typval_T *argvars)
{
if (argvars[0].v_type == VAR_UNKNOWN) {
- return curwin->w_id;
+ return curwin->handle;
}
int winnr = get_tv_number(&argvars[0]);
win_T *wp;
@@ -5703,7 +5707,7 @@ int win_getid(typval_T *argvars)
}
for ( ; wp != NULL; wp = wp->w_next) {
if (--winnr == 0) {
- return wp->w_id;
+ return wp->handle;
}
}
}
@@ -5719,7 +5723,7 @@ int win_gotoid(typval_T *argvars)
for (tp = first_tabpage; tp != NULL; tp = tp->tp_next) {
for (wp = tp == curtab ? firstwin : tp->tp_firstwin;
wp != NULL; wp = wp->w_next) {
- if (wp->w_id == id) {
+ if (wp->handle == id) {
goto_tabpage_win(tp, wp);
return 1;
}
@@ -5739,7 +5743,7 @@ void win_id2tabwin(typval_T *argvars, list_T *list)
for (tp = first_tabpage; tp != NULL; tp = tp->tp_next) {
for (wp = tp == curtab ? firstwin : tp->tp_firstwin;
wp != NULL; wp = wp->w_next) {
- if (wp->w_id == id) {
+ if (wp->handle == id) {
list_append_number(list, tabnr);
list_append_number(list, winnr);
return;
@@ -5760,10 +5764,24 @@ int win_id2win(typval_T *argvars)
int id = get_tv_number(&argvars[0]);
for (wp = firstwin; wp != NULL; wp = wp->w_next) {
- if (wp->w_id == id) {
+ if (wp->handle == id) {
return nr;
}
nr++;
}
return 0;
}
+
+void win_findbuf(typval_T *argvars, list_T *list)
+{
+ int bufnr = get_tv_number(&argvars[0]);
+
+ for (tabpage_T *tp = first_tabpage; tp != NULL; tp = tp->tp_next) {
+ for (win_T *wp = tp == curtab ? firstwin : tp->tp_firstwin;
+ wp != NULL; wp = wp->w_next) {
+ if (wp->w_buffer->b_fnum == bufnr) {
+ list_append_number(list, wp->handle);
+ }
+ }
+ }
+}
diff --git a/test/functional/api/buffer_spec.lua b/test/functional/api/buffer_spec.lua
index cf8a83ad81..71ec213b97 100644
--- a/test/functional/api/buffer_spec.lua
+++ b/test/functional/api/buffer_spec.lua
@@ -3,105 +3,112 @@ local helpers = require('test.functional.helpers')(after_each)
local clear, nvim, buffer = helpers.clear, helpers.nvim, helpers.buffer
local curbuf, curwin, eq = helpers.curbuf, helpers.curwin, helpers.eq
local curbufmeths, ok = helpers.curbufmeths, helpers.ok
-local funcs = helpers.funcs
+local funcs, request = helpers.funcs, helpers.request
+local NIL = helpers.NIL
describe('buffer_* functions', function()
before_each(clear)
+ -- access deprecated functions
+ local function curbuf_depr(method, ...)
+ return request('buffer_'..method, 0, ...)
+ end
+
+
describe('line_count, insert and del_line', function()
it('works', function()
- eq(1, curbuf('line_count'))
- curbuf('insert', -1, {'line'})
- eq(2, curbuf('line_count'))
- curbuf('insert', -1, {'line'})
- eq(3, curbuf('line_count'))
- curbuf('del_line', -1)
- eq(2, curbuf('line_count'))
- curbuf('del_line', -1)
- curbuf('del_line', -1)
+ eq(1, curbuf_depr('line_count'))
+ curbuf_depr('insert', -1, {'line'})
+ eq(2, curbuf_depr('line_count'))
+ curbuf_depr('insert', -1, {'line'})
+ eq(3, curbuf_depr('line_count'))
+ curbuf_depr('del_line', -1)
+ eq(2, curbuf_depr('line_count'))
+ curbuf_depr('del_line', -1)
+ curbuf_depr('del_line', -1)
-- There's always at least one line
- eq(1, curbuf('line_count'))
+ eq(1, curbuf_depr('line_count'))
end)
end)
describe('{get,set,del}_line', function()
it('works', function()
- eq('', curbuf('get_line', 0))
- curbuf('set_line', 0, 'line1')
- eq('line1', curbuf('get_line', 0))
- curbuf('set_line', 0, 'line2')
- eq('line2', curbuf('get_line', 0))
- curbuf('del_line', 0)
- eq('', curbuf('get_line', 0))
+ eq('', curbuf_depr('get_line', 0))
+ curbuf_depr('set_line', 0, 'line1')
+ eq('line1', curbuf_depr('get_line', 0))
+ curbuf_depr('set_line', 0, 'line2')
+ eq('line2', curbuf_depr('get_line', 0))
+ curbuf_depr('del_line', 0)
+ eq('', curbuf_depr('get_line', 0))
end)
it('get_line: out-of-bounds is an error', function()
- curbuf('set_line', 0, 'line1.a')
- eq(1, curbuf('line_count')) -- sanity
- eq(false, pcall(curbuf, 'get_line', 1))
- eq(false, pcall(curbuf, 'get_line', -2))
+ curbuf_depr('set_line', 0, 'line1.a')
+ eq(1, curbuf_depr('line_count')) -- sanity
+ eq(false, pcall(curbuf_depr, 'get_line', 1))
+ eq(false, pcall(curbuf_depr, 'get_line', -2))
end)
it('set_line, del_line: out-of-bounds is an error', function()
- curbuf('set_line', 0, 'line1.a')
- eq(false, pcall(curbuf, 'set_line', 1, 'line1.b'))
- eq(false, pcall(curbuf, 'set_line', -2, 'line1.b'))
- eq(false, pcall(curbuf, 'del_line', 2))
- eq(false, pcall(curbuf, 'del_line', -3))
+ curbuf_depr('set_line', 0, 'line1.a')
+ eq(false, pcall(curbuf_depr, 'set_line', 1, 'line1.b'))
+ eq(false, pcall(curbuf_depr, 'set_line', -2, 'line1.b'))
+ eq(false, pcall(curbuf_depr, 'del_line', 2))
+ eq(false, pcall(curbuf_depr, 'del_line', -3))
end)
it('can handle NULs', function()
- curbuf('set_line', 0, 'ab\0cd')
- eq('ab\0cd', curbuf('get_line', 0))
+ curbuf_depr('set_line', 0, 'ab\0cd')
+ eq('ab\0cd', curbuf_depr('get_line', 0))
end)
end)
describe('{get,set}_line_slice', function()
it('get_line_slice: out-of-bounds returns empty array', function()
- curbuf('set_line_slice', 0, 0, true, true, {'a', 'b', 'c'})
- eq({'a', 'b', 'c'}, curbuf('get_line_slice', 0, 2, true, true)) --sanity
-
- eq({}, curbuf('get_line_slice', 2, 3, false, true))
- eq({}, curbuf('get_line_slice', 3, 9, true, true))
- eq({}, curbuf('get_line_slice', 3, -1, true, true))
- eq({}, curbuf('get_line_slice', -3, -4, false, true))
- eq({}, curbuf('get_line_slice', -4, -5, true, true))
+ curbuf_depr('set_line_slice', 0, 0, true, true, {'a', 'b', 'c'})
+ eq({'a', 'b', 'c'}, curbuf_depr('get_line_slice', 0, 2, true, true)) --sanity
+
+ eq({}, curbuf_depr('get_line_slice', 2, 3, false, true))
+ eq({}, curbuf_depr('get_line_slice', 3, 9, true, true))
+ eq({}, curbuf_depr('get_line_slice', 3, -1, true, true))
+ eq({}, curbuf_depr('get_line_slice', -3, -4, false, true))
+ eq({}, curbuf_depr('get_line_slice', -4, -5, true, true))
end)
it('set_line_slice: out-of-bounds extends past end', function()
- curbuf('set_line_slice', 0, 0, true, true, {'a', 'b', 'c'})
- eq({'a', 'b', 'c'}, curbuf('get_line_slice', 0, 2, true, true)) --sanity
-
- eq({'c'}, curbuf('get_line_slice', -1, 4, true, true))
- eq({'a', 'b', 'c'}, curbuf('get_line_slice', 0, 5, true, true))
- curbuf('set_line_slice', 4, 5, true, true, {'d'})
- eq({'a', 'b', 'c', 'd'}, curbuf('get_line_slice', 0, 5, true, true))
- curbuf('set_line_slice', -4, -5, true, true, {'e'})
- eq({'e', 'a', 'b', 'c', 'd'}, curbuf('get_line_slice', 0, 5, true, true))
+ curbuf_depr('set_line_slice', 0, 0, true, true, {'a', 'b', 'c'})
+ eq({'a', 'b', 'c'}, curbuf_depr('get_line_slice', 0, 2, true, true)) --sanity
+
+ eq({'c'}, curbuf_depr('get_line_slice', -1, 4, true, true))
+ eq({'a', 'b', 'c'}, curbuf_depr('get_line_slice', 0, 5, true, true))
+ curbuf_depr('set_line_slice', 4, 5, true, true, {'d'})
+ eq({'a', 'b', 'c', 'd'}, curbuf_depr('get_line_slice', 0, 5, true, true))
+ curbuf_depr('set_line_slice', -4, -5, true, true, {'e'})
+ eq({'e', 'a', 'b', 'c', 'd'}, curbuf_depr('get_line_slice', 0, 5, true, true))
end)
it('works', function()
- eq({''}, curbuf('get_line_slice', 0, -1, true, true))
+ eq({''}, curbuf_depr('get_line_slice', 0, -1, true, true))
-- Replace buffer
- curbuf('set_line_slice', 0, -1, true, true, {'a', 'b', 'c'})
- eq({'a', 'b', 'c'}, curbuf('get_line_slice', 0, -1, true, true))
- eq({'b', 'c'}, curbuf('get_line_slice', 1, -1, true, true))
- eq({'b'}, curbuf('get_line_slice', 1, 2, true, false))
- eq({}, curbuf('get_line_slice', 1, 1, true, false))
- eq({'a', 'b'}, curbuf('get_line_slice', 0, -1, true, false))
- eq({'b'}, curbuf('get_line_slice', 1, -1, true, false))
- eq({'b', 'c'}, curbuf('get_line_slice', -2, -1, true, true))
- curbuf('set_line_slice', 1, 2, true, false, {'a', 'b', 'c'})
- eq({'a', 'a', 'b', 'c', 'c'}, curbuf('get_line_slice', 0, -1, true, true))
- curbuf('set_line_slice', -1, -1, true, true, {'a', 'b', 'c'})
+ curbuf_depr('set_line_slice', 0, -1, true, true, {'a', 'b', 'c'})
+ eq({'a', 'b', 'c'}, curbuf_depr('get_line_slice', 0, -1, true, true))
+ eq({'b', 'c'}, curbuf_depr('get_line_slice', 1, -1, true, true))
+ eq({'b'}, curbuf_depr('get_line_slice', 1, 2, true, false))
+ eq({}, curbuf_depr('get_line_slice', 1, 1, true, false))
+ eq({'a', 'b'}, curbuf_depr('get_line_slice', 0, -1, true, false))
+ eq({'b'}, curbuf_depr('get_line_slice', 1, -1, true, false))
+ eq({'b', 'c'}, curbuf_depr('get_line_slice', -2, -1, true, true))
+ curbuf_depr('set_line_slice', 1, 2, true, false, {'a', 'b', 'c'})
+ eq({'a', 'a', 'b', 'c', 'c'}, curbuf_depr('get_line_slice', 0, -1, true, true))
+ curbuf_depr('set_line_slice', -1, -1, true, true, {'a', 'b', 'c'})
eq({'a', 'a', 'b', 'c', 'a', 'b', 'c'},
- curbuf('get_line_slice', 0, -1, true, true))
- curbuf('set_line_slice', 0, -3, true, false, {})
- eq({'a', 'b', 'c'}, curbuf('get_line_slice', 0, -1, true, true))
- curbuf('set_line_slice', 0, -1, true, true, {})
- eq({''}, curbuf('get_line_slice', 0, -1, true, true))
+ curbuf_depr('get_line_slice', 0, -1, true, true))
+ curbuf_depr('set_line_slice', 0, -3, true, false, {})
+ eq({'a', 'b', 'c'}, curbuf_depr('get_line_slice', 0, -1, true, true))
+ curbuf_depr('set_line_slice', 0, -1, true, true, {})
+ eq({''}, curbuf_depr('get_line_slice', 0, -1, true, true))
end)
end)
@@ -244,6 +251,21 @@ describe('buffer_* functions', function()
curbufmeths.del_var('lua')
eq(0, funcs.exists('b:lua'))
end)
+
+ it('buffer_set_var returns the old value', function()
+ local val1 = {1, 2, {['3'] = 1}}
+ local val2 = {4, 7}
+ eq(NIL, request('buffer_set_var', 0, 'lua', val1))
+ eq(val1, request('buffer_set_var', 0, 'lua', val2))
+ end)
+
+ it('buffer_del_var returns the old value', function()
+ local val1 = {1, 2, {['3'] = 1}}
+ local val2 = {4, 7}
+ eq(NIL, request('buffer_set_var', 0, 'lua', val1))
+ eq(val1, request('buffer_set_var', 0, 'lua', val2))
+ eq(val2, request('buffer_del_var', 0, 'lua'))
+ end)
end)
describe('{get,set}_option', function()
@@ -277,7 +299,7 @@ describe('buffer_* functions', function()
describe('is_valid', function()
it('works', function()
nvim('command', 'new')
- local b = nvim('get_current_buffer')
+ local b = nvim('get_current_buf')
ok(buffer('is_valid', b))
nvim('command', 'bw!')
ok(not buffer('is_valid', b))
@@ -286,7 +308,7 @@ describe('buffer_* functions', function()
describe('get_mark', function()
it('works', function()
- curbuf('insert', -1, {'a', 'bit of', 'text'})
+ curbuf('set_lines', -1, -1, true, {'a', 'bit of', 'text'})
curwin('set_cursor', {3, 4})
nvim('command', 'mark V')
eq({3, 0}, curbuf('get_mark', 'V'))
diff --git a/test/functional/api/server_requests_spec.lua b/test/functional/api/server_requests_spec.lua
index b76c3b9cd6..480f099b4d 100644
--- a/test/functional/api/server_requests_spec.lua
+++ b/test/functional/api/server_requests_spec.lua
@@ -8,6 +8,7 @@ local nvim_prog, command, funcs = helpers.nvim_prog, helpers.command, helpers.fu
local source, next_message = helpers.source, helpers.next_message
local meths = helpers.meths
+if helpers.pending_win32(pending) then return end
describe('server -> client', function()
local cid
@@ -140,8 +141,8 @@ describe('server -> client', function()
describe('when the client is a recursive vim instance', function()
if os.getenv("TRAVIS") and helpers.os_name() == "osx" then
- -- XXX: Hangs Travis OSX since e9061117a5b8f195c3f26a5cb94e18ddd7752d86.
- pending("[Hangs on Travis OSX. #5002]", function() end)
+ -- XXX: Hangs Travis macOS since e9061117a5b8f195c3f26a5cb94e18ddd7752d86.
+ pending("[Hangs on Travis macOS. #5002]", function() end)
return
end
@@ -162,11 +163,11 @@ describe('server -> client', function()
end)
it('can communicate buffers, tabpages, and windows', function()
- eq({3}, eval("rpcrequest(vim, 'vim_get_tabpages')"))
- eq({1}, eval("rpcrequest(vim, 'vim_get_windows')"))
+ eq({1}, eval("rpcrequest(vim, 'nvim_list_tabpages')"))
+ eq({1}, eval("rpcrequest(vim, 'nvim_list_wins')"))
- local buf = eval("rpcrequest(vim, 'vim_get_buffers')")[1]
- eq(2, buf)
+ local buf = eval("rpcrequest(vim, 'nvim_list_bufs')")[1]
+ eq(1, buf)
eval("rpcnotify(vim, 'buffer_set_line', "..buf..", 0, 'SOME TEXT')")
nvim('command', "call rpcrequest(vim, 'vim_eval', '0')") -- wait
diff --git a/test/functional/api/tabpage_spec.lua b/test/functional/api/tabpage_spec.lua
index 7b97c7f067..47dede8b44 100644
--- a/test/functional/api/tabpage_spec.lua
+++ b/test/functional/api/tabpage_spec.lua
@@ -5,21 +5,23 @@ local clear, nvim, tabpage, curtab, eq, ok =
helpers.ok
local curtabmeths = helpers.curtabmeths
local funcs = helpers.funcs
+local request = helpers.request
+local NIL = helpers.NIL
describe('tabpage_* functions', function()
before_each(clear)
- describe('get_windows and get_window', function()
+ describe('list_wins and get_win', function()
it('works', function()
nvim('command', 'tabnew')
nvim('command', 'vsplit')
- local tab1, tab2 = unpack(nvim('get_tabpages'))
- local win1, win2, win3 = unpack(nvim('get_windows'))
- eq({win1}, tabpage('get_windows', tab1))
- eq({win2, win3}, tabpage('get_windows', tab2))
- eq(win2, tabpage('get_window', tab2))
- nvim('set_current_window', win3)
- eq(win3, tabpage('get_window', tab2))
+ local tab1, tab2 = unpack(nvim('list_tabpages'))
+ local win1, win2, win3 = unpack(nvim('list_wins'))
+ eq({win1}, tabpage('list_wins', tab1))
+ eq({win2, win3}, tabpage('list_wins', tab2))
+ eq(win2, tabpage('get_win', tab2))
+ nvim('set_current_win', win3)
+ eq(win3, tabpage('get_win', tab2))
end)
end)
@@ -32,12 +34,27 @@ describe('tabpage_* functions', function()
curtabmeths.del_var('lua')
eq(0, funcs.exists('t:lua'))
end)
+
+ it('tabpage_set_var returns the old value', function()
+ local val1 = {1, 2, {['3'] = 1}}
+ local val2 = {4, 7}
+ eq(NIL, request('tabpage_set_var', 0, 'lua', val1))
+ eq(val1, request('tabpage_set_var', 0, 'lua', val2))
+ end)
+
+ it('tabpage_del_var returns the old value', function()
+ local val1 = {1, 2, {['3'] = 1}}
+ local val2 = {4, 7}
+ eq(NIL, request('tabpage_set_var', 0, 'lua', val1))
+ eq(val1, request('tabpage_set_var', 0, 'lua', val2))
+ eq(val2, request('tabpage_del_var', 0, 'lua'))
+ end)
end)
describe('is_valid', function()
it('works', function()
nvim('command', 'tabnew')
- local tab = nvim('get_tabpages')[2]
+ local tab = nvim('list_tabpages')[2]
nvim('set_current_tabpage', tab)
ok(tabpage('is_valid', tab))
nvim('command', 'tabclose')
diff --git a/test/functional/api/vim_spec.lua b/test/functional/api/vim_spec.lua
index eb2b06edcb..6b30c0e81c 100644
--- a/test/functional/api/vim_spec.lua
+++ b/test/functional/api/vim_spec.lua
@@ -7,13 +7,14 @@ local ok, nvim_async, feed = helpers.ok, helpers.nvim_async, helpers.feed
local os_name = helpers.os_name
local meths = helpers.meths
local funcs = helpers.funcs
+local request = helpers.request
describe('vim_* functions', function()
before_each(clear)
describe('command', function()
it('works', function()
- local fname = os.tmpname()
+ local fname = helpers.tmpname()
nvim('command', 'new')
nvim('command', 'edit '..fname)
nvim('command', 'normal itesting\napi')
@@ -41,6 +42,10 @@ describe('vim_* functions', function()
eq(1, nvim('eval',"matcharg(1) == ['', '']"))
eq({'', ''}, nvim('eval','matcharg(1)'))
end)
+
+ it('works under deprecated name', function()
+ eq(2, request("vim_eval", "1+1"))
+ end)
end)
describe('call_function', function()
@@ -83,19 +88,19 @@ describe('vim_* functions', function()
eq(0, funcs.exists('g:lua'))
end)
- it('set_var returns the old value', function()
+ it('vim_set_var returns the old value', function()
local val1 = {1, 2, {['3'] = 1}}
local val2 = {4, 7}
- eq(NIL, nvim('set_var', 'lua', val1))
- eq(val1, nvim('set_var', 'lua', val2))
+ eq(NIL, request('vim_set_var', 'lua', val1))
+ eq(val1, request('vim_set_var', 'lua', val2))
end)
- it('del_var returns the old value', function()
+ it('vim_del_var returns the old value', function()
local val1 = {1, 2, {['3'] = 1}}
local val2 = {4, 7}
- eq(NIL, meths.set_var('lua', val1))
- eq(val1, meths.set_var('lua', val2))
- eq(val2, meths.del_var('lua'))
+ eq(NIL, request('vim_set_var', 'lua', val1))
+ eq(val1, request('vim_set_var', 'lua', val2))
+ eq(val2, request('vim_del_var', 'lua'))
end)
it('truncates values with NULs in them', function()
@@ -112,47 +117,47 @@ describe('vim_* functions', function()
end)
end)
- describe('{get,set}_current_buffer and get_buffers', function()
+ describe('{get,set}_current_buf and list_bufs', function()
it('works', function()
- eq(1, #nvim('get_buffers'))
- eq(nvim('get_buffers')[1], nvim('get_current_buffer'))
+ eq(1, #nvim('list_bufs'))
+ eq(nvim('list_bufs')[1], nvim('get_current_buf'))
nvim('command', 'new')
- eq(2, #nvim('get_buffers'))
- eq(nvim('get_buffers')[2], nvim('get_current_buffer'))
- nvim('set_current_buffer', nvim('get_buffers')[1])
- eq(nvim('get_buffers')[1], nvim('get_current_buffer'))
+ eq(2, #nvim('list_bufs'))
+ eq(nvim('list_bufs')[2], nvim('get_current_buf'))
+ nvim('set_current_buf', nvim('list_bufs')[1])
+ eq(nvim('list_bufs')[1], nvim('get_current_buf'))
end)
end)
- describe('{get,set}_current_window and get_windows', function()
+ describe('{get,set}_current_win and list_wins', function()
it('works', function()
- eq(1, #nvim('get_windows'))
- eq(nvim('get_windows')[1], nvim('get_current_window'))
+ eq(1, #nvim('list_wins'))
+ eq(nvim('list_wins')[1], nvim('get_current_win'))
nvim('command', 'vsplit')
nvim('command', 'split')
- eq(3, #nvim('get_windows'))
- eq(nvim('get_windows')[1], nvim('get_current_window'))
- nvim('set_current_window', nvim('get_windows')[2])
- eq(nvim('get_windows')[2], nvim('get_current_window'))
+ eq(3, #nvim('list_wins'))
+ eq(nvim('list_wins')[1], nvim('get_current_win'))
+ nvim('set_current_win', nvim('list_wins')[2])
+ eq(nvim('list_wins')[2], nvim('get_current_win'))
end)
end)
- describe('{get,set}_current_tabpage and get_tabpages', function()
+ describe('{get,set}_current_tabpage and list_tabpages', function()
it('works', function()
- eq(1, #nvim('get_tabpages'))
- eq(nvim('get_tabpages')[1], nvim('get_current_tabpage'))
+ eq(1, #nvim('list_tabpages'))
+ eq(nvim('list_tabpages')[1], nvim('get_current_tabpage'))
nvim('command', 'tabnew')
- eq(2, #nvim('get_tabpages'))
- eq(2, #nvim('get_windows'))
- eq(nvim('get_windows')[2], nvim('get_current_window'))
- eq(nvim('get_tabpages')[2], nvim('get_current_tabpage'))
- nvim('set_current_window', nvim('get_windows')[1])
+ eq(2, #nvim('list_tabpages'))
+ eq(2, #nvim('list_wins'))
+ eq(nvim('list_wins')[2], nvim('get_current_win'))
+ eq(nvim('list_tabpages')[2], nvim('get_current_tabpage'))
+ nvim('set_current_win', nvim('list_wins')[1])
-- Switching window also switches tabpages if necessary
- eq(nvim('get_tabpages')[1], nvim('get_current_tabpage'))
- eq(nvim('get_windows')[1], nvim('get_current_window'))
- nvim('set_current_tabpage', nvim('get_tabpages')[2])
- eq(nvim('get_tabpages')[2], nvim('get_current_tabpage'))
- eq(nvim('get_windows')[2], nvim('get_current_window'))
+ eq(nvim('list_tabpages')[1], nvim('get_current_tabpage'))
+ eq(nvim('list_wins')[1], nvim('get_current_win'))
+ nvim('set_current_tabpage', nvim('list_tabpages')[2])
+ eq(nvim('list_tabpages')[2], nvim('get_current_tabpage'))
+ eq(nvim('list_wins')[2], nvim('get_current_win'))
end)
end)
@@ -298,4 +303,11 @@ describe('vim_* functions', function()
eq(false, status)
ok(err:match('Invalid option name') ~= nil)
end)
+
+ it("doesn't leak memory on incorrect argument types", function()
+ local status, err = pcall(nvim, 'set_current_dir',{'not', 'a', 'dir'})
+ eq(false, status)
+ ok(err:match(': Wrong type for argument 1, expecting String') ~= nil)
+ end)
+
end)
diff --git a/test/functional/api/window_spec.lua b/test/functional/api/window_spec.lua
index d90323181c..2c43e4db2c 100644
--- a/test/functional/api/window_spec.lua
+++ b/test/functional/api/window_spec.lua
@@ -7,6 +7,8 @@ local clear, nvim, curbuf, curbuf_contents, window, curwin, eq, neq,
local wait = helpers.wait
local curwinmeths = helpers.curwinmeths
local funcs = helpers.funcs
+local request = helpers.request
+local NIL = helpers.NIL
-- check if str is visible at the beginning of some line
local function is_visible(str)
@@ -30,14 +32,14 @@ end
describe('window_* functions', function()
before_each(clear)
- describe('get_buffer', function()
+ describe('get_buf', function()
it('works', function()
- eq(curbuf(), window('get_buffer', nvim('get_windows')[1]))
+ eq(curbuf(), window('get_buf', nvim('list_wins')[1]))
nvim('command', 'new')
- nvim('set_current_window', nvim('get_windows')[2])
- eq(curbuf(), window('get_buffer', nvim('get_windows')[2]))
- neq(window('get_buffer', nvim('get_windows')[1]),
- window('get_buffer', nvim('get_windows')[2]))
+ nvim('set_current_win', nvim('list_wins')[2])
+ eq(curbuf(), window('get_buf', nvim('list_wins')[2]))
+ neq(window('get_buf', nvim('list_wins')[1]),
+ window('get_buf', nvim('list_wins')[2]))
end)
end)
@@ -103,28 +105,28 @@ describe('window_* functions', function()
describe('{get,set}_height', function()
it('works', function()
nvim('command', 'vsplit')
- eq(window('get_height', nvim('get_windows')[2]),
- window('get_height', nvim('get_windows')[1]))
- nvim('set_current_window', nvim('get_windows')[2])
+ eq(window('get_height', nvim('list_wins')[2]),
+ window('get_height', nvim('list_wins')[1]))
+ nvim('set_current_win', nvim('list_wins')[2])
nvim('command', 'split')
- eq(window('get_height', nvim('get_windows')[2]),
- math.floor(window('get_height', nvim('get_windows')[1]) / 2))
- window('set_height', nvim('get_windows')[2], 2)
- eq(2, window('get_height', nvim('get_windows')[2]))
+ eq(window('get_height', nvim('list_wins')[2]),
+ math.floor(window('get_height', nvim('list_wins')[1]) / 2))
+ window('set_height', nvim('list_wins')[2], 2)
+ eq(2, window('get_height', nvim('list_wins')[2]))
end)
end)
describe('{get,set}_width', function()
it('works', function()
nvim('command', 'split')
- eq(window('get_width', nvim('get_windows')[2]),
- window('get_width', nvim('get_windows')[1]))
- nvim('set_current_window', nvim('get_windows')[2])
+ eq(window('get_width', nvim('list_wins')[2]),
+ window('get_width', nvim('list_wins')[1]))
+ nvim('set_current_win', nvim('list_wins')[2])
nvim('command', 'vsplit')
- eq(window('get_width', nvim('get_windows')[2]),
- math.floor(window('get_width', nvim('get_windows')[1]) / 2))
- window('set_width', nvim('get_windows')[2], 2)
- eq(2, window('get_width', nvim('get_windows')[2]))
+ eq(window('get_width', nvim('list_wins')[2]),
+ math.floor(window('get_width', nvim('list_wins')[1]) / 2))
+ window('set_width', nvim('list_wins')[2], 2)
+ eq(2, window('get_width', nvim('list_wins')[2]))
end)
end)
@@ -137,6 +139,21 @@ describe('window_* functions', function()
curwinmeths.del_var('lua')
eq(0, funcs.exists('w:lua'))
end)
+
+ it('window_set_var returns the old value', function()
+ local val1 = {1, 2, {['3'] = 1}}
+ local val2 = {4, 7}
+ eq(NIL, request('window_set_var', 0, 'lua', val1))
+ eq(val1, request('window_set_var', 0, 'lua', val2))
+ end)
+
+ it('window_del_var returns the old value', function()
+ local val1 = {1, 2, {['3'] = 1}}
+ local val2 = {4, 7}
+ eq(NIL, request('window_set_var', 0, 'lua', val1))
+ eq(val1, request('window_set_var', 0, 'lua', val2))
+ eq(val2, request('window_del_var', 0, 'lua'))
+ end)
end)
describe('{get,set}_option', function()
@@ -152,17 +169,17 @@ describe('window_* functions', function()
describe('get_position', function()
it('works', function()
- local height = window('get_height', nvim('get_windows')[1])
- local width = window('get_width', nvim('get_windows')[1])
+ local height = window('get_height', nvim('list_wins')[1])
+ local width = window('get_width', nvim('list_wins')[1])
nvim('command', 'split')
nvim('command', 'vsplit')
- eq({0, 0}, window('get_position', nvim('get_windows')[1]))
+ eq({0, 0}, window('get_position', nvim('list_wins')[1]))
local vsplit_pos = math.floor(width / 2)
local split_pos = math.floor(height / 2)
local win2row, win2col =
- unpack(window('get_position', nvim('get_windows')[2]))
+ unpack(window('get_position', nvim('list_wins')[2]))
local win3row, win3col =
- unpack(window('get_position', nvim('get_windows')[3]))
+ unpack(window('get_position', nvim('list_wins')[3]))
eq(0, win2row)
eq(0, win3col)
ok(vsplit_pos - 1 <= win2col and win2col <= vsplit_pos + 1)
@@ -175,19 +192,19 @@ describe('window_* functions', function()
nvim('command', 'tabnew')
nvim('command', 'vsplit')
eq(window('get_tabpage',
- nvim('get_windows')[1]), nvim('get_tabpages')[1])
+ nvim('list_wins')[1]), nvim('list_tabpages')[1])
eq(window('get_tabpage',
- nvim('get_windows')[2]), nvim('get_tabpages')[2])
+ nvim('list_wins')[2]), nvim('list_tabpages')[2])
eq(window('get_tabpage',
- nvim('get_windows')[3]), nvim('get_tabpages')[2])
+ nvim('list_wins')[3]), nvim('list_tabpages')[2])
end)
end)
describe('is_valid', function()
it('works', function()
nvim('command', 'split')
- local win = nvim('get_windows')[2]
- nvim('set_current_window', win)
+ local win = nvim('list_wins')[2]
+ nvim('set_current_win', win)
ok(window('is_valid', win))
nvim('command', 'close')
ok(not window('is_valid', win))
diff --git a/test/functional/autocmd/tabnew_spec.lua b/test/functional/autocmd/tabnew_spec.lua
index 8c94dee49b..2148b21832 100644
--- a/test/functional/autocmd/tabnew_spec.lua
+++ b/test/functional/autocmd/tabnew_spec.lua
@@ -5,6 +5,8 @@ local command = helpers.command
local eq = helpers.eq
local eval = helpers.eval
+if helpers.pending_win32(pending) then return end
+
describe('autocmd TabNew', function()
before_each(clear)
diff --git a/test/functional/autocmd/tabnewentered_spec.lua b/test/functional/autocmd/tabnewentered_spec.lua
index 7044307399..f033bd5fe4 100644
--- a/test/functional/autocmd/tabnewentered_spec.lua
+++ b/test/functional/autocmd/tabnewentered_spec.lua
@@ -1,6 +1,8 @@
local helpers = require('test.functional.helpers')(after_each)
local clear, nvim, eq = helpers.clear, helpers.nvim, helpers.eq
+if helpers.pending_win32(pending) then return end
+
describe('TabNewEntered', function()
describe('au TabNewEntered', function()
describe('with * as <afile>', function()
diff --git a/test/functional/autocmd/termclose_spec.lua b/test/functional/autocmd/termclose_spec.lua
index 02ea0dbd95..6871711058 100644
--- a/test/functional/autocmd/termclose_spec.lua
+++ b/test/functional/autocmd/termclose_spec.lua
@@ -5,6 +5,8 @@ local clear, execute, feed, nvim, nvim_dir = helpers.clear,
helpers.execute, helpers.feed, helpers.nvim, helpers.nvim_dir
local eval, eq = helpers.eval, helpers.eq
+if helpers.pending_win32(pending) then return end
+
describe('TermClose event', function()
local screen
before_each(function()
@@ -12,7 +14,7 @@ describe('TermClose event', function()
nvim('set_option', 'shell', nvim_dir .. '/shell-test')
nvim('set_option', 'shellcmdflag', 'EXE')
screen = Screen.new(20, 4)
- screen:attach(false)
+ screen:attach({rgb=false})
end)
it('works as expected', function()
diff --git a/test/functional/clipboard/clipboard_provider_spec.lua b/test/functional/clipboard/clipboard_provider_spec.lua
index 15977b9777..6424b39e13 100644
--- a/test/functional/clipboard/clipboard_provider_spec.lua
+++ b/test/functional/clipboard/clipboard_provider_spec.lua
@@ -5,6 +5,8 @@ local Screen = require('test.functional.ui.screen')
local clear, feed, insert = helpers.clear, helpers.feed, helpers.insert
local execute, expect, eq, eval = helpers.execute, helpers.expect, helpers.eq, helpers.eval
+if helpers.pending_win32(pending) then return end
+
local function basic_register_test(noblock)
insert("some words")
diff --git a/test/functional/core/job_spec.lua b/test/functional/core/job_spec.lua
index 921bf1655e..adbe17d4b5 100644
--- a/test/functional/core/job_spec.lua
+++ b/test/functional/core/job_spec.lua
@@ -8,6 +8,7 @@ local clear, eq, eval, execute, feed, insert, neq, next_msg, nvim,
local command = helpers.command
local Screen = require('test.functional.ui.screen')
+if helpers.pending_win32(pending) then return end
describe('jobs', function()
local channel
@@ -90,7 +91,7 @@ describe('jobs', function()
it('preserves NULs', function()
-- Make a file with NULs in it.
- local filename = os.tmpname()
+ local filename = helpers.tmpname()
write_file(filename, "abc\0def\n")
nvim('command', "let j = jobstart(['cat', '"..filename.."'], g:job_opts)")
@@ -108,8 +109,8 @@ describe('jobs', function()
it("will not buffer data if it doesn't end in newlines", function()
if os.getenv("TRAVIS") and os.getenv("CC") == "gcc-4.9"
and helpers.os_name() == "osx" then
- -- XXX: Hangs Travis OSX since e9061117a5b8f195c3f26a5cb94e18ddd7752d86.
- pending("[Hangs on Travis OSX. #5002]", function() end)
+ -- XXX: Hangs Travis macOS since e9061117a5b8f195c3f26a5cb94e18ddd7752d86.
+ pending("[Hangs on Travis macOS. #5002]", function() end)
return
end
diff --git a/test/functional/eval/api_functions_spec.lua b/test/functional/eval/api_functions_spec.lua
new file mode 100644
index 0000000000..2ef67e7808
--- /dev/null
+++ b/test/functional/eval/api_functions_spec.lua
@@ -0,0 +1,148 @@
+local helpers = require('test.functional.helpers')(after_each)
+local Screen = require('test.functional.ui.screen')
+local lfs = require('lfs')
+local neq, eq, execute = helpers.neq, helpers.eq, helpers.execute
+local clear, curbufmeths = helpers.clear, helpers.curbufmeths
+local exc_exec, expect, eval = helpers.exc_exec, helpers.expect, helpers.eval
+local insert = helpers.insert
+
+describe('api functions', function()
+ before_each(clear)
+
+ it("work", function()
+ execute("call nvim_command('let g:test = 1')")
+ eq(1, eval("nvim_get_var('test')"))
+
+ local buf = eval("nvim_get_current_buf()")
+ execute("call nvim_buf_set_lines("..buf..", 0, -1, v:true, ['aa', 'bb'])")
+ expect([[
+ aa
+ bb]])
+
+ execute("call nvim_win_set_cursor(0, [1, 1])")
+ execute("call nvim_input('ax<esc>')")
+ expect([[
+ aax
+ bb]])
+ end)
+
+ it("throw errors for invalid arguments", function()
+ local err = exc_exec('call nvim_get_current_buf("foo")')
+ eq('Vim(call):E118: Too many arguments for function: nvim_get_current_buf', err)
+
+ err = exc_exec('call nvim_set_option("hlsearch")')
+ eq('Vim(call):E119: Not enough arguments for function: nvim_set_option', err)
+
+ err = exc_exec('call nvim_buf_set_lines(1, 0, -1, [], ["list"])')
+ eq('Vim(call):Wrong type for argument 4, expecting Boolean', err)
+
+ err = exc_exec('call nvim_buf_set_lines(0, 0, -1, v:true, "string")')
+ eq('Vim(call):Wrong type for argument 5, expecting ArrayOf(String)', err)
+
+ err = exc_exec('call nvim_buf_get_number("0")')
+ eq('Vim(call):Wrong type for argument 1, expecting Buffer', err)
+
+ err = exc_exec('call nvim_buf_line_count(17)')
+ eq('Vim(call):Invalid buffer id', err)
+ end)
+
+
+ it("use buffer numbers and windows ids as handles", function()
+ local screen = Screen.new(40, 8)
+ screen:attach()
+ local bnr = eval("bufnr('')")
+ local bhnd = eval("nvim_get_current_buf()")
+ local wid = eval("win_getid()")
+ local whnd = eval("nvim_get_current_win()")
+ eq(bnr, bhnd)
+ eq(wid, whnd)
+
+ execute("new") -- creates new buffer and new window
+ local bnr2 = eval("bufnr('')")
+ local bhnd2 = eval("nvim_get_current_buf()")
+ local wid2 = eval("win_getid()")
+ local whnd2 = eval("nvim_get_current_win()")
+ eq(bnr2, bhnd2)
+ eq(wid2, whnd2)
+ neq(bnr, bnr2)
+ neq(wid, wid2)
+ -- 0 is synonymous to the current buffer
+ eq(bnr2, eval("nvim_buf_get_number(0)"))
+
+ execute("bn") -- show old buffer in new window
+ eq(bnr, eval("nvim_get_current_buf()"))
+ eq(bnr, eval("bufnr('')"))
+ eq(bnr, eval("nvim_buf_get_number(0)"))
+ eq(wid2, eval("win_getid()"))
+ eq(whnd2, eval("nvim_get_current_win()"))
+ end)
+
+ it("get_lines and set_lines use NL to represent NUL", function()
+ curbufmeths.set_lines(0, -1, true, {"aa\0", "b\0b"})
+ eq({'aa\n', 'b\nb'}, eval("nvim_buf_get_lines(0, 0, -1, 1)"))
+
+ execute('call nvim_buf_set_lines(0, 1, 2, v:true, ["xx", "\\nyy"])')
+ eq({'aa\0', 'xx', '\0yy'}, curbufmeths.get_lines(0, -1, 1))
+ end)
+
+ it("that are FUNC_ATTR_NOEVAL cannot be called", function()
+ -- Deprecated vim_ prefix is not exported.
+ local err = exc_exec('call vim_get_current_buffer("foo")')
+ eq('Vim(call):E117: Unknown function: vim_get_current_buffer', err)
+
+ -- Deprecated buffer_ prefix is not exported.
+ err = exc_exec('call buffer_line_count(0)')
+ eq('Vim(call):E117: Unknown function: buffer_line_count', err)
+
+ -- Functions deprecated before the api functions became available
+ -- in vimscript are not exported.
+ err = exc_exec('call buffer_get_line(0, 1)')
+ eq('Vim(call):E117: Unknown function: buffer_get_line', err)
+
+ -- some api functions are only useful from a msgpack-rpc channel
+ err = exc_exec('call nvim_subscribe("fancyevent")')
+ eq('Vim(call):E117: Unknown function: nvim_subscribe', err)
+ end)
+
+ it('have metadata accessible with api_info()', function()
+ local api_keys = eval("sort(keys(api_info()))")
+ eq({'error_types', 'functions', 'types'}, api_keys)
+ end)
+
+ it('are highlighted by vim.vim syntax file', function()
+ if lfs.attributes("build/runtime/syntax/vim/generated.vim",'uid') == nil then
+ pending("runtime was not built, skipping test")
+ return
+ end
+ local screen = Screen.new(40, 8)
+ screen:attach()
+ screen:set_default_attr_ids({
+ [1] = {bold = true, foreground = Screen.colors.Brown},
+ [2] = {foreground = Screen.colors.DarkCyan},
+ [3] = {foreground = Screen.colors.SlateBlue},
+ [4] = {foreground = Screen.colors.Fuchsia},
+ [5] = {bold = true, foreground = Screen.colors.Blue},
+ })
+
+ execute("set ft=vim")
+ execute("let &rtp='build/runtime/,'.&rtp")
+ execute("syntax on")
+ insert([[
+ call bufnr('%')
+ call nvim_input('typing...')
+ call not_a_function(42)]])
+
+ screen:expect([[
+ {1:call} {2:bufnr}{3:(}{4:'%'}{3:)} |
+ {1:call} {2:nvim_input}{3:(}{4:'typing...'}{3:)} |
+ {1:call} not_a_function{3:(}{4:42}{3:^)} |
+ {5:~ }|
+ {5:~ }|
+ {5:~ }|
+ {5:~ }|
+ |
+ ]])
+ screen:detach()
+ end)
+
+end)
diff --git a/test/functional/eval/server_spec.lua b/test/functional/eval/server_spec.lua
index 0fd55ce2f9..d2c985e894 100644
--- a/test/functional/eval/server_spec.lua
+++ b/test/functional/eval/server_spec.lua
@@ -4,6 +4,8 @@ local nvim, eq, neq, eval = helpers.nvim, helpers.eq, helpers.neq, helpers.eval
local clear, funcs, meths = helpers.clear, helpers.funcs, helpers.meths
local os_name = helpers.os_name
+if helpers.pending_win32(pending) then return end
+
describe('serverstart(), serverstop()', function()
before_each(clear)
diff --git a/test/functional/ex_cmds/cd_spec.lua b/test/functional/ex_cmds/cd_spec.lua
index fcd826c25d..5bf4d22d0f 100644
--- a/test/functional/ex_cmds/cd_spec.lua
+++ b/test/functional/ex_cmds/cd_spec.lua
@@ -9,6 +9,8 @@ local clear = helpers.clear
local execute = helpers.execute
local exc_exec = helpers.exc_exec
+if helpers.pending_win32(pending) then return end
+
-- These directories will be created for testing
local directories = {
tab = 'Xtest-functional-ex_cmds-cd_spec.tab', -- Tab
@@ -138,6 +140,27 @@ for _, cmd in ipairs {'cd', 'chdir'} do
end)
end)
+ describe('Local directory gets inherited', function()
+ it('by tabs', function()
+ local globalDir = directories.start
+
+ -- Create a new tab and change directory
+ execute('tabnew')
+ execute('silent t' .. cmd .. ' ' .. directories.tab)
+ eq(globalDir .. '/' .. directories.tab, tcwd())
+
+ -- Create a new tab and verify it has inherited the directory
+ execute('tabnew')
+ eq(globalDir .. '/' .. directories.tab, tcwd())
+
+ -- Change tab and change back, verify that directories are correct
+ execute('tabnext')
+ eq(globalDir, tcwd())
+ execute('tabprevious')
+ eq(globalDir .. '/' .. directories.tab, tcwd())
+ end)
+ end)
+
it('works', function()
local globalDir = directories.start
-- Create a new tab first and verify that is has the same working dir
@@ -246,3 +269,21 @@ for _, cmd in ipairs {'getcwd', 'haslocaldir'} do
end)
end
+describe("getcwd()", function ()
+ before_each(function()
+ clear()
+ lfs.mkdir(directories.global)
+ end)
+
+ after_each(function()
+ helpers.rmdir(directories.global)
+ end)
+
+ it("returns empty string if working directory does not exist", function()
+ execute("cd "..directories.global)
+ execute("call delete('../"..directories.global.."', 'd')")
+ eq("", helpers.eval("getcwd()"))
+ end)
+end)
+
+
diff --git a/test/functional/ex_cmds/profile_spec.lua b/test/functional/ex_cmds/profile_spec.lua
index d390806679..f185db192a 100644
--- a/test/functional/ex_cmds/profile_spec.lua
+++ b/test/functional/ex_cmds/profile_spec.lua
@@ -5,9 +5,9 @@ local helpers = require('test.functional.helpers')(after_each)
local eval = helpers.eval
local command = helpers.command
local eq, neq = helpers.eq, helpers.neq
-local tempfile = os.tmpname()
+local tempfile = helpers.tmpname()
--- os.tmpname() also creates the file on POSIX systems. Remove it again.
+-- tmpname() also creates the file on POSIX systems. Remove it again.
-- We just need the name, ignoring any race conditions.
if lfs.attributes(tempfile, 'uid') then
os.remove(tempfile)
diff --git a/test/functional/ex_cmds/recover_spec.lua b/test/functional/ex_cmds/recover_spec.lua
index 60673d25ef..0c97857180 100644
--- a/test/functional/ex_cmds/recover_spec.lua
+++ b/test/functional/ex_cmds/recover_spec.lua
@@ -6,6 +6,8 @@ local execute, eq, clear, eval, feed, expect, source =
helpers.execute, helpers.eq, helpers.clear, helpers.eval, helpers.feed,
helpers.expect, helpers.source
+if helpers.pending_win32(pending) then return end
+
describe(':recover', function()
before_each(clear)
diff --git a/test/functional/ex_cmds/write_spec.lua b/test/functional/ex_cmds/write_spec.lua
index b38ae29f7d..c1bc5d3140 100644
--- a/test/functional/ex_cmds/write_spec.lua
+++ b/test/functional/ex_cmds/write_spec.lua
@@ -5,6 +5,8 @@ local eq, eval, clear, write_file, execute, source =
helpers.eq, helpers.eval, helpers.clear, helpers.write_file,
helpers.execute, helpers.source
+if helpers.pending_win32(pending) then return end
+
describe(':write', function()
after_each(function()
os.remove('test_bkc_file.txt')
diff --git a/test/functional/helpers.lua b/test/functional/helpers.lua
index 2d54d23254..f6d09e6139 100644
--- a/test/functional/helpers.lua
+++ b/test/functional/helpers.lua
@@ -133,11 +133,11 @@ local function stop()
end
local function nvim_command(cmd)
- request('vim_command', cmd)
+ request('nvim_command', cmd)
end
local function nvim_eval(expr)
- return request('vim_eval', expr)
+ return request('nvim_eval', expr)
end
local os_name = (function()
@@ -157,12 +157,12 @@ local os_name = (function()
end)()
local function nvim_call(name, ...)
- return request('vim_call_function', name, {...})
+ return request('nvim_call_function', name, {...})
end
local function nvim_feed(input)
while #input > 0 do
- local written = request('vim_input', input)
+ local written = request('nvim_input', input)
input = input:sub(written + 1)
end
end
@@ -291,43 +291,82 @@ local function write_file(name, text, dont_dedent)
file:close()
end
-local function source(code)
- local tmpname = os.tmpname()
- if os_name() == 'osx' and string.match(tmpname, '^/tmp') then
- tmpname = '/private'..tmpname
+-- Tries to get platform name, from $SYSTEM_NAME, uname,
+-- fallback is 'Windows'
+local uname = (function()
+ local platform = nil
+ return (function()
+ if platform then
+ return platform
+ end
+
+ platform = os.getenv("SYSTEM_NAME")
+ if platform then
+ return platform
+ end
+
+ local status, f = pcall(io.popen, "uname -s")
+ if status then
+ platform = f:read("*l")
+ else
+ platform = 'Windows'
+ end
+ return platform
+ end)
+end)()
+
+local function tmpname()
+ local fname = os.tmpname()
+ if uname() == 'Windows' and fname:sub(1, 2) == '\\s' then
+ -- In Windows tmpname() returns a filename starting with
+ -- special sequence \s, prepend $TEMP path
+ local tmpdir = os.getenv('TEMP')
+ return tmpdir..fname
+ elseif fname:match('^/tmp') and uname() == 'Darwin' then
+ -- In OS X /tmp links to /private/tmp
+ return '/private'..fname
+ else
+ return fname
end
- write_file(tmpname, code)
- nvim_command('source '..tmpname)
- os.remove(tmpname)
- return tmpname
+end
+
+local function source(code)
+ local fname = tmpname()
+ write_file(fname, code)
+ nvim_command('source '..fname)
+ os.remove(fname)
+ return fname
end
local function nvim(method, ...)
- return request('vim_'..method, ...)
+ return request('nvim_'..method, ...)
+end
+
+local function ui(method, ...)
+ return request('nvim_ui_'..method, ...)
end
local function nvim_async(method, ...)
- session:notify('vim_'..method, ...)
+ session:notify('nvim_'..method, ...)
end
local function buffer(method, ...)
- return request('buffer_'..method, ...)
+ return request('nvim_buf_'..method, ...)
end
local function window(method, ...)
- return request('window_'..method, ...)
+ return request('nvim_win_'..method, ...)
end
local function tabpage(method, ...)
- return request('tabpage_'..method, ...)
+ return request('nvim_tabpage_'..method, ...)
end
local function curbuf(method, ...)
- local buf = nvim('get_current_buffer')
if not method then
- return buf
+ return nvim('get_current_buf')
end
- return buffer(method, buf, ...)
+ return buffer(method, 0, ...)
end
local function wait()
@@ -347,19 +386,17 @@ local function curbuf_contents()
end
local function curwin(method, ...)
- local win = nvim('get_current_window')
if not method then
- return win
+ return nvim('get_current_win')
end
- return window(method, win, ...)
+ return window(method, 0, ...)
end
local function curtab(method, ...)
- local tab = nvim('get_current_tabpage')
if not method then
- return tab
+ return nvim('get_current_tabpage')
end
- return tabpage(method, tab, ...)
+ return tabpage(method, 0, ...)
end
local function expect(contents)
@@ -430,8 +467,23 @@ local function create_callindex(func)
return table
end
+-- Helper to skip tests. Returns true in Windows systems.
+-- pending_func is pending() from busted
+local function pending_win32(pending_func)
+ clear()
+ if uname() == 'Windows' then
+ if pending_func ~= nil then
+ pending_func('FIXME: Windows', function() end)
+ end
+ return true
+ else
+ return false
+ end
+end
+
local funcs = create_callindex(nvim_call)
local meths = create_callindex(nvim)
+local uimeths = create_callindex(ui)
local bufmeths = create_callindex(buffer)
local winmeths = create_callindex(window)
local tabmeths = create_callindex(tabpage)
@@ -490,9 +542,12 @@ return function(after_each)
bufmeths = bufmeths,
winmeths = winmeths,
tabmeths = tabmeths,
+ uimeths = uimeths,
curbufmeths = curbufmeths,
curwinmeths = curwinmeths,
curtabmeths = curtabmeths,
+ pending_win32 = pending_win32,
+ tmpname = tmpname,
NIL = mpack.NIL,
}
end
diff --git a/test/functional/legacy/011_autocommands_spec.lua b/test/functional/legacy/011_autocommands_spec.lua
index 6e613c85df..ba899f8119 100644
--- a/test/functional/legacy/011_autocommands_spec.lua
+++ b/test/functional/legacy/011_autocommands_spec.lua
@@ -18,6 +18,8 @@ local clear, execute, expect, eq, neq, dedent, write_file, feed =
helpers.clear, helpers.execute, helpers.expect, helpers.eq, helpers.neq,
helpers.dedent, helpers.write_file, helpers.feed
+if helpers.pending_win32(pending) then return end
+
local function has_gzip()
return os.execute('gzip --help >/dev/null 2>&1') == 0
end
diff --git a/test/functional/legacy/025_jump_tag_hidden_spec.lua b/test/functional/legacy/025_jump_tag_hidden_spec.lua
index 7b7ddb07b9..99224f9e08 100644
--- a/test/functional/legacy/025_jump_tag_hidden_spec.lua
+++ b/test/functional/legacy/025_jump_tag_hidden_spec.lua
@@ -5,6 +5,8 @@ local helpers = require('test.functional.helpers')(after_each)
local clear, feed, insert = helpers.clear, helpers.feed, helpers.insert
local execute, expect = helpers.execute, helpers.expect
+if helpers.pending_win32(pending) then return end
+
describe('jump to a tag with hidden set', function()
setup(clear)
diff --git a/test/functional/legacy/030_fileformats_spec.lua b/test/functional/legacy/030_fileformats_spec.lua
index 9bc62a375e..5fd78b2c59 100644
--- a/test/functional/legacy/030_fileformats_spec.lua
+++ b/test/functional/legacy/030_fileformats_spec.lua
@@ -4,6 +4,8 @@ local helpers = require('test.functional.helpers')(after_each)
local feed, clear, execute = helpers.feed, helpers.clear, helpers.execute
local eq, write_file = helpers.eq, helpers.write_file
+if helpers.pending_win32(pending) then return end
+
describe('fileformats option', function()
setup(function()
clear()
diff --git a/test/functional/legacy/036_regexp_character_classes_spec.lua b/test/functional/legacy/036_regexp_character_classes_spec.lua
index 9e67bb9429..15287b9901 100644
--- a/test/functional/legacy/036_regexp_character_classes_spec.lua
+++ b/test/functional/legacy/036_regexp_character_classes_spec.lua
@@ -3,7 +3,6 @@
local helpers = require('test.functional.helpers')(after_each)
local clear, execute, expect = helpers.clear, helpers.execute, helpers.expect
local source, write_file = helpers.source, helpers.write_file
-local os_name = helpers.os_name
local function sixlines(text)
local result = ''
@@ -14,19 +13,16 @@ local function sixlines(text)
end
local function diff(text, nodedent)
- local tmpname = os.tmpname()
- if os_name() == 'osx' and string.match(tmpname, '^/tmp') then
- tmpname = '/private'..tmpname
- end
- execute('w! '..tmpname)
+ local fname = helpers.tmpname()
+ execute('w! '..fname)
helpers.wait()
- local data = io.open(tmpname):read('*all')
+ local data = io.open(fname):read('*all')
if nodedent then
helpers.eq(text, data)
else
helpers.eq(helpers.dedent(text), data)
end
- os.remove(tmpname)
+ os.remove(fname)
end
describe('character classes in regexp', function()
diff --git a/test/functional/legacy/051_highlight_spec.lua b/test/functional/legacy/051_highlight_spec.lua
index 5bf3b51b90..ef392d8c67 100644
--- a/test/functional/legacy/051_highlight_spec.lua
+++ b/test/functional/legacy/051_highlight_spec.lua
@@ -7,6 +7,8 @@ local clear, feed = helpers.clear, helpers.feed
local execute, expect = helpers.execute, helpers.expect
local wait = helpers.wait
+if helpers.pending_win32(pending) then return end
+
describe(':highlight', function()
setup(clear)
diff --git a/test/functional/legacy/059_utf8_spell_checking_spec.lua b/test/functional/legacy/059_utf8_spell_checking_spec.lua
index c44ab44b3c..2fb8f3557d 100644
--- a/test/functional/legacy/059_utf8_spell_checking_spec.lua
+++ b/test/functional/legacy/059_utf8_spell_checking_spec.lua
@@ -5,6 +5,8 @@ local feed, insert, source = helpers.feed, helpers.insert, helpers.source
local clear, execute, expect = helpers.clear, helpers.execute, helpers.expect
local write_file, call = helpers.write_file, helpers.call
+if helpers.pending_win32(pending) then return end
+
local function write_latin1(name, text)
text = call('iconv', text, 'utf-8', 'latin-1')
write_file(name, text)
diff --git a/test/functional/legacy/093_mksession_cursor_cols_latin1_spec.lua b/test/functional/legacy/093_mksession_cursor_cols_latin1_spec.lua
index 719ce25099..40be7dcca4 100644
--- a/test/functional/legacy/093_mksession_cursor_cols_latin1_spec.lua
+++ b/test/functional/legacy/093_mksession_cursor_cols_latin1_spec.lua
@@ -7,6 +7,8 @@ local helpers = require('test.functional.helpers')(after_each)
local feed, insert = helpers.feed, helpers.insert
local clear, execute, expect = helpers.clear, helpers.execute, helpers.expect
+if helpers.pending_win32(pending) then return end
+
describe('store cursor position in session file in Latin-1', function()
setup(clear)
diff --git a/test/functional/legacy/097_glob_path_spec.lua b/test/functional/legacy/097_glob_path_spec.lua
index a6c146891a..23f1427cb5 100644
--- a/test/functional/legacy/097_glob_path_spec.lua
+++ b/test/functional/legacy/097_glob_path_spec.lua
@@ -6,6 +6,8 @@ local helpers = require('test.functional.helpers')(after_each)
local clear = helpers.clear
local execute, expect = helpers.execute, helpers.expect
+if helpers.pending_win32(pending) then return end
+
describe('glob() and globpath()', function()
setup(clear)
diff --git a/test/functional/legacy/107_adjust_window_and_contents_spec.lua b/test/functional/legacy/107_adjust_window_and_contents_spec.lua
index ce8d967e00..610bac7f21 100644
--- a/test/functional/legacy/107_adjust_window_and_contents_spec.lua
+++ b/test/functional/legacy/107_adjust_window_and_contents_spec.lua
@@ -5,6 +5,8 @@ local Screen = require('test.functional.ui.screen')
local insert = helpers.insert
local clear, execute = helpers.clear, helpers.execute
+if helpers.pending_win32(pending) then return end
+
describe('107', function()
setup(clear)
diff --git a/test/functional/legacy/arglist_spec.lua b/test/functional/legacy/arglist_spec.lua
index c128aaf115..b86d3f0aea 100644
--- a/test/functional/legacy/arglist_spec.lua
+++ b/test/functional/legacy/arglist_spec.lua
@@ -4,6 +4,8 @@ local helpers = require('test.functional.helpers')(after_each)
local clear, execute, eq = helpers.clear, helpers.execute, helpers.eq
local eval, exc_exec, neq = helpers.eval, helpers.exc_exec, helpers.neq
+if helpers.pending_win32(pending) then return end
+
describe('argument list commands', function()
before_each(clear)
diff --git a/test/functional/legacy/delete_spec.lua b/test/functional/legacy/delete_spec.lua
index 42238b3a9e..cd19e31a79 100644
--- a/test/functional/legacy/delete_spec.lua
+++ b/test/functional/legacy/delete_spec.lua
@@ -2,6 +2,8 @@ local helpers = require('test.functional.helpers')(after_each)
local clear, source = helpers.clear, helpers.source
local eq, eval, execute = helpers.eq, helpers.eval, helpers.execute
+if helpers.pending_win32(pending) then return end
+
describe('Test for delete()', function()
before_each(clear)
diff --git a/test/functional/legacy/file_perm_spec.lua b/test/functional/legacy/file_perm_spec.lua
index 9ebbfd25e4..77e82352c5 100644
--- a/test/functional/legacy/file_perm_spec.lua
+++ b/test/functional/legacy/file_perm_spec.lua
@@ -6,7 +6,7 @@ local clear, call, eq = helpers.clear, helpers.call, helpers.eq
local neq, exc_exec = helpers.neq, helpers.exc_exec
describe('Test getting and setting file permissions', function()
- local tempfile = os.tmpname()
+ local tempfile = helpers.tmpname()
before_each(function()
os.remove(tempfile)
diff --git a/test/functional/legacy/fixeol_spec.lua b/test/functional/legacy/fixeol_spec.lua
index bba1415535..1e9e832536 100644
--- a/test/functional/legacy/fixeol_spec.lua
+++ b/test/functional/legacy/fixeol_spec.lua
@@ -4,6 +4,8 @@ local helpers = require('test.functional.helpers')(after_each)
local feed = helpers.feed
local clear, execute, expect = helpers.clear, helpers.execute, helpers.expect
+if helpers.pending_win32(pending) then return end
+
describe('fixeol', function()
local function rmtestfiles()
os.remove('test.out')
diff --git a/test/functional/legacy/fnamemodify_spec.lua b/test/functional/legacy/fnamemodify_spec.lua
index f614b07b36..d8ecbfe058 100644
--- a/test/functional/legacy/fnamemodify_spec.lua
+++ b/test/functional/legacy/fnamemodify_spec.lua
@@ -4,6 +4,8 @@ local helpers = require('test.functional.helpers')(after_each)
local clear, source = helpers.clear, helpers.source
local call, eq, nvim = helpers.call, helpers.eq, helpers.meths
+if helpers.pending_win32(pending) then return end
+
local function expected_empty()
eq({}, nvim.get_vvar('errors'))
end
diff --git a/test/functional/legacy/getcwd_spec.lua b/test/functional/legacy/getcwd_spec.lua
index 3bb9930b74..dcb56eb242 100644
--- a/test/functional/legacy/getcwd_spec.lua
+++ b/test/functional/legacy/getcwd_spec.lua
@@ -4,6 +4,8 @@ local helpers = require('test.functional.helpers')(after_each)
local eq, eval, source = helpers.eq, helpers.eval, helpers.source
local call, clear, execute = helpers.call, helpers.clear, helpers.execute
+if helpers.pending_win32(pending) then return end
+
describe('getcwd', function()
before_each(clear)
diff --git a/test/functional/legacy/packadd_spec.lua b/test/functional/legacy/packadd_spec.lua
index a6979d8eb2..68bdbf5257 100644
--- a/test/functional/legacy/packadd_spec.lua
+++ b/test/functional/legacy/packadd_spec.lua
@@ -9,6 +9,8 @@ local function expected_empty()
eq({}, nvim.get_vvar('errors'))
end
+if helpers.pending_win32(pending) then return end
+
describe('packadd', function()
before_each(function()
clear()
diff --git a/test/functional/legacy/wordcount_spec.lua b/test/functional/legacy/wordcount_spec.lua
index 300a777772..171ec3de92 100644
--- a/test/functional/legacy/wordcount_spec.lua
+++ b/test/functional/legacy/wordcount_spec.lua
@@ -5,6 +5,8 @@ local feed, insert, source = helpers.feed, helpers.insert, helpers.source
local clear, execute = helpers.clear, helpers.execute
local eq, eval = helpers.eq, helpers.eval
+if helpers.pending_win32(pending) then return end
+
describe('wordcount', function()
before_each(clear)
diff --git a/test/functional/normal/K_spec.lua b/test/functional/normal/K_spec.lua
index af0f82ef9a..43e598633c 100644
--- a/test/functional/normal/K_spec.lua
+++ b/test/functional/normal/K_spec.lua
@@ -2,6 +2,8 @@ local helpers = require('test.functional.helpers')(after_each)
local eq, clear, eval, feed =
helpers.eq, helpers.clear, helpers.eval, helpers.feed
+if helpers.pending_win32(pending) then return end
+
describe('K', function()
local test_file = 'K_spec_out'
before_each(function()
diff --git a/test/functional/options/autochdir_spec.lua b/test/functional/options/autochdir_spec.lua
index 0e293761ad..209531515c 100644
--- a/test/functional/options/autochdir_spec.lua
+++ b/test/functional/options/autochdir_spec.lua
@@ -3,6 +3,8 @@ local clear = helpers.clear
local eq = helpers.eq
local getcwd = helpers.funcs.getcwd
+if helpers.pending_win32(pending) then return end
+
describe("'autochdir'", function()
it('given on the shell gets processed properly', function()
local targetdir = 'test/functional/fixtures'
diff --git a/test/functional/options/defaults_spec.lua b/test/functional/options/defaults_spec.lua
index a131f72cf6..1ae855f26c 100644
--- a/test/functional/options/defaults_spec.lua
+++ b/test/functional/options/defaults_spec.lua
@@ -9,6 +9,8 @@ local eval = helpers.eval
local eq = helpers.eq
local neq = helpers.neq
+if helpers.pending_win32(pending) then return end
+
local function init_session(...)
local args = { helpers.nvim_prog, '-i', 'NONE', '--embed',
'--cmd', 'set shortmess+=I background=light noswapfile noautoindent',
diff --git a/test/functional/options/shortmess_spec.lua b/test/functional/options/shortmess_spec.lua
index d531e47e28..22e8a39b79 100644
--- a/test/functional/options/shortmess_spec.lua
+++ b/test/functional/options/shortmess_spec.lua
@@ -2,6 +2,8 @@ local helpers = require('test.functional.helpers')(after_each)
local Screen = require('test.functional.ui.screen')
local clear, execute = helpers.clear, helpers.execute
+if helpers.pending_win32(pending) then return end
+
describe("'shortmess'", function()
local screen
diff --git a/test/functional/plugin/health_spec.lua b/test/functional/plugin/health_spec.lua
index a9665cd751..4bcaab009f 100644
--- a/test/functional/plugin/health_spec.lua
+++ b/test/functional/plugin/health_spec.lua
@@ -34,9 +34,9 @@ describe('health.vim', function()
## Baz
- WARNING: Zim
- - SUGGESTIONS:
- - suggestion 1
- - suggestion 2]]),
+ - SUGGESTIONS:
+ - suggestion 1
+ - suggestion 2]]),
result)
end)
@@ -45,9 +45,9 @@ describe('health.vim', function()
it("concatenates multiple reports", function()
helpers.execute("CheckHealth success1 success2")
helpers.expect([[
+
health#success1#check
================================================================================
-
## report 1
- SUCCESS: everything is fine
@@ -56,26 +56,30 @@ describe('health.vim', function()
health#success2#check
================================================================================
-
## another 1
- - SUCCESS: ok]])
+ - SUCCESS: ok
+ ]])
end)
it("gracefully handles broken healthcheck", function()
helpers.execute("CheckHealth broken")
helpers.expect([[
+
health#broken#check
================================================================================
- ERROR: Failed to run healthcheck for "broken" plugin. Exception:
- caused an error]])
+ caused an error
+ ]])
end)
it("gracefully handles invalid healthcheck", function()
helpers.execute("CheckHealth non_existent_healthcheck")
helpers.expect([[
+
health#non_existent_healthcheck#check
================================================================================
- - ERROR: No healthcheck found for "non_existent_healthcheck" plugin.]])
+ - ERROR: No healthcheck found for "non_existent_healthcheck" plugin.
+ ]])
end)
end)
end)
diff --git a/test/functional/plugin/shada_spec.lua b/test/functional/plugin/shada_spec.lua
index e18e9ef428..b1209a22e9 100644
--- a/test/functional/plugin/shada_spec.lua
+++ b/test/functional/plugin/shada_spec.lua
@@ -43,6 +43,8 @@ local wshada, _, fname = get_shada_rw('Xtest-functional-plugin-shada.shada')
local wshada_tmp, _, fname_tmp =
get_shada_rw('Xtest-functional-plugin-shada.shada.tmp.f')
+if helpers.pending_win32(pending) then return end
+
describe('In autoload/shada.vim', function()
local epoch = os.date('%Y-%m-%dT%H:%M:%S', 0)
before_each(function()
@@ -2461,17 +2463,17 @@ describe('ftplugin/shada.vim', function()
nvim_command('setlocal filetype=shada')
funcs.setline(1, ' Replacement with timestamp ' .. epoch)
nvim_feed('ggA:\027')
- eq('Replacement with timestamp ' .. epoch .. ':', curbuf('get_line', 0))
+ eq('Replacement with timestamp ' .. epoch .. ':', curbuf('get_lines', 0, 1, true)[1])
nvim_feed('o-\027')
- eq(' -', curbuf('get_line', 1))
+ eq({' -'}, curbuf('get_lines', 1, 2, true))
nvim_feed('ggO+\027')
- eq('+', curbuf('get_line', 0))
+ eq({'+'}, curbuf('get_lines', 0, 1, true))
nvim_feed('GO*\027')
- eq(' *', curbuf('get_line', 2))
+ eq({' *'}, curbuf('get_lines', 2, 3, true))
nvim_feed('ggO /\027')
- eq(' /', curbuf('get_line', 0))
+ eq({' /'}, curbuf('get_lines', 0, 1, true))
nvim_feed('ggOx\027')
- eq('x', curbuf('get_line', 0))
+ eq({'x'}, curbuf('get_lines', 0, 1, true))
end)
end)
diff --git a/test/functional/shada/buffers_spec.lua b/test/functional/shada/buffers_spec.lua
index e4d02c268b..01952560d6 100644
--- a/test/functional/shada/buffers_spec.lua
+++ b/test/functional/shada/buffers_spec.lua
@@ -8,6 +8,8 @@ local reset, set_additional_cmd, clear =
shada_helpers.reset, shada_helpers.set_additional_cmd,
shada_helpers.clear
+if helpers.pending_win32(pending) then return end
+
describe('ShaDa support code', function()
local testfilename = 'Xtestfile-functional-shada-buffers'
local testfilename_2 = 'Xtestfile-functional-shada-buffers-2'
@@ -78,9 +80,9 @@ describe('ShaDa support code', function()
it('does not dump unnamed buffers', function()
set_additional_cmd('set shada+=% hidden')
reset()
- curbufmeths.set_line(0, 'foo')
+ curbufmeths.set_lines(0, 1, true, {'foo'})
nvim_command('enew')
- curbufmeths.set_line(0, 'bar')
+ curbufmeths.set_lines(0, 1, true, {'bar'})
eq(2, funcs.bufnr('$'))
nvim_command('qall!')
reset()
diff --git a/test/functional/shada/helpers.lua b/test/functional/shada/helpers.lua
index bb2919d4fb..8e2c0cc1f6 100644
--- a/test/functional/shada/helpers.lua
+++ b/test/functional/shada/helpers.lua
@@ -5,11 +5,11 @@ local write_file, merge_args = helpers.write_file, helpers.merge_args
local mpack = require('mpack')
-local tmpname = os.tmpname()
+local tmpname = helpers.tmpname()
local additional_cmd = ''
-local function nvim_argv()
- local argv = {nvim_prog, '-u', 'NONE', '-i', tmpname, '-N',
+local function nvim_argv(shada_file)
+ local argv = {nvim_prog, '-u', 'NONE', '-i', shada_file or tmpname, '-N',
'--cmd', 'set shortmess+=I background=light noswapfile',
'--cmd', additional_cmd,
'--embed'}
@@ -20,8 +20,8 @@ local function nvim_argv()
end
end
-local reset = function()
- set_session(spawn(nvim_argv()))
+local reset = function(shada_file)
+ set_session(spawn(nvim_argv(shada_file)))
meths.set_var('tmpname', tmpname)
end
diff --git a/test/functional/shada/marks_spec.lua b/test/functional/shada/marks_spec.lua
index ace3c74a62..646b0b692e 100644
--- a/test/functional/shada/marks_spec.lua
+++ b/test/functional/shada/marks_spec.lua
@@ -14,6 +14,8 @@ local nvim_current_line = function()
return curwinmeths.get_cursor()[1]
end
+if helpers.pending_win32(pending) then return end
+
describe('ShaDa support code', function()
local testfilename = 'Xtestfile-functional-shada-marks'
local testfilename_2 = 'Xtestfile-functional-shada-marks-2'
diff --git a/test/functional/shada/shada_spec.lua b/test/functional/shada/shada_spec.lua
index 32e7b16fc5..f845f6f93b 100644
--- a/test/functional/shada/shada_spec.lua
+++ b/test/functional/shada/shada_spec.lua
@@ -5,6 +5,7 @@ local meths, nvim_command, funcs, eq =
local write_file, spawn, set_session, nvim_prog, exc_exec =
helpers.write_file, helpers.spawn, helpers.set_session, helpers.nvim_prog,
helpers.exc_exec
+
local lfs = require('lfs')
local paths = require('test.config.paths')
@@ -14,15 +15,22 @@ local shada_helpers = require('test.functional.shada.helpers')
local reset, clear, get_shada_rw =
shada_helpers.reset, shada_helpers.clear, shada_helpers.get_shada_rw
local read_shada_file = shada_helpers.read_shada_file
+local set_additional_cmd = shada_helpers.set_additional_cmd
local wshada, _, shada_fname, clean =
get_shada_rw('Xtest-functional-shada-shada.shada')
+local dirname = 'Xtest-functional-shada-shada.d'
+local dirshada = dirname .. '/main.shada'
+
+if helpers.pending_win32(pending) then return end
+
describe('ShaDa support code', function()
before_each(reset)
after_each(function()
clear()
clean()
+ lfs.rmdir(dirname)
end)
it('preserves `s` item size limit with unknown entries', function()
@@ -230,4 +238,17 @@ describe('ShaDa support code', function()
eq('', meths.get_option('viminfo'))
eq('', meths.get_option('shada'))
end)
+
+ it('does not crash when ShaDa file directory is not writable', function()
+ funcs.mkdir(dirname, '', 0)
+ eq(0, funcs.filewritable(dirname))
+ set_additional_cmd('set shada=')
+ reset(dirshada)
+ meths.set_option('shada', '\'10')
+ eq('Vim(wshada):E886: System error while opening ShaDa file '
+ .. 'Xtest-functional-shada-shada.d/main.shada for reading to merge '
+ .. 'before writing it: permission denied',
+ exc_exec('wshada'))
+ meths.set_option('shada', '')
+ end)
end)
diff --git a/test/functional/shell/bang_filter_spec.lua b/test/functional/shell/bang_filter_spec.lua
index cd5325c4e1..a320e6d018 100644
--- a/test/functional/shell/bang_filter_spec.lua
+++ b/test/functional/shell/bang_filter_spec.lua
@@ -4,6 +4,8 @@ local helpers = require('test.functional.helpers')(after_each)
local feed, execute, clear = helpers.feed, helpers.execute, helpers.clear
local mkdir, write_file, rmdir = helpers.mkdir, helpers.write_file, helpers.rmdir
+if helpers.pending_win32(pending) then return end
+
local Screen = require('test.functional.ui.screen')
diff --git a/test/functional/shell/viml_system_spec.lua b/test/functional/shell/viml_system_spec.lua
index 3de022cbd9..b8de7cc86f 100644
--- a/test/functional/shell/viml_system_spec.lua
+++ b/test/functional/shell/viml_system_spec.lua
@@ -8,6 +8,7 @@ local eq, clear, eval, feed, nvim =
local Screen = require('test.functional.ui.screen')
+if helpers.pending_win32(pending) then return end
local function create_file_with_nuls(name)
return function()
diff --git a/test/functional/terminal/altscreen_spec.lua b/test/functional/terminal/altscreen_spec.lua
index 9553ffac43..4526037808 100644
--- a/test/functional/terminal/altscreen_spec.lua
+++ b/test/functional/terminal/altscreen_spec.lua
@@ -6,6 +6,8 @@ local feed_data = thelpers.feed_data
local enter_altscreen = thelpers.enter_altscreen
local exit_altscreen = thelpers.exit_altscreen
+if helpers.pending_win32(pending) then return end
+
describe('terminal altscreen', function()
local screen
diff --git a/test/functional/terminal/buffer_spec.lua b/test/functional/terminal/buffer_spec.lua
index 1923e2c675..427aa011e9 100644
--- a/test/functional/terminal/buffer_spec.lua
+++ b/test/functional/terminal/buffer_spec.lua
@@ -5,6 +5,7 @@ local wait = helpers.wait
local eval, execute, source = helpers.eval, helpers.execute, helpers.source
local eq, neq = helpers.eq, helpers.neq
+if helpers.pending_win32(pending) then return end
describe('terminal buffer', function()
local screen
diff --git a/test/functional/terminal/cursor_spec.lua b/test/functional/terminal/cursor_spec.lua
index 1557868473..1953022a7a 100644
--- a/test/functional/terminal/cursor_spec.lua
+++ b/test/functional/terminal/cursor_spec.lua
@@ -6,6 +6,7 @@ local nvim_dir, execute = helpers.nvim_dir, helpers.execute
local hide_cursor = thelpers.hide_cursor
local show_cursor = thelpers.show_cursor
+if helpers.pending_win32(pending) then return end
describe('terminal cursor', function()
local screen
@@ -135,7 +136,7 @@ describe('cursor with customized highlighting', function()
[2] = {foreground = 55, background = 56},
[3] = {bold = true},
})
- screen:attach(false)
+ screen:attach({rgb=false})
execute('call termopen(["'..nvim_dir..'/tty-test"]) | startinsert')
end)
diff --git a/test/functional/terminal/edit_spec.lua b/test/functional/terminal/edit_spec.lua
index c98aef70b1..1936f70b82 100644
--- a/test/functional/terminal/edit_spec.lua
+++ b/test/functional/terminal/edit_spec.lua
@@ -12,7 +12,7 @@ local eq = helpers.eq
describe(':edit term://*', function()
local get_screen = function(columns, lines)
local scr = screen.new(columns, lines)
- scr:attach(false)
+ scr:attach({rgb=false})
return scr
end
diff --git a/test/functional/terminal/ex_terminal_spec.lua b/test/functional/terminal/ex_terminal_spec.lua
index 458fa02fca..6f929f17e4 100644
--- a/test/functional/terminal/ex_terminal_spec.lua
+++ b/test/functional/terminal/ex_terminal_spec.lua
@@ -4,13 +4,15 @@ local clear, wait, nvim = helpers.clear, helpers.wait, helpers.nvim
local nvim_dir, source, eq = helpers.nvim_dir, helpers.source, helpers.eq
local execute, eval = helpers.execute, helpers.eval
+if helpers.pending_win32(pending) then return end
+
describe(':terminal', function()
local screen
before_each(function()
clear()
screen = Screen.new(50, 4)
- screen:attach(false)
+ screen:attach({rgb=false})
nvim('set_option', 'shell', nvim_dir..'/shell-test')
nvim('set_option', 'shellcmdflag', 'EXE')
diff --git a/test/functional/terminal/helpers.lua b/test/functional/terminal/helpers.lua
index 1b8893c988..aacf109f2f 100644
--- a/test/functional/terminal/helpers.lua
+++ b/test/functional/terminal/helpers.lua
@@ -53,7 +53,7 @@ local function screen_setup(extra_height, command)
[9] = {foreground = 4},
})
- screen:attach(false)
+ screen:attach({rgb=false})
-- tty-test puts the terminal into raw mode and echoes all input. tests are
-- done by feeding it with terminfo codes to control the display and
-- verifying output with screen:expect.
diff --git a/test/functional/terminal/highlight_spec.lua b/test/functional/terminal/highlight_spec.lua
index 95fbf2c871..377f335c5c 100644
--- a/test/functional/terminal/highlight_spec.lua
+++ b/test/functional/terminal/highlight_spec.lua
@@ -5,6 +5,7 @@ local feed, clear, nvim = helpers.feed, helpers.clear, helpers.nvim
local nvim_dir, execute = helpers.nvim_dir, helpers.execute
local eq, eval = helpers.eq, helpers.eval
+if helpers.pending_win32(pending) then return end
describe('terminal window highlighting', function()
local screen
@@ -25,7 +26,7 @@ describe('terminal window highlighting', function()
[10] = {reverse = true},
[11] = {background = 11},
})
- screen:attach(false)
+ screen:attach({rgb=false})
execute('enew | call termopen(["'..nvim_dir..'/tty-test"]) | startinsert')
screen:expect([[
tty ready |
@@ -127,7 +128,7 @@ describe('terminal window highlighting with custom palette', function()
[8] = {background = 11},
[9] = {bold = true},
})
- screen:attach(true)
+ screen:attach({rgb=true})
nvim('set_var', 'terminal_color_3', '#123456')
execute('enew | call termopen(["'..nvim_dir..'/tty-test"]) | startinsert')
screen:expect([[
@@ -171,8 +172,8 @@ describe('synIDattr()', function()
it('returns cterm-color if RGB-capable UI is _not_ attached', function()
eq('252', eval('synIDattr(hlID("Normal"), "fg")'))
eq('252', eval('synIDattr(hlID("Normal"), "fg#")'))
- eq('-1', eval('synIDattr(hlID("Normal"), "bg")'))
- eq('-1', eval('synIDattr(hlID("Normal"), "bg#")'))
+ eq('', eval('synIDattr(hlID("Normal"), "bg")'))
+ eq('', eval('synIDattr(hlID("Normal"), "bg#")'))
eq('79', eval('synIDattr(hlID("Keyword"), "fg")'))
eq('79', eval('synIDattr(hlID("Keyword"), "fg#")'))
eq('', eval('synIDattr(hlID("Keyword"), "sp")'))
@@ -185,7 +186,7 @@ describe('synIDattr()', function()
end)
it('returns gui-color if RGB-capable UI is attached', function()
- screen:attach(true)
+ screen:attach({rgb=true})
eq('#ff0000', eval('synIDattr(hlID("Normal"), "fg")'))
eq('Black', eval('synIDattr(hlID("Normal"), "bg")'))
eq('Salmon', eval('synIDattr(hlID("Keyword"), "fg")'))
@@ -193,16 +194,66 @@ describe('synIDattr()', function()
end)
it('returns #RRGGBB value for fg#/bg#/sp#', function()
- screen:attach(true)
- eq('#ff0000', eval('synIDattr(hlID("Normal"), "fg#")'))
- eq('#000000', eval('synIDattr(hlID("Normal"), "bg#")'))
+ screen:attach({rgb=true})
+ eq('#ff0000', eval('synIDattr(hlID("Normal"), "fg#")'))
+ eq('#000000', eval('synIDattr(hlID("Normal"), "bg#")'))
eq('#fa8072', eval('synIDattr(hlID("Keyword"), "fg#")'))
eq('#800000', eval('synIDattr(hlID("Keyword"), "sp#")'))
end)
it('returns color number if non-GUI', function()
- screen:attach(false)
+ screen:attach({rgb=false})
eq('252', eval('synIDattr(hlID("Normal"), "fg")'))
eq('79', eval('synIDattr(hlID("Keyword"), "fg")'))
end)
end)
+
+describe('fg/bg special colors', function()
+ local screen
+ before_each(function()
+ clear()
+ screen = Screen.new(50, 7)
+ execute('highlight Normal ctermfg=145 ctermbg=16 guifg=#ff0000 guibg=Black')
+ execute('highlight Visual ctermfg=bg ctermbg=fg guifg=bg guibg=fg guisp=bg')
+ end)
+
+ it('resolve to "Normal" values', function()
+ eq(eval('synIDattr(hlID("Normal"), "bg")'),
+ eval('synIDattr(hlID("Visual"), "fg")'))
+ eq(eval('synIDattr(hlID("Normal"), "bg#")'),
+ eval('synIDattr(hlID("Visual"), "fg#")'))
+ eq(eval('synIDattr(hlID("Normal"), "fg")'),
+ eval('synIDattr(hlID("Visual"), "bg")'))
+ eq(eval('synIDattr(hlID("Normal"), "fg#")'),
+ eval('synIDattr(hlID("Visual"), "bg#")'))
+ eq('bg', eval('synIDattr(hlID("Visual"), "fg", "gui")'))
+ eq('bg', eval('synIDattr(hlID("Visual"), "fg#", "gui")'))
+ eq('fg', eval('synIDattr(hlID("Visual"), "bg", "gui")'))
+ eq('fg', eval('synIDattr(hlID("Visual"), "bg#", "gui")'))
+ eq('bg', eval('synIDattr(hlID("Visual"), "sp", "gui")'))
+ eq('bg', eval('synIDattr(hlID("Visual"), "sp#", "gui")'))
+ end)
+
+ it('resolve to "Normal" values in RGB-capable UI', function()
+ screen:attach({rgb=true})
+ eq('bg', eval('synIDattr(hlID("Visual"), "fg")'))
+ eq(eval('synIDattr(hlID("Normal"), "bg#")'),
+ eval('synIDattr(hlID("Visual"), "fg#")'))
+ eq('fg', eval('synIDattr(hlID("Visual"), "bg")'))
+ eq(eval('synIDattr(hlID("Normal"), "fg#")'),
+ eval('synIDattr(hlID("Visual"), "bg#")'))
+ eq('bg', eval('synIDattr(hlID("Visual"), "sp")'))
+ eq(eval('synIDattr(hlID("Normal"), "bg#")'),
+ eval('synIDattr(hlID("Visual"), "sp#")'))
+ end)
+
+ it('resolve after the "Normal" group is modified', function()
+ screen:attach({rgb=true})
+ local new_guibg = '#282c34'
+ local new_guifg = '#abb2bf'
+ execute('highlight Normal guifg='..new_guifg..' guibg='..new_guibg)
+ eq(new_guibg, eval('synIDattr(hlID("Visual"), "fg#")'))
+ eq(new_guifg, eval('synIDattr(hlID("Visual"), "bg#")'))
+ eq(new_guibg, eval('synIDattr(hlID("Visual"), "sp#")'))
+ end)
+end)
diff --git a/test/functional/terminal/mouse_spec.lua b/test/functional/terminal/mouse_spec.lua
index 715f071708..ecb0b2beb0 100644
--- a/test/functional/terminal/mouse_spec.lua
+++ b/test/functional/terminal/mouse_spec.lua
@@ -4,6 +4,8 @@ local clear = helpers.clear
local feed, nvim = helpers.feed, helpers.nvim
local feed_data = thelpers.feed_data
+if helpers.pending_win32(pending) then return end
+
describe('terminal mouse', function()
local screen
diff --git a/test/functional/terminal/scrollback_spec.lua b/test/functional/terminal/scrollback_spec.lua
index 4790419bc8..d60819af65 100644
--- a/test/functional/terminal/scrollback_spec.lua
+++ b/test/functional/terminal/scrollback_spec.lua
@@ -6,6 +6,8 @@ local feed, nvim_dir, execute = helpers.feed, helpers.nvim_dir, helpers.execute
local wait = helpers.wait
local feed_data = thelpers.feed_data
+if helpers.pending_win32(pending) then return end
+
describe('terminal scrollback', function()
local screen
@@ -331,7 +333,7 @@ describe('terminal prints more lines than the screen height and exits', function
it('will push extra lines to scrollback', function()
clear()
local screen = Screen.new(50, 7)
- screen:attach(false)
+ screen:attach({rgb=false})
execute('call termopen(["'..nvim_dir..'/tty-test", "10"]) | startinsert')
wait()
screen:expect([[
diff --git a/test/functional/terminal/tui_spec.lua b/test/functional/terminal/tui_spec.lua
index 0f7bf7ba9a..27f00e8550 100644
--- a/test/functional/terminal/tui_spec.lua
+++ b/test/functional/terminal/tui_spec.lua
@@ -6,6 +6,8 @@ local feed = thelpers.feed_data
local execute = helpers.execute
local nvim_dir = helpers.nvim_dir
+if helpers.pending_win32(pending) then return end
+
describe('tui', function()
local screen
diff --git a/test/functional/terminal/window_spec.lua b/test/functional/terminal/window_spec.lua
index 96489045e4..70c234d897 100644
--- a/test/functional/terminal/window_spec.lua
+++ b/test/functional/terminal/window_spec.lua
@@ -4,6 +4,8 @@ local feed, clear = helpers.feed, helpers.clear
local wait = helpers.wait
local execute = helpers.execute
+if helpers.pending_win32(pending) then return end
+
describe('terminal window', function()
local screen
diff --git a/test/functional/terminal/window_split_tab_spec.lua b/test/functional/terminal/window_split_tab_spec.lua
index f4de5f7fca..6951b84a69 100644
--- a/test/functional/terminal/window_split_tab_spec.lua
+++ b/test/functional/terminal/window_split_tab_spec.lua
@@ -4,6 +4,8 @@ local clear = helpers.clear
local feed, nvim = helpers.feed, helpers.nvim
local execute = helpers.execute
+if helpers.pending_win32(pending) then return end
+
describe('terminal', function()
local screen
diff --git a/test/functional/ui/bufhl_spec.lua b/test/functional/ui/bufhl_spec.lua
index 80d413a455..53fe303762 100644
--- a/test/functional/ui/bufhl_spec.lua
+++ b/test/functional/ui/bufhl_spec.lua
@@ -3,6 +3,7 @@ local Screen = require('test.functional.ui.screen')
local clear, feed, insert = helpers.clear, helpers.feed, helpers.insert
local execute, request, neq = helpers.execute, helpers.request, helpers.neq
+if helpers.pending_win32(pending) then return end
describe('Buffer highlighting', function()
local screen
@@ -24,7 +25,7 @@ describe('Buffer highlighting', function()
[8] = {underline = true, bold = true, foreground = Screen.colors.SlateBlue},
[9] = {foreground = Screen.colors.SlateBlue, underline = true}
})
- curbuf = request('vim_get_current_buffer')
+ curbuf = request('nvim_get_current_buf')
end)
after_each(function()
@@ -32,11 +33,11 @@ describe('Buffer highlighting', function()
end)
local function add_hl(...)
- return request('buffer_add_highlight', curbuf, ...)
+ return request('nvim_buf_add_highlight', curbuf, ...)
end
local function clear_hl(...)
- return request('buffer_clear_highlight', curbuf, ...)
+ return request('nvim_buf_clear_highlight', curbuf, ...)
end
diff --git a/test/functional/ui/highlight_spec.lua b/test/functional/ui/highlight_spec.lua
index 46c0964a67..945b16ef92 100644
--- a/test/functional/ui/highlight_spec.lua
+++ b/test/functional/ui/highlight_spec.lua
@@ -4,6 +4,7 @@ local os = require('os')
local clear, feed, insert = helpers.clear, helpers.feed, helpers.insert
local execute, request, eq = helpers.execute, helpers.request, helpers.eq
+if helpers.pending_win32(pending) then return end
describe('color scheme compatibility', function()
before_each(function()
@@ -12,7 +13,7 @@ describe('color scheme compatibility', function()
it('t_Co is set to 256 by default', function()
eq('256', request('vim_eval', '&t_Co'))
- request('vim_set_option', 't_Co', '88')
+ request('nvim_set_option', 't_Co', '88')
eq('88', request('vim_eval', '&t_Co'))
end)
end)
diff --git a/test/functional/ui/input_spec.lua b/test/functional/ui/input_spec.lua
index 407c576002..cec19250d2 100644
--- a/test/functional/ui/input_spec.lua
+++ b/test/functional/ui/input_spec.lua
@@ -4,6 +4,8 @@ local feed, next_message, eq = helpers.feed, helpers.next_message, helpers.eq
local expect = helpers.expect
local Screen = require('test.functional.ui.screen')
+if helpers.pending_win32(pending) then return end
+
describe('mappings', function()
local cid
diff --git a/test/functional/ui/mouse_spec.lua b/test/functional/ui/mouse_spec.lua
index 3f6d8e4663..13bfe9e23f 100644
--- a/test/functional/ui/mouse_spec.lua
+++ b/test/functional/ui/mouse_spec.lua
@@ -4,6 +4,8 @@ local clear, feed, meths = helpers.clear, helpers.feed, helpers.meths
local insert, execute = helpers.insert, helpers.execute
local eq, funcs = helpers.eq, helpers.funcs
+if helpers.pending_win32(pending) then return end
+
describe('Mouse input', function()
local screen
@@ -109,6 +111,232 @@ describe('Mouse input', function()
]])
end)
+ describe('tab drag', function()
+ before_each(function()
+ screen:set_default_attr_ids( {
+ [0] = {bold=true, foreground=Screen.colors.Blue},
+ tab = { background=Screen.colors.LightGrey, underline=true },
+ sel = { bold=true },
+ fill = { reverse=true }
+ })
+ screen.timeout = 15000
+ end)
+
+ it('in tabline on filler space moves tab to the end', function()
+ execute('%delete')
+ insert('this is foo')
+ execute('silent file foo | tabnew | file bar')
+ insert('this is bar')
+ screen:expect([[
+ {tab: + foo }{sel: + bar }{fill: }{tab:X}|
+ this is ba^r |
+ {0:~ }|
+ {0:~ }|
+ |
+ ]])
+ feed('<LeftMouse><4,0>')
+ screen:expect([[
+ {sel: + foo }{tab: + bar }{fill: }{tab:X}|
+ this is fo^o |
+ {0:~ }|
+ {0:~ }|
+ |
+ ]])
+ feed('<LeftDrag><14,0>')
+ screen:expect([[
+ {tab: + bar }{sel: + foo }{fill: }{tab:X}|
+ this is fo^o |
+ {0:~ }|
+ {0:~ }|
+ |
+ ]])
+ end)
+
+ it('in tabline to the left moves tab left', function()
+ if os.getenv("TRAVIS") and helpers.os_name() == "osx" then
+ pending("[Fails on Travis macOS. #4874]", function() end)
+ return
+ end
+
+ execute('%delete')
+ insert('this is foo')
+ execute('silent file foo | tabnew | file bar')
+ insert('this is bar')
+ screen:expect([[
+ {tab: + foo }{sel: + bar }{fill: }{tab:X}|
+ this is ba^r |
+ {0:~ }|
+ {0:~ }|
+ |
+ ]])
+ feed('<LeftMouse><11,0>')
+ screen:expect([[
+ {tab: + foo }{sel: + bar }{fill: }{tab:X}|
+ this is ba^r |
+ {0:~ }|
+ {0:~ }|
+ |
+ ]])
+ feed('<LeftDrag><6,0>')
+ screen:expect([[
+ {sel: + bar }{tab: + foo }{fill: }{tab:X}|
+ this is ba^r |
+ {0:~ }|
+ {0:~ }|
+ |
+ ]])
+ end)
+
+ it('in tabline to the right moves tab right', function()
+ execute('%delete')
+ insert('this is foo')
+ execute('silent file foo | tabnew | file bar')
+ insert('this is bar')
+ screen:expect([[
+ {tab: + foo }{sel: + bar }{fill: }{tab:X}|
+ this is ba^r |
+ {0:~ }|
+ {0:~ }|
+ |
+ ]])
+ feed('<LeftMouse><4,0>')
+ screen:expect([[
+ {sel: + foo }{tab: + bar }{fill: }{tab:X}|
+ this is fo^o |
+ {0:~ }|
+ {0:~ }|
+ |
+ ]])
+ feed('<LeftDrag><7,0>')
+ screen:expect([[
+ {tab: + bar }{sel: + foo }{fill: }{tab:X}|
+ this is fo^o |
+ {0:~ }|
+ {0:~ }|
+ |
+ ]])
+ end)
+
+ it('out of tabline under filler space moves tab to the end', function()
+ execute('%delete')
+ insert('this is foo')
+ execute('silent file foo | tabnew | file bar')
+ insert('this is bar')
+ screen:expect([[
+ {tab: + foo }{sel: + bar }{fill: }{tab:X}|
+ this is ba^r |
+ {0:~ }|
+ {0:~ }|
+ |
+ ]])
+ feed('<LeftMouse><4,0>')
+ screen:expect([[
+ {sel: + foo }{tab: + bar }{fill: }{tab:X}|
+ this is fo^o |
+ {0:~ }|
+ {0:~ }|
+ |
+ ]])
+ feed('<LeftDrag><4,1>')
+ screen:expect([[
+ {sel: + foo }{tab: + bar }{fill: }{tab:X}|
+ this is fo^o |
+ {0:~ }|
+ {0:~ }|
+ |
+ ]])
+ feed('<LeftDrag><14,1>')
+ screen:expect([[
+ {tab: + bar }{sel: + foo }{fill: }{tab:X}|
+ this is fo^o |
+ {0:~ }|
+ {0:~ }|
+ |
+ ]])
+ end)
+
+ it('out of tabline to the left moves tab left', function()
+ if os.getenv("TRAVIS") and helpers.os_name() == "osx" then
+ pending("[Fails on Travis macOS. #4874]", function() end)
+ return
+ end
+
+ execute('%delete')
+ insert('this is foo')
+ execute('silent file foo | tabnew | file bar')
+ insert('this is bar')
+ screen:expect([[
+ {tab: + foo }{sel: + bar }{fill: }{tab:X}|
+ this is ba^r |
+ {0:~ }|
+ {0:~ }|
+ |
+ ]])
+ feed('<LeftMouse><11,0>')
+ screen:expect([[
+ {tab: + foo }{sel: + bar }{fill: }{tab:X}|
+ this is ba^r |
+ {0:~ }|
+ {0:~ }|
+ |
+ ]])
+ feed('<LeftDrag><11,1>')
+ screen:expect([[
+ {tab: + foo }{sel: + bar }{fill: }{tab:X}|
+ this is ba^r |
+ {0:~ }|
+ {0:~ }|
+ |
+ ]])
+ feed('<LeftDrag><6,1>')
+ screen:expect([[
+ {sel: + bar }{tab: + foo }{fill: }{tab:X}|
+ this is ba^r |
+ {0:~ }|
+ {0:~ }|
+ |
+ ]])
+ end)
+
+ it('out of tabline to the right moves tab right', function()
+ execute('%delete')
+ insert('this is foo')
+ execute('silent file foo | tabnew | file bar')
+ insert('this is bar')
+ screen:expect([[
+ {tab: + foo }{sel: + bar }{fill: }{tab:X}|
+ this is ba^r |
+ {0:~ }|
+ {0:~ }|
+ |
+ ]])
+ feed('<LeftMouse><4,0>')
+ screen:expect([[
+ {sel: + foo }{tab: + bar }{fill: }{tab:X}|
+ this is fo^o |
+ {0:~ }|
+ {0:~ }|
+ |
+ ]])
+ feed('<LeftDrag><4,1>')
+ screen:expect([[
+ {sel: + foo }{tab: + bar }{fill: }{tab:X}|
+ this is fo^o |
+ {0:~ }|
+ {0:~ }|
+ |
+ ]])
+ feed('<LeftDrag><7,1>')
+ screen:expect([[
+ {tab: + bar }{sel: + foo }{fill: }{tab:X}|
+ this is fo^o |
+ {0:~ }|
+ {0:~ }|
+ |
+ ]])
+ end)
+ end)
+
describe('tabline', function()
before_each(function()
screen:set_default_attr_ids( {
diff --git a/test/functional/ui/output_spec.lua b/test/functional/ui/output_spec.lua
index 22ffc156ef..c58bbe9147 100644
--- a/test/functional/ui/output_spec.lua
+++ b/test/functional/ui/output_spec.lua
@@ -1,6 +1,8 @@
local session = require('test.functional.helpers')(after_each)
local child_session = require('test.functional.terminal.helpers')
+if session.pending_win32(pending) then return end
+
describe("shell command :!", function()
local screen
before_each(function()
@@ -19,6 +21,7 @@ describe("shell command :!", function()
end)
after_each(function()
+ child_session.feed_data("\3") -- Ctrl-C
screen:detach()
end)
@@ -27,12 +30,12 @@ describe("shell command :!", function()
-- to avoid triggering a UI flush.
child_session.feed_data(":!printf foo; sleep 200\n")
screen:expect([[
- {1: } |
- {4:~ }|
{4:~ }|
{4:~ }|
{5:[No Name] }|
+ :!printf foo; sleep 200 |
|
+ foo |
{3:-- TERMINAL --} |
]])
end)
diff --git a/test/functional/ui/screen.lua b/test/functional/ui/screen.lua
index b219196866..96324bfac5 100644
--- a/test/functional/ui/screen.lua
+++ b/test/functional/ui/screen.lua
@@ -106,7 +106,7 @@
-- use `screen:snapshot_util({},true)`
local helpers = require('test.functional.helpers')(nil)
-local request, run = helpers.request, helpers.run
+local request, run, uimeths = helpers.request, helpers.run, helpers.uimeths
local dedent = helpers.dedent
local Screen = {}
@@ -192,22 +192,22 @@ function Screen:set_default_attr_ignore(attr_ignore)
self._default_attr_ignore = attr_ignore
end
-function Screen:attach(rgb)
- if rgb == nil then
- rgb = true
+function Screen:attach(options)
+ if options == nil then
+ options = {rgb=true}
end
- request('ui_attach', self._width, self._height, rgb)
+ uimeths.attach(self._width, self._height, options)
end
function Screen:detach()
- request('ui_detach')
+ uimeths.detach()
end
function Screen:try_resize(columns, rows)
- request('ui_try_resize', columns, rows)
+ uimeths.try_resize(columns, rows)
end
-function Screen:expect(expected, attr_ids, attr_ignore)
+function Screen:expect(expected, attr_ids, attr_ignore, condition)
-- remove the last line and dedent
expected = dedent(expected:gsub('\n[ ]+$', ''))
local expected_rows = {}
@@ -219,6 +219,12 @@ function Screen:expect(expected, attr_ids, attr_ignore)
local ids = attr_ids or self._default_attr_ids
local ignore = attr_ignore or self._default_attr_ignore
self:wait(function()
+ if condition ~= nil then
+ local status, res = pcall(condition)
+ if not status then
+ return tostring(res)
+ end
+ end
local actual_rows = {}
for i = 1, self._height do
actual_rows[i] = self:_row_repr(self._rows[i], ids, ignore)
@@ -303,12 +309,20 @@ function Screen:_redraw(updates)
local method = update[1]
for i = 2, #update do
local handler = self['_handle_'..method]
- handler(self, unpack(update[i]))
+ if handler ~= nil then
+ handler(self, unpack(update[i]))
+ else
+ self._on_event(method, update[i])
+ end
end
-- print(self:_current_screen())
end
end
+function Screen:set_on_event_handler(callback)
+ self._on_event = callback
+end
+
function Screen:_handle_resize(width, height)
local rows = {}
for _ = 1, height do
diff --git a/test/functional/ui/screen_basic_spec.lua b/test/functional/ui/screen_basic_spec.lua
index d8cff1c766..2b44b92336 100644
--- a/test/functional/ui/screen_basic_spec.lua
+++ b/test/functional/ui/screen_basic_spec.lua
@@ -4,6 +4,8 @@ local spawn, set_session, clear = helpers.spawn, helpers.set_session, helpers.cl
local feed, execute = helpers.feed, helpers.execute
local insert = helpers.insert
+if helpers.pending_win32(pending) then return end
+
describe('Initial screen', function()
local screen
local nvim_argv = {helpers.nvim_prog, '-u', 'NONE', '-i', 'NONE', '-N',
diff --git a/test/functional/ui/searchhl_spec.lua b/test/functional/ui/searchhl_spec.lua
index cd4cc68c80..3914648e8f 100644
--- a/test/functional/ui/searchhl_spec.lua
+++ b/test/functional/ui/searchhl_spec.lua
@@ -3,6 +3,8 @@ local Screen = require('test.functional.ui.screen')
local clear, feed, insert = helpers.clear, helpers.feed, helpers.insert
local execute = helpers.execute
+if helpers.pending_win32(pending) then return end
+
describe('search highlighting', function()
local screen
local colors = Screen.colors
diff --git a/test/functional/ui/sign_spec.lua b/test/functional/ui/sign_spec.lua
index eabd05b349..d02fc83809 100644
--- a/test/functional/ui/sign_spec.lua
+++ b/test/functional/ui/sign_spec.lua
@@ -2,6 +2,8 @@ local helpers = require('test.functional.helpers')(after_each)
local Screen = require('test.functional.ui.screen')
local clear, feed, execute = helpers.clear, helpers.feed, helpers.execute
+if helpers.pending_win32(pending) then return end
+
describe('Signs', function()
local screen
diff --git a/test/functional/ui/syntax_conceal_spec.lua b/test/functional/ui/syntax_conceal_spec.lua
index 4e2bd4d6be..58e3597233 100644
--- a/test/functional/ui/syntax_conceal_spec.lua
+++ b/test/functional/ui/syntax_conceal_spec.lua
@@ -3,6 +3,8 @@ local Screen = require('test.functional.ui.screen')
local clear, feed, execute = helpers.clear, helpers.feed, helpers.execute
local insert = helpers.insert
+if helpers.pending_win32(pending) then return end
+
describe('Screen', function()
local screen
diff --git a/test/functional/ui/wildmode_spec.lua b/test/functional/ui/wildmode_spec.lua
index 1d582703d0..6a6dc99c3d 100644
--- a/test/functional/ui/wildmode_spec.lua
+++ b/test/functional/ui/wildmode_spec.lua
@@ -3,6 +3,8 @@ local Screen = require('test.functional.ui.screen')
local clear, feed, execute = helpers.clear, helpers.feed, helpers.execute
local funcs = helpers.funcs
+if helpers.pending_win32(pending) then return end
+
describe("'wildmode'", function()
local screen
diff --git a/test/functional/viml/completion_spec.lua b/test/functional/viml/completion_spec.lua
index 07544a91ab..0897c2d836 100644
--- a/test/functional/viml/completion_spec.lua
+++ b/test/functional/viml/completion_spec.lua
@@ -4,6 +4,8 @@ local clear, feed = helpers.clear, helpers.feed
local eval, eq, neq = helpers.eval, helpers.eq, helpers.neq
local execute, source, expect = helpers.execute, helpers.source, helpers.expect
+if helpers.pending_win32(pending) then return end
+
describe('completion', function()
local screen
@@ -755,4 +757,106 @@ describe('completion', function()
]])
end)
end)
+
+end)
+
+describe('External completion popupmenu', function()
+ local screen
+ local items, selected, anchor
+ before_each(function()
+ clear()
+ screen = Screen.new(60, 8)
+ screen:attach({rgb=true, popupmenu_external=true})
+ screen:set_default_attr_ids({
+ [1] = {bold=true, foreground=Screen.colors.Blue},
+ [2] = {bold = true},
+ })
+ screen:set_on_event_handler(function(name, data)
+ if name == "popupmenu_show" then
+ local row, col
+ items, selected, row, col = unpack(data)
+ anchor = {row, col}
+ elseif name == "popupmenu_select" then
+ selected = data[1]
+ elseif name == "popupmenu_hide" then
+ items = nil
+ end
+ end)
+ end)
+
+ it('works', function()
+ source([[
+ function! TestComplete() abort
+ call complete(1, ['foo', 'bar', 'spam'])
+ return ''
+ endfunction
+ ]])
+ local expected = {
+ {'foo', '', '', ''},
+ {'bar', '', '', ''},
+ {'spam', '', '', ''},
+ }
+ feed('o<C-r>=TestComplete()<CR>')
+ screen:expect([[
+ |
+ foo^ |
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {2:-- INSERT --} |
+ ]], nil, nil, function()
+ eq(expected, items)
+ eq(0, selected)
+ eq({1,0}, anchor)
+ end)
+
+ feed('<c-p>')
+ screen:expect([[
+ |
+ ^ |
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {2:-- INSERT --} |
+ ]], nil, nil, function()
+ eq(expected, items)
+ eq(-1, selected)
+ eq({1,0}, anchor)
+ end)
+
+ -- down moves the selection in the menu, but does not insert anything
+ feed('<down><down>')
+ screen:expect([[
+ |
+ ^ |
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {2:-- INSERT --} |
+ ]], nil, nil, function()
+ eq(expected, items)
+ eq(1, selected)
+ eq({1,0}, anchor)
+ end)
+
+ feed('<cr>')
+ screen:expect([[
+ |
+ bar^ |
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {2:-- INSERT --} |
+ ]], nil, nil, function()
+ eq(nil, items) -- popupmenu was hidden
+ end)
+ end)
end)
diff --git a/test/functional/viml/function_spec.lua b/test/functional/viml/function_spec.lua
index f0a4406593..776e760aaf 100644
--- a/test/functional/viml/function_spec.lua
+++ b/test/functional/viml/function_spec.lua
@@ -2,7 +2,6 @@ local helpers = require('test.functional.helpers')(after_each)
local clear = helpers.clear
local eq = helpers.eq
-local eval = helpers.eval
local exc_exec = helpers.exc_exec
describe('Up to MAX_FUNC_ARGS arguments are handled by', function()
@@ -28,11 +27,3 @@ describe('Up to MAX_FUNC_ARGS arguments are handled by', function()
eq('Vim(call):E740: Too many arguments for function rpcnotify', ret)
end)
end)
-
-describe('api_info()', function()
- before_each(clear)
- it('has the right keys', function()
- local api_keys = eval("sort(keys(api_info()))")
- eq({'error_types', 'functions', 'types'}, api_keys)
- end)
-end)
diff --git a/test/unit/buffer_spec.lua b/test/unit/buffer_spec.lua
index 317c9be6e7..49a4d84279 100644
--- a/test/unit/buffer_spec.lua
+++ b/test/unit/buffer_spec.lua
@@ -87,7 +87,7 @@ describe('buffer functions', function()
it('should find exact matches', function()
local buf = buflist_new(path1, buffer.BLN_LISTED)
- eq(buf.b_fnum, buflist_findpat(path1, ONLY_LISTED))
+ eq(buf.handle, buflist_findpat(path1, ONLY_LISTED))
close_buffer(NULL, buf, buffer.DOBUF_WIPE, 0)
end)
@@ -97,9 +97,9 @@ describe('buffer functions', function()
local buf2 = buflist_new(path2, buffer.BLN_LISTED)
local buf3 = buflist_new(path3, buffer.BLN_LISTED)
- eq(buf1.b_fnum, buflist_findpat("test", ONLY_LISTED))
- eq(buf2.b_fnum, buflist_findpat("file", ONLY_LISTED))
- eq(buf3.b_fnum, buflist_findpat("path", ONLY_LISTED))
+ eq(buf1.handle, buflist_findpat("test", ONLY_LISTED))
+ eq(buf2.handle, buflist_findpat("file", ONLY_LISTED))
+ eq(buf3.handle, buflist_findpat("path", ONLY_LISTED))
close_buffer(NULL, buf1, buffer.DOBUF_WIPE, 0)
close_buffer(NULL, buf2, buffer.DOBUF_WIPE, 0)
@@ -113,7 +113,7 @@ describe('buffer functions', function()
local buf3 = buflist_new(path3, buffer.BLN_LISTED)
-- Then: buf2 is the buffer that is found
- eq(buf2.b_fnum, buflist_findpat("test", ONLY_LISTED))
+ eq(buf2.handle, buflist_findpat("test", ONLY_LISTED))
--}
--{ When: We close buf2
@@ -123,7 +123,7 @@ describe('buffer functions', function()
local buf1 = buflist_new(path1, buffer.BLN_LISTED)
-- Then: buf3 is found since 'file' appears at the end of the name
- eq(buf3.b_fnum, buflist_findpat("file", ONLY_LISTED))
+ eq(buf3.handle, buflist_findpat("file", ONLY_LISTED))
--}
close_buffer(NULL, buf1, buffer.DOBUF_WIPE, 0)
@@ -135,7 +135,7 @@ describe('buffer functions', function()
local buf2 = buflist_new(path2, buffer.BLN_LISTED)
local buf3 = buflist_new(path3, buffer.BLN_LISTED)
- eq(buf3.b_fnum, buflist_findpat("_test_", ONLY_LISTED))
+ eq(buf3.handle, buflist_findpat("_test_", ONLY_LISTED))
close_buffer(NULL, buf1, buffer.DOBUF_WIPE, 0)
close_buffer(NULL, buf2, buffer.DOBUF_WIPE, 0)
@@ -147,7 +147,7 @@ describe('buffer functions', function()
local buf3 = buflist_new(path3, buffer.BLN_LISTED)
-- Then: We should find the buffer when it is given a unique pattern
- eq(buf3.b_fnum, buflist_findpat("_test_", ONLY_LISTED))
+ eq(buf3.handle, buflist_findpat("_test_", ONLY_LISTED))
--}
--{ When: We unlist the buffer
@@ -157,7 +157,7 @@ describe('buffer functions', function()
eq(-1, buflist_findpat("_test_", ONLY_LISTED))
-- And: It should find the buffer when including unlisted buffers
- eq(buf3.b_fnum, buflist_findpat("_test_", ALLOW_UNLISTED))
+ eq(buf3.handle, buflist_findpat("_test_", ALLOW_UNLISTED))
--}
--{ When: We wipe the buffer
@@ -175,7 +175,7 @@ describe('buffer functions', function()
local buf2 = buflist_new(path2, buffer.BLN_LISTED)
-- Then: The first buffer is preferred when both are listed
- eq(buf1.b_fnum, buflist_findpat("test", ONLY_LISTED))
+ eq(buf1.handle, buflist_findpat("test", ONLY_LISTED))
--}
--{ When: The first buffer is unlisted
@@ -183,13 +183,13 @@ describe('buffer functions', function()
-- Then: The second buffer is preferred because
-- unlisted buffers are not allowed
- eq(buf2.b_fnum, buflist_findpat("test", ONLY_LISTED))
+ eq(buf2.handle, buflist_findpat("test", ONLY_LISTED))
--}
--{ When: We allow unlisted buffers
-- Then: The second buffer is still preferred
-- because listed buffers are preferred to unlisted
- eq(buf2.b_fnum, buflist_findpat("test", ALLOW_UNLISTED))
+ eq(buf2.handle, buflist_findpat("test", ALLOW_UNLISTED))
--}
--{ When: We unlist the second buffer
@@ -198,7 +198,7 @@ describe('buffer functions', function()
-- Then: The first buffer is preferred again
-- because buf1 matches better which takes precedence
-- when both buffers have the same listing status.
- eq(buf1.b_fnum, buflist_findpat("test", ALLOW_UNLISTED))
+ eq(buf1.handle, buflist_findpat("test", ALLOW_UNLISTED))
-- And: Neither buffer is returned when ignoring unlisted
eq(-1, buflist_findpat("test", ONLY_LISTED))
diff --git a/test/unit/option_spec.lua b/test/unit/option_spec.lua
new file mode 100644
index 0000000000..8bab0194a2
--- /dev/null
+++ b/test/unit/option_spec.lua
@@ -0,0 +1,51 @@
+local helpers = require("test.unit.helpers")
+
+local to_cstr = helpers.to_cstr
+local eq = helpers.eq
+
+local option = helpers.cimport("./src/nvim/option.h")
+local globals = helpers.cimport("./src/nvim/globals.h")
+
+local check_ff_value = function(ff)
+ return option.check_ff_value(to_cstr(ff))
+end
+
+describe('check_ff_value', function()
+
+ it('views empty string as valid', function()
+ eq(1, check_ff_value(""))
+ end)
+
+ it('views "unix", "dos" and "mac" as valid', function()
+ eq(1, check_ff_value("unix"))
+ eq(1, check_ff_value("dos"))
+ eq(1, check_ff_value("mac"))
+ end)
+
+ it('views "foo" as invalid', function()
+ eq(0, check_ff_value("foo"))
+ end)
+end)
+
+describe('get_sts_value', function()
+ it([[returns 'softtabstop' when it is non-negative]], function()
+ globals.curbuf.b_p_sts = 5
+ eq(5, option.get_sts_value())
+
+ globals.curbuf.b_p_sts = 0
+ eq(0, option.get_sts_value())
+ end)
+
+ it([[returns "effective shiftwidth" when 'softtabstop' is negative]], function()
+ local shiftwidth = 2
+ globals.curbuf.b_p_sw = shiftwidth
+ local tabstop = 5
+ globals.curbuf.b_p_ts = tabstop
+ globals.curbuf.b_p_sts = -2
+ eq(shiftwidth, option.get_sts_value())
+
+ shiftwidth = 0
+ globals.curbuf.b_p_sw = shiftwidth
+ eq(tabstop, option.get_sts_value())
+ end)
+end)
diff --git a/test/unit/os/shell_spec.lua b/test/unit/os/shell_spec.lua
index 906f950308..3603403daf 100644
--- a/test/unit/os/shell_spec.lua
+++ b/test/unit/os/shell_spec.lua
@@ -1,15 +1,3 @@
--- not all operating systems support the system()-tests, as of yet.
-local allowed_os = {
- Linux = true,
- OSX = true,
- BSD = true,
- POSIX = true
-}
-
-if allowed_os[jit.os] ~= true then
- return
-end
-
local helpers = require('test.unit.helpers')
local cimported = helpers.cimport(
'./src/nvim/os/shell.h',
@@ -24,10 +12,12 @@ local to_cstr = helpers.to_cstr
local NULL = ffi.cast('void *', 0)
describe('shell functions', function()
- setup(function()
+ before_each(function()
-- os_system() can't work when the p_sh and p_shcf variables are unset
cimported.p_sh = to_cstr('/bin/bash')
cimported.p_shcf = to_cstr('-c')
+ cimported.p_sxq = to_cstr('')
+ cimported.p_sxe = to_cstr('')
end)
local function shell_build_argv(cmd, extra_args)
@@ -126,5 +116,50 @@ describe('shell functions', function()
'-c', 'abc def'},
shell_build_argv('abc def', 'ghi jkl'))
end)
+
+ it('applies shellxescape (p_sxe) and shellxquote (p_sxq)', function()
+ cimported.p_sxq = to_cstr('(')
+ cimported.p_sxe = to_cstr('"&|<>()@^')
+
+ local argv = ffi.cast('char**',
+ cimported.shell_build_argv(to_cstr('echo &|<>()@^'), nil))
+ eq(ffi.string(argv[0]), '/bin/bash')
+ eq(ffi.string(argv[1]), '-c')
+ eq(ffi.string(argv[2]), '(echo ^&^|^<^>^(^)^@^^)')
+ eq(nil, argv[3])
+ end)
+
+ it('applies shellxquote="(', function()
+ cimported.p_sxq = to_cstr('"(')
+ cimported.p_sxe = to_cstr('"&|<>()@^')
+
+ local argv = ffi.cast('char**', cimported.shell_build_argv(
+ to_cstr('echo -n some text'), nil))
+ eq(ffi.string(argv[0]), '/bin/bash')
+ eq(ffi.string(argv[1]), '-c')
+ eq(ffi.string(argv[2]), '"(echo -n some text)"')
+ eq(nil, argv[3])
+ end)
+
+ it('applies shellxquote="', function()
+ cimported.p_sxq = to_cstr('"')
+ cimported.p_sxe = to_cstr('')
+
+ local argv = ffi.cast('char**', cimported.shell_build_argv(
+ to_cstr('echo -n some text'), nil))
+ eq(ffi.string(argv[0]), '/bin/bash')
+ eq(ffi.string(argv[1]), '-c')
+ eq(ffi.string(argv[2]), '"echo -n some text"')
+ eq(nil, argv[3])
+ end)
+
+ it('with empty shellxquote/shellxescape', function()
+ local argv = ffi.cast('char**', cimported.shell_build_argv(
+ to_cstr('echo -n some text'), nil))
+ eq(ffi.string(argv[0]), '/bin/bash')
+ eq(ffi.string(argv[1]), '-c')
+ eq(ffi.string(argv[2]), 'echo -n some text')
+ eq(nil, argv[3])
+ end)
end)
end)
diff --git a/third-party/CMakeLists.txt b/third-party/CMakeLists.txt
index 7eba17aba3..e0dcf6e04c 100644
--- a/third-party/CMakeLists.txt
+++ b/third-party/CMakeLists.txt
@@ -32,6 +32,12 @@ option(USE_BUNDLED_LUV "Use the bundled version of luv." ${USE_BUNDLED})
# build it unless explicitly requested
option(USE_BUNDLED_LUA "Use the bundled version of lua." OFF)
+if(USE_BUNDLED AND (NOT WIN32))
+ option(USE_BUNDLED_GPERF "Use the bundled version of gperf." ON)
+else()
+ option(USE_BUNDLED_GPERF "Use the bundled version of gperf." OFF)
+endif()
+
option(USE_EXISTING_SRC_DIR "Skip download of deps sources in case of existing source directory." OFF)
if(UNIX)
@@ -81,8 +87,8 @@ endif()
include(ExternalProject)
-set(LIBUV_URL https://github.com/libuv/libuv/archive/v1.8.0.tar.gz)
-set(LIBUV_SHA256 906e1a5c673c95cb261adeacdb7308a65b4a8f7c9c50d85f3021364951fa9cde)
+set(LIBUV_URL https://github.com/libuv/libuv/archive/v1.9.1.tar.gz)
+set(LIBUV_SHA256 a6ca9f0648973d1463f46b495ce546ddcbe7cce2f04b32e802a15539e46c57ad)
set(MSGPACK_URL https://github.com/msgpack/msgpack-c/archive/cpp-1.0.0.tar.gz)
set(MSGPACK_SHA256 afda64ca445203bb7092372b822bae8b2539fdcebbfc3f753f393628c2bcfe7d)
@@ -108,8 +114,11 @@ set(LIBVTERM_SHA256 1a4272be91d9614dc183a503786df83b6584e4afaab7feaaa5409f841afb
set(JEMALLOC_URL https://github.com/jemalloc/jemalloc/releases/download/4.2.1/jemalloc-4.2.1.tar.bz2)
set(JEMALLOC_SHA256 5630650d5c1caab95d2f0898de4fe5ab8519dc680b04963b38bb425ef6a42d57)
-set(LUV_URL https://github.com/luvit/luv/archive/146f1ce4c08c3b67f604c9ee1e124b1cf5c15cf3.tar.gz)
-set(LUV_SHA256 3d537f8eb9fa5adb146a083eae22af886aee324ec268e2aa0fa75f2f1c52ca7a)
+set(LUV_URL https://github.com/luvit/luv/archive/1.9.1-0.tar.gz)
+set(LUV_SHA256 86a199403856018cd8e5529c8527450c83664a3d36f52d5253cbe909ea6c5a06)
+
+set(GPERF_URL http://ftp.gnu.org/pub/gnu/gperf/gperf-3.0.4.tar.gz)
+set(GPERF_SHA256 767112a204407e62dbc3106647cf839ed544f3cf5d0f0523aaa2508623aad63e)
if(USE_BUNDLED_UNIBILIUM)
include(BuildUnibilium)
@@ -151,6 +160,10 @@ if(USE_BUNDLED_LUV)
include(BuildLuv)
endif()
+if(USE_BUNDLED_GPERF)
+ include(BuildGperf)
+endif()
+
add_custom_target(clean-shared-libraries
COMMAND ${CMAKE_COMMAND}
-DREMOVE_FILE_GLOB=${DEPS_INSTALL_DIR}/lib/${CMAKE_SHARED_LIBRARY_PREFIX}*${CMAKE_SHARED_LIBRARY_SUFFIX}*
diff --git a/third-party/cmake/BuildGperf.cmake b/third-party/cmake/BuildGperf.cmake
new file mode 100644
index 0000000000..494d0d9717
--- /dev/null
+++ b/third-party/cmake/BuildGperf.cmake
@@ -0,0 +1,51 @@
+# Gperf recipe. Gperf is only required when building Neovim, when
+# cross compiling we still want to build for the HOST system, whenever
+# writing a recipe that is meant for cross-compile, use the HOSTDEPS_* variables
+# instead of DEPS_* - check the main CMakeLists.txt for a list.
+
+# BuildGperf(CONFIGURE_COMMAND ... BUILD_COMMAND ... INSTALL_COMMAND ...)
+# Reusable function to build Gperf, wraps ExternalProject_Add.
+# Failing to pass a command argument will result in no command being run
+function(BuildGperf)
+ cmake_parse_arguments(_gperf
+ ""
+ ""
+ "CONFIGURE_COMMAND;BUILD_COMMAND;INSTALL_COMMAND"
+ ${ARGN})
+
+ if(NOT _gperf_CONFIGURE_COMMAND AND NOT _gperf_BUILD_COMMAND
+ AND NOT _gperf_INSTALL_COMMAND)
+ message(FATAL_ERROR "Must pass at least one of CONFIGURE_COMMAND, BUILD_COMMAND, INSTALL_COMMAND")
+ endif()
+
+ ExternalProject_Add(gperf
+ PREFIX ${DEPS_BUILD_DIR}
+ URL ${GPERF_URL}
+ DOWNLOAD_DIR ${DEPS_DOWNLOAD_DIR}/gperf
+ DOWNLOAD_COMMAND ${CMAKE_COMMAND}
+ -DPREFIX=${DEPS_BUILD_DIR}
+ -DDOWNLOAD_DIR=${DEPS_DOWNLOAD_DIR}/gperf
+ -DURL=${GPERF_URL}
+ -DEXPECTED_SHA256=${GPERF_SHA256}
+ -DTARGET=gperf
+ -DUSE_EXISTING_SRC_DIR=${USE_EXISTING_SRC_DIR}
+ -P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/DownloadAndExtractFile.cmake
+ BUILD_IN_SOURCE 1
+ CONFIGURE_COMMAND "${_gperf_CONFIGURE_COMMAND}"
+ BUILD_COMMAND "${_gperf_BUILD_COMMAND}"
+ INSTALL_COMMAND "${_gperf_INSTALL_COMMAND}")
+endfunction()
+
+set(GPERF_BUILDARGS CC=${HOSTDEPS_C_COMPILER} LD=${HOSTDEPS_C_COMPILER})
+
+if(UNIX OR (MINGW AND CMAKE_CROSSCOMPILING))
+
+ BuildGperf(
+ CONFIGURE_COMMAND ${DEPS_BUILD_DIR}/src/gperf/configure
+ --prefix=${HOSTDEPS_INSTALL_DIR}
+ INSTALL_COMMAND ${MAKE_PRG} install)
+
+else()
+ message(FATAL_ERROR "Trying to build gperf in an unsupported system ${CMAKE_SYSTEM_NAME}/${CMAKE_C_COMPILER_ID}")
+endif()
+
diff --git a/third-party/cmake/BuildLuarocks.cmake b/third-party/cmake/BuildLuarocks.cmake
index cbc1959d4f..fee8dba207 100644
--- a/third-party/cmake/BuildLuarocks.cmake
+++ b/third-party/cmake/BuildLuarocks.cmake
@@ -3,11 +3,7 @@
# writing a recipe that is meant for cross-compile, use the HOSTDEPS_* variables
# instead of DEPS_* - check the main CMakeLists.txt for a list.
-if(MSVC OR (MINGW AND NOT CMAKE_CROSSCOMPILING))
- message(STATUS "Building busted in Windows is not supported (skipping)")
-else()
- option(USE_BUNDLED_BUSTED "Use the bundled version of busted to run tests." ON)
-endif()
+option(USE_BUNDLED_BUSTED "Use the bundled version of busted to run tests." ON)
# BuildLuarocks(CONFIGURE_COMMAND ... BUILD_COMMAND ... INSTALL_COMMAND ...)
# Reusable function to build luarocks, wraps ExternalProject_Add.
@@ -134,12 +130,17 @@ if(USE_BUNDLED_BUSTED)
add_custom_target(penlight
DEPENDS ${HOSTDEPS_LIB_DIR}/luarocks/rocks/penlight/1.3.2-2)
- add_custom_command(OUTPUT ${HOSTDEPS_BIN_DIR}/busted
+ if(WIN32)
+ set(BUSTED_EXE "${HOSTDEPS_BIN_DIR}/busted.bat")
+ else()
+ set(BUSTED_EXE "${HOSTDEPS_BIN_DIR}/busted")
+ endif()
+ add_custom_command(OUTPUT ${BUSTED_EXE}
COMMAND ${LUAROCKS_BINARY}
ARGS build https://raw.githubusercontent.com/Olivine-Labs/busted/v2.0.rc11-0/busted-2.0.rc11-0.rockspec ${LUAROCKS_BUILDARGS}
DEPENDS penlight)
add_custom_target(busted
- DEPENDS ${HOSTDEPS_BIN_DIR}/busted)
+ DEPENDS ${BUSTED_EXE})
add_custom_command(OUTPUT ${HOSTDEPS_BIN_DIR}/luacheck
COMMAND ${LUAROCKS_BINARY}
@@ -152,9 +153,9 @@ if(USE_BUNDLED_BUSTED)
if(MINGW AND CMAKE_CROSSCOMPILING)
set(LUV_DEPS ${LUV_DEPS} libuv_host)
endif()
- set(LUV_ARGS CFLAGS='-O0 -g3 -fPIC')
+ set(LUV_ARGS "CFLAGS=-O0 -g3 -fPIC")
if(USE_BUNDLED_LIBUV)
- set(LUV_ARGS LIBUV_DIR=${HOSTDEPS_INSTALL_DIR} CFLAGS='-O0 -g3 -fPIC')
+ list(APPEND LUV_ARGS LIBUV_DIR=${HOSTDEPS_INSTALL_DIR})
endif()
add_custom_command(OUTPUT ${HOSTDEPS_LIB_DIR}/luarocks/rocks/luv
COMMAND ${LUAROCKS_BINARY}