aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CMakeLists.txt22
-rw-r--r--README.md2
-rw-r--r--clint-files.txt2
-rw-r--r--cmake/GenerateHelptags.cmake2
-rw-r--r--cmake/RunTests.cmake2
-rw-r--r--runtime/autoload/provider/clipboard.vim32
-rw-r--r--runtime/autoload/provider/python.vim6
-rw-r--r--runtime/autoload/remote/define.vim (renamed from runtime/autoload/rpc/define.vim)36
-rw-r--r--runtime/autoload/remote/host.vim (renamed from runtime/autoload/rpc/host.vim)63
-rw-r--r--runtime/doc/Makefile4
-rw-r--r--runtime/doc/external_plugin.txt104
-rw-r--r--runtime/doc/job_control.txt2
-rw-r--r--runtime/doc/msgpack_rpc.txt3
-rw-r--r--runtime/doc/nvim_intro.txt2
-rw-r--r--runtime/doc/remote_plugin.txt136
-rw-r--r--runtime/plugin/external_plugins.vim5
-rw-r--r--runtime/plugin/rplugin.vim5
-rwxr-xr-xscripts/vim-patch.sh81
-rw-r--r--src/nvim/CMakeLists.txt72
-rw-r--r--src/nvim/api/vim.c20
-rw-r--r--src/nvim/buffer.c13
-rw-r--r--src/nvim/buffer_defs.h5
-rw-r--r--src/nvim/cursor_shape.c6
-rw-r--r--src/nvim/digraph.c17
-rw-r--r--src/nvim/edit.c54
-rw-r--r--src/nvim/eval.c93
-rw-r--r--src/nvim/ex_cmds.c6
-rw-r--r--src/nvim/ex_docmd.c16
-rw-r--r--src/nvim/ex_getln.c48
-rw-r--r--src/nvim/file_search.c4
-rw-r--r--src/nvim/fileio.c11
-rw-r--r--src/nvim/getchar.c15
-rw-r--r--src/nvim/globals.h5
-rw-r--r--src/nvim/hardcopy.c4
-rw-r--r--src/nvim/if_cscope.c4
-rw-r--r--src/nvim/main.c7
-rw-r--r--src/nvim/mark.c6
-rw-r--r--src/nvim/mbyte.c21
-rw-r--r--src/nvim/memfile.c6
-rw-r--r--src/nvim/memline.c4
-rw-r--r--src/nvim/memory.c18
-rw-r--r--src/nvim/message.c14
-rw-r--r--src/nvim/misc1.c16
-rw-r--r--src/nvim/misc2.c1
-rw-r--r--src/nvim/mouse.c438
-rw-r--r--src/nvim/mouse.h32
-rw-r--r--src/nvim/normal.c37
-rw-r--r--src/nvim/ops.c13
-rw-r--r--src/nvim/option.c24
-rw-r--r--src/nvim/option_defs.h4
-rw-r--r--src/nvim/os/event.c20
-rw-r--r--src/nvim/os/input.c60
-rw-r--r--src/nvim/os_unix.c1
-rw-r--r--src/nvim/path.c8
-rw-r--r--src/nvim/quickfix.c4
-rw-r--r--src/nvim/screen.c28
-rw-r--r--src/nvim/search.c5
-rw-r--r--src/nvim/spell.c6
-rw-r--r--src/nvim/strings.c1
-rw-r--r--src/nvim/syntax.c4
-rw-r--r--src/nvim/tag.c22
-rw-r--r--src/nvim/term.c7
-rw-r--r--src/nvim/testdir/Makefile14
-rw-r--r--src/nvim/testdir/test101.in45
-rw-r--r--src/nvim/testdir/test101.ok11
-rw-r--r--src/nvim/testdir/test104.in30
-rw-r--r--src/nvim/testdir/test104.ok13
-rw-r--r--src/nvim/testdir/test105.in45
-rw-r--r--src/nvim/testdir/test105.ok29
-rw-r--r--src/nvim/testdir/test21.in19
-rw-r--r--src/nvim/testdir/test21.ok2
-rw-r--r--src/nvim/testdir/test25.in31
-rw-r--r--src/nvim/testdir/test25.ok1
-rw-r--r--src/nvim/testdir/test26.in44
-rw-r--r--src/nvim/testdir/test26.ok10
-rw-r--r--src/nvim/testdir/test33.in34
-rw-r--r--src/nvim/testdir/test33.ok23
-rw-r--r--src/nvim/testdir/test43.in34
-rw-r--r--src/nvim/testdir/test43.ok11
-rw-r--r--src/nvim/testdir/test5.in29
-rw-r--r--src/nvim/testdir/test5.ok9
-rw-r--r--src/nvim/testdir/test51.in36
-rw-r--r--src/nvim/testdir/test51.ok20
-rw-r--r--src/nvim/testdir/test66.in33
-rw-r--r--src/nvim/testdir/test66.ok16
-rw-r--r--src/nvim/testdir/test67.in33
-rw-r--r--src/nvim/testdir/test67.ok10
-rw-r--r--src/nvim/testdir/test75.in41
-rw-r--r--src/nvim/testdir/test75.ok7
-rw-r--r--src/nvim/ui.c612
-rw-r--r--src/nvim/ui.h21
-rw-r--r--src/nvim/window.c6
-rw-r--r--test/functional/api/vim_spec.lua43
-rw-r--r--test/functional/api/window_spec.lua4
-rw-r--r--test/functional/fixtures/autoload/Test104.vim (renamed from src/nvim/testdir/sautest/autoload/Test104.vim)0
-rw-r--r--test/functional/helpers.lua94
-rw-r--r--test/functional/job/job_spec.lua11
-rw-r--r--test/functional/legacy/004_bufenter_with_modelines_spec.lua4
-rw-r--r--test/functional/legacy/005_bufleave_delete_buffer.lua71
-rw-r--r--test/functional/legacy/025_jump_tag_hidden_spec.lua50
-rw-r--r--test/functional/legacy/026_execute_while_if_spec.lua66
-rw-r--r--test/functional/legacy/033_lisp_indent_spec.lua73
-rw-r--r--test/functional/legacy/043_magic_settings_spec.lua61
-rw-r--r--test/functional/legacy/051_highlight_spec.lua70
-rw-r--r--test/functional/legacy/066_visual_block_tab_spec.lua64
-rw-r--r--test/functional/legacy/067_augroup_exists_spec.lua46
-rw-r--r--test/functional/legacy/075_maparg_spec.lua58
-rw-r--r--test/functional/legacy/101_hlsearch_spec.lua63
-rw-r--r--test/functional/legacy/104_let_assignment.lua54
-rw-r--r--test/functional/legacy/105_filename_modifiers_spec.lua81
-rw-r--r--test/functional/runtime/autoload/remote/define_spec.lua (renamed from test/functional/runtime/autoload/rpc/define_spec.lua)26
-rw-r--r--test/functional/shell/viml_system_spec.lua7
-rw-r--r--third-party/CMakeLists.txt4
-rw-r--r--third-party/cmake/DownloadAndExtractFile.cmake8
114 files changed, 2079 insertions, 1857 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index f7ecf10816..d2b5217658 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,5 +1,5 @@
-cmake_minimum_required (VERSION 2.8.7)
-project (NEOVIM)
+cmake_minimum_required(VERSION 2.8.7)
+project(NEOVIM)
# Point CMake at any custom modules we may ship
list(APPEND CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake")
@@ -67,11 +67,25 @@ set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
# Default to -O2 on release builds.
string(REPLACE "-O3" "-O2" CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE}")
+# Enable -Wconversion.
+set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wconversion")
+
# gcc 4.0 and better turn on _FORTIFY_SOURCE=2 automatically. This currently
# does not work with Neovim due to some uses of dynamically-sized structures.
# See https://github.com/neovim/neovim/issues/223 for details.
-if(CMAKE_COMPILER_IS_GNUCC AND NOT CMAKE_C_COMPILER_VERSION VERSION_LESS "4"
- AND CMAKE_BUILD_TYPE MATCHES "^Rel")
+include(CheckCSourceCompiles)
+check_c_source_compiles("
+#if defined(_FORTIFY_SOURCE) && _FORTIFY_SOURCE > 1
+#error \"_FORTIFY_SOURCE > 1\"
+#endif
+int
+main(void)
+{
+ return 0;
+}
+" _FORTIFY_SOURCE_ACCEPTABLE)
+
+if(NOT _FORTIFY_SOURCE_ACCEPTABLE)
# -U in add_definitions doesn't end up in the correct spot, so we add it to
# the flags variable instead.
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=1")
diff --git a/README.md b/README.md
index 91bbe7bb9b..0db2a817c3 100644
--- a/README.md
+++ b/README.md
@@ -36,7 +36,7 @@ For lots more details, see
### What's being worked on now
-- Port all IO to [libuv](https://github.com/joyent/libuv/blob/master/README.md)
+- Port all IO to [libuv](https://github.com/libuv/libuv/blob/master/README.md)
- Lots of refactoring
- A VimL => Lua transpiler
diff --git a/clint-files.txt b/clint-files.txt
index a0aec7a31c..6f4a293205 100644
--- a/clint-files.txt
+++ b/clint-files.txt
@@ -25,6 +25,8 @@ src/nvim/map_defs.h
src/nvim/memfile.c
src/nvim/memfile.h
src/nvim/memfile_defs.h
+src/nvim/mouse.c
+src/nvim/mouse.h
src/nvim/msgpack_rpc/channel.c
src/nvim/msgpack_rpc/channel.h
src/nvim/msgpack_rpc/helpers.c
diff --git a/cmake/GenerateHelptags.cmake b/cmake/GenerateHelptags.cmake
index 090cdf8ef4..658f4ab9cc 100644
--- a/cmake/GenerateHelptags.cmake
+++ b/cmake/GenerateHelptags.cmake
@@ -22,5 +22,5 @@ execute_process(
RESULT_VARIABLE res)
if(NOT res EQUAL 0)
- message(FATAL_ERROR "Generating helptags failed: ${err}")
+ message(FATAL_ERROR "Generating helptags failed: ${err} - ${res}")
endif()
diff --git a/cmake/RunTests.cmake b/cmake/RunTests.cmake
index 0f301a6a10..227569f84c 100644
--- a/cmake/RunTests.cmake
+++ b/cmake/RunTests.cmake
@@ -20,5 +20,5 @@ execute_process(
RESULT_VARIABLE res)
if(NOT res EQUAL 0)
- message(FATAL_ERROR "Running ${TEST_TYPE} tests failed.")
+ message(FATAL_ERROR "Running ${TEST_TYPE} tests failed with error: ${res}.")
endif()
diff --git a/runtime/autoload/provider/clipboard.vim b/runtime/autoload/provider/clipboard.vim
index 615a80ca6d..46c05a882c 100644
--- a/runtime/autoload/provider/clipboard.vim
+++ b/runtime/autoload/provider/clipboard.vim
@@ -4,6 +4,15 @@
let s:copy = ''
let s:paste = ''
+function! s:try_cmd(cmd, ...)
+ let out = a:0 ? systemlist(a:cmd, a:1) : systemlist(a:cmd)
+ if v:shell_error
+ echo "clipboard: error: ".(len(out) ? out[0] : '')
+ return ''
+ endif
+ return out
+endfunction
+
if executable('pbcopy')
let s:copy = 'pbcopy'
let s:paste = 'pbpaste'
@@ -13,28 +22,21 @@ elseif executable('xsel')
elseif executable('xclip')
let s:copy = 'xclip -i -selection clipboard'
let s:paste = 'xclip -o -selection clipboard'
-endif
-
-if s:copy == ''
- echom 'No shell command for communicating with the clipboard found.'
+else
+ echom 'clipboard: No shell command for communicating with the clipboard found.'
finish
endif
-let s:methods = {}
+let s:clipboard = {}
-function! s:ClipboardGet(...)
- return systemlist(s:paste)
+function! s:clipboard.get(...)
+ return s:try_cmd(s:paste)
endfunction
-function! s:ClipboardSet(...)
- call systemlist(s:copy, a:1)
+function! s:clipboard.set(...)
+ call s:try_cmd(s:copy, a:1)
endfunction
-let s:methods = {
- \ 'get': function('s:ClipboardGet'),
- \ 'set': function('s:ClipboardSet')
- \ }
-
function! provider#clipboard#Call(method, args)
- return s:methods[a:method](a:args)
+ return s:clipboard[a:method](a:args)
endfunction
diff --git a/runtime/autoload/provider/python.vim b/runtime/autoload/provider/python.vim
index 9ca81c35f4..53b984dfe2 100644
--- a/runtime/autoload/provider/python.vim
+++ b/runtime/autoload/provider/python.vim
@@ -11,11 +11,11 @@ let s:loaded_python_provider = 1
let s:plugin_path = expand('<sfile>:p:h').'/script_host.py'
" The python provider plugin will run in a separate instance of the python
" host.
-call rpc#host#RegisterClone('legacy-python-provider', 'python')
-call rpc#host#RegisterPlugin('legacy-python-provider', s:plugin_path, [])
+call remote#host#RegisterClone('legacy-python-provider', 'python')
+call remote#host#RegisterPlugin('legacy-python-provider', s:plugin_path, [])
" Ensure that we can load the python host before bootstrapping
try
- let s:host = rpc#host#Require('legacy-python-provider')
+ let s:host = remote#host#Require('legacy-python-provider')
catch
echomsg v:exception
finish
diff --git a/runtime/autoload/rpc/define.vim b/runtime/autoload/remote/define.vim
index e7817c5fac..dd2482998d 100644
--- a/runtime/autoload/rpc/define.vim
+++ b/runtime/autoload/remote/define.vim
@@ -1,4 +1,4 @@
-function! rpc#define#CommandOnHost(host, method, sync, name, opts)
+function! remote#define#CommandOnHost(host, method, sync, name, opts)
let prefix = ''
if has_key(a:opts, 'range')
@@ -28,7 +28,7 @@ function! rpc#define#CommandOnHost(host, method, sync, name, opts)
endif
exe s:GetCommandPrefix(a:name, a:opts)
- \ .' call rpc#define#CommandBootstrap("'.a:host.'"'
+ \ .' call remote#define#CommandBootstrap("'.a:host.'"'
\ . ', "'.a:method.'"'
\ . ', "'.a:sync.'"'
\ . ', "'.a:name.'"'
@@ -38,11 +38,11 @@ function! rpc#define#CommandOnHost(host, method, sync, name, opts)
endfunction
-function! rpc#define#CommandBootstrap(host, method, sync, name, opts, forward)
- let channel = rpc#host#Require(a:host)
+function! remote#define#CommandBootstrap(host, method, sync, name, opts, forward)
+ let channel = remote#host#Require(a:host)
if channel
- call rpc#define#CommandOnChannel(channel, a:method, a:sync, a:name, a:opts)
+ call remote#define#CommandOnChannel(channel, a:method, a:sync, a:name, a:opts)
exe a:forward
else
exe 'delcommand '.a:name
@@ -51,7 +51,7 @@ function! rpc#define#CommandBootstrap(host, method, sync, name, opts, forward)
endfunction
-function! rpc#define#CommandOnChannel(channel, method, sync, name, opts)
+function! remote#define#CommandOnChannel(channel, method, sync, name, opts)
let rpcargs = [a:channel, '"'.a:method.'"']
if has_key(a:opts, 'nargs')
" -nargs, pass arguments in a list
@@ -87,12 +87,12 @@ function! rpc#define#CommandOnChannel(channel, method, sync, name, opts)
endfunction
-function! rpc#define#AutocmdOnHost(host, method, sync, name, opts)
+function! remote#define#AutocmdOnHost(host, method, sync, name, opts)
let group = s:GetNextAutocmdGroup()
let forward = '"doau '.group.' '.a:name.' ".'.'expand("<amatch>")'
let a:opts.group = group
let bootstrap_def = s:GetAutocmdPrefix(a:name, a:opts)
- \ .' call rpc#define#AutocmdBootstrap("'.a:host.'"'
+ \ .' call remote#define#AutocmdBootstrap("'.a:host.'"'
\ . ', "'.a:method.'"'
\ . ', "'.a:sync.'"'
\ . ', "'.a:name.'"'
@@ -103,12 +103,12 @@ function! rpc#define#AutocmdOnHost(host, method, sync, name, opts)
endfunction
-function! rpc#define#AutocmdBootstrap(host, method, sync, name, opts, forward)
- let channel = rpc#host#Require(a:host)
+function! remote#define#AutocmdBootstrap(host, method, sync, name, opts, forward)
+ let channel = remote#host#Require(a:host)
exe 'autocmd! '.a:opts.group
if channel
- call rpc#define#AutocmdOnChannel(channel, a:method, a:sync, a:name,
+ call remote#define#AutocmdOnChannel(channel, a:method, a:sync, a:name,
\ a:opts)
exe eval(a:forward)
else
@@ -118,7 +118,7 @@ function! rpc#define#AutocmdBootstrap(host, method, sync, name, opts, forward)
endfunction
-function! rpc#define#AutocmdOnChannel(channel, method, sync, name, opts)
+function! remote#define#AutocmdOnChannel(channel, method, sync, name, opts)
let rpcargs = [a:channel, '"'.a:method.'"']
call s:AddEval(rpcargs, a:opts)
@@ -128,10 +128,10 @@ function! rpc#define#AutocmdOnChannel(channel, method, sync, name, opts)
endfunction
-function! rpc#define#FunctionOnHost(host, method, sync, name, opts)
+function! remote#define#FunctionOnHost(host, method, sync, name, opts)
let group = s:GetNextAutocmdGroup()
exe 'autocmd! '.group.' FuncUndefined '.a:name
- \ .' call rpc#define#FunctionBootstrap("'.a:host.'"'
+ \ .' call remote#define#FunctionBootstrap("'.a:host.'"'
\ . ', "'.a:method.'"'
\ . ', "'.a:sync.'"'
\ . ', "'.a:name.'"'
@@ -141,13 +141,13 @@ function! rpc#define#FunctionOnHost(host, method, sync, name, opts)
endfunction
-function! rpc#define#FunctionBootstrap(host, method, sync, name, opts, group)
- let channel = rpc#host#Require(a:host)
+function! remote#define#FunctionBootstrap(host, method, sync, name, opts, group)
+ let channel = remote#host#Require(a:host)
exe 'autocmd! '.a:group
exe 'augroup! '.a:group
if channel
- call rpc#define#FunctionOnChannel(channel, a:method, a:sync, a:name,
+ call remote#define#FunctionOnChannel(channel, a:method, a:sync, a:name,
\ a:opts)
else
echoerr 'Host "'a:host.'" for "'.a:name.'" function is not available'
@@ -155,7 +155,7 @@ function! rpc#define#FunctionBootstrap(host, method, sync, name, opts, group)
endfunction
-function! rpc#define#FunctionOnChannel(channel, method, sync, name, opts)
+function! remote#define#FunctionOnChannel(channel, method, sync, name, opts)
let rpcargs = [a:channel, '"'.a:method.'"', 'a:000']
call s:AddEval(rpcargs, a:opts)
diff --git a/runtime/autoload/rpc/host.vim b/runtime/autoload/remote/host.vim
index 177d816df0..b07593f39b 100644
--- a/runtime/autoload/rpc/host.vim
+++ b/runtime/autoload/remote/host.vim
@@ -2,11 +2,12 @@ let s:hosts = {}
let s:plugin_patterns = {
\ 'python': '*.py'
\ }
-let s:external_plugins = fnamemodify($MYVIMRC, ':p:h').'/.external_plugins~'
+let s:remote_plugins_manifest = fnamemodify($MYVIMRC, ':p:h')
+ \.'/.'.fnamemodify($MYVIMRC, ':t').'-rplugin~'
" Register a host by associating it with a factory(funcref)
-function! rpc#host#Register(name, factory)
+function! remote#host#Register(name, factory)
let s:hosts[a:name] = {'factory': a:factory, 'channel': 0, 'initialized': 0}
if type(a:factory) == type(1) && a:factory
" Passed a channel directly
@@ -19,7 +20,7 @@ endfunction
" as `source`, but it will run as a different process. This can be used by
" plugins that should run isolated from other plugins created for the same host
" type
-function! rpc#host#RegisterClone(name, orig_name)
+function! remote#host#RegisterClone(name, orig_name)
if !has_key(s:hosts, a:orig_name)
throw 'No host named "'.a:orig_name.'" is registered'
endif
@@ -29,7 +30,7 @@ endfunction
" Get a host channel, bootstrapping it if necessary
-function! rpc#host#Require(name)
+function! remote#host#Require(name)
if !has_key(s:hosts, a:name)
throw 'No host named "'.a:name.'" is registered'
endif
@@ -42,7 +43,7 @@ function! rpc#host#Require(name)
endfunction
-function! rpc#host#IsRunning(name)
+function! remote#host#IsRunning(name)
if !has_key(s:hosts, a:name)
throw 'No host named "'.a:name.'" is registered'
endif
@@ -54,7 +55,7 @@ endfunction
" autocmd(async) and one function(sync):
"
" let s:plugin_path = expand('<sfile>:p:h').'/nvim_plugin.py'
-" call rpc#host#RegisterPlugin('python', s:plugin_path, [
+" call remote#host#RegisterPlugin('python', s:plugin_path, [
" \ {'type': 'command', 'name': 'PyCmd', 'sync': 1, 'opts': {}},
" \ {'type': 'command', 'name': 'PyAsyncCmd', 'sync': 0, 'opts': {'eval': 'cursor()'}},
" \ {'type': 'autocmd', 'name': 'BufEnter', 'sync': 0, 'opts': {'eval': 'expand("<afile>")'}},
@@ -63,7 +64,7 @@ endfunction
"
" The third item in a declaration is a boolean: non zero means the command,
" autocommand or function will be executed synchronously with rpcrequest.
-function! rpc#host#RegisterPlugin(host, path, specs)
+function! remote#host#RegisterPlugin(host, path, specs)
let plugins = s:PluginsForHost(a:host)
for plugin in plugins
@@ -72,7 +73,7 @@ function! rpc#host#RegisterPlugin(host, path, specs)
endif
endfor
- if rpc#host#IsRunning(a:host)
+ if remote#host#IsRunning(a:host)
" For now we won't allow registration of plugins when the host is already
" running.
throw 'Host "'.a:host.'" is already running'
@@ -86,7 +87,7 @@ function! rpc#host#RegisterPlugin(host, path, specs)
let rpc_method = a:path
if type == 'command'
let rpc_method .= ':command:'.name
- call rpc#define#CommandOnHost(a:host, rpc_method, sync, name, opts)
+ call remote#define#CommandOnHost(a:host, rpc_method, sync, name, opts)
elseif type == 'autocmd'
" Since multiple handlers can be attached to the same autocmd event by a
" single plugin, we need a way to uniquely identify the rpc method to
@@ -94,10 +95,10 @@ function! rpc#host#RegisterPlugin(host, path, specs)
" name(This still has a limit: one handler per event/pattern combo, but
" there's no need to allow plugins define multiple handlers in that case)
let rpc_method .= ':autocmd:'.name.':'.get(opts, 'pattern', '*')
- call rpc#define#AutocmdOnHost(a:host, rpc_method, sync, name, opts)
+ call remote#define#AutocmdOnHost(a:host, rpc_method, sync, name, opts)
elseif type == 'function'
let rpc_method .= ':function:'.name
- call rpc#define#FunctionOnHost(a:host, rpc_method, sync, name, opts)
+ call remote#define#FunctionOnHost(a:host, rpc_method, sync, name, opts)
else
echoerr 'Invalid declaration type: '.type
endif
@@ -107,9 +108,9 @@ function! rpc#host#RegisterPlugin(host, path, specs)
endfunction
-function! rpc#host#LoadExternalPlugins()
- if filereadable(s:external_plugins)
- exe 'source '.s:external_plugins
+function! remote#host#LoadRemotePlugins()
+ if filereadable(s:remote_plugins_manifest)
+ exe 'source '.s:remote_plugins_manifest
endif
endfunction
@@ -117,17 +118,22 @@ endfunction
function! s:RegistrationCommands(host)
" Register a temporary host clone for discovering specs
let host_id = a:host.'-registration-clone'
- call rpc#host#RegisterClone(host_id, a:host)
+ call remote#host#RegisterClone(host_id, a:host)
let pattern = s:plugin_patterns[a:host]
- let paths = globpath(&rtp, 'plugin/external/'.a:host.'/'.pattern, 0, 1)
+ let paths = globpath(&rtp, 'rplugin/'.a:host.'/'.pattern, 0, 1)
+ if len(paths) < 1
+ echom "Could not find any plugins when attempting to register plugin "
+ \ ."commands. See :he remote-plugin"
+ return []
+ endif
for path in paths
- call rpc#host#RegisterPlugin(host_id, path, [])
+ call remote#host#RegisterPlugin(host_id, path, [])
endfor
- let channel = rpc#host#Require(host_id)
+ let channel = remote#host#Require(host_id)
let lines = []
for path in paths
let specs = rpcrequest(channel, 'specs', path)
- call add(lines, "call rpc#host#RegisterPlugin('".a:host
+ call add(lines, "call remote#host#RegisterPlugin('".a:host
\ ."', '".path."', [")
for spec in specs
call add(lines, " \\ ".string(spec).",")
@@ -142,7 +148,7 @@ function! s:RegistrationCommands(host)
endfunction
-function! s:UpdateExternalPlugins()
+function! s:UpdateRemotePlugins()
let commands = []
let hosts = keys(s:hosts)
for host in hosts
@@ -153,11 +159,11 @@ function! s:UpdateExternalPlugins()
\ + ['', '']
endif
endfor
- call writefile(commands, s:external_plugins)
+ call writefile(commands, s:remote_plugins_manifest)
endfunction
-command! UpdateExternalPlugins call s:UpdateExternalPlugins()
+command! UpdateRemotePlugins call s:UpdateRemotePlugins()
let s:plugins_for_host = {}
@@ -213,7 +219,9 @@ function! s:RequirePythonHost(name)
" In some distros, python3 is the default python
let python_host_prog = 'python2'
else
- throw 'No python interpreter found'
+ throw 'No python interpreter found.' .
+ \ " Try setting 'let g:python_host_prog=/path/to/python' in your '.nvimrc'" .
+ \ " or see ':help nvim-python'."
endif
" Make sure we pick correct python version on path.
@@ -225,7 +233,8 @@ function! s:RequirePythonHost(name)
let import_result = system(python_host_prog .
\ ' -c "import neovim, sys; sys.stdout.write(\"ok\")"')
if import_result != 'ok'
- throw 'No neovim module found for ' . python_version
+ throw 'No neovim module found for ' . python_version . '.' .
+ \ " Try installing it with 'pip install neovim' or see ':help nvim-python'."
endif
try
@@ -235,8 +244,10 @@ function! s:RequirePythonHost(name)
endif
catch
endtry
- throw 'Failed to load python host'
+ throw 'Failed to load python host.' .
+ \ " Try upgrading the Neovim python module with 'pip install --upgrade neovim'" .
+ \ " or see ':help nvim-python'."
endfunction
-call rpc#host#Register('python', function('s:RequirePythonHost'))
+call remote#host#Register('python', function('s:RequirePythonHost'))
" }}}
diff --git a/runtime/doc/Makefile b/runtime/doc/Makefile
index 48674a773f..82fd921038 100644
--- a/runtime/doc/Makefile
+++ b/runtime/doc/Makefile
@@ -21,6 +21,7 @@ DOCS = \
digraph.txt \
editing.txt \
eval.txt \
+ remote_plugin.txt \
farsi.txt \
filetype.txt \
fold.txt \
@@ -53,6 +54,7 @@ DOCS = \
msgpack_rpc.txt \
nvim_clipboard.txt \
nvim_intro.txt \
+ nvim_provider.txt \
nvim_python.txt \
options.txt \
os_dos.txt \
@@ -140,6 +142,7 @@ HTMLS = \
digraph.html \
editing.html \
eval.html \
+ remote_plugin.html \
farsi.html \
filetype.html \
fold.html \
@@ -171,6 +174,7 @@ HTMLS = \
msgpack_rpc.html \
nvim_clipboard.html \
nvim_intro.html \
+ nvim_provider.html \
nvim_python.html \
options.html \
os_dos.html \
diff --git a/runtime/doc/external_plugin.txt b/runtime/doc/external_plugin.txt
deleted file mode 100644
index 3f7772c906..0000000000
--- a/runtime/doc/external_plugin.txt
+++ /dev/null
@@ -1,104 +0,0 @@
-*external_plugin.txt* For Nvim. {Nvim}
-
-
- NVIM REFERENCE MANUAL by Thiago de Arruda
-
-
-Nvim support for external plugins *external-plugin*
-
-1. Introduction |external-plugin-intro|
-2. Plugin Hosts |external-plugin-hosts|
-3. Example |external-plugin-example|
-
-==============================================================================
-1. Introduction *external-plugin-intro*
-
-A big Nvim goal is to allow extensibility in arbitrary programming languages
-without requiring direct support from the editor. This is achieved with
-external plugins, coprocesses that have a direct communication channel(via
-|msgpack-rpc|) with the Nvim process.
-
-Even though these plugins are running in separate processes, they can call, be
-called, and receive events just as if the code was being executed in the main
-process.
-
-==============================================================================
-2. Plugin Hosts *external-plugin-hosts*
-
-While plugins can be implemented as arbitrary programs that communicate
-directly with Nvim API and are called via |rpcrequest()| and |rpcnotify()|,
-that is not the best approach available. Instead, developers should first
-check if a plugin host implementation is available for their favorite
-programming language.
-
-Plugin hosts are programs that provide a high level environment for plugins,
-and also take care of most boilerplate involved in defining commands, autocmds
-and functions that are implemented over msgpack-rpc connections. They are
-loaded the first time one of it's registered plugins are required, keeping
-Nvim startup as fast a possible despite the number of installed plugins/hosts.
-
-==============================================================================
-3. Example *external-plugin-example*
-
-The best way to learn how to create external plugins is with an example, so
-let's see how to implement a very useless python plugin that exports a
-command, a function and an autocmd(requires configuration detailed in
-|nvim-python| to work).
-
-The plugin is called 'Limit', and all it does is limit the number of "calls"
-made to it. Here's the plugin source code:
->
- import neovim
-
- @neovim.plugin
- class Limit(object):
- def __init__(self, vim):
- self.vim = vim
- self.calls = 0
-
- @neovim.command('Cmd', range='', nargs='*', sync=True)
- def command_handler(self, args, range):
- self._increment_calls()
- self.vim.current.line = (
- 'Command: Called %d times, args: %s, range: %s' % (self.calls,
- args,
- range))
-
- @neovim.autocmd('BufEnter', pattern='*.py', eval='expand("<afile>")',
- sync=True)
- def autocmd_handler(self, filename):
- self._increment_calls()
- self.vim.current.line = (
- 'Autocmd: Called %s times, file: %s' % (self.calls, filename))
-
- @neovim.function('Func')
- def function_handler(self, args):
- self._increment_calls()
- self.vim.current.line = (
- 'Function: Called %d times, args: %s' % (self.calls, args))
-
- def _increment_calls(self):
- if self.calls == 5:
- raise Exception('Too many calls!')
- self.calls += 1
-<
-
-This code needs to be saved to "external/python/limit.py" in a runtime
-directory(~/.nvim/plugin/external/python/limit.py for example).
-
-As can be seen, the plugin is implemented using pure python idioms(classes,
-methods and decorators). It is the host's responsibility to translate
-language-specific idioms to vimscript entities. Notice that the exported
-command and autocmd are defined with the "sync" flag, which tells Nvim to call
-it using |rpcrequest()|. Since the "Func" doesn't set "sync", it will be
-called using |rpcnotify()|.
-
-Just installing the plugin to ~/.nvim/plugin/external/python/limit.py won't
-make Nvim load it at startup. That is because external plugins are loaded
-only when required, and for that Nvim must be fed with information about
-installed external plugins with the `:UpdateExternalPlugins` command(must be
-called whenever plugins are updated, this is analogous to the |:helptags|
-command but for external plugins).
-
-==============================================================================
- vim:tw=78:ts=8:noet:ft=help:norl:
diff --git a/runtime/doc/job_control.txt b/runtime/doc/job_control.txt
index 226244875d..f381d5ad66 100644
--- a/runtime/doc/job_control.txt
+++ b/runtime/doc/job_control.txt
@@ -31,7 +31,7 @@ facilities for calling with external commands, job control does not depend
on installed shells, calling OS functions for process management directly.
Internally, Nvim job control is powered by libuv, which has a nice
-cross-platform API for managing processes. See https://github.com/joyent/libuv
+cross-platform API for managing processes. See https://github.com/libuv/libuv
for details
==============================================================================
diff --git a/runtime/doc/msgpack_rpc.txt b/runtime/doc/msgpack_rpc.txt
index 41f387b452..0fb419e5d5 100644
--- a/runtime/doc/msgpack_rpc.txt
+++ b/runtime/doc/msgpack_rpc.txt
@@ -113,7 +113,8 @@ string 'hello world!' on the current nvim instance:
A better way is to use the python REPL with the `neovim` package, where API
functions can be called interactively:
>
- >>> import neovim; nvim = neovim.connect('[address]')
+ >>> from neovim import attach
+ >>> nvim = attach('socket', path='[address]')
>>> nvim.command('echo "hello world!"')
<
==============================================================================
diff --git a/runtime/doc/nvim_intro.txt b/runtime/doc/nvim_intro.txt
index 177c906db6..8a82a09890 100644
--- a/runtime/doc/nvim_intro.txt
+++ b/runtime/doc/nvim_intro.txt
@@ -17,7 +17,7 @@ differentiate Nvim from Vim:
2. Job control |job-control|
3. Python plugins |nvim-python|
4. Clipboard integration |nvim-clipboard|
-5. External plugins |external-plugin|
+5. Remote plugins |remote-plugin|
6. Provider infrastructure |nvim-provider|
==============================================================================
diff --git a/runtime/doc/remote_plugin.txt b/runtime/doc/remote_plugin.txt
new file mode 100644
index 0000000000..ca7e763d1b
--- /dev/null
+++ b/runtime/doc/remote_plugin.txt
@@ -0,0 +1,136 @@
+*remote_plugin.txt* For Nvim. {Nvim}
+
+
+ NVIM REFERENCE MANUAL by Thiago de Arruda
+
+
+Nvim support for remote plugins *remote-plugin*
+
+1. Introduction |remote-plugin-intro|
+2. Plugin hosts |remote-plugin-hosts|
+3. Example |remote-plugin-example|
+4. Plugin manifest |remote-plugin-manifest|
+
+==============================================================================
+1. Introduction *remote-plugin-intro*
+
+A big Nvim goal is to allow extensibility in arbitrary programming languages
+without requiring direct support from the editor. This is achieved with
+remote plugins, coprocesses that have a direct communication channel(via
+|msgpack-rpc|) with the Nvim process.
+
+Even though these plugins are running in separate processes, they can call, be
+called, and receive events just as if the code was being executed in the main
+process.
+
+==============================================================================
+2. Plugin hosts *remote-plugin-hosts*
+
+While plugins can be implemented as arbitrary programs that communicate
+directly with Nvim API and are called via |rpcrequest()| and |rpcnotify()|,
+that is not the best approach available. Instead, developers should first
+check if a plugin host implementation is available for their favorite
+programming language.
+
+Plugin hosts are programs that provide a high level environment for plugins,
+and also take care of most boilerplate involved in defining commands, autocmds
+and functions that are implemented over msgpack-rpc connections. They are
+loaded the first time one of its registered plugins are required, keeping
+Nvim startup as fast a possible despite the number of installed plugins/hosts.
+
+==============================================================================
+3. Example *remote-plugin-example*
+
+The best way to learn about remote plugins is with an example, so let's see
+how a very useless python plugin looks like. This plugin exports a command, a
+function and an autocmd. The plugin is called 'Limit', and all it does is
+limit the number of requests made to it. Here's the plugin source code:
+>
+ import neovim
+
+ @neovim.plugin
+ class Limit(object):
+ def __init__(self, vim):
+ self.vim = vim
+ self.calls = 0
+
+ @neovim.command('Cmd', range='', nargs='*', sync=True)
+ def command_handler(self, args, range):
+ self._increment_calls()
+ self.vim.current.line = (
+ 'Command: Called %d times, args: %s, range: %s' % (self.calls,
+ args,
+ range))
+
+ @neovim.autocmd('BufEnter', pattern='*.py', eval='expand("<afile>")',
+ sync=True)
+ def autocmd_handler(self, filename):
+ self._increment_calls()
+ self.vim.current.line = (
+ 'Autocmd: Called %s times, file: %s' % (self.calls, filename))
+
+ @neovim.function('Func')
+ def function_handler(self, args):
+ self._increment_calls()
+ self.vim.current.line = (
+ 'Function: Called %d times, args: %s' % (self.calls, args))
+
+ def _increment_calls(self):
+ if self.calls == 5:
+ raise Exception('Too many calls!')
+ self.calls += 1
+<
+
+As can be seen, the plugin is implemented using pure python idioms(classes,
+methods and decorators), the translation between these language-specific
+idioms to vimscript occurs while the plugin manifest is being generated(see
+below).
+
+Notice that the exported command and autocmd are defined with the "sync" flag,
+which affects how Nvim calls the plugin: with "sync" the |rpcrequest()|
+function is used, which will block Nvim until the handler function returns a
+value. Without the "sync" flag, the call is made using a fire and forget
+approach with |rpcnotify()|(return values or exceptions raised in the handler
+function are ignored)
+
+To test the above plugin, it must be saved in "rplugin/python" in a
+'runtimepath' directory(~/.nvim/rplugin/python/limit.py for example).
+Then, the remote plugin manifest must be generated with
+`:UpdateRemotePlugins`.
+
+==============================================================================
+4. remote plugin manifest *remote-plugin-manifest*
+
+Just installing remote plugins to "rplugin/{host}" isn't enough to
+load them at startup. The `:UpdateRemotePlugins` command must be executed
+every time a remote plugin is installed, updated, or deleted.
+
+`:UpdateRemotePlugins` will generate the remote plugin manifest, a special
+vimscript file containing declarations for all vimscript entities
+(commands/autocommands/functions) defined by all remote plugins, with each
+entity associated with the host and plugin path. The manifest can be seen as a
+generated extension to the user's vimrc(it even has the vimrc filename
+prepended).
+
+The manifest declarations are nothing but calls to the remote#host#RegisterPlugin
+function, which will take care of bootstrapping the host as soon as the
+declared command, autocommand or function is used for the first time.
+
+The manifest generation step is necessary to keep editor startup fast in
+situations where a user has remote plugins with different hosts. For
+example, imagine a user that has three plugins, for python, java and .NET
+hosts respectively, if we were to load all three plugins at startup, then
+three language runtimes would also be spawned which could take seconds!
+
+With the manifest, each host will only be loaded when required. Continuing
+with the example, imagine the java plugin is a semantic completion engine for
+java files, if it defines an BufEnter *.java autocommand then the java host
+will only be spawned when java source files are loaded.
+
+If the explicit call to `:UpdateRemotePlugins` seems incovenient, try
+to see it like this: Its a way to give IDE-like capabilities to nvim while
+still keeping it a fast/lightweight editor for general use. It can also be
+seen as an analogous to the |:helptags| facility.
+
+==============================================================================
+ vim:tw=78:ts=8:noet:ft=help:norl:
diff --git a/runtime/plugin/external_plugins.vim b/runtime/plugin/external_plugins.vim
deleted file mode 100644
index 1c5fa1ab8e..0000000000
--- a/runtime/plugin/external_plugins.vim
+++ /dev/null
@@ -1,5 +0,0 @@
-if exists('loaded_external_plugins') || &cp
- finish
-endif
-let loaded_external_plugins = 1
-call rpc#host#LoadExternalPlugins()
diff --git a/runtime/plugin/rplugin.vim b/runtime/plugin/rplugin.vim
new file mode 100644
index 0000000000..2b2d333738
--- /dev/null
+++ b/runtime/plugin/rplugin.vim
@@ -0,0 +1,5 @@
+if exists('loaded_remote_plugins') || &cp
+ finish
+endif
+let loaded_remote_plugins = 1
+call remote#host#LoadRemotePlugins()
diff --git a/scripts/vim-patch.sh b/scripts/vim-patch.sh
new file mode 100755
index 0000000000..7c07524090
--- /dev/null
+++ b/scripts/vim-patch.sh
@@ -0,0 +1,81 @@
+#!/bin/bash -e
+
+NEOVIM_SOURCE_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
+VIM_SOURCE_DIR_DEFAULT=${NEOVIM_SOURCE_DIR}/build/vim
+VIM_SOURCE_DIR="${VIM_SOURCE_DIR:-${VIM_SOURCE_DIR_DEFAULT}}"
+
+if [[ ${#} != 1 ]]; then
+ >&2 echo "Helper script for porting Vim patches. For more information,"
+ >&2 echo "see https://github.com/neovim/neovim/wiki/Merging-patches-from-upstream-vim."
+ >&2 echo
+ >&2 echo "Usage: ${0} vim-version"
+ >&2 echo "vim-version must be in format '7.4.xxx'."
+ >&2 echo
+ >&2 echo "Set VIM_SOURCE_DIR to change where Vim's sources are stored."
+ >&2 echo "The default is '${VIM_SOURCE_DIR_DEFAULT}'."
+ exit 1
+fi
+
+vim_version="${1}"
+if [[ ! ${vim_version} =~ [0-9]\.[0-9]\.[0-9][0-9][0-9] ]]; then
+ >&2 echo "vim-version must be in format '7.4.xxx'."
+ exit 2
+fi
+
+if [[ ! -d ${VIM_SOURCE_DIR} ]]; then
+ echo "Cloning Vim sources into '${VIM_SOURCE_DIR}'."
+ hg clone https://code.google.com/p/vim ${VIM_SOURCE_DIR}
+ cd ${VIM_SOURCE_DIR}
+else
+ echo "Updating Vim sources in '${VIM_SOURCE_DIR}'."
+ cd ${VIM_SOURCE_DIR}
+ hg pull --update
+fi
+
+vim_tag="v${vim_version//./-}"
+echo "Using Vim tag '${vim_tag}'."
+
+hg log --rev ${vim_tag} >/dev/null 2>&1 || {
+ >&2 echo "Couldn't find Vim tag '${vim_tag}'."
+ exit 3
+}
+
+vim_full="$(hg log --patch --git --verbose --rev ${vim_tag})"
+vim_message="$(hg log --template "{desc}" --rev ${vim_tag} \
+ | sed -e '1d')" # Remove first line of commit message.
+vim_diff="$(hg diff --show-function --git --change ${vim_tag} \
+ | sed -e 's/\( [ab]\/src\)/\1\/nvim/g')" # Change directory to src/nvim.
+
+
+neovim_branch="vim-${vim_version}"
+echo
+echo "Creating Neovim branch '${neovim_branch}'."
+cd ${NEOVIM_SOURCE_DIR}
+git checkout -b "${neovim_branch}"
+
+echo
+echo "Saving patch to '${NEOVIM_SOURCE_DIR}/${neovim_branch}.patch'."
+echo "${vim_diff}" > ${NEOVIM_SOURCE_DIR}/${neovim_branch}.patch
+
+echo "Saving full commit details to '${NEOVIM_SOURCE_DIR}/${neovim_branch}.commit'."
+echo "${vim_full}" > ${NEOVIM_SOURCE_DIR}/${neovim_branch}.commit
+
+echo
+echo "Creating empty Neovim commit with correct commit message."
+neovim_message="
+vim-patch:${vim_version}
+
+${vim_message}
+
+https://code.google.com/p/vim/source/detail?r=${vim_tag}"
+
+git commit --allow-empty --file - <<< "${neovim_message}"
+
+echo
+echo "Proceed to port the patch and stage your changes ('git add ...')."
+echo "Then use 'git commit --amend' to commit."
+echo "Push your changes with 'git push origin ${neovim_branch}' and create a"
+echo "pull request called '[RFC] vim-patch:${vim_version}'."
+echo
+echo "See https://github.com/neovim/neovim/wiki/Merging-patches-from-upstream-vim"
+echo "for more information."
diff --git a/src/nvim/CMakeLists.txt b/src/nvim/CMakeLists.txt
index b06b4fa547..a2d052c4ec 100644
--- a/src/nvim/CMakeLists.txt
+++ b/src/nvim/CMakeLists.txt
@@ -38,34 +38,66 @@ endforeach()
list(REMOVE_ITEM NEOVIM_SOURCES ${to_remove})
+# Handle legacy files that don't yet pass -Wconversion.
set(CONV_SOURCES
- arabic.c
- cursor.c
- garray.c
- hashtab.c
- log.c
- map.c
- memfile.c
- memory.c
- misc2.c
- profile.c
- tempfile.c
- )
+ buffer.c
+ charset.c
+ diff.c
+ edit.c
+ eval.c
+ ex_cmds2.c
+ ex_cmds.c
+ ex_docmd.c
+ ex_eval.c
+ ex_getln.c
+ farsi.c
+ fileio.c
+ file_search.c
+ fold.c
+ getchar.c
+ hardcopy.c
+ if_cscope.c
+ indent.c
+ indent_c.c
+ keymap.c
+ main.c
+ mark.c
+ mbyte.c
+ memline.c
+ menu.c
+ message.c
+ misc1.c
+ move.c
+ normal.c
+ ops.c
+ option.c
+ os_unix.c
+ path.c
+ popupmnu.c
+ quickfix.c
+ regexp.c
+ regexp_nfa.c
+ screen.c
+ search.c
+ sha256.c
+ spell.c
+ strings.c
+ syntax.c
+ tag.c
+ term.c
+ ui.c
+ undo.c
+ version.c
+ window.c)
foreach(sfile ${CONV_SOURCES})
if(NOT EXISTS "${PROJECT_SOURCE_DIR}/src/nvim/${sfile}")
- message(FATAL_ERROR "${sfile} doesn't exist(it was added to CONV_SOURCES)")
+ message(FATAL_ERROR "${sfile} doesn't exist (it was added to CONV_SOURCES)")
endif()
endforeach()
-file(GLOB_RECURSE EXTRA_CONV_SOURCES os/*.c api/*.c msgpack_rpc/*.c)
-foreach(sfile ${EXTRA_CONV_SOURCES})
- file(RELATIVE_PATH f "${PROJECT_SOURCE_DIR}/src/nvim" "${sfile}")
- list(APPEND CONV_SOURCES ${f})
-endforeach()
-
set_source_files_properties(
- ${CONV_SOURCES} PROPERTIES COMPILE_FLAGS "${COMPILE_FLAGS} -Wconversion")
+ ${CONV_SOURCES} PROPERTIES COMPILE_FLAGS "${COMPILE_FLAGS} -Wno-conversion")
if(CMAKE_C_COMPILER_ID MATCHES "Clang")
if(DEFINED ENV{SANITIZE})
diff --git a/src/nvim/api/vim.c b/src/nvim/api/vim.c
index addcbf62e9..fc1307090d 100644
--- a/src/nvim/api/vim.c
+++ b/src/nvim/api/vim.c
@@ -49,8 +49,10 @@ void vim_command(String str, Error *err)
///
/// @param keys to be typed
/// @param mode specifies the mapping options
+/// @param escape_csi the string needs escaping for K_SPECIAL/CSI bytes
/// @see feedkeys()
-void vim_feedkeys(String keys, String mode)
+/// @see vim_strsave_escape_csi
+void vim_feedkeys(String keys, String mode, Boolean escape_csi)
FUNC_ATTR_DEFERRED
{
bool remap = true;
@@ -68,12 +70,20 @@ void vim_feedkeys(String keys, String mode)
}
}
- /* Need to escape K_SPECIAL and CSI before putting the string in the
- * typeahead buffer. */
- char *keys_esc = (char *)vim_strsave_escape_csi((char_u *)keys.data);
+ char *keys_esc;
+ if (escape_csi) {
+ // Need to escape K_SPECIAL and CSI before putting the string in the
+ // typeahead buffer.
+ keys_esc = (char *)vim_strsave_escape_csi((char_u *)keys.data);
+ } else {
+ keys_esc = keys.data;
+ }
ins_typebuf((char_u *)keys_esc, (remap ? REMAP_YES : REMAP_NONE),
typebuf.tb_len, !typed, false);
- free(keys_esc);
+
+ if (escape_csi) {
+ free(keys_esc);
+ }
if (vgetc_busy)
typebuf_was_filled = true;
diff --git a/src/nvim/buffer.c b/src/nvim/buffer.c
index 6b5b97fe67..ec10a826c7 100644
--- a/src/nvim/buffer.c
+++ b/src/nvim/buffer.c
@@ -69,10 +69,11 @@
#include "nvim/strings.h"
#include "nvim/syntax.h"
#include "nvim/term.h"
-#include "nvim/ui.h"
#include "nvim/undo.h"
#include "nvim/window.h"
#include "nvim/os/os.h"
+#include "nvim/os/time.h"
+#include "nvim/os/input.h"
#define HAVE_BUFLIST_MATCH
@@ -716,7 +717,7 @@ do_bufdel (
} else /* addr_count == 1 */
bnr = end_bnr;
- for (; !got_int; ui_breakcheck()) {
+ for (; !got_int; os_breakcheck()) {
/*
* delete the current buffer last, otherwise when the
* current buffer is deleted, the next buffer becomes
@@ -1422,7 +1423,7 @@ buflist_new (
EMSG(_("W14: Warning: List of file names overflow"));
if (emsg_silent == 0) {
out_flush();
- ui_delay(3000L, true); /* make sure it is noticed */
+ os_delay(3000L, true); /* make sure it is noticed */
}
top_file_num = 1;
}
@@ -2162,7 +2163,7 @@ void buflist_list(exarg_T *eap)
: (int64_t)buflist_findlnum(buf));
msg_outtrans(IObuff);
out_flush(); /* output one line at a time */
- ui_breakcheck();
+ os_breakcheck();
}
}
@@ -3801,7 +3802,7 @@ do_arg_all (
++autocmd_no_leave;
use_firstwin = FALSE;
}
- ui_breakcheck();
+ os_breakcheck();
/* When ":tab" was used open a new tab for a new window repeatedly. */
if (had_tab > 0 && tabpage_index(NULL) <= p_tpm)
@@ -3965,7 +3966,7 @@ void ex_buffer_all(exarg_T *eap)
#endif
}
- ui_breakcheck();
+ os_breakcheck();
if (got_int) {
(void)vgetc(); /* only break the file loading, not the rest */
break;
diff --git a/src/nvim/buffer_defs.h b/src/nvim/buffer_defs.h
index 196b975d2a..23f20c3c75 100644
--- a/src/nvim/buffer_defs.h
+++ b/src/nvim/buffer_defs.h
@@ -578,12 +578,7 @@ struct file_buffer {
#define B_IMODE_USE_INSERT -1 /* Use b_p_iminsert value for search */
#define B_IMODE_NONE 0 /* Input via none */
#define B_IMODE_LMAP 1 /* Input via langmap */
-#ifndef USE_IM_CONTROL
# define B_IMODE_LAST 1
-#else
-# define B_IMODE_IM 2 /* Input via input method */
-# define B_IMODE_LAST 2
-#endif
short b_kmap_state; /* using "lmap" mappings */
# define KEYMAP_INIT 1 /* 'keymap' was set, call keymap_init() */
diff --git a/src/nvim/cursor_shape.c b/src/nvim/cursor_shape.c
index 328b751693..06c8186bf9 100644
--- a/src/nvim/cursor_shape.c
+++ b/src/nvim/cursor_shape.c
@@ -1,4 +1,5 @@
#include <assert.h>
+#include <stdint.h>
#include "nvim/vim.h"
#include "nvim/ascii.h"
#include "nvim/cursor_shape.h"
@@ -52,7 +53,6 @@ char_u *parse_shape_opt(int what)
int all_idx;
int len;
int i;
- long n;
int found_ve = FALSE; /* found "ve" flag */
int round;
@@ -135,7 +135,9 @@ char_u *parse_shape_opt(int what)
p += len;
if (!VIM_ISDIGIT(*p))
return (char_u *)N_("E548: digit expected");
- n = getdigits(&p);
+ long digits = getdigits(&p);
+ assert(digits <= INT_MAX);
+ int n = (int)digits;
if (len == 3) { /* "ver" or "hor" */
if (n == 0)
return (char_u *)N_("E549: Illegal percentage");
diff --git a/src/nvim/digraph.c b/src/nvim/digraph.c
index f41a16bc1b..440d07aab0 100644
--- a/src/nvim/digraph.c
+++ b/src/nvim/digraph.c
@@ -2,7 +2,9 @@
///
/// code for digraphs
+#include <assert.h>
#include <stdbool.h>
+#include <stdint.h>
#include <inttypes.h>
#include "nvim/vim.h"
@@ -21,7 +23,7 @@
#include "nvim/normal.h"
#include "nvim/screen.h"
#include "nvim/strings.h"
-#include "nvim/ui.h"
+#include "nvim/os/input.h"
typedef int result_T;
@@ -1582,7 +1584,7 @@ int getdigraph(int char1, int char2, int meta_char)
/// @param str
void putdigraph(char_u *str)
{
- int char1, char2, n;
+ char_u char1, char2;
digr_T *dp;
while (*str != NUL) {
@@ -1609,7 +1611,9 @@ void putdigraph(char_u *str)
EMSG(_(e_number_exp));
return;
}
- n = getdigits(&str);
+ long digits = getdigits(&str);
+ assert(digits <= INT_MAX);
+ int n = (int)digits;
// If the digraph already exists, replace the result.
dp = (digr_T *)user_digraphs.ga_data;
@@ -1655,13 +1659,13 @@ void listdigraphs(void)
printdigraph(&tmp);
}
dp++;
- ui_breakcheck();
+ os_breakcheck();
}
dp = (digr_T *)user_digraphs.ga_data;
for (int i = 0; i < user_digraphs.ga_len && !got_int; ++i) {
printdigraph(dp);
- ui_breakcheck();
+ os_breakcheck();
dp++;
}
// clear screen, because some digraphs may be wrong, in which case we messed
@@ -1711,7 +1715,8 @@ static void printdigraph(digr_T *dp)
if (char2cells(dp->result) == 1) {
*p++ = ' ';
}
- vim_snprintf((char *)p, sizeof(buf) - (p - buf), " %3d", dp->result);
+ assert(p >= buf);
+ vim_snprintf((char *)p, sizeof(buf) - (size_t)(p - buf), " %3d", dp->result);
msg_outtrans(buf);
}
}
diff --git a/src/nvim/edit.c b/src/nvim/edit.c
index 8bf5170ae7..c7f20783a9 100644
--- a/src/nvim/edit.c
+++ b/src/nvim/edit.c
@@ -56,9 +56,12 @@
#include "nvim/tag.h"
#include "nvim/term.h"
#include "nvim/ui.h"
+#include "nvim/mouse.h"
#include "nvim/undo.h"
#include "nvim/window.h"
#include "nvim/os/event.h"
+#include "nvim/os/input.h"
+#include "nvim/os/time.h"
/*
* definitions used for CTRL-X submode
@@ -388,9 +391,6 @@ edit (
*/
if (curbuf->b_p_iminsert == B_IMODE_LMAP)
State |= LANGMAP;
-#ifdef USE_IM_CONTROL
- im_set_active(curbuf->b_p_iminsert == B_IMODE_IM);
-#endif
setmouse();
clear_showcmd();
@@ -593,9 +593,17 @@ edit (
* Get a character for Insert mode. Ignore K_IGNORE.
*/
lastc = c; /* remember previous char for CTRL-D */
+ event_enable_deferred();
do {
c = safe_vgetc();
} while (c == K_IGNORE);
+ event_disable_deferred();
+
+ if (c == K_EVENT) {
+ c = lastc;
+ event_process();
+ continue;
+ }
/* Don't want K_CURSORHOLD for the second key, e.g., after CTRL-V. */
did_cursorhold = TRUE;
@@ -943,10 +951,6 @@ doESCkey:
did_cursorhold = TRUE;
break;
- case K_EVENT:
- event_process();
- break;
-
case K_HOME: /* <Home> */
case K_KHOME:
case K_S_HOME:
@@ -1757,7 +1761,7 @@ static int has_compl_option(int dict_opt)
vim_beep();
setcursor();
out_flush();
- ui_delay(2000L, false);
+ os_delay(2000L, false);
}
return FALSE;
}
@@ -2001,7 +2005,7 @@ ins_compl_add (
compl_T *match;
int dir = (cdir == 0 ? compl_direction : cdir);
- ui_breakcheck();
+ os_breakcheck();
if (got_int)
return FAIL;
if (len < 0)
@@ -6757,19 +6761,11 @@ static void ins_reg(void)
* message for it. Only call it explicitly. */
++no_u_sync;
if (regname == '=') {
-# ifdef USE_IM_CONTROL
- int im_on = im_get_status();
-# endif
/* Sync undo when evaluating the expression calls setline() or
* append(), so that it can be undone separately. */
u_sync_once = 2;
regname = get_expr_register();
-# ifdef USE_IM_CONTROL
- /* Restore the Input Method. */
- if (im_on)
- im_set_active(TRUE);
-# endif
}
if (regname == NUL || !valid_yank_reg(regname, FALSE)) {
vim_beep();
@@ -6866,24 +6862,8 @@ static void ins_ctrl_hat(void)
} else {
curbuf->b_p_iminsert = B_IMODE_LMAP;
State |= LANGMAP;
-#ifdef USE_IM_CONTROL
- im_set_active(FALSE);
-#endif
}
}
-#ifdef USE_IM_CONTROL
- else {
- /* There are no ":lmap" mappings, toggle IM */
- if (im_get_status()) {
- curbuf->b_p_iminsert = B_IMODE_NONE;
- im_set_active(FALSE);
- } else {
- curbuf->b_p_iminsert = B_IMODE_IM;
- State &= ~LANGMAP;
- im_set_active(TRUE);
- }
- }
-#endif
set_iminsert_global();
showmode();
/* Show/unshow value of 'keymap' in status lines. */
@@ -6983,14 +6963,6 @@ ins_esc (
}
}
-#ifdef USE_IM_CONTROL
- /* Disable IM to allow typing English directly for Normal mode commands.
- * When ":lmap" is enabled don't change 'iminsert' (IM can be enabled as
- * well). */
- if (!(State & LANGMAP))
- im_save_status(&curbuf->b_p_iminsert);
- im_set_active(FALSE);
-#endif
State = NORMAL;
/* need to position cursor again (e.g. when on a TAB ) */
diff --git a/src/nvim/eval.c b/src/nvim/eval.c
index 498795dc38..34990a62e0 100644
--- a/src/nvim/eval.c
+++ b/src/nvim/eval.c
@@ -76,7 +76,7 @@
#include "nvim/tag.h"
#include "nvim/tempfile.h"
#include "nvim/term.h"
-#include "nvim/ui.h"
+#include "nvim/mouse.h"
#include "nvim/undo.h"
#include "nvim/version.h"
#include "nvim/window.h"
@@ -90,6 +90,7 @@
#include "nvim/api/vim.h"
#include "nvim/os/dl.h"
#include "nvim/os/event.h"
+#include "nvim/os/input.h"
#define DICT_MAXNEST 100 /* maximum nesting of lists and dicts */
@@ -178,6 +179,8 @@ static char *e_nofunc = N_("E130: Unknown function: %s");
static char *e_illvar = N_("E461: Illegal variable name: %s");
static char *e_float_as_string = N_("E806: using Float as a String");
+static char_u * const empty_string = (char_u *)"";
+
static dictitem_T globvars_var; /* variable used for g: */
#define globvarht globvardict.dv_hashtab
@@ -2272,6 +2275,7 @@ static void set_var_lval(lval_T *lp, char_u *endp, typval_T *rettv, int copy, ch
if (lp->ll_li->li_next == NULL) {
/* Need to add an empty item. */
list_append_number(lp->ll_list, 0);
+ assert(lp->ll_li->li_next);
}
lp->ll_li = lp->ll_li->li_next;
++lp->ll_n1;
@@ -4123,7 +4127,7 @@ eval7 (
* get_func_tv, but it's needed in handle_subscript() to parse
* what follows. So set it here. */
if (rettv->v_type == VAR_UNKNOWN && !evaluate && **arg == '(') {
- rettv->vval.v_string = (char_u *)"";
+ rettv->vval.v_string = empty_string;
rettv->v_type = VAR_FUNC;
}
@@ -5733,7 +5737,9 @@ dict_free (
dictitem_T *dictitem_alloc(char_u *key) FUNC_ATTR_NONNULL_RET
{
dictitem_T *di = xmalloc(sizeof(dictitem_T) + STRLEN(key));
+#ifndef __clang_analyzer__
STRCPY(di->di_key, key);
+#endif
di->di_flags = 0;
return di;
}
@@ -8409,7 +8415,7 @@ static void f_feedkeys(typval_T *argvars, typval_T *rettv)
}
vim_feedkeys(cstr_as_string((char *)keys),
- cstr_as_string((char *)flags));
+ cstr_as_string((char *)flags), true);
}
}
@@ -10268,12 +10274,6 @@ static void get_user_input(typval_T *argvars, typval_T *rettv, int inputdialog)
rettv->v_type = VAR_STRING;
rettv->vval.v_string = NULL;
-#ifdef NO_CONSOLE_INPUT
- /* While starting up, there is no place to enter text. */
- if (no_console_input())
- return;
-#endif
-
cmd_silent = FALSE; /* Want to see the prompt. */
if (prompt != NULL) {
/* Only the part of the message after the last NL is considered as
@@ -10368,11 +10368,6 @@ static void f_inputlist(typval_T *argvars, typval_T *rettv)
int selected;
int mouse_used;
-#ifdef NO_CONSOLE_INPUT
- /* While starting up, there is no place to enter text. */
- if (no_console_input())
- return;
-#endif
if (argvars[0].v_type != VAR_LIST || argvars[0].vval.v_list == NULL) {
EMSG2(_(e_listarg), "inputlist()");
return;
@@ -12518,6 +12513,7 @@ static void f_rpcrequest(typval_T *argvars, typval_T *rettv)
{
rettv->v_type = VAR_NUMBER;
rettv->vval.v_number = 0;
+ const int l_provider_call_nesting = provider_call_nesting;
if (check_restricted() || check_secure()) {
return;
@@ -12545,7 +12541,7 @@ static void f_rpcrequest(typval_T *argvars, typval_T *rettv)
int save_autocmd_fname_full, save_autocmd_bufnr;
void *save_funccalp;
- if (provider_call_nesting) {
+ if (l_provider_call_nesting) {
// If this is called from a provider function, restore the scope
// information of the caller.
save_current_SID = current_SID;
@@ -12574,7 +12570,7 @@ static void f_rpcrequest(typval_T *argvars, typval_T *rettv)
args,
&err);
- if (provider_call_nesting) {
+ if (l_provider_call_nesting) {
current_SID = save_current_SID;
sourcing_name = save_sourcing_name;
sourcing_lnum = save_sourcing_lnum;
@@ -13542,13 +13538,12 @@ static bool item_compare_numeric;
static char_u *item_compare_func;
static dict_T *item_compare_selfdict;
static int item_compare_func_err;
-static bool item_compare_keep_zero;
#define ITEM_COMPARE_FAIL 999
/*
* Compare functions for f_sort() and f_uniq() below.
*/
-static int item_compare(const void *s1, const void *s2)
+static int item_compare(const void *s1, const void *s2, bool keep_zero)
{
sortItem_T *si1, *si2;
char_u *p1, *p2;
@@ -13601,7 +13596,7 @@ static int item_compare(const void *s1, const void *s2)
// When the result would be zero, compare the item indexes. Makes the
// sort stable.
- if (res == 0 && !item_compare_keep_zero) {
+ if (res == 0 && !keep_zero) {
res = si1->idx > si2->idx ? 1 : -1;
}
@@ -13610,7 +13605,17 @@ static int item_compare(const void *s1, const void *s2)
return res;
}
-static int item_compare2(const void *s1, const void *s2)
+static int item_compare_keeping_zero(const void *s1, const void *s2)
+{
+ return item_compare(s1, s2, true);
+}
+
+static int item_compare_not_keeping_zero(const void *s1, const void *s2)
+{
+ return item_compare(s1, s2, false);
+}
+
+static int item_compare2(const void *s1, const void *s2, bool keep_zero)
{
sortItem_T *si1, *si2;
int res;
@@ -13647,13 +13652,23 @@ static int item_compare2(const void *s1, const void *s2)
// When the result would be zero, compare the pointers themselves. Makes
// the sort stable.
- if (res == 0 && !item_compare_keep_zero) {
+ if (res == 0 && !keep_zero) {
res = si1->idx > si2->idx ? 1 : -1;
}
return res;
}
+static int item_compare2_keeping_zero(const void *s1, const void *s2)
+{
+ return item_compare2(s1, s2, true);
+}
+
+static int item_compare2_not_keeping_zero(const void *s1, const void *s2)
+{
+ return item_compare2(s1, s2, false);
+}
+
/*
* "sort({list})" function
*/
@@ -13734,15 +13749,16 @@ static void do_sort_uniq(typval_T *argvars, typval_T *rettv, bool sort)
}
item_compare_func_err = FALSE;
- item_compare_keep_zero = false;
// Test the compare function.
if (item_compare_func != NULL
- && item_compare2(&ptrs[0], &ptrs[1]) == ITEM_COMPARE_FAIL) {
+ && item_compare2_not_keeping_zero(&ptrs[0], &ptrs[1])
+ == ITEM_COMPARE_FAIL) {
EMSG(_("E702: Sort compare function failed"));
} else {
// Sort the array with item pointers.
qsort(ptrs, (size_t)len, sizeof (sortItem_T),
- item_compare_func == NULL ? item_compare : item_compare2);
+ item_compare_func == NULL ? item_compare_not_keeping_zero :
+ item_compare2_not_keeping_zero);
if (!item_compare_func_err) {
// Clear the list and append the items in the sorted order.
@@ -13761,8 +13777,8 @@ static void do_sort_uniq(typval_T *argvars, typval_T *rettv, bool sort)
// f_uniq(): ptrs will be a stack of items to remove.
item_compare_func_err = FALSE;
- item_compare_keep_zero = true;
- item_compare_func_ptr = item_compare_func ? item_compare2 : item_compare;
+ item_compare_func_ptr = item_compare_func ? item_compare2_keeping_zero :
+ item_compare_keeping_zero;
for (li = l->lv_first; li != NULL && li->li_next != NULL; li = li->li_next) {
if (item_compare_func_ptr(&li, &li->li_next) == 0) {
@@ -13776,6 +13792,7 @@ static void do_sort_uniq(typval_T *argvars, typval_T *rettv, bool sort)
if (!item_compare_func_err) {
while (--i >= 0) {
+ assert(ptrs[i].item->li_next);
li = ptrs[i].item->li_next;
ptrs[i].item->li_next = li->li_next;
if (li->li_next != NULL) {
@@ -14561,8 +14578,7 @@ static void get_system_output_as_rettv(typval_T *argvars, typval_T *rettv,
if (res == NULL) {
if (retlist) {
// return an empty list when there's no output
- rettv->v_type = VAR_LIST;
- rettv->vval.v_list = list_alloc();
+ rettv_list_alloc(rettv);
}
return;
}
@@ -16111,7 +16127,11 @@ void clear_tv(typval_T *varp)
switch (varp->v_type) {
case VAR_FUNC:
func_unref(varp->vval.v_string);
- /*FALLTHROUGH*/
+ if (varp->vval.v_string != empty_string) {
+ free(varp->vval.v_string);
+ }
+ varp->vval.v_string = NULL;
+ break;
case VAR_STRING:
free(varp->vval.v_string);
varp->vval.v_string = NULL;
@@ -17251,7 +17271,7 @@ void ex_function(exarg_T *eap)
msg_putchar(' ');
msg_prt_line(FUNCLINE(fp, j), FALSE);
out_flush(); /* show a line at a time */
- ui_breakcheck();
+ os_breakcheck();
}
if (!got_int) {
msg_putchar('\n');
@@ -18250,6 +18270,7 @@ char_u *get_user_func_name(expand_T *xp, int idx)
done = 0;
hi = func_hashtab.ht_array;
}
+ assert(hi);
if (done < func_hashtab.ht_used) {
if (done++ > 0)
++hi;
@@ -18465,8 +18486,10 @@ call_user_func (
/* Set l:self to "selfdict". Use "name" to avoid a warning from
* some compiler that checks the destination size. */
v = &fc->fixvar[fixvar_idx++].var;
+#ifndef __clang_analyzer__
name = v->di_key;
STRCPY(name, "self");
+#endif
v->di_flags = DI_FLAGS_RO + DI_FLAGS_FIX;
hash_add(&fc->l_vars.dv_hashtab, DI2HIKEY(v));
v->di_tv.v_type = VAR_DICT;
@@ -18486,8 +18509,10 @@ call_user_func (
/* Use "name" to avoid a warning from some compiler that checks the
* destination size. */
v = &fc->fixvar[fixvar_idx++].var;
+#ifndef __clang_analyzer__
name = v->di_key;
STRCPY(name, "000");
+#endif
v->di_flags = DI_FLAGS_RO | DI_FLAGS_FIX;
hash_add(&fc->l_avars.dv_hashtab, DI2HIKEY(v));
v->di_tv.v_type = VAR_LIST;
@@ -18774,7 +18799,9 @@ free_funccal (
*/
static void add_nr_var(dict_T *dp, dictitem_T *v, char *name, varnumber_T nr)
{
+#ifndef __clang_analyzer__
STRCPY(v->di_key, name);
+#endif
v->di_flags = DI_FLAGS_RO | DI_FLAGS_FIX;
hash_add(&dp->dv_hashtab, DI2HIKEY(v));
v->di_tv.v_type = VAR_NUMBER;
@@ -18864,8 +18891,10 @@ int do_return(exarg_T *eap, int reanimate, int is_cmd, void *rettv)
else {
/* When undoing a return in order to make it pending, get the stored
* return rettv. */
- if (reanimate)
+ if (reanimate) {
+ assert(current_funccal->rettv);
rettv = current_funccal->rettv;
+ }
if (rettv != NULL) {
/* Store the value of the pending return. */
@@ -19267,7 +19296,7 @@ void ex_oldfiles(exarg_T *eap)
msg_outtrans(get_tv_string(&li->li_tv));
msg_putchar('\n');
out_flush(); /* output one line at a time */
- ui_breakcheck();
+ os_breakcheck();
}
/* Assume "got_int" was set to truncate the listing. */
got_int = FALSE;
diff --git a/src/nvim/ex_cmds.c b/src/nvim/ex_cmds.c
index f33a96cc50..556e0c01e3 100644
--- a/src/nvim/ex_cmds.c
+++ b/src/nvim/ex_cmds.c
@@ -62,11 +62,11 @@
#include "nvim/tag.h"
#include "nvim/tempfile.h"
#include "nvim/term.h"
-#include "nvim/ui.h"
#include "nvim/undo.h"
#include "nvim/window.h"
#include "nvim/os/os.h"
#include "nvim/os/shell.h"
+#include "nvim/os/input.h"
/*
* Struct to hold the sign properties.
@@ -1110,7 +1110,7 @@ do_filter (
/* When interrupting the shell command, it may still have produced some
* useful output. Reset got_int here, so that readfile() won't cancel
* reading. */
- ui_breakcheck();
+ os_breakcheck();
got_int = FALSE;
if (do_out) {
@@ -4560,7 +4560,7 @@ void global_exe(char_u *cmd)
do_cmdline((char_u *)"p", NULL, NULL, DOCMD_NOWAIT);
else
do_cmdline(cmd, NULL, NULL, DOCMD_NOWAIT);
- ui_breakcheck();
+ os_breakcheck();
}
global_busy = 0;
diff --git a/src/nvim/ex_docmd.c b/src/nvim/ex_docmd.c
index 3e9b889253..3967c916bb 100644
--- a/src/nvim/ex_docmd.c
+++ b/src/nvim/ex_docmd.c
@@ -67,6 +67,8 @@
#include "nvim/version.h"
#include "nvim/window.h"
#include "nvim/os/os.h"
+#include "nvim/os/input.h"
+#include "nvim/os/time.h"
#include "nvim/ex_cmds_defs.h"
static int quitmore = 0;
@@ -4337,7 +4339,7 @@ static void uc_list(char_u *name, size_t name_len)
if (p_verbose > 0)
last_set_msg(cmd->uc_scriptID);
out_flush();
- ui_breakcheck();
+ os_breakcheck();
if (got_int)
break;
}
@@ -5459,7 +5461,7 @@ static void ex_print(exarg_T *eap)
if (curbuf->b_ml.ml_flags & ML_EMPTY)
EMSG(_(e_emptybuf));
else {
- for (; !got_int; ui_breakcheck()) {
+ for (; !got_int; os_breakcheck()) {
print_line(eap->line1,
(eap->cmdidx == CMD_number || eap->cmdidx == CMD_pound
|| (eap->flags & EXFLAG_NR)),
@@ -5586,7 +5588,7 @@ void alist_set(alist_T *al, int count, char_u **files, int use_curbuf, int *fnum
buf_set_name(fnum_list[i], files[i]);
alist_add(al, files[i], use_curbuf ? 2 : 1);
- ui_breakcheck();
+ os_breakcheck();
}
free(files);
}
@@ -5842,7 +5844,7 @@ static void ex_tabs(exarg_T *eap)
vim_snprintf((char *)IObuff, IOSIZE, _("Tab page %d"), tabcount++);
msg_outtrans_attr(IObuff, hl_attr(HLF_T));
out_flush(); /* output one line at a time */
- ui_breakcheck();
+ os_breakcheck();
FOR_ALL_WINDOWS_IN_TAB(wp, tp) {
if (got_int) {
@@ -5861,7 +5863,7 @@ static void ex_tabs(exarg_T *eap)
IObuff, IOSIZE, TRUE);
msg_outtrans(IObuff);
out_flush(); /* output one line at a time */
- ui_breakcheck();
+ os_breakcheck();
}
}
}
@@ -6408,8 +6410,8 @@ void do_sleep(long msec)
cursor_on();
out_flush();
for (done = 0; !got_int && done < msec; done += 1000L) {
- ui_delay(msec - done > 1000L ? 1000L : msec - done, true);
- ui_breakcheck();
+ os_delay(msec - done > 1000L ? 1000L : msec - done, true);
+ os_breakcheck();
}
}
diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c
index 5feff4d456..70db2dc479 100644
--- a/src/nvim/ex_getln.c
+++ b/src/nvim/ex_getln.c
@@ -265,14 +265,7 @@ getcmdline (
b_im_ptr = &curbuf->b_p_imsearch;
if (*b_im_ptr == B_IMODE_LMAP)
State |= LANGMAP;
-#ifdef USE_IM_CONTROL
- im_set_active(*b_im_ptr == B_IMODE_IM);
-#endif
}
-#ifdef USE_IM_CONTROL
- else if (p_imcmdline)
- im_set_active(TRUE);
-#endif
setmouse();
ui_cursor_shape(); /* may show different cursor shape */
@@ -311,9 +304,16 @@ getcmdline (
/* Get a character. Ignore K_IGNORE, it should not do anything, such
* as stop completion. */
+ event_enable_deferred();
do {
c = safe_vgetc();
} while (c == K_IGNORE);
+ event_disable_deferred();
+
+ if (c == K_EVENT) {
+ event_process();
+ continue;
+ }
if (KeyTyped) {
some_key_typed = TRUE;
@@ -769,11 +769,6 @@ getcmdline (
* Big switch for a typed command line character.
*/
switch (c) {
- case K_EVENT:
- event_process();
- // Force a redraw even though the command line didn't change
- shell_resized();
- goto cmdline_not_changed;
case K_BS:
case Ctrl_H:
case K_DEL:
@@ -865,9 +860,6 @@ getcmdline (
if (map_to_exists_mode((char_u *)"", LANGMAP, FALSE)) {
/* ":lmap" mappings exists, toggle use of mappings. */
State ^= LANGMAP;
-#ifdef USE_IM_CONTROL
- im_set_active(FALSE); /* Disable input method */
-#endif
if (b_im_ptr != NULL) {
if (State & LANGMAP)
*b_im_ptr = B_IMODE_LMAP;
@@ -875,23 +867,6 @@ getcmdline (
*b_im_ptr = B_IMODE_NONE;
}
}
-#ifdef USE_IM_CONTROL
- else {
- /* There are no ":lmap" mappings, toggle IM. When
- * 'imdisable' is set don't try getting the status, it's
- * always off. */
- if ((p_imdisable && b_im_ptr != NULL)
- ? *b_im_ptr == B_IMODE_IM : im_get_status()) {
- im_set_active(FALSE); /* Disable input method */
- if (b_im_ptr != NULL)
- *b_im_ptr = B_IMODE_NONE;
- } else {
- im_set_active(TRUE); /* Enable input method */
- if (b_im_ptr != NULL)
- *b_im_ptr = B_IMODE_IM;
- }
- }
-#endif
if (b_im_ptr != NULL) {
if (b_im_ptr == &curbuf->b_p_iminsert)
set_iminsert_global();
@@ -1540,11 +1515,6 @@ returncmd:
need_wait_return = FALSE;
State = save_State;
-#ifdef USE_IM_CONTROL
- if (b_im_ptr != NULL && *b_im_ptr != B_IMODE_LMAP)
- im_save_status(b_im_ptr);
- im_set_active(FALSE);
-#endif
setmouse();
ui_cursor_shape(); /* may show different cursor shape */
@@ -1885,8 +1855,6 @@ redraw:
}
if (IS_SPECIAL(c1)) {
- // Process deferred events
- event_process();
// Ignore other special key codes
continue;
}
@@ -1946,7 +1914,7 @@ redraw:
msg_col = 0;
if (msg_row < Rows - 1)
++msg_row;
- emsg_on_display = FALSE; /* don't want ui_delay() */
+ emsg_on_display = FALSE; /* don't want os_delay() */
if (got_int)
ga_clear(&line_ga);
diff --git a/src/nvim/file_search.c b/src/nvim/file_search.c
index 955b0b0a68..1cb9e1e8f7 100644
--- a/src/nvim/file_search.c
+++ b/src/nvim/file_search.c
@@ -62,9 +62,9 @@
#include "nvim/path.h"
#include "nvim/strings.h"
#include "nvim/tag.h"
-#include "nvim/ui.h"
#include "nvim/window.h"
#include "nvim/os/os.h"
+#include "nvim/os/input.h"
#include "nvim/os/fs_defs.h"
static char_u *ff_expand_buffer = NULL; /* used for expanding filenames */
@@ -607,7 +607,7 @@ char_u *vim_findfile(void *search_ctx_arg)
/* downward search loop */
for (;; ) {
/* check if user user wants to stop the search*/
- ui_breakcheck();
+ os_breakcheck();
if (got_int)
break;
diff --git a/src/nvim/fileio.c b/src/nvim/fileio.c
index 97a357bff7..3be9d89d87 100644
--- a/src/nvim/fileio.c
+++ b/src/nvim/fileio.c
@@ -53,10 +53,11 @@
#include "nvim/tempfile.h"
#include "nvim/term.h"
#include "nvim/types.h"
-#include "nvim/ui.h"
#include "nvim/undo.h"
#include "nvim/window.h"
#include "nvim/os/os.h"
+#include "nvim/os/time.h"
+#include "nvim/os/input.h"
#if defined(HAVE_UTIME) && defined(HAVE_UTIME_H)
# include <utime.h> /* for struct utimbuf */
@@ -1704,7 +1705,7 @@ rewind_retry:
}
}
linerest = (long)(ptr - line_start);
- ui_breakcheck();
+ os_breakcheck();
}
failed:
@@ -2927,7 +2928,7 @@ buf_write (
"E506: Can't write to backup file (add ! to override)");
break;
}
- ui_breakcheck();
+ os_breakcheck();
if (got_int) {
errmsg = (char_u *)_(e_interr);
break;
@@ -3377,7 +3378,7 @@ restore_backup:
s = buffer;
len = 0;
- ui_breakcheck();
+ os_breakcheck();
if (got_int) {
end = 0; /* Interrupted, break loop */
break;
@@ -4958,7 +4959,7 @@ buf_check_timestamp (
if (emsg_silent == 0) {
out_flush();
/* give the user some time to think about it */
- ui_delay(1000L, true);
+ os_delay(1000L, true);
/* don't redraw and erase the message */
redraw_cmdline = FALSE;
diff --git a/src/nvim/getchar.c b/src/nvim/getchar.c
index fd60664b7b..d0bdcde9e8 100644
--- a/src/nvim/getchar.c
+++ b/src/nvim/getchar.c
@@ -47,7 +47,6 @@
#include "nvim/screen.h"
#include "nvim/strings.h"
#include "nvim/term.h"
-#include "nvim/ui.h"
#include "nvim/undo.h"
#include "nvim/os/event.h"
#include "nvim/os/input.h"
@@ -1702,14 +1701,14 @@ static int vgetorpeek(int advance)
*/
for (;; ) {
/*
- * ui_breakcheck() is slow, don't use it too often when
+ * os_breakcheck() is slow, don't use it too often when
* inside a mapping. But call it each time for typed
* characters.
*/
if (typebuf.tb_maplen)
line_breakcheck();
else
- ui_breakcheck(); /* check for CTRL-C */
+ os_breakcheck(); /* check for CTRL-C */
keylen = 0;
if (got_int) {
/* flush all input */
@@ -2350,11 +2349,6 @@ static int vgetorpeek(int advance)
+ typebuf.tb_len] != NUL)
typebuf.tb_noremap[typebuf.tb_off
+ typebuf.tb_len++] = RM_YES;
-#ifdef USE_IM_CONTROL
- /* Get IM status right after getting keys, not after the
- * timeout for a mapping (focus may be lost by then). */
- vgetc_im_active = im_get_status();
-#endif
}
} /* for (;;) */
} /* if (!character from stuffbuf) */
@@ -2481,8 +2475,7 @@ inchar (
char_u dum[DUM_LEN + 1];
for (;; ) {
- event_process();
- len = ui_inchar(dum, DUM_LEN, 0L, 0);
+ len = os_inchar(dum, DUM_LEN, 0L, 0);
if (len == 0 || (len == 1 && dum[0] == 3))
break;
}
@@ -2499,7 +2492,7 @@ inchar (
* Fill up to a third of the buffer, because each character may be
* tripled below.
*/
- len = ui_inchar(buf, maxlen / 3, wait_time, tb_change_cnt);
+ len = os_inchar(buf, maxlen / 3, wait_time, tb_change_cnt);
}
if (typebuf_changed(tb_change_cnt))
diff --git a/src/nvim/globals.h b/src/nvim/globals.h
index cd9f7a648f..ea91135194 100644
--- a/src/nvim/globals.h
+++ b/src/nvim/globals.h
@@ -855,7 +855,6 @@ EXTERN char_u *exe_name; /* the name of the executable */
EXTERN int dont_scroll INIT(= FALSE); /* don't use scrollbars when TRUE */
#endif
EXTERN int mapped_ctrl_c INIT(= FALSE); /* CTRL-C is mapped */
-EXTERN bool ctrl_c_interrupts INIT(= true); /* CTRL-C sets got_int */
EXTERN cmdmod_T cmdmod; /* Ex command modifiers */
@@ -898,10 +897,6 @@ EXTERN int stop_insert_mode; /* for ":stopinsert" and 'insertmode' */
EXTERN int KeyTyped; /* TRUE if user typed current char */
EXTERN int KeyStuffed; /* TRUE if current char from stuffbuf */
-#ifdef USE_IM_CONTROL
-EXTERN int vgetc_im_active; /* Input Method was active for last
- character obtained from vgetc() */
-#endif
EXTERN int maptick INIT(= 0); /* tick for each non-mapped char */
EXTERN char_u chartab[256]; /* table used in charset.c; See
diff --git a/src/nvim/hardcopy.c b/src/nvim/hardcopy.c
index 1d15e30921..5d9d353fc8 100644
--- a/src/nvim/hardcopy.c
+++ b/src/nvim/hardcopy.c
@@ -41,8 +41,8 @@
#include "nvim/syntax.h"
#include "nvim/term.h"
#include "nvim/tempfile.h"
-#include "nvim/ui.h"
#include "nvim/os/os.h"
+#include "nvim/os/input.h"
/*
* To implement printing on a platform, the following functions must be
@@ -724,7 +724,7 @@ void ex_hardcopy(exarg_T *eap)
*/
/* Check for interrupt character every page. */
- ui_breakcheck();
+ os_breakcheck();
if (got_int || settings.user_abort)
goto print_fail;
diff --git a/src/nvim/if_cscope.c b/src/nvim/if_cscope.c
index 667e6512f3..bb41db6168 100644
--- a/src/nvim/if_cscope.c
+++ b/src/nvim/if_cscope.c
@@ -29,9 +29,9 @@
#include "nvim/strings.h"
#include "nvim/tag.h"
#include "nvim/tempfile.h"
-#include "nvim/ui.h"
#include "nvim/window.h"
#include "nvim/os/os.h"
+#include "nvim/os/input.h"
#include <sys/types.h>
#include <sys/stat.h>
@@ -1735,7 +1735,7 @@ static void cs_print_tags_priv(char **matches, char **cntxts, int num_matches)
if (msg_col)
msg_putchar('\n');
- ui_breakcheck();
+ os_breakcheck();
if (got_int) {
got_int = FALSE; /* don't print any more matches */
break;
diff --git a/src/nvim/main.c b/src/nvim/main.c
index 4447c404d5..68ae000c35 100644
--- a/src/nvim/main.c
+++ b/src/nvim/main.c
@@ -57,6 +57,7 @@
#include "nvim/ui.h"
#include "nvim/version.h"
#include "nvim/window.h"
+#include "nvim/os/time.h"
#include "nvim/os/input.h"
#include "nvim/os/os.h"
#include "nvim/os/signal.h"
@@ -1608,7 +1609,7 @@ static void check_tty(mparm_T *parmp)
mch_errmsg(_("Vim: Warning: Input is not from a terminal\n"));
out_flush();
if (scriptin[0] == NULL)
- ui_delay(2000L, true);
+ os_delay(2000L, true);
TIME_MSG("Warning delay");
}
}
@@ -1742,7 +1743,7 @@ static void create_windows(mparm_T *parmp)
#endif
dorewind = TRUE; /* start again */
}
- ui_breakcheck();
+ os_breakcheck();
if (got_int) {
(void)vgetc(); /* only break the file loading, not the rest */
break;
@@ -1832,7 +1833,7 @@ static void edit_buffers(mparm_T *parmp)
arg_had_last = TRUE;
++arg_idx;
}
- ui_breakcheck();
+ os_breakcheck();
if (got_int) {
(void)vgetc(); /* only break the file loading, not the rest */
break;
diff --git a/src/nvim/mark.c b/src/nvim/mark.c
index 120645cfe6..4ded438f52 100644
--- a/src/nvim/mark.c
+++ b/src/nvim/mark.c
@@ -38,8 +38,8 @@
#include "nvim/search.h"
#include "nvim/strings.h"
#include "nvim/term.h"
-#include "nvim/ui.h"
#include "nvim/os/os.h"
+#include "nvim/os/input.h"
/*
* This file contains routines to maintain and manipulate marks.
@@ -811,7 +811,7 @@ void ex_jumps(exarg_T *eap)
curwin->w_jumplist[i].fmark.fnum == curbuf->b_fnum
? hl_attr(HLF_D) : 0);
free(name);
- ui_breakcheck();
+ os_breakcheck();
}
out_flush();
}
@@ -845,7 +845,7 @@ void ex_changes(exarg_T *eap)
name = mark_line(&curbuf->b_changelist[i], 17);
msg_outtrans_attr(name, hl_attr(HLF_D));
free(name);
- ui_breakcheck();
+ os_breakcheck();
}
out_flush();
}
diff --git a/src/nvim/mbyte.c b/src/nvim/mbyte.c
index 2240c1fe83..d79a46ceaa 100644
--- a/src/nvim/mbyte.c
+++ b/src/nvim/mbyte.c
@@ -103,7 +103,6 @@
#include "nvim/screen.h"
#include "nvim/spell.h"
#include "nvim/strings.h"
-#include "nvim/ui.h"
#include "nvim/os/os.h"
#include "nvim/arabic.h"
@@ -3972,3 +3971,23 @@ char_u * string_convert_ext(vimconv_T *vcp, char_u *ptr, int *lenp,
return retval;
}
+
+// Check bounds for column number
+static int check_col(int col)
+{
+ if (col < 0)
+ return 0;
+ if (col >= (int)screen_Columns)
+ return (int)screen_Columns - 1;
+ return col;
+}
+
+// Check bounds for row number
+static int check_row(int row)
+{
+ if (row < 0)
+ return 0;
+ if (row >= (int)screen_Rows)
+ return (int)screen_Rows - 1;
+ return row;
+}
diff --git a/src/nvim/memfile.c b/src/nvim/memfile.c
index 1656acb689..d8d59474a2 100644
--- a/src/nvim/memfile.c
+++ b/src/nvim/memfile.c
@@ -61,8 +61,8 @@
#include "nvim/memory.h"
#include "nvim/os_unix.h"
#include "nvim/path.h"
-#include "nvim/ui.h"
#include "nvim/os/os.h"
+#include "nvim/os/input.h"
#define MEMFILE_PAGE_SIZE 4096 /// default page size
@@ -455,10 +455,10 @@ int mf_sync(memfile_T *mfp, int flags)
status = FAIL;
}
if (flags & MFS_STOP) { // Stop when char available now.
- if (ui_char_avail())
+ if (os_char_avail())
break;
} else {
- ui_breakcheck();
+ os_breakcheck();
}
if (got_int)
break;
diff --git a/src/nvim/memline.c b/src/nvim/memline.c
index e9edeb842f..f6246c8b57 100644
--- a/src/nvim/memline.c
+++ b/src/nvim/memline.c
@@ -71,10 +71,10 @@
#include "nvim/strings.h"
#include "nvim/term.h"
#include "nvim/tempfile.h"
-#include "nvim/ui.h"
#include "nvim/undo.h"
#include "nvim/window.h"
#include "nvim/os/os.h"
+#include "nvim/os/input.h"
#ifndef UNIX /* it's in os_unix_defs.h for Unix */
# include <time.h>
@@ -1642,7 +1642,7 @@ void ml_sync_all(int check_file, int check_char)
if (buf->b_ml.ml_mfp->mf_dirty) {
(void)mf_sync(buf->b_ml.ml_mfp, (check_char ? MFS_STOP : 0)
| (bufIsChanged(buf) ? MFS_FLUSH : 0));
- if (check_char && ui_char_avail()) /* character available now */
+ if (check_char && os_char_avail()) /* character available now */
break;
}
}
diff --git a/src/nvim/memory.c b/src/nvim/memory.c
index c2c406a235..4c5a45b8b6 100644
--- a/src/nvim/memory.c
+++ b/src/nvim/memory.c
@@ -49,11 +49,11 @@ static void try_to_free_memory(void)
/// @return pointer to allocated space. NULL if out of memory
void *try_malloc(size_t size) FUNC_ATTR_MALLOC FUNC_ATTR_ALLOC_SIZE(1)
{
- size = size ? size : 1;
- void *ret = malloc(size);
+ size_t allocated_size = size ? size : 1;
+ void *ret = malloc(allocated_size);
if (!ret) {
try_to_free_memory();
- ret = malloc(size);
+ ret = malloc(allocated_size);
}
return ret;
}
@@ -102,10 +102,12 @@ void *xmalloc(size_t size)
void *xcalloc(size_t count, size_t size)
FUNC_ATTR_MALLOC FUNC_ATTR_ALLOC_SIZE_PROD(1, 2) FUNC_ATTR_NONNULL_RET
{
- void *ret = count && size ? calloc(count, size) : calloc(1, 1);
+ size_t allocated_count = count && size ? count : 1;
+ size_t allocated_size = count && size ? size : 1;
+ void *ret = calloc(allocated_count, allocated_size);
if (!ret) {
try_to_free_memory();
- ret = count && size ? calloc(count, size) : calloc(1, 1);
+ ret = calloc(allocated_count, allocated_size);
if (!ret) {
OUT_STR(e_outofmem);
out_char('\n');
@@ -123,10 +125,11 @@ void *xcalloc(size_t count, size_t size)
void *xrealloc(void *ptr, size_t size)
FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_ALLOC_SIZE(2) FUNC_ATTR_NONNULL_RET
{
- void *ret = size ? realloc(ptr, size) : realloc(ptr, 1);
+ size_t allocated_size = size ? size : 1;
+ void *ret = realloc(ptr, allocated_size);
if (!ret) {
try_to_free_memory();
- ret = size ? realloc(ptr, size) : realloc(ptr, 1);
+ ret = realloc(ptr, allocated_size);
if (!ret) {
OUT_STR(e_outofmem);
out_char('\n');
@@ -427,7 +430,6 @@ void do_outofmem_msg(size_t size)
#include "nvim/spell.h"
#include "nvim/syntax.h"
#include "nvim/tag.h"
-#include "nvim/ui.h"
#include "nvim/window.h"
#include "nvim/os/os.h"
diff --git a/src/nvim/message.c b/src/nvim/message.c
index ee83fd371e..cd0c548fb4 100644
--- a/src/nvim/message.c
+++ b/src/nvim/message.c
@@ -42,9 +42,10 @@
#include "nvim/screen.h"
#include "nvim/strings.h"
#include "nvim/term.h"
-#include "nvim/ui.h"
+#include "nvim/mouse.h"
#include "nvim/os/os.h"
-#include "nvim/os/event.h"
+#include "nvim/os/input.h"
+#include "nvim/os/time.h"
/*
* To be able to scroll back at the "more" and "hit-enter" prompts we need to
@@ -878,7 +879,7 @@ void wait_return(int redraw)
|| c == K_X1MOUSE
|| c == K_X2MOUSE))
);
- ui_breakcheck();
+ os_breakcheck();
/*
* Avoid that the mouse-up event causes visual mode to start.
*/
@@ -2076,9 +2077,6 @@ static int do_more_prompt(int typed_char)
toscroll = 0;
switch (c) {
- case K_EVENT:
- event_process();
- break;
case BS: /* scroll one line back */
case K_BS:
case 'k':
@@ -2706,11 +2704,9 @@ do_dialog (
int c;
int i;
-#ifndef NO_CONSOLE
/* Don't output anything in silent mode ("ex -s") */
if (silent_mode)
return dfltbutton; /* return default option */
-#endif
oldState = State;
@@ -2738,8 +2734,6 @@ do_dialog (
break;
default: /* Could be a hotkey? */
if (c < 0) { /* special keys are ignored here */
- // drain event queue to prevent infinite loop
- event_process();
continue;
}
if (c == ':' && ex_cmd) {
diff --git a/src/nvim/misc1.c b/src/nvim/misc1.c
index 310cb6faac..230e198121 100644
--- a/src/nvim/misc1.c
+++ b/src/nvim/misc1.c
@@ -58,6 +58,8 @@
#include "nvim/window.h"
#include "nvim/os/os.h"
#include "nvim/os/shell.h"
+#include "nvim/os/input.h"
+#include "nvim/os/time.h"
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "misc1.c.generated.h"
@@ -1840,7 +1842,7 @@ void changed(void)
* and don't let the emsg() set msg_scroll. */
if (need_wait_return && emsg_silent == 0) {
out_flush();
- ui_delay(2000L, true);
+ os_delay(2000L, true);
wait_return(TRUE);
msg_scroll = save_msg_scroll;
}
@@ -2261,7 +2263,7 @@ change_warning (
(void)msg_end();
if (msg_silent == 0 && !silent_mode) {
out_flush();
- ui_delay(1000L, true); /* give the user time to think about it */
+ os_delay(1000L, true); /* give the user time to think about it */
}
curbuf->b_did_warn = true;
redraw_cmdline = FALSE; /* don't redraw and erase the message */
@@ -2383,7 +2385,7 @@ int get_keystroke(void)
/* First time: blocking wait. Second time: wait up to 100ms for a
* terminal code to complete. */
- n = ui_inchar(buf + len, maxlen, len == 0 ? -1L : 100L, 0);
+ n = os_inchar(buf + len, maxlen, len == 0 ? -1L : 100L, 0);
if (n > 0) {
/* Replace zero and CSI by a special key code. */
n = fix_input_buffer(buf + len, n, FALSE);
@@ -3362,8 +3364,8 @@ void preserve_exit(void)
/*
* Check for CTRL-C pressed, but only once in a while.
- * Should be used instead of ui_breakcheck() for functions that check for
- * each line in the file. Calling ui_breakcheck() each time takes too much
+ * Should be used instead of os_breakcheck() for functions that check for
+ * each line in the file. Calling os_breakcheck() each time takes too much
* time, because it can be a system call.
*/
@@ -3377,7 +3379,7 @@ void line_breakcheck(void)
{
if (++breakcheck_count >= BREAKCHECK_SKIP) {
breakcheck_count = 0;
- ui_breakcheck();
+ os_breakcheck();
}
}
@@ -3388,7 +3390,7 @@ void fast_breakcheck(void)
{
if (++breakcheck_count >= BREAKCHECK_SKIP * 10) {
breakcheck_count = 0;
- ui_breakcheck();
+ os_breakcheck();
}
}
diff --git a/src/nvim/misc2.c b/src/nvim/misc2.c
index 3fe5f1a0ed..acf243b349 100644
--- a/src/nvim/misc2.c
+++ b/src/nvim/misc2.c
@@ -50,7 +50,6 @@
#include "nvim/syntax.h"
#include "nvim/tag.h"
#include "nvim/term.h"
-#include "nvim/ui.h"
#include "nvim/window.h"
#include "nvim/os/os.h"
#include "nvim/os/shell.h"
diff --git a/src/nvim/mouse.c b/src/nvim/mouse.c
new file mode 100644
index 0000000000..7fc581a7c0
--- /dev/null
+++ b/src/nvim/mouse.c
@@ -0,0 +1,438 @@
+#include <stdbool.h>
+
+#include "nvim/mouse.h"
+#include "nvim/vim.h"
+#include "nvim/screen.h"
+#include "nvim/window.h"
+#include "nvim/term.h"
+#include "nvim/fold.h"
+#include "nvim/diff.h"
+#include "nvim/move.h"
+#include "nvim/misc1.h"
+#include "nvim/cursor.h"
+#include "nvim/buffer_defs.h"
+
+#ifdef INCLUDE_GENERATED_DECLARATIONS
+# include "mouse.c.generated.h"
+#endif
+
+// Move the cursor to the specified row and column on the screen.
+// Change current window if necessary. Returns an integer with the
+// CURSOR_MOVED bit set if the cursor has moved or unset otherwise.
+//
+// The MOUSE_FOLD_CLOSE bit is set when clicked on the '-' in a fold column.
+// The MOUSE_FOLD_OPEN bit is set when clicked on the '+' in a fold column.
+//
+// If flags has MOUSE_FOCUS, then the current window will not be changed, and
+// if the mouse is outside the window then the text will scroll, or if the
+// mouse was previously on a status line, then the status line may be dragged.
+//
+// If flags has MOUSE_MAY_VIS, then VIsual mode will be started before the
+// cursor is moved unless the cursor was on a status line.
+// This function returns one of IN_UNKNOWN, IN_BUFFER, IN_STATUS_LINE or
+// IN_SEP_LINE depending on where the cursor was clicked.
+//
+// If flags has MOUSE_MAY_STOP_VIS, then Visual mode will be stopped, unless
+// the mouse is on the status line of the same window.
+//
+// If flags has MOUSE_DID_MOVE, nothing is done if the mouse didn't move since
+// the last call.
+//
+// If flags has MOUSE_SETPOS, nothing is done, only the current position is
+// remembered.
+int jump_to_mouse(int flags,
+ bool *inclusive, // used for inclusive operator, can be NULL
+ int which_button) // MOUSE_LEFT, MOUSE_RIGHT, MOUSE_MIDDLE
+{
+ static int on_status_line = 0; // #lines below bottom of window
+ static int on_sep_line = 0; // on separator right of window
+ static int prev_row = -1;
+ static int prev_col = -1;
+ static win_T *dragwin = NULL; // window being dragged
+ static int did_drag = false; // drag was noticed
+
+ win_T *wp, *old_curwin;
+ pos_T old_cursor;
+ int count;
+ bool first;
+ int row = mouse_row;
+ int col = mouse_col;
+ int mouse_char;
+
+ mouse_past_bottom = false;
+ mouse_past_eol = false;
+
+ if (flags & MOUSE_RELEASED) {
+ // On button release we may change window focus if positioned on a
+ // status line and no dragging happened.
+ if (dragwin != NULL && !did_drag)
+ flags &= ~(MOUSE_FOCUS | MOUSE_DID_MOVE);
+ dragwin = NULL;
+ did_drag = false;
+ }
+
+ if ((flags & MOUSE_DID_MOVE)
+ && prev_row == mouse_row
+ && prev_col == mouse_col) {
+retnomove:
+ // before moving the cursor for a left click which is NOT in a status
+ // line, stop Visual mode
+ if (on_status_line)
+ return IN_STATUS_LINE;
+ if (on_sep_line)
+ return IN_SEP_LINE;
+ if (flags & MOUSE_MAY_STOP_VIS) {
+ end_visual_mode();
+ redraw_curbuf_later(INVERTED); // delete the inversion
+ }
+ return IN_BUFFER;
+ }
+
+ prev_row = mouse_row;
+ prev_col = mouse_col;
+
+ if (flags & MOUSE_SETPOS)
+ goto retnomove; // ugly goto...
+
+ // Remember the character under the mouse, it might be a '-' or '+' in the
+ // fold column.
+ if (row >= 0 && row < Rows && col >= 0 && col <= Columns
+ && ScreenLines != NULL)
+ mouse_char = ScreenLines[LineOffset[row] + (unsigned)col];
+ else
+ mouse_char = ' ';
+
+ old_curwin = curwin;
+ old_cursor = curwin->w_cursor;
+
+ if (!(flags & MOUSE_FOCUS)) {
+ if (row < 0 || col < 0) // check if it makes sense
+ return IN_UNKNOWN;
+
+ // find the window where the row is in
+ wp = mouse_find_win(&row, &col);
+ dragwin = NULL;
+ // winpos and height may change in win_enter()!
+ if (row >= wp->w_height) { // In (or below) status line
+ on_status_line = row - wp->w_height + 1;
+ dragwin = wp;
+ } else {
+ on_status_line = 0;
+ }
+
+ if (col >= wp->w_width) { // In separator line
+ on_sep_line = col - wp->w_width + 1;
+ dragwin = wp;
+ } else {
+ on_sep_line = 0;
+ }
+
+ // The rightmost character of the status line might be a vertical
+ // separator character if there is no connecting window to the right.
+ if (on_status_line && on_sep_line) {
+ if (stl_connected(wp))
+ on_sep_line = 0;
+ else
+ on_status_line = 0;
+ }
+
+ // Before jumping to another buffer, or moving the cursor for a left
+ // click, stop Visual mode.
+ if (VIsual_active
+ && (wp->w_buffer != curwin->w_buffer
+ || (!on_status_line
+ && !on_sep_line
+ && (
+ wp->w_p_rl ? col < wp->w_width - wp->w_p_fdc :
+ col >= wp->w_p_fdc
+ + (cmdwin_type == 0 && wp ==
+ curwin ? 0 : 1)
+ )
+ && (flags & MOUSE_MAY_STOP_VIS)))) {
+ end_visual_mode();
+ redraw_curbuf_later(INVERTED); // delete the inversion
+ }
+ if (cmdwin_type != 0 && wp != curwin) {
+ // A click outside the command-line window: Use modeless
+ // selection if possible. Allow dragging the status lines.
+ on_sep_line = 0;
+ row = 0;
+ col += wp->w_wincol;
+ wp = curwin;
+ }
+ // Only change window focus when not clicking on or dragging the
+ // status line. Do change focus when releasing the mouse button
+ // (MOUSE_FOCUS was set above if we dragged first).
+ if (dragwin == NULL || (flags & MOUSE_RELEASED))
+ win_enter(wp, true); // can make wp invalid!
+# ifdef CHECK_DOUBLE_CLICK
+ // set topline, to be able to check for double click ourselves
+ if (curwin != old_curwin)
+ set_mouse_topline(curwin);
+# endif
+ if (on_status_line) { // In (or below) status line
+ // Don't use start_arrow() if we're in the same window
+ if (curwin == old_curwin)
+ return IN_STATUS_LINE;
+ else
+ return IN_STATUS_LINE | CURSOR_MOVED;
+ }
+ if (on_sep_line) { // In (or below) status line
+ // Don't use start_arrow() if we're in the same window
+ if (curwin == old_curwin)
+ return IN_SEP_LINE;
+ else
+ return IN_SEP_LINE | CURSOR_MOVED;
+ }
+
+ curwin->w_cursor.lnum = curwin->w_topline;
+ } else if (on_status_line && which_button == MOUSE_LEFT) {
+ if (dragwin != NULL) {
+ // Drag the status line
+ count = row - dragwin->w_winrow - dragwin->w_height + 1
+ - on_status_line;
+ win_drag_status_line(dragwin, count);
+ did_drag |= count;
+ }
+ return IN_STATUS_LINE; // Cursor didn't move
+ } else if (on_sep_line && which_button == MOUSE_LEFT) {
+ if (dragwin != NULL) {
+ // Drag the separator column
+ count = col - dragwin->w_wincol - dragwin->w_width + 1
+ - on_sep_line;
+ win_drag_vsep_line(dragwin, count);
+ did_drag |= count;
+ }
+ return IN_SEP_LINE; // Cursor didn't move
+ } else {
+ // keep_window_focus must be true
+ // before moving the cursor for a left click, stop Visual mode
+ if (flags & MOUSE_MAY_STOP_VIS) {
+ end_visual_mode();
+ redraw_curbuf_later(INVERTED); // delete the inversion
+ }
+
+
+ row -= curwin->w_winrow;
+ col -= curwin->w_wincol;
+
+ // When clicking beyond the end of the window, scroll the screen.
+ // Scroll by however many rows outside the window we are.
+ if (row < 0) {
+ count = 0;
+ for (first = true; curwin->w_topline > 1; ) {
+ if (curwin->w_topfill < diff_check(curwin, curwin->w_topline))
+ ++count;
+ else
+ count += plines(curwin->w_topline - 1);
+ if (!first && count > -row)
+ break;
+ first = false;
+ hasFolding(curwin->w_topline, &curwin->w_topline, NULL);
+ if (curwin->w_topfill < diff_check(curwin, curwin->w_topline)) {
+ ++curwin->w_topfill;
+ } else {
+ --curwin->w_topline;
+ curwin->w_topfill = 0;
+ }
+ }
+ check_topfill(curwin, false);
+ curwin->w_valid &=
+ ~(VALID_WROW|VALID_CROW|VALID_BOTLINE|VALID_BOTLINE_AP);
+ redraw_later(VALID);
+ row = 0;
+ } else if (row >= curwin->w_height) {
+ count = 0;
+ for (first = true; curwin->w_topline < curbuf->b_ml.ml_line_count; ) {
+ if (curwin->w_topfill > 0) {
+ ++count;
+ } else {
+ count += plines(curwin->w_topline);
+ }
+
+ if (!first && count > row - curwin->w_height + 1) {
+ break;
+ }
+ first = false;
+
+ if (hasFolding(curwin->w_topline, NULL, &curwin->w_topline)
+ && curwin->w_topline == curbuf->b_ml.ml_line_count) {
+ break;
+ }
+
+ if (curwin->w_topfill > 0) {
+ --curwin->w_topfill;
+ } else {
+ ++curwin->w_topline;
+ curwin->w_topfill =
+ diff_check_fill(curwin, curwin->w_topline);
+ }
+ }
+ check_topfill(curwin, false);
+ redraw_later(VALID);
+ curwin->w_valid &=
+ ~(VALID_WROW|VALID_CROW|VALID_BOTLINE|VALID_BOTLINE_AP);
+ row = curwin->w_height - 1;
+ } else if (row == 0) {
+ // When dragging the mouse, while the text has been scrolled up as
+ // far as it goes, moving the mouse in the top line should scroll
+ // the text down (done later when recomputing w_topline).
+ if (mouse_dragging > 0
+ && curwin->w_cursor.lnum
+ == curwin->w_buffer->b_ml.ml_line_count
+ && curwin->w_cursor.lnum == curwin->w_topline) {
+ curwin->w_valid &= ~(VALID_TOPLINE);
+ }
+ }
+ }
+
+ // Check for position outside of the fold column.
+ if (curwin->w_p_rl ? col < curwin->w_width - curwin->w_p_fdc :
+ col >= curwin->w_p_fdc + (cmdwin_type == 0 ? 0 : 1)) {
+ mouse_char = ' ';
+ }
+
+ // compute the position in the buffer line from the posn on the screen
+ if (mouse_comp_pos(curwin, &row, &col, &curwin->w_cursor.lnum)) {
+ mouse_past_bottom = true;
+ }
+
+ // Start Visual mode before coladvance(), for when 'sel' != "old"
+ if ((flags & MOUSE_MAY_VIS) && !VIsual_active) {
+ check_visual_highlight();
+ VIsual = old_cursor;
+ VIsual_active = true;
+ VIsual_reselect = true;
+ // if 'selectmode' contains "mouse", start Select mode
+ may_start_select('o');
+ setmouse();
+
+ if (p_smd && msg_silent == 0) {
+ redraw_cmdline = true; // show visual mode later
+ }
+ }
+
+ curwin->w_curswant = col;
+ curwin->w_set_curswant = false; // May still have been true
+ if (coladvance(col) == FAIL) { // Mouse click beyond end of line
+ if (inclusive != NULL) {
+ *inclusive = true;
+ }
+ mouse_past_eol = true;
+ } else if (inclusive != NULL) {
+ *inclusive = false;
+ }
+
+ count = IN_BUFFER;
+ if (curwin != old_curwin || curwin->w_cursor.lnum != old_cursor.lnum
+ || curwin->w_cursor.col != old_cursor.col) {
+ count |= CURSOR_MOVED; // Cursor has moved
+ }
+
+ if (mouse_char == '+') {
+ count |= MOUSE_FOLD_OPEN;
+ } else if (mouse_char != ' ') {
+ count |= MOUSE_FOLD_CLOSE;
+ }
+
+ return count;
+}
+
+// Compute the position in the buffer line from the posn on the screen in
+// window "win".
+// Returns true if the position is below the last line.
+bool mouse_comp_pos(win_T *win, int *rowp, int *colp, linenr_T *lnump)
+{
+ int col = *colp;
+ int row = *rowp;
+ linenr_T lnum;
+ bool retval = false;
+ int off;
+ int count;
+
+ if (win->w_p_rl)
+ col = win->w_width - 1 - col;
+
+ lnum = win->w_topline;
+
+ while (row > 0) {
+ // Don't include filler lines in "count"
+ if (win->w_p_diff
+ && !hasFoldingWin(win, lnum, NULL, NULL, true, NULL)) {
+ if (lnum == win->w_topline) {
+ row -= win->w_topfill;
+ } else {
+ row -= diff_check_fill(win, lnum);
+ }
+ count = plines_win_nofill(win, lnum, true);
+ } else {
+ count = plines_win(win, lnum, true);
+ }
+
+ if (count > row) {
+ break; // Position is in this buffer line.
+ }
+
+ (void)hasFoldingWin(win, lnum, NULL, &lnum, true, NULL);
+
+ if (lnum == win->w_buffer->b_ml.ml_line_count) {
+ retval = true;
+ break; // past end of file
+ }
+ row -= count;
+ ++lnum;
+ }
+
+ if (!retval) {
+ // Compute the column without wrapping.
+ off = win_col_off(win) - win_col_off2(win);
+ if (col < off)
+ col = off;
+ col += row * (win->w_width - off);
+ // add skip column (for long wrapping line)
+ col += win->w_skipcol;
+ }
+
+ if (!win->w_p_wrap) {
+ col += win->w_leftcol;
+ }
+
+ // skip line number and fold column in front of the line
+ col -= win_col_off(win);
+ if (col < 0) {
+ col = 0;
+ }
+
+ *colp = col;
+ *rowp = row;
+ *lnump = lnum;
+ return retval;
+}
+
+// Find the window at screen position "*rowp" and "*colp". The positions are
+// updated to become relative to the top-left of the window.
+win_T *mouse_find_win(int *rowp, int *colp)
+{
+ frame_T *fp;
+
+ fp = topframe;
+ *rowp -= firstwin->w_winrow;
+ for (;; ) {
+ if (fp->fr_layout == FR_LEAF)
+ break;
+ if (fp->fr_layout == FR_ROW) {
+ for (fp = fp->fr_child; fp->fr_next != NULL; fp = fp->fr_next) {
+ if (*colp < fp->fr_width)
+ break;
+ *colp -= fp->fr_width;
+ }
+ } else { // fr_layout == FR_COL
+ for (fp = fp->fr_child; fp->fr_next != NULL; fp = fp->fr_next) {
+ if (*rowp < fp->fr_height)
+ break;
+ *rowp -= fp->fr_height;
+ }
+ }
+ }
+ return fp->fr_win;
+}
diff --git a/src/nvim/mouse.h b/src/nvim/mouse.h
new file mode 100644
index 0000000000..4f797c7480
--- /dev/null
+++ b/src/nvim/mouse.h
@@ -0,0 +1,32 @@
+#ifndef NVIM_MOUSE_H
+#define NVIM_MOUSE_H
+
+#include <stdbool.h>
+
+#include "nvim/vim.h"
+#include "nvim/buffer_defs.h"
+
+// jump_to_mouse() returns one of first four these values, possibly with
+// some of the other three added.
+#define IN_UNKNOWN 0
+#define IN_BUFFER 1
+#define IN_STATUS_LINE 2 // on status or command line
+#define IN_SEP_LINE 4 // on vertical separator line
+#define IN_OTHER_WIN 8 // in other window but can't go there
+#define CURSOR_MOVED 0x100
+#define MOUSE_FOLD_CLOSE 0x200 // clicked on '-' in fold column
+#define MOUSE_FOLD_OPEN 0x400 // clicked on '+' in fold column
+
+// flags for jump_to_mouse()
+#define MOUSE_FOCUS 0x01 // need to stay in this window
+#define MOUSE_MAY_VIS 0x02 // may start Visual mode
+#define MOUSE_DID_MOVE 0x04 // only act when mouse has moved
+#define MOUSE_SETPOS 0x08 // only set current mouse position
+#define MOUSE_MAY_STOP_VIS 0x10 // may stop Visual mode
+#define MOUSE_RELEASED 0x20 // button was released
+
+#ifdef INCLUDE_GENERATED_DECLARATIONS
+# include "mouse.h.generated.h"
+#endif
+
+#endif // NVIM_MOUSE_H
diff --git a/src/nvim/normal.c b/src/nvim/normal.c
index 9ec97bd320..0a43d59607 100644
--- a/src/nvim/normal.c
+++ b/src/nvim/normal.c
@@ -57,9 +57,11 @@
#include "nvim/tag.h"
#include "nvim/term.h"
#include "nvim/ui.h"
+#include "nvim/mouse.h"
#include "nvim/undo.h"
#include "nvim/window.h"
#include "nvim/os/event.h"
+#include "nvim/os/time.h"
/*
* The Visual area is remembered for reselection.
@@ -312,7 +314,6 @@ static const struct nv_cmd {
{K_F8, farsi_fkey, 0, 0},
{K_F9, farsi_fkey, 0, 0},
{K_CURSORHOLD, nv_cursorhold, NV_KEEPREG, 0},
- {K_EVENT, nv_event, NV_KEEPREG, 0},
};
/* Number of commands in nv_cmds[]. */
@@ -483,7 +484,15 @@ normal_cmd (
/*
* Get the command character from the user.
*/
+ event_enable_deferred();
c = safe_vgetc();
+ event_disable_deferred();
+
+ if (c == K_EVENT) {
+ event_process();
+ return;
+ }
+
LANGMAP_ADJUST(c, true);
/*
@@ -708,9 +717,6 @@ getcount:
bool lit = false; /* get extra character literally */
bool langmap_active = false; /* using :lmap mappings */
int lang; /* getting a text character */
-#ifdef USE_IM_CONTROL
- bool save_smd; /* saved value of p_smd */
-#endif
++no_mapping;
++allow_keys; /* no mapping for nchar, but allow key codes */
@@ -759,12 +765,6 @@ getcount:
State = LANGMAP;
langmap_active = true;
}
-#ifdef USE_IM_CONTROL
- save_smd = p_smd;
- p_smd = false; /* Don't let the IM code show the mode here */
- if (lang && curbuf->b_p_iminsert == B_IMODE_IM)
- im_set_active(true);
-#endif
*cp = plain_vgetc();
@@ -774,14 +774,6 @@ getcount:
++allow_keys;
State = NORMAL_BUSY;
}
-#ifdef USE_IM_CONTROL
- if (lang) {
- if (curbuf->b_p_iminsert != B_IMODE_LMAP)
- im_save_status(&curbuf->b_p_iminsert);
- im_set_active(false);
- }
- p_smd = save_smd;
-#endif
State = NORMAL_BUSY;
need_flushbuf |= add_to_showcmd(*cp);
@@ -1001,8 +993,8 @@ getcount:
cursor_on();
out_flush();
if (msg_scroll || emsg_on_display)
- ui_delay(1000L, true); /* wait at least one second */
- ui_delay(3000L, false); /* wait up to three seconds */
+ os_delay(1000L, true); /* wait at least one second */
+ os_delay(3000L, false); /* wait up to three seconds */
State = save_State;
msg_scroll = false;
@@ -7382,8 +7374,3 @@ static void nv_cursorhold(cmdarg_T *cap)
did_cursorhold = true;
cap->retval |= CA_COMMAND_BUSY; /* don't call edit() now */
}
-
-static void nv_event(cmdarg_T *cap)
-{
- event_process();
-}
diff --git a/src/nvim/ops.c b/src/nvim/ops.c
index 5ef605bb3b..6bf3f6036f 100644
--- a/src/nvim/ops.c
+++ b/src/nvim/ops.c
@@ -45,10 +45,9 @@
#include "nvim/search.h"
#include "nvim/strings.h"
#include "nvim/term.h"
-#include "nvim/ui.h"
#include "nvim/undo.h"
#include "nvim/window.h"
-#include "nvim/api/private/helpers.h"
+#include "nvim/os/input.h"
/*
* Registers:
@@ -1112,7 +1111,7 @@ insert_reg (
* register a and then, in insert mode, doing CTRL-R a.
* If you hit CTRL-C, the loop will be broken here.
*/
- ui_breakcheck();
+ os_breakcheck();
if (got_int)
return FAIL;
@@ -1296,7 +1295,7 @@ cmdline_paste_reg (
/* Check for CTRL-C, in case someone tries to paste a few thousand
* lines and gets bored. */
- ui_breakcheck();
+ os_breakcheck();
if (got_int)
return FAIL;
}
@@ -3254,7 +3253,7 @@ void ex_display(exarg_T *eap)
MSG_PUTS_ATTR("^J", attr);
out_flush(); /* show one line at a time */
}
- ui_breakcheck();
+ os_breakcheck();
}
/*
@@ -3339,7 +3338,7 @@ dis_msg (
} else
msg_outtrans_len(p++, 1);
}
- ui_breakcheck();
+ os_breakcheck();
}
/*
@@ -5079,7 +5078,7 @@ void cursor_pos_info(void)
for (lnum = 1; lnum <= curbuf->b_ml.ml_line_count; ++lnum) {
/* Check for a CTRL-C every 100000 characters. */
if (byte_count > last_check) {
- ui_breakcheck();
+ os_breakcheck();
if (got_int)
return;
last_check = byte_count + 100000L;
diff --git a/src/nvim/option.c b/src/nvim/option.c
index 830a30204b..ee70b5bf8a 100644
--- a/src/nvim/option.c
+++ b/src/nvim/option.c
@@ -75,10 +75,10 @@
#include "nvim/strings.h"
#include "nvim/syntax.h"
#include "nvim/term.h"
-#include "nvim/ui.h"
#include "nvim/undo.h"
#include "nvim/window.h"
#include "nvim/os/os.h"
+#include "nvim/os/input.h"
/*
* The options that are local to a window or buffer have "indir" set to one of
@@ -912,18 +912,10 @@ static struct vimoption
(char_u *)NULL, PV_NONE,
{(char_u *)"", (char_u *)0L} SCRIPTID_INIT},
{"imcmdline", "imc", P_BOOL|P_VI_DEF,
-#ifdef USE_IM_CONTROL
- (char_u *)&p_imcmdline, PV_NONE,
-#else
(char_u *)NULL, PV_NONE,
-#endif
{(char_u *)FALSE, (char_u *)0L} SCRIPTID_INIT},
{"imdisable", "imd", P_BOOL|P_VI_DEF,
-#ifdef USE_IM_CONTROL
- (char_u *)&p_imdisable, PV_NONE,
-#else
(char_u *)NULL, PV_NONE,
-#endif
{(char_u *)FALSE, (char_u *)0L}
SCRIPTID_INIT},
{"iminsert", "imi", P_NUM|P_VI_DEF,
@@ -5134,18 +5126,6 @@ set_bool_option (
foldUpdateAll(curwin);
}
-#ifdef USE_IM_CONTROL
- /* 'imdisable' */
- else if ((int *)varp == &p_imdisable) {
- /* Only de-activate it here, it will be enabled when changing mode. */
- if (p_imdisable)
- im_set_active(FALSE);
- else if (State & INSERT)
- /* When the option is set from an autocommand, it may need to take
- * effect right away. */
- im_set_active(curbuf->b_p_iminsert == B_IMODE_IM);
- }
-#endif
/* 'spell' */
else if ((int *)varp == &curwin->w_p_spell) {
@@ -6123,7 +6103,7 @@ showoptions (
col += INC;
}
out_flush();
- ui_breakcheck();
+ os_breakcheck();
}
}
free(items);
diff --git a/src/nvim/option_defs.h b/src/nvim/option_defs.h
index cd61b6427c..89264f8982 100644
--- a/src/nvim/option_defs.h
+++ b/src/nvim/option_defs.h
@@ -416,10 +416,6 @@ EXTERN int p_arshape; /* 'arabicshape' */
EXTERN int p_icon; /* 'icon' */
EXTERN char_u *p_iconstring; /* 'iconstring' */
EXTERN int p_ic; /* 'ignorecase' */
-#ifdef USE_IM_CONTROL
-EXTERN int p_imcmdline; /* 'imcmdline' */
-EXTERN int p_imdisable; /* 'imdisable' */
-#endif
EXTERN int p_is; /* 'incsearch' */
EXTERN int p_im; /* 'insertmode' */
EXTERN char_u *p_isf; /* 'isfname' */
diff --git a/src/nvim/os/event.c b/src/nvim/os/event.c
index 1477072f4f..34560610bd 100644
--- a/src/nvim/os/event.c
+++ b/src/nvim/os/event.c
@@ -18,6 +18,8 @@
#include "nvim/vim.h"
#include "nvim/memory.h"
#include "nvim/misc2.h"
+#include "nvim/term.h"
+#include "nvim/screen.h"
#include "nvim/lib/klist.h"
@@ -39,6 +41,7 @@ typedef struct {
// loop(to avoid recursion), but before returning from
// `event_poll`
static klist_t(Event) *deferred_events = NULL, *immediate_events = NULL;
+static int deferred_events_allowed = 0;
void event_init(void)
{
@@ -134,7 +137,17 @@ void event_poll(int ms)
bool event_has_deferred(void)
{
- return !kl_empty(deferred_events);
+ return deferred_events_allowed && !kl_empty(deferred_events);
+}
+
+void event_enable_deferred(void)
+{
+ ++deferred_events_allowed;
+}
+
+void event_disable_deferred(void)
+{
+ --deferred_events_allowed;
}
// Queue an event
@@ -146,6 +159,11 @@ void event_push(Event event, bool deferred)
void event_process(void)
{
process_events_from(deferred_events);
+
+ if (must_redraw) {
+ update_screen(0);
+ out_flush();
+ }
}
static void process_events_from(klist_t(Event) *queue)
diff --git a/src/nvim/os/input.c b/src/nvim/os/input.c
index 3ebfb3f12b..686fe1f06d 100644
--- a/src/nvim/os/input.c
+++ b/src/nvim/os/input.c
@@ -17,8 +17,11 @@
#include "nvim/keymap.h"
#include "nvim/mbyte.h"
#include "nvim/fileio.h"
+#include "nvim/ex_cmds2.h"
#include "nvim/getchar.h"
#include "nvim/term.h"
+#include "nvim/main.h"
+#include "nvim/misc1.h"
#define READ_BUFFER_SIZE 0xfff
#define INPUT_BUFFER_SIZE (READ_BUFFER_SIZE * 4)
@@ -84,13 +87,11 @@ void input_stop(void)
// Low level input function.
int os_inchar(uint8_t *buf, int maxlen, int ms, int tb_change_cnt)
{
- InbufPollResult result;
-
- if (event_has_deferred()) {
- // Return pending event bytes
- return push_event_key(buf, maxlen);
+ if (rbuffer_pending(input_buffer)) {
+ return (int)rbuffer_read(input_buffer, (char *)buf, (size_t)maxlen);
}
+ InbufPollResult result;
if (ms >= 0) {
if ((result = inbuf_poll(ms)) == kInputNone) {
return 0;
@@ -110,24 +111,27 @@ int os_inchar(uint8_t *buf, int maxlen, int ms, int tb_change_cnt)
}
}
- // If there are deferred events, return the keys directly
- if (event_has_deferred()) {
- return push_event_key(buf, maxlen);
- }
-
// If input was put directly in typeahead buffer bail out here.
if (typebuf_changed(tb_change_cnt)) {
return 0;
}
+ if (rbuffer_pending(input_buffer)) {
+ // Safe to convert rbuffer_read to int, it will never overflow since we use
+ // relatively small buffers.
+ return (int)rbuffer_read(input_buffer, (char *)buf, (size_t)maxlen);
+ }
+
+ // If there are deferred events, return the keys directly
+ if (event_has_deferred()) {
+ return push_event_key(buf, maxlen);
+ }
+
if (result == kInputEof) {
read_error_exit();
- return 0;
}
- // Safe to convert rbuffer_read to int, it will never overflow since
- // we use relatively small buffers.
- return (int)rbuffer_read(input_buffer, (char *)buf, (size_t)maxlen);
+ return 0;
}
// Check if a character is available for reading
@@ -183,7 +187,16 @@ size_t input_enqueue(String keys)
static bool input_poll(int ms)
{
+ if (do_profiling == PROF_YES && ms) {
+ prof_inchar_enter();
+ }
+
event_poll_until(ms, input_ready());
+
+ if (do_profiling == PROF_YES && ms) {
+ prof_inchar_exit();
+ }
+
return input_ready();
}
@@ -281,7 +294,7 @@ static void convert_input(void)
static void process_interrupts(void)
{
- if (!ctrl_c_interrupts) {
+ if (mapped_ctrl_c) {
return;
}
@@ -319,10 +332,17 @@ static int push_event_key(uint8_t *buf, int maxlen)
// Check if there's pending input
static bool input_ready(void)
{
- return typebuf_was_filled || // API call filled typeahead
- event_has_deferred() || // Events must be processed
- (!embedded_mode && (
- rbuffer_pending(input_buffer) > 0 || // Stdin input
- eof)); // Stdin closed
+ return typebuf_was_filled || // API call filled typeahead
+ rbuffer_pending(input_buffer) > 0 || // Stdin input
+ event_has_deferred() || // Events must be processed
+ (!embedded_mode && eof); // Stdin closed
}
+// Exit because of an input read error.
+static void read_error_exit(void)
+{
+ if (silent_mode) /* Normal way to exit for "ex -s" */
+ getout(0);
+ STRCPY(IObuff, _("Vim: Error reading input, exiting...\n"));
+ preserve_exit();
+}
diff --git a/src/nvim/os_unix.c b/src/nvim/os_unix.c
index 8ab61045dc..3bf1198b46 100644
--- a/src/nvim/os_unix.c
+++ b/src/nvim/os_unix.c
@@ -46,7 +46,6 @@
#include "nvim/tempfile.h"
#include "nvim/term.h"
#include "nvim/types.h"
-#include "nvim/ui.h"
#include "nvim/os/os.h"
#include "nvim/os/time.h"
#include "nvim/os/event.h"
diff --git a/src/nvim/path.c b/src/nvim/path.c
index ff97b7774a..e8d31f3f73 100644
--- a/src/nvim/path.c
+++ b/src/nvim/path.c
@@ -31,7 +31,7 @@
#include "nvim/strings.h"
#include "nvim/tag.h"
#include "nvim/types.h"
-#include "nvim/ui.h"
+#include "nvim/os/input.h"
#include "nvim/window.h"
#define URL_SLASH 1 /* path_is_url() has found "://" */
@@ -449,7 +449,7 @@ unix_expandpath (
/* Expanding "**" may take a long time, check for CTRL-C. */
if (stardepth > 0) {
- ui_breakcheck();
+ os_breakcheck();
if (got_int)
return 0;
}
@@ -850,7 +850,7 @@ static void uniquefy_paths(garray_T *gap, char_u *pattern)
STRMOVE(path + STRLEN(path), short_name);
}
}
- ui_breakcheck();
+ os_breakcheck();
}
/* Shorten filenames in /in/current/directory/{filename} */
@@ -879,7 +879,7 @@ static void uniquefy_paths(garray_T *gap, char_u *pattern)
free(fnames[i]);
fnames[i] = rel_path;
sort_again = TRUE;
- ui_breakcheck();
+ os_breakcheck();
}
free(curdir);
diff --git a/src/nvim/quickfix.c b/src/nvim/quickfix.c
index 3de7f73339..4baba00ccf 100644
--- a/src/nvim/quickfix.c
+++ b/src/nvim/quickfix.c
@@ -49,9 +49,9 @@
#include "nvim/strings.h"
#include "nvim/term.h"
#include "nvim/tempfile.h"
-#include "nvim/ui.h"
#include "nvim/window.h"
#include "nvim/os/os.h"
+#include "nvim/os/input.h"
struct dir_stack_T {
@@ -1791,7 +1791,7 @@ void qf_list(exarg_T *eap)
qfp = qfp->qf_next;
++i;
- ui_breakcheck();
+ os_breakcheck();
}
}
diff --git a/src/nvim/screen.c b/src/nvim/screen.c
index 73df08aac9..2dbf3f8888 100644
--- a/src/nvim/screen.c
+++ b/src/nvim/screen.c
@@ -129,10 +129,10 @@
#include "nvim/strings.h"
#include "nvim/syntax.h"
#include "nvim/term.h"
-#include "nvim/ui.h"
#include "nvim/undo.h"
#include "nvim/version.h"
#include "nvim/window.h"
+#include "nvim/os/time.h"
#define MB_FILLER_CHAR '<' /* character used when a double-width character
* doesn't fit. */
@@ -6261,7 +6261,7 @@ void check_for_delay(int check_msg_scroll)
&& !did_wait_return
&& emsg_silent == 0) {
out_flush();
- ui_delay(1000L, true);
+ os_delay(1000L, true);
emsg_on_display = FALSE;
if (check_msg_scroll)
msg_scroll = FALSE;
@@ -6307,6 +6307,8 @@ void screenalloc(bool doclear)
static int entered = FALSE; /* avoid recursiveness */
static int done_outofmem_msg = FALSE; /* did outofmem message */
int retry_count = 0;
+ const bool l_enc_utf8 = enc_utf8;
+ const int l_enc_dbcs = enc_dbcs;
retry:
/*
@@ -6317,8 +6319,8 @@ retry:
if ((ScreenLines != NULL
&& Rows == screen_Rows
&& Columns == screen_Columns
- && enc_utf8 == (ScreenLinesUC != NULL)
- && (enc_dbcs == DBCS_JPNU) == (ScreenLines2 != NULL)
+ && l_enc_utf8 == (ScreenLinesUC != NULL)
+ && (l_enc_dbcs == DBCS_JPNU) == (ScreenLines2 != NULL)
&& p_mco == Screen_mco
)
|| Rows == 0
@@ -6364,13 +6366,13 @@ retry:
new_ScreenLines = xmalloc((size_t)((Rows + 1) * Columns * sizeof(schar_T)));
memset(new_ScreenLinesC, 0, sizeof(u8char_T *) * MAX_MCO);
- if (enc_utf8) {
+ if (l_enc_utf8) {
new_ScreenLinesUC = xmalloc(
(size_t)((Rows + 1) * Columns * sizeof(u8char_T)));
for (i = 0; i < p_mco; ++i)
new_ScreenLinesC[i] = xcalloc((Rows + 1) * Columns, sizeof(u8char_T));
}
- if (enc_dbcs == DBCS_JPNU)
+ if (l_enc_dbcs == DBCS_JPNU)
new_ScreenLines2 = xmalloc(
(size_t)((Rows + 1) * Columns * sizeof(schar_T)));
new_ScreenAttrs = xmalloc((size_t)((Rows + 1) * Columns * sizeof(sattr_T)));
@@ -6389,8 +6391,8 @@ retry:
if (new_ScreenLinesC[i] == NULL)
break;
if (new_ScreenLines == NULL
- || (enc_utf8 && (new_ScreenLinesUC == NULL || i != p_mco))
- || (enc_dbcs == DBCS_JPNU && new_ScreenLines2 == NULL)
+ || (l_enc_utf8 && (new_ScreenLinesUC == NULL || i != p_mco))
+ || (l_enc_dbcs == DBCS_JPNU && new_ScreenLines2 == NULL)
|| new_ScreenAttrs == NULL
|| new_LineOffset == NULL
|| new_LineWraps == NULL
@@ -6438,7 +6440,7 @@ retry:
if (!doclear) {
(void)memset(new_ScreenLines + new_row * Columns,
' ', (size_t)Columns * sizeof(schar_T));
- if (enc_utf8) {
+ if (l_enc_utf8) {
(void)memset(new_ScreenLinesUC + new_row * Columns,
0, (size_t)Columns * sizeof(u8char_T));
for (i = 0; i < p_mco; ++i)
@@ -6446,7 +6448,7 @@ retry:
+ new_row * Columns,
0, (size_t)Columns * sizeof(u8char_T));
}
- if (enc_dbcs == DBCS_JPNU)
+ if (l_enc_dbcs == DBCS_JPNU)
(void)memset(new_ScreenLines2 + new_row * Columns,
0, (size_t)Columns * sizeof(schar_T));
(void)memset(new_ScreenAttrs + new_row * Columns,
@@ -6459,12 +6461,12 @@ retry:
len = Columns;
/* When switching to utf-8 don't copy characters, they
* may be invalid now. Also when p_mco changes. */
- if (!(enc_utf8 && ScreenLinesUC == NULL)
+ if (!(l_enc_utf8 && ScreenLinesUC == NULL)
&& p_mco == Screen_mco)
memmove(new_ScreenLines + new_LineOffset[new_row],
ScreenLines + LineOffset[old_row],
(size_t)len * sizeof(schar_T));
- if (enc_utf8 && ScreenLinesUC != NULL
+ if (l_enc_utf8 && ScreenLinesUC != NULL
&& p_mco == Screen_mco) {
memmove(new_ScreenLinesUC + new_LineOffset[new_row],
ScreenLinesUC + LineOffset[old_row],
@@ -6475,7 +6477,7 @@ retry:
ScreenLinesC[i] + LineOffset[old_row],
(size_t)len * sizeof(u8char_T));
}
- if (enc_dbcs == DBCS_JPNU && ScreenLines2 != NULL)
+ if (l_enc_dbcs == DBCS_JPNU && ScreenLines2 != NULL)
memmove(new_ScreenLines2 + new_LineOffset[new_row],
ScreenLines2 + LineOffset[old_row],
(size_t)len * sizeof(schar_T));
diff --git a/src/nvim/search.c b/src/nvim/search.c
index bd1811c7fb..78d9dcbccb 100644
--- a/src/nvim/search.c
+++ b/src/nvim/search.c
@@ -48,6 +48,7 @@
#include "nvim/term.h"
#include "nvim/ui.h"
#include "nvim/window.h"
+#include "nvim/os/time.h"
#ifdef INCLUDE_GENERATED_DECLARATIONS
@@ -2053,9 +2054,9 @@ showmatch (
* available.
*/
if (vim_strchr(p_cpo, CPO_SHOWMATCH) != NULL)
- ui_delay(p_mat * 100L, true);
+ os_delay(p_mat * 100L, true);
else if (!char_avail())
- ui_delay(p_mat * 100L, false);
+ os_delay(p_mat * 100L, false);
curwin->w_cursor = save_cursor; /* restore cursor position */
p_so = save_so;
p_siso = save_siso;
diff --git a/src/nvim/spell.c b/src/nvim/spell.c
index ea5ce7ee0d..fa786fdd74 100644
--- a/src/nvim/spell.c
+++ b/src/nvim/spell.c
@@ -325,9 +325,9 @@
#include "nvim/syntax.h"
#include "nvim/term.h"
#include "nvim/tempfile.h"
-#include "nvim/ui.h"
#include "nvim/undo.h"
#include "nvim/os/os.h"
+#include "nvim/os/input.h"
#ifndef UNIX // it's in os_unix_defs.h for Unix
# include <time.h> // for time_t
@@ -9018,7 +9018,7 @@ static void spell_suggest_intern(suginfo_T *su, bool interactive)
// When CTRL-C was hit while searching do show the results. Only clear
// got_int when using a command, not for spellsuggest().
- ui_breakcheck();
+ os_breakcheck();
if (interactive && got_int) {
(void)vgetc();
got_int = FALSE;
@@ -10616,7 +10616,7 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char_u *fword, bool so
// Don't check for CTRL-C too often, it takes time.
if (--breakcheckcount == 0) {
- ui_breakcheck();
+ os_breakcheck();
breakcheckcount = 1000;
}
}
diff --git a/src/nvim/strings.c b/src/nvim/strings.c
index d34014ac75..6c69b3b34a 100644
--- a/src/nvim/strings.c
+++ b/src/nvim/strings.c
@@ -42,7 +42,6 @@
#include "nvim/syntax.h"
#include "nvim/tag.h"
#include "nvim/term.h"
-#include "nvim/ui.h"
#include "nvim/window.h"
#include "nvim/os/os.h"
#include "nvim/os/shell.h"
diff --git a/src/nvim/syntax.c b/src/nvim/syntax.c
index 6c5c0f37b1..69d6479cf3 100644
--- a/src/nvim/syntax.c
+++ b/src/nvim/syntax.c
@@ -44,8 +44,8 @@
#include "nvim/strings.h"
#include "nvim/syntax_defs.h"
#include "nvim/term.h"
-#include "nvim/ui.h"
#include "nvim/os/os.h"
+#include "nvim/os/time.h"
/*
* Structure that stores information about a highlight group.
@@ -7606,7 +7606,7 @@ static void highlight_list_two(int cnt, int attr)
msg_puts_attr((char_u *)&("N \bI \b! \b"[cnt / 11]), attr);
msg_clr_eos();
out_flush();
- ui_delay(cnt == 99 ? 40L : (long)cnt * 50L, false);
+ os_delay(cnt == 99 ? 40L : (long)cnt * 50L, false);
}
diff --git a/src/nvim/tag.c b/src/nvim/tag.c
index e267280bbd..fb39e069f0 100644
--- a/src/nvim/tag.c
+++ b/src/nvim/tag.c
@@ -10,6 +10,7 @@
* Code to handle tags and the tag stack
*/
+#include <assert.h>
#include <errno.h>
#include <inttypes.h>
#include <stdbool.h>
@@ -48,9 +49,10 @@
#include "nvim/search.h"
#include "nvim/strings.h"
#include "nvim/term.h"
-#include "nvim/ui.h"
#include "nvim/window.h"
#include "nvim/os/os.h"
+#include "nvim/os/time.h"
+#include "nvim/os/input.h"
/*
* Structure to hold pointers to various items in a tag line.
@@ -671,7 +673,7 @@ do_tag (
}
if (msg_col)
msg_putchar('\n');
- ui_breakcheck();
+ os_breakcheck();
}
if (got_int)
got_int = FALSE; /* only stop the listing */
@@ -880,7 +882,7 @@ do_tag (
give_warning(IObuff, ic);
if (ic && !msg_scrolled && msg_silent == 0) {
out_flush();
- ui_delay(1000L, true);
+ os_delay(1000L, true);
}
}
@@ -2307,6 +2309,7 @@ jumpto_tag (
win_T *curwin_save = NULL;
char_u *full_fname = NULL;
int old_KeyTyped = KeyTyped; /* getting the file may reset it */
+ const int l_g_do_tagpreview = g_do_tagpreview;
pbuf = xmalloc(LSIZE);
@@ -2363,7 +2366,7 @@ jumpto_tag (
++RedrawingDisabled;
- if (g_do_tagpreview != 0) {
+ if (l_g_do_tagpreview != 0) {
postponed_split = 0; /* don't split again below */
curwin_save = curwin; /* Save current window */
@@ -2395,7 +2398,7 @@ jumpto_tag (
if (keep_help) {
/* A :ta from a help file will keep the b_help flag set. For ":ptag"
* we need to use the flag from the window where we came from. */
- if (g_do_tagpreview != 0)
+ if (l_g_do_tagpreview != 0)
keep_help_flag = curwin_save->w_buffer->b_help;
else
keep_help_flag = curbuf->b_help;
@@ -2491,7 +2494,7 @@ jumpto_tag (
MSG(_("E435: Couldn't find tag, just guessing!"));
if (!msg_scrolled && msg_silent == 0) {
out_flush();
- ui_delay(1000L, true);
+ os_delay(1000L, true);
}
}
retval = OK;
@@ -2541,7 +2544,7 @@ jumpto_tag (
foldOpenCursor();
}
- if (g_do_tagpreview != 0
+ if (l_g_do_tagpreview != 0
&& curwin != curwin_save && win_valid(curwin_save)) {
/* Return cursor to where we were */
validate_cursor();
@@ -2779,7 +2782,8 @@ int get_tags(list_T *list, char_u *pat)
TAG_REGEXP | TAG_NOIC, (int)MAXCOL, NULL);
if (ret == OK && num_matches > 0) {
for (i = 0; i < num_matches; ++i) {
- parse_match(matches[i], &tp);
+ int parse_result = parse_match(matches[i], &tp);
+ assert(parse_result == OK);
is_static = test_for_static(&tp);
/* Skip pseudo-tag lines. */
@@ -2796,7 +2800,7 @@ int get_tags(list_T *list, char_u *pat)
|| add_tag_field(dict, "cmd", tp.command,
tp.command_end) == FAIL
|| add_tag_field(dict, "kind", tp.tagkind,
- tp.tagkind_end) == FAIL
+ tp.tagkind ? tp.tagkind_end : NULL) == FAIL
|| dict_add_nr_str(dict, "static", is_static, NULL) == FAIL)
ret = FAIL;
diff --git a/src/nvim/term.c b/src/nvim/term.c
index 263b81fc3a..3d1053bd2f 100644
--- a/src/nvim/term.c
+++ b/src/nvim/term.c
@@ -54,6 +54,7 @@
#include "nvim/window.h"
#include "nvim/os/os.h"
#include "nvim/os/time.h"
+#include "nvim/os/input.h"
#ifdef HAVE_TGETENT
# ifdef HAVE_TERMIOS_H
@@ -1330,7 +1331,7 @@ int set_termname(char_u *term)
if (emsg_silent == 0) {
screen_start(); /* don't know where cursor is now */
out_flush();
- ui_delay(2000L, true);
+ os_delay(2000L, true);
}
set_string_option_direct((char_u *)"term", -1, term,
OPT_FREE, 0);
@@ -2302,7 +2303,7 @@ void set_shellsize(int width, int height, int mustset)
Rows = height;
Columns = width;
check_shellsize();
- ui_set_shellsize(mustset);
+ mch_set_shellsize();
} else
check_shellsize();
@@ -4111,7 +4112,7 @@ void show_termcodes(void)
col += INC3;
}
out_flush();
- ui_breakcheck();
+ os_breakcheck();
}
}
free(items);
diff --git a/src/nvim/testdir/Makefile b/src/nvim/testdir/Makefile
index 9ca2c9688a..6bacef9778 100644
--- a/src/nvim/testdir/Makefile
+++ b/src/nvim/testdir/Makefile
@@ -52,13 +52,13 @@ ifdef USE_VALGRIND
--leak-check=yes \
--track-origins=yes
# VALGRIND_TOOL := exp-sgcheck
- TOOL := valgrind -q \
- -q \
- $(VALGRIND_TOOL) \
- --suppressions=../../.valgrind.supp \
- --error-exitcode=123 \
- --log-file=valgrind.\%p.$* \
- $(VGDB) \
+ TOOL := valgrind -q \
+ -q \
+ $(VALGRIND_TOOL) \
+ --suppressions=../../../.valgrind.supp \
+ --error-exitcode=123 \
+ --log-file=valgrind.\%p.$* \
+ $(VGDB) \
--trace-children=yes
else
ifdef USE_GDB
diff --git a/src/nvim/testdir/test101.in b/src/nvim/testdir/test101.in
deleted file mode 100644
index 04c934f2c5..0000000000
--- a/src/nvim/testdir/test101.in
+++ /dev/null
@@ -1,45 +0,0 @@
-Test for v:hlsearch vim: set ft=vim :
-
-STARTTEST
-:" Last abc: Q
-:so small.vim
-:new
-:call setline(1, repeat(['aaa'], 10))
-:set hlsearch nolazyredraw
-:let r=[]
-:command -nargs=0 -bar AddR :call add(r, [screenattr(1, 1), v:hlsearch])
-/aaa
-:AddR
-:nohlsearch
-:AddR
-:let v:hlsearch=1
-:AddR
-:let v:hlsearch=0
-:AddR
-:set hlsearch
-:AddR
-:let v:hlsearch=0
-:AddR
-n:AddR
-:let v:hlsearch=0
-:AddR
-/
-:AddR
-:let r1=r[0][0]
-:" I guess it is not guaranteed that screenattr outputs always the same character
-:call map(r, 'v:val[1].":".(v:val[0]==r1?"highlighted":"not highlighted")')
-:try
-: let v:hlsearch=[]
-:catch
-: call add(r, matchstr(v:exception,'^Vim(let):E\d\+:'))
-:endtry
-:bwipeout!
-:$put=r
-:call garbagecollect(1)
-:"
-:/^start:/,$wq! test.out
-:" vim: et ts=4 isk-=\:
-:call getchar()
-ENDTEST
-
-start:
diff --git a/src/nvim/testdir/test101.ok b/src/nvim/testdir/test101.ok
deleted file mode 100644
index 3ed7436cf7..0000000000
--- a/src/nvim/testdir/test101.ok
+++ /dev/null
@@ -1,11 +0,0 @@
-start:
-1:highlighted
-0:not highlighted
-1:highlighted
-0:not highlighted
-1:highlighted
-0:not highlighted
-1:highlighted
-0:not highlighted
-1:highlighted
-Vim(let):E706:
diff --git a/src/nvim/testdir/test104.in b/src/nvim/testdir/test104.in
deleted file mode 100644
index fd847131e9..0000000000
--- a/src/nvim/testdir/test104.in
+++ /dev/null
@@ -1,30 +0,0 @@
-Tests for :let. vim: set ft=vim ts=8 :
-
-STARTTEST
-:so small.vim
-:set runtimepath+=./sautest
-:" Test to not autoload when assigning. It causes internal error.
-:try
-: let Test104#numvar = function('tr')
-: $put ='OK: ' . string(Test104#numvar)
-:catch
-: $put ='FAIL: ' . v:exception
-:endtry
-:let a = 1
-:let b = 2
-:for letargs in ['a b', '{0 == 1 ? "a" : "b"}', '{0 == 1 ? "a" : "b"} a', 'a {0 == 1 ? "a" : "b"}']
-: try
-: redir => messages
-: execute 'let' letargs
-: redir END
-: $put ='OK:'
-: $put =split(substitute(messages, '\n', '\0 ', 'g'), '\n')
-: catch
-: $put ='FAIL: ' . v:exception
-: redir END
-: endtry
-:endfor
-:/^Results/,$wq! test.out
-ENDTEST
-
-Results of test104:
diff --git a/src/nvim/testdir/test104.ok b/src/nvim/testdir/test104.ok
deleted file mode 100644
index 5fb20945c3..0000000000
--- a/src/nvim/testdir/test104.ok
+++ /dev/null
@@ -1,13 +0,0 @@
-Results of test104:
-OK: function('tr')
-OK:
- a #1
- b #2
-OK:
- b #2
-OK:
- b #2
- a #1
-OK:
- a #1
- b #2
diff --git a/src/nvim/testdir/test105.in b/src/nvim/testdir/test105.in
deleted file mode 100644
index bfb4b65fbb..0000000000
--- a/src/nvim/testdir/test105.in
+++ /dev/null
@@ -1,45 +0,0 @@
-Test filename modifiers vim: set ft=vim :
-
-STARTTEST
-:source small.vim
-:%delete _
-:set shell=sh
-:set shellslash
-:let tab="\t"
-:command -nargs=1 Put :let expr=<q-args> | $put =expr.tab.strtrans(string(eval(expr)))
-:let $HOME=fnamemodify('.', ':p:h:h:h')
-:Put fnamemodify('.', ':p' )[-1:]
-:Put fnamemodify('.', ':p:h' )[-1:]
-:Put fnamemodify('test.out', ':p' )[-1:]
-:Put fnamemodify('test.out', ':.' )
-:Put fnamemodify('../testdir/a', ':.' )
-:Put fnamemodify('test.out', ':~' )
-:Put fnamemodify('../testdir/a', ':~' )
-:Put fnamemodify('../testdir/a', ':t' )
-:Put fnamemodify('.', ':p:t' )
-:Put fnamemodify('test.out', ':p:t' )
-:Put fnamemodify('test.out', ':p:e' )
-:Put fnamemodify('test.out', ':p:t:e' )
-:Put fnamemodify('abc.fb2.tar.gz', ':r' )
-:Put fnamemodify('abc.fb2.tar.gz', ':r:r' )
-:Put fnamemodify('abc.fb2.tar.gz', ':r:r:r' )
-:Put substitute(fnamemodify('abc.fb2.tar.gz', ':p:r:r'), '.*\(nvim/testdir/.*\)', '\1', '')
-:Put fnamemodify('abc.fb2.tar.gz', ':e' )
-:Put fnamemodify('abc.fb2.tar.gz', ':e:e' )
-:Put fnamemodify('abc.fb2.tar.gz', ':e:e:e' )
-:Put fnamemodify('abc.fb2.tar.gz', ':e:e:e:e')
-:Put fnamemodify('abc.fb2.tar.gz', ':e:e:r' )
-:Put fnamemodify('abc def', ':S' )
-:Put fnamemodify('abc" "def', ':S' )
-:Put fnamemodify('abc"%"def', ':S' )
-:Put fnamemodify('abc'' ''def', ':S' )
-:Put fnamemodify('abc''%''def', ':S' )
-:Put fnamemodify("abc\ndef", ':S' )
-:set shell=tcsh
-:Put fnamemodify("abc\ndef", ':S' )
-:$put ='vim: ts=8'
-:1 delete _
-:w! test.out
-:qa!
-ENDTEST
-
diff --git a/src/nvim/testdir/test105.ok b/src/nvim/testdir/test105.ok
deleted file mode 100644
index 0b30ee4281..0000000000
--- a/src/nvim/testdir/test105.ok
+++ /dev/null
@@ -1,29 +0,0 @@
-fnamemodify('.', ':p' )[-1:] '/'
-fnamemodify('.', ':p:h' )[-1:] 'r'
-fnamemodify('test.out', ':p' )[-1:] 't'
-fnamemodify('test.out', ':.' ) 'test.out'
-fnamemodify('../testdir/a', ':.' ) 'a'
-fnamemodify('test.out', ':~' ) '~/nvim/testdir/test.out'
-fnamemodify('../testdir/a', ':~' ) '~/nvim/testdir/a'
-fnamemodify('../testdir/a', ':t' ) 'a'
-fnamemodify('.', ':p:t' ) ''
-fnamemodify('test.out', ':p:t' ) 'test.out'
-fnamemodify('test.out', ':p:e' ) 'out'
-fnamemodify('test.out', ':p:t:e' ) 'out'
-fnamemodify('abc.fb2.tar.gz', ':r' ) 'abc.fb2.tar'
-fnamemodify('abc.fb2.tar.gz', ':r:r' ) 'abc.fb2'
-fnamemodify('abc.fb2.tar.gz', ':r:r:r' ) 'abc'
-substitute(fnamemodify('abc.fb2.tar.gz', ':p:r:r'), '.*\(nvim/testdir/.*\)', '\1', '') 'nvim/testdir/abc.fb2'
-fnamemodify('abc.fb2.tar.gz', ':e' ) 'gz'
-fnamemodify('abc.fb2.tar.gz', ':e:e' ) 'tar.gz'
-fnamemodify('abc.fb2.tar.gz', ':e:e:e' ) 'fb2.tar.gz'
-fnamemodify('abc.fb2.tar.gz', ':e:e:e:e') 'fb2.tar.gz'
-fnamemodify('abc.fb2.tar.gz', ':e:e:r' ) 'tar'
-fnamemodify('abc def', ':S' ) '''abc def'''
-fnamemodify('abc" "def', ':S' ) '''abc" "def'''
-fnamemodify('abc"%"def', ':S' ) '''abc"%"def'''
-fnamemodify('abc'' ''def', ':S' ) '''abc''\'''' ''\''''def'''
-fnamemodify('abc''%''def', ':S' ) '''abc''\''''%''\''''def'''
-fnamemodify("abc\ndef", ':S' ) '''abc^@def'''
-fnamemodify("abc\ndef", ':S' ) '''abc\^@def'''
-vim: ts=8
diff --git a/src/nvim/testdir/test21.in b/src/nvim/testdir/test21.in
deleted file mode 100644
index 491b9f7404..0000000000
--- a/src/nvim/testdir/test21.in
+++ /dev/null
@@ -1,19 +0,0 @@
-Tests for [ CTRL-I with a count and CTRL-W CTRL-I with a count
-
-STARTTEST
-:so small.vim
-/start
-6[ :.w! test.out
-?start here
-6 :.w >>test.out
-:qa!
-ENDTEST
-
-#include test21.in
-
-/* test text test tex start here
- some text
- test text
- start OK if found this line
- start found wrong line
-test text
diff --git a/src/nvim/testdir/test21.ok b/src/nvim/testdir/test21.ok
deleted file mode 100644
index d9f1b759ce..0000000000
--- a/src/nvim/testdir/test21.ok
+++ /dev/null
@@ -1,2 +0,0 @@
- start OK if found this line
- start OK if found this line
diff --git a/src/nvim/testdir/test25.in b/src/nvim/testdir/test25.in
deleted file mode 100644
index 4139865daf..0000000000
--- a/src/nvim/testdir/test25.in
+++ /dev/null
@@ -1,31 +0,0 @@
-Test for jumping to a tag with 'hidden' set, with symbolic link in path of tag.
-This only works for Unix, because of the symbolic link.
-
-STARTTEST
-:so small.vim
-:set hidden
-:" Create a link from test25.dir to the current directory.
-:!rm -f test25.dir
-:!ln -s . test25.dir
-:" Create tags.text, with the current directory name inserted.
-/tags line
-:r !pwd
-d$/test
-hP:.w! tags.test
-:" Try jumping to a tag in the current file, but with a path that contains a
-:" symbolic link. When wrong, this will give the ATTENTION message. The next
-:" space will then be eaten by hit-return, instead of moving the cursor to 'd'.
-:set tags=tags.test
-G x:.w! test.out
-:!rm -f test25.dir tags.test
-:qa!
-ENDTEST
-
-tags line:
-SECTION_OFF /test25.dir/test25.in /^#define SECTION_OFF 3$/
-
-/*tx.c*/
-#define SECTION_OFF 3
-#define NUM_SECTIONS 3
-
-SECTION_OFF
diff --git a/src/nvim/testdir/test25.ok b/src/nvim/testdir/test25.ok
deleted file mode 100644
index 08fc070b7b..0000000000
--- a/src/nvim/testdir/test25.ok
+++ /dev/null
@@ -1 +0,0 @@
-#efine SECTION_OFF 3
diff --git a/src/nvim/testdir/test26.in b/src/nvim/testdir/test26.in
deleted file mode 100644
index e7cd757661..0000000000
--- a/src/nvim/testdir/test26.in
+++ /dev/null
@@ -1,44 +0,0 @@
-Test for :execute, :while and :if
-
-STARTTEST
-:so small.vim
-mt:let i = 0
-:while i < 12
-: let i = i + 1
-: if has("ebcdic")
-: execute "normal o" . i . "\047"
-: else
-: execute "normal o" . i . "\033"
-: endif
-: if i % 2
-: normal Ax
-: if i == 9
-: break
-: endif
-: if i == 5
-: continue
-: else
-: let j = 9
-: while j > 0
-: if has("ebcdic")
-: execute "normal" j . "a" . j . "\x27"
-: else
-: execute "normal" j . "a" . j . "\x1b"
-: endif
-: let j = j - 1
-: endwhile
-: endif
-: endif
-: if i == 9
-: if has("ebcdic")
-: execute "normal Az\047"
-: else
-: execute "normal Az\033"
-: endif
-: endif
-:endwhile
-:unlet i j
-:'t,$w! test.out
-:qa!
-ENDTEST
-
diff --git a/src/nvim/testdir/test26.ok b/src/nvim/testdir/test26.ok
deleted file mode 100644
index bc44761187..0000000000
--- a/src/nvim/testdir/test26.ok
+++ /dev/null
@@ -1,10 +0,0 @@
-
-1x999999999888888887777777666666555554444333221
-2
-3x999999999888888887777777666666555554444333221
-4
-5x
-6
-7x999999999888888887777777666666555554444333221
-8
-9x
diff --git a/src/nvim/testdir/test33.in b/src/nvim/testdir/test33.in
deleted file mode 100644
index 5644760402..0000000000
--- a/src/nvim/testdir/test33.in
+++ /dev/null
@@ -1,34 +0,0 @@
-Test for 'lisp'
-If the lisp feature is not enabled, this will fail!
-
-STARTTEST
-:so small.vim
-:set lisp
-/^(defun
-=G:/^(defun/,$w! test.out
-:q!
-ENDTEST
-
-(defun html-file (base)
-(format nil "~(~A~).html" base))
-
-(defmacro page (name title &rest body)
-(let ((ti (gensym)))
-`(with-open-file (*standard-output*
-(html-file ,name)
-:direction :output
-:if-exists :supersede)
-(let ((,ti ,title))
-(as title ,ti)
-(with center
-(as h2 (string-upcase ,ti)))
-(brs 3)
-,@body))))
-
-;;; Utilities for generating links
-
-(defmacro with-link (dest &rest body)
-`(progn
-(format t "<a href=\"~A\">" (html-file ,dest))
-,@body
-(princ "</a>")))
diff --git a/src/nvim/testdir/test33.ok b/src/nvim/testdir/test33.ok
deleted file mode 100644
index cd1d87a14b..0000000000
--- a/src/nvim/testdir/test33.ok
+++ /dev/null
@@ -1,23 +0,0 @@
-(defun html-file (base)
- (format nil "~(~A~).html" base))
-
-(defmacro page (name title &rest body)
- (let ((ti (gensym)))
- `(with-open-file (*standard-output*
- (html-file ,name)
- :direction :output
- :if-exists :supersede)
- (let ((,ti ,title))
- (as title ,ti)
- (with center
- (as h2 (string-upcase ,ti)))
- (brs 3)
- ,@body))))
-
-;;; Utilities for generating links
-
-(defmacro with-link (dest &rest body)
- `(progn
- (format t "<a href=\"~A\">" (html-file ,dest))
- ,@body
- (princ "</a>")))
diff --git a/src/nvim/testdir/test43.in b/src/nvim/testdir/test43.in
deleted file mode 100644
index 7c545073da..0000000000
--- a/src/nvim/testdir/test43.in
+++ /dev/null
@@ -1,34 +0,0 @@
-Tests for regexp with various magic settings.
-
-STARTTEST
-:so small.vim
-:set nocompatible viminfo+=nviminfo
-/^1
-/a*b\{2}c\+/e
-x/\Md\*e\{2}f\+/e
-x:set nomagic
-/g\*h\{2}i\+/e
-x/\mj*k\{2}l\+/e
-x/\vm*n{2}o+/e
-x/\V^aa$
-x:set magic
-/\v(a)(b)\2\1\1/e
-x/\V[ab]\(\[xy]\)\1
-x:$
-:set undolevels=100
-dv?bar?
-Yup:"
-:?^1?,$w! test.out
-:qa!
-ENDTEST
-
-1 a aa abb abbccc
-2 d dd dee deefff
-3 g gg ghh ghhiii
-4 j jj jkk jkklll
-5 m mm mnn mnnooo
-6 x ^aa$ x
-7 (a)(b) abbaa
-8 axx [ab]xx
-9 foobar
-
diff --git a/src/nvim/testdir/test43.ok b/src/nvim/testdir/test43.ok
deleted file mode 100644
index 0b37a6a61e..0000000000
--- a/src/nvim/testdir/test43.ok
+++ /dev/null
@@ -1,11 +0,0 @@
-1 a aa abb abbcc
-2 d dd dee deeff
-3 g gg ghh ghhii
-4 j jj jkk jkkll
-5 m mm mnn mnnoo
-6 x aa$ x
-7 (a)(b) abba
-8 axx ab]xx
-9 foobar
-9 foo
-
diff --git a/src/nvim/testdir/test5.in b/src/nvim/testdir/test5.in
deleted file mode 100644
index e19e20d59b..0000000000
--- a/src/nvim/testdir/test5.in
+++ /dev/null
@@ -1,29 +0,0 @@
-Test for autocommand that deletes the current buffer on BufLeave event.
-Also test deleting the last buffer, should give a new, empty buffer.
-
-STARTTEST
-:so small.vim
-:au BufLeave Xxx bwipe
-/start of
-:.,/end of/w! Xxx " write test file Xxx
-:sp Xxx " split to Xxx
-:bwipe " delete buffer Xxx, now we're back here
-G?this is a
-othis is some more text
-: " Append some text to this file
-:?start?,$w! test.out " Write current file contents
-:bwipe test.out " delete alternate buffer
-:au bufleave test5.in bwipe
-:bwipe! " delete current buffer, get an empty one
-ithis is another test line:w >>test.out
-: " append an extra line to the output file
-:qa!
-ENDTEST
-
-start of test file Xxx
-vim: set noai :
- this is a test
- this is a test
- this is a test
- this is a test
-end of test file Xxx
diff --git a/src/nvim/testdir/test5.ok b/src/nvim/testdir/test5.ok
deleted file mode 100644
index 6743060794..0000000000
--- a/src/nvim/testdir/test5.ok
+++ /dev/null
@@ -1,9 +0,0 @@
-start of test file Xxx
-vim: set noai :
- this is a test
- this is a test
- this is a test
- this is a test
-this is some more text
-end of test file Xxx
-this is another test line
diff --git a/src/nvim/testdir/test51.in b/src/nvim/testdir/test51.in
deleted file mode 100644
index b4f45d1f75..0000000000
--- a/src/nvim/testdir/test51.in
+++ /dev/null
@@ -1,36 +0,0 @@
-Tests for ":highlight". vim: set ft=vim :
-
-STARTTEST
-:so small.vim
-:" basic test if ":highlight" doesn't crash
-:highlight
-:hi Search
-:" test setting colors.
-:" test clearing one color and all doesn't generate error or warning
-:hi NewGroup term=bold cterm=italic ctermfg=DarkBlue ctermbg=Grey gui= guifg=#00ff00 guibg=Cyan
-:hi Group2 term= cterm=
-:hi Group3 term=underline cterm=bold
-:redir! >test.out
-:hi NewGroup
-:hi Group2
-:hi Group3
-:hi clear NewGroup
-:hi NewGroup
-:hi Group2
-:hi Group2 NONE
-:hi Group2
-:hi clear
-:hi Group3
-:hi Crash term='asdf
-:redir END
-:" filter ctermfg and ctermbg, the numbers depend on the terminal
-:e test.out
-:%s/ctermfg=\d*/ctermfg=2/
-:%s/ctermbg=\d*/ctermbg=3/
-:" filter out possibly translated error message
-:%s/E475: [^:]*:/E475:/
-:" fix the fileformat
-:set ff&
-:wq!
-ENDTEST
-
diff --git a/src/nvim/testdir/test51.ok b/src/nvim/testdir/test51.ok
deleted file mode 100644
index be9ff7862c..0000000000
--- a/src/nvim/testdir/test51.ok
+++ /dev/null
@@ -1,20 +0,0 @@
-
-
-NewGroup xxx term=bold cterm=italic ctermfg=2 ctermbg=3
-
-Group2 xxx cleared
-
-Group3 xxx term=underline cterm=bold
-
-
-NewGroup xxx cleared
-
-Group2 xxx cleared
-
-
-Group2 xxx cleared
-
-
-Group3 xxx cleared
-
-E475: term='asdf
diff --git a/src/nvim/testdir/test66.in b/src/nvim/testdir/test66.in
deleted file mode 100644
index f1fdce3792..0000000000
--- a/src/nvim/testdir/test66.in
+++ /dev/null
@@ -1,33 +0,0 @@
-
-Test for visual block shift and tab characters.
-
-STARTTEST
-:so small.vim
-/^one
-fe4jRugvr1:'<,'>w! test.out
-/^abcdefgh
-4jI j<<11|D
-7|a 
-7|a 
-7|a 4k13|4j<
-:$-5,$w >> test.out
-:$-4,$s/\s\+//g
-4kI j<<
-7|a 
-7|a 
-7|a 4k13|4j3<
-:$-4,$w >> test.out
-:qa!
-ENDTEST
-
-one two three
-one two three
-one two three
-one two three
-one two three
-
-abcdefghijklmnopqrstuvwxyz
-abcdefghijklmnopqrstuvwxyz
-abcdefghijklmnopqrstuvwxyz
-abcdefghijklmnopqrstuvwxyz
-abcdefghijklmnopqrstuvwxyz
diff --git a/src/nvim/testdir/test66.ok b/src/nvim/testdir/test66.ok
deleted file mode 100644
index 4c3ab0fb56..0000000000
--- a/src/nvim/testdir/test66.ok
+++ /dev/null
@@ -1,16 +0,0 @@
-on1 two three
-on1 two three
-on1 two three
-on1 two three
-on1 two three
-
- abcdefghijklmnopqrstuvwxyz
-abcdefghij
- abc defghijklmnopqrstuvwxyz
- abc defghijklmnopqrstuvwxyz
- abc defghijklmnopqrstuvwxyz
- abcdefghijklmnopqrstuvwxyz
-abcdefghij
- abc defghijklmnopqrstuvwxyz
- abc defghijklmnopqrstuvwxyz
- abc defghijklmnopqrstuvwxyz
diff --git a/src/nvim/testdir/test67.in b/src/nvim/testdir/test67.in
deleted file mode 100644
index 08b4e3701f..0000000000
--- a/src/nvim/testdir/test67.in
+++ /dev/null
@@ -1,33 +0,0 @@
-Test that groups and patterns are tested correctly when calling exists() for
-autocommands.
-
-STARTTEST
-:so small.vim
-:let results=[]
-:augroup auexists
-:augroup END
-:call add(results, "##BufEnter: " . exists("##BufEnter"))
-:call add(results, "#BufEnter: " . exists("#BufEnter"))
-:au BufEnter * let g:entered=1
-:call add(results, "#BufEnter: " . exists("#BufEnter"))
-:call add(results, "#auexists#BufEnter: " . exists("#auexists#BufEnter"))
-:augroup auexists
-:au BufEnter * let g:entered=1
-:augroup END
-:call add(results, "#auexists#BufEnter: " . exists("#auexists#BufEnter"))
-:call add(results, "#BufEnter#*.test: " . exists("#BufEnter#*.test"))
-:au BufEnter *.test let g:entered=1
-:call add(results, "#BufEnter#*.test: " . exists("#BufEnter#*.test"))
-:edit testfile.test
-:call add(results, "#BufEnter#<buffer>: " . exists("#BufEnter#<buffer>"))
-:au BufEnter <buffer> let g:entered=1
-:call add(results, "#BufEnter#<buffer>: " . exists("#BufEnter#<buffer>"))
-:edit testfile2.test
-:call add(results, "#BufEnter#<buffer>: " . exists("#BufEnter#<buffer>"))
-:e test.out
-:call append(0, results)
-:$d
-:w
-:qa!
-ENDTEST
-
diff --git a/src/nvim/testdir/test67.ok b/src/nvim/testdir/test67.ok
deleted file mode 100644
index 51188e5afd..0000000000
--- a/src/nvim/testdir/test67.ok
+++ /dev/null
@@ -1,10 +0,0 @@
-##BufEnter: 1
-#BufEnter: 0
-#BufEnter: 1
-#auexists#BufEnter: 0
-#auexists#BufEnter: 1
-#BufEnter#*.test: 0
-#BufEnter#*.test: 1
-#BufEnter#<buffer>: 0
-#BufEnter#<buffer>: 1
-#BufEnter#<buffer>: 0
diff --git a/src/nvim/testdir/test75.in b/src/nvim/testdir/test75.in
deleted file mode 100644
index 8fabccdf52..0000000000
--- a/src/nvim/testdir/test75.in
+++ /dev/null
@@ -1,41 +0,0 @@
-Tests for maparg().
-Also test utf8 map with a 0x80 byte.
-
-STARTTEST
-:so small.vim
-:so mbyte.vim
-:set cpo-=<
-:set encoding=utf8
-:" Test maparg() with a string result
-:map foo<C-V> is<F4>foo
-:vnoremap <script> <buffer> <expr> <silent> bar isbar
-:call append('$', maparg('foo<C-V>'))
-:call append('$', string(maparg('foo<C-V>', '', 0, 1)))
-:call append('$', string(maparg('bar', '', 0, 1)))
-:map <buffer> <nowait> foo bar
-:call append('$', string(maparg('foo', '', 0, 1)))
-:"
-:map abc x<char-114>x
-:call append('$', maparg('abc'))
-:map abc y<S-char-114>y
-:call append('$', maparg('abc'))
-:"
-Go:"
-:" Outside of the range, minimum
-:inoremap <Char-0x1040> a
-:execute "normal a\u1040\<Esc>"
-:" Inside of the range, minimum
-:inoremap <Char-0x103f> b
-:execute "normal a\u103f\<Esc>"
-:" Inside of the range, maximum
-:inoremap <Char-0xf03f> c
-:execute "normal a\uf03f\<Esc>"
-:" Outside of the range, maximum
-:inoremap <Char-0xf040> d
-:execute "normal a\uf040\<Esc>"
-:"
-:/^eof/+1,$w! test.out
-:qa!
-ENDTEST
-
-eof
diff --git a/src/nvim/testdir/test75.ok b/src/nvim/testdir/test75.ok
deleted file mode 100644
index a2c5c5ac3d..0000000000
--- a/src/nvim/testdir/test75.ok
+++ /dev/null
@@ -1,7 +0,0 @@
-is<F4>foo
-{'silent': 0, 'noremap': 0, 'lhs': 'foo<C-V>', 'mode': ' ', 'nowait': 0, 'expr': 0, 'sid': 0, 'rhs': 'is<F4>foo', 'buffer': 0}
-{'silent': 1, 'noremap': 1, 'lhs': 'bar', 'mode': 'v', 'nowait': 0, 'expr': 1, 'sid': 0, 'rhs': 'isbar', 'buffer': 1}
-{'silent': 0, 'noremap': 0, 'lhs': 'foo', 'mode': ' ', 'nowait': 1, 'expr': 0, 'sid': 0, 'rhs': 'bar', 'buffer': 1}
-xrx
-yRy
-abcd
diff --git a/src/nvim/ui.c b/src/nvim/ui.c
index d6269897d7..526cc3e47e 100644
--- a/src/nvim/ui.c
+++ b/src/nvim/ui.c
@@ -44,7 +44,6 @@
void ui_write(char_u *s, int len)
{
-#ifndef NO_CONSOLE
/* Don't output anything in silent mode ("ex -s") unless 'verbose' set */
if (!(silent_mode && p_verbose == 0)) {
char_u *tofree = NULL;
@@ -61,112 +60,6 @@ void ui_write(char_u *s, int len)
if (output_conv.vc_type != CONV_NONE)
free(tofree);
}
-#endif
-}
-
-/*
- * ui_inchar(): low level input function.
- * Get characters from the keyboard.
- * Return the number of characters that are available.
- * If "wtime" == 0 do not wait for characters.
- * If "wtime" == -1 wait forever for characters.
- * If "wtime" > 0 wait "wtime" milliseconds for a character.
- *
- * "tb_change_cnt" is the value of typebuf.tb_change_cnt if "buf" points into
- * it. When typebuf.tb_change_cnt changes (e.g., when a message is received
- * from a remote client) "buf" can no longer be used. "tb_change_cnt" is NULL
- * otherwise.
- */
-int
-ui_inchar (
- char_u *buf,
- int maxlen,
- long wtime, /* don't use "time", MIPS cannot handle it */
- int tb_change_cnt
-)
-{
- int retval = 0;
-
-
- if (do_profiling == PROF_YES && wtime != 0)
- prof_inchar_enter();
-
-#ifdef NO_CONSOLE_INPUT
- /* Don't wait for character input when the window hasn't been opened yet.
- * Do try reading, this works when redirecting stdin from a file.
- * Must return something, otherwise we'll loop forever. If we run into
- * this very often we probably got stuck, exit Vim. */
- if (no_console_input()) {
- static int count = 0;
-
-# ifndef NO_CONSOLE
- retval = os_inchar(buf, maxlen, (wtime >= 0 && wtime < 10)
- ? 10L : wtime, tb_change_cnt);
- if (retval > 0 || typebuf_changed(tb_change_cnt) || wtime >= 0)
- goto theend;
-# endif
- if (wtime == -1 && ++count == 1000)
- read_error_exit();
- buf[0] = CAR;
- retval = 1;
- goto theend;
- }
-#endif
-
- /* If we are going to wait for some time or block... */
- if (wtime == -1 || wtime > 100L) {
- /* ... allow signals to kill us. */
- signal_accept_deadly();
-
- /* ... there is no need for CTRL-C to interrupt something, don't let
- * it set got_int when it was mapped. */
- if (mapped_ctrl_c)
- ctrl_c_interrupts = false;
- }
-
-#ifndef NO_CONSOLE
- {
- retval = os_inchar(buf, maxlen, wtime, tb_change_cnt);
- }
-#endif
-
- if (wtime == -1 || wtime > 100L)
- /* block SIGHUP et al. */
- signal_reject_deadly();
-
- ctrl_c_interrupts = true;
-
-#ifdef NO_CONSOLE_INPUT
-theend:
-#endif
- if (do_profiling == PROF_YES && wtime != 0)
- prof_inchar_exit();
- return retval;
-}
-
-/*
- * return non-zero if a character is available
- */
-int ui_char_avail(void)
-{
-#ifndef NO_CONSOLE
-# ifdef NO_CONSOLE_INPUT
- if (no_console_input())
- return 0;
-# endif
- return os_char_avail();
-#else
- return 0;
-#endif
-}
-
-/*
- * Delay for the given number of milliseconds. If ignoreinput is FALSE then we
- * cancel the delay if a key is hit.
- */
-void ui_delay(long msec, bool ignoreinput)
-{
- os_delay(msec, ignoreinput);
}
/*
@@ -201,516 +94,11 @@ int ui_get_shellsize(void)
}
/*
- * Set the size of the Vim shell according to Rows and Columns, if possible.
- * The gui_set_shellsize() or mch_set_shellsize() function will try to set the
- * new size. If this is not possible, it will adjust Rows and Columns.
- */
-void
-ui_set_shellsize(int mustset)
-{
- mch_set_shellsize();
-}
-
-void ui_breakcheck(void)
-{
- os_breakcheck();
-}
-
-/*****************************************************************************
- * Functions for copying and pasting text between applications.
- * This is always included in a GUI version, but may also be included when the
- * clipboard and mouse is available to a terminal version such as xterm.
- * Note: there are some more functions in ops.c that handle selection stuff.
- *
- * Also note that the majority of functions here deal with the X 'primary'
- * (visible - for Visual mode use) selection, and only that. There are no
- * versions of these for the 'clipboard' selection, as Visual mode has no use
- * for them.
- */
-
-/*
- * Exit because of an input read error.
- */
-void read_error_exit(void)
-{
- if (silent_mode) /* Normal way to exit for "ex -s" */
- getout(0);
- STRCPY(IObuff, _("Vim: Error reading input, exiting...\n"));
- preserve_exit();
-}
-
-/*
* May update the shape of the cursor.
*/
void ui_cursor_shape(void)
{
term_cursor_shape();
-
-
conceal_check_cursur_line();
}
-/*
- * Check bounds for column number
- */
-int check_col(int col)
-{
- if (col < 0)
- return 0;
- if (col >= (int)screen_Columns)
- return (int)screen_Columns - 1;
- return col;
-}
-
-/*
- * Check bounds for row number
- */
-int check_row(int row)
-{
- if (row < 0)
- return 0;
- if (row >= (int)screen_Rows)
- return (int)screen_Rows - 1;
- return row;
-}
-
-/*
- * Stuff for the X clipboard. Shared between VMS and Unix.
- */
-
-/*
- * Move the cursor to the specified row and column on the screen.
- * Change current window if necessary. Returns an integer with the
- * CURSOR_MOVED bit set if the cursor has moved or unset otherwise.
- *
- * The MOUSE_FOLD_CLOSE bit is set when clicked on the '-' in a fold column.
- * The MOUSE_FOLD_OPEN bit is set when clicked on the '+' in a fold column.
- *
- * If flags has MOUSE_FOCUS, then the current window will not be changed, and
- * if the mouse is outside the window then the text will scroll, or if the
- * mouse was previously on a status line, then the status line may be dragged.
- *
- * If flags has MOUSE_MAY_VIS, then VIsual mode will be started before the
- * cursor is moved unless the cursor was on a status line.
- * This function returns one of IN_UNKNOWN, IN_BUFFER, IN_STATUS_LINE or
- * IN_SEP_LINE depending on where the cursor was clicked.
- *
- * If flags has MOUSE_MAY_STOP_VIS, then Visual mode will be stopped, unless
- * the mouse is on the status line of the same window.
- *
- * If flags has MOUSE_DID_MOVE, nothing is done if the mouse didn't move since
- * the last call.
- *
- * If flags has MOUSE_SETPOS, nothing is done, only the current position is
- * remembered.
- */
-int
-jump_to_mouse (
- int flags,
- bool *inclusive, /* used for inclusive operator, can be NULL */
- int which_button /* MOUSE_LEFT, MOUSE_RIGHT, MOUSE_MIDDLE */
-)
-{
- static int on_status_line = 0; /* #lines below bottom of window */
- static int on_sep_line = 0; /* on separator right of window */
- static int prev_row = -1;
- static int prev_col = -1;
- static win_T *dragwin = NULL; /* window being dragged */
- static int did_drag = FALSE; /* drag was noticed */
-
- win_T *wp, *old_curwin;
- pos_T old_cursor;
- int count;
- bool first;
- int row = mouse_row;
- int col = mouse_col;
- int mouse_char;
-
- mouse_past_bottom = false;
- mouse_past_eol = false;
-
- if (flags & MOUSE_RELEASED) {
- /* On button release we may change window focus if positioned on a
- * status line and no dragging happened. */
- if (dragwin != NULL && !did_drag)
- flags &= ~(MOUSE_FOCUS | MOUSE_DID_MOVE);
- dragwin = NULL;
- did_drag = FALSE;
- }
-
- if ((flags & MOUSE_DID_MOVE)
- && prev_row == mouse_row
- && prev_col == mouse_col) {
-retnomove:
- /* before moving the cursor for a left click which is NOT in a status
- * line, stop Visual mode */
- if (on_status_line)
- return IN_STATUS_LINE;
- if (on_sep_line)
- return IN_SEP_LINE;
- if (flags & MOUSE_MAY_STOP_VIS) {
- end_visual_mode();
- redraw_curbuf_later(INVERTED); /* delete the inversion */
- }
- return IN_BUFFER;
- }
-
- prev_row = mouse_row;
- prev_col = mouse_col;
-
- if (flags & MOUSE_SETPOS)
- goto retnomove; /* ugly goto... */
-
- /* Remember the character under the mouse, it might be a '-' or '+' in the
- * fold column. */
- if (row >= 0 && row < Rows && col >= 0 && col <= Columns
- && ScreenLines != NULL)
- mouse_char = ScreenLines[LineOffset[row] + col];
- else
- mouse_char = ' ';
-
- old_curwin = curwin;
- old_cursor = curwin->w_cursor;
-
- if (!(flags & MOUSE_FOCUS)) {
- if (row < 0 || col < 0) /* check if it makes sense */
- return IN_UNKNOWN;
-
- /* find the window where the row is in */
- wp = mouse_find_win(&row, &col);
- dragwin = NULL;
- /*
- * winpos and height may change in win_enter()!
- */
- if (row >= wp->w_height) { /* In (or below) status line */
- on_status_line = row - wp->w_height + 1;
- dragwin = wp;
- } else
- on_status_line = 0;
- if (col >= wp->w_width) { /* In separator line */
- on_sep_line = col - wp->w_width + 1;
- dragwin = wp;
- } else
- on_sep_line = 0;
-
- /* The rightmost character of the status line might be a vertical
- * separator character if there is no connecting window to the right. */
- if (on_status_line && on_sep_line) {
- if (stl_connected(wp))
- on_sep_line = 0;
- else
- on_status_line = 0;
- }
-
- /* Before jumping to another buffer, or moving the cursor for a left
- * click, stop Visual mode. */
- if (VIsual_active
- && (wp->w_buffer != curwin->w_buffer
- || (!on_status_line
- && !on_sep_line
- && (
- wp->w_p_rl ? col < wp->w_width - wp->w_p_fdc :
- col >= wp->w_p_fdc
- + (cmdwin_type == 0 && wp ==
- curwin ? 0 : 1)
- )
- && (flags & MOUSE_MAY_STOP_VIS)))) {
- end_visual_mode();
- redraw_curbuf_later(INVERTED); /* delete the inversion */
- }
- if (cmdwin_type != 0 && wp != curwin) {
- /* A click outside the command-line window: Use modeless
- * selection if possible. Allow dragging the status lines. */
- on_sep_line = 0;
- row = 0;
- col += wp->w_wincol;
- wp = curwin;
- }
- /* Only change window focus when not clicking on or dragging the
- * status line. Do change focus when releasing the mouse button
- * (MOUSE_FOCUS was set above if we dragged first). */
- if (dragwin == NULL || (flags & MOUSE_RELEASED))
- win_enter(wp, true); /* can make wp invalid! */
-# ifdef CHECK_DOUBLE_CLICK
- /* set topline, to be able to check for double click ourselves */
- if (curwin != old_curwin)
- set_mouse_topline(curwin);
-# endif
- if (on_status_line) { /* In (or below) status line */
- /* Don't use start_arrow() if we're in the same window */
- if (curwin == old_curwin)
- return IN_STATUS_LINE;
- else
- return IN_STATUS_LINE | CURSOR_MOVED;
- }
- if (on_sep_line) { /* In (or below) status line */
- /* Don't use start_arrow() if we're in the same window */
- if (curwin == old_curwin)
- return IN_SEP_LINE;
- else
- return IN_SEP_LINE | CURSOR_MOVED;
- }
-
- curwin->w_cursor.lnum = curwin->w_topline;
- } else if (on_status_line && which_button == MOUSE_LEFT) {
- if (dragwin != NULL) {
- /* Drag the status line */
- count = row - dragwin->w_winrow - dragwin->w_height + 1
- - on_status_line;
- win_drag_status_line(dragwin, count);
- did_drag |= count;
- }
- return IN_STATUS_LINE; /* Cursor didn't move */
- } else if (on_sep_line && which_button == MOUSE_LEFT) {
- if (dragwin != NULL) {
- /* Drag the separator column */
- count = col - dragwin->w_wincol - dragwin->w_width + 1
- - on_sep_line;
- win_drag_vsep_line(dragwin, count);
- did_drag |= count;
- }
- return IN_SEP_LINE; /* Cursor didn't move */
- } else { /* keep_window_focus must be TRUE */
- /* before moving the cursor for a left click, stop Visual mode */
- if (flags & MOUSE_MAY_STOP_VIS) {
- end_visual_mode();
- redraw_curbuf_later(INVERTED); /* delete the inversion */
- }
-
-
- row -= curwin->w_winrow;
- col -= curwin->w_wincol;
-
- /*
- * When clicking beyond the end of the window, scroll the screen.
- * Scroll by however many rows outside the window we are.
- */
- if (row < 0) {
- count = 0;
- for (first = true; curwin->w_topline > 1; ) {
- if (curwin->w_topfill < diff_check(curwin, curwin->w_topline))
- ++count;
- else
- count += plines(curwin->w_topline - 1);
- if (!first && count > -row)
- break;
- first = false;
- hasFolding(curwin->w_topline, &curwin->w_topline, NULL);
- if (curwin->w_topfill < diff_check(curwin, curwin->w_topline))
- ++curwin->w_topfill;
- else {
- --curwin->w_topline;
- curwin->w_topfill = 0;
- }
- }
- check_topfill(curwin, false);
- curwin->w_valid &=
- ~(VALID_WROW|VALID_CROW|VALID_BOTLINE|VALID_BOTLINE_AP);
- redraw_later(VALID);
- row = 0;
- } else if (row >= curwin->w_height) {
- count = 0;
- for (first = true; curwin->w_topline < curbuf->b_ml.ml_line_count; ) {
- if (curwin->w_topfill > 0)
- ++count;
- else
- count += plines(curwin->w_topline);
- if (!first && count > row - curwin->w_height + 1)
- break;
- first = false;
- if (hasFolding(curwin->w_topline, NULL, &curwin->w_topline)
- && curwin->w_topline == curbuf->b_ml.ml_line_count)
- break;
- if (curwin->w_topfill > 0)
- --curwin->w_topfill;
- else {
- ++curwin->w_topline;
- curwin->w_topfill =
- diff_check_fill(curwin, curwin->w_topline);
- }
- }
- check_topfill(curwin, false);
- redraw_later(VALID);
- curwin->w_valid &=
- ~(VALID_WROW|VALID_CROW|VALID_BOTLINE|VALID_BOTLINE_AP);
- row = curwin->w_height - 1;
- } else if (row == 0) {
- /* When dragging the mouse, while the text has been scrolled up as
- * far as it goes, moving the mouse in the top line should scroll
- * the text down (done later when recomputing w_topline). */
- if (mouse_dragging > 0
- && curwin->w_cursor.lnum
- == curwin->w_buffer->b_ml.ml_line_count
- && curwin->w_cursor.lnum == curwin->w_topline)
- curwin->w_valid &= ~(VALID_TOPLINE);
- }
- }
-
- /* Check for position outside of the fold column. */
- if (
- curwin->w_p_rl ? col < curwin->w_width - curwin->w_p_fdc :
- col >= curwin->w_p_fdc
- + (cmdwin_type == 0 ? 0 : 1)
- )
- mouse_char = ' ';
-
- /* compute the position in the buffer line from the posn on the screen */
- if (mouse_comp_pos(curwin, &row, &col, &curwin->w_cursor.lnum))
- mouse_past_bottom = true;
-
- /* Start Visual mode before coladvance(), for when 'sel' != "old" */
- if ((flags & MOUSE_MAY_VIS) && !VIsual_active) {
- check_visual_highlight();
- VIsual = old_cursor;
- VIsual_active = TRUE;
- VIsual_reselect = TRUE;
- /* if 'selectmode' contains "mouse", start Select mode */
- may_start_select('o');
- setmouse();
- if (p_smd && msg_silent == 0)
- redraw_cmdline = TRUE; /* show visual mode later */
- }
-
- curwin->w_curswant = col;
- curwin->w_set_curswant = FALSE; /* May still have been TRUE */
- if (coladvance(col) == FAIL) { /* Mouse click beyond end of line */
- if (inclusive != NULL)
- *inclusive = true;
- mouse_past_eol = true;
- } else if (inclusive != NULL)
- *inclusive = false;
-
- count = IN_BUFFER;
- if (curwin != old_curwin || curwin->w_cursor.lnum != old_cursor.lnum
- || curwin->w_cursor.col != old_cursor.col)
- count |= CURSOR_MOVED; /* Cursor has moved */
-
- if (mouse_char == '+')
- count |= MOUSE_FOLD_OPEN;
- else if (mouse_char != ' ')
- count |= MOUSE_FOLD_CLOSE;
-
- return count;
-}
-
-/*
- * Compute the position in the buffer line from the posn on the screen in
- * window "win".
- * Returns TRUE if the position is below the last line.
- */
-bool mouse_comp_pos(win_T *win, int *rowp, int *colp, linenr_T *lnump)
-{
- int col = *colp;
- int row = *rowp;
- linenr_T lnum;
- bool retval = false;
- int off;
- int count;
-
- if (win->w_p_rl)
- col = win->w_width - 1 - col;
-
- lnum = win->w_topline;
-
- while (row > 0) {
- /* Don't include filler lines in "count" */
- if (win->w_p_diff
- && !hasFoldingWin(win, lnum, NULL, NULL, TRUE, NULL)
- ) {
- if (lnum == win->w_topline)
- row -= win->w_topfill;
- else
- row -= diff_check_fill(win, lnum);
- count = plines_win_nofill(win, lnum, TRUE);
- } else
- count = plines_win(win, lnum, TRUE);
- if (count > row)
- break; /* Position is in this buffer line. */
- (void)hasFoldingWin(win, lnum, NULL, &lnum, TRUE, NULL);
- if (lnum == win->w_buffer->b_ml.ml_line_count) {
- retval = true;
- break; /* past end of file */
- }
- row -= count;
- ++lnum;
- }
-
- if (!retval) {
- /* Compute the column without wrapping. */
- off = win_col_off(win) - win_col_off2(win);
- if (col < off)
- col = off;
- col += row * (win->w_width - off);
- /* add skip column (for long wrapping line) */
- col += win->w_skipcol;
- }
-
- if (!win->w_p_wrap)
- col += win->w_leftcol;
-
- /* skip line number and fold column in front of the line */
- col -= win_col_off(win);
- if (col < 0) {
- col = 0;
- }
-
- *colp = col;
- *rowp = row;
- *lnump = lnum;
- return retval;
-}
-
-/*
- * Find the window at screen position "*rowp" and "*colp". The positions are
- * updated to become relative to the top-left of the window.
- */
-win_T *mouse_find_win(int *rowp, int *colp)
-{
- frame_T *fp;
-
- fp = topframe;
- *rowp -= firstwin->w_winrow;
- for (;; ) {
- if (fp->fr_layout == FR_LEAF)
- break;
- if (fp->fr_layout == FR_ROW) {
- for (fp = fp->fr_child; fp->fr_next != NULL; fp = fp->fr_next) {
- if (*colp < fp->fr_width)
- break;
- *colp -= fp->fr_width;
- }
- } else { /* fr_layout == FR_COL */
- for (fp = fp->fr_child; fp->fr_next != NULL; fp = fp->fr_next) {
- if (*rowp < fp->fr_height)
- break;
- *rowp -= fp->fr_height;
- }
- }
- }
- return fp->fr_win;
-}
-
-#if defined(USE_IM_CONTROL) || defined(PROTO)
-/*
- * Save current Input Method status to specified place.
- */
-void im_save_status(long *psave)
-{
- /* Don't save when 'imdisable' is set or "xic" is NULL, IM is always
- * disabled then (but might start later).
- * Also don't save when inside a mapping, vgetc_im_active has not been set
- * then.
- * And don't save when the keys were stuffed (e.g., for a "." command).
- * And don't save when the GUI is running but our window doesn't have
- * input focus (e.g., when a find dialog is open). */
- if (!p_imdisable && KeyTyped && !KeyStuffed
- ) {
- /* Do save when IM is on, or IM is off and saved status is on. */
- if (vgetc_im_active)
- *psave = B_IMODE_IM;
- else if (*psave == B_IMODE_IM)
- *psave = B_IMODE_NONE;
- }
-}
-#endif
-
diff --git a/src/nvim/ui.h b/src/nvim/ui.h
index 2b1543a918..b174af9abe 100644
--- a/src/nvim/ui.h
+++ b/src/nvim/ui.h
@@ -3,27 +3,6 @@
#include <stdbool.h>
-/*
- * jump_to_mouse() returns one of first four these values, possibly with
- * some of the other three added.
- */
-#define IN_UNKNOWN 0
-#define IN_BUFFER 1
-#define IN_STATUS_LINE 2 /* on status or command line */
-#define IN_SEP_LINE 4 /* on vertical separator line */
-#define IN_OTHER_WIN 8 /* in other window but can't go there */
-#define CURSOR_MOVED 0x100
-#define MOUSE_FOLD_CLOSE 0x200 /* clicked on '-' in fold column */
-#define MOUSE_FOLD_OPEN 0x400 /* clicked on '+' in fold column */
-
-/* flags for jump_to_mouse() */
-#define MOUSE_FOCUS 0x01 /* need to stay in this window */
-#define MOUSE_MAY_VIS 0x02 /* may start Visual mode */
-#define MOUSE_DID_MOVE 0x04 /* only act when mouse has moved */
-#define MOUSE_SETPOS 0x08 /* only set current mouse position */
-#define MOUSE_MAY_STOP_VIS 0x10 /* may stop Visual mode */
-#define MOUSE_RELEASED 0x20 /* button was released */
-
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "ui.h.generated.h"
#endif
diff --git a/src/nvim/window.c b/src/nvim/window.c
index 9345d740d1..315d5f07de 100644
--- a/src/nvim/window.c
+++ b/src/nvim/window.c
@@ -1230,7 +1230,6 @@ static void win_rotate(int upwards, int count)
return;
}
-
/* Check if all frames in this row/col have one window. */
for (frp = curwin->w_frame->fr_parent->fr_child; frp != NULL;
frp = frp->fr_next)
@@ -1246,6 +1245,7 @@ static void win_rotate(int upwards, int count)
wp1 = frp->fr_win;
win_remove(wp1, NULL);
frame_remove(frp);
+ assert(frp->fr_parent->fr_child);
/* find last frame and append removed window/frame after it */
for (; frp->fr_next != NULL; frp = frp->fr_next)
@@ -1263,6 +1263,7 @@ static void win_rotate(int upwards, int count)
wp2 = wp1->w_prev; /* will become last window */
win_remove(wp1, NULL);
frame_remove(frp);
+ assert(frp->fr_parent->fr_child);
/* append the removed window/frame before the first in the list */
win_append(frp->fr_parent->fr_child->fr_win->w_prev, wp1);
@@ -2193,6 +2194,7 @@ winframe_remove (
* the frames into this list. */
if (frp2->fr_child == frp)
frp2->fr_child = frp->fr_child;
+ assert(frp->fr_child);
frp->fr_child->fr_prev = frp->fr_prev;
if (frp->fr_prev != NULL)
frp->fr_prev->fr_next = frp->fr_child;
@@ -4502,6 +4504,7 @@ void win_drag_vsep_line(win_T *dragwin, int offset)
room += fr->fr_width - frame_minwidth(fr, NULL);
fr = curfr; /* put fr at window that grows */
}
+ assert(fr);
if (room < offset) /* Not enough room */
offset = room; /* Move as far as we can */
@@ -4973,6 +4976,7 @@ static void last_status_rec(frame_T *fr, int statusline)
*/
int tabline_height(void)
{
+ assert(first_tabpage);
switch (p_stal) {
case 0: return 0;
case 1: return (first_tabpage->tp_next == NULL) ? 0 : 1;
diff --git a/test/functional/api/vim_spec.lua b/test/functional/api/vim_spec.lua
index abf9c9efcd..f34df8cefb 100644
--- a/test/functional/api/vim_spec.lua
+++ b/test/functional/api/vim_spec.lua
@@ -1,6 +1,6 @@
-- Sanity checks for vim_* API calls via msgpack-rpc
local helpers = require('test.functional.helpers')
-local clear, nvim, eq, ok = helpers.clear, helpers.nvim, helpers.eq, helpers.ok
+local clear, nvim, eq, neq, ok = helpers.clear, helpers.nvim, helpers.eq, helpers.neq, helpers.ok
describe('vim_* functions', function()
@@ -106,6 +106,47 @@ describe('vim_* functions', function()
end)
end)
+ describe('replace_termcodes', function()
+ it('escapes K_SPECIAL as K_SPECIAL KS_SPECIAL KE_FILLER', function()
+ eq(helpers.nvim('replace_termcodes', '\x80', true, true, true), '\x80\xfeX')
+ end)
+
+ it('leaves non K_SPECIAL string unchanged', function()
+ eq(helpers.nvim('replace_termcodes', 'abc', true, true, true), 'abc')
+ end)
+
+ it('converts <expressions>', function()
+ eq(helpers.nvim('replace_termcodes', '<Leader>', true, true, true), '\\')
+ end)
+ end)
+
+ describe('feedkeys', function()
+ it('CSI escaping', function()
+ local function on_setup()
+ -- notice the special char(…) \xe2\80\xa6
+ nvim('feedkeys', ':let x1="…"\n', '', true)
+
+ -- Both replace_termcodes and feedkeys escape \x80
+ local inp = helpers.nvim('replace_termcodes', ':let x2="…"<CR>', true, true, true)
+ nvim('feedkeys', inp, '', true)
+
+ -- Disabling CSI escaping in feedkeys
+ inp = helpers.nvim('replace_termcodes', ':let x3="…"<CR>', true, true, true)
+ nvim('feedkeys', inp, '', false)
+
+ helpers.stop()
+ end
+
+ -- spin the loop a bit
+ helpers.run(nil, nil, on_setup)
+
+ eq(nvim('get_var', 'x1'), '…')
+ -- Because of the double escaping this is neq
+ neq(nvim('get_var', 'x2'), '…')
+ eq(nvim('get_var', 'x3'), '…')
+ end)
+ end)
+
it('can throw exceptions', function()
local status, err = pcall(nvim, 'get_option', 'invalid-option')
eq(false, status)
diff --git a/test/functional/api/window_spec.lua b/test/functional/api/window_spec.lua
index 4c867d2f5d..f3ac90de21 100644
--- a/test/functional/api/window_spec.lua
+++ b/test/functional/api/window_spec.lua
@@ -104,7 +104,7 @@ describe('window_* functions', function()
nvim('set_current_window', nvim('get_windows')[2])
nvim('command', 'split')
eq(window('get_height', nvim('get_windows')[2]),
- window('get_height', nvim('get_windows')[1]) / 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]))
end)
@@ -118,7 +118,7 @@ describe('window_* functions', function()
nvim('set_current_window', nvim('get_windows')[2])
nvim('command', 'vsplit')
eq(window('get_width', nvim('get_windows')[2]),
- window('get_width', nvim('get_windows')[1]) / 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]))
end)
diff --git a/src/nvim/testdir/sautest/autoload/Test104.vim b/test/functional/fixtures/autoload/Test104.vim
index d1e0e17a3b..d1e0e17a3b 100644
--- a/src/nvim/testdir/sautest/autoload/Test104.vim
+++ b/test/functional/fixtures/autoload/Test104.vim
diff --git a/test/functional/helpers.lua b/test/functional/helpers.lua
index 6c3f5190c9..b758817b41 100644
--- a/test/functional/helpers.lua
+++ b/test/functional/helpers.lua
@@ -6,23 +6,33 @@ local Session = require('nvim.session')
local nvim_prog = os.getenv('NVIM_PROG') or 'build/bin/nvim'
local nvim_argv = {nvim_prog, '-u', 'NONE', '-i', 'NONE', '-N', '--embed'}
+local prepend_argv
if os.getenv('VALGRIND') then
local log_file = os.getenv('VALGRIND_LOG') or 'valgrind-%p.log'
- local valgrind_argv = {'valgrind', '-q', '--tool=memcheck',
- '--leak-check=yes', '--track-origins=yes',
- '--show-possibly-lost=no',
- '--suppressions=.valgrind.supp',
- '--log-file='..log_file}
- if os.getenv('VALGRIND_GDB') then
- table.insert(valgrind_argv, '--vgdb=yes')
- table.insert(valgrind_argv, '--vgdb-error=0')
+ prepend_argv = {'valgrind', '-q', '--tool=memcheck',
+ '--leak-check=yes', '--track-origins=yes',
+ '--show-possibly-lost=no',
+ '--suppressions=.valgrind.supp',
+ '--log-file='..log_file}
+ if os.getenv('GDB') then
+ table.insert(prepend_argv, '--vgdb=yes')
+ table.insert(prepend_argv, '--vgdb-error=0')
end
- local len = #valgrind_argv
+elseif os.getenv('GDB') then
+ local gdbserver_port = '7777'
+ if os.getenv('GDBSERVER_PORT') then
+ gdbserver_port = os.getenv('GDBSERVER_PORT')
+ end
+ prepend_argv = {'gdbserver', 'localhost:'..gdbserver_port}
+end
+
+if prepend_argv then
+ local len = #prepend_argv
for i = 1, #nvim_argv do
- valgrind_argv[i + len] = nvim_argv[i]
+ prepend_argv[i + len] = nvim_argv[i]
end
- nvim_argv = valgrind_argv
+ nvim_argv = prepend_argv
end
local session, loop_running, loop_stopped, last_error
@@ -42,7 +52,6 @@ local function request(method, ...)
if not loop_stopped then
-- Except when the loop has been stopped by a notification triggered
-- by the initial request, for example.
- session:request('vim_eval', '1')
end
return rv
end
@@ -99,25 +108,20 @@ local function nvim_eval(expr)
return request('vim_eval', expr)
end
-local function nvim_feed(input, mode)
- mode = mode or ''
- request('vim_feedkeys', input, mode)
-end
-
-local function buffer_slice(start, stop, buffer_idx)
- local include_end = false
- if not stop then
- stop = -1
- include_end = true
+local function nvim_feed(input)
+ while #input > 0 do
+ local written = request('vim_input', input)
+ input = input:sub(written + 1)
end
- local buffer = request('vim_get_buffers')[buffer_idx or 1]
- local slice = request('buffer_get_line_slice', buffer, start or 0, stop,
- true, include_end)
- return table.concat(slice, '\n')
end
local function nvim_replace_termcodes(input)
- return request('vim_replace_termcodes', input, false, true, true)
+ -- small hack to stop <C-@> from being replaced by the internal
+ -- representation(which is different and won't work for vim_input)
+ local temp_replacement = 'CCCCCCCCC@@@@@@@@@@'
+ input = input:gsub('<[Cc][-]@>', temp_replacement)
+ local rv = request('vim_replace_termcodes', input, false, true, true)
+ return rv:gsub(temp_replacement, '\000')
end
local function dedent(str)
@@ -150,13 +154,14 @@ end
local function rawfeed(...)
for _, v in ipairs({...}) do
- nvim_feed(dedent(v), 'nt')
+ nvim_feed(dedent(v))
end
end
local function clear()
if session then
session:request('vim_command', 'qa!')
+ session._async_session._msgpack_stream._loop:exit()
end
local loop = Loop.new()
local msgpack_stream = MsgpackStream.new(loop)
@@ -166,22 +171,32 @@ local function clear()
end
local function insert(...)
- nvim_feed('i', 'nt')
+ nvim_feed('i')
rawfeed(...)
- nvim_feed(nvim_replace_termcodes('<ESC>'), 'nt')
+ nvim_feed(nvim_replace_termcodes('<ESC>'))
end
local function execute(...)
for _, v in ipairs({...}) do
if v:sub(1, 1) ~= '/' then
-- not a search command, prefix with colon
- nvim_feed(':', 'nt')
+ nvim_feed(':')
end
- nvim_feed(v, 'nt')
- nvim_feed(nvim_replace_termcodes('<CR>'), 'nt')
+ nvim_feed(v)
+ nvim_feed(nvim_replace_termcodes('<CR>'))
end
end
+local function source(code)
+ local tmpname = os.tmpname()
+ local tmpfile = io.open(tmpname, "w")
+ tmpfile:write(code)
+ tmpfile:flush()
+ tmpfile:close()
+ nvim_command('source '..tmpname)
+ os.remove(tmpname)
+end
+
local function eq(expected, actual)
return assert.are.same(expected, actual)
end
@@ -190,10 +205,6 @@ local function neq(expected, actual)
return assert.are_not.same(expected, actual)
end
-local function expect(contents, first, last, buffer_index)
- return eq(dedent(contents), buffer_slice(first, last, buffer_index))
-end
-
local function ok(expr)
assert.is_true(expr)
end
@@ -223,6 +234,10 @@ local function curbuf(method, ...)
end
local function curbuf_contents()
+ -- Before inspecting the buffer, execute 'vim_eval' to wait until all
+ -- previously sent keys are processed(vim_eval is a deferred function, and
+ -- only processed after all input)
+ session:request('vim_eval', '1')
return table.concat(curbuf('get_line_slice', 0, -1, true, true), '\n')
end
@@ -242,11 +257,16 @@ local function curtab(method, ...)
return tabpage(method, tab, ...)
end
+local function expect(contents)
+ return eq(dedent(contents), curbuf_contents())
+end
+
clear()
return {
clear = clear,
dedent = dedent,
+ source = source,
rawfeed = rawfeed,
insert = insert,
feed = feed,
diff --git a/test/functional/job/job_spec.lua b/test/functional/job/job_spec.lua
index 85a1e92e38..07ca0c0058 100644
--- a/test/functional/job/job_spec.lua
+++ b/test/functional/job/job_spec.lua
@@ -37,7 +37,7 @@ describe('jobs', function()
end)
it('allows interactive commands', function()
- nvim('command', notify_str('v:job_data[1]', 'v:job_data[2]'))
+ nvim('command', notify_str('v:job_data[1]', 'get(v:job_data, 2)'))
nvim('command', "let j = jobstart('xxx', 'cat', ['-'])")
neq(0, eval('j'))
nvim('command', 'call jobsend(j, "abc\\n")')
@@ -46,9 +46,8 @@ describe('jobs', function()
eq({'notification', 'stdout', {{'123', 'xyz'}}}, next_message())
nvim('command', 'call jobsend(j, [123, "xyz"])')
eq({'notification', 'stdout', {{'123', 'xyz'}}}, next_message())
- nvim('command', notify_str('v:job_data[1])'))
nvim('command', "call jobstop(j)")
- eq({'notification', 'exit', {}}, next_message())
+ eq({'notification', 'exit', {0}}, next_message())
end)
it('preserves NULs', function()
@@ -59,9 +58,10 @@ describe('jobs', function()
file:close()
-- v:job_data preserves NULs.
- nvim('command', notify_str('v:job_data[1]', 'v:job_data[2]'))
+ nvim('command', notify_str('v:job_data[1]', 'get(v:job_data, 2)'))
nvim('command', "let j = jobstart('xxx', 'cat', ['"..filename.."'])")
eq({'notification', 'stdout', {{'abc\ndef'}}}, next_message())
+ eq({'notification', 'exit', {0}}, next_message())
os.remove(filename)
-- jobsend() preserves NULs.
@@ -72,12 +72,13 @@ describe('jobs', function()
end)
it('will hold data if it does not end in a newline', function()
- nvim('command', notify_str('v:job_data[1]', 'v:job_data[2]'))
+ nvim('command', notify_str('v:job_data[1]', 'get(v:job_data, 2)'))
nvim('command', "let j = jobstart('xxx', 'cat', ['-'])")
nvim('command', 'call jobsend(j, "abc\\nxyz")')
eq({'notification', 'stdout', {{'abc'}}}, next_message())
nvim('command', "call jobstop(j)")
eq({'notification', 'stdout', {{'xyz'}}}, next_message())
+ eq({'notification', 'exit', {0}}, next_message())
end)
it('will not allow jobsend/stop on a non-existent job', function()
diff --git a/test/functional/legacy/004_bufenter_with_modelines_spec.lua b/test/functional/legacy/004_bufenter_with_modelines_spec.lua
index f1222700a7..6f009b52dd 100644
--- a/test/functional/legacy/004_bufenter_with_modelines_spec.lua
+++ b/test/functional/legacy/004_bufenter_with_modelines_spec.lua
@@ -31,7 +31,7 @@ describe('BufEnter with modelines', function()
execute('sp Xxx')
-- Append text with autoindent to this file
- feed('G?this is a<Esc>')
+ feed('G?this is a<CR>')
feed('othis should be auto-indented<Esc>')
-- Go to Xxx, no autocmd anymore
@@ -39,7 +39,7 @@ describe('BufEnter with modelines', function()
execute('buf Xxx')
-- Append text without autoindent to Xxx
- feed('G?this is a<Esc>')
+ feed('G?this is a<CR>')
feed('othis should be in column 1<Esc>')
execute('wq')
diff --git a/test/functional/legacy/005_bufleave_delete_buffer.lua b/test/functional/legacy/005_bufleave_delete_buffer.lua
new file mode 100644
index 0000000000..e8459ad4a7
--- /dev/null
+++ b/test/functional/legacy/005_bufleave_delete_buffer.lua
@@ -0,0 +1,71 @@
+-- Test for autocommand that deletes the current buffer on BufLeave event.
+-- Also test deleting the last buffer, should give a new, empty buffer.
+
+local helpers = require('test.functional.helpers')
+local clear, feed, insert = helpers.clear, helpers.feed, helpers.insert
+local execute, expect = helpers.execute, helpers.expect
+
+describe('test5', function()
+ setup(clear)
+
+ it('is working', function()
+ insert([[
+ start of test file Xxx
+ vim: set noai :
+ this is a test
+ this is a test
+ this is a test
+ this is a test
+ end of test file Xxx]])
+
+ execute('w! Xxx0')
+ execute('au BufLeave Xxx bwipe')
+ execute('/start of')
+
+ -- Write test file Xxx.
+ execute('.,/end of/w! Xxx')
+
+ -- Split to Xxx.
+ execute('sp Xxx')
+
+ -- Delete buffer Xxx, now we're back here.
+ execute('bwipe')
+ feed('G?this is a<cr>')
+ feed('othis is some more text<esc>')
+
+ -- Append some text to this file.
+
+ -- Write current file contents.
+ execute('?start?,$yank A')
+
+ -- Delete alternate buffer.
+ execute('bwipe test.out')
+ execute('au bufleave test5.in bwipe')
+
+ -- Delete current buffer, get an empty one.
+ execute('bwipe!')
+ feed('ithis is another test line<esc>:yank A<cr>')
+
+ -- Output results
+ execute('%d')
+ execute('0put a')
+ execute('1d | $d')
+
+ -- Assert buffer contents.
+ expect([[
+ start of test file Xxx
+ vim: set noai :
+ this is a test
+ this is a test
+ this is a test
+ this is a test
+ this is some more text
+ end of test file Xxx
+ this is another test line]])
+ end)
+
+ teardown(function()
+ os.remove('Xxx')
+ os.remove('Xxx0')
+ end)
+end)
diff --git a/test/functional/legacy/025_jump_tag_hidden_spec.lua b/test/functional/legacy/025_jump_tag_hidden_spec.lua
new file mode 100644
index 0000000000..bd434c013c
--- /dev/null
+++ b/test/functional/legacy/025_jump_tag_hidden_spec.lua
@@ -0,0 +1,50 @@
+-- Test for jumping to a tag with 'hidden' set, with symbolic link in path of tag.
+-- This only works for Unix, because of the symbolic link.
+
+local helpers = require('test.functional.helpers')
+local clear, feed, insert = helpers.clear, helpers.feed, helpers.insert
+local execute, expect = helpers.execute, helpers.expect
+
+describe('jump to a tag with hidden set', function()
+ setup(clear)
+
+ it('is working', function()
+ insert([[
+ tags line:
+ SECTION_OFF /test25.dir/Xxx /^#define SECTION_OFF 3$/
+
+ /*tx.c*/
+ #define SECTION_OFF 3
+ #define NUM_SECTIONS 3
+
+ SECTION_OFF]])
+
+ execute('w! Xxx')
+ execute('set hidden')
+
+ -- Create a link from test25.dir to the current directory.
+ execute('!rm -f test25.dir')
+ execute('!ln -s . test25.dir')
+
+ -- Create tags.text, with the current directory name inserted.
+ execute('/tags line')
+ execute('r !pwd')
+ feed('d$/test<cr>')
+ feed('hP:.w! tags.test<cr>')
+
+ -- Try jumping to a tag in the current file, but with a path that contains a
+ -- symbolic link. When wrong, this will give the ATTENTION message. The next
+ -- space will then be eaten by hit-return, instead of moving the cursor to 'd'.
+ execute('set tags=tags.test')
+ feed('G<C-]> x:yank a<cr>')
+ execute('!rm -f Xxx test25.dir tags.test')
+
+ -- Put @a and remove empty line
+ execute('%d')
+ execute('0put a')
+ execute('$d')
+
+ -- Assert buffer contents.
+ expect("#efine SECTION_OFF 3")
+ end)
+end)
diff --git a/test/functional/legacy/026_execute_while_if_spec.lua b/test/functional/legacy/026_execute_while_if_spec.lua
new file mode 100644
index 0000000000..9acbf76673
--- /dev/null
+++ b/test/functional/legacy/026_execute_while_if_spec.lua
@@ -0,0 +1,66 @@
+-- Test for :execute, :while and :if
+
+local helpers = require('test.functional.helpers')
+local clear, feed, insert = helpers.clear, helpers.feed, helpers.insert
+local execute, expect = helpers.execute, helpers.expect
+local source = helpers.source
+
+describe(':execute, :while and :if', function()
+ setup(clear)
+
+ it('is working', function()
+ source([[
+ let i = 0
+ while i < 12
+ let i = i + 1
+ if has("ebcdic")
+ execute "normal o" . i . "\047"
+ else
+ execute "normal o" . i . "\033"
+ endif
+ if i % 2
+ normal Ax
+ if i == 9
+ break
+ endif
+ if i == 5
+ continue
+ else
+ let j = 9
+ while j > 0
+ if has("ebcdic")
+ execute "normal" j . "a" . j . "\x27"
+ else
+ execute "normal" j . "a" . j . "\x1b"
+ endif
+ let j = j - 1
+ endwhile
+ endif
+ endif
+ if i == 9
+ if has("ebcdic")
+ execute "normal Az\047"
+ else
+ execute "normal Az\033"
+ endif
+ endif
+ endwhile
+ unlet i j
+ ]])
+
+ -- Remove empty line
+ execute('1d')
+
+ -- Assert buffer contents.
+ expect([[
+ 1x999999999888888887777777666666555554444333221
+ 2
+ 3x999999999888888887777777666666555554444333221
+ 4
+ 5x
+ 6
+ 7x999999999888888887777777666666555554444333221
+ 8
+ 9x]])
+ end)
+end)
diff --git a/test/functional/legacy/033_lisp_indent_spec.lua b/test/functional/legacy/033_lisp_indent_spec.lua
new file mode 100644
index 0000000000..3ee248815d
--- /dev/null
+++ b/test/functional/legacy/033_lisp_indent_spec.lua
@@ -0,0 +1,73 @@
+-- vim: set foldmethod=marker foldmarker=[[,]] :
+-- Test for 'lisp'
+-- If the lisp feature is not enabled, this will fail!
+
+local helpers = require('test.functional.helpers')
+local clear, feed, insert = helpers.clear, helpers.feed, helpers.insert
+local execute, expect = helpers.execute, helpers.expect
+
+describe('lisp indent', function()
+ setup(clear)
+
+ it('is working', function()
+ insert([[
+ (defun html-file (base)
+ (format nil "~(~A~).html" base))
+
+ (defmacro page (name title &rest body)
+ (let ((ti (gensym)))
+ `(with-open-file (*standard-output*
+ (html-file ,name)
+ :direction :output
+ :if-exists :supersede)
+ (let ((,ti ,title))
+ (as title ,ti)
+ (with center
+ (as h2 (string-upcase ,ti)))
+ (brs 3)
+ ,@body))))
+
+ ;;; Utilities for generating links
+
+ (defmacro with-link (dest &rest body)
+ `(progn
+ (format t "<a href=\"~A\">" (html-file ,dest))
+ ,@body
+ (princ "</a>")))]])
+
+ execute('set lisp expandtab')
+ execute('/^(defun')
+ feed('=G:/^(defun/,$yank A<cr>')
+
+ -- Put @a and clean empty line
+ execute('%d')
+ execute('0put a')
+ execute('$d')
+
+ -- Assert buffer contents.
+ expect([[
+ (defun html-file (base)
+ (format nil "~(~A~).html" base))
+
+ (defmacro page (name title &rest body)
+ (let ((ti (gensym)))
+ `(with-open-file (*standard-output*
+ (html-file ,name)
+ :direction :output
+ :if-exists :supersede)
+ (let ((,ti ,title))
+ (as title ,ti)
+ (with center
+ (as h2 (string-upcase ,ti)))
+ (brs 3)
+ ,@body))))
+
+ ;;; Utilities for generating links
+
+ (defmacro with-link (dest &rest body)
+ `(progn
+ (format t "<a href=\"~A\">" (html-file ,dest))
+ ,@body
+ (princ "</a>")))]])
+ end)
+end)
diff --git a/test/functional/legacy/043_magic_settings_spec.lua b/test/functional/legacy/043_magic_settings_spec.lua
new file mode 100644
index 0000000000..ccef298cdd
--- /dev/null
+++ b/test/functional/legacy/043_magic_settings_spec.lua
@@ -0,0 +1,61 @@
+-- vim: set foldmethod=marker foldmarker=[[,]] :
+-- Tests for regexp with various magic settings.
+
+local helpers = require('test.functional.helpers')
+local clear, feed, insert = helpers.clear, helpers.feed, helpers.insert
+local execute, expect = helpers.execute, helpers.expect
+
+describe('regexp with magic settings', function()
+ setup(clear)
+
+ it('is working', function()
+ insert([[
+ 1 a aa abb abbccc
+ 2 d dd dee deefff
+ 3 g gg ghh ghhiii
+ 4 j jj jkk jkklll
+ 5 m mm mnn mnnooo
+ 6 x ^aa$ x
+ 7 (a)(b) abbaa
+ 8 axx [ab]xx
+ 9 foobar
+ ]])
+
+ execute('set nocompatible viminfo+=nviminfo')
+ execute('/^1')
+ execute([[/a*b\{2}c\+/e]])
+ feed([[x/\Md\*e\{2}f\+/e<cr>]])
+ feed('x:set nomagic<cr>')
+ execute([[/g\*h\{2}i\+/e]])
+ feed([[x/\mj*k\{2}l\+/e<cr>]])
+ feed([[x/\vm*n{2}o+/e<cr>]])
+ feed([[x/\V^aa$<cr>]])
+ feed('x:set magic<cr>')
+ execute([[/\v(a)(b)\2\1\1/e]])
+ feed([[x/\V[ab]\(\[xy]\)\1<cr>]])
+ feed('x:$<cr>')
+ execute('set undolevels=100')
+ feed('dv?bar?<cr>')
+ feed('Yup:<cr>')
+ execute('?^1?,$yank A')
+
+ -- Put @a and clean empty line
+ execute('%d')
+ execute('0put a')
+ execute('$d')
+
+ -- Assert buffer contents.
+ expect([[
+ 1 a aa abb abbcc
+ 2 d dd dee deeff
+ 3 g gg ghh ghhii
+ 4 j jj jkk jkkll
+ 5 m mm mnn mnnoo
+ 6 x aa$ x
+ 7 (a)(b) abba
+ 8 axx ab]xx
+ 9 foobar
+ 9 foo
+ ]])
+ end)
+end)
diff --git a/test/functional/legacy/051_highlight_spec.lua b/test/functional/legacy/051_highlight_spec.lua
new file mode 100644
index 0000000000..f35b70f93f
--- /dev/null
+++ b/test/functional/legacy/051_highlight_spec.lua
@@ -0,0 +1,70 @@
+-- vim: set foldmethod=marker foldmarker=[[,]] :
+-- Tests for ":highlight".
+
+local helpers = require('test.functional.helpers')
+local clear, feed, insert = helpers.clear, helpers.feed, helpers.insert
+local execute, expect = helpers.execute, helpers.expect
+
+describe(':highlight', function()
+ setup(clear)
+
+ it('is working', function()
+ -- Basic test if ":highlight" doesn't crash
+ execute('highlight')
+ execute('hi Search')
+
+ -- Test setting colors.
+ -- Test clearing one color and all doesn't generate error or warning
+ execute('hi NewGroup term=bold cterm=italic ctermfg=DarkBlue ctermbg=Grey gui= guifg=#00ff00 guibg=Cyan')
+ execute('hi Group2 term= cterm=')
+ execute('hi Group3 term=underline cterm=bold')
+ execute('redir! @a')
+ execute('hi NewGroup')
+ execute('hi Group2')
+ execute('hi Group3')
+ execute('hi clear NewGroup')
+ execute('hi NewGroup')
+ execute('hi Group2')
+ execute('hi Group2 NONE')
+ execute('hi Group2')
+ execute('hi clear')
+ execute('hi Group3')
+ execute([[hi Crash term='asdf]])
+ execute('redir END')
+
+ -- Filter ctermfg and ctermbg, the numbers depend on the terminal
+ execute('0put a')
+ execute([[%s/ctermfg=\d*/ctermfg=2/]])
+ execute([[%s/ctermbg=\d*/ctermbg=3/]])
+
+ -- Filter out possibly translated error message
+ execute('%s/E475: [^:]*:/E475:/')
+
+ -- Fix the fileformat
+ execute('set ff&')
+ execute('$d')
+
+ -- Assert buffer contents.
+ expect([[
+
+
+ NewGroup xxx term=bold cterm=italic ctermfg=2 ctermbg=3
+
+ Group2 xxx cleared
+
+ Group3 xxx term=underline cterm=bold
+
+
+ NewGroup xxx cleared
+
+ Group2 xxx cleared
+
+
+ Group2 xxx cleared
+
+
+ Group3 xxx cleared
+
+ E475: term='asdf]])
+ end)
+end)
diff --git a/test/functional/legacy/066_visual_block_tab_spec.lua b/test/functional/legacy/066_visual_block_tab_spec.lua
new file mode 100644
index 0000000000..cd283e6746
--- /dev/null
+++ b/test/functional/legacy/066_visual_block_tab_spec.lua
@@ -0,0 +1,64 @@
+-- vim: set foldmethod=marker foldmarker=[[,]] :
+-- Test for visual block shift and tab characters.
+
+local helpers = require('test.functional.helpers')
+local clear, feed, insert = helpers.clear, helpers.feed, helpers.insert
+local execute, expect = helpers.execute, helpers.expect
+
+describe('visual block shift and tab characters', function()
+ setup(clear)
+
+ it('is working', function()
+ insert([[
+ one two three
+ one two three
+ one two three
+ one two three
+ one two three
+
+ abcdefghijklmnopqrstuvwxyz
+ abcdefghijklmnopqrstuvwxyz
+ abcdefghijklmnopqrstuvwxyz
+ abcdefghijklmnopqrstuvwxyz
+ abcdefghijklmnopqrstuvwxyz]])
+
+ feed('gg')
+ feed([[fe<C-v>4jR<esc>ugvr1:'<,'>yank A<cr>]])
+ execute('/^abcdefgh')
+ feed('<C-v>4jI <esc>j<<11|D')
+ feed('j7|a <esc>')
+ feed('j7|a <esc>')
+ feed('j7|a <esc>4k13|<C-v>4j<')
+ execute('$-5,$yank A')
+ execute([[$-4,$s/\s\+//g]])
+ feed('<C-v>4kI <esc>j<<')
+ feed('j7|a <esc>')
+ feed('j7|a <esc>')
+ feed('j7|a <esc>4k13|<C-v>4j3<')
+ execute('$-4,$yank A')
+
+ -- Put @a and clean empty lines
+ execute('%d')
+ execute('0put a')
+ execute('$d')
+
+ -- Assert buffer contents.
+ expect([[
+ on1 two three
+ on1 two three
+ on1 two three
+ on1 two three
+ on1 two three
+
+ abcdefghijklmnopqrstuvwxyz
+ abcdefghij
+ abc defghijklmnopqrstuvwxyz
+ abc defghijklmnopqrstuvwxyz
+ abc defghijklmnopqrstuvwxyz
+ abcdefghijklmnopqrstuvwxyz
+ abcdefghij
+ abc defghijklmnopqrstuvwxyz
+ abc defghijklmnopqrstuvwxyz
+ abc defghijklmnopqrstuvwxyz]])
+ end)
+end)
diff --git a/test/functional/legacy/067_augroup_exists_spec.lua b/test/functional/legacy/067_augroup_exists_spec.lua
new file mode 100644
index 0000000000..6d89ad6d55
--- /dev/null
+++ b/test/functional/legacy/067_augroup_exists_spec.lua
@@ -0,0 +1,46 @@
+-- Test that groups and patterns are tested correctly when calling exists() for
+-- autocommands.
+
+local helpers = require('test.functional.helpers')
+local clear, feed, insert = helpers.clear, helpers.feed, helpers.insert
+local execute, expect = helpers.execute, helpers.expect
+
+describe('augroup when calling exists()', function()
+ setup(clear)
+
+ it('is working', function()
+ execute('let results=[]')
+ execute('call add(results, "##BufEnter: " . exists("##BufEnter"))')
+ execute('call add(results, "#BufEnter: " . exists("#BufEnter"))')
+ execute('au BufEnter * let g:entered=1')
+ execute('call add(results, "#BufEnter: " . exists("#BufEnter"))')
+ execute('call add(results, "#auexists#BufEnter: " . exists("#auexists#BufEnter"))')
+ execute('augroup auexists', 'au BufEnter * let g:entered=1', 'augroup END')
+ execute('call add(results, "#auexists#BufEnter: " . exists("#auexists#BufEnter"))')
+ execute('call add(results, "#BufEnter#*.test: " . exists("#BufEnter#*.test"))')
+ execute('au BufEnter *.test let g:entered=1')
+ execute('call add(results, "#BufEnter#*.test: " . exists("#BufEnter#*.test"))')
+ execute('edit testfile.test')
+ execute('call add(results, "#BufEnter#<buffer>: " . exists("#BufEnter#<buffer>"))')
+ execute('au BufEnter <buffer> let g:entered=1')
+ execute('call add(results, "#BufEnter#<buffer>: " . exists("#BufEnter#<buffer>"))')
+ execute('edit testfile2.test')
+ execute('call add(results, "#BufEnter#<buffer>: " . exists("#BufEnter#<buffer>"))')
+ execute('bf')
+ execute('call append(0, results)')
+ execute('$d')
+
+ -- Assert buffer contents.
+ expect([[
+ ##BufEnter: 1
+ #BufEnter: 0
+ #BufEnter: 1
+ #auexists#BufEnter: 0
+ #auexists#BufEnter: 1
+ #BufEnter#*.test: 0
+ #BufEnter#*.test: 1
+ #BufEnter#<buffer>: 0
+ #BufEnter#<buffer>: 1
+ #BufEnter#<buffer>: 0]])
+ end)
+end)
diff --git a/test/functional/legacy/075_maparg_spec.lua b/test/functional/legacy/075_maparg_spec.lua
new file mode 100644
index 0000000000..dac8940314
--- /dev/null
+++ b/test/functional/legacy/075_maparg_spec.lua
@@ -0,0 +1,58 @@
+-- Tests for maparg().
+-- Also test utf8 map with a 0x80 byte.
+
+local helpers = require('test.functional.helpers')
+local clear, feed, insert = helpers.clear, helpers.feed, helpers.insert
+local execute, expect = helpers.execute, helpers.expect
+
+describe('maparg()', function()
+ setup(clear)
+
+ it('is working', function()
+ execute('set cpo-=<')
+ execute('set encoding=utf8')
+
+ -- Test maparg() with a string result
+ execute('map foo<C-V> is<F4>foo')
+ execute('vnoremap <script> <buffer> <expr> <silent> bar isbar')
+ execute([[call append('$', maparg('foo<C-V>'))]])
+ execute([[call append('$', string(maparg('foo<C-V>', '', 0, 1)))]])
+ execute([[call append('$', string(maparg('bar', '', 0, 1)))]])
+ execute('map <buffer> <nowait> foo bar')
+ execute([[call append('$', string(maparg('foo', '', 0, 1)))]])
+ execute('map abc x<char-114>x')
+ execute([[call append('$', maparg('abc'))]])
+ execute('map abc y<S-char-114>y')
+ execute([[call append('$', maparg('abc'))]])
+ feed('Go<esc>:<cr>')
+
+ -- Outside of the range, minimum
+ execute('inoremap <Char-0x1040> a')
+ execute([[execute "normal a\u1040\<Esc>"]])
+
+ -- Inside of the range, minimum
+ execute('inoremap <Char-0x103f> b')
+ execute([[execute "normal a\u103f\<Esc>"]])
+
+ -- Inside of the range, maximum
+ execute('inoremap <Char-0xf03f> c')
+ execute([[execute "normal a\uf03f\<Esc>"]])
+
+ -- Outside of the range, maximum
+ execute('inoremap <Char-0xf040> d')
+ execute([[execute "normal a\uf040\<Esc>"]])
+
+ -- Remove empty line
+ execute('1d')
+
+ -- Assert buffer contents.
+ expect([[
+ is<F4>foo
+ {'silent': 0, 'noremap': 0, 'lhs': 'foo<C-V>', 'mode': ' ', 'nowait': 0, 'expr': 0, 'sid': 0, 'rhs': 'is<F4>foo', 'buffer': 0}
+ {'silent': 1, 'noremap': 1, 'lhs': 'bar', 'mode': 'v', 'nowait': 0, 'expr': 1, 'sid': 0, 'rhs': 'isbar', 'buffer': 1}
+ {'silent': 0, 'noremap': 0, 'lhs': 'foo', 'mode': ' ', 'nowait': 1, 'expr': 0, 'sid': 0, 'rhs': 'bar', 'buffer': 1}
+ xrx
+ yRy
+ abcd]])
+ end)
+end)
diff --git a/test/functional/legacy/101_hlsearch_spec.lua b/test/functional/legacy/101_hlsearch_spec.lua
new file mode 100644
index 0000000000..3c44f02edb
--- /dev/null
+++ b/test/functional/legacy/101_hlsearch_spec.lua
@@ -0,0 +1,63 @@
+-- Test for v:hlsearch
+
+local helpers = require('test.functional.helpers')
+local clear, feed, insert = helpers.clear, helpers.feed, helpers.insert
+local execute, expect = helpers.execute, helpers.expect
+local eval = helpers.eval
+
+describe('v:hlsearch', function()
+ setup(clear)
+
+ it('is working', function()
+ -- Last abc: Q
+ execute('new')
+ execute([[call setline(1, repeat(['aaa'], 10))]])
+ execute('set hlsearch nolazyredraw')
+ execute('let r=[]')
+ execute('command -nargs=0 -bar AddR :call add(r, [screenattr(1, 1), v:hlsearch])')
+ execute('/aaa')
+ execute('AddR')
+ execute('nohlsearch')
+ execute('AddR')
+ execute('let v:hlsearch=1')
+ execute('AddR')
+ execute('let v:hlsearch=0')
+ execute('AddR')
+ execute('set hlsearch')
+ execute('AddR')
+ execute('let v:hlsearch=0')
+ execute('AddR')
+ feed('n:AddR<cr>')
+ execute('let v:hlsearch=0')
+ execute('AddR')
+ execute('/')
+ execute('AddR')
+ execute('let r1=r[0][0]')
+
+ -- I guess it is not guaranteed that screenattr outputs always the same character
+ execute([[call map(r, 'v:val[1].":".(v:val[0]==r1?"highlighted":"not highlighted")')]])
+ execute('try')
+ execute(' let v:hlsearch=[]')
+ execute('catch')
+ execute([[ call add(r, matchstr(v:exception,'^Vim(let):E\d\+:'))]])
+ execute('endtry')
+ execute('bwipeout!')
+ execute('$put=r')
+ execute('call garbagecollect(1)')
+ execute('call getchar()')
+ execute('1d', '1d')
+
+ -- Assert buffer contents.
+ expect([[
+ 1:highlighted
+ 0:not highlighted
+ 1:highlighted
+ 0:not highlighted
+ 1:highlighted
+ 0:not highlighted
+ 1:highlighted
+ 0:not highlighted
+ 1:highlighted
+ Vim(let):E706:]])
+ end)
+end)
diff --git a/test/functional/legacy/104_let_assignment.lua b/test/functional/legacy/104_let_assignment.lua
new file mode 100644
index 0000000000..a2431da835
--- /dev/null
+++ b/test/functional/legacy/104_let_assignment.lua
@@ -0,0 +1,54 @@
+-- Tests for :let.
+
+local helpers = require('test.functional.helpers')
+local clear, source = helpers.clear, helpers.source
+local execute, expect = helpers.execute, helpers.expect
+
+describe(':let', function()
+ setup(clear)
+
+ it('is working', function()
+ execute('set runtimepath+=test/functional/fixtures')
+
+ -- Test to not autoload when assigning. It causes internal error.
+ source([[
+ try
+ let Test104#numvar = function('tr')
+ $put ='OK: ' . string(Test104#numvar)
+ catch
+ $put ='FAIL: ' . v:exception
+ endtry
+ let a = 1
+ let b = 2
+ for letargs in ['a b', '{0 == 1 ? "a" : "b"}', '{0 == 1 ? "a" : "b"} a', 'a {0 == 1 ? "a" : "b"}']
+ try
+ redir => messages
+ execute 'let' letargs
+ redir END
+ $put ='OK:'
+ $put =split(substitute(messages, '\n', '\0 ', 'g'), '\n')
+ catch
+ $put ='FAIL: ' . v:exception
+ redir END
+ endtry
+ endfor]])
+
+ -- Remove empty line
+ execute('1d')
+
+ -- Assert buffer contents.
+ expect([[
+ OK: function('tr')
+ OK:
+ a #1
+ b #2
+ OK:
+ b #2
+ OK:
+ b #2
+ a #1
+ OK:
+ a #1
+ b #2]])
+ end)
+end)
diff --git a/test/functional/legacy/105_filename_modifiers_spec.lua b/test/functional/legacy/105_filename_modifiers_spec.lua
new file mode 100644
index 0000000000..3b417a88eb
--- /dev/null
+++ b/test/functional/legacy/105_filename_modifiers_spec.lua
@@ -0,0 +1,81 @@
+-- Test filename modifiers.
+
+local helpers = require('test.functional.helpers')
+local clear, feed, insert = helpers.clear, helpers.feed, helpers.insert
+local execute, expect = helpers.execute, helpers.expect
+
+describe('filename modifiers', function()
+ setup(clear)
+
+ it('is working', function()
+ local tmpdir = helpers.nvim('eval', 'resolve("/tmp")')
+
+ execute('cd ' .. tmpdir)
+ execute([=[set shell=sh]=])
+ execute([=[set shellslash]=])
+ execute([=[let tab="\t"]=])
+ execute([=[command -nargs=1 Put :let expr=<q-args> | $put =expr.tab.strtrans(string(eval(expr)))]=])
+ execute([=[let $HOME=fnamemodify('.', ':p:h:h:h')]=])
+ execute([=[Put fnamemodify('.', ':p' )[-1:]]=])
+ execute([=[Put fnamemodify('.', ':p:h' )[-1:]]=])
+ execute([=[Put fnamemodify('test.out', ':p' )[-1:]]=])
+ execute([=[Put fnamemodify('test.out', ':.' )]=])
+ execute([=[Put fnamemodify('../testdir/a', ':.' )]=])
+ execute([=[Put fnamemodify('test.out', ':~' )]=])
+ execute([=[Put fnamemodify('../testdir/a', ':~' )]=])
+ execute([=[Put fnamemodify('../testdir/a', ':t' )]=])
+ execute([=[Put fnamemodify('.', ':p:t' )]=])
+ execute([=[Put fnamemodify('test.out', ':p:t' )]=])
+ execute([=[Put fnamemodify('test.out', ':p:e' )]=])
+ execute([=[Put fnamemodify('test.out', ':p:t:e' )]=])
+ execute([=[Put fnamemodify('abc.fb2.tar.gz', ':r' )]=])
+ execute([=[Put fnamemodify('abc.fb2.tar.gz', ':r:r' )]=])
+ execute([=[Put fnamemodify('abc.fb2.tar.gz', ':r:r:r' )]=])
+ execute([=[Put substitute(fnamemodify('abc.fb2.tar.gz', ':p:r:r'), '.*\(nvim/testdir/.*\)', '\1', '')]=])
+ execute([=[Put fnamemodify('abc.fb2.tar.gz', ':e' )]=])
+ execute([=[Put fnamemodify('abc.fb2.tar.gz', ':e:e' )]=])
+ execute([=[Put fnamemodify('abc.fb2.tar.gz', ':e:e:e' )]=])
+ execute([=[Put fnamemodify('abc.fb2.tar.gz', ':e:e:e:e')]=])
+ execute([=[Put fnamemodify('abc.fb2.tar.gz', ':e:e:r' )]=])
+ execute([=[Put fnamemodify('abc def', ':S' )]=])
+ execute([=[Put fnamemodify('abc" "def', ':S' )]=])
+ execute([=[Put fnamemodify('abc"%"def', ':S' )]=])
+ execute([=[Put fnamemodify('abc'' ''def', ':S' )]=])
+ execute([=[Put fnamemodify('abc''%''def', ':S' )]=])
+ execute([=[Put fnamemodify("abc\ndef", ':S' )]=])
+ execute([=[set shell=tcsh]=])
+ execute([=[Put fnamemodify("abc\ndef", ':S' )]=])
+ execute([=[1 delete _]=])
+
+ -- Assert buffer contents.
+ expect([=[
+ fnamemodify('.', ':p' )[-1:] '/'
+ fnamemodify('.', ':p:h' )[-1:] 'p'
+ fnamemodify('test.out', ':p' )[-1:] 't'
+ fnamemodify('test.out', ':.' ) 'test.out'
+ fnamemodify('../testdir/a', ':.' ) '../testdir/a'
+ fnamemodify('test.out', ':~' ) 'test.out'
+ fnamemodify('../testdir/a', ':~' ) '../testdir/a'
+ fnamemodify('../testdir/a', ':t' ) 'a'
+ fnamemodify('.', ':p:t' ) ''
+ fnamemodify('test.out', ':p:t' ) 'test.out'
+ fnamemodify('test.out', ':p:e' ) 'out'
+ fnamemodify('test.out', ':p:t:e' ) 'out'
+ fnamemodify('abc.fb2.tar.gz', ':r' ) 'abc.fb2.tar'
+ fnamemodify('abc.fb2.tar.gz', ':r:r' ) 'abc.fb2'
+ fnamemodify('abc.fb2.tar.gz', ':r:r:r' ) 'abc'
+ substitute(fnamemodify('abc.fb2.tar.gz', ':p:r:r'), '.*\(nvim/testdir/.*\)', '\1', '') ']=] .. tmpdir .. [=[/abc.fb2'
+ fnamemodify('abc.fb2.tar.gz', ':e' ) 'gz'
+ fnamemodify('abc.fb2.tar.gz', ':e:e' ) 'tar.gz'
+ fnamemodify('abc.fb2.tar.gz', ':e:e:e' ) 'fb2.tar.gz'
+ fnamemodify('abc.fb2.tar.gz', ':e:e:e:e') 'fb2.tar.gz'
+ fnamemodify('abc.fb2.tar.gz', ':e:e:r' ) 'tar'
+ fnamemodify('abc def', ':S' ) '''abc def'''
+ fnamemodify('abc" "def', ':S' ) '''abc" "def'''
+ fnamemodify('abc"%"def', ':S' ) '''abc"%"def'''
+ fnamemodify('abc'' ''def', ':S' ) '''abc''\'''' ''\''''def'''
+ fnamemodify('abc''%''def', ':S' ) '''abc''\''''%''\''''def'''
+ fnamemodify("abc\ndef", ':S' ) '''abc^@def'''
+ fnamemodify("abc\ndef", ':S' ) '''abc\^@def''']=])
+ end)
+end)
diff --git a/test/functional/runtime/autoload/rpc/define_spec.lua b/test/functional/runtime/autoload/remote/define_spec.lua
index a85ba4d37b..53da47243c 100644
--- a/test/functional/runtime/autoload/rpc/define_spec.lua
+++ b/test/functional/runtime/autoload/remote/define_spec.lua
@@ -346,20 +346,20 @@ local function host()
end
local function register()
- eval('rpc#host#Register("busted", '..channel()..')')
+ eval('remote#host#Register("busted", '..channel()..')')
end
-command_specs_for('rpc#define#CommandOnChannel', true, channel)
-command_specs_for('rpc#define#CommandOnChannel', false, channel)
-command_specs_for('rpc#define#CommandOnHost', true, host, register)
-command_specs_for('rpc#define#CommandOnHost', false, host, register)
+command_specs_for('remote#define#CommandOnChannel', true, channel)
+command_specs_for('remote#define#CommandOnChannel', false, channel)
+command_specs_for('remote#define#CommandOnHost', true, host, register)
+command_specs_for('remote#define#CommandOnHost', false, host, register)
-autocmd_specs_for('rpc#define#AutocmdOnChannel', true, channel)
-autocmd_specs_for('rpc#define#AutocmdOnChannel', false, channel)
-autocmd_specs_for('rpc#define#AutocmdOnHost', true, host, register)
-autocmd_specs_for('rpc#define#AutocmdOnHost', false, host, register)
+autocmd_specs_for('remote#define#AutocmdOnChannel', true, channel)
+autocmd_specs_for('remote#define#AutocmdOnChannel', false, channel)
+autocmd_specs_for('remote#define#AutocmdOnHost', true, host, register)
+autocmd_specs_for('remote#define#AutocmdOnHost', false, host, register)
-function_specs_for('rpc#define#FunctionOnChannel', true, channel)
-function_specs_for('rpc#define#FunctionOnChannel', false, channel)
-function_specs_for('rpc#define#FunctionOnHost', true, host, register)
-function_specs_for('rpc#define#FunctionOnHost', false, host, register)
+function_specs_for('remote#define#FunctionOnChannel', true, channel)
+function_specs_for('remote#define#FunctionOnChannel', false, channel)
+function_specs_for('remote#define#FunctionOnHost', true, host, register)
+function_specs_for('remote#define#FunctionOnHost', false, host, register)
diff --git a/test/functional/shell/viml_system_spec.lua b/test/functional/shell/viml_system_spec.lua
index 91e115aedf..8d212c1375 100644
--- a/test/functional/shell/viml_system_spec.lua
+++ b/test/functional/shell/viml_system_spec.lua
@@ -10,6 +10,7 @@ local eq, clear, eval, feed, nvim =
local function create_file_with_nuls(name)
return function()
feed('ipart1<C-V>000part2<C-V>000part3<ESC>:w '..name..'<CR>')
+ eval('1') -- wait for the file to be created
end
end
@@ -21,11 +22,9 @@ end
-- Some tests require the xclip program and a x server.
local xclip = nil
-do
+do
if os.getenv('DISPLAY') then
- local proc = io.popen('which xclip')
- xclip = proc:read()
- proc:close()
+ xclip = (os.execute('command -v xclip > /dev/null 2>&1') == 0)
end
end
diff --git a/third-party/CMakeLists.txt b/third-party/CMakeLists.txt
index 38c5533ddd..83c2cfdc61 100644
--- a/third-party/CMakeLists.txt
+++ b/third-party/CMakeLists.txt
@@ -51,7 +51,7 @@ endif()
include(ExternalProject)
-set(LIBUV_URL https://github.com/joyent/libuv/archive/v0.11.28.tar.gz)
+set(LIBUV_URL https://github.com/libuv/libuv/archive/v0.11.28.tar.gz)
set(LIBUV_SHA1 3b70b65467ee693228b8b8385665a52690d74092)
set(LIBUV_MD5 1a849ba4fc571d531482ed74bc7aabc4)
@@ -194,7 +194,7 @@ if(USE_BUNDLED_LUAROCKS)
add_custom_command(OUTPUT ${DEPS_LIB_DIR}/luarocks/rocks/nvim-client
COMMAND ${DEPS_BIN_DIR}/luarocks
- ARGS build https://raw.githubusercontent.com/neovim/lua-client/master/nvim-client-0.0.1-2.rockspec CC=${DEPS_C_COMPILER} LD=${DEPS_C_COMPILER} LIBUV_DIR=${DEPS_INSTALL_DIR}
+ ARGS build https://raw.githubusercontent.com/neovim/lua-client/0aefb79d8f60fd180594f376d20144414e1f37a4/nvim-client-0.0.1-3.rockspec CC=${DEPS_C_COMPILER} LD=${DEPS_C_COMPILER} LIBUV_DIR=${DEPS_INSTALL_DIR}
DEPENDS lpeg libuv)
add_custom_target(nvim-client
DEPENDS ${DEPS_LIB_DIR}/luarocks/rocks/nvim-client)
diff --git a/third-party/cmake/DownloadAndExtractFile.cmake b/third-party/cmake/DownloadAndExtractFile.cmake
index eb5c1c6602..b0d28355cb 100644
--- a/third-party/cmake/DownloadAndExtractFile.cmake
+++ b/third-party/cmake/DownloadAndExtractFile.cmake
@@ -59,9 +59,13 @@ message(STATUS "downloading...
timeout='${timeout_msg}'")
if((DEFINED EXPECTED_SHA1) AND (${CMAKE_VERSION} VERSION_GREATER 2.8.10))
- set(hash_args EXPECTED_HASH SHA1=${EXPECTED_SHA1})
+ if(NOT (EXPECTED_SHA1 STREQUAL "0000000000000000000000000000000000000000"))
+ set(hash_args EXPECTED_HASH SHA1=${EXPECTED_SHA1})
+ endif()
else()
- set(hash_args EXPECTED_MD5 ${EXPECTED_MD5})
+ if(NOT (EXPECTED_MD5 STREQUAL "00000000000000000000000000000000"))
+ set(hash_args EXPECTED_MD5 ${EXPECTED_MD5})
+ endif()
endif()
file(DOWNLOAD ${URL} ${file}