aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.ci/common/build.sh3
-rw-r--r--.ci/common/test.sh2
-rw-r--r--.travis.yml5
-rw-r--r--CMakeLists.txt27
-rw-r--r--ISSUE_TEMPLATE.md12
-rw-r--r--Makefile10
-rwxr-xr-xclint.py2
-rw-r--r--runtime/autoload/man.vim44
-rw-r--r--runtime/autoload/msgpack.vim3
-rw-r--r--runtime/autoload/provider/python.vim4
-rw-r--r--runtime/autoload/provider/python3.vim4
-rw-r--r--runtime/autoload/provider/pythonx.vim26
-rw-r--r--runtime/autoload/provider/ruby.vim34
-rw-r--r--runtime/autoload/provider/script_host.py247
-rw-r--r--runtime/autoload/remote/host.vim69
-rw-r--r--runtime/doc/autocmd.txt14
-rw-r--r--runtime/doc/eval.txt66
-rw-r--r--runtime/doc/options.txt3
-rw-r--r--runtime/doc/os_dos.txt279
-rw-r--r--runtime/doc/repeat.txt6
-rw-r--r--runtime/doc/starting.txt2
-rw-r--r--runtime/doc/usr_05.txt5
-rw-r--r--runtime/doc/usr_06.txt2
-rw-r--r--runtime/doc/various.txt4
-rw-r--r--runtime/doc/vim_diff.txt48
-rw-r--r--runtime/doc/windows.txt2
-rw-r--r--runtime/ftplugin/man.vim4
-rw-r--r--runtime/macros/less.bat4
-rwxr-xr-xruntime/macros/less.sh4
-rw-r--r--runtime/plugin/rplugin.vim15
-rwxr-xr-xscripts/vim-patch.sh4
-rw-r--r--src/.clang-format8
-rw-r--r--src/nvim/CMakeLists.txt9
-rw-r--r--src/nvim/api/buffer.c150
-rw-r--r--src/nvim/auevents.lua1
-rw-r--r--src/nvim/buffer.c250
-rw-r--r--src/nvim/buffer_defs.h4
-rw-r--r--src/nvim/charset.c100
-rw-r--r--src/nvim/diff.c4
-rw-r--r--src/nvim/edit.c803
-rw-r--r--src/nvim/eval.c197
-rw-r--r--src/nvim/eval.h3
-rw-r--r--src/nvim/ex_cmds.c21
-rw-r--r--src/nvim/ex_cmds2.c164
-rw-r--r--src/nvim/ex_docmd.c6
-rw-r--r--src/nvim/ex_eval.c2
-rw-r--r--src/nvim/ex_getln.c27
-rw-r--r--src/nvim/fold.c4
-rw-r--r--src/nvim/globals.h8
-rw-r--r--src/nvim/main.c8
-rw-r--r--src/nvim/memfile.c144
-rw-r--r--src/nvim/memline.c6
-rw-r--r--src/nvim/normal.c12
-rw-r--r--src/nvim/ops.c144
-rw-r--r--src/nvim/option.c14
-rw-r--r--src/nvim/option_defs.h56
-rw-r--r--src/nvim/os/fs.c2
-rw-r--r--src/nvim/os/stdpaths.c15
-rw-r--r--src/nvim/path.c237
-rw-r--r--src/nvim/pos.h6
-rw-r--r--src/nvim/quickfix.c306
-rw-r--r--src/nvim/screen.c39
-rw-r--r--src/nvim/syntax.c28
-rw-r--r--src/nvim/tempfile.c3
-rw-r--r--src/nvim/terminal.c4
-rw-r--r--src/nvim/testdir/Makefile1
-rw-r--r--src/nvim/testdir/test88.in99
-rw-r--r--src/nvim/testdir/test88.ok29
-rw-r--r--src/nvim/undo.c8
-rw-r--r--src/nvim/version.c46
-rw-r--r--src/nvim/window.c41
-rw-r--r--test/functional/api/buffer_spec.lua151
-rw-r--r--test/functional/api/server_requests_spec.lua4
-rw-r--r--test/functional/api/vim_spec.lua4
-rw-r--r--test/functional/autocmd/autocmd_spec.lua31
-rw-r--r--test/functional/autocmd/tabnew_spec.lua44
-rw-r--r--test/functional/autocmd/textyankpost_spec.lua216
-rw-r--r--test/functional/eval/operators_spec.lua28
-rw-r--r--test/functional/eval/string_spec.lua175
-rw-r--r--test/functional/eval/vvar_event_spec.lua15
-rw-r--r--test/functional/fixtures/shell-test.c66
-rw-r--r--test/functional/helpers.lua41
-rw-r--r--test/functional/legacy/036_regexp_character_classes_spec.lua10
-rw-r--r--test/functional/legacy/039_visual_block_mode_commands_spec.lua2
-rw-r--r--test/functional/legacy/061_undo_tree_spec.lua2
-rw-r--r--test/functional/legacy/083_tag_search_with_file_encoding_spec.lua4
-rw-r--r--test/functional/legacy/088_conceal_tabs_spec.lua96
-rw-r--r--test/functional/legacy/100_lispwords_spec.lua47
-rw-r--r--test/functional/legacy/105_filename_modifiers_spec.lua81
-rw-r--r--test/functional/legacy/eval_spec.lua186
-rw-r--r--test/functional/legacy/fnamemodify_spec.lua75
-rw-r--r--test/functional/legacy/lispwords_spec.lua25
-rw-r--r--test/functional/options/shortmess_spec.lua39
-rw-r--r--test/functional/plugin/msgpack_spec.lua37
-rw-r--r--test/functional/plugin/shada_spec.lua8
-rw-r--r--test/functional/preload.lua1
-rw-r--r--test/functional/server/server_spec.lua4
-rw-r--r--test/functional/terminal/edit_spec.lua75
-rw-r--r--test/functional/terminal/tui_spec.lua36
-rw-r--r--test/functional/ui/screen.lua21
-rw-r--r--test/functional/viml/completion_spec.lua71
-rw-r--r--test/functional/viml/errorlist_spec.lua50
-rw-r--r--test/functional/viml/function_spec.lua29
-rw-r--r--test/unit/buffer_spec.lua10
-rw-r--r--third-party/CMakeLists.txt14
-rw-r--r--third-party/cmake/BuildLua.cmake85
106 files changed, 3330 insertions, 2416 deletions
diff --git a/.ci/common/build.sh b/.ci/common/build.sh
index f635ee4960..06bdab707f 100644
--- a/.ci/common/build.sh
+++ b/.ci/common/build.sh
@@ -5,6 +5,9 @@ build_deps() {
if [[ "${BUILD_MINGW}" == ON ]]; then
DEPS_CMAKE_FLAGS="${DEPS_CMAKE_FLAGS} ${CMAKE_FLAGS_MINGW}"
fi
+ if [[ "${FUNCTIONALTEST}" == "functionaltest-lua" ]]; then
+ DEPS_CMAKE_FLAGS="${DEPS_CMAKE_FLAGS} -DUSE_BUNDLED_LUA=ON"
+ fi
rm -rf "${DEPS_BUILD_DIR}"
diff --git a/.ci/common/test.sh b/.ci/common/test.sh
index c1bbd8dc9a..8c32b63ab2 100644
--- a/.ci/common/test.sh
+++ b/.ci/common/test.sh
@@ -53,7 +53,7 @@ run_unittests() {
}
run_functionaltests() {
- if ! ${MAKE_CMD} -C "${BUILD_DIR}" functionaltest; then
+ if ! ${MAKE_CMD} -C "${BUILD_DIR}" ${FUNCTIONALTEST}; then
asan_check "${LOG_DIR}"
valgrind_check "${LOG_DIR}"
exit 1
diff --git a/.travis.yml b/.travis.yml
index 10219690b3..985a5c5381 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -53,6 +53,8 @@ env:
# if the tests were successful, but don't have this information
# available in before_cache (which is run before after_success).
- SUCCESS_MARKER="$BUILD_DIR/.tests_successful"
+ # default target name for functional tests
+ - FUNCTIONALTEST=functionaltest
matrix:
include:
@@ -61,6 +63,9 @@ matrix:
- os: linux
compiler: gcc-5
- os: linux
+ compiler: gcc-5
+ env: FUNCTIONALTEST=functionaltest-lua
+ - os: linux
# Travis creates a cache per compiler.
# Set a different value here to store 32-bit
# dependencies in a separate cache.
diff --git a/CMakeLists.txt b/CMakeLists.txt
index acd9dc1865..5798a74369 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,6 +1,10 @@
cmake_minimum_required(VERSION 2.8.7)
project(nvim)
+if(POLICY CMP0059)
+ cmake_policy(SET CMP0059 OLD) # Needed until cmake 2.8.12. #4389
+endif()
+
# Point CMake at any custom modules we may ship
list(APPEND CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake")
@@ -55,7 +59,7 @@ set_property(CACHE CMAKE_BUILD_TYPE PROPERTY
# version string, else it is combined with the result of `git describe`.
set(NVIM_VERSION_MAJOR 0)
set(NVIM_VERSION_MINOR 1)
-set(NVIM_VERSION_PATCH 3)
+set(NVIM_VERSION_PATCH 4)
set(NVIM_VERSION_PRERELEASE "-dev") # for package maintainers
file(TO_CMAKE_PATH ${CMAKE_CURRENT_LIST_DIR}/.git FORCED_GIT_DIR)
@@ -206,6 +210,12 @@ if(MSVC)
else()
add_definitions(-Wall -Wextra -pedantic -Wno-unused-parameter
-Wstrict-prototypes -std=gnu99)
+
+ # On FreeBSD 64 math.h uses unguarded C11 extension, which taints clang
+ # 3.4.1 used there.
+ if(CMAKE_SYSTEM_NAME STREQUAL "FreeBSD")
+ add_definitions(-Wno-c11-extensions)
+ endif()
endif()
if(MINGW)
@@ -384,6 +394,7 @@ message(STATUS "Using the Lua interpreter ${LUA_PRG}.")
# Setup busted.
find_program(BUSTED_PRG busted)
+find_program(BUSTED_LUA_PRG busted-lua)
if(NOT BUSTED_OUTPUT_TYPE)
set(BUSTED_OUTPUT_TYPE "utfTerminal")
endif()
@@ -495,6 +506,20 @@ if(BUSTED_PRG)
DEPENDS ${BENCHMARK_PREREQS})
endif()
+if(BUSTED_LUA_PRG)
+ add_custom_target(functionaltest-lua
+ COMMAND ${CMAKE_COMMAND}
+ -DBUSTED_PRG=${BUSTED_LUA_PRG}
+ -DNVIM_PRG=$<TARGET_FILE:nvim>
+ -DWORKING_DIR=${CMAKE_CURRENT_SOURCE_DIR}
+ -DBUSTED_OUTPUT_TYPE=${BUSTED_OUTPUT_TYPE}
+ -DTEST_DIR=${CMAKE_CURRENT_SOURCE_DIR}/test
+ -DBUILD_DIR=${CMAKE_BINARY_DIR}
+ -DTEST_TYPE=functional
+ -P ${PROJECT_SOURCE_DIR}/cmake/RunTests.cmake
+ DEPENDS ${FUNCTIONALTEST_PREREQS})
+endif()
+
if(LUACHECK_PRG)
add_custom_target(testlint
COMMAND ${CMAKE_COMMAND}
diff --git a/ISSUE_TEMPLATE.md b/ISSUE_TEMPLATE.md
index 4abcc4eae1..e0185844ad 100644
--- a/ISSUE_TEMPLATE.md
+++ b/ISSUE_TEMPLATE.md
@@ -1,9 +1,15 @@
- Neovim version:
-- Operating system:
-- Terminal emulator:
+- [ ] Vim behaves differently?
+ - Vim version:
+- Operating system/version:
+- Terminal name/version:
+- `$TERM`:
### Actual behaviour
### Expected behaviour
-### Steps to reproduce
+### Steps to reproduce using `nvim -u NONE`
+
+1. `nvim -u NONE`
+2.
diff --git a/Makefile b/Makefile
index 1fc15e1312..097832748b 100644
--- a/Makefile
+++ b/Makefile
@@ -45,6 +45,11 @@ ifneq (,$(USE_BUNDLED_DEPS))
BUNDLED_CMAKE_FLAG := -DUSE_BUNDLED=$(USE_BUNDLED_DEPS)
endif
+ifneq (,$(findstring functionaltest-lua,$(MAKECMDGOALS)))
+ BUNDLED_LUA_CMAKE_FLAG := -DUSE_BUNDLED_LUA=ON
+ $(shell [ -x .deps/usr/bin/lua ] || rm build/.ran-*)
+endif
+
# For use where we want to make sure only a single job is run. This does issue
# a warning, but we need to keep SCRIPTS argument.
SINGLE_MAKE = export MAKEFLAGS= ; $(MAKE)
@@ -74,7 +79,7 @@ build/.ran-third-party-cmake:
ifeq ($(call filter-true,$(USE_BUNDLED_DEPS)),)
mkdir -p .deps
cd .deps && \
- cmake -G '$(BUILD_TYPE)' $(BUNDLED_CMAKE_FLAG) \
+ cmake -G '$(BUILD_TYPE)' $(BUNDLED_CMAKE_FLAG) $(BUNDLED_LUA_CMAKE_FLAG) \
$(DEPS_CMAKE_FLAGS) ../third-party
endif
mkdir -p build
@@ -86,6 +91,9 @@ oldtest: | nvim
functionaltest: | nvim
+$(BUILD_CMD) -C build functionaltest
+functionaltest-lua: | nvim
+ +$(BUILD_CMD) -C build functionaltest-lua
+
testlint: | nvim
$(BUILD_CMD) -C build testlint
diff --git a/clint.py b/clint.py
index 9f6a35b7f4..fc081dcd14 100755
--- a/clint.py
+++ b/clint.py
@@ -2552,7 +2552,7 @@ def CheckBraces(filename, clean_lines, linenum, error):
# If should always have a brace
for blockstart in ('if', 'while', 'for'):
- if Match(r'\s*{0}[^{{]*$'.format(blockstart), line):
+ if Match(r'\s*{0}(?!\w)[^{{]*$'.format(blockstart), line):
pos = line.find(blockstart)
pos = line.find('(', pos)
if pos > 0:
diff --git a/runtime/autoload/man.vim b/runtime/autoload/man.vim
index 49663d7e5a..0dfcc424e2 100644
--- a/runtime/autoload/man.vim
+++ b/runtime/autoload/man.vim
@@ -11,6 +11,8 @@ catch /E145:/
" Ignore the error in restricted mode
endtry
+" Load man page {page} from {section}
+" call man#get_page([{section}, ]{page})
function man#get_page(...) abort
let invoked_from_man = (&filetype ==# 'man')
@@ -20,21 +22,14 @@ function man#get_page(...) abort
elseif a:0 > 2
echoerr 'too many arguments'
return
- elseif a:0 == 2
- let [page, sect] = [a:2, 0 + a:1]
- elseif type(1) == type(a:1)
- let [page, sect] = ['<cword>', a:1]
- else
- let [page, sect] = [a:1, '']
endif
- if page == '<cword>'
- let page = expand('<cword>')
- endif
+ let sect = get(a:000, 0)
+ let page = get(a:000, 1, sect)
let [page, sect] = s:parse_page_and_section(sect, page)
- if 0 + sect > 0 && s:find_page(sect, page) == 0
+ if !empty(sect) && s:find_page(sect, page) == 0
let sect = ''
endif
@@ -54,9 +49,9 @@ function man#get_page(...) abort
let thiswin = winnr()
wincmd b
if winnr() > 1
- exe "norm! " . thiswin . "\<C-W>w"
+ exec thiswin . 'wincmd w'
while 1
- if &filetype == 'man'
+ if &filetype ==# 'man'
break
endif
wincmd w
@@ -80,11 +75,11 @@ function man#get_page(...) abort
endif
silent exec 'r!/usr/bin/man '.s:cmd(sect, page).' | col -b'
" Remove blank lines from top and bottom.
- while getline(1) =~ '^\s*$'
- silent keepjumps norm! gg"_dd
+ while getline(1) =~# '^\s*$'
+ silent keepjumps 1delete _
endwhile
- while getline('$') =~ '^\s*$'
- silent keepjumps norm! G"_dd
+ while getline('$') =~# '^\s*$'
+ silent keepjumps $delete _
endwhile
setlocal nomodified
setlocal filetype=man
@@ -118,15 +113,11 @@ endfunction
" Expects a string like 'access' or 'access(2)'.
function s:parse_page_and_section(sect, str) abort
try
- let save_isk = &iskeyword
- setlocal iskeyword-=(,)
- let page = substitute(a:str, '(*\(\k\+\).*', '\1', '')
- let sect = substitute(a:str, '\(\k\+\)(\([^()]*\)).*', '\2', '')
- if sect == page || -1 == match(sect, '^[0-9 ]\+$')
+ let [page, sect] = matchlist(a:str, '\v\C([-.[:alnum:]_]+)%(\(([-.[:alnum:]_]+)\))?')[1:2]
+ if empty(sect)
let sect = a:sect
endif
catch
- let &l:iskeyword = save_isk
echoerr 'man.vim: failed to parse: "'.a:str.'"'
endtry
@@ -134,7 +125,7 @@ function s:parse_page_and_section(sect, str) abort
endfunction
function s:cmd(sect, page) abort
- if 0 + a:sect > 0
+ if !empty(a:sect)
return s:man_sect_arg.' '.a:sect.' '.a:page
endif
return a:page
@@ -142,10 +133,5 @@ endfunction
function s:find_page(sect, page) abort
let where = system('/usr/bin/man '.s:man_find_arg.' '.s:cmd(a:sect, a:page))
- if where !~ "^/"
- if matchstr(where, " [^ ]*$") !~ "^ /"
- return 0
- endif
- endif
- return 1
+ return (where =~# '^ */')
endfunction
diff --git a/runtime/autoload/msgpack.vim b/runtime/autoload/msgpack.vim
index e6022922fe..2bb7ec5b02 100644
--- a/runtime/autoload/msgpack.vim
+++ b/runtime/autoload/msgpack.vim
@@ -395,7 +395,8 @@ endfunction
""
" Dump floating-point value.
function s:msgpack_dump_float(v) abort
- return string(type(a:v) == type({}) ? a:v._VAL : a:v)
+ return substitute(string(type(a:v) == type({}) ? a:v._VAL : a:v),
+ \'\V\^\(-\)\?str2float(''\(inf\|nan\)'')\$', '\1\2', '')
endfunction
""
diff --git a/runtime/autoload/provider/python.vim b/runtime/autoload/provider/python.vim
index b769895357..cb9d5c5296 100644
--- a/runtime/autoload/provider/python.vim
+++ b/runtime/autoload/provider/python.vim
@@ -24,12 +24,10 @@ if s:prog == ''
finish
endif
-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 remote#host#RegisterClone('legacy-python-provider', 'python')
-call remote#host#RegisterPlugin('legacy-python-provider', s:plugin_path, [])
+call remote#host#RegisterPlugin('legacy-python-provider', 'script_host.py', [])
function! provider#python#Call(method, args)
if s:err != ''
diff --git a/runtime/autoload/provider/python3.vim b/runtime/autoload/provider/python3.vim
index 2952f76b40..f4a751e7a2 100644
--- a/runtime/autoload/provider/python3.vim
+++ b/runtime/autoload/provider/python3.vim
@@ -24,12 +24,10 @@ if s:prog == ''
finish
endif
-let s:plugin_path = expand('<sfile>:p:h').'/script_host.py'
-
" The Python3 provider plugin will run in a separate instance of the Python3
" host.
call remote#host#RegisterClone('legacy-python3-provider', 'python3')
-call remote#host#RegisterPlugin('legacy-python3-provider', s:plugin_path, [])
+call remote#host#RegisterPlugin('legacy-python3-provider', 'script_host.py', [])
function! provider#python3#Call(method, args)
if s:err != ''
diff --git a/runtime/autoload/provider/pythonx.vim b/runtime/autoload/provider/pythonx.vim
index 022ef19914..05815a4896 100644
--- a/runtime/autoload/provider/pythonx.vim
+++ b/runtime/autoload/provider/pythonx.vim
@@ -5,6 +5,32 @@ endif
let s:loaded_pythonx_provider = 1
+function! provider#pythonx#Require(host) abort
+ let ver = (a:host.orig_name ==# 'python') ? 2 : 3
+
+ " Python host arguments
+ let args = ['-c', 'import sys; sys.path.remove(""); import neovim; neovim.start_host()']
+
+ " Collect registered Python plugins into args
+ let python_plugins = remote#host#PluginsForHost(a:host.name)
+ for plugin in python_plugins
+ call add(args, plugin.path)
+ endfor
+
+ try
+ let channel_id = rpcstart((ver == '2' ?
+ \ provider#python#Prog() : provider#python3#Prog()), args)
+ if rpcrequest(channel_id, 'poll') == 'ok'
+ return channel_id
+ endif
+ catch
+ echomsg v:throwpoint
+ echomsg v:exception
+ endtry
+ throw remote#host#LoadErrorForHost(a:host.orig_name,
+ \ '$NVIM_PYTHON_LOG_FILE')
+endfunction
+
function! provider#pythonx#Detect(major_ver) abort
let host_var = (a:major_ver == 2) ?
\ 'g:python_host_prog' : 'g:python3_host_prog'
diff --git a/runtime/autoload/provider/ruby.vim b/runtime/autoload/provider/ruby.vim
new file mode 100644
index 0000000000..aad8c09d28
--- /dev/null
+++ b/runtime/autoload/provider/ruby.vim
@@ -0,0 +1,34 @@
+" The Ruby provider helper
+if exists('s:loaded_ruby_provider')
+ finish
+endif
+
+let s:loaded_ruby_provider = 1
+
+function! provider#ruby#Require(host) abort
+ " Collect registered Ruby plugins into args
+ let args = []
+ let ruby_plugins = remote#host#PluginsForHost(a:host.name)
+
+ for plugin in ruby_plugins
+ call add(args, plugin.path)
+ endfor
+
+ try
+ let channel_id = rpcstart(provider#ruby#Prog(), args)
+
+ if rpcrequest(channel_id, 'poll') == 'ok'
+ return channel_id
+ endif
+ catch
+ echomsg v:throwpoint
+ echomsg v:exception
+ endtry
+
+ throw remote#host#LoadErrorForHost(a:host.orig_name,
+ \ '$NVIM_RUBY_LOG_FILE')
+endfunction
+
+function! provider#ruby#Prog() abort
+ return 'neovim-ruby-host'
+endfunction
diff --git a/runtime/autoload/provider/script_host.py b/runtime/autoload/provider/script_host.py
deleted file mode 100644
index 416b4070bb..0000000000
--- a/runtime/autoload/provider/script_host.py
+++ /dev/null
@@ -1,247 +0,0 @@
-"""Legacy python/python3-vim emulation."""
-import imp
-import io
-import logging
-import os
-import sys
-
-import neovim
-
-__all__ = ('ScriptHost',)
-
-
-logger = logging.getLogger(__name__)
-debug, info, warn = (logger.debug, logger.info, logger.warn,)
-
-IS_PYTHON3 = sys.version_info >= (3, 0)
-
-if IS_PYTHON3:
- basestring = str
-
- if sys.version_info >= (3, 4):
- from importlib.machinery import PathFinder
-
-
-@neovim.plugin
-class ScriptHost(object):
-
- """Provides an environment for running python plugins created for Vim."""
-
- def __init__(self, nvim):
- """Initialize the legacy python-vim environment."""
- self.setup(nvim)
- # context where all code will run
- self.module = imp.new_module('__main__')
- nvim.script_context = self.module
- # it seems some plugins assume 'sys' is already imported, so do it now
- exec('import sys', self.module.__dict__)
- self.legacy_vim = nvim.with_hook(LegacyEvalHook())
- sys.modules['vim'] = self.legacy_vim
-
- def setup(self, nvim):
- """Setup import hooks and global streams.
-
- This will add import hooks for importing modules from runtime
- directories and patch the sys module so 'print' calls will be
- forwarded to Nvim.
- """
- self.nvim = nvim
- info('install import hook/path')
- self.hook = path_hook(nvim)
- sys.path_hooks.append(self.hook)
- nvim.VIM_SPECIAL_PATH = '_vim_path_'
- sys.path.append(nvim.VIM_SPECIAL_PATH)
- info('redirect sys.stdout and sys.stderr')
- self.saved_stdout = sys.stdout
- self.saved_stderr = sys.stderr
- sys.stdout = RedirectStream(lambda data: nvim.out_write(data))
- sys.stderr = RedirectStream(lambda data: nvim.err_write(data))
-
- def teardown(self):
- """Restore state modified from the `setup` call."""
- for plugin in self.installed_plugins:
- if hasattr(plugin, 'on_teardown'):
- plugin.teardown()
- nvim = self.nvim
- info('uninstall import hook/path')
- sys.path.remove(nvim.VIM_SPECIAL_PATH)
- sys.path_hooks.remove(self.hook)
- info('restore sys.stdout and sys.stderr')
- sys.stdout = self.saved_stdout
- sys.stderr = self.saved_stderr
-
- @neovim.rpc_export('python_execute', sync=True)
- def python_execute(self, script, range_start, range_stop):
- """Handle the `python` ex command."""
- self._set_current_range(range_start, range_stop)
- exec(script, self.module.__dict__)
-
- @neovim.rpc_export('python_execute_file', sync=True)
- def python_execute_file(self, file_path, range_start, range_stop):
- """Handle the `pyfile` ex command."""
- self._set_current_range(range_start, range_stop)
- with open(file_path) as f:
- script = compile(f.read(), file_path, 'exec')
- exec(script, self.module.__dict__)
-
- @neovim.rpc_export('python_do_range', sync=True)
- def python_do_range(self, start, stop, code):
- """Handle the `pydo` ex command."""
- self._set_current_range(start, stop)
- nvim = self.nvim
- start -= 1
- stop -= 1
- fname = '_vim_pydo'
-
- # define the function
- function_def = 'def %s(line, linenr):\n %s' % (fname, code,)
- exec(function_def, self.module.__dict__)
- # get the function
- function = self.module.__dict__[fname]
- while start <= stop:
- # Process batches of 5000 to avoid the overhead of making multiple
- # API calls for every line. Assuming an average line length of 100
- # bytes, approximately 488 kilobytes will be transferred per batch,
- # which can be done very quickly in a single API call.
- sstart = start
- sstop = min(start + 5000, stop)
- lines = nvim.current.buffer.get_line_slice(sstart, sstop, True,
- True)
-
- exception = None
- newlines = []
- linenr = sstart + 1
- for i, line in enumerate(lines):
- result = function(line, linenr)
- if result is None:
- # Update earlier lines, and skip to the next
- if newlines:
- end = sstart + len(newlines) - 1
- nvim.current.buffer.set_line_slice(sstart, end,
- True, True,
- newlines)
- sstart += len(newlines) + 1
- newlines = []
- pass
- elif isinstance(result, basestring):
- newlines.append(result)
- else:
- exception = TypeError('pydo should return a string ' +
- 'or None, found %s instead'
- % result.__class__.__name__)
- break
- linenr += 1
-
- start = sstop + 1
- if newlines:
- end = sstart + len(newlines) - 1
- nvim.current.buffer.set_line_slice(sstart, end, True, True,
- newlines)
- if exception:
- raise exception
- # delete the function
- del self.module.__dict__[fname]
-
- @neovim.rpc_export('python_eval', sync=True)
- def python_eval(self, expr):
- """Handle the `pyeval` vim function."""
- return eval(expr, self.module.__dict__)
-
- def _set_current_range(self, start, stop):
- current = self.legacy_vim.current
- current.range = current.buffer.range(start, stop)
-
-
-class RedirectStream(io.IOBase):
- def __init__(self, redirect_handler):
- self.redirect_handler = redirect_handler
-
- def write(self, data):
- self.redirect_handler(data)
-
- def writelines(self, seq):
- self.redirect_handler('\n'.join(seq))
-
-
-class LegacyEvalHook(neovim.SessionHook):
-
- """Injects legacy `vim.eval` behavior to a Nvim instance."""
-
- def __init__(self):
- super(LegacyEvalHook, self).__init__(from_nvim=self._string_eval)
-
- def _string_eval(self, obj, session, method, kind):
- if method == 'vim_eval':
- if IS_PYTHON3:
- if isinstance(obj, (int, float)):
- return str(obj)
- elif isinstance(obj, (int, long, float)):
- return str(obj)
- return obj
-
-
-# This was copied/adapted from nvim-python help
-def path_hook(nvim):
- def _get_paths():
- return discover_runtime_directories(nvim)
-
- def _find_module(fullname, oldtail, path):
- idx = oldtail.find('.')
- if idx > 0:
- name = oldtail[:idx]
- tail = oldtail[idx+1:]
- fmr = imp.find_module(name, path)
- module = imp.find_module(fullname[:-len(oldtail)] + name, *fmr)
- return _find_module(fullname, tail, module.__path__)
- else:
- return imp.find_module(fullname, path)
-
- class VimModuleLoader(object):
- def __init__(self, module):
- self.module = module
-
- def load_module(self, fullname, path=None):
- # Check sys.modules, required for reload (see PEP302).
- if fullname in sys.modules:
- return sys.modules[fullname]
- return imp.load_module(fullname, *self.module)
-
- class VimPathFinder(object):
- @staticmethod
- def find_module(fullname, path=None):
- "Method for Python 2.7 and 3.3."
- try:
- return VimModuleLoader(
- _find_module(fullname, fullname, path or _get_paths()))
- except ImportError:
- return None
-
- @staticmethod
- def find_spec(fullname, path=None, target=None):
- "Method for Python 3.4+."
- return PathFinder.find_spec(fullname, path or _get_paths(), target)
-
- def hook(path):
- if path == nvim.VIM_SPECIAL_PATH:
- return VimPathFinder
- else:
- raise ImportError
-
- return hook
-
-
-def discover_runtime_directories(nvim):
- rv = []
- for path in nvim.list_runtime_paths():
- if not os.path.exists(path):
- continue
- path1 = os.path.join(path, 'pythonx')
- if IS_PYTHON3:
- path2 = os.path.join(path, 'python3')
- else:
- path2 = os.path.join(path, 'python2')
- if os.path.exists(path1):
- rv.append(path1)
- if os.path.exists(path2):
- rv.append(path2)
- return rv
diff --git a/runtime/autoload/remote/host.vim b/runtime/autoload/remote/host.vim
index 24497b10c2..1aead649a0 100644
--- a/runtime/autoload/remote/host.vim
+++ b/runtime/autoload/remote/host.vim
@@ -2,6 +2,7 @@ let s:hosts = {}
let s:plugin_patterns = {}
let s:remote_plugins_manifest = fnamemodify(expand($MYVIMRC, 1), ':h')
\.'/.'.fnamemodify($MYVIMRC, ':t').'-rplugin~'
+let s:plugins_for_host = {}
" Register a host by associating it with a factory(funcref)
@@ -35,6 +36,9 @@ endfunction
" Get a host channel, bootstrapping it if necessary
function! remote#host#Require(name) abort
+ if empty(s:plugins_for_host)
+ call remote#host#LoadRemotePlugins()
+ endif
if !has_key(s:hosts, a:name)
throw 'No host named "'.a:name.'" is registered'
endif
@@ -123,6 +127,13 @@ function! remote#host#LoadRemotePlugins() abort
endfunction
+function! remote#host#LoadRemotePluginsEvent(event, pattern) abort
+ autocmd! nvim-rplugin
+ call remote#host#LoadRemotePlugins()
+ execute 'silent doautocmd' a:event a:pattern
+endfunction
+
+
function! s:RegistrationCommands(host) abort
" Register a temporary host clone for discovering specs
let host_id = a:host.'-registration-clone'
@@ -138,7 +149,9 @@ function! s:RegistrationCommands(host) abort
endfor
let channel = remote#host#Require(host_id)
let lines = []
+ let registered = []
for path in paths
+ unlet! specs
let specs = rpcrequest(channel, 'specs', path)
if type(specs) != type([])
" host didn't return a spec list, indicates a failure while loading a
@@ -151,9 +164,10 @@ function! s:RegistrationCommands(host) abort
call add(lines, " \\ ".string(spec).",")
endfor
call add(lines, " \\ ])")
+ call add(registered, path)
endfor
echomsg printf("remote/host: %s host registered plugins %s",
- \ a:host, string(map(copy(paths), "fnamemodify(v:val, ':t')")))
+ \ a:host, string(map(registered, "fnamemodify(v:val, ':t')")))
" Delete the temporary host clone
call rpcstop(s:hosts[host_id].channel)
@@ -163,7 +177,7 @@ function! s:RegistrationCommands(host) abort
endfunction
-function! s:UpdateRemotePlugins() abort
+function! remote#host#UpdateRemotePlugins() abort
let commands = []
let hosts = keys(s:hosts)
for host in hosts
@@ -185,10 +199,6 @@ function! s:UpdateRemotePlugins() abort
endfunction
-command! UpdateRemotePlugins call s:UpdateRemotePlugins()
-
-
-let s:plugins_for_host = {}
function! remote#host#PluginsForHost(host) abort
if !has_key(s:plugins_for_host, a:host)
let s:plugins_for_host[a:host] = []
@@ -197,40 +207,25 @@ function! remote#host#PluginsForHost(host) abort
endfunction
-" Registration of standard hosts
-
-" Python/Python3 {{{
-function! s:RequirePythonHost(host) abort
- let ver = (a:host.orig_name ==# 'python') ? 2 : 3
-
- " Python host arguments
- let args = ['-c', 'import sys; sys.path.remove(""); import neovim; neovim.start_host()']
-
- " Collect registered Python plugins into args
- let python_plugins = remote#host#PluginsForHost(a:host.name)
- for plugin in python_plugins
- call add(args, plugin.path)
- endfor
-
- try
- let channel_id = rpcstart((ver == '2' ?
- \ provider#python#Prog() : provider#python3#Prog()), args)
- if rpcrequest(channel_id, 'poll') == 'ok'
- return channel_id
- endif
- catch
- echomsg v:throwpoint
- echomsg v:exception
- endtry
- throw 'Failed to load '. a:host.orig_name . ' host. '.
+function! remote#host#LoadErrorForHost(host, log) abort
+ return 'Failed to load '. a:host . ' host. '.
\ 'You can try to see what happened '.
\ 'by starting Neovim with the environment variable '.
- \ '$NVIM_PYTHON_LOG_FILE set to a file and opening '.
- \ 'the generated log file. Also, the host stderr will be available '.
+ \ a:log . ' set to a file and opening the generated '.
+ \ 'log file. Also, the host stderr will be available '.
\ 'in Neovim log, so it may contain useful information. '.
\ 'See also ~/.nvimlog.'
endfunction
-call remote#host#Register('python', '*.py', function('s:RequirePythonHost'))
-call remote#host#Register('python3', '*.py', function('s:RequirePythonHost'))
-" }}}
+
+" Registration of standard hosts
+
+" Python/Python3
+call remote#host#Register('python', '*',
+ \ function('provider#pythonx#Require'))
+call remote#host#Register('python3', '*',
+ \ function('provider#pythonx#Require'))
+
+" Ruby
+call remote#host#Register('ruby', '*.rb',
+ \ function('provider#ruby#Require'))
diff --git a/runtime/doc/autocmd.txt b/runtime/doc/autocmd.txt
index e17281821c..ec5818e16f 100644
--- a/runtime/doc/autocmd.txt
+++ b/runtime/doc/autocmd.txt
@@ -308,6 +308,8 @@ Name triggered by ~
|InsertCharPre| when a character was typed in Insert mode, before
inserting it
+|TextYankPost| when some text is yanked or deleted
+
|TextChanged| after a change was made to the text in Normal mode
|TextChangedI| after a change was made to the text in Insert mode
@@ -722,6 +724,18 @@ InsertCharPre When a character is typed in Insert mode,
It is not allowed to change the text |textlock|.
The event is not triggered when 'paste' is
set.
+ *TextYankPost*
+TextYankPost Just after a |yank| or |deleting| command, but not
+ if the black hole register |quote_| is used nor
+ for |setreg()|. Pattern must be * because its
+ meaning may change in the future.
+ Sets these |v:event| keys:
+ operator
+ regcontents
+ regname
+ regtype
+ Recursion is ignored.
+ It is not allowed to change the text |textlock|.
*InsertEnter*
InsertEnter Just before starting Insert mode. Also for
Replace mode and Virtual Replace mode. The
diff --git a/runtime/doc/eval.txt b/runtime/doc/eval.txt
index c478a217c1..f3192e108b 100644
--- a/runtime/doc/eval.txt
+++ b/runtime/doc/eval.txt
@@ -1391,6 +1391,22 @@ v:errors Errors found by assert functions, such as |assert_true()|.
< If v:errors is set to anything but a list it is made an empty
list by the assert function.
+ *v:event* *event-variable*
+v:event Dictionary of event data for the current |autocommand|. The
+ available keys differ per event type and are specified at the
+ documentation for each |event|. The possible keys are:
+ operator The operation performed. Unlike
+ |v:operator|, it is set also for an Ex
+ mode command. For instance, |:yank| is
+ translated to "|y|".
+ regcontents Text stored in the register as a
+ |readfile()|-style list of lines.
+ regname Requested register (e.g "x" for "xyy)
+ or the empty string for an unnamed
+ operation.
+ regtype Type of register as returned by
+ |getregtype()|.
+
*v:exception* *exception-variable*
v:exception The value of the exception most recently caught and not
finished. See also |v:throwpoint| and |throw-variables|.
@@ -1791,8 +1807,10 @@ cursor( {lnum}, {col} [, {off}])
cursor( {list}) Number move cursor to position in {list}
deepcopy( {expr} [, {noref}]) any make a full copy of {expr}
delete( {fname}) Number delete file {fname}
-dictwatcheradd({dict}, {pattern}, {callback}) Start watching a dictionary
-dictwatcherdel({dict}, {pattern}, {callback}) Stop watching a dictionary
+dictwatcheradd( {dict}, {pattern}, {callback})
+ Start watching a dictionary
+dictwatcherdel( {dict}, {pattern}, {callback})
+ Stop watching a dictionary
did_filetype() Number TRUE if FileType autocommand event used
diff_filler( {lnum}) Number diff filler lines about {lnum}
diff_hlID( {lnum}, {col}) Number diff highlighting at {lnum}/{col}
@@ -1812,7 +1830,7 @@ feedkeys( {string} [, {mode}]) Number add key sequence to typeahead buffer
filereadable( {file}) Number TRUE if {file} is a readable file
filewritable( {file}) Number TRUE if {file} is a writable file
filter( {expr}, {string}) List/Dict remove items from {expr} where
- {string} is 0
+ {string} is 0
finddir( {name}[, {path}[, {count}]])
String find directory {name} in {path}
findfile( {name}[, {path}[, {count}]])
@@ -1894,20 +1912,22 @@ inputdialog( {p} [, {t} [, {c}]]) String like input() but in a GUI dialog
inputlist( {textlist}) Number let the user pick from a choice list
inputrestore() Number restore typeahead
inputsave() Number save and clear typeahead
-inputsecret( {prompt} [, {text}]) String like input() but hiding the text
-insert( {list}, {item} [, {idx}]) List insert {item} in {list} [before {idx}]
+inputsecret( {prompt} [, {text}])
+ String like input() but hiding the text
+insert( {list}, {item} [, {idx}])
+ List insert {item} in {list} [before {idx}]
invert( {expr}) Number bitwise invert
isdirectory( {directory}) Number TRUE if {directory} is a directory
islocked( {expr}) Number TRUE if {expr} is locked
items( {dict}) List key-value pairs in {dict}
-jobclose({job}[, {stream}]) Number Closes a job stream(s)
-jobpid({job}) Number Returns pid of a job.
-jobresize({job}, {width}, {height})
+jobclose( {job}[, {stream}]) Number Closes a job stream(s)
+jobpid( {job}) Number Returns pid of a job.
+jobresize( {job}, {width}, {height})
Number Resize {job}'s pseudo terminal window
-jobsend({job}, {data}) Number Writes {data} to {job}'s stdin
-jobstart({cmd}[, {opts}]) Number Spawns {cmd} as a job
-jobstop({job}) Number Stops a job
-jobwait({ids}[, {timeout}]) Number Wait for a set of jobs
+jobsend( {job}, {data}) Number Writes {data} to {job}'s stdin
+jobstart( {cmd}[, {opts}]) Number Spawns {cmd} as a job
+jobstop( {job}) Number Stops a job
+jobwait( {ids}[, {timeout}]) Number Wait for a set of jobs
join( {list} [, {sep}]) String join {list} items into one String
keys( {dict}) List keys in {dict}
len( {expr}) Number the length of {expr}
@@ -1977,12 +1997,12 @@ repeat( {expr}, {count}) String repeat {expr} {count} times
resolve( {filename}) String get filename a shortcut points to
reverse( {list}) List reverse {list} in-place
round( {expr}) Float round off {expr}
-rpcnotify({channel}, {event}[, {args}...])
+rpcnotify( {channel}, {event}[, {args}...])
Sends a |msgpack-rpc| notification to {channel}
-rpcrequest({channel}, {method}[, {args}...])
+rpcrequest( {channel}, {method}[, {args}...])
Sends a |msgpack-rpc| request to {channel}
-rpcstart({prog}[, {argv}]) Spawns {prog} and opens a |msgpack-rpc| channel
-rpcstop({channel}) Closes a |msgpack-rpc| {channel}
+rpcstart( {prog}[, {argv}]) Spawns {prog} and opens a |msgpack-rpc| channel
+rpcstop( {channel}) Closes a |msgpack-rpc| {channel}
screenattr( {row}, {col}) Number attribute at screen position
screenchar( {row}, {col}) Number character at screen position
screencol() Number current cursor column
@@ -6243,12 +6263,22 @@ string({expr}) Return {expr} converted to a String. If {expr} is a Number,
{expr} type result ~
String 'string'
Number 123
- Float 123.123456 or 1.123456e8
- Funcref function('name')
+ Float 123.123456 or 1.123456e8 or
+ `str2float('inf')`
+ Funcref `function('name')`
List [item, item]
Dictionary {key: value, key: value}
Note that in String values the ' character is doubled.
Also see |strtrans()|.
+ Note 2: Output format is mostly compatible with YAML, except
+ for infinite and NaN floating-point values representations
+ which use |str2float()|. Strings are also dumped literally,
+ only single quote is escaped, which does not allow using YAML
+ for parsing back binary strings (including text when
+ 'encoding' is not UTF-8). |eval()| should always work for
+ strings and floats though and this is the only official
+ method, use |msgpackdump()| or |json_encode()| if you need to
+ share data with other application.
*strlen()*
strlen({expr}) The result is a Number, which is the length of the String
diff --git a/runtime/doc/options.txt b/runtime/doc/options.txt
index ced303947b..dbc87a8676 100644
--- a/runtime/doc/options.txt
+++ b/runtime/doc/options.txt
@@ -5538,6 +5538,9 @@ A jump table for the options with a short description can be found at |Q_op|.
c don't give |ins-completion-menu| messages. For example,
"-- XXX completion (YYY)", "match 1 of 2", "The only match",
"Pattern not found", "Back at original", etc.
+ q use "recording" instead of "recording @a"
+ F don't give the file info when editing a file, like `:silent`
+ was used for the command
This gives you the opportunity to avoid that a change between buffers
requires you to hit <Enter>, but still gives as useful a message as
diff --git a/runtime/doc/os_dos.txt b/runtime/doc/os_dos.txt
deleted file mode 100644
index 1601d65ffd..0000000000
--- a/runtime/doc/os_dos.txt
+++ /dev/null
@@ -1,279 +0,0 @@
-*os_dos.txt* For Vim version 7.4. Last change: 2006 Mar 30
-
-
- VIM REFERENCE MANUAL by Bram Moolenaar
-
-
- *dos* *DOS*
-This file documents some particularities of the Win32
-version of Vim. Also see |os_win32.txt|.
-
-1. File locations |dos-locations|
-2. Using backslashes |dos-backslash|
-3. Standard mappings |dos-standard-mappings|
-4. Screen output and colors |dos-colors|
-5. File formats |dos-file-formats|
-6. :cd command |dos-:cd|
-7. Interrupting |dos-CTRL-Break|
-8. Temp files |dos-temp-files|
-9. Shell option default |dos-shell|
-
-==============================================================================
-1. File locations *dos-locations*
-
-If you keep the Vim executable in the directory that contains the help and
-syntax subdirectories, there is no need to do anything special for Vim to
-work. No registry entries or environment variables need to be set. Just make
-sure that the directory is in your search path, or use a shortcut on the
-desktop.
-
-Your vimrc files ("_vimrc" and "_gvimrc") are normally located one directory
-up from the runtime files. If you want to put them somewhere else, set the
-environment variable $VIM to the directory where you keep them. Example: >
- set VIM=C:\user\piet
-Will find "c:\user\piet\_vimrc".
-Note: This would only be needed when the computer is used by several people.
-Otherwise it's simpler to keep your _vimrc file in the default place.
-
-If you move the executable to another location, you also need to set the $VIM
-environment variable. The runtime files will be found in "$VIM/vim{version}".
-Example: >
- set VIM=E:\vim
-Will find the version 5.4 runtime files in "e:\vim\vim54".
-Note: This is _not_ recommended. The preferred way is to keep the executable
-in the runtime directory.
-
-If you move your executable AND want to put your "_vimrc" and "_gvimrc" files
-somewhere else, you must set $VIM to where you vimrc files are, and set
-$VIMRUNTIME to the runtime files. Example: >
- set VIM=C:\usr\piet
- set VIMRUNTIME=E:\vim\vim54
-Will find "c:\user\piet\_vimrc" and the runtime files in "e:\vim\vim54".
-
-See |$VIM| and |$VIMRUNTIME| for more information.
-
-You can set environment variables for each user separately under
-"Start/Settings/Control Panel->System", or through the properties in the menu
-of "My Computer", under the Environment Tab.
-
-==============================================================================
-2. Using backslashes *dos-backslash*
-
-Using backslashes in file names can be a problem. Vi halves the number of
-backslashes for some commands. Vim is a bit more tolerant and does not remove
-backslashes from a file name, so ":e c:\foo\bar" works as expected. But when
-a backslash occurs before a special character (space, comma, backslash, etc.),
-Vim removes the backslash. Use slashes to avoid problems: ":e c:/foo/bar"
-works fine. Vim replaces the slashes with backslashes internally to avoid
-problems with some MS-DOS programs and Win32 programs.
-
-When you prefer to use forward slashes, set the 'shellslash' option. Vim will
-then replace backslashes with forward slashes when expanding file names. This
-is especially useful when using a Unix-like 'shell'.
-
-==============================================================================
-3. Standard mappings *dos-standard-mappings*
-
-The mappings for CTRL-PageUp and CTRL-PageDown have been removed, they now
-jump to the next or previous tab page |<C-PageUp>| |<C-PageDown>|
-
-If you want them to move to the first and last screen line you can use these
-mappings:
-
-key key code Normal/Visual mode Insert mode ~
-CTRL-PageUp <M-N><M-C-D> H <C-O>H
-CTRL-PageDown <M-N>v L$ <C-O>L<C-O>$
-
-Additionally, these keys are available for copy/cut/paste.
-In the Win32 version, they also use the clipboard.
-
-Shift-Insert paste text (from clipboard) *<S-Insert>*
-CTRL-Insert copy Visual text (to clipboard) *<C-Insert>*
-CTRL-Del cut Visual text (to clipboard) *<C-Del>*
-Shift-Del cut Visual text (to clipboard) *<S-Del>*
-
-These mappings accomplish this (Win32 version of Vim):
-
-key key code Normal Visual Insert ~
-Shift-Insert <M-N><M-T> "*P "-d"*P <C-R><C-O>*
-CTRL-Insert <M-N><M-U> "*y
-Shift-Del <M-N><M-W> "*d
-CTRL-Del <M-N><M-X> "*d
-
-Or these mappings (non-Win32 version of Vim):
-
-key key code Normal Visual Insert ~
-Shift-Insert <M-N><M-T> P "-dP <C-R><C-O>"
-CTRL-Insert <M-N><M-U> y
-Shift-Del <M-N><M-W> d
-CTRL-Del <M-N><M-X> d
-
-When the clipboard is supported, the "* register is used.
-
-==============================================================================
-4. Screen output and colors *dos-colors*
-
-The default output method for the screen is to use bios calls. This works
-right away on most systems. You do not need ansi.sys. You can use ":mode" to
-set the current screen mode. See |:mode|.
-
-To change the screen colors that Vim uses, you can use the |:highlight|
-command. The Normal highlight group specifies the colors Vim uses for normal
-text. For example, to get grey text on a blue background: >
- :hi Normal ctermbg=Blue ctermfg=grey
-See |highlight-groups| for other groups that are available.
-
-A DOS console does not support attributes like bold and underlining. You can
-set the color used in five modes with nine terminal options. Note that this
-is not necessary since you can set the color directly with the ":highlight"
-command; these options are for backward compatibility with older Vim versions.
-The |'highlight'| option specifies which of the five modes is used for which
-action. >
-
- :set t_mr=^V^[\|xxm start of invert mode
- :set t_md=^V^[\|xxm start of bold mode
- :set t_me=^V^[\|xxm back to normal text
-
- :set t_so=^V^[\|xxm start of standout mode
- :set t_se=^V^[\|xxm back to normal text
-
- :set t_us=^V^[\|xxm start of underline mode
- :set t_ue=^V^[\|xxm back to normal text
-
- :set t_ZH=^V^[\|xxm start of italics mode
- :set t_ZR=^V^[\|xxm back to normal text
-
-^V is CTRL-V
-^[ is <Esc>
-You must replace xx with a decimal code, which is the foreground color number
-and background color number added together:
-
-COLOR FOREGROUND BACKGROUND ~
-Black 0 0
-DarkBlue 1 16
-DarkGreen 2 32
-DarkCyan 3 48
-DarkRed 4 64
-DarkMagenta 5 80
-Brown, DarkYellow 6 96
-LightGray 7 112
-DarkGray 8 128 *
-Blue, LightBlue 9 144 *
-Green, LightGreen 10 160 *
-Cyan, LightCyan 11 176 *
-Red, LightRed 12 192 *
-Magenta, LightMagenta 13 208 *
-Yellow, LightYellow 14 224 *
-White 15 240 *
-
-* Depending on the display mode, the color codes above 128 may not be
- available, and code 128 will make the text blink.
-
-When you use 0, the color is reset to the one used when you started Vim
-(usually 7, lightgray on black, but you can override this. If you have
-overridden the default colors in a command prompt, you may need to adjust
-some of the highlight colors in your vimrc---see below).
-This is the default for t_me.
-
-The defaults for the various highlight modes are:
- t_mr 112 reverse mode: Black text (0) on LightGray (112)
- t_md 15 bold mode: White text (15) on Black (0)
- t_me 0 normal mode (revert to default)
-
- t_so 31 standout mode: White (15) text on DarkBlue (16)
- t_se 0 standout mode end (revert to default)
-
- t_czh 225 italic mode: DarkBlue text (1) on Yellow (224)
- t_czr 0 italic mode end (revert to default)
-
- t_us 67 underline mode: DarkCyan text (3) on DarkRed (64)
- t_ue 0 underline mode end (revert to default)
-
-These colors were chosen because they also look good when using an inverted
-display, but you can change them to your liking.
-
-Example: >
- :set t_mr=^V^[\|97m " start of invert mode: DarkBlue (1) on Brown (96)
- :set t_md=^V^[\|67m " start of bold mode: DarkCyan (3) on DarkRed (64)
- :set t_me=^V^[\|112m " back to normal mode: Black (0) on LightGray (112)
-
- :set t_so=^V^[\|37m " start of standout mode: DarkMagenta (5) on DarkGreen
- (32)
- :set t_se=^V^[\|112m " back to normal mode: Black (0) on LightGray (112)
-
-==============================================================================
-5. File formats *dos-file-formats*
-
-If the 'fileformat' option is set to "dos" (which is the default), Vim accepts
-a single <NL> or a <CR><NL> pair for end-of-line (<EOL>). When writing a
-file, Vim uses <CR><NL>. Thus, if you edit a file and write it, Vim replaces
-<NL> with <CR><NL>.
-
-If the 'fileformat' option is set to "unix", Vim uses a single <NL> for <EOL>
-and shows <CR> as ^M.
-
-You can use Vim to replace <NL> with <CR><NL> by reading in any mode and
-writing in Dos mode (":se ff=dos").
-You can use Vim to replace <CR><NL> with <NL> by reading in Dos mode and
-writing in Unix mode (":se ff=unix").
-
-Vim sets 'fileformat' automatically when 'fileformats' is not empty (which is
-the default), so you don't really have to worry about what you are doing.
- |'fileformat'| |'fileformats'|
-
-If you want to edit a script file or a binary file, you should set the
-'binary' option before loading the file. Script files and binary files may
-contain single <NL> characters which Vim would replace with <CR><NL>. You can
-set 'binary' automatically by starting Vim with the "-b" (binary) option.
-
-==============================================================================
-6. :cd command *dos-:cd*
-
-The ":cd" command recognizes the drive specifier and changes the current
-drive. Use ":cd c:" to make drive C the active drive. Use ":cd d:\foo" to go
-to the directory "foo" in the root of drive D. Vim also recognizes UNC names
-if the system supports them; e.g., ":cd \\server\share\dir". |:cd|
-
-==============================================================================
-7. Interrupting *dos-CTRL-Break*
-
-Use CTRL-Break instead of CTRL-C to interrupt searches. Vim does not detect
-the CTRL-C until it tries to read a key.
-
-==============================================================================
-8. Temp files *dos-temp-files*
-
-Vim uses standard Windows functions to obtain a temporary file name (for
-filtering). The first of these directories that exists and in which Vim can
-create a file is used:
- $TMP
- $TEMP
- current directory
-
-==============================================================================
-9. Shell option default *dos-shell*
-
-The default for the 'sh' ('shell') option is "cmd.exe" on Windows.
-If SHELL is defined, Vim uses SHELL instead, and if SHELL is not defined
-but COMSPEC is, Vim uses COMSPEC. Vim starts external commands with
-"<shell> /c <command_name>". Typing CTRL-Z starts a new command
-subshell. Return to Vim with "exit". |'shell'| |CTRL-Z|
-
-If you are running a third-party shell, you may need to set the
-|'shellcmdflag'| ('shcf') and |'shellquote'| ('shq') or |'shellxquote'|
-('sxq') options. Unfortunately, this also depends on the version of Vim used.
-For example, with the MKS Korn shell or with bash, the values of the options
-on Win32 should be:
-
-'shellcmdflag' -c
-'shellquote' (empty)
-'shellxquote' "
-
-For Win32, this starts the shell as:
- <shell> -c "command name >file"
-
-When starting up, Vim checks for the presence of "sh" anywhere in the 'shell'
-option. If it is present, Vim sets the 'shellcmdflag' and 'shellquote' or
-'shellxquote' options will be set as described above.
-
- vim:tw=78:ts=8:ft=help:norl:
diff --git a/runtime/doc/repeat.txt b/runtime/doc/repeat.txt
index 21b5eef811..b2e935eb3f 100644
--- a/runtime/doc/repeat.txt
+++ b/runtime/doc/repeat.txt
@@ -109,6 +109,12 @@ q{0-9a-zA-Z"} Record typed characters into register {0-9a-zA-Z"}
while executing a register, and it doesn't work inside
a mapping and |:normal|.
+ Note: If the register being used for recording is also
+ used for |y| and |p| the result is most likely not
+ what is expected, because the put will paste the
+ recorded macro and the yank will overwrite the
+ recorded macro.
+
q Stops recording.
Implementation note: The 'q' that stops recording is
not stored in the register, unless it was the result
diff --git a/runtime/doc/starting.txt b/runtime/doc/starting.txt
index be108d4633..37593aef43 100644
--- a/runtime/doc/starting.txt
+++ b/runtime/doc/starting.txt
@@ -380,6 +380,8 @@ accordingly. Vim proceeds in this order:
Places for your personal initializations:
Unix $XDG_CONFIG_HOME/nvim/init.vim
(default for $XDG_CONFIG_HOME is ~/.config)
+ Windows $XDG_CONFIG_HOME/nvim/init.vim
+ (default for $XDG_CONFIG_HOME is ~/AppData/Local)
The files are searched in the order specified above and only the first
one that is found is read.
diff --git a/runtime/doc/usr_05.txt b/runtime/doc/usr_05.txt
index 86fcf0cc2f..5aecf33557 100644
--- a/runtime/doc/usr_05.txt
+++ b/runtime/doc/usr_05.txt
@@ -37,9 +37,10 @@ for you), you can edit it this way: >
If you don't have a vimrc file yet, see |init.vim| to find out where you can
create a vimrc file.
-For Unix and Macintosh this file is always used and is recommended:
+This file is always used and is recommended:
- ~/.config/nvim/init.vim ~
+ ~/.config/nvim/init.vim (Unix and OSX) ~
+ ~/AppData/Local/nvim/init.vim (Windows) ~
The vimrc file can contain all the commands that you type after a colon. The
most simple ones are for setting options. For example, if you want Vim to
diff --git a/runtime/doc/usr_06.txt b/runtime/doc/usr_06.txt
index 1cb3eb8673..b4b495ff9f 100644
--- a/runtime/doc/usr_06.txt
+++ b/runtime/doc/usr_06.txt
@@ -152,7 +152,7 @@ You could also write your own color scheme. This is how you do it:
directory. For Unix, this should work: >
!mkdir -p ~/.config/nvim/colors
- !cp $VIMRUNTIME/colors/morning.vim ~/.vim/colors/mine.vim
+ !cp $VIMRUNTIME/colors/morning.vim ~/.config/nvim/colors/mine.vim
<
This is done from Vim, because it knows the value of $VIMRUNTIME.
diff --git a/runtime/doc/various.txt b/runtime/doc/various.txt
index ff37466a14..3f53e3f507 100644
--- a/runtime/doc/various.txt
+++ b/runtime/doc/various.txt
@@ -222,6 +222,10 @@ g8 Print the hex values of the bytes used in the
modified, but can be forced with "!". See |termopen()|
and |nvim-terminal-emulator| for more information.
+ To switch to terminal mode automatically:
+>
+ autocmd BufEnter term://* startinsert
+<
*:!cmd* *:!* *E34*
:!{cmd} Execute {cmd} with 'shell'. See also |:terminal|.
diff --git a/runtime/doc/vim_diff.txt b/runtime/doc/vim_diff.txt
index d3768409f5..17e16911bc 100644
--- a/runtime/doc/vim_diff.txt
+++ b/runtime/doc/vim_diff.txt
@@ -21,10 +21,10 @@ these differences.
==============================================================================
1. Configuration *nvim-configuration*
-- Use `$XDG_CONFIG_HOME/nvim/init.vim` instead of `.vimrc` for storing
+- Use `$XDG_CONFIG_HOME/nvim/init.vim` instead of `.vimrc` for storing
configuration.
- Use `$XDG_CONFIG_HOME/nvim` instead of `.vim` to store configuration files.
-- Use `$XDG_DATA_HOME/nvim/shada/main.shada` instead of `.viminfo` for persistent
+- Use `$XDG_DATA_HOME/nvim/shada/main.shada` instead of `.viminfo` for persistent
session information.
==============================================================================
@@ -73,54 +73,56 @@ are always available and may be used simultaneously in separate plugins. The
|nvim-python|).
|mkdir()| behaviour changed:
-1. Assuming /tmp/foo does not exist and /tmp can be written to
+1. Assuming /tmp/foo does not exist and /tmp can be written to
mkdir('/tmp/foo/bar', 'p', 0700) will create both /tmp/foo and /tmp/foo/bar
with 0700 permissions. Vim mkdir will create /tmp/foo with 0755.
-2. If you try to create an existing directory with `'p'` (e.g. mkdir('/',
+2. If you try to create an existing directory with `'p'` (e.g. mkdir('/',
'p')) mkdir() will silently exit. In Vim this was an error.
3. mkdir() error messages now include strerror() text when mkdir fails.
'encoding' cannot be changed after startup.
|string()| and |:echo| behaviour changed:
-1. No maximum recursion depth limit is applied to nested container
+1. No maximum recursion depth limit is applied to nested container
structures.
-2. |string()| fails immediately on nested containers, not when recursion limit
+2. |string()| fails immediately on nested containers, not when recursion limit
was exceeded.
2. When |:echo| encounters duplicate containers like >
let l = []
echo [l, l]
<
- it does not use "[...]" (was: "[[], [...]]", now: "[[], []]"). "..." is
+ it does not use "[...]" (was: "[[], [...]]", now: "[[], []]"). "..." is
only used for recursive containers.
-3. |:echo| printing nested containers adds "@level" after "..." designating
- the level at which recursive container was printed: |:echo-self-refer|.
- Same thing applies to |string()| (though it uses construct like
- "{E724@level}"), but this is not reliable because |string()| continues to
+3. |:echo| printing nested containers adds "@level" after "..." designating
+ the level at which recursive container was printed: |:echo-self-refer|.
+ Same thing applies to |string()| (though it uses construct like
+ "{E724@level}"), but this is not reliable because |string()| continues to
error out.
+4. Stringifyed infinite and NaN values now use |str2float()| and can be evaled
+ back.
-Viminfo text files were replaced with binary (messagepack) ShaDa files.
+Viminfo text files were replaced with binary (messagepack) ShaDa files.
Additional differences:
- |shada-c| has no effect.
- |shada-s| now limits size of every item and not just registers.
-- When reading ShaDa files items are merged according to the timestamp.
+- When reading ShaDa files items are merged according to the timestamp.
|shada-merging|
-- 'viminfo' option got renamed to 'shada'. Old option is kept as an alias for
+- 'viminfo' option got renamed to 'shada'. Old option is kept as an alias for
compatibility reasons.
-- |:wviminfo| was renamed to |:wshada|, |:rviminfo| to |:rshada|. Old
+- |:wviminfo| was renamed to |:wshada|, |:rviminfo| to |:rshada|. Old
commands are still kept.
- |:oldfiles| supports !.
-- When writing (|:wshada| without bang or at exit) it merges much more data,
- and does this according to the timestamp. Vim merges only marks.
+- When writing (|:wshada| without bang or at exit) it merges much more data,
+ and does this according to the timestamp. Vim merges only marks.
|shada-merging|
-- ShaDa file format was designed with forward and backward compatibility in
+- ShaDa file format was designed with forward and backward compatibility in
mind. |shada-compatibility|
-- Some errors make ShaDa code keep temporary file in-place for user to decide
- what to do with it. Vim deletes temporary file in these cases.
+- Some errors make ShaDa code keep temporary file in-place for user to decide
+ what to do with it. Vim deletes temporary file in these cases.
|shada-error-handling|
-- Vim keeps no timestamps at all, neither in viminfo file nor in the instance
+- Vim keeps no timestamps at all, neither in viminfo file nor in the instance
itself.
- ShaDa file keeps search direction (|v:searchforward|), viminfo does not.
@@ -139,8 +141,8 @@ Meta (alt) chords are recognized (even in the terminal).
Note: Meta chords are case-sensitive (<M-a> is distinguished from <M-A>).
-Some `CTRL-SHIFT-...` key chords are distinguished from `CTRL-...` variants (even in
-the terminal). Specifically, the following are known to work:
+Some `CTRL-SHIFT-...` key chords are distinguished from `CTRL-...` variants
+(even in the terminal). Specifically, the following are known to work:
<C-Tab>, <C-S-Tab>
<C-BS>, <C-S-BS>
<C-Enter>, <C-S-Enter>
diff --git a/runtime/doc/windows.txt b/runtime/doc/windows.txt
index eee171b7da..29c8aaf808 100644
--- a/runtime/doc/windows.txt
+++ b/runtime/doc/windows.txt
@@ -706,7 +706,7 @@ can also get to them with the buffer list commands, like ":bnext".
*:bufdo*
:[range]bufdo[!] {cmd} Execute {cmd} in each buffer in the buffer list or if
- [range[ is given only for buffers for which their
+ [range] is given only for buffers for which their
buffer name is in the [range]. It works like doing
this: >
:bfirst
diff --git a/runtime/ftplugin/man.vim b/runtime/ftplugin/man.vim
index 133a28e626..36cd70f203 100644
--- a/runtime/ftplugin/man.vim
+++ b/runtime/ftplugin/man.vim
@@ -24,11 +24,11 @@ setlocal buftype=nofile noswapfile
setlocal nomodifiable readonly bufhidden=hide nobuflisted tabstop=8
if !exists("g:no_plugin_maps") && !exists("g:no_man_maps")
- nnoremap <silent> <buffer> <C-]> :call man#get_page(v:count)<CR>
+ nnoremap <silent> <buffer> <C-]> :call man#get_page(v:count, expand('<cword>'))<CR>
nnoremap <silent> <buffer> <C-T> :call man#pop_page()<CR>
nnoremap <silent> <nowait><buffer> q <C-W>c
if &keywordprg !=# ':Man'
- nnoremap <silent> <buffer> K :call man#get_page(v:count)<CR>
+ nnoremap <silent> <buffer> K :call man#get_page(v:count, expand('<cword>'))<CR>
endif
endif
diff --git a/runtime/macros/less.bat b/runtime/macros/less.bat
index bbe619bc92..7395a70003 100644
--- a/runtime/macros/less.bat
+++ b/runtime/macros/less.bat
@@ -4,7 +4,7 @@ rem Read stdin if no arguments were given.
rem Written by Ken Takata.
if "%1"=="" (
- vim --cmd "let no_plugin_maps = 1" -c "runtime! macros/less.vim" -
+ nvim --cmd "let no_plugin_maps = 1" -c "runtime! macros/less.vim" -
) else (
- vim --cmd "let no_plugin_maps = 1" -c "runtime! macros/less.vim" %*
+ nvim --cmd "let no_plugin_maps = 1" -c "runtime! macros/less.vim" %*
)
diff --git a/runtime/macros/less.sh b/runtime/macros/less.sh
index e29958f7ad..125162f10a 100755
--- a/runtime/macros/less.sh
+++ b/runtime/macros/less.sh
@@ -8,9 +8,9 @@ if test -t 1; then
echo "Missing filename" 1>&2
exit
fi
- vim --cmd 'let no_plugin_maps = 1' -c 'runtime! macros/less.vim' -
+ nvim --cmd 'let no_plugin_maps = 1' -c 'runtime! macros/less.vim' -
else
- vim --cmd 'let no_plugin_maps = 1' -c 'runtime! macros/less.vim' "$@"
+ nvim --cmd 'let no_plugin_maps = 1' -c 'runtime! macros/less.vim' "$@"
fi
else
# Output is not a terminal, cat arguments or stdin
diff --git a/runtime/plugin/rplugin.vim b/runtime/plugin/rplugin.vim
index 879775ff0e..b4b03032b3 100644
--- a/runtime/plugin/rplugin.vim
+++ b/runtime/plugin/rplugin.vim
@@ -1,5 +1,16 @@
-if exists('g:loaded_remote_plugins') || &cp
+if exists('g:loaded_remote_plugins')
finish
endif
let g:loaded_remote_plugins = 1
-call remote#host#LoadRemotePlugins()
+
+command! UpdateRemotePlugins call remote#host#UpdateRemotePlugins()
+
+augroup nvim-rplugin
+ autocmd!
+ autocmd FuncUndefined *
+ \ call remote#host#LoadRemotePluginsEvent(
+ \ 'FuncUndefined', expand('<amatch>'))
+ autocmd CmdUndefined *
+ \ call remote#host#LoadRemotePluginsEvent(
+ \ 'CmdUndefined', expand('<amatch>'))
+augroup END
diff --git a/scripts/vim-patch.sh b/scripts/vim-patch.sh
index 7612a2ada0..4dc24a8cdf 100755
--- a/scripts/vim-patch.sh
+++ b/scripts/vim-patch.sh
@@ -65,7 +65,7 @@ get_vim_sources() {
if [[ ! -d ${VIM_SOURCE_DIR} ]]; then
echo "Cloning Vim sources into '${VIM_SOURCE_DIR}'."
- git clone --depth=1000 https://github.com/vim/vim.git "${VIM_SOURCE_DIR}"
+ git clone https://github.com/vim/vim.git "${VIM_SOURCE_DIR}"
cd "${VIM_SOURCE_DIR}"
else
if [[ ! -d "${VIM_SOURCE_DIR}/.git" ]]; then
@@ -243,7 +243,7 @@ list_vim_patches() {
local patch_number="${vim_tag:5}" # Remove prefix like "v7.4."
# Tagged Vim patch, check version.c:
is_missing="$(sed -n '/static int included_patches/,/}/p' "${NEOVIM_SOURCE_DIR}/src/nvim/version.c" |
- grep -x -e "[[:space:]]*//[[:space:]]${patch_number} NA" -e "[[:space:]]*${patch_number}," >/dev/null && echo "false" || echo "true")"
+ grep -x -e "[[:space:]]*//[[:space:]]${patch_number} NA.*" -e "[[:space:]]*${patch_number}," >/dev/null && echo "false" || echo "true")"
vim_commit="${vim_tag#v}"
else
# Untagged Vim patch (e.g. runtime updates), check the Neovim git log:
diff --git a/src/.clang-format b/src/.clang-format
index 35e545ac4b..5a910ff34b 100644
--- a/src/.clang-format
+++ b/src/.clang-format
@@ -1,4 +1,4 @@
-BasedOnStyle: llvm
+BasedOnStyle: Google
Language: Cpp
ColumnLimit: 80
IndentWidth: 2
@@ -10,3 +10,9 @@ AlignEscapedNewlinesLeft: false
AllowShortFunctionsOnASingleLine: false
SpacesBeforeTrailingComments: 2
PenaltyReturnTypeOnItsOwnLine: 200
+AllowAllParametersOfDeclarationOnNextLine: false
+AllowShortIfStatementsOnASingleLine: false
+AllowShortLoopsOnASingleLine: false
+BinPackParameters: false
+BreakBeforeBinaryOperators: true
+ContinuationIndentWidth: 4
diff --git a/src/nvim/CMakeLists.txt b/src/nvim/CMakeLists.txt
index ea5125e4e7..487b554d6d 100644
--- a/src/nvim/CMakeLists.txt
+++ b/src/nvim/CMakeLists.txt
@@ -60,6 +60,11 @@ file(GLOB NEOVIM_SOURCES *.c os/*.c api/*.c api/private/*.c msgpack_rpc/*.c
file(GLOB_RECURSE NEOVIM_HEADERS *.h)
file(GLOB UNIT_TEST_FIXTURES ${PROJECT_SOURCE_DIR}/test/unit/fixtures/*.c)
+# Sort file lists to ensure generated files are created in the same order from
+# build to build.
+list(SORT NEOVIM_SOURCES)
+list(SORT NEOVIM_HEADERS)
+
foreach(sfile ${NEOVIM_SOURCES})
get_filename_component(f ${sfile} NAME)
if(${f} MATCHES "^(regexp_nfa.c)$")
@@ -72,11 +77,9 @@ list(REMOVE_ITEM NEOVIM_SOURCES ${to_remove})
# Handle legacy files that don't yet pass -Wconversion.
set(CONV_SOURCES
buffer.c
- charset.c
diff.c
edit.c
eval.c
- ex_cmds2.c
ex_cmds.c
ex_docmd.c
ex_getln.c
@@ -87,8 +90,6 @@ set(CONV_SOURCES
message.c
misc1.c
ops.c
- path.c
- quickfix.c
regexp.c
screen.c
search.c
diff --git a/src/nvim/api/buffer.c b/src/nvim/api/buffer.c
index fa4b8e5f7d..c25a9789c5 100644
--- a/src/nvim/api/buffer.c
+++ b/src/nvim/api/buffer.c
@@ -45,14 +45,22 @@ Integer buffer_line_count(Buffer buffer, Error *err)
/// Gets a buffer line
///
+/// @deprecated use buffer_get_lines instead.
+/// for positive indices (including 0) use
+/// "buffer_get_lines(buffer, index, index+1, true)"
+/// for negative indices use
+/// "buffer_get_lines(buffer, index-1, index, true)"
+///
/// @param buffer The buffer handle
/// @param index The line index
/// @param[out] err Details of an error that may have occurred
/// @return The line string
String buffer_get_line(Buffer buffer, Integer index, Error *err)
{
- String rv = {.size = 0};
- Array slice = buffer_get_line_slice(buffer, index, index, true, true, err);
+ String rv = { .size = 0 };
+
+ index = convert_index(index);
+ Array slice = buffer_get_lines(buffer, index, index+1, true, err);
if (!err->set && slice.size) {
rv = slice.items[0].data.string;
@@ -65,6 +73,12 @@ String buffer_get_line(Buffer buffer, Integer index, Error *err)
/// Sets a buffer line
///
+/// @deprecated use buffer_set_lines instead.
+/// for positive indices use
+/// "buffer_set_lines(buffer, index, index+1, true, [line])"
+/// for negative indices use
+/// "buffer_set_lines(buffer, index-1, index, true, [line])"
+///
/// @param buffer The buffer handle
/// @param index The line index
/// @param line The new line.
@@ -72,23 +86,34 @@ String buffer_get_line(Buffer buffer, Integer index, Error *err)
void buffer_set_line(Buffer buffer, Integer index, String line, Error *err)
{
Object l = STRING_OBJ(line);
- Array array = {.items = &l, .size = 1};
- buffer_set_line_slice(buffer, index, index, true, true, array, err);
+ Array array = { .items = &l, .size = 1 };
+ index = convert_index(index);
+ buffer_set_lines(buffer, index, index+1, true, array, err);
}
/// Deletes a buffer line
///
+/// @deprecated use buffer_set_lines instead.
+/// for positive indices use
+/// "buffer_set_lines(buffer, index, index+1, true, [])"
+/// for negative indices use
+/// "buffer_set_lines(buffer, index-1, index, true, [])"
/// @param buffer The buffer handle
/// @param index The line index
/// @param[out] err Details of an error that may have occurred
void buffer_del_line(Buffer buffer, Integer index, Error *err)
{
Array array = ARRAY_DICT_INIT;
- buffer_set_line_slice(buffer, index, index, true, true, array, err);
+ index = convert_index(index);
+ buffer_set_lines(buffer, index, index+1, true, array, err);
}
/// Retrieves a line range from the buffer
///
+/// @deprecated use buffer_get_lines(buffer, newstart, newend, false)
+/// where newstart = start + int(not include_start) - int(start < 0)
+/// newend = end + int(include_end) - int(end < 0)
+/// int(bool) = 1 if bool is true else 0
/// @param buffer The buffer handle
/// @param start The first line index
/// @param end The last line index
@@ -103,16 +128,48 @@ ArrayOf(String) buffer_get_line_slice(Buffer buffer,
Boolean include_end,
Error *err)
{
+ start = convert_index(start) + !include_start;
+ end = convert_index(end) + include_end;
+ return buffer_get_lines(buffer, start , end, false, err);
+}
+
+
+/// Retrieves a line range from the buffer
+///
+/// Indexing is zero-based, end-exclusive. Negative indices are interpreted
+/// as length+1+index, i e -1 refers to the index past the end. So to get the
+/// last element set start=-2 and end=-1.
+///
+/// Out-of-bounds indices are clamped to the nearest valid value, unless
+/// `strict_indexing` is set.
+///
+/// @param buffer The buffer handle
+/// @param start The first line index
+/// @param end The last line index (exclusive)
+/// @param strict_indexing whether out-of-bounds should be an error.
+/// @param[out] err Details of an error that may have occurred
+/// @return An array of lines
+ArrayOf(String) buffer_get_lines(Buffer buffer,
+ Integer start,
+ Integer end,
+ Boolean strict_indexing,
+ Error *err)
+{
Array rv = ARRAY_DICT_INIT;
buf_T *buf = find_buffer_by_handle(buffer, err);
- if (!buf || !inbounds(buf, start)) {
+ if (!buf) {
return rv;
}
- start = normalize_index(buf, start) + (include_start ? 0 : 1);
- include_end = include_end || (end >= buf->b_ml.ml_line_count);
- end = normalize_index(buf, end) + (include_end ? 1 : 0);
+ bool oob = false;
+ start = normalize_index(buf, start, &oob);
+ end = normalize_index(buf, end, &oob);
+
+ if (strict_indexing && oob) {
+ api_set_error(err, Validation, _("Index out of bounds"));
+ return rv;
+ }
if (start >= end) {
// Return 0-length array
@@ -152,8 +209,14 @@ end:
return rv;
}
+
/// Replaces a line range on the buffer
///
+/// @deprecated use buffer_set_lines(buffer, newstart, newend, false, lines)
+/// where newstart = start + int(not include_start) + int(start < 0)
+/// newend = end + int(include_end) + int(end < 0)
+/// int(bool) = 1 if bool is true else 0
+///
/// @param buffer The buffer handle
/// @param start The first line index
/// @param end The last line index
@@ -170,20 +233,52 @@ void buffer_set_line_slice(Buffer buffer,
ArrayOf(String) replacement,
Error *err)
{
+ start = convert_index(start) + !include_start;
+ end = convert_index(end) + include_end;
+ buffer_set_lines(buffer, start, end, false, replacement, err);
+}
+
+
+/// Replaces line range on the buffer
+///
+/// Indexing is zero-based, end-exclusive. Negative indices are interpreted
+/// as length+1+index, i e -1 refers to the index past the end. So to change
+/// or delete the last element set start=-2 and end=-1.
+///
+/// To insert lines at a given index, set both start and end to the same index.
+/// To delete a range of lines, set replacement to an empty array.
+///
+/// Out-of-bounds indices are clamped to the nearest valid value, unless
+/// `strict_indexing` is set.
+///
+/// @param buffer The buffer handle
+/// @param start The first line index
+/// @param end The last line index (exclusive)
+/// @param strict_indexing whether out-of-bounds should be an error.
+/// @param replacement An array of lines to use as replacement
+/// @param[out] err Details of an error that may have occurred
+void buffer_set_lines(Buffer buffer,
+ Integer start,
+ Integer end,
+ Boolean strict_indexing,
+ ArrayOf(String) replacement,
+ Error *err)
+{
buf_T *buf = find_buffer_by_handle(buffer, err);
if (!buf) {
return;
}
- if (!inbounds(buf, start)) {
+ bool oob = false;
+ start = normalize_index(buf, start, &oob);
+ end = normalize_index(buf, end, &oob);
+
+ if (strict_indexing && oob) {
api_set_error(err, Validation, _("Index out of bounds"));
return;
}
- start = normalize_index(buf, start) + (include_start ? 0 : 1);
- include_end = include_end || (end >= buf->b_ml.ml_line_count);
- end = normalize_index(buf, end) + (include_end ? 1 : 0);
if (start > end) {
api_set_error(err,
@@ -457,6 +552,8 @@ Boolean buffer_is_valid(Buffer buffer)
/// Inserts a sequence of lines to a buffer at a certain index
///
+/// @deprecated use buffer_set_lines(buffer, lnum, lnum, true, lines)
+///
/// @param buffer The buffer handle
/// @param lnum Insert the lines after `lnum`. If negative, it will append
/// to the end of the buffer.
@@ -467,8 +564,9 @@ void buffer_insert(Buffer buffer,
ArrayOf(String) lines,
Error *err)
{
- bool end_start = lnum < 0;
- buffer_set_line_slice(buffer, lnum, lnum, !end_start, end_start, lines, err);
+ // "lnum" will be the index of the line after inserting,
+ // no matter if it is negative or not
+ buffer_set_lines(buffer, lnum, lnum, true, lines, err);
}
/// Return a tuple (row,col) representing the position of the named mark
@@ -632,20 +730,26 @@ static void fix_cursor(linenr_T lo, linenr_T hi, linenr_T extra)
}
// Normalizes 0-based indexes to buffer line numbers
-static int64_t normalize_index(buf_T *buf, int64_t index)
+static int64_t normalize_index(buf_T *buf, int64_t index, bool *oob)
{
+ int64_t line_count = buf->b_ml.ml_line_count;
// Fix if < 0
- index = index < 0 ? buf->b_ml.ml_line_count + index : index;
+ index = index < 0 ? line_count + index +1 : index;
+
+ // Check for oob
+ if (index > line_count) {
+ *oob = true;
+ index = line_count;
+ } else if (index < 0) {
+ *oob = true;
+ index = 0;
+ }
// Convert the index to a vim line number
index++;
- // Fix if > line_count
- index = index > buf->b_ml.ml_line_count ? buf->b_ml.ml_line_count : index;
return index;
}
-// Returns true if the 0-indexed `index` is within the 1-indexed buffer bounds.
-static bool inbounds(buf_T *buf, int64_t index)
+static int64_t convert_index(int64_t index)
{
- linenr_T nlines = buf->b_ml.ml_line_count;
- return index >= -nlines && index < nlines;
+ return index < 0 ? index - 1 : index;
}
diff --git a/src/nvim/auevents.lua b/src/nvim/auevents.lua
index aa4a8d8332..8d891effae 100644
--- a/src/nvim/auevents.lua
+++ b/src/nvim/auevents.lua
@@ -83,6 +83,7 @@ return {
'TermResponse', -- after setting "v:termresponse"
'TextChanged', -- text was modified
'TextChangedI', -- text was modified in Insert mode
+ 'TextYankPost', -- after a yank or delete was done (y, d, c)
'User', -- user defined autocommand
'VimEnter', -- after starting Vim
'VimLeave', -- before exiting Vim
diff --git a/src/nvim/buffer.c b/src/nvim/buffer.c
index 62ab7495da..c514c4378e 100644
--- a/src/nvim/buffer.c
+++ b/src/nvim/buffer.c
@@ -141,14 +141,21 @@ open_buffer (
/* mark cursor position as being invalid */
curwin->w_valid = 0;
- if (curbuf->b_ffname != NULL
- ) {
+ if (curbuf->b_ffname != NULL) {
+ int old_msg_silent = msg_silent;
+ if (shortmess(SHM_FILEINFO)) {
+ msg_silent = 1;
+ }
+
retval = readfile(curbuf->b_ffname, curbuf->b_fname,
- (linenr_T)0, (linenr_T)0, (linenr_T)MAXLNUM, eap,
- flags | READ_NEW);
- /* Help buffer is filtered. */
- if (curbuf->b_help)
+ (linenr_T)0, (linenr_T)0, (linenr_T)MAXLNUM, eap,
+ flags | READ_NEW);
+ msg_silent = old_msg_silent;
+
+ // Help buffer is filtered.
+ if (curbuf->b_help) {
fix_help_buffer();
+ }
} else if (read_stdin) {
int save_bin = curbuf->b_p_bin;
linenr_T line_count;
@@ -257,17 +264,16 @@ open_buffer (
return retval;
}
-/*
- * Return TRUE if "buf" points to a valid buffer (in the buffer list).
- */
-int buf_valid(buf_T *buf)
+/// Check that "buf" points to a valid buffer (in the buffer list).
+bool buf_valid(buf_T *buf)
+ FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT
{
FOR_ALL_BUFFERS(bp) {
if (bp == buf) {
- return TRUE;
+ return true;
}
}
- return FALSE;
+ return false;
}
/*
@@ -2055,16 +2061,15 @@ void buflist_setfpos(buf_T *const buf, win_T *const win,
}
-/*
- * Return true when "wip" has 'diff' set and the diff is only for another tab
- * page. That's because a diff is local to a tab page.
- */
+/// Check that "wip" has 'diff' set and the diff is only for another tab page.
+/// That's because a diff is local to a tab page.
static bool wininfo_other_tab_diff(wininfo_T *wip)
+ FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ALL
{
if (wip->wi_opt.wo_diff) {
FOR_ALL_WINDOWS_IN_TAB(wp, curtab) {
- /* return false when it's a window in the current tab page, thus
- * the buffer was in diff mode here */
+ // return false when it's a window in the current tab page, thus
+ // the buffer was in diff mode here
if (wip->wi_win == wp) {
return false;
}
@@ -2421,52 +2426,62 @@ void buflist_altfpos(win_T *win)
buflist_setfpos(curbuf, win, win->w_cursor.lnum, win->w_cursor.col, TRUE);
}
-/*
- * Return TRUE if 'ffname' is not the same file as current file.
- * Fname must have a full path (expanded by path_get_absolute_path()).
- */
-int otherfile(char_u *ffname)
+/// Check that "ffname" is not the same file as current file.
+/// Fname must have a full path (expanded by path_get_absolute_path()).
+///
+/// @param ffname full path name to check
+bool otherfile(char_u *ffname)
+ FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ALL
{
return otherfile_buf(curbuf, ffname, NULL, false);
}
-static int otherfile_buf(buf_T *buf, char_u *ffname,
- FileID *file_id_p, bool file_id_valid)
+/// Check that "ffname" is not the same file as the file loaded in "buf".
+/// Fname must have a full path (expanded by path_get_absolute_path()).
+///
+/// @param buf buffer to check
+/// @param ffname full path name to check
+/// @param file_id_p information about the file at "ffname".
+/// @param file_id_valid whether a valid "file_id_p" was passed in.
+static bool otherfile_buf(buf_T *buf, char_u *ffname, FileID *file_id_p,
+ bool file_id_valid)
+ FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT
{
- /* no name is different */
+ // no name is different
if (ffname == NULL || *ffname == NUL || buf->b_ffname == NULL) {
- return TRUE;
+ return true;
}
if (fnamecmp(ffname, buf->b_ffname) == 0) {
- return FALSE;
+ return false;
}
{
FileID file_id;
- /* If no struct stat given, get it now */
+ // If no struct stat given, get it now
if (file_id_p == NULL) {
file_id_p = &file_id;
file_id_valid = os_fileid((char *)ffname, file_id_p);
}
if (!file_id_valid) {
// file_id not valid, assume files are different.
- return TRUE;
+ return true;
}
- /* Use dev/ino to check if the files are the same, even when the names
- * are different (possible with links). Still need to compare the
- * name above, for when the file doesn't exist yet.
- * Problem: The dev/ino changes when a file is deleted (and created
- * again) and remains the same when renamed/moved. We don't want to
- * stat() each buffer each time, that would be too slow. Get the
- * dev/ino again when they appear to match, but not when they appear
- * to be different: Could skip a buffer when it's actually the same
- * file. */
+ // Use dev/ino to check if the files are the same, even when the names
+ // are different (possible with links). Still need to compare the
+ // name above, for when the file doesn't exist yet.
+ // Problem: The dev/ino changes when a file is deleted (and created
+ // again) and remains the same when renamed/moved. We don't want to
+ // stat() each buffer each time, that would be too slow. Get the
+ // dev/ino again when they appear to match, but not when they appear
+ // to be different: Could skip a buffer when it's actually the same
+ // file.
if (buf_same_file_id(buf, file_id_p)) {
buf_set_file_id(buf);
- if (buf_same_file_id(buf, file_id_p))
- return FALSE;
+ if (buf_same_file_id(buf, file_id_p)) {
+ return false;
+ }
}
}
- return TRUE;
+ return true;
}
// Set file_id for a buffer.
@@ -2483,11 +2498,14 @@ void buf_set_file_id(buf_T *buf)
}
}
-// return TRUE if file_id in buffer "buf" matches with "file_id".
+/// Check that file_id in buffer "buf" matches with "file_id".
+///
+/// @param buf buffer
+/// @param file_id file id
static bool buf_same_file_id(buf_T *buf, FileID *file_id)
+ FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ALL
{
- return buf->file_id_valid
- && os_fileid_equal(&(buf->file_id), file_id);
+ return buf->file_id_valid && os_fileid_equal(&(buf->file_id), file_id);
}
/*
@@ -2770,23 +2788,28 @@ void maketitle(void)
resettitle();
}
-/*
- * Used for title and icon: Check if "str" differs from "*last". Set "*last"
- * from "str" if it does.
- * Return TRUE when "*last" changed.
- */
-static int ti_change(char_u *str, char_u **last)
+/// Used for title and icon: Check if "str" differs from "*last". Set "*last"
+/// from "str" if it does by freeing the old value of "*last" and duplicating
+/// "str".
+///
+/// @param str desired title string
+/// @param[in,out] last current title string
+//
+/// @return true when "*last" changed.
+static bool ti_change(char_u *str, char_u **last)
+ FUNC_ATTR_WARN_UNUSED_RESULT
{
if ((str == NULL) != (*last == NULL)
|| (str != NULL && *last != NULL && STRCMP(str, *last) != 0)) {
xfree(*last);
- if (str == NULL)
+ if (str == NULL) {
*last = NULL;
- else
+ } else {
*last = vim_strsave(str);
- return TRUE;
+ }
+ return true;
}
- return FALSE;
+ return false;
}
/*
@@ -3014,7 +3037,7 @@ int build_stl_str_hl(
&& item[groupitem[groupdepth]].minwid == 0) {
bool has_normal_items = false;
for (long n = groupitem[groupdepth] + 1; n < curitem; n++) {
- if (item[n].type == Normal) {
+ if (item[n].type == Normal || item[n].type == Highlight) {
has_normal_items = true;
break;
}
@@ -3922,26 +3945,29 @@ void get_rel_pos(win_T *wp, char_u *buf, int buflen)
: (int)(above * 100L / (above + below)));
}
-/*
- * Append (file 2 of 8) to "buf[buflen]", if editing more than one file.
- * Return TRUE if it was appended.
- */
-static int
-append_arg_number (
- win_T *wp,
- char_u *buf,
- int buflen,
- int add_file /* Add "file" before the arg number */
-)
+/// Append (file 2 of 8) to "buf[buflen]", if editing more than one file.
+///
+/// @param wp window whose buffers to check
+/// @param[in,out] buf string buffer to add the text to
+/// @param buflen length of the string buffer
+/// @param add_file if true, add "file" before the arg number
+///
+/// @return true if it was appended.
+static bool append_arg_number(win_T *wp, char_u *buf, int buflen, bool add_file)
+ FUNC_ATTR_NONNULL_ALL
{
- char_u *p;
+ // Nothing to do
+ if (ARGCOUNT <= 1) {
+ return false;
+ }
+
+ char_u *p = buf + STRLEN(buf); // go to the end of the buffer
- if (ARGCOUNT <= 1) /* nothing to do */
- return FALSE;
+ // Early out if the string is getting too long
+ if (p - buf + 35 >= buflen) {
+ return false;
+ }
- p = buf + STRLEN(buf); /* go to the end of the buffer */
- if (p - buf + 35 >= buflen) /* getting too long */
- return FALSE;
*p++ = ' ';
*p++ = '(';
if (add_file) {
@@ -3949,9 +3975,10 @@ append_arg_number (
p += 5;
}
vim_snprintf((char *)p, (size_t)(buflen - (p - buf)),
- wp->w_arg_idx_invalid ? "(%d) of %d)"
- : "%d of %d)", wp->w_arg_idx + 1, ARGCOUNT);
- return TRUE;
+ wp->w_arg_idx_invalid
+ ? "(%d) of %d)"
+ : "%d of %d)", wp->w_arg_idx + 1, ARGCOUNT);
+ return true;
}
/*
@@ -4585,11 +4612,16 @@ char_u *buf_spname(buf_T *buf)
return NULL;
}
-/*
- * Find a window for buffer "buf".
- * If found true is returned and "wp" and "tp" are set to the window and tabpage.
- * If not found false is returned.
- */
+/// Find a window for buffer "buf".
+/// If found true is returned and "wp" and "tp" are set to
+/// the window and tabpage.
+/// If not found, false is returned.
+///
+/// @param buf buffer to find a window for
+/// @param[out] wp stores the found window
+/// @param[out] tp stores the found tabpage
+///
+/// @return true if a window was found for the buffer.
bool find_win_for_buf(buf_T *buf, win_T **wp, tabpage_T **tp)
{
*wp = NULL;
@@ -5103,50 +5135,54 @@ void set_buflisted(int on)
}
}
-/*
- * Read the file for "buf" again and check if the contents changed.
- * Return TRUE if it changed or this could not be checked.
- */
-int buf_contents_changed(buf_T *buf)
+/// Read the file for "buf" again and check if the contents changed.
+/// Return true if it changed or this could not be checked.
+///
+/// @param buf buffer to check
+///
+/// @return true if the buffer's contents have changed
+bool buf_contents_changed(buf_T *buf)
+ FUNC_ATTR_NONNULL_ALL
{
- buf_T *newbuf;
- int differ = TRUE;
- linenr_T lnum;
- aco_save_T aco;
- exarg_T ea;
+ bool differ = true;
- /* Allocate a buffer without putting it in the buffer list. */
- newbuf = buflist_new(NULL, NULL, (linenr_T)1, BLN_DUMMY);
- if (newbuf == NULL)
- return TRUE;
+ // Allocate a buffer without putting it in the buffer list.
+ buf_T *newbuf = buflist_new(NULL, NULL, (linenr_T)1, BLN_DUMMY);
+ if (newbuf == NULL) {
+ return true;
+ }
- /* Force the 'fileencoding' and 'fileformat' to be equal. */
+ // Force the 'fileencoding' and 'fileformat' to be equal.
+ exarg_T ea;
prep_exarg(&ea, buf);
- /* set curwin/curbuf to buf and save a few things */
+ // set curwin/curbuf to buf and save a few things
+ aco_save_T aco;
aucmd_prepbuf(&aco, newbuf);
if (ml_open(curbuf) == OK
&& readfile(buf->b_ffname, buf->b_fname,
- (linenr_T)0, (linenr_T)0, (linenr_T)MAXLNUM,
- &ea, READ_NEW | READ_DUMMY) == OK) {
- /* compare the two files line by line */
+ (linenr_T)0, (linenr_T)0, (linenr_T)MAXLNUM,
+ &ea, READ_NEW | READ_DUMMY) == OK) {
+ // compare the two files line by line
if (buf->b_ml.ml_line_count == curbuf->b_ml.ml_line_count) {
- differ = FALSE;
- for (lnum = 1; lnum <= curbuf->b_ml.ml_line_count; ++lnum)
- if (STRCMP(ml_get_buf(buf, lnum, FALSE), ml_get(lnum)) != 0) {
- differ = TRUE;
+ differ = false;
+ for (linenr_T lnum = 1; lnum <= curbuf->b_ml.ml_line_count; ++lnum) {
+ if (STRCMP(ml_get_buf(buf, lnum, false), ml_get(lnum)) != 0) {
+ differ = true;
break;
}
+ }
}
}
xfree(ea.cmd);
- /* restore curwin/curbuf and a few other things */
+ // restore curwin/curbuf and a few other things
aucmd_restbuf(&aco);
- if (curbuf != newbuf) /* safety check */
- wipe_buffer(newbuf, FALSE);
+ if (curbuf != newbuf) { // safety check
+ wipe_buffer(newbuf, false);
+ }
return differ;
}
diff --git a/src/nvim/buffer_defs.h b/src/nvim/buffer_defs.h
index 936a14b903..86e63eb52c 100644
--- a/src/nvim/buffer_defs.h
+++ b/src/nvim/buffer_defs.h
@@ -533,9 +533,9 @@ struct file_buffer {
/*
* Character table, only used in charset.c for 'iskeyword'
- * 32 bytes of 8 bits: 1 bit per character 0-255.
+ * bitset with 4*64=256 bits: 1 bit per character 0-255.
*/
- char_u b_chartab[32];
+ uint64_t b_chartab[4];
/* Table used for mappings local to a buffer. */
mapblock_T *(b_maphash[256]);
diff --git a/src/nvim/charset.c b/src/nvim/charset.c
index 4e329b5cd8..83e2aaa6e6 100644
--- a/src/nvim/charset.c
+++ b/src/nvim/charset.c
@@ -32,16 +32,16 @@
#endif
-static int chartab_initialized = FALSE;
+static bool chartab_initialized = false;
-// b_chartab[] is an array of 32 bytes, each bit representing one of the
+// b_chartab[] is an array with 256 bits, each bit representing one of the
// characters 0-255.
#define SET_CHARTAB(buf, c) \
- (buf)->b_chartab[(unsigned)(c) >> 3] |= (1 << ((c) & 0x7))
+ (buf)->b_chartab[(unsigned)(c) >> 6] |= (1ull << ((c) & 0x3f))
#define RESET_CHARTAB(buf, c) \
- (buf)->b_chartab[(unsigned)(c) >> 3] &= ~(1 << ((c) & 0x7))
+ (buf)->b_chartab[(unsigned)(c) >> 6] &= ~(1ull << ((c) & 0x3f))
#define GET_CHARTAB(buf, c) \
- ((buf)->b_chartab[(unsigned)(c) >> 3] & (1 << ((c) & 0x7)))
+ ((buf)->b_chartab[(unsigned)(c) >> 6] & (1ull << ((c) & 0x3f)))
/// Fill chartab[]. Also fills curbuf->b_chartab[] with flags for keyword
/// characters for current buffer.
@@ -69,12 +69,12 @@ static int chartab_initialized = FALSE;
/// an error, OK otherwise.
int init_chartab(void)
{
- return buf_init_chartab(curbuf, TRUE);
+ return buf_init_chartab(curbuf, true);
}
/// Helper for init_chartab
///
-/// @param global FALSE: only set buf->b_chartab[]
+/// @param global false: only set buf->b_chartab[]
///
/// @return FAIL if 'iskeyword', 'isident', 'isfname' or 'isprint' option has
/// an error, OK otherwise.
@@ -84,13 +84,13 @@ int buf_init_chartab(buf_T *buf, int global)
int c2;
char_u *p;
int i;
- int tilde;
- int do_isalpha;
+ bool tilde;
+ bool do_isalpha;
if (global) {
// Set the default size for printable characters:
// From <Space> to '~' is 1 (printable), others are 2 (not printable).
- // This also inits all 'isident' and 'isfname' flags to FALSE.
+ // This also inits all 'isident' and 'isfname' flags to false.
c = 0;
while (c < ' ') {
@@ -133,7 +133,7 @@ int buf_init_chartab(buf_T *buf, int global)
}
}
- // Init word char flags all to FALSE
+ // Init word char flags all to false
memset(buf->b_chartab, 0, (size_t)32);
if (enc_dbcs != 0) {
@@ -169,11 +169,11 @@ int buf_init_chartab(buf_T *buf, int global)
}
while (*p) {
- tilde = FALSE;
- do_isalpha = FALSE;
+ tilde = false;
+ do_isalpha = false;
if ((*p == '^') && (p[1] != NUL)) {
- tilde = TRUE;
+ tilde = true;
++p;
}
@@ -212,7 +212,7 @@ int buf_init_chartab(buf_T *buf, int global)
// standard function isalpha(). This takes care of locale for
// single-byte characters).
if (c == '@') {
- do_isalpha = TRUE;
+ do_isalpha = true;
c = 1;
c2 = 255;
} else {
@@ -231,7 +231,7 @@ int buf_init_chartab(buf_T *buf, int global)
if (i == 0) {
// (re)set ID flag
if (tilde) {
- chartab[c] &= ~CT_ID_CHAR;
+ chartab[c] &= (uint8_t)~CT_ID_CHAR;
} else {
chartab[c] |= CT_ID_CHAR;
}
@@ -244,18 +244,18 @@ int buf_init_chartab(buf_T *buf, int global)
|| (p_altkeymap && (F_isalpha(c) || F_isdigit(c))))
&& !(enc_dbcs && (MB_BYTE2LEN(c) == 2))) {
if (tilde) {
- chartab[c] = (chartab[c] & ~CT_CELL_MASK)
- + ((dy_flags & DY_UHEX) ? 4 : 2);
- chartab[c] &= ~CT_PRINT_CHAR;
+ chartab[c] = (uint8_t)((chartab[c] & ~CT_CELL_MASK)
+ + ((dy_flags & DY_UHEX) ? 4 : 2));
+ chartab[c] &= (uint8_t)~CT_PRINT_CHAR;
} else {
- chartab[c] = (chartab[c] & ~CT_CELL_MASK) + 1;
+ chartab[c] = (uint8_t)((chartab[c] & ~CT_CELL_MASK) + 1);
chartab[c] |= CT_PRINT_CHAR;
}
}
} else if (i == 2) {
// (re)set fname flag
if (tilde) {
- chartab[c] &= ~CT_FNAME_CHAR;
+ chartab[c] &= (uint8_t)~CT_FNAME_CHAR;
} else {
chartab[c] |= CT_FNAME_CHAR;
}
@@ -280,7 +280,7 @@ int buf_init_chartab(buf_T *buf, int global)
}
}
}
- chartab_initialized = TRUE;
+ chartab_initialized = true;
return OK;
}
@@ -333,7 +333,8 @@ char_u *transstr(char_u *s) FUNC_ATTR_NONNULL_RET
{
char_u *res;
char_u *p;
- int l, c;
+ int c;
+ size_t l;
char_u hexbuf[11];
if (has_mbyte) {
@@ -343,7 +344,7 @@ char_u *transstr(char_u *s) FUNC_ATTR_NONNULL_RET
p = s;
while (*p != NUL) {
- if ((l = (*mb_ptr2len)(p)) > 1) {
+ if ((l = (size_t)(*mb_ptr2len)(p)) > 1) {
c = (*mb_ptr2char)(p);
p += l;
@@ -354,7 +355,7 @@ char_u *transstr(char_u *s) FUNC_ATTR_NONNULL_RET
len += STRLEN(hexbuf);
}
} else {
- l = byte2cells(*p++);
+ l = (size_t)byte2cells(*p++);
if (l > 0) {
len += l;
@@ -366,14 +367,14 @@ char_u *transstr(char_u *s) FUNC_ATTR_NONNULL_RET
}
res = xmallocz(len);
} else {
- res = xmallocz(vim_strsize(s));
+ res = xmallocz((size_t)vim_strsize(s));
}
*res = NUL;
p = s;
while (*p != NUL) {
- if (has_mbyte && ((l = (*mb_ptr2len)(p)) > 1)) {
+ if (has_mbyte && ((l = (size_t)(*mb_ptr2len)(p)) > 1)) {
c = (*mb_ptr2char)(p);
if (vim_isprintc(c)) {
@@ -477,9 +478,9 @@ char_u* str_foldcase(char_u *str, int orglen, char_u *buf, int buflen)
i += (*mb_ptr2len)(STR_PTR(i));
} else {
if (buf == NULL) {
- GA_CHAR(i) = TOLOWER_LOC(GA_CHAR(i));
+ GA_CHAR(i) = (char_u)TOLOWER_LOC(GA_CHAR(i));
} else {
- buf[i] = TOLOWER_LOC(buf[i]);
+ buf[i] = (char_u)TOLOWER_LOC(buf[i]);
}
++i;
}
@@ -493,7 +494,7 @@ char_u* str_foldcase(char_u *str, int orglen, char_u *buf, int buflen)
// Catch 22: chartab[] can't be initialized before the options are
// initialized, and initializing options may cause transchar() to be called!
-// When chartab_initialized == FALSE don't use chartab[].
+// When chartab_initialized == false don't use chartab[].
// Does NOT work for multi-byte characters, c must be <= 255.
// Also doesn't work for the first byte of a multi-byte, "c" must be a
// character!
@@ -518,7 +519,7 @@ char_u* transchar(int c)
if ((!chartab_initialized && (((c >= ' ') && (c <= '~')) || F_ischar(c)))
|| ((c < 256) && vim_isprintc_strict(c))) {
// printable character
- transchar_buf[i] = c;
+ transchar_buf[i] = (char_u)c;
transchar_buf[i + 1] = NUL;
} else {
transchar_nonprint(transchar_buf + i, c);
@@ -564,7 +565,7 @@ void transchar_nonprint(char_u *buf, int c)
// 0x00 - 0x1f and 0x7f
buf[0] = '^';
// DEL displayed as ^?
- buf[1] = c ^ 0x40;
+ buf[1] = (char_u)(c ^ 0x40);
buf[2] = NUL;
} else if (enc_utf8 && (c >= 0x80)) {
@@ -572,12 +573,12 @@ void transchar_nonprint(char_u *buf, int c)
} else if ((c >= ' ' + 0x80) && (c <= '~' + 0x80)) {
// 0xa0 - 0xfe
buf[0] = '|';
- buf[1] = c - 0x80;
+ buf[1] = (char_u)(c - 0x80);
buf[2] = NUL;
} else {
// 0x80 - 0x9f and 0xff
buf[0] = '~';
- buf[1] = (c - 0x80) ^ 0x40;
+ buf[1] = (char_u)((c - 0x80) ^ 0x40);
buf[2] = NUL;
}
}
@@ -592,11 +593,11 @@ void transchar_hex(char_u *buf, int c)
buf[0] = '<';
if (c > 255) {
- buf[++i] = nr2hex((unsigned)c >> 12);
- buf[++i] = nr2hex((unsigned)c >> 8);
+ buf[++i] = (char_u)nr2hex((unsigned)c >> 12);
+ buf[++i] = (char_u)nr2hex((unsigned)c >> 8);
}
- buf[++i] = nr2hex((unsigned)c >> 4);
- buf[++i] = nr2hex((unsigned)c);
+ buf[++i] = (char_u)(nr2hex((unsigned)c >> 4));
+ buf[++i] = (char_u)(nr2hex((unsigned)c));
buf[++i] = '>';
buf[++i] = NUL;
}
@@ -734,9 +735,8 @@ int vim_strnsize(char_u *s, int len)
/// @return Number of characters.
#define RET_WIN_BUF_CHARTABSIZE(wp, buf, p, col) \
if (*(p) == TAB && (!(wp)->w_p_list || lcs_tab1)) { \
- int ts; \
- ts = (buf)->b_p_ts; \
- return (int)(ts - (col % ts)); \
+ const int ts = (int) (buf)->b_p_ts; \
+ return (ts - (int)(col % ts)); \
} else { \
return ptr2cells(p); \
}
@@ -1137,7 +1137,7 @@ static int win_nolbr_chartabsize(win_T *wp, char_u *s, colnr_T col, int *headp)
int n;
if ((*s == TAB) && (!wp->w_p_list || lcs_tab1)) {
- n = wp->w_buffer->b_p_ts;
+ n = (int)wp->w_buffer->b_p_ts;
return n - (col % n);
}
n = ptr2cells(s);
@@ -1205,11 +1205,11 @@ void getvcol(win_T *wp, pos_T *pos, colnr_T *start, colnr_T *cursor,
char_u *line; // start of the line
int incr;
int head;
- int ts = wp->w_buffer->b_p_ts;
+ int ts = (int)wp->w_buffer->b_p_ts;
int c;
vcol = 0;
- line = ptr = ml_get_buf(wp->w_buffer, pos->lnum, FALSE);
+ line = ptr = ml_get_buf(wp->w_buffer, pos->lnum, false);
if (pos->col == MAXCOL) {
// continue until the NUL
@@ -1329,7 +1329,7 @@ colnr_T getvcol_nolist(pos_T *posp)
int list_save = curwin->w_p_list;
colnr_T vcol;
- curwin->w_p_list = FALSE;
+ curwin->w_p_list = false;
getvcol(curwin, posp, NULL, &vcol, NULL);
curwin->w_p_list = list_save;
return vcol;
@@ -1358,7 +1358,7 @@ void getvvcol(win_T *wp, pos_T *pos, colnr_T *start, colnr_T *cursor,
endadd = 0;
// Cannot put the cursor on part of a wide character.
- ptr = ml_get_buf(wp->w_buffer, pos->lnum, FALSE);
+ ptr = ml_get_buf(wp->w_buffer, pos->lnum, false);
if (pos->col < (colnr_T)STRLEN(ptr)) {
int c = (*mb_ptr2char)(ptr + pos->col);
@@ -1595,7 +1595,7 @@ bool vim_islower(int c)
if (c >= 0x100) {
if (has_mbyte) {
- return iswlower(c);
+ return iswlower((wint_t)c);
}
// islower() can't handle these chars and may crash
@@ -1626,7 +1626,7 @@ bool vim_isupper(int c)
if (c >= 0x100) {
if (has_mbyte) {
- return iswupper(c);
+ return iswupper((wint_t)c);
}
// isupper() can't handle these chars and may crash
@@ -1653,7 +1653,7 @@ int vim_toupper(int c)
if (c >= 0x100) {
if (has_mbyte) {
- return towupper(c);
+ return (int)towupper((wint_t)c);
}
// toupper() can't handle these chars and may crash
@@ -1680,7 +1680,7 @@ int vim_tolower(int c)
if (c >= 0x100) {
if (has_mbyte) {
- return towlower(c);
+ return (int)towlower((wint_t)c);
}
// tolower() can't handle these chars and may crash
diff --git a/src/nvim/diff.c b/src/nvim/diff.c
index 0be8b3c514..1149ca1e62 100644
--- a/src/nvim/diff.c
+++ b/src/nvim/diff.c
@@ -819,8 +819,8 @@ static void diff_file(char_u *tmp_orig, char_u *tmp_new, char_u *tmp_diff)
(diff_flags & DIFF_IWHITE) ? "-b " : "",
(diff_flags & DIFF_ICASE) ? "-i " : "",
tmp_orig, tmp_new);
- append_redir(cmd, (int)len, p_srr, tmp_diff);
- block_autocmds(); /* Avoid ShellCmdPost stuff */
+ append_redir(cmd, len, p_srr, tmp_diff);
+ block_autocmds(); // Avoid ShellCmdPost stuff
(void)call_shell(
cmd,
kShellOptFilter | kShellOptSilent | kShellOptDoOut,
diff --git a/src/nvim/edit.c b/src/nvim/edit.c
index 6313ea2e81..614a5d43be 100644
--- a/src/nvim/edit.c
+++ b/src/nvim/edit.c
@@ -165,10 +165,6 @@ static int compl_restarting = FALSE; /* don't insert match */
* FALSE the word to be completed must be located. */
static int compl_started = FALSE;
-/* Set when doing something for completion that may call edit() recursively,
- * which is not allowed. */
-static int compl_busy = FALSE;
-
static int compl_matches = 0;
static char_u *compl_pattern = NULL;
static int compl_direction = FORWARD;
@@ -887,7 +883,7 @@ static int insert_handle_key(InsertState *s)
case Ctrl_T: // Make indent one shiftwidth greater.
if (s->c == Ctrl_T && ctrl_x_mode == CTRL_X_THESAURUS) {
- if (has_compl_option(false)) {
+ if (check_compl_option(false)) {
insert_do_complete(s);
}
break;
@@ -1102,7 +1098,7 @@ static int insert_handle_key(InsertState *s)
case Ctrl_K: // digraph or keyword completion
if (ctrl_x_mode == CTRL_X_DICTIONARY) {
- if (has_compl_option(true)) {
+ if (check_compl_option(true)) {
insert_do_complete(s);
}
break;
@@ -1264,30 +1260,28 @@ static void insert_do_cindent(InsertState *s)
}
}
-/*
- * edit(): Start inserting text.
- *
- * "cmdchar" can be:
- * 'i' normal insert command
- * 'a' normal append command
- * 'R' replace command
- * 'r' "r<CR>" command: insert one <CR>. Note: count can be > 1, for redo,
- * but still only one <CR> is inserted. The <Esc> is not used for redo.
- * 'g' "gI" command.
- * 'V' "gR" command for Virtual Replace mode.
- * 'v' "gr" command for single character Virtual Replace mode.
- *
- * This function is not called recursively. For CTRL-O commands, it returns
- * and lets the caller handle the Normal-mode command.
- *
- * Return TRUE if a CTRL-O command caused the return (insert mode pending).
- */
-int
-edit (
- int cmdchar,
- int startln, /* if set, insert at start of line */
- long count
-)
+/// edit(): Start inserting text.
+///
+/// "cmdchar" can be:
+/// 'i' normal insert command
+/// 'a' normal append command
+/// 'R' replace command
+/// 'r' "r<CR>" command: insert one <CR>.
+/// Note: count can be > 1, for redo, but still only one <CR> is inserted.
+/// <Esc> is not used for redo.
+/// 'g' "gI" command.
+/// 'V' "gR" command for Virtual Replace mode.
+/// 'v' "gr" command for single character Virtual Replace mode.
+///
+/// This function is not called recursively. For CTRL-O commands, it returns
+/// and lets the caller handle the Normal-mode command.
+///
+/// @param cmdchar command that started the insert
+/// @param startln if true, insert at start of line
+/// @param count repeat count for the command
+///
+/// @return true if a CTRL-O command caused the return (insert mode pending).
+bool edit(int cmdchar, bool startln, long count)
{
if (curbuf->terminal) {
if (ex_normal_busy) {
@@ -1795,33 +1789,37 @@ void backspace_until_column(int col)
}
}
-/*
- * Like del_char(), but make sure not to go before column "limit_col".
- * Only matters when there are composing characters.
- * Return TRUE when something was deleted.
- */
-static int del_char_after_col(int limit_col)
+/// Like del_char(), but make sure not to go before column "limit_col".
+/// Only matters when there are composing characters.
+///
+/// @param limit_col only delete the character if it is after this column
+//
+/// @return true when something was deleted.
+static bool del_char_after_col(int limit_col)
{
if (enc_utf8 && limit_col >= 0) {
colnr_T ecol = curwin->w_cursor.col + 1;
- /* Make sure the cursor is at the start of a character, but
- * skip forward again when going too far back because of a
- * composing character. */
+ // Make sure the cursor is at the start of a character, but
+ // skip forward again when going too far back because of a
+ // composing character.
mb_adjust_cursor();
while (curwin->w_cursor.col < (colnr_T)limit_col) {
int l = utf_ptr2len(get_cursor_pos_ptr());
- if (l == 0) /* end of line */
+ if (l == 0) { // end of line
break;
+ }
curwin->w_cursor.col += l;
}
- if (*get_cursor_pos_ptr() == NUL || curwin->w_cursor.col == ecol)
- return FALSE;
- del_bytes((long)((int)ecol - curwin->w_cursor.col), FALSE, TRUE);
- } else
- (void)del_char(FALSE);
- return TRUE;
+ if (*get_cursor_pos_ptr() == NUL || curwin->w_cursor.col == ecol) {
+ return false;
+ }
+ del_bytes((long)(ecol - curwin->w_cursor.col), false, true);
+ } else {
+ del_char(false);
+ }
+ return true;
}
/*
@@ -1846,47 +1844,48 @@ static void ins_ctrl_x(void)
}
}
-/*
- * Return TRUE if the 'dict' or 'tsr' option can be used.
- */
-static int has_compl_option(int dict_opt)
+/// Check that the "dict" or "tsr" option can be used.
+///
+/// @param dict_opt check "dict" when true, "tsr" when false.
+static bool check_compl_option(bool dict_opt)
{
- if (dict_opt ? (*curbuf->b_p_dict == NUL && *p_dict == NUL
- && !curwin->w_p_spell
- )
+ if (dict_opt
+ ? (*curbuf->b_p_dict == NUL && *p_dict == NUL && !curwin->w_p_spell)
: (*curbuf->b_p_tsr == NUL && *p_tsr == NUL)) {
ctrl_x_mode = 0;
edit_submode = NULL;
msg_attr(dict_opt ? (char_u *)_("'dictionary' option is empty")
- : (char_u *)_("'thesaurus' option is empty"),
- hl_attr(HLF_E));
+ : (char_u *)_("'thesaurus' option is empty"), hl_attr(HLF_E));
if (emsg_silent == 0) {
vim_beep(BO_COMPL);
setcursor();
ui_flush();
os_delay(2000L, false);
}
- return FALSE;
+ return false;
}
- return TRUE;
+ return true;
}
-/*
- * Is the character 'c' a valid key to go to or keep us in CTRL-X mode?
- * This depends on the current mode.
- */
-int vim_is_ctrl_x_key(int c)
+/// Check that the character "c" a valid key to go to or keep us in CTRL-X mode?
+/// This depends on the current mode.
+///
+/// @param c character to check
+bool vim_is_ctrl_x_key(int c)
+ FUNC_ATTR_WARN_UNUSED_RESULT
{
- /* Always allow ^R - let it's results then be checked */
- if (c == Ctrl_R)
- return TRUE;
+ // Always allow ^R - let its results then be checked
+ if (c == Ctrl_R) {
+ return true;
+ }
- /* Accept <PageUp> and <PageDown> if the popup menu is visible. */
- if (ins_compl_pum_key(c))
- return TRUE;
+ // Accept <PageUp> and <PageDown> if the popup menu is visible.
+ if (ins_compl_pum_key(c)) {
+ return true;
+ }
switch (ctrl_x_mode) {
- case 0: /* Not in any CTRL-X mode */
+ case 0: // Not in any CTRL-X mode
return c == Ctrl_N || c == Ctrl_P || c == Ctrl_X;
case CTRL_X_NOT_DEFINED_YET:
return c == Ctrl_X || c == Ctrl_Y || c == Ctrl_E
@@ -1924,35 +1923,37 @@ int vim_is_ctrl_x_key(int c)
return (c == Ctrl_P || c == Ctrl_N);
}
EMSG(_(e_internal));
- return FALSE;
+ return false;
}
-/*
- * Return TRUE when character "c" is part of the item currently being
- * completed. Used to decide whether to abandon complete mode when the menu
- * is visible.
- */
-static int ins_compl_accept_char(int c)
+/// Check that character "c" is part of the item currently being
+/// completed. Used to decide whether to abandon complete mode when the menu
+/// is visible.
+///
+/// @param c character to check
+static bool ins_compl_accept_char(int c)
+ FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT
{
- if (ctrl_x_mode & CTRL_X_WANT_IDENT)
- /* When expanding an identifier only accept identifier chars. */
+ if (ctrl_x_mode & CTRL_X_WANT_IDENT) {
+ // When expanding an identifier only accept identifier chars.
return vim_isIDc(c);
+ }
switch (ctrl_x_mode) {
case CTRL_X_FILES:
- /* When expanding file name only accept file name chars. But not
- * path separators, so that "proto/<Tab>" expands files in
- * "proto", not "proto/" as a whole */
+ // When expanding file name only accept file name chars. But not
+ // path separators, so that "proto/<Tab>" expands files in
+ // "proto", not "proto/" as a whole
return vim_isfilec(c) && !vim_ispathsep(c);
case CTRL_X_CMDLINE:
case CTRL_X_OMNI:
- /* Command line and Omni completion can work with just about any
- * printable character, but do stop at white space. */
+ // Command line and Omni completion can work with just about any
+ // printable character, but do stop at white space.
return vim_isprintc(c) && !ascii_iswhite(c);
case CTRL_X_WHOLE_LINE:
- /* For while line completion a space can be part of the line. */
+ // For while line completion a space can be part of the line.
return vim_isprintc(c);
}
return vim_iswordc(c);
@@ -2197,15 +2198,19 @@ ins_compl_add (
return OK;
}
-/*
- * Return TRUE if "str[len]" matches with match->cp_str, considering
- * match->cp_icase.
- */
-static int ins_compl_equal(compl_T *match, char_u *str, int len)
+/// Check that "str[len]" matches with "match->cp_str", considering
+/// "match->cp_icase".
+///
+/// @param match completion match
+/// @param str character string to check
+/// @param len lenth of "str"
+static bool ins_compl_equal(compl_T *match, char_u *str, size_t len)
+ FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ALL
{
- if (match->cp_icase)
- return STRNICMP(match->cp_str, str, (size_t)len) == 0;
- return STRNCMP(match->cp_str, str, (size_t)len) == 0;
+ if (match->cp_icase) {
+ return STRNICMP(match->cp_str, str, len) == 0;
+ }
+ return STRNCMP(match->cp_str, str, len) == 0;
}
/*
@@ -2353,13 +2358,13 @@ void set_completion(colnr_T startcol, list_T *list)
int save_w_wrow = curwin->w_wrow;
compl_curr_match = compl_first_match;
- if (compl_no_insert) {
+ if (compl_no_insert || compl_no_select) {
ins_complete(K_DOWN, false);
- } else {
- ins_complete(Ctrl_N, false);
if (compl_no_select) {
- ins_complete(Ctrl_P, false);
+ ins_complete(K_UP, false);
}
+ } else {
+ ins_complete(Ctrl_N, false);
}
// Lazily show the popup menu, unless we got interrupted.
@@ -2403,44 +2408,33 @@ static void ins_compl_del_pum(void)
}
}
-/*
- * Return TRUE if the popup menu should be displayed.
- */
-static int pum_wanted(void)
+/// Check if the popup menu should be displayed.
+static bool pum_wanted(void)
+ FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT
{
- /* 'completeopt' must contain "menu" or "menuone" */
- if (vim_strchr(p_cot, 'm') == NULL)
- return FALSE;
-
- /* The display looks bad on a B&W display. */
- if (t_colors < 8
- )
- return FALSE;
- return TRUE;
+ // "completeopt" must contain "menu" or "menuone"
+ return vim_strchr(p_cot, 'm') != NULL;
}
-/*
- * Return TRUE if there are two or more matches to be shown in the popup menu.
- * One if 'completopt' contains "menuone".
- */
-static int pum_enough_matches(void)
+/// Check that there are two or more matches to be shown in the popup menu.
+/// One if "completopt" contains "menuone".
+static bool pum_enough_matches(void)
+ FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT
{
- compl_T *compl;
- int i;
-
- /* Don't display the popup menu if there are no matches or there is only
- * one (ignoring the original text). */
- compl = compl_first_match;
- i = 0;
+ // Don't display the popup menu if there are no matches or there is only
+ // one (ignoring the original text).
+ compl_T *comp = compl_first_match;
+ int i = 0;
do {
- if (compl == NULL
- || ((compl->cp_flags & ORIGINAL_TEXT) == 0 && ++i == 2))
+ if (comp == NULL || ((comp->cp_flags & ORIGINAL_TEXT) == 0 && ++i == 2)) {
break;
- compl = compl->cp_next;
- } while (compl != compl_first_match);
+ }
+ comp = comp->cp_next;
+ } while (comp != compl_first_match);
- if (strstr((char *)p_cot, "menuone") != NULL)
+ if (strstr((char *)p_cot, "menuone") != NULL) {
return i >= 1;
+ }
return i >= 2;
}
@@ -2871,10 +2865,9 @@ static void ins_compl_clear(void)
set_vim_var_dict(VV_COMPLETED_ITEM, dict_alloc());
}
-/*
- * Return TRUE when Insert completion is active.
- */
-int ins_compl_active(void)
+/// Check that Insert completion is active.
+bool ins_compl_active(void)
+ FUNC_ATTR_PURE
{
return compl_started;
}
@@ -2918,14 +2911,13 @@ static int ins_compl_bs(void)
return NUL;
}
-/*
- * Return TRUE when we need to find matches again, ins_compl_restart() is to
- * be called.
- */
-static int ins_compl_need_restart(void)
+/// Check that we need to find matches again, ins_compl_restart() is to
+/// be called.
+static bool ins_compl_need_restart(void)
+ FUNC_ATTR_PURE
{
- /* Return TRUE if we didn't complete finding matches or when the
- * 'completefunc' returned "always" in the "refresh" dictionary item. */
+ // Return true if we didn't complete finding matches or when the
+ // "completefunc" returned "always" in the "refresh" dictionary item.
return compl_was_interrupted
|| ((ctrl_x_mode == CTRL_X_FUNCTION || ctrl_x_mode == CTRL_X_OMNI)
&& compl_opt_refresh_always);
@@ -3073,16 +3065,16 @@ static void ins_compl_addfrommatch(void)
ins_compl_addleader(c);
}
-/*
- * Prepare for Insert mode completion, or stop it.
- * Called just after typing a character in Insert mode.
- * Returns TRUE when the character is not to be inserted;
- */
-static int ins_compl_prep(int c)
+/// Prepare for Insert mode completion, or stop it.
+/// Called just after typing a character in Insert mode.
+///
+/// @param c character that was typed
+///
+/// @return true when the character is not to be inserted;
+static bool ins_compl_prep(int c)
{
- char_u *ptr;
- int want_cindent;
- int retval = FALSE;
+ char_u *ptr;
+ bool retval = false;
/* Forget any previous 'special' messages if this is actually
* a ^X mode key - bar ^R, in which case we wait to see what it gives us.
@@ -3092,8 +3084,10 @@ static int ins_compl_prep(int c)
/* Ignore end of Select mode mapping and mouse scroll buttons. */
if (c == K_SELECT || c == K_MOUSEDOWN || c == K_MOUSEUP
- || c == K_MOUSELEFT || c == K_MOUSERIGHT)
+ || c == K_MOUSELEFT || c == K_MOUSERIGHT || c == K_EVENT
+ || c == K_FOCUSGAINED || c == K_FOCUSLOST) {
return retval;
+ }
/* Set "compl_get_longest" when finding the first matches. */
if (ctrl_x_mode == CTRL_X_NOT_DEFINED_YET
@@ -3247,11 +3241,9 @@ static int ins_compl_prep(int c)
ins_compl_fixRedoBufForLeader(ptr);
}
- want_cindent = (can_cindent && cindent_on());
- /*
- * When completing whole lines: fix indent for 'cindent'.
- * Otherwise, break line if it's too long.
- */
+ bool want_cindent = (can_cindent && cindent_on());
+ // When completing whole lines: fix indent for 'cindent'.
+ // Otherwise, break line if it's too long.
if (compl_cont_mode == CTRL_X_WHOLE_LINE) {
/* re-indent the current line */
if (want_cindent) {
@@ -3271,22 +3263,24 @@ static int ins_compl_prep(int c)
inc_cursor();
}
- /* If the popup menu is displayed pressing CTRL-Y means accepting
- * the selection without inserting anything. When
- * compl_enter_selects is set the Enter key does the same. */
+ // If the popup menu is displayed pressing CTRL-Y means accepting
+ // the selection without inserting anything. When
+ // compl_enter_selects is set the Enter key does the same.
if ((c == Ctrl_Y || (compl_enter_selects
&& (c == CAR || c == K_KENTER || c == NL)))
- && pum_visible())
- retval = TRUE;
+ && pum_visible()) {
+ retval = true;
+ }
/* CTRL-E means completion is Ended, go back to the typed text. */
if (c == Ctrl_E) {
ins_compl_delete();
- if (compl_leader != NULL)
+ if (compl_leader != NULL) {
ins_bytes(compl_leader + ins_compl_len());
- else if (compl_first_match != NULL)
+ } else if (compl_first_match != NULL) {
ins_bytes(compl_orig_text + ins_compl_len());
- retval = TRUE;
+ }
+ retval = true;
}
auto_format(FALSE, TRUE);
@@ -4245,22 +4239,22 @@ void ins_compl_check_keys(int frequency)
static int ins_compl_key2dir(int c)
{
if (c == Ctrl_P || c == Ctrl_L
- || (pum_visible() && (c == K_PAGEUP || c == K_KPAGEUP
- || c == K_S_UP || c == K_UP)))
+ || c == K_PAGEUP || c == K_KPAGEUP
+ || c == K_S_UP || c == K_UP) {
return BACKWARD;
+ }
return FORWARD;
}
-/*
- * Return TRUE for keys that are used for completion only when the popup menu
- * is visible.
- */
-static int ins_compl_pum_key(int c)
+/// Check that "c" is a valid completion key only while the popup menu is shown
+///
+/// @param c character to check
+static bool ins_compl_pum_key(int c)
+ FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT
{
return pum_visible() && (c == K_PAGEUP || c == K_KPAGEUP || c == K_S_UP
- || c == K_PAGEDOWN || c == K_KPAGEDOWN || c ==
- K_S_DOWN
- || c == K_UP || c == K_DOWN);
+ || c == K_PAGEDOWN || c == K_KPAGEDOWN
+ || c == K_S_DOWN || c == K_UP || c == K_DOWN);
}
/*
@@ -4280,11 +4274,12 @@ static int ins_compl_key2count(int c)
return 1;
}
-/*
- * Return TRUE if completion with "c" should insert the match, FALSE if only
- * to change the currently selected completion.
- */
-static int ins_compl_use_match(int c)
+/// Check that completion with "c" should insert the match, false if only
+/// to change the currently selected completion.
+///
+/// @param c character to check
+static bool ins_compl_use_match(int c)
+ FUNC_ATTR_CONST FUNC_ATTR_WARN_UNUSED_RESULT
{
switch (c) {
case K_UP:
@@ -4295,9 +4290,9 @@ static int ins_compl_use_match(int c)
case K_PAGEUP:
case K_KPAGEUP:
case K_S_UP:
- return FALSE;
+ return false;
}
- return TRUE;
+ return true;
}
/*
@@ -6313,18 +6308,22 @@ char_u *get_last_insert_save(void)
return s;
}
-/*
- * Check the word in front of the cursor for an abbreviation.
- * Called when the non-id character "c" has been entered.
- * When an abbreviation is recognized it is removed from the text and
- * the replacement string is inserted in typebuf.tb_buf[], followed by "c".
- */
-static int echeck_abbr(int c)
+/// Check the word in front of the cursor for an abbreviation.
+/// Called when the non-id character "c" has been entered.
+/// When an abbreviation is recognized it is removed from the text and
+/// the replacement string is inserted in typebuf.tb_buf[], followed by "c".
+///
+/// @param c character
+///
+/// @return true if the word is a known abbreviation.
+static bool echeck_abbr(int c)
+ FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT
{
- /* Don't check for abbreviation in paste mode, when disabled and just
- * after moving around with cursor keys. */
- if (p_paste || no_abbr || arrow_used)
- return FALSE;
+ // Don't check for abbreviation in paste mode, when disabled and just
+ // after moving around with cursor keys.
+ if (p_paste || no_abbr || arrow_used) {
+ return false;
+ }
return check_abbr(c, get_cursor_line_ptr(), curwin->w_cursor.col,
curwin->w_cursor.lnum == Insstart.lnum ? Insstart.col : 0);
@@ -6560,13 +6559,11 @@ static void replace_do_bs(int limit_col)
(void)del_char_after_col(limit_col);
}
-/*
- * Return TRUE if C-indenting is on.
- */
-static int cindent_on(void) {
- return !p_paste && (curbuf->b_p_cin
- || *curbuf->b_p_inde != NUL
- );
+/// Check that C-indenting is on.
+static bool cindent_on(void)
+ FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT
+{
+ return !p_paste && (curbuf->b_p_cin || *curbuf->b_p_inde != NUL);
}
/*
@@ -6596,32 +6593,33 @@ void fix_indent(void) {
do_c_expr_indent();
}
-/*
- * return TRUE if 'cinkeys' contains the key "keytyped",
- * when == '*': Only if key is preceded with '*' (indent before insert)
- * when == '!': Only if key is preceded with '!' (don't insert)
- * when == ' ': Only if key is not preceded with '*'(indent afterwards)
- *
- * "keytyped" can have a few special values:
- * KEY_OPEN_FORW
- * KEY_OPEN_BACK
- * KEY_COMPLETE just finished completion.
- *
- * If line_is_empty is TRUE accept keys with '0' before them.
- */
-int in_cinkeys(int keytyped, int when, int line_is_empty)
+/// Check that "cinkeys" contains the key "keytyped",
+/// when == '*': Only if key is preceded with '*' (indent before insert)
+/// when == '!': Only if key is preceded with '!' (don't insert)
+/// when == ' ': Only if key is not preceded with '*' (indent afterwards)
+///
+/// "keytyped" can have a few special values:
+/// KEY_OPEN_FORW :
+/// KEY_OPEN_BACK :
+/// KEY_COMPLETE : Just finished completion.
+///
+/// @param keytyped key that was typed
+/// @param when condition on when to perform the check
+/// @param line_is_empty when true, accept keys with '0' before them.
+bool in_cinkeys(int keytyped, int when, bool line_is_empty)
{
- char_u *look;
+ char_u *look;
int try_match;
int try_match_word;
- char_u *p;
- char_u *line;
+ char_u *p;
+ char_u *line;
int icase;
int i;
- if (keytyped == NUL)
- /* Can happen with CTRL-Y and CTRL-E on a short line. */
- return FALSE;
+ if (keytyped == NUL) {
+ // Can happen with CTRL-Y and CTRL-E on a short line.
+ return false;
+ }
if (*curbuf->b_p_inde != NUL)
look = curbuf->b_p_indk; /* 'indentexpr' set: use 'indentkeys' */
@@ -6637,68 +6635,64 @@ int in_cinkeys(int keytyped, int when, int line_is_empty)
case '!': try_match = (*look == '!'); break;
default: try_match = (*look != '*'); break;
}
- if (*look == '*' || *look == '!')
- ++look;
+ if (*look == '*' || *look == '!') {
+ look++;
+ }
- /*
- * If there is a '0', only accept a match if the line is empty.
- * But may still match when typing last char of a word.
- */
+ // If there is a '0', only accept a match if the line is empty.
+ // But may still match when typing last char of a word.
if (*look == '0') {
try_match_word = try_match;
- if (!line_is_empty)
- try_match = FALSE;
- ++look;
- } else
- try_match_word = FALSE;
+ if (!line_is_empty) {
+ try_match = false;
+ }
+ look++;
+ } else {
+ try_match_word = false;
+ }
- /*
- * does it look like a control character?
- */
- if (*look == '^'
- && look[1] >= '?' && look[1] <= '_'
- ) {
- if (try_match && keytyped == Ctrl_chr(look[1]))
- return TRUE;
+ // Does it look like a control character?
+ if (*look == '^' && look[1] >= '?' && look[1] <= '_') {
+ if (try_match && keytyped == Ctrl_chr(look[1])) {
+ return true;
+ }
look += 2;
- }
- /*
- * 'o' means "o" command, open forward.
- * 'O' means "O" command, open backward.
- */
- else if (*look == 'o') {
- if (try_match && keytyped == KEY_OPEN_FORW)
- return TRUE;
- ++look;
+
+ // 'o' means "o" command, open forward.
+ // 'O' means "O" command, open backward.
+ } else if (*look == 'o') {
+ if (try_match && keytyped == KEY_OPEN_FORW) {
+ return true;
+ }
+ look++;
} else if (*look == 'O') {
- if (try_match && keytyped == KEY_OPEN_BACK)
- return TRUE;
- ++look;
- }
- /*
- * 'e' means to check for "else" at start of line and just before the
- * cursor.
- */
- else if (*look == 'e') {
+ if (try_match && keytyped == KEY_OPEN_BACK) {
+ return true;
+ }
+ look++;
+
+ // 'e' means to check for "else" at start of line and just before the
+ // cursor.
+ } else if (*look == 'e') {
if (try_match && keytyped == 'e' && curwin->w_cursor.col >= 4) {
p = get_cursor_line_ptr();
if (skipwhite(p) == p + curwin->w_cursor.col - 4 &&
- STRNCMP(p + curwin->w_cursor.col - 4, "else", 4) == 0)
- return TRUE;
+ STRNCMP(p + curwin->w_cursor.col - 4, "else", 4) == 0) {
+ return true;
+ }
}
- ++look;
- }
- /*
- * ':' only causes an indent if it is at the end of a label or case
- * statement, or when it was before typing the ':' (to fix
- * class::method for C++).
- */
- else if (*look == ':') {
+ look++;
+
+ // ':' only causes an indent if it is at the end of a label or case
+ // statement, or when it was before typing the ':' (to fix
+ // class::method for C++).
+ } else if (*look == ':') {
if (try_match && keytyped == ':') {
p = get_cursor_line_ptr();
- if (cin_iscase(p, FALSE) || cin_isscopedecl(p) || cin_islabel())
- return TRUE;
- /* Need to get the line again after cin_islabel(). */
+ if (cin_iscase(p, false) || cin_isscopedecl(p) || cin_islabel()) {
+ return true;
+ }
+ // Need to get the line again after cin_islabel().
p = get_cursor_line_ptr();
if (curwin->w_cursor.col > 2
&& p[curwin->w_cursor.col - 1] == ':'
@@ -6708,28 +6702,27 @@ int in_cinkeys(int keytyped, int when, int line_is_empty)
|| cin_islabel());
p = get_cursor_line_ptr();
p[curwin->w_cursor.col - 1] = ':';
- if (i)
- return TRUE;
+ if (i) {
+ return true;
+ }
}
}
- ++look;
- }
- /*
- * Is it a key in <>, maybe?
- */
- else if (*look == '<') {
+ look++;
+
+ // Is it a key in <>, maybe?
+ } else if (*look == '<') {
if (try_match) {
- /*
- * make up some named keys <o>, <O>, <e>, <0>, <>>, <<>, <*>,
- * <:> and <!> so that people can re-indent on o, O, e, 0, <,
- * >, *, : and ! keys if they really really want to.
- */
+ // make up some named keys <o>, <O>, <e>, <0>, <>>, <<>, <*>,
+ // <:> and <!> so that people can re-indent on o, O, e, 0, <,
+ // >, *, : and ! keys if they really really want to.
if (vim_strchr((char_u *)"<>!*oOe0:", look[1]) != NULL
- && keytyped == look[1])
- return TRUE;
+ && keytyped == look[1]) {
+ return true;
+ }
- if (keytyped == get_special_key_code(look + 1))
- return TRUE;
+ if (keytyped == get_special_key_code(look + 1)) {
+ return true;
+ }
}
while (*look && *look != '>')
look++;
@@ -6800,18 +6793,18 @@ int in_cinkeys(int keytyped, int when, int line_is_empty)
(int)(curwin->w_cursor.col - (p - look)))
match = FALSE;
}
- if (match)
- return TRUE;
+ if (match) {
+ return true;
+ }
}
look = p;
- }
- /*
- * ok, it's a boring generic character.
- */
- else {
- if (try_match && *look == keytyped)
- return TRUE;
- ++look;
+
+ // Ok, it's a boring generic character.
+ } else {
+ if (try_match && *look == keytyped) {
+ return true;
+ }
+ look++;
}
/*
@@ -6819,7 +6812,7 @@ int in_cinkeys(int keytyped, int when, int line_is_empty)
*/
look = skip_to_option_part(look);
}
- return FALSE;
+ return false;
}
/*
@@ -7046,27 +7039,24 @@ static void ins_ctrl_hat(void)
status_redraw_curbuf();
}
-/*
- * Handle ESC in insert mode.
- * Returns TRUE when leaving insert mode, FALSE when going to repeat the
- * insert.
- */
-static int
-ins_esc (
- long *count,
- int cmdchar,
- int nomove /* don't move cursor */
-)
+/// Handle ESC in insert mode.
+///
+/// @param[in,out] count repeat count of the insert command
+/// @param cmdchar command that started the insert
+/// @param nomove when true, don't move the cursor
+///
+/// @return true when leaving insert mode, false when repeating the insert.
+static bool ins_esc(long *count, int cmdchar, bool nomove)
+ FUNC_ATTR_NONNULL_ARG(1)
{
- int temp;
- static int disabled_redraw = FALSE;
+ static bool disabled_redraw = false;
check_spell_redraw();
- temp = curwin->w_cursor.col;
+ int temp = curwin->w_cursor.col;
if (disabled_redraw) {
- --RedrawingDisabled;
- disabled_redraw = FALSE;
+ RedrawingDisabled--;
+ disabled_redraw = false;
}
if (!arrow_used) {
/*
@@ -7096,9 +7086,10 @@ ins_esc (
if (cmdchar == 'r' || cmdchar == 'v') {
stuffRedoReadbuff(ESC_STR); // No ESC in redo buffer
}
- ++RedrawingDisabled;
- disabled_redraw = TRUE;
- return FALSE; /* repeat the insert */
+ RedrawingDisabled++;
+ disabled_redraw = true;
+ // Repeat the insert
+ return false;
}
stop_insert(&curwin->w_cursor, TRUE, nomove);
undisplay_dollar();
@@ -7148,16 +7139,15 @@ ins_esc (
setmouse();
ui_cursor_shape(); /* may show different cursor shape */
- /*
- * When recording or for CTRL-O, need to display the new mode.
- * Otherwise remove the mode message.
- */
- if (Recording || restart_edit != NUL)
+ // When recording or for CTRL-O, need to display the new mode.
+ // Otherwise remove the mode message.
+ if (Recording || restart_edit != NUL) {
showmode();
- else if (p_smd)
+ } else if (p_smd) {
MSG("");
-
- return TRUE; /* exit Insert mode */
+ }
+ // Exit Insert mode
+ return true;
}
/*
@@ -7195,14 +7185,16 @@ static void ins_ctrl_(void)
showmode();
}
-/*
- * If 'keymodel' contains "startsel", may start selection.
- * Returns TRUE when a CTRL-O and other keys stuffed.
- */
-static int ins_start_select(int c)
+/// If 'keymodel' contains "startsel", may start selection.
+///
+/// @param c character to check
+//
+/// @return true when a CTRL-O and other keys stuffed.
+static bool ins_start_select(int c)
+ FUNC_ATTR_WARN_UNUSED_RESULT
{
if (!km_startsel) {
- return FALSE;
+ return false;
}
switch (c) {
case K_KHOME:
@@ -7213,32 +7205,27 @@ static int ins_start_select(int c)
case K_KPAGEDOWN:
if (!(mod_mask & MOD_MASK_SHIFT))
break;
- /* FALLTHROUGH */
+ // FALLTHROUGH
case K_S_LEFT:
case K_S_RIGHT:
case K_S_UP:
case K_S_DOWN:
case K_S_END:
case K_S_HOME:
- /* Start selection right away, the cursor can move with
- * CTRL-O when beyond the end of the line. */
+ // Start selection right away, the cursor can move with
+ // CTRL-O when beyond the end of the line.
start_selection();
- /* Execute the key in (insert) Select mode. */
+ // Execute the key in (insert) Select mode.
stuffcharReadbuff(Ctrl_O);
if (mod_mask) {
- char_u buf[4];
-
- buf[0] = K_SPECIAL;
- buf[1] = KS_MODIFIER;
- buf[2] = mod_mask;
- buf[3] = NUL;
+ char_u buf[4] = { K_SPECIAL, KS_MODIFIER, mod_mask, NUL };
stuffReadbuff(buf);
}
stuffcharReadbuff(c);
- return TRUE;
+ return true;
}
- return FALSE;
+ return false;
}
/*
@@ -7362,18 +7349,23 @@ static void ins_bs_one(colnr_T *vcolp)
(void)del_char(FALSE);
}
-/*
- * Handle Backspace, delete-word and delete-line in Insert mode.
- * Return TRUE when backspace was actually used.
- */
-static int ins_bs(int c, int mode, int *inserted_space_p)
+/// Handle Backspace, delete-word and delete-line in Insert mode.
+///
+/// @param c charcter that was typed
+/// @param mode backspace mode to use
+/// @param[in,out] inserted_space_p whether a space was the last
+// character inserted
+///
+/// @return true when backspace was actually used.
+static bool ins_bs(int c, int mode, int *inserted_space_p)
+ FUNC_ATTR_NONNULL_ARG(3)
{
linenr_T lnum;
int cc;
int temp = 0; /* init for GCC */
colnr_T save_col;
colnr_T mincol;
- int did_backspace = FALSE;
+ bool did_backspace = false;
int in_indent;
int oldState;
int cpc[MAX_MCO]; /* composing characters */
@@ -7399,28 +7391,29 @@ static int ins_bs(int c, int mode, int *inserted_space_p)
return false;
}
- if (stop_arrow() == FAIL)
- return FALSE;
+ if (stop_arrow() == FAIL) {
+ return false;
+ }
in_indent = inindent(0);
- if (in_indent)
- can_cindent = FALSE;
- end_comment_pending = NUL; /* After BS, don't auto-end comment */
- if (revins_on) /* put cursor after last inserted char */
+ if (in_indent) {
+ can_cindent = false;
+ }
+ end_comment_pending = NUL; // After BS, don't auto-end comment
+ if (revins_on) { // put cursor after last inserted char
inc_cursor();
-
- /* Virtualedit:
- * BACKSPACE_CHAR eats a virtual space
- * BACKSPACE_WORD eats all coladd
- * BACKSPACE_LINE eats all coladd and keeps going
- */
+ }
+ // Virtualedit:
+ // BACKSPACE_CHAR eats a virtual space
+ // BACKSPACE_WORD eats all coladd
+ // BACKSPACE_LINE eats all coladd and keeps going
if (curwin->w_cursor.coladd > 0) {
if (mode == BACKSPACE_CHAR) {
- --curwin->w_cursor.coladd;
- return TRUE;
+ curwin->w_cursor.coladd--;
+ return true;
}
if (mode == BACKSPACE_WORD) {
curwin->w_cursor.coladd = 0;
- return TRUE;
+ return true;
}
curwin->w_cursor.coladd = 0;
}
@@ -7432,10 +7425,10 @@ static int ins_bs(int c, int mode, int *inserted_space_p)
lnum = Insstart.lnum;
if (curwin->w_cursor.lnum == lnum || revins_on) {
if (u_save((linenr_T)(curwin->w_cursor.lnum - 2),
- (linenr_T)(curwin->w_cursor.lnum + 1)) == FAIL) {
- return FALSE;
+ (linenr_T)(curwin->w_cursor.lnum + 1)) == FAIL) {
+ return false;
}
- --Insstart.lnum;
+ Insstart.lnum--;
Insstart.col = MAXCOL;
}
/*
@@ -7677,12 +7670,12 @@ static int ins_bs(int c, int mode, int *inserted_space_p)
if (vim_strchr(p_cpo, CPO_BACKSPACE) != NULL && dollar_vcol == -1)
dollar_vcol = curwin->w_virtcol;
- /* When deleting a char the cursor line must never be in a closed fold.
- * E.g., when 'foldmethod' is indent and deleting the first non-white
- * char before a Tab. */
- if (did_backspace)
+ // When deleting a char the cursor line must never be in a closed fold.
+ // E.g., when 'foldmethod' is indent and deleting the first non-white
+ // char before a Tab.
+ if (did_backspace) {
foldOpenCursor();
-
+ }
return did_backspace;
}
@@ -8001,35 +7994,37 @@ static void ins_pagedown(void)
}
}
-/*
- * Handle TAB in Insert or Replace mode.
- * Return TRUE when the TAB needs to be inserted like a normal character.
- */
-static int ins_tab(void)
+/// Handle TAB in Insert or Replace mode.
+///
+/// @return true when the TAB needs to be inserted like a normal character.
+static bool ins_tab(void)
+ FUNC_ATTR_WARN_UNUSED_RESULT
{
- int ind;
int i;
int temp;
- if (Insstart_blank_vcol == MAXCOL && curwin->w_cursor.lnum == Insstart.lnum)
+ if (Insstart_blank_vcol == MAXCOL && curwin->w_cursor.lnum == Insstart.lnum) {
Insstart_blank_vcol = get_nolist_virtcol();
- if (echeck_abbr(TAB + ABBR_OFF))
- return FALSE;
+ }
+ if (echeck_abbr(TAB + ABBR_OFF)) {
+ return false;
+ }
- ind = inindent(0);
- if (ind)
- can_cindent = FALSE;
+ int ind = inindent(0);
+ if (ind) {
+ can_cindent = false;
+ }
- /*
- * When nothing special, insert TAB like a normal character
- */
+ // When nothing special, insert TAB like a normal character
if (!curbuf->b_p_et
&& !(p_sta && ind && curbuf->b_p_ts != get_sw_value(curbuf))
- && get_sts_value() == 0)
- return TRUE;
+ && get_sts_value() == 0) {
+ return true;
+ }
- if (stop_arrow() == FAIL)
- return TRUE;
+ if (stop_arrow() == FAIL) {
+ return true;
+ }
did_ai = FALSE;
did_si = FALSE;
@@ -8037,12 +8032,13 @@ static int ins_tab(void)
can_si_back = FALSE;
AppendToRedobuff((char_u *)"\t");
- if (p_sta && ind) /* insert tab in indent, use 'shiftwidth' */
+ if (p_sta && ind) { // insert tab in indent, use "shiftwidth"
temp = get_sw_value(curbuf);
- else if (curbuf->b_p_sts != 0) /* use 'softtabstop' when set */
+ } else if (curbuf->b_p_sts != 0) { // use "softtabstop" when set
temp = get_sts_value();
- else /* otherwise use 'tabstop' */
+ } else { // otherwise use "tabstop"
temp = (int)curbuf->b_p_ts;
+ }
temp -= get_nolist_virtcol() % temp;
/*
@@ -8182,21 +8178,20 @@ static int ins_tab(void)
curwin->w_p_list = save_list;
}
- return FALSE;
+ return false;
}
-/*
- * Handle CR or NL in insert mode.
- * Return TRUE when it can't undo.
- */
-static int ins_eol(int c)
+/// Handle CR or NL in insert mode.
+///
+/// @return true when it can't undo.
+static bool ins_eol(int c)
{
- int i;
-
- if (echeck_abbr(c + ABBR_OFF))
- return FALSE;
- if (stop_arrow() == FAIL)
- return TRUE;
+ if (echeck_abbr(c + ABBR_OFF)) {
+ return false;
+ }
+ if (stop_arrow() == FAIL) {
+ return true;
+ }
undisplay_dollar();
/*
@@ -8229,9 +8224,9 @@ static int ins_eol(int c)
curwin->w_cursor.col += (colnr_T)STRLEN(get_cursor_pos_ptr());
AppendToRedobuff(NL_STR);
- i = open_line(FORWARD,
- has_format_option(FO_RET_COMS) ? OPENLINE_DO_COM :
- 0, old_indent);
+ bool i = open_line(FORWARD,
+ has_format_option(FO_RET_COMS) ? OPENLINE_DO_COM : 0,
+ old_indent);
old_indent = 0;
can_cindent = TRUE;
/* When inserting a line the cursor line must never be in a closed fold. */
diff --git a/src/nvim/eval.c b/src/nvim/eval.c
index 72f2b984b0..5477e79cad 100644
--- a/src/nvim/eval.c
+++ b/src/nvim/eval.c
@@ -160,6 +160,7 @@ static char *e_listdictarg = N_(
static char *e_emptykey = N_("E713: Cannot use empty key for Dictionary");
static char *e_listreq = N_("E714: List required");
static char *e_dictreq = N_("E715: Dictionary required");
+static char *e_strreq = N_("E114: String required");
static char *e_toomanyarg = N_("E118: Too many arguments for function: %s");
static char *e_dictkey = N_("E716: Key not present in Dictionary: %s");
static char *e_funcexts = N_(
@@ -379,6 +380,7 @@ static struct vimvar {
{ VV_NAME("option_type", VAR_STRING), VV_RO },
{ VV_NAME("errors", VAR_LIST), 0 },
{ VV_NAME("msgpack_types", VAR_DICT), VV_RO },
+ { VV_NAME("event", VAR_DICT), VV_RO },
};
/* shorthand */
@@ -546,6 +548,10 @@ void eval_init(void)
set_vim_var_dict(VV_MSGPACK_TYPES, msgpack_types_dict);
set_vim_var_dict(VV_COMPLETED_ITEM, dict_alloc());
+
+ dict_T *v_event = dict_alloc();
+ v_event->dv_lock = VAR_FIXED;
+ set_vim_var_dict(VV_EVENT, v_event);
set_vim_var_list(VV_ERRORS, list_alloc());
set_vim_var_nr(VV_SEARCHFORWARD, 1L);
set_vim_var_nr(VV_HLSEARCH, 1L);
@@ -4011,12 +4017,22 @@ eval6 (
* When either side is a float the result is a float.
*/
if (use_float) {
- if (op == '*')
+ if (op == '*') {
f1 = f1 * f2;
- else if (op == '/') {
- /* We rely on the floating point library to handle divide
- * by zero to result in "inf" and not a crash. */
- f1 = f2 != 0 ? f1 / f2 : INFINITY;
+ } else if (op == '/') {
+ // Division by zero triggers error from AddressSanitizer
+ f1 = (f2 == 0
+ ? (
+#ifdef NAN
+ f1 == 0
+ ? NAN
+ :
+#endif
+ (f1 > 0
+ ? INFINITY
+ : -INFINITY)
+ )
+ : f1 / f2);
} else {
EMSG(_("E804: Cannot use '%' with Float"));
return FAIL;
@@ -6008,6 +6024,27 @@ static void rettv_dict_alloc(typval_T *rettv)
++d->dv_refcount;
}
+/// Clear all the keys of a Dictionary. "d" remains a valid empty Dictionary.
+///
+/// @param d The Dictionary to clear
+void dict_clear(dict_T *d)
+ FUNC_ATTR_NONNULL_ALL
+{
+ hash_lock(&d->dv_hashtab);
+ assert(d->dv_hashtab.ht_locked > 0);
+
+ size_t todo = d->dv_hashtab.ht_used;
+ for (hashitem_T *hi = d->dv_hashtab.ht_array; todo > 0; hi++) {
+ if (!HASHITEM_EMPTY(hi)) {
+ dictitem_free(HI2DI(hi));
+ hash_remove(&d->dv_hashtab, hi);
+ todo--;
+ }
+ }
+
+ hash_unlock(&d->dv_hashtab);
+}
+
/*
* Unreference a Dictionary: decrement the reference count and free it when it
@@ -6249,6 +6286,24 @@ int dict_add_list(dict_T *d, char *key, list_T *list)
return OK;
}
+/// Set all existing keys in "dict" as read-only.
+///
+/// This does not protect against adding new keys to the Dictionary.
+///
+/// @param dict The dict whose keys should be frozen
+void dict_set_keys_readonly(dict_T *dict)
+ FUNC_ATTR_NONNULL_ALL
+{
+ size_t todo = dict->dv_hashtab.ht_used;
+ for (hashitem_T *hi = dict->dv_hashtab.ht_array; todo > 0 ; hi++) {
+ if (HASHITEM_EMPTY(hi)) {
+ continue;
+ }
+ todo--;
+ HI2DI(hi)->di_flags |= DI_FLAGS_RO | DI_FLAGS_FIX;
+ }
+}
+
/*
* Get the number of items in a Dictionary.
*/
@@ -6849,9 +6904,25 @@ vim_to_msgpack_error_ret: \
#define CONV_FLOAT(flt) \
do { \
- char numbuf[NUMBUFLEN]; \
- vim_snprintf(numbuf, NUMBUFLEN - 1, "%g", (flt)); \
- ga_concat(gap, (char_u *) numbuf); \
+ const float_T flt_ = (flt); \
+ switch (fpclassify(flt_)) { \
+ case FP_NAN: { \
+ ga_concat(gap, (char_u *) "str2float('nan')"); \
+ break; \
+ } \
+ case FP_INFINITE: { \
+ if (flt_ < 0) { \
+ ga_append(gap, '-'); \
+ } \
+ ga_concat(gap, (char_u *) "str2float('inf')"); \
+ break; \
+ } \
+ default: { \
+ char numbuf[NUMBUFLEN]; \
+ vim_snprintf(numbuf, NUMBUFLEN - 1, "%g", flt_); \
+ ga_concat(gap, (char_u *) numbuf); \
+ } \
+ } \
} while (0)
#define CONV_FUNC(fun) \
@@ -7291,7 +7362,7 @@ static struct fst {
{ "pathshorten", 1, 1, f_pathshorten },
{ "pow", 2, 2, f_pow },
{ "prevnonblank", 1, 1, f_prevnonblank },
- { "printf", 2, 19, f_printf },
+ { "printf", 2, MAX_FUNC_ARGS, f_printf },
{ "pumvisible", 0, 0, f_pumvisible },
{ "py3eval", 1, 1, f_py3eval },
{ "pyeval", 1, 1, f_pyeval },
@@ -7305,8 +7376,8 @@ static struct fst {
{ "resolve", 1, 1, f_resolve },
{ "reverse", 1, 1, f_reverse },
{ "round", 1, 1, f_round },
- { "rpcnotify", 2, 64, f_rpcnotify },
- { "rpcrequest", 2, 64, f_rpcrequest },
+ { "rpcnotify", 2, MAX_FUNC_ARGS, f_rpcnotify },
+ { "rpcrequest", 2, MAX_FUNC_ARGS, f_rpcrequest },
{ "rpcstart", 1, 2, f_rpcstart },
{ "rpcstop", 1, 1, f_rpcstop },
{ "screenattr", 2, 2, f_screenattr },
@@ -10554,8 +10625,6 @@ static void f_getregtype(typval_T *argvars, typval_T *rettv)
{
char_u *strregname;
int regname;
- char_u buf[NUMBUFLEN + 2];
- long reglen = 0;
if (argvars[0].v_type != VAR_UNKNOWN) {
strregname = get_tv_string_chk(&argvars[0]);
@@ -10572,18 +10641,13 @@ static void f_getregtype(typval_T *argvars, typval_T *rettv)
if (regname == 0)
regname = '"';
- buf[0] = NUL;
- buf[1] = NUL;
- switch (get_reg_type(regname, &reglen)) {
- case MLINE: buf[0] = 'V'; break;
- case MCHAR: buf[0] = 'v'; break;
- case MBLOCK:
- buf[0] = Ctrl_V;
- sprintf((char *)buf + 1, "%" PRId64, (int64_t)(reglen + 1));
- break;
- }
+ colnr_T reglen = 0;
+ char buf[NUMBUFLEN + 2];
+ char_u reg_type = get_reg_type(regname, &reglen);
+ format_reg_type(reg_type, reglen, buf, ARRAY_SIZE(buf));
+
rettv->v_type = VAR_STRING;
- rettv->vval.v_string = vim_strsave(buf);
+ rettv->vval.v_string = (char_u *)xstrdup(buf);
}
/*
@@ -15229,43 +15293,51 @@ static void f_setline(typval_T *argvars, typval_T *rettv)
/// replace its content or create a new one.
/// @param[in] title_arg New list title. Defaults to caller function name.
/// @param[out] rettv Return value: 0 in case of success, -1 otherwise.
-static void set_qf_ll_list(win_T *wp, typval_T *list_arg, typval_T *action_arg,
- typval_T *title_arg, typval_T *rettv)
- FUNC_ATTR_NONNULL_ARG(2, 3, 4, 5)
+static void set_qf_ll_list(win_T *wp, typval_T *args, typval_T *rettv)
+ FUNC_ATTR_NONNULL_ARG(2, 3)
{
- char_u *act;
- int action = ' ';
char_u *title = NULL;
-
+ int action = ' ';
rettv->vval.v_number = -1;
- if (list_arg->v_type != VAR_LIST)
+ typval_T *list_arg = &args[0];
+ if (list_arg->v_type != VAR_LIST) {
EMSG(_(e_listreq));
- else {
- list_T *l = list_arg->vval.v_list;
+ return;
+ }
- if (action_arg->v_type != VAR_UNKNOWN) {
- act = get_tv_string_chk(action_arg);
- if (act == NULL)
- return; /* type error; errmsg already given */
- if (*act == 'a' || *act == 'r')
- action = *act;
- }
+ typval_T *action_arg = &args[1];
+ if (action_arg->v_type == VAR_UNKNOWN) {
+ // Option argument was not given.
+ goto skip_args;
+ } else if (action_arg->v_type != VAR_STRING) {
+ EMSG(_(e_strreq));
+ return;
+ }
+ char_u *act = get_tv_string_chk(action_arg);
+ if (*act == 'a' || *act == 'r') {
+ action = *act;
+ }
- if (title_arg->v_type == VAR_STRING) {
- title = get_tv_string_chk(title_arg);
- if (!title) {
- return; // type error; errmsg already given
- }
- }
+ typval_T *title_arg = &args[2];
+ if (title_arg->v_type == VAR_UNKNOWN) {
+ // Option argument was not given.
+ goto skip_args;
+ }
+ title = get_tv_string_chk(title_arg);
+ if (!title) {
+ // Type error. Error already printed by get_tv_string_chk().
+ return;
+ }
- if (!title) {
- title = (char_u*)(wp ? "setloclist()" : "setqflist()");
- }
+skip_args:
+ if (!title) {
+ title = (char_u*)(wp ? "setloclist()" : "setqflist()");
+ }
- if (l && set_errorlist(wp, l, action, title) == OK) {
- rettv->vval.v_number = 0;
- }
+ list_T *l = list_arg->vval.v_list;
+ if (l && set_errorlist(wp, l, action, title) == OK) {
+ rettv->vval.v_number = 0;
}
}
@@ -15280,7 +15352,7 @@ static void f_setloclist(typval_T *argvars, typval_T *rettv)
win = find_win_by_nr(&argvars[0], NULL);
if (win != NULL) {
- set_qf_ll_list(win, &argvars[1], &argvars[2], &argvars[3], rettv);
+ set_qf_ll_list(win, &argvars[1], rettv);
}
}
@@ -15417,7 +15489,7 @@ static void f_setpos(typval_T *argvars, typval_T *rettv)
*/
static void f_setqflist(typval_T *argvars, typval_T *rettv)
{
- set_qf_ll_list(NULL, &argvars[0], &argvars[1], &argvars[2], rettv);
+ set_qf_ll_list(NULL, argvars, rettv);
}
/*
@@ -18159,14 +18231,7 @@ void set_vim_var_dict(int idx, dict_T *val)
if (val != NULL) {
++val->dv_refcount;
// Set readonly
- size_t todo = val->dv_hashtab.ht_used;
- for (hashitem_T *hi = val->dv_hashtab.ht_array; todo > 0 ; ++hi) {
- if (HASHITEM_EMPTY(hi)) {
- continue;
- }
- --todo;
- HI2DI(hi)->di_flags = DI_FLAGS_RO | DI_FLAGS_FIX;
- }
+ dict_set_keys_readonly(val);
}
}
@@ -21951,7 +22016,15 @@ repeat:
}
if (src[*usedlen] == ':' && src[*usedlen + 1] == 'S') {
+ // vim_strsave_shellescape() needs a NUL terminated string.
+ c = (*fnamep)[*fnamelen];
+ if (c != NUL) {
+ (*fnamep)[*fnamelen] = NUL;
+ }
p = vim_strsave_shellescape(*fnamep, false, false);
+ if (c != NUL) {
+ (*fnamep)[*fnamelen] = c;
+ }
xfree(*bufp);
*bufp = *fnamep = p;
*fnamelen = STRLEN(p);
diff --git a/src/nvim/eval.h b/src/nvim/eval.h
index 79a1341d98..f51b0f4921 100644
--- a/src/nvim/eval.h
+++ b/src/nvim/eval.h
@@ -113,7 +113,8 @@ enum {
VV_OPTION_TYPE,
VV_ERRORS,
VV_MSGPACK_TYPES,
- VV_LEN, /* number of v: vars */
+ VV_EVENT,
+ VV_LEN, // number of v: vars
};
/// Maximum number of function arguments
diff --git a/src/nvim/ex_cmds.c b/src/nvim/ex_cmds.c
index ad21e71c51..5ea5beb478 100644
--- a/src/nvim/ex_cmds.c
+++ b/src/nvim/ex_cmds.c
@@ -1377,9 +1377,9 @@ char_u *make_filter_cmd(char_u *cmd, char_u *itmp, char_u *otmp)
}
}
#endif
- if (otmp != NULL)
- append_redir(buf, (int)len, p_srr, otmp);
-
+ if (otmp != NULL) {
+ append_redir(buf, len, p_srr, otmp);
+ }
return buf;
}
@@ -1390,7 +1390,7 @@ char_u *make_filter_cmd(char_u *cmd, char_u *itmp, char_u *otmp)
* The caller should make sure that there is enough room:
* STRLEN(opt) + STRLEN(fname) + 3
*/
-void append_redir(char_u *buf, int buflen, char_u *opt, char_u *fname)
+void append_redir(char_u *buf, size_t buflen, char_u *opt, char_u *fname)
{
char_u *p;
char_u *end;
@@ -1506,8 +1506,11 @@ void ex_file(exarg_T *eap)
if (rename_buffer(eap->arg) == FAIL)
return;
}
- /* print full file name if :cd used */
- fileinfo(FALSE, FALSE, eap->forceit);
+
+ if (!shortmess(SHM_FILEINFO)) {
+ // print full file name if :cd used
+ fileinfo(false, false, eap->forceit);
+ }
}
/*
@@ -2483,7 +2486,9 @@ do_ecmd (
msg_scroll = msg_scroll_save;
msg_scrolled_ign = TRUE;
- fileinfo(FALSE, TRUE, FALSE);
+ if (!shortmess(SHM_FILEINFO)) {
+ fileinfo(false, true, false);
+ }
msg_scrolled_ign = FALSE;
}
@@ -3017,7 +3022,7 @@ void do_sub(exarg_T *eap)
// The number of lines joined is the number of lines in the range
linenr_T joined_lines_count = eap->line2 - eap->line1 + 1
// plus one extra line if not at the end of file.
- + eap->line2 < curbuf->b_ml.ml_line_count ? 1 : 0;
+ + (eap->line2 < curbuf->b_ml.ml_line_count ? 1 : 0);
if (joined_lines_count > 1) {
do_join(joined_lines_count, FALSE, TRUE, FALSE, true);
sub_nsubs = joined_lines_count - 1;
diff --git a/src/nvim/ex_cmds2.c b/src/nvim/ex_cmds2.c
index 47774f5a99..71ea170e1c 100644
--- a/src/nvim/ex_cmds2.c
+++ b/src/nvim/ex_cmds2.c
@@ -57,23 +57,23 @@ typedef struct scriptitem_S {
char_u *sn_name;
bool file_id_valid;
FileID file_id;
- int sn_prof_on; /* TRUE when script is/was profiled */
- int sn_pr_force; /* forceit: profile functions in this script */
- proftime_T sn_pr_child; /* time set when going into first child */
- int sn_pr_nest; /* nesting for sn_pr_child */
- /* profiling the script as a whole */
- int sn_pr_count; /* nr of times sourced */
- proftime_T sn_pr_total; /* time spent in script + children */
- proftime_T sn_pr_self; /* time spent in script itself */
- proftime_T sn_pr_start; /* time at script start */
- proftime_T sn_pr_children; /* time in children after script start */
- /* profiling the script per line */
- garray_T sn_prl_ga; /* things stored for every line */
- proftime_T sn_prl_start; /* start time for current line */
- proftime_T sn_prl_children; /* time spent in children for this line */
- proftime_T sn_prl_wait; /* wait start time for current line */
- int sn_prl_idx; /* index of line being timed; -1 if none */
- int sn_prl_execed; /* line being timed was executed */
+ bool sn_prof_on; ///< true when script is/was profiled
+ int sn_pr_force; ///< forceit: profile functions in this script
+ proftime_T sn_pr_child; ///< time set when going into first child
+ int sn_pr_nest; ///< nesting for sn_pr_child
+ // profiling the script as a whole
+ int sn_pr_count; ///< nr of times sourced
+ proftime_T sn_pr_total; ///< time spent in script + children
+ proftime_T sn_pr_self; ///< time spent in script itself
+ proftime_T sn_pr_start; ///< time at script start
+ proftime_T sn_pr_children; ///< time in children after script start
+ // profiling the script per line
+ garray_T sn_prl_ga; ///< things stored for every line
+ proftime_T sn_prl_start; ///< start time for current line
+ proftime_T sn_prl_children; ///< time spent in children for this line
+ proftime_T sn_prl_wait; ///< wait start time for current line
+ linenr_T sn_prl_idx; ///< index of line being timed; -1 if none
+ int sn_prl_execed; ///< line being timed was executed
} scriptitem_T;
static garray_T script_items = {0, 0, sizeof(scriptitem_T), 4, NULL};
@@ -81,9 +81,9 @@ static garray_T script_items = {0, 0, sizeof(scriptitem_T), 4, NULL};
/* Struct used in sn_prl_ga for every line of a script. */
typedef struct sn_prl_S {
- int snp_count; /* nr of times line was executed */
- proftime_T sn_prl_total; /* time spent in a line + children */
- proftime_T sn_prl_self; /* time spent in a line itself */
+ int snp_count; ///< nr of times line was executed
+ proftime_T sn_prl_total; ///< time spent in a line + children
+ proftime_T sn_prl_self; ///< time spent in a line itself
} sn_prl_T;
/*
@@ -93,18 +93,18 @@ typedef struct sn_prl_S {
* sourcing can be done recursively.
*/
struct source_cookie {
- FILE *fp; /* opened file for sourcing */
- char_u *nextline; /* if not NULL: line that was read ahead */
- int finished; /* ":finish" used */
+ FILE *fp; ///< opened file for sourcing
+ char_u *nextline; ///< if not NULL: line that was read ahead
+ int finished; ///< ":finish" used
#if defined(USE_CRNL)
- int fileformat; /* EOL_UNKNOWN, EOL_UNIX or EOL_DOS */
- int error; /* TRUE if LF found after CR-LF */
+ int fileformat; ///< EOL_UNKNOWN, EOL_UNIX or EOL_DOS
+ int error; ///< TRUE if LF found after CR-LF
#endif
- linenr_T breakpoint; /* next line with breakpoint or zero */
- char_u *fname; /* name of sourced file */
- int dbg_tick; /* debug_tick when breakpoint was set */
- int level; /* top nesting level of sourced file */
- vimconv_T conv; /* type of conversion */
+ linenr_T breakpoint; ///< next line with breakpoint or zero
+ char_u *fname; ///< name of sourced file
+ int dbg_tick; ///< debug_tick when breakpoint was set
+ int level; ///< top nesting level of sourced file
+ vimconv_T conv; ///< type of conversion
};
# define PRL_ITEM(si, idx) (((sn_prl_T *)(si)->sn_prl_ga.ga_data)[(idx)])
@@ -272,7 +272,7 @@ void do_debug(char_u *cmd)
xfree(cmdline);
}
- lines_left = Rows - 1;
+ lines_left = (int)(Rows - 1);
}
xfree(cmdline);
@@ -281,7 +281,7 @@ void do_debug(char_u *cmd)
redraw_all_later(NOT_VALID);
need_wait_return = FALSE;
msg_scroll = save_msg_scroll;
- lines_left = Rows - 1;
+ lines_left = (int)(Rows - 1);
State = save_State;
did_emsg = save_did_emsg;
cmd_silent = save_cmd_silent;
@@ -392,12 +392,12 @@ int dbg_check_skipped(exarg_T *eap)
* This is a grow-array of structs.
*/
struct debuggy {
- int dbg_nr; /* breakpoint number */
- int dbg_type; /* DBG_FUNC or DBG_FILE */
- char_u *dbg_name; /* function or file name */
- regprog_T *dbg_prog; /* regexp program */
- linenr_T dbg_lnum; /* line number in function or file */
- int dbg_forceit; /* ! used */
+ int dbg_nr; ///< breakpoint number
+ int dbg_type; ///< DBG_FUNC or DBG_FILE
+ char_u *dbg_name; ///< function or file name
+ regprog_T *dbg_prog; ///< regexp program
+ linenr_T dbg_lnum; ///< line number in function or file
+ int dbg_forceit; ///< ! used
};
static garray_T dbg_breakp = {0, 0, sizeof(struct debuggy), 4, NULL};
@@ -563,13 +563,14 @@ void ex_breakdel(exarg_T *eap)
}
if (ascii_isdigit(*eap->arg)) {
- /* ":breakdel {nr}" */
- nr = atol((char *)eap->arg);
- for (int i = 0; i < gap->ga_len; ++i)
+ // ":breakdel {nr}"
+ nr = atoi((char *)eap->arg);
+ for (int i = 0; i < gap->ga_len; ++i) {
if (DEBUGGY(gap, i).dbg_nr == nr) {
todel = i;
break;
}
+ }
} else if (*eap->arg == '*') {
todel = 0;
del_all = TRUE;
@@ -602,11 +603,13 @@ void ex_breakdel(exarg_T *eap)
--gap->ga_len;
if (todel < gap->ga_len)
memmove(&DEBUGGY(gap, todel), &DEBUGGY(gap, todel + 1),
- (gap->ga_len - todel) * sizeof(struct debuggy));
- if (eap->cmdidx == CMD_breakdel)
+ (size_t)(gap->ga_len - todel) * sizeof(struct debuggy));
+ if (eap->cmdidx == CMD_breakdel) {
++debug_tick;
- if (!del_all)
+ }
+ if (!del_all) {
break;
+ }
}
/* If all breakpoints were removed clear the array. */
@@ -810,8 +813,8 @@ void ex_pydo3(exarg_T *eap)
/* Command line expansion for :profile. */
static enum {
- PEXP_SUBCMD, /* expand :profile sub-commands */
- PEXP_FUNC /* expand :profile func {funcname} */
+ PEXP_SUBCMD, ///< expand :profile sub-commands
+ PEXP_FUNC ///< expand :profile func {funcname}
} pexpand_what;
static char *pexpand_cmds[] = {
@@ -892,7 +895,7 @@ static void profile_reset(void)
for (int id = 1; id <= script_items.ga_len; id++) {
scriptitem_T *si = &SCRIPT_ITEM(id);
if (si->sn_prof_on) {
- si->sn_prof_on = 0;
+ si->sn_prof_on = false;
si->sn_pr_force = 0;
si->sn_pr_child = profile_zero();
si->sn_pr_nest = 0;
@@ -949,7 +952,7 @@ static void profile_init(scriptitem_T *si)
ga_init(&si->sn_prl_ga, sizeof(sn_prl_T), 100);
si->sn_prl_idx = -1;
- si->sn_prof_on = TRUE;
+ si->sn_prof_on = true;
si->sn_pr_nest = 0;
}
@@ -1255,7 +1258,7 @@ check_changed_any (
int save;
int i;
int bufnum = 0;
- int bufcount = 0;
+ size_t bufcount = 0;
int *bufnrs;
FOR_ALL_BUFFERS(buf) {
@@ -1520,7 +1523,7 @@ do_arglist (
didone = TRUE;
xfree(ARGLIST[match].ae_fname);
memmove(ARGLIST + match, ARGLIST + match + 1,
- (ARGCOUNT - match - 1) * sizeof(aentry_T));
+ (size_t)(ARGCOUNT - match - 1) * sizeof(aentry_T));
--ALIST(curwin)->al_ga.ga_len;
if (curwin->w_arg_idx > match)
--curwin->w_arg_idx;
@@ -1537,9 +1540,7 @@ do_arglist (
int i = expand_wildcards(new_ga.ga_len, (char_u **)new_ga.ga_data,
&exp_count, &exp_files, EW_DIR|EW_FILE|EW_ADDSLASH|EW_NOTFOUND);
ga_clear(&new_ga);
- if (i == FAIL)
- return FAIL;
- if (exp_count == 0) {
+ if (i == FAIL || exp_count == 0) {
EMSG(_(e_nomatch));
return FAIL;
}
@@ -1702,10 +1703,11 @@ void ex_argument(exarg_T *eap)
{
int i;
- if (eap->addr_count > 0)
- i = eap->line2 - 1;
- else
+ if (eap->addr_count > 0) {
+ i = (int)eap->line2 - 1;
+ } else {
i = curwin->w_arg_idx;
+ }
do_argfile(eap, i);
}
@@ -1844,22 +1846,25 @@ void ex_argadd(exarg_T *eap)
void ex_argdelete(exarg_T *eap)
{
if (eap->addr_count > 0) {
- /* ":1,4argdel": Delete all arguments in the range. */
- if (eap->line2 > ARGCOUNT)
+ // ":1,4argdel": Delete all arguments in the range.
+ if (eap->line2 > ARGCOUNT) {
eap->line2 = ARGCOUNT;
- int n = eap->line2 - eap->line1 + 1;
- if (*eap->arg != NUL || n <= 0)
+ }
+ linenr_T n = eap->line2 - eap->line1 + 1;
+ if (*eap->arg != NUL || n <= 0) {
EMSG(_(e_invarg));
- else {
- for (int i = eap->line1; i <= eap->line2; ++i)
+ } else {
+ for (linenr_T i = eap->line1; i <= eap->line2; ++i) {
xfree(ARGLIST[i - 1].ae_fname);
+ }
memmove(ARGLIST + eap->line1 - 1, ARGLIST + eap->line2,
- (size_t)((ARGCOUNT - eap->line2) * sizeof(aentry_T)));
- ALIST(curwin)->al_ga.ga_len -= n;
- if (curwin->w_arg_idx >= eap->line2)
- curwin->w_arg_idx -= n;
- else if (curwin->w_arg_idx > eap->line1)
- curwin->w_arg_idx = eap->line1;
+ (size_t)(ARGCOUNT - eap->line2) * sizeof(aentry_T));
+ ALIST(curwin)->al_ga.ga_len -= (int)n;
+ if (curwin->w_arg_idx >= eap->line2) {
+ curwin->w_arg_idx -= (int)n;
+ } else if (curwin->w_arg_idx > eap->line1) {
+ curwin->w_arg_idx = (int)eap->line1;
+ }
}
} else if (*eap->arg == NUL)
EMSG(_(e_argreq));
@@ -1909,7 +1914,7 @@ void ex_listdo(exarg_T *eap)
}
break;
case CMD_argdo:
- i = eap->line1 - 1;
+ i = (int)eap->line1 - 1;
break;
default:
break;
@@ -1942,10 +1947,11 @@ void ex_listdo(exarg_T *eap)
ex_cc(eap);
buf = curbuf;
- i = eap->line1 - 1;
+ i = (int)eap->line1 - 1;
if (eap->addr_count <= 0) {
// Default to all quickfix/location list entries.
- eap->line2 = qf_size;
+ assert(qf_size < MAXLNUM);
+ eap->line2 = (linenr_T)qf_size;
}
}
} else {
@@ -2098,7 +2104,7 @@ alist_add_list (
after = ARGCOUNT;
if (after < ARGCOUNT)
memmove(&(ARGLIST[after + count]), &(ARGLIST[after]),
- (ARGCOUNT - after) * sizeof(aentry_T));
+ (size_t)(ARGCOUNT - after) * sizeof(aentry_T));
for (int i = 0; i < count; ++i) {
ARGLIST[after + i].ae_fname = files[i];
ARGLIST[after + i].ae_fnum = buflist_add(files[i], BLN_LISTED);
@@ -2571,7 +2577,7 @@ do_source (
while (script_items.ga_len < current_SID) {
++script_items.ga_len;
SCRIPT_ITEM(script_items.ga_len).sn_name = NULL;
- SCRIPT_ITEM(script_items.ga_len).sn_prof_on = FALSE;
+ SCRIPT_ITEM(script_items.ga_len).sn_prof_on = false;
}
si = &SCRIPT_ITEM(current_SID);
si->sn_name = fname_exp;
@@ -3386,8 +3392,8 @@ static void script_host_execute(char *name, exarg_T *eap)
// script
list_append_string(args, script ? script : eap->arg, -1);
// current range
- list_append_number(args, eap->line1);
- list_append_number(args, eap->line2);
+ list_append_number(args, (int)eap->line1);
+ list_append_number(args, (int)eap->line2);
(void)eval_call_provider(name, "execute", args);
}
@@ -3403,16 +3409,16 @@ static void script_host_execute_file(char *name, exarg_T *eap)
// filename
list_append_string(args, buffer, -1);
// current range
- list_append_number(args, eap->line1);
- list_append_number(args, eap->line2);
+ list_append_number(args, (int)eap->line1);
+ list_append_number(args, (int)eap->line2);
(void)eval_call_provider(name, "execute_file", args);
}
static void script_host_do_range(char *name, exarg_T *eap)
{
list_T *args = list_alloc();
- list_append_number(args, eap->line1);
- list_append_number(args, eap->line2);
+ list_append_number(args, (int)eap->line1);
+ list_append_number(args, (int)eap->line2);
list_append_string(args, eap->arg, -1);
(void)eval_call_provider(name, "do_range", args);
}
diff --git a/src/nvim/ex_docmd.c b/src/nvim/ex_docmd.c
index 3a24f194c1..a7e98e7f04 100644
--- a/src/nvim/ex_docmd.c
+++ b/src/nvim/ex_docmd.c
@@ -6290,10 +6290,8 @@ void ex_splitview(exarg_T *eap)
if (eap->cmdidx == CMD_tabedit
|| eap->cmdidx == CMD_tabfind
|| eap->cmdidx == CMD_tabnew) {
- if (win_new_tabpage(cmdmod.tab != 0 ? cmdmod.tab
- : eap->addr_count == 0 ? 0
- : (int)eap->line2 + 1) != FAIL) {
- apply_autocmds(EVENT_TABNEW, eap->arg, eap->arg, FALSE, curbuf);
+ if (win_new_tabpage(cmdmod.tab != 0 ? cmdmod.tab : eap->addr_count == 0
+ ? 0 : (int)eap->line2 + 1, eap->arg) != FAIL) {
do_exedit(eap, old_curwin);
apply_autocmds(EVENT_TABNEWENTERED, NULL, NULL, FALSE, curbuf);
diff --git a/src/nvim/ex_eval.c b/src/nvim/ex_eval.c
index bf67047ae8..a1e54e74a6 100644
--- a/src/nvim/ex_eval.c
+++ b/src/nvim/ex_eval.c
@@ -378,7 +378,7 @@ char_u *get_exception_string(void *value, int type, char_u *cmdname, int *should
char_u *p, *val;
if (type == ET_ERROR) {
- *should_free = FALSE;
+ *should_free = true;
mesg = ((struct msglist *)value)->throw_msg;
if (cmdname != NULL && *cmdname != NUL) {
size_t cmdlen = STRLEN(cmdname);
diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c
index 39bff9b2ad..cffda1ca55 100644
--- a/src/nvim/ex_getln.c
+++ b/src/nvim/ex_getln.c
@@ -1130,7 +1130,7 @@ static int command_line_handle_key(CommandLineState *s)
if (!mouse_has(MOUSE_COMMAND)) {
return command_line_not_changed(s); // Ignore mouse
}
- cmdline_paste(0, true, true);
+ cmdline_paste(eval_has_provider("clipboard") ? '*' : 0, true, true);
redrawcmd();
return command_line_changed(s);
@@ -2424,20 +2424,17 @@ void restore_cmdline_alloc(char_u *p)
xfree(p);
}
-/*
- * paste a yank register into the command line.
- * used by CTRL-R command in command-line mode
- * insert_reg() can't be used here, because special characters from the
- * register contents will be interpreted as commands.
- *
- * return FAIL for failure, OK otherwise
- */
-static int
-cmdline_paste (
- int regname,
- int literally, /* Insert text literally instead of "as typed" */
- int remcr /* remove trailing CR */
-)
+/// Paste a yank register into the command line.
+/// Used by CTRL-R command in command-line mode.
+/// insert_reg() can't be used here, because special characters from the
+/// register contents will be interpreted as commands.
+///
+/// @param regname Register name.
+/// @param literally Insert text literally instead of "as typed".
+/// @param remcr When true, remove trailing CR.
+///
+/// @returns FAIL for failure, OK otherwise
+static bool cmdline_paste(int regname, bool literally, bool remcr)
{
long i;
char_u *arg;
diff --git a/src/nvim/fold.c b/src/nvim/fold.c
index 6c135ef47b..70ab4ced75 100644
--- a/src/nvim/fold.c
+++ b/src/nvim/fold.c
@@ -762,6 +762,10 @@ void clearFolding(win_T *win)
*/
void foldUpdate(win_T *wp, linenr_T top, linenr_T bot)
{
+ if (compl_busy) {
+ return;
+ }
+
fold_T *fp;
if (wp->w_buffer->terminal) {
return;
diff --git a/src/nvim/globals.h b/src/nvim/globals.h
index 69e65c3208..40b5718071 100644
--- a/src/nvim/globals.h
+++ b/src/nvim/globals.h
@@ -214,6 +214,10 @@ EXTERN int compl_length INIT(= 0);
* stop looking for matches. */
EXTERN int compl_interrupted INIT(= FALSE);
+// Set when doing something for completion that may call edit() recursively,
+// which is not allowed. Also used to disable folding during completion
+EXTERN int compl_busy INIT(= false);
+
/* List of flags for method of completion. */
EXTERN int compl_cont_status INIT(= 0);
# define CONT_ADDING 1 /* "normal" or "adding" expansion */
@@ -918,8 +922,8 @@ EXTERN int KeyTyped; // TRUE if user typed current char
EXTERN int KeyStuffed; // TRUE if current char from stuffbuf
EXTERN int maptick INIT(= 0); // tick for each non-mapped char
-EXTERN char_u chartab[256]; /* table used in charset.c; See
- init_chartab() for explanation */
+EXTERN uint8_t chartab[256]; // table used in charset.c; See
+ // init_chartab() for explanation
EXTERN int must_redraw INIT(= 0); /* type of redraw necessary */
EXTERN int skip_redraw INIT(= FALSE); /* skip redraw once */
diff --git a/src/nvim/main.c b/src/nvim/main.c
index a2aca65001..5b5c8a22aa 100644
--- a/src/nvim/main.c
+++ b/src/nvim/main.c
@@ -317,14 +317,16 @@ int main(int argc, char **argv)
}
// open terminals when opening files that start with term://
- do_cmdline_cmd("autocmd BufReadCmd term://* "
+#define PROTO "term://"
+ do_cmdline_cmd("autocmd BufReadCmd " PROTO "* nested "
":call termopen( "
// Capture the command string
"matchstr(expand(\"<amatch>\"), "
- "'\\c\\mterm://\\%(.\\{-}//\\%(\\d\\+:\\)\\?\\)\\?\\zs.*'), "
+ "'\\c\\m" PROTO "\\%(.\\{-}//\\%(\\d\\+:\\)\\?\\)\\?\\zs.*'), "
// capture the working directory
"{'cwd': get(matchlist(expand(\"<amatch>\"), "
- "'\\c\\mterm://\\(.\\{-}\\)//'), 1, '')})");
+ "'\\c\\m" PROTO "\\(.\\{-}\\)//'), 1, '')})");
+#undef PROTO
/* Execute --cmd arguments. */
exe_pre_commands(&params);
diff --git a/src/nvim/memfile.c b/src/nvim/memfile.c
index 8cf5642a80..6599db787f 100644
--- a/src/nvim/memfile.c
+++ b/src/nvim/memfile.c
@@ -79,8 +79,6 @@ static size_t total_mem_used = 0; /// total memory used for memfiles
/// - NULL, on failure.
memfile_T *mf_open(char_u *fname, int flags)
{
- off_t size;
-
memfile_T *mfp = xmalloc(sizeof(memfile_T));
if (fname == NULL) { // no file, use memory only
@@ -88,11 +86,9 @@ memfile_T *mf_open(char_u *fname, int flags)
mfp->mf_ffname = NULL;
mfp->mf_fd = -1;
} else { // try to open the file
- mf_do_open(mfp, fname, flags);
-
- if (mfp->mf_fd < 0) { // fail if file could not be opened
+ if (!mf_do_open(mfp, fname, flags)) {
xfree(mfp);
- return NULL;
+ return NULL; // fail if file could not be opened
}
}
@@ -115,6 +111,8 @@ memfile_T *mf_open(char_u *fname, int flags)
}
}
+ off_t size;
+
// When recovering, the actual block size will be retrieved from block 0
// in ml_recover(). The size used here may be wrong, therefore mf_blocknr_max
// must be rounded up.
@@ -171,13 +169,12 @@ memfile_T *mf_open(char_u *fname, int flags)
/// FAIL If file could not be opened.
int mf_open_file(memfile_T *mfp, char_u *fname)
{
- mf_do_open(mfp, fname, O_RDWR|O_CREAT|O_EXCL); // try to open the file
-
- if (mfp->mf_fd < 0)
- return FAIL;
+ if (mf_do_open(mfp, fname, O_RDWR | O_CREAT | O_EXCL)) {
+ mfp->mf_dirty = true;
+ return OK;
+ }
- mfp->mf_dirty = true;
- return OK;
+ return FAIL;
}
/// Close a memory file and optionally delete the associated file.
@@ -185,28 +182,28 @@ int mf_open_file(memfile_T *mfp, char_u *fname)
/// @param del_file Whether to delete associated file.
void mf_close(memfile_T *mfp, bool del_file)
{
- bhdr_T *hp, *nextp;
-
if (mfp == NULL) { // safety check
return;
}
if (mfp->mf_fd >= 0 && close(mfp->mf_fd) < 0) {
EMSG(_(e_swapclose));
}
- if (del_file && mfp->mf_fname != NULL)
+ if (del_file && mfp->mf_fname != NULL) {
os_remove((char *)mfp->mf_fname);
+ }
+
// free entries in used list
- for (hp = mfp->mf_used_first; hp != NULL; hp = nextp) {
+ for (bhdr_T *hp = mfp->mf_used_first, *nextp; hp != NULL; hp = nextp) {
total_mem_used -= hp->bh_page_count * mfp->mf_page_size;
nextp = hp->bh_next;
mf_free_bhdr(hp);
}
- while (mfp->mf_free_first != NULL) // free entries in free list
+ while (mfp->mf_free_first != NULL) { // free entries in free list
xfree(mf_rem_free(mfp));
+ }
mf_hash_free(&mfp->mf_hash);
mf_hash_free_all(&mfp->mf_trans); // free hashtable and its items
- xfree(mfp->mf_fname);
- xfree(mfp->mf_ffname);
+ mf_free_fnames(mfp);
xfree(mfp);
}
@@ -216,28 +213,28 @@ void mf_close(memfile_T *mfp, bool del_file)
void mf_close_file(buf_T *buf, bool getlines)
{
memfile_T *mfp = buf->b_ml.ml_mfp;
- if (mfp == NULL || mfp->mf_fd < 0) // nothing to close
+ if (mfp == NULL || mfp->mf_fd < 0) { // nothing to close
return;
+ }
if (getlines) {
// get all blocks in memory by accessing all lines (clumsy!)
mf_dont_release = true;
- for (linenr_T lnum = 1; lnum <= buf->b_ml.ml_line_count; ++lnum)
+ for (linenr_T lnum = 1; lnum <= buf->b_ml.ml_line_count; ++lnum) {
(void)ml_get_buf(buf, lnum, false);
+ }
mf_dont_release = false;
// TODO(elmart): should check if all blocks are really in core
}
- if (close(mfp->mf_fd) < 0) // close the file
+ if (close(mfp->mf_fd) < 0) { // close the file
EMSG(_(e_swapclose));
+ }
mfp->mf_fd = -1;
if (mfp->mf_fname != NULL) {
os_remove((char *)mfp->mf_fname); // delete the swap file
- xfree(mfp->mf_fname);
- xfree(mfp->mf_ffname);
- mfp->mf_fname = NULL;
- mfp->mf_ffname = NULL;
+ mf_free_fnames(mfp);
}
}
@@ -390,11 +387,11 @@ void mf_put(memfile_T *mfp, bhdr_T *hp, bool dirty, bool infile)
/// Signal block as no longer used (may put it in the free list).
void mf_free(memfile_T *mfp, bhdr_T *hp)
{
- xfree(hp->bh_data); // free data
+ xfree(hp->bh_data); // free data
mf_rem_hash(mfp, hp); // get *hp out of the hash list
mf_rem_used(mfp, hp); // get *hp out of the used list
if (hp->bh_bnum < 0) {
- xfree(hp); // don't want negative numbers in free list
+ xfree(hp); // don't want negative numbers in free list
mfp->mf_neg_count--;
} else {
mf_ins_free(mfp, hp); // put *hp in the free list
@@ -475,10 +472,11 @@ int mf_sync(memfile_T *mfp, int flags)
/// These are blocks that need to be written to a newly created swapfile.
void mf_set_dirty(memfile_T *mfp)
{
- bhdr_T *hp;
- for (hp = mfp->mf_used_last; hp != NULL; hp = hp->bh_prev)
- if (hp->bh_bnum > 0)
+ for (bhdr_T *hp = mfp->mf_used_last; hp != NULL; hp = hp->bh_prev) {
+ if (hp->bh_bnum > 0) {
hp->bh_flags |= BH_DIRTY;
+ }
+ }
mfp->mf_dirty = true;
}
@@ -506,10 +504,11 @@ static void mf_ins_used(memfile_T *mfp, bhdr_T *hp)
hp->bh_next = mfp->mf_used_first;
mfp->mf_used_first = hp;
hp->bh_prev = NULL;
- if (hp->bh_next == NULL) // list was empty, adjust last pointer
+ if (hp->bh_next == NULL) { // list was empty, adjust last pointer
mfp->mf_used_last = hp;
- else
+ } else {
hp->bh_next->bh_prev = hp;
+ }
mfp->mf_used_count += hp->bh_page_count;
total_mem_used += hp->bh_page_count * mfp->mf_page_size;
}
@@ -615,9 +614,10 @@ bool mf_release_all(void)
FOR_ALL_BUFFERS(buf) {
memfile_T *mfp = buf->b_ml.ml_mfp;
if (mfp != NULL) {
- // If no swap file yet, may open one.
- if (mfp->mf_fd < 0 && buf->b_may_swap)
+ // If no swap file yet, try to open one.
+ if (mfp->mf_fd < 0 && buf->b_may_swap) {
ml_open_file(buf);
+ }
// Flush as many blocks as possible, only if there is a swapfile.
if (mfp->mf_fd >= 0) {
@@ -752,7 +752,8 @@ static int mf_write(memfile_T *mfp, bhdr_T *hp)
else
page_count = hp2->bh_page_count;
size = page_size * page_count;
- if (mf_write_block(mfp, hp2 == NULL ? hp : hp2, offset, size) == FAIL) {
+ void *data = (hp2 == NULL) ? hp->bh_data : hp2->bh_data;
+ if ((unsigned)write_eintr(mfp->mf_fd, data, size) != size) {
/// Avoid repeating the error message, this mostly happens when the
/// disk is full. We give the message again only after a successful
/// write or when hitting a key. We keep on trying, in case some
@@ -773,20 +774,6 @@ static int mf_write(memfile_T *mfp, bhdr_T *hp)
return OK;
}
-/// Write block to memfile's file.
-///
-/// @return OK On success.
-/// FAIL On failure.
-static int mf_write_block(memfile_T *mfp, bhdr_T *hp,
- off_t offset, unsigned size)
-{
- void *data = hp->bh_data;
- int result = OK;
- if ((unsigned)write_eintr(mfp->mf_fd, data, size) != size)
- result = FAIL;
- return result;
-}
-
/// Make block number positive and add it to the translation list.
///
/// @return OK On success.
@@ -856,13 +843,23 @@ blocknr_T mf_trans_del(memfile_T *mfp, blocknr_T old_nr)
return new_bnum;
}
-/// Set full file name of memfile's swapfile, out of simple file name and some
-/// other considerations.
+/// Frees mf_fname and mf_ffname.
+void mf_free_fnames(memfile_T *mfp)
+{
+ xfree(mfp->mf_fname);
+ xfree(mfp->mf_ffname);
+ mfp->mf_fname = NULL;
+ mfp->mf_ffname = NULL;
+}
+
+/// Set the simple file name and the full file name of memfile's swapfile, out
+/// of simple file name and some other considerations.
///
/// Only called when creating or renaming the swapfile. Either way it's a new
/// name so we must work out the full path name.
-void mf_set_ffname(memfile_T *mfp)
+void mf_set_fnames(memfile_T *mfp, char_u *fname)
{
+ mfp->mf_fname = fname;
mfp->mf_ffname = (char_u *)FullName_save((char *)mfp->mf_fname, false);
}
@@ -878,7 +875,7 @@ void mf_fullname(memfile_T *mfp)
}
}
-/// Return TRUE if there are any translations pending for memfile.
+/// Return true if there are any translations pending for memfile.
bool mf_need_trans(memfile_T *mfp)
{
return mfp->mf_fname != NULL && mfp->mf_neg_count > 0;
@@ -889,11 +886,11 @@ bool mf_need_trans(memfile_T *mfp)
/// "fname" must be in allocated memory, and is consumed (also when error).
///
/// @param flags Flags for open().
-static void mf_do_open(memfile_T *mfp, char_u *fname, int flags)
+/// @return A bool indicating success of the `open` call.
+static bool mf_do_open(memfile_T *mfp, char_u *fname, int flags)
{
// fname cannot be NameBuff, because it must have been allocated.
- mfp->mf_fname = fname;
- mf_set_ffname(mfp);
+ mf_set_fnames(mfp, fname);
/// Extra security check: When creating a swap file it really shouldn't
/// exist yet. If there is a symbolic link, this is most likely an attack.
@@ -904,26 +901,26 @@ static void mf_do_open(memfile_T *mfp, char_u *fname, int flags)
EMSG(_("E300: Swap file already exists (symlink attack?)"));
} else {
// try to open the file
- flags |= O_NOFOLLOW;
- mfp->mf_fd = mch_open_rw((char *)mfp->mf_fname, flags);
+ mfp->mf_fd = mch_open_rw((char *)mfp->mf_fname, flags | O_NOFOLLOW);
}
// If the file cannot be opened, use memory only
if (mfp->mf_fd < 0) {
- xfree(mfp->mf_fname);
- xfree(mfp->mf_ffname);
- mfp->mf_fname = NULL;
- mfp->mf_ffname = NULL;
- } else {
+ mf_free_fnames(mfp);
+ return false;
+ }
+
#ifdef HAVE_FD_CLOEXEC
- int fdflags = fcntl(mfp->mf_fd, F_GETFD);
- if (fdflags >= 0 && (fdflags & FD_CLOEXEC) == 0)
- fcntl(mfp->mf_fd, F_SETFD, fdflags | FD_CLOEXEC);
+ int fdflags = fcntl(mfp->mf_fd, F_GETFD);
+ if (fdflags >= 0 && (fdflags & FD_CLOEXEC) == 0) {
+ fcntl(mfp->mf_fd, F_SETFD, fdflags | FD_CLOEXEC);
+ }
#endif
#ifdef HAVE_SELINUX
- mch_copy_sec(fname, mfp->mf_fname);
+ mch_copy_sec(fname, mfp->mf_fname);
#endif
- }
+
+ return true;
}
//
@@ -948,20 +945,21 @@ static void mf_hash_init(mf_hashtab_T *mht)
/// The hash table must not be used again without another mf_hash_init() call.
static void mf_hash_free(mf_hashtab_T *mht)
{
- if (mht->mht_buckets != mht->mht_small_buckets)
+ if (mht->mht_buckets != mht->mht_small_buckets) {
xfree(mht->mht_buckets);
+ }
}
/// Free the array of a hash table and all the items it contains.
static void mf_hash_free_all(mf_hashtab_T *mht)
{
- mf_hashitem_T *next;
-
- for (size_t idx = 0; idx <= mht->mht_mask; idx++)
+ for (size_t idx = 0; idx <= mht->mht_mask; idx++) {
+ mf_hashitem_T *next;
for (mf_hashitem_T *mhi = mht->mht_buckets[idx]; mhi != NULL; mhi = next) {
next = mhi->mhi_next;
xfree(mhi);
}
+ }
mf_hash_free(mht);
}
diff --git a/src/nvim/memline.c b/src/nvim/memline.c
index f58b2ac38f..b568279d7d 100644
--- a/src/nvim/memline.c
+++ b/src/nvim/memline.c
@@ -426,10 +426,8 @@ void ml_setname(buf_T *buf)
/* try to rename the swap file */
if (vim_rename(mfp->mf_fname, fname) == 0) {
success = TRUE;
- xfree(mfp->mf_fname);
- mfp->mf_fname = fname;
- xfree(mfp->mf_ffname);
- mf_set_ffname(mfp);
+ mf_free_fnames(mfp);
+ mf_set_fnames(mfp, fname);
ml_upd_block0(buf, UB_SAME_DIR);
break;
}
diff --git a/src/nvim/normal.c b/src/nvim/normal.c
index e064d34e09..2895816b8f 100644
--- a/src/nvim/normal.c
+++ b/src/nvim/normal.c
@@ -2344,9 +2344,12 @@ do_mouse (
if (mouse_row == 0 && firstwin->w_winrow > 0) {
if (is_drag) {
if (in_tab_line) {
- tabpage_move(tab_page_click_defs[mouse_col].type == kStlClickTabClose
- ? 9999
- : tab_page_click_defs[mouse_col].tabnr - 1);
+ if (tab_page_click_defs[mouse_col].type == kStlClickTabClose) {
+ tabpage_move(9999);
+ } else {
+ int tabnr = tab_page_click_defs[mouse_col].tabnr;
+ tabpage_move(tabnr < tabpage_index(curtab) ? tabnr - 1 : tabnr);
+ }
}
return false;
}
@@ -4096,6 +4099,7 @@ dozet:
case 't': scroll_cursor_top(0, true);
redraw_later(VALID);
+ set_fraction(curwin);
break;
/* "z." and "zz": put cursor in middle of screen */
@@ -4104,6 +4108,7 @@ dozet:
case 'z': scroll_cursor_halfway(true);
redraw_later(VALID);
+ set_fraction(curwin);
break;
/* "z^", "z-" and "zb": put cursor at bottom of screen */
@@ -4124,6 +4129,7 @@ dozet:
case 'b': scroll_cursor_bot(0, true);
redraw_later(VALID);
+ set_fraction(curwin);
break;
/* "zH" - scroll screen right half-page */
diff --git a/src/nvim/ops.c b/src/nvim/ops.c
index b1adc85e1d..5f48fdbf3d 100644
--- a/src/nvim/ops.c
+++ b/src/nvim/ops.c
@@ -19,6 +19,7 @@
#include "nvim/ex_cmds.h"
#include "nvim/ex_cmds2.h"
#include "nvim/ex_getln.h"
+#include "nvim/fileio.h"
#include "nvim/fold.h"
#include "nvim/getchar.h"
#include "nvim/indent.h"
@@ -835,12 +836,13 @@ int do_record(int c)
yankreg_T *old_y_previous;
int retval;
- if (Recording == FALSE) { /* start recording */
- /* registers 0-9, a-z and " are allowed */
- if (c < 0 || (!ASCII_ISALNUM(c) && c != '"'))
+ if (Recording == false) {
+ // start recording
+ // registers 0-9, a-z and " are allowed
+ if (c < 0 || (!ASCII_ISALNUM(c) && c != '"')) {
retval = FAIL;
- else {
- Recording = TRUE;
+ } else {
+ Recording = c;
showmode();
regname = c;
retval = OK;
@@ -1259,21 +1261,18 @@ get_spec_reg (
return FALSE;
}
-/*
- * Paste a yank register into the command line.
- * Only for non-special registers.
- * Used by CTRL-R command in command-line mode
- * insert_reg() can't be used here, because special characters from the
- * register contents will be interpreted as commands.
- *
- * return FAIL for failure, OK otherwise
- */
-int
-cmdline_paste_reg (
- int regname,
- int literally, /* Insert text literally instead of "as typed" */
- int remcr /* don't add trailing CR */
-)
+/// Paste a yank register into the command line.
+/// Only for non-special registers.
+/// Used by CTRL-R command in command-line mode
+/// insert_reg() can't be used here, because special characters from the
+/// register contents will be interpreted as commands.
+///
+/// @param regname Register name.
+/// @param literally Insert text literally instead of "as typed".
+/// @param remcr When true, don't add CR characters.
+///
+/// @returns FAIL for failure, OK otherwise
+bool cmdline_paste_reg(int regname, bool literally, bool remcr)
{
long i;
@@ -1284,13 +1283,9 @@ cmdline_paste_reg (
for (i = 0; i < reg->y_size; i++) {
cmdline_paste_str(reg->y_array[i], literally);
- /* Insert ^M between lines and after last line if type is MLINE.
- * Don't do this when "remcr" is TRUE and the next line is empty. */
- if (reg->y_type == MLINE
- || (i < reg->y_size - 1
- && !(remcr
- && i == reg->y_size - 2
- && *reg->y_array[i + 1] == NUL))) {
+ // Insert ^M between lines and after last line if type is MLINE.
+ // Don't do this when "remcr" is true.
+ if ((reg->y_type == MLINE || i < reg->y_size - 1) && !remcr) {
cmdline_paste_str((char_u *)"\r", literally);
}
@@ -1409,8 +1404,9 @@ int op_delete(oparg_T *oap)
op_yank_reg(oap, false, reg, false);
}
- if(oap->regname == 0) {
+ if (oap->regname == 0) {
set_clipboard(0, reg);
+ yank_do_autocmd(oap, reg);
}
}
@@ -2309,6 +2305,8 @@ bool op_yank(oparg_T *oap, bool message)
yankreg_T *reg = get_yank_register(oap->regname, YREG_YANK);
op_yank_reg(oap, message, reg, is_append_register(oap->regname));
set_clipboard(oap->regname, reg);
+ yank_do_autocmd(oap, reg);
+
return true;
}
@@ -2524,6 +2522,58 @@ static void yank_copy_line(yankreg_T *reg, struct block_def *bd, long y_idx)
*pnew = NUL;
}
+/// Execute autocommands for TextYankPost.
+///
+/// @param oap Operator arguments.
+/// @param reg The yank register used.
+static void yank_do_autocmd(oparg_T *oap, yankreg_T *reg)
+ FUNC_ATTR_NONNULL_ALL
+{
+ static bool recursive = false;
+
+ if (recursive || !has_event(EVENT_TEXTYANKPOST)) {
+ // No autocommand was defined
+ // or we yanked from this autocommand.
+ return;
+ }
+
+ recursive = true;
+
+ // set v:event to a dictionary with information about the yank
+ dict_T *dict = get_vim_var_dict(VV_EVENT);
+
+ // the yanked text
+ list_T *list = list_alloc();
+ for (linenr_T i = 0; i < reg->y_size; i++) {
+ list_append_string(list, reg->y_array[i], -1);
+ }
+ list->lv_lock = VAR_FIXED;
+ dict_add_list(dict, "regcontents", list);
+
+ // the register type
+ char buf[NUMBUFLEN+2];
+ format_reg_type(reg->y_type, reg->y_width, buf, ARRAY_SIZE(buf));
+ dict_add_nr_str(dict, "regtype", 0, (char_u *)buf);
+
+ // name of requested register or the empty string for an unnamed operation.
+ buf[0] = (char)oap->regname;
+ buf[1] = NUL;
+ dict_add_nr_str(dict, "regname", 0, (char_u *)buf);
+
+ // kind of operation (yank/delete/change)
+ buf[0] = get_op_char(oap->op_type);
+ buf[1] = NUL;
+ dict_add_nr_str(dict, "operator", 0, (char_u *)buf);
+
+ dict_set_keys_readonly(dict);
+ textlock++;
+ apply_autocmds(EVENT_TEXTYANKPOST, NULL, NULL, false, curbuf);
+ textlock--;
+ dict_clear(dict);
+
+ recursive = false;
+}
+
/*
* Put contents of register "regname" into the text.
@@ -4631,7 +4681,7 @@ theend:
* Used for getregtype()
* Returns MAUTO for error.
*/
-char_u get_reg_type(int regname, long *reglen)
+char_u get_reg_type(int regname, colnr_T *reg_width)
{
switch (regname) {
case '%': /* file name */
@@ -4654,13 +4704,45 @@ char_u get_reg_type(int regname, long *reglen)
yankreg_T *reg = get_yank_register(regname, YREG_PASTE);
if (reg->y_array != NULL) {
- if (reglen != NULL && reg->y_type == MBLOCK)
- *reglen = reg->y_width;
+ if (reg_width != NULL && reg->y_type == MBLOCK) {
+ *reg_width = reg->y_width;
+ }
return reg->y_type;
}
return MAUTO;
}
+/// Format the register type as a string.
+///
+/// @param reg_type The register type.
+/// @param reg_width The width, only used if "reg_type" is MBLOCK.
+/// @param[out] buf Buffer to store formatted string. The allocated size should
+/// be at least NUMBUFLEN+2 to always fit the value.
+/// @param buf_len The allocated size of the buffer.
+void format_reg_type(char_u reg_type, colnr_T reg_width,
+ char* buf, size_t buf_len)
+ FUNC_ATTR_NONNULL_ALL
+{
+ assert(buf_len > 1);
+ switch (reg_type) {
+ case MLINE:
+ buf[0] = 'V';
+ buf[1] = NUL;
+ break;
+ case MCHAR:
+ buf[0] = 'v';
+ buf[1] = NUL;
+ break;
+ case MBLOCK:
+ snprintf(buf, buf_len, CTRL_V_STR "%" PRIdCOLNR, reg_width + 1);
+ break;
+ case MAUTO:
+ buf[0] = NUL;
+ break;
+ }
+}
+
+
/// When `flags` has `kGRegList` return a list with text `s`.
/// Otherwise just return `s`.
///
diff --git a/src/nvim/option.c b/src/nvim/option.c
index af7b272467..5efd71444a 100644
--- a/src/nvim/option.c
+++ b/src/nvim/option.c
@@ -6167,16 +6167,14 @@ int has_format_option(int x)
return vim_strchr(curbuf->b_p_fo, x) != NULL;
}
-/*
- * Return TRUE if "x" is present in 'shortmess' option, or
- * 'shortmess' contains 'a' and "x" is present in SHM_A.
- */
-int shortmess(int x)
+/// @returns true if "x" is present in 'shortmess' option, or
+/// 'shortmess' contains 'a' and "x" is present in SHM_ALL_ABBREVIATIONS.
+bool shortmess(int x)
{
return p_shm != NULL &&
- ( vim_strchr(p_shm, x) != NULL
- || (vim_strchr(p_shm, 'a') != NULL
- && vim_strchr((char_u *)SHM_A, x) != NULL));
+ (vim_strchr(p_shm, x) != NULL
+ || (vim_strchr(p_shm, 'a') != NULL
+ && vim_strchr((char_u *)SHM_ALL_ABBREVIATIONS, x) != NULL));
}
/*
diff --git a/src/nvim/option_defs.h b/src/nvim/option_defs.h
index 10706a0753..8e74e5036e 100644
--- a/src/nvim/option_defs.h
+++ b/src/nvim/option_defs.h
@@ -151,26 +151,42 @@
#define COCU_ALL "nvic" /* flags for 'concealcursor' */
-/* characters for p_shm option: */
-#define SHM_RO 'r' /* readonly */
-#define SHM_MOD 'm' /* modified */
-#define SHM_FILE 'f' /* (file 1 of 2) */
-#define SHM_LAST 'i' /* last line incomplete */
-#define SHM_TEXT 'x' /* tx instead of textmode */
-#define SHM_LINES 'l' /* "L" instead of "lines" */
-#define SHM_NEW 'n' /* "[New]" instead of "[New file]" */
-#define SHM_WRI 'w' /* "[w]" instead of "written" */
-#define SHM_A "rmfixlnw" /* represented by 'a' flag */
-#define SHM_WRITE 'W' /* don't use "written" at all */
-#define SHM_TRUNC 't' /* trunctate file messages */
-#define SHM_TRUNCALL 'T' /* trunctate all messages */
-#define SHM_OVER 'o' /* overwrite file messages */
-#define SHM_OVERALL 'O' /* overwrite more messages */
-#define SHM_SEARCH 's' /* no search hit bottom messages */
-#define SHM_ATTENTION 'A' /* no ATTENTION messages */
-#define SHM_INTRO 'I' /* intro messages */
-#define SHM_COMPLETIONMENU 'c' // completion menu messages
-#define SHM_ALL "rmfixlnwaWtToOsAIc" /* all possible flags for 'shm' */
+/// characters for p_shm option:
+enum {
+ SHM_RO = 'r', ///< Readonly.
+ SHM_MOD = 'm', ///< Modified.
+ SHM_FILE = 'f', ///< (file 1 of 2)
+ SHM_LAST = 'i', ///< Last line incomplete.
+ SHM_TEXT = 'x', ///< Tx instead of textmode.
+ SHM_LINES = 'l', ///< "L" instead of "lines".
+ SHM_NEW = 'n', ///< "[New]" instead of "[New file]".
+ SHM_WRI = 'w', ///< "[w]" instead of "written".
+ SHM_ABBREVIATIONS = 'a', ///< Use abbreviations from #SHM_ALL_ABBREVIATIONS.
+ SHM_WRITE = 'W', ///< Don't use "written" at all.
+ SHM_TRUNC = 't', ///< Trunctate file messages.
+ SHM_TRUNCALL = 'T', ///< Trunctate all messages.
+ SHM_OVER = 'o', ///< Overwrite file messages.
+ SHM_OVERALL = 'O', ///< Overwrite more messages.
+ SHM_SEARCH = 's', ///< No search hit bottom messages.
+ SHM_ATTENTION = 'A', ///< No ATTENTION messages.
+ SHM_INTRO = 'I', ///< Intro messages.
+ SHM_COMPLETIONMENU = 'c', ///< Completion menu messages.
+ SHM_RECORDING = 'q', ///< Short recording message.
+ SHM_FILEINFO = 'F', ///< No file info messages.
+};
+/// Represented by 'a' flag.
+#define SHM_ALL_ABBREVIATIONS ((char_u[]) { \
+ SHM_RO, SHM_MOD, SHM_FILE, SHM_LAST, SHM_TEXT, SHM_LINES, SHM_NEW, SHM_WRI, \
+ 0, \
+})
+/// All possible flags for 'shm'.
+#define SHM_ALL ((char_u[]) { \
+ SHM_RO, SHM_MOD, SHM_FILE, SHM_LAST, SHM_TEXT, SHM_LINES, SHM_NEW, SHM_WRI, \
+ SHM_ABBREVIATIONS, SHM_WRITE, SHM_TRUNC, SHM_TRUNCALL, SHM_OVER, \
+ SHM_OVERALL, SHM_SEARCH, SHM_ATTENTION, SHM_INTRO, SHM_COMPLETIONMENU, \
+ SHM_RECORDING, SHM_FILEINFO, \
+ 0, \
+})
/* characters for p_go: */
#define GO_ASEL 'a' /* autoselect */
diff --git a/src/nvim/os/fs.c b/src/nvim/os/fs.c
index 2e671653ed..34d8fde4f1 100644
--- a/src/nvim/os/fs.c
+++ b/src/nvim/os/fs.c
@@ -166,7 +166,7 @@ static bool is_executable_in_path(const char_u *name, char_u **abspath)
// Glue together the given directory from $PATH with name and save into
// buf.
STRLCPY(buf, path, e - path + 1);
- append_path((char *) buf, (const char *) name, (int)buf_len);
+ append_path((char *) buf, (const char *) name, buf_len);
if (is_executable(buf)) {
// Check if the caller asked for a copy of the path.
diff --git a/src/nvim/os/stdpaths.c b/src/nvim/os/stdpaths.c
index c9631a434c..81ceb919c4 100644
--- a/src/nvim/os/stdpaths.c
+++ b/src/nvim/os/stdpaths.c
@@ -22,9 +22,9 @@ static const char *xdg_env_vars[] = {
static const char *const xdg_defaults[] = {
#ifdef WIN32
// Windows
- [kXDGConfigHome] = "$LOCALAPPDATA\\nvim\\config",
- [kXDGDataHome] = "$LOCALAPPDATA\\nvim\\data",
- [kXDGCacheHome] = "$LOCALAPPDATA\\nvim\\cache",
+ [kXDGConfigHome] = "$LOCALAPPDATA",
+ [kXDGDataHome] = "$LOCALAPPDATA",
+ [kXDGCacheHome] = "$TEMP",
[kXDGRuntimeDir] = NULL,
[kXDGConfigDirs] = NULL,
[kXDGDataDirs] = NULL,
@@ -66,12 +66,21 @@ char *stdpaths_get_xdg_var(const XDGVarType idx)
/// @param[in] idx XDG directory to use.
///
/// @return [allocated] `{xdg_directory}/nvim`
+///
+/// In WIN32 get_xdg_home(kXDGDataHome) returns `{xdg_directory}/nvim-data` to
+/// avoid storing configuration and data files in the same path.
static char *get_xdg_home(const XDGVarType idx)
FUNC_ATTR_WARN_UNUSED_RESULT
{
char *dir = stdpaths_get_xdg_var(idx);
if (dir) {
+#if defined(WIN32)
+ dir = concat_fnames_realloc(dir,
+ (idx == kXDGDataHome ? "nvim-data" : "nvim"),
+ true);
+#else
dir = concat_fnames_realloc(dir, "nvim", true);
+#endif
}
return dir;
}
diff --git a/src/nvim/path.c b/src/nvim/path.c
index 5cd93ab811..22a3f96cfa 100644
--- a/src/nvim/path.c
+++ b/src/nvim/path.c
@@ -268,16 +268,13 @@ char_u *shorten_dir(char_u *str)
*/
bool dir_of_file_exists(char_u *fname)
{
- char_u *p;
- int c;
- bool retval;
-
- p = path_tail_with_sep(fname);
- if (p == fname)
+ char_u *p = path_tail_with_sep(fname);
+ if (p == fname) {
return true;
- c = *p;
+ }
+ char_u c = *p;
*p = NUL;
- retval = os_isdir(fname);
+ bool retval = os_isdir(fname);
*p = c;
return retval;
}
@@ -539,15 +536,10 @@ static size_t do_path_expand(garray_T *gap, const char_u *path,
size_t wildoff, int flags, bool didstar)
FUNC_ATTR_NONNULL_ALL
{
- char_u *buf;
- char_u *p, *s, *e;
int start_len = gap->ga_len;
- char_u *pat;
- int starts_with_dot;
- int matches;
- int len;
+ size_t len;
bool starstar = false;
- static int stardepth = 0; /* depth for "**" expansion */
+ static int stardepth = 0; // depth for "**" expansion
/* Expanding "**" may take a long time, check for CTRL-C. */
if (stardepth > 0) {
@@ -558,16 +550,14 @@ static size_t do_path_expand(garray_T *gap, const char_u *path,
// Make room for file name. When doing encoding conversion the actual
// length may be quite a bit longer, thus use the maximum possible length.
- buf = xmalloc(MAXPATHL);
-
- /*
- * Find the first part in the path name that contains a wildcard.
- * When EW_ICASE is set every letter is considered to be a wildcard.
- * Copy it into "buf", including the preceding characters.
- */
- p = buf;
- s = buf;
- e = NULL;
+ char_u *buf = xmalloc(MAXPATHL);
+
+ // Find the first part in the path name that contains a wildcard.
+ // When EW_ICASE is set every letter is considered to be a wildcard.
+ // Copy it into "buf", including the preceding characters.
+ char_u *p = buf;
+ char_u *s = buf;
+ char_u *e = NULL;
const char_u *path_end = path;
while (*path_end != NUL) {
/* May ignore a wildcard that has a backslash before it; it will
@@ -588,7 +578,7 @@ static size_t do_path_expand(garray_T *gap, const char_u *path,
e = p;
}
if (has_mbyte) {
- len = (*mb_ptr2len)(path_end);
+ len = (size_t)(*mb_ptr2len)(path_end);
STRNCPY(p, path_end, len);
p += len;
path_end += len;
@@ -613,9 +603,9 @@ static size_t do_path_expand(garray_T *gap, const char_u *path,
if (p[0] == '*' && p[1] == '*')
starstar = true;
- /* convert the file pattern to a regexp pattern */
- starts_with_dot = (*s == '.');
- pat = file_pat_to_reg_pat(s, e, NULL, FALSE);
+ // convert the file pattern to a regexp pattern
+ int starts_with_dot = (*s == '.');
+ char_u *pat = file_pat_to_reg_pat(s, e, NULL, false);
if (pat == NULL) {
xfree(buf);
return 0;
@@ -646,9 +636,9 @@ static size_t do_path_expand(garray_T *gap, const char_u *path,
if (!didstar && stardepth < 100 && starstar && e - s == 2
&& *path_end == '/') {
STRCPY(s, path_end + 1);
- ++stardepth;
- (void)do_path_expand(gap, buf, (int)(s - buf), flags, true);
- --stardepth;
+ stardepth++;
+ (void)do_path_expand(gap, buf, (size_t)(s - buf), flags, true);
+ stardepth--;
}
*s = NUL;
@@ -703,10 +693,11 @@ static size_t do_path_expand(garray_T *gap, const char_u *path,
xfree(buf);
vim_regfree(regmatch.regprog);
- matches = gap->ga_len - start_len;
- if (matches > 0)
+ size_t matches = (size_t)(gap->ga_len - start_len);
+ if (matches > 0) {
qsort(((char_u **)gap->ga_data) + start_len, matches,
- sizeof(char_u *), pstrcmp);
+ sizeof(char_u *), pstrcmp);
+ }
return matches;
}
@@ -736,27 +727,24 @@ static int find_previous_pathsep(char_u *path, char_u **psep)
*/
static bool is_unique(char_u *maybe_unique, garray_T *gap, int i)
{
- int candidate_len;
- int other_path_len;
- char_u **other_paths = (char_u **)gap->ga_data;
- char_u *rival;
+ char_u **other_paths = (char_u **)gap->ga_data;
for (int j = 0; j < gap->ga_len; j++) {
- if (j == i)
- continue; /* don't compare it with itself */
-
- candidate_len = (int)STRLEN(maybe_unique);
- other_path_len = (int)STRLEN(other_paths[j]);
- if (other_path_len < candidate_len)
- continue; /* it's different when it's shorter */
-
- rival = other_paths[j] + other_path_len - candidate_len;
+ if (j == i) {
+ continue; // don't compare it with itself
+ }
+ size_t candidate_len = STRLEN(maybe_unique);
+ size_t other_path_len = STRLEN(other_paths[j]);
+ if (other_path_len < candidate_len) {
+ continue; // it's different when it's shorter
+ }
+ char_u *rival = other_paths[j] + other_path_len - candidate_len;
if (fnamecmp(maybe_unique, rival) == 0
- && (rival == other_paths[j] || vim_ispathsep(*(rival - 1))))
- return false; /* match */
+ && (rival == other_paths[j] || vim_ispathsep(*(rival - 1)))) {
+ return false; // match
+ }
}
-
- return true; /* no match found */
+ return true; // no match found
}
/*
@@ -770,12 +758,8 @@ static bool is_unique(char_u *maybe_unique, garray_T *gap, int i)
*/
static void expand_path_option(char_u *curdir, garray_T *gap)
{
- char_u *path_option = *curbuf->b_p_path == NUL
- ? p_path : curbuf->b_p_path;
- char_u *buf;
- int len;
-
- buf = xmalloc(MAXPATHL);
+ char_u *path_option = *curbuf->b_p_path == NUL ? p_path : curbuf->b_p_path;
+ char_u *buf = xmalloc(MAXPATHL);
while (*path_option != NUL) {
copy_option_part(&path_option, buf, MAXPATHL, " ,");
@@ -787,26 +771,27 @@ static void expand_path_option(char_u *curdir, garray_T *gap)
if (curbuf->b_ffname == NULL)
continue;
char_u *p = path_tail(curbuf->b_ffname);
- len = (int)(p - curbuf->b_ffname);
- if (len + (int)STRLEN(buf) >= MAXPATHL)
+ size_t len = (size_t)(p - curbuf->b_ffname);
+ if (len + STRLEN(buf) >= MAXPATHL) {
continue;
- if (buf[1] == NUL)
+ }
+ if (buf[1] == NUL) {
buf[len] = NUL;
- else
+ } else {
STRMOVE(buf + len, buf + 2);
+ }
memmove(buf, curbuf->b_ffname, len);
simplify_filename(buf);
- } else if (buf[0] == NUL)
- /* relative to current directory */
- STRCPY(buf, curdir);
- else if (path_with_url((char *)buf))
- /* URL can't be used here */
- continue;
- else if (!path_is_absolute_path(buf)) {
- /* Expand relative path to their full path equivalent */
- len = (int)STRLEN(curdir);
- if (len + (int)STRLEN(buf) + 3 > MAXPATHL)
+ } else if (buf[0] == NUL) {
+ STRCPY(buf, curdir); // relative to current directory
+ } else if (path_with_url((char *)buf)) {
+ continue; // URL can't be used here
+ } else if (!path_is_absolute_path(buf)) {
+ // Expand relative path to their full path equivalent
+ size_t len = STRLEN(curdir);
+ if (len + STRLEN(buf) + 3 > MAXPATHL) {
continue;
+ }
STRMOVE(buf + len + 1, buf);
STRCPY(buf, curdir);
buf[len] = PATHSEP;
@@ -860,31 +845,25 @@ static char_u *get_path_cutoff(char_u *fname, garray_T *gap)
*/
static void uniquefy_paths(garray_T *gap, char_u *pattern)
{
- int len;
- char_u **fnames = (char_u **)gap->ga_data;
+ char_u **fnames = (char_u **)gap->ga_data;
bool sort_again = false;
- char_u *pat;
- char_u *file_pattern;
- char_u *curdir;
regmatch_T regmatch;
garray_T path_ga;
- char_u **in_curdir = NULL;
- char_u *short_name;
+ char_u **in_curdir = NULL;
+ char_u *short_name;
ga_remove_duplicate_strings(gap);
ga_init(&path_ga, (int)sizeof(char_u *), 1);
- /*
- * We need to prepend a '*' at the beginning of file_pattern so that the
- * regex matches anywhere in the path. FIXME: is this valid for all
- * possible patterns?
- */
- len = (int)STRLEN(pattern);
- file_pattern = xmalloc(len + 2);
+ // We need to prepend a '*' at the beginning of file_pattern so that the
+ // regex matches anywhere in the path. FIXME: is this valid for all
+ // possible patterns?
+ size_t len = STRLEN(pattern);
+ char_u *file_pattern = xmalloc(len + 2);
file_pattern[0] = '*';
file_pattern[1] = NUL;
STRCAT(file_pattern, pattern);
- pat = file_pat_to_reg_pat(file_pattern, NULL, NULL, TRUE);
+ char_u *pat = file_pat_to_reg_pat(file_pattern, NULL, NULL, true);
xfree(file_pattern);
if (pat == NULL)
return;
@@ -895,11 +874,11 @@ static void uniquefy_paths(garray_T *gap, char_u *pattern)
if (regmatch.regprog == NULL)
return;
- curdir = xmalloc(MAXPATHL);
+ char_u *curdir = xmalloc(MAXPATHL);
os_dirname(curdir, MAXPATHL);
expand_path_option(curdir, &path_ga);
- in_curdir = xcalloc(gap->ga_len, sizeof(char_u *));
+ in_curdir = xcalloc((size_t)gap->ga_len, sizeof(char_u *));
for (int i = 0; i < gap->ga_len && !got_int; i++) {
char_u *path = fnames[i];
@@ -908,7 +887,7 @@ static void uniquefy_paths(garray_T *gap, char_u *pattern)
char_u *pathsep_p;
char_u *path_cutoff;
- len = (int)STRLEN(path);
+ len = STRLEN(path);
is_in_curdir = fnamencmp(curdir, path, dir_end - path) == 0
&& curdir[dir_end - path] == NUL;
if (is_in_curdir)
@@ -1113,9 +1092,8 @@ static bool has_special_wildchar(char_u *p)
int gen_expand_wildcards(int num_pat, char_u **pat, int *num_file,
char_u ***file, int flags)
{
- int i;
garray_T ga;
- char_u *p;
+ char_u *p;
static bool recursive = false;
int add_pat;
bool did_expand_in_path = false;
@@ -1140,11 +1118,11 @@ int gen_expand_wildcards(int num_pat, char_u **pat, int *num_file,
* avoids starting the shell for each argument separately.
* For `=expr` do use the internal function.
*/
- for (i = 0; i < num_pat; i++) {
+ for (int i = 0; i < num_pat; i++) {
if (has_special_wildchar(pat[i])
- && !(vim_backtick(pat[i]) && pat[i][1] == '=')
- )
+ && !(vim_backtick(pat[i]) && pat[i][1] == '=')) {
return mch_expand_wildcards(num_pat, pat, num_file, file, flags);
+ }
}
#endif
@@ -1155,7 +1133,7 @@ int gen_expand_wildcards(int num_pat, char_u **pat, int *num_file,
*/
ga_init(&ga, (int)sizeof(char_u *), 30);
- for (i = 0; i < num_pat; ++i) {
+ for (int i = 0; i < num_pat; ++i) {
add_pat = -1;
p = pat[i];
@@ -1212,7 +1190,9 @@ int gen_expand_wildcards(int num_pat, char_u **pat, int *num_file,
recursive = true;
did_expand_in_path = true;
} else {
- add_pat = path_expand(&ga, p, flags);
+ size_t tmp_add_pat = path_expand(&ga, p, flags);
+ assert(tmp_add_pat <= INT_MAX);
+ add_pat = (int)tmp_add_pat;
}
}
}
@@ -1261,14 +1241,12 @@ static int expand_backtick(
int flags /* EW_* flags */
)
{
- char_u *p;
- char_u *cmd;
- char_u *buffer;
+ char_u *p;
+ char_u *buffer;
int cnt = 0;
- int i;
- /* Create the command: lop off the backticks. */
- cmd = vim_strnsave(pat + 1, (int)STRLEN(pat) - 2);
+ // Create the command: lop off the backticks.
+ char_u *cmd = vim_strnsave(pat + 1, STRLEN(pat) - 2);
if (*cmd == '=') /* `={expr}`: Expand expression */
buffer = eval_to_string(cmd + 1, &p, TRUE);
@@ -1288,7 +1266,7 @@ static int expand_backtick(
++p;
/* add an entry if it is not empty */
if (p > cmd) {
- i = *p;
+ char_u i = *p;
*p = NUL;
addfile(gap, cmd, flags);
*p = i;
@@ -1541,9 +1519,8 @@ find_file_name_in_path (
char_u *rel_fname /* file we are searching relative to */
)
{
- char_u *file_name;
- int c;
- char_u *tofree = NULL;
+ char_u *file_name;
+ char_u *tofree = NULL;
if ((options & FNAME_INCL) && *curbuf->b_p_inex != NUL) {
tofree = eval_includeexpr(ptr, len);
@@ -1554,8 +1531,8 @@ find_file_name_in_path (
}
if (options & FNAME_EXP) {
- file_name = find_file_in_path(ptr, len, options & ~FNAME_MESS,
- TRUE, rel_fname);
+ file_name = find_file_in_path(ptr, len, options & ~FNAME_MESS, true,
+ rel_fname);
/*
* If the file could not be found in a normal way, try applying
@@ -1572,7 +1549,7 @@ find_file_name_in_path (
}
}
if (file_name == NULL && (options & FNAME_MESS)) {
- c = ptr[len];
+ char_u c = ptr[len];
ptr[len] = NUL;
EMSG2(_("E447: Can't find file \"%s\" in path"), ptr);
ptr[len] = c;
@@ -1631,7 +1608,7 @@ bool vim_isAbsName(char_u *name)
/// @param force is a flag to force expanding even if the path is absolute
///
/// @return FAIL for failure, OK otherwise
-int vim_FullName(const char *fname, char *buf, int len, bool force)
+int vim_FullName(const char *fname, char *buf, size_t len, bool force)
FUNC_ATTR_NONNULL_ARG(2)
{
int retval = OK;
@@ -2017,14 +1994,12 @@ int expand_wildcards(int num_pat, char_u **pat, int *num_file, char_u ***file,
*/
int match_suffix(char_u *fname)
{
- int fnamelen, setsuflen;
- char_u *setsuf;
-#define MAXSUFLEN 30 /* maximum length of a file suffix */
+#define MAXSUFLEN 30 // maximum length of a file suffix
char_u suf_buf[MAXSUFLEN];
- fnamelen = (int)STRLEN(fname);
- setsuflen = 0;
- for (setsuf = p_su; *setsuf; ) {
+ size_t fnamelen = STRLEN(fname);
+ size_t setsuflen = 0;
+ for (char_u *setsuf = p_su; *setsuf; ) {
setsuflen = copy_option_part(&setsuf, suf_buf, MAXSUFLEN, ".,");
if (setsuflen == 0) {
char_u *tail = path_tail(fname);
@@ -2035,10 +2010,10 @@ int match_suffix(char_u *fname)
break;
}
} else {
- if (fnamelen >= setsuflen
- && fnamencmp(suf_buf, fname + fnamelen - setsuflen,
- (size_t)setsuflen) == 0)
+ if (fnamelen >= setsuflen &&
+ fnamencmp(suf_buf, fname + fnamelen - setsuflen, setsuflen) == 0) {
break;
+ }
setsuflen = 0;
}
}
@@ -2049,7 +2024,7 @@ int match_suffix(char_u *fname)
///
/// @param directory Directory name, relative to current directory.
/// @return `FAIL` for failure, `OK` for success.
-int path_full_dir_name(char *directory, char *buffer, int len)
+int path_full_dir_name(char *directory, char *buffer, size_t len)
{
int SUCCESS = 0;
int retval = OK;
@@ -2091,10 +2066,10 @@ int path_full_dir_name(char *directory, char *buffer, int len)
// Append to_append to path with a slash in between.
// Append to_append to path with a slash in between.
-int append_path(char *path, const char *to_append, int max_len)
+int append_path(char *path, const char *to_append, size_t max_len)
{
- int current_length = STRLEN(path);
- int to_append_length = STRLEN(to_append);
+ size_t current_length = strlen(path);
+ size_t to_append_length = strlen(to_append);
// Do not append empty strings.
if (to_append_length == 0) {
@@ -2129,12 +2104,14 @@ int append_path(char *path, const char *to_append, int max_len)
/// Expand a given file to its absolute path.
///
-/// @param fname The filename which should be expanded.
-/// @param buf Buffer to store the absolute path of `fname`.
-/// @param len Length of `buf`.
-/// @param force Also expand when `fname` is already absolute.
-/// @return `FAIL` for failure, `OK` for success.
-static int path_get_absolute_path(const char_u *fname, char_u *buf, int len, int force)
+/// @param fname filename which should be expanded.
+/// @param buf buffer to store the absolute path of "fname".
+/// @param len length of "buf".
+/// @param force also expand when "fname" is already absolute.
+///
+/// @return FAIL for failure, OK for success.
+static int path_get_absolute_path(const char_u *fname, char_u *buf,
+ size_t len, int force)
{
char_u *p;
*buf = NUL;
diff --git a/src/nvim/pos.h b/src/nvim/pos.h
index 7071df51e8..864f3fe866 100644
--- a/src/nvim/pos.h
+++ b/src/nvim/pos.h
@@ -2,7 +2,11 @@
#define NVIM_POS_H
typedef long linenr_T; // line number type
-typedef int colnr_T; // column number type
+
+/// Column number type
+typedef int colnr_T;
+/// Format used to print values which have colnr_T type
+#define PRIdCOLNR "d"
#define MAXLNUM 0x7fffffff // maximum (invalid) line number
#define MAXCOL 0x7fffffff // maximum column number, 31 bits
diff --git a/src/nvim/quickfix.c b/src/nvim/quickfix.c
index f3abf864fb..3bc6d46dd9 100644
--- a/src/nvim/quickfix.c
+++ b/src/nvim/quickfix.c
@@ -200,9 +200,8 @@ qf_init_ext (
char_u *pattern;
char_u *fmtstr = NULL;
int col = 0;
- char_u use_viscol = FALSE;
- int type = 0;
- int valid;
+ bool use_viscol = false;
+ char_u type = 0;
linenr_T buflnum = lnumfirst;
long lnum = 0L;
int enr = 0;
@@ -220,16 +219,16 @@ qf_init_ext (
int i;
int round;
int idx = 0;
- int multiline = FALSE;
- int multiignore = FALSE;
- int multiscan = FALSE;
- int retval = -1; /* default: return error flag */
- char_u *directory = NULL;
- char_u *currfile = NULL;
- char_u *tail = NULL;
- char_u *p_str = NULL;
- listitem_T *p_li = NULL;
- struct dir_stack_T *file_stack = NULL;
+ bool multiline = false;
+ bool multiignore = false;
+ bool multiscan = false;
+ int retval = -1; // default: return error flag
+ char_u *directory = NULL;
+ char_u *currfile = NULL;
+ char_u *tail = NULL;
+ char_u *p_str = NULL;
+ listitem_T *p_li = NULL;
+ struct dir_stack_T *file_stack = NULL;
regmatch_T regmatch;
static struct fmtpattern {
char_u convchar;
@@ -278,15 +277,16 @@ qf_init_ext (
/*
* Get some space to modify the format string into.
*/
- i = 3 * FMT_PATTERNS + 4 * (int)STRLEN(efm);
- for (round = FMT_PATTERNS; round > 0; )
- i += (int)STRLEN(fmt_pat[--round].pattern);
+ size_t fmtstr_size = 3 * FMT_PATTERNS + 4 * STRLEN(efm);
+ for (round = FMT_PATTERNS; round > 0; ) {
+ fmtstr_size += STRLEN(fmt_pat[--round].pattern);
+ }
#ifdef COLON_IN_FILENAME
- i += 12; /* "%f" can become twelve chars longer */
+ fmtstr_size += 12; // "%f" can become twelve chars longer
#else
- i += 2; /* "%f" can become two chars longer */
+ fmtstr_size += 2; // "%f" can become two chars longer
#endif
- fmtstr = xmalloc(i);
+ fmtstr = xmalloc(fmtstr_size);
while (efm[0] != NUL) {
/*
@@ -530,11 +530,9 @@ qf_init_ext (
fmt_start = NULL;
}
- /*
- * Try to match each part of 'errorformat' until we find a complete
- * match or no match.
- */
- valid = TRUE;
+ // Try to match each part of 'errorformat' until we find a complete
+ // match or no match.
+ bool valid = true;
restofline:
for (; fmt_ptr != NULL; fmt_ptr = fmt_ptr->next) {
idx = fmt_ptr->prefix;
@@ -546,7 +544,7 @@ restofline:
errmsg[0] = NUL;
lnum = 0;
col = 0;
- use_viscol = FALSE;
+ use_viscol = false;
enr = -1;
type = 0;
tail = NULL;
@@ -555,25 +553,23 @@ restofline:
int r = vim_regexec(&regmatch, IObuff, (colnr_T)0);
fmt_ptr->prog = regmatch.regprog;
if (r) {
- if ((idx == 'C' || idx == 'Z') && !multiline)
+ if ((idx == 'C' || idx == 'Z') && !multiline) {
continue;
- if (vim_strchr((char_u *)"EWI", idx) != NULL)
- type = idx;
- else
+ }
+ if (vim_strchr((char_u *)"EWI", idx) != NULL) {
+ type = (char_u)idx;
+ } else {
type = 0;
- /*
- * Extract error message data from matched line.
- * We check for an actual submatch, because "\[" and "\]" in
- * the 'errorformat' may cause the wrong submatch to be used.
- */
- if ((i = (int)fmt_ptr->addr[0]) > 0) { /* %f */
- int c;
-
- if (regmatch.startp[i] == NULL || regmatch.endp[i] == NULL)
+ }
+ // Extract error message data from matched line.
+ // We check for an actual submatch, because "\[" and "\]" in
+ // the 'errorformat' may cause the wrong submatch to be used.
+ if ((i = (int)fmt_ptr->addr[0]) > 0) { // %f
+ if (regmatch.startp[i] == NULL || regmatch.endp[i] == NULL) {
continue;
-
- /* Expand ~/file and $HOME/file to full path. */
- c = *regmatch.endp[i];
+ }
+ // Expand ~/file and $HOME/file to full path.
+ char_u c = *regmatch.endp[i];
*regmatch.endp[i] = NUL;
expand_env(regmatch.startp[i], namebuf, CMDBUFFSIZE);
*regmatch.endp[i] = c;
@@ -629,14 +625,14 @@ restofline:
col -= col % 8;
}
}
- ++col;
- use_viscol = TRUE;
+ col++;
+ use_viscol = true;
}
if ((i = (int)fmt_ptr->addr[8]) > 0) { /* %v */
if (regmatch.startp[i] == NULL)
continue;
col = (int)atol((char *)regmatch.startp[i]);
- use_viscol = TRUE;
+ use_viscol = true;
}
if ((i = (int)fmt_ptr->addr[9]) > 0) { /* %s */
if (regmatch.startp[i] == NULL || regmatch.endp[i] == NULL)
@@ -653,7 +649,7 @@ restofline:
break;
}
}
- multiscan = FALSE;
+ multiscan = false;
if (fmt_ptr == NULL || idx == 'D' || idx == 'X') {
if (fmt_ptr != NULL) {
@@ -667,20 +663,21 @@ restofline:
} else if (idx == 'X') /* leave directory */
directory = qf_pop_dir(&dir_stack);
}
- namebuf[0] = NUL; /* no match found, remove file name */
- lnum = 0; /* don't jump to this line */
- valid = FALSE;
- STRCPY(errmsg, IObuff); /* copy whole line to error message */
- if (fmt_ptr == NULL)
- multiline = multiignore = FALSE;
+ namebuf[0] = NUL; // no match found, remove file name
+ lnum = 0; // don't jump to this line
+ valid = false;
+ STRCPY(errmsg, IObuff); // copy whole line to error message
+ if (fmt_ptr == NULL) {
+ multiline = multiignore = false;
+ }
} else if (fmt_ptr != NULL) {
/* honor %> item */
if (fmt_ptr->conthere)
fmt_start = fmt_ptr;
if (vim_strchr((char_u *)"AEWI", idx) != NULL) {
- multiline = TRUE; /* start of a multi-line message */
- multiignore = FALSE; /* reset continuation */
+ multiline = true; // start of a multi-line message
+ multiignore = false; // reset continuation
} else if (vim_strchr((char_u *)"CZ", idx)
!= NULL) { /* continuation of multi-line msg */
if (qfprev == NULL)
@@ -702,15 +699,17 @@ restofline:
qfprev->qf_viscol = use_viscol;
if (!qfprev->qf_fnum)
qfprev->qf_fnum = qf_get_fnum(directory,
- *namebuf || directory ? namebuf
- : currfile && valid ? currfile : 0);
- if (idx == 'Z')
- multiline = multiignore = FALSE;
+ *namebuf
+ || directory ? namebuf : currfile
+ && valid ? currfile : 0);
+ if (idx == 'Z') {
+ multiline = multiignore = false;
+ }
line_breakcheck();
continue;
} else if (vim_strchr((char_u *)"OPQ", idx) != NULL) {
- /* global file names */
- valid = FALSE;
+ // global file names
+ valid = false;
if (*namebuf == NUL || os_file_exists(namebuf)) {
if (*namebuf && idx == 'P')
currfile = qf_push_dir(namebuf, &file_stack);
@@ -719,14 +718,15 @@ restofline:
*namebuf = NUL;
if (tail && *tail) {
STRMOVE(IObuff, skipwhite(tail));
- multiscan = TRUE;
+ multiscan = true;
goto restofline;
}
}
}
- if (fmt_ptr->flags == '-') { /* generally exclude this line */
- if (multiline)
- multiignore = TRUE; /* also exclude continuation lines */
+ if (fmt_ptr->flags == '-') { // generally exclude this line
+ if (multiline) {
+ multiignore = true; // also exclude continuation lines
+ }
continue;
}
}
@@ -867,26 +867,27 @@ void qf_free_all(win_T *wp)
qf_free(qi, i);
}
-/*
- * Add an entry to the end of the list of errors.
- * Returns OK or FAIL.
- */
-static int
-qf_add_entry (
- qf_info_T *qi, /* quickfix list */
- qfline_T **prevp, /* nonnull pointer (to previously added entry or NULL) */
- char_u *dir, /* optional directory name */
- char_u *fname, /* file name or NULL */
- int bufnum, /* buffer number or zero */
- char_u *mesg, /* message */
- long lnum, /* line number */
- int col, /* column */
- int vis_col, /* using visual column */
- char_u *pattern, /* search pattern */
- int nr, /* error number */
- int type, /* type character */
- int valid /* valid entry */
-)
+/// Add an entry to the end of the list of errors.
+///
+/// @param qi quickfix list
+/// @param prevp nonnull pointer (to previously added entry or NULL)
+/// @param dir optional directory name
+/// @param fname file name or NULL
+/// @param bufnum buffer number or zero
+/// @param mesg message
+/// @param lnum line number
+/// @param col column
+/// @param vis_col using visual column
+/// @param pattern search pattern
+/// @param nr error number
+/// @param type type character
+/// @param valid valid entry
+///
+/// @returns OK or FAIL.
+static int qf_add_entry(qf_info_T *qi, qfline_T **prevp, char_u *dir,
+ char_u *fname, int bufnum, char_u *mesg, long lnum,
+ int col, char_u vis_col, char_u *pattern, int nr,
+ char_u type, char_u valid)
{
qfline_T *qfp = xmalloc(sizeof(qfline_T));
@@ -1657,12 +1658,13 @@ win_found:
* flag is present in 'shortmess'; But when not jumping, print the
* whole message. */
i = msg_scroll;
- if (curbuf == old_curbuf && curwin->w_cursor.lnum == old_lnum)
- msg_scroll = TRUE;
- else if (!msg_scrolled && shortmess(SHM_OVERALL))
- msg_scroll = FALSE;
- msg_attr_keep(IObuff, 0, TRUE);
- msg_scroll = i;
+ if (curbuf == old_curbuf && curwin->w_cursor.lnum == old_lnum) {
+ msg_scroll = true;
+ } else if (!msg_scrolled && shortmess(SHM_OVERALL)) {
+ msg_scroll = false;
+ }
+ msg_attr_keep(IObuff, 0, true);
+ msg_scroll = (int)i;
}
} else {
if (opened_window)
@@ -1827,10 +1829,12 @@ void qf_age(exarg_T *eap)
}
}
- if (eap->addr_count != 0)
- count = eap->line2;
- else
+ if (eap->addr_count != 0) {
+ assert(eap->line2 <= INT_MAX);
+ count = (int)eap->line2;
+ } else {
count = 1;
+ }
while (count--) {
if (eap->cmdidx == CMD_colder || eap->cmdidx == CMD_lolder) {
if (qi->qf_curlist == 0) {
@@ -1882,6 +1886,8 @@ static void qf_free(qf_info_T *qi, int idx)
--qi->qf_lists[idx].qf_count;
}
xfree(qi->qf_lists[idx].qf_title);
+ qi->qf_lists[idx].qf_start = NULL;
+ qi->qf_lists[idx].qf_ptr = NULL;
qi->qf_lists[idx].qf_title = NULL;
qi->qf_lists[idx].qf_index = 0;
}
@@ -1948,7 +1954,7 @@ static char_u *qf_types(int c, int nr)
p = (char_u *)"";
else {
cc[0] = ' ';
- cc[1] = c;
+ cc[1] = (char_u)c;
cc[2] = NUL;
p = cc;
}
@@ -2036,12 +2042,13 @@ void ex_copen(exarg_T *eap)
}
}
- if (eap->addr_count != 0)
- height = eap->line2;
- else
+ if (eap->addr_count != 0) {
+ assert(eap->line2 <= INT_MAX);
+ height = (int)eap->line2;
+ } else {
height = QF_WINHEIGHT;
-
- reset_VIsual_and_resel(); /* stop Visual mode */
+ }
+ reset_VIsual_and_resel(); // stop Visual mode
/*
* Find existing quickfix window, or open a new one.
@@ -2299,13 +2306,15 @@ static void qf_fill_buffer(qf_info_T *qi)
if (qfp->qf_fnum != 0
&& (errbuf = buflist_findnr(qfp->qf_fnum)) != NULL
&& errbuf->b_fname != NULL) {
- if (qfp->qf_type == 1) /* :helpgrep */
- STRCPY(IObuff, path_tail(errbuf->b_fname));
- else
- STRCPY(IObuff, errbuf->b_fname);
+ if (qfp->qf_type == 1) { // :helpgrep
+ STRLCPY(IObuff, path_tail(errbuf->b_fname), sizeof(IObuff));
+ } else {
+ STRLCPY(IObuff, errbuf->b_fname, sizeof(IObuff));
+ }
len = (int)STRLEN(IObuff);
- } else
+ } else {
len = 0;
+ }
IObuff[len++] = '|';
if (qfp->qf_lnum > 0) {
@@ -2432,7 +2441,7 @@ void ex_make(exarg_T *eap)
{
char_u *fname;
char_u *cmd;
- unsigned len;
+ size_t len;
win_T *wp = NULL;
qf_info_T *qi = &ql_info;
int res;
@@ -2473,9 +2482,10 @@ void ex_make(exarg_T *eap)
/*
* If 'shellpipe' empty: don't redirect to 'errorfile'.
*/
- len = (unsigned)STRLEN(p_shq) * 2 + (unsigned)STRLEN(eap->arg) + 1;
- if (*p_sp != NUL)
- len += (unsigned)STRLEN(p_sp) + (unsigned)STRLEN(fname) + 3;
+ len = STRLEN(p_shq) * 2 + STRLEN(eap->arg) + 1;
+ if (*p_sp != NUL) {
+ len += STRLEN(p_sp) + STRLEN(fname) + 3;
+ }
cmd = xmalloc(len);
sprintf((char *)cmd, "%s%s%s", (char *)p_shq, (char *)eap->arg,
(char *)p_shq);
@@ -2546,11 +2556,11 @@ static char_u *get_mef_name(void)
/* Keep trying until the name doesn't exist yet. */
for (;; ) {
- if (start == -1)
- start = os_get_pid();
- else
+ if (start == -1) {
+ start = (int)os_get_pid();
+ } else {
off += 19;
-
+ }
name = xmalloc(STRLEN(p_mef) + 30);
STRCPY(name, p_mef);
sprintf((char *)name + (p - p_mef), "%d%d", start, off);
@@ -2897,7 +2907,7 @@ void ex_vimgrep(exarg_T *eap)
int found_match;
buf_T *first_match_buf = NULL;
time_t seconds = 0;
- int save_mls;
+ long save_mls;
char_u *save_ei = NULL;
aco_save_T aco;
int flags = 0;
@@ -3454,18 +3464,12 @@ int get_errorlist(win_T *wp, list_T *list)
*/
int set_errorlist(win_T *wp, list_T *list, int action, char_u *title)
{
- listitem_T *li;
- dict_T *d;
- char_u *filename, *pattern, *text, *type;
- int bufnum;
- long lnum;
- int col, nr;
- int vcol;
- qfline_T *prevp = NULL;
- int valid, status;
+ listitem_T *li;
+ dict_T *d;
+ qfline_T *prevp = NULL;
int retval = OK;
- qf_info_T *qi = &ql_info;
- int did_bufnr_emsg = FALSE;
+ qf_info_T *qi = &ql_info;
+ bool did_bufnr_emsg = false;
if (wp != NULL) {
qi = ll_get_or_alloc_list(wp);
@@ -3492,21 +3496,22 @@ int set_errorlist(win_T *wp, list_T *list, int action, char_u *title)
if (d == NULL)
continue;
- filename = get_dict_string(d, (char_u *)"filename", TRUE);
- bufnum = get_dict_number(d, (char_u *)"bufnr");
- lnum = get_dict_number(d, (char_u *)"lnum");
- col = get_dict_number(d, (char_u *)"col");
- vcol = get_dict_number(d, (char_u *)"vcol");
- nr = get_dict_number(d, (char_u *)"nr");
- type = get_dict_string(d, (char_u *)"type", TRUE);
- pattern = get_dict_string(d, (char_u *)"pattern", TRUE);
- text = get_dict_string(d, (char_u *)"text", TRUE);
- if (text == NULL)
+ char_u *filename = get_dict_string(d, (char_u *)"filename", true);
+ int bufnum = (int)get_dict_number(d, (char_u *)"bufnr");
+ long lnum = get_dict_number(d, (char_u *)"lnum");
+ int col = (int)get_dict_number(d, (char_u *)"col");
+ char_u vcol = (char_u)get_dict_number(d, (char_u *)"vcol");
+ int nr = (int)get_dict_number(d, (char_u *)"nr");
+ char_u *type = get_dict_string(d, (char_u *)"type", true);
+ char_u *pattern = get_dict_string(d, (char_u *)"pattern", true);
+ char_u *text = get_dict_string(d, (char_u *)"text", true);
+ if (text == NULL) {
text = vim_strsave((char_u *)"");
-
- valid = TRUE;
- if ((filename == NULL && bufnum == 0) || (lnum == 0 && pattern == NULL))
- valid = FALSE;
+ }
+ bool valid = true;
+ if ((filename == NULL && bufnum == 0) || (lnum == 0 && pattern == NULL)) {
+ valid = false;
+ }
/* Mark entries with non-existing buffer number as not valid. Give the
* error message only once. */
@@ -3515,22 +3520,23 @@ int set_errorlist(win_T *wp, list_T *list, int action, char_u *title)
did_bufnr_emsg = TRUE;
EMSGN(_("E92: Buffer %" PRId64 " not found"), bufnum);
}
- valid = FALSE;
+ valid = false;
bufnum = 0;
}
- status = qf_add_entry(qi, &prevp,
- NULL, /* dir */
- filename,
- bufnum,
- text,
- lnum,
- col,
- vcol, /* vis_col */
- pattern, /* search pattern */
- nr,
- type == NULL ? NUL : *type,
- valid);
+ int status = qf_add_entry(qi,
+ &prevp,
+ NULL, // dir
+ filename,
+ bufnum,
+ text,
+ lnum,
+ col,
+ vcol, // vis_col
+ pattern, // search pattern
+ nr,
+ (char_u)(type == NULL ? NUL : *type),
+ valid);
xfree(filename);
xfree(pattern);
diff --git a/src/nvim/screen.c b/src/nvim/screen.c
index cd440fe8dc..1cc270023c 100644
--- a/src/nvim/screen.c
+++ b/src/nvim/screen.c
@@ -6780,8 +6780,8 @@ int showmode(void)
if (Recording
&& edit_submode == NULL /* otherwise it gets too long */
) {
- MSG_PUTS_ATTR(_("recording"), attr);
- need_clear = TRUE;
+ recording_mode(attr);
+ need_clear = true;
}
mode_displayed = TRUE;
@@ -6820,26 +6820,33 @@ static void msg_pos_mode(void)
msg_row = Rows - 1;
}
-/*
- * Delete mode message. Used when ESC is typed which is expected to end
- * Insert mode (but Insert mode didn't end yet!).
- * Caller should check "mode_displayed".
- */
-void unshowmode(int force)
+/// Delete mode message. Used when ESC is typed which is expected to end
+/// Insert mode (but Insert mode didn't end yet!).
+/// Caller should check "mode_displayed".
+void unshowmode(bool force)
{
- /*
- * Don't delete it right now, when not redrawing or inside a mapping.
- */
- if (!redrawing() || (!force && char_avail() && !KeyTyped))
- redraw_cmdline = TRUE; /* delete mode later */
- else {
+ // Don't delete it right now, when not redrawing or inside a mapping.
+ if (!redrawing() || (!force && char_avail() && !KeyTyped)) {
+ redraw_cmdline = true; // delete mode later
+ } else {
msg_pos_mode();
- if (Recording)
- MSG_PUTS_ATTR(_("recording"), hl_attr(HLF_CM));
+ if (Recording) {
+ recording_mode(hl_attr(HLF_CM));
+ }
msg_clr_eos();
}
}
+static void recording_mode(int attr)
+{
+ MSG_PUTS_ATTR(_("recording"), attr);
+ if (!shortmess(SHM_RECORDING)) {
+ char_u s[4];
+ vim_snprintf((char *)s, ARRAY_SIZE(s), " @%c", Recording);
+ MSG_PUTS_ATTR(s, attr);
+ }
+}
+
/*
* Draw the tab pages line at the top of the Vim window.
*/
diff --git a/src/nvim/syntax.c b/src/nvim/syntax.c
index 478fa973a1..26f0a6c94b 100644
--- a/src/nvim/syntax.c
+++ b/src/nvim/syntax.c
@@ -5533,25 +5533,29 @@ char_u *get_syntax_name(expand_T *xp, int idx)
}
-/*
- * Function called for expression evaluation: get syntax ID at file position.
- */
-int
-syn_get_id (
+// Function called for expression evaluation: get syntax ID at file position.
+int syn_get_id(
win_T *wp,
long lnum,
colnr_T col,
- int trans, /* remove transparency */
- bool *spellp, /* return: can do spell checking */
- int keep_state /* keep state of char at "col" */
+ int trans, // remove transparency
+ bool *spellp, // return: can do spell checking
+ int keep_state // keep state of char at "col"
)
{
- /* When the position is not after the current position and in the same
- * line of the same buffer, need to restart parsing. */
+ // When the position is not after the current position and in the same
+ // line of the same buffer, need to restart parsing.
if (wp->w_buffer != syn_buf
|| lnum != current_lnum
- || col < current_col)
+ || col < current_col) {
syntax_start(wp, lnum);
+ } else if (wp->w_buffer == syn_buf
+ && lnum == current_lnum
+ && col > current_col) {
+ // next_match may not be correct when moving around, e.g. with the
+ // "skip" expression in searchpair()
+ next_match_idx = -1;
+ }
(void)get_syntax_attr(col, spellp, keep_state);
@@ -6391,7 +6395,7 @@ do_highlight (
HL_TABLE()[idx].sg_cterm_bg = color + 1;
if (is_normal_group) {
cterm_normal_bg_color = color + 1;
- {
+ if (!ui_rgb_attached()) {
must_redraw = CLEAR;
if (color >= 0) {
if (t_colors < 16)
diff --git a/src/nvim/tempfile.c b/src/nvim/tempfile.c
index a218c03fdb..afe926b2ef 100644
--- a/src/nvim/tempfile.c
+++ b/src/nvim/tempfile.c
@@ -32,8 +32,9 @@ static void vim_maketempdir(void)
char_u path[TEMP_FILE_PATH_MAXLEN];
for (size_t i = 0; i < ARRAY_SIZE(temp_dirs); ++i) {
// Expand environment variables, leave room for "/nvimXXXXXX/999999999"
+ // Skip the directory check if the expansion fails.
expand_env((char_u *)temp_dirs[i], template, TEMP_FILE_PATH_MAXLEN - 22);
- if (!os_isdir(template)) { // directory doesn't exist
+ if (template[0] == '$' || !os_isdir(template)) {
continue;
}
diff --git a/src/nvim/terminal.c b/src/nvim/terminal.c
index 42fd81f643..63a7e20880 100644
--- a/src/nvim/terminal.c
+++ b/src/nvim/terminal.c
@@ -411,6 +411,10 @@ static int terminal_execute(VimState *state, int key)
apply_autocmds(EVENT_FOCUSLOST, NULL, NULL, false, curbuf);
break;
+ // Temporary fix until paste events gets implemented
+ case K_PASTE:
+ break;
+
case K_LEFTMOUSE:
case K_LEFTDRAG:
case K_LEFTRELEASE:
diff --git a/src/nvim/testdir/Makefile b/src/nvim/testdir/Makefile
index 63ca4cf6c4..ec236e72b4 100644
--- a/src/nvim/testdir/Makefile
+++ b/src/nvim/testdir/Makefile
@@ -32,7 +32,6 @@ SCRIPTS := \
test69.out \
test73.out \
test79.out \
- test88.out \
test_listlbr.out \
test_breakindent.out \
test_close_count.out \
diff --git a/src/nvim/testdir/test88.in b/src/nvim/testdir/test88.in
deleted file mode 100644
index 9e43f703e9..0000000000
--- a/src/nvim/testdir/test88.in
+++ /dev/null
@@ -1,99 +0,0 @@
-vim: set ft=vim
-
-Tests for correct display (cursor column position) with +conceal and
-tabulators.
-
-STARTTEST
-:so small.vim
-:if !has('conceal')
- e! test.ok
- wq! test.out
-:endif
-:" Conceal settings.
-:set conceallevel=2
-:set concealcursor=nc
-:syntax match test /|/ conceal
-:" Save current cursor position. Only works in <expr> mode, can't be used
-:" with :normal because it moves the cursor to the command line. Thanks to ZyX
-:" <zyx.vim@gmail.com> for the idea to use an <expr> mapping.
-:let positions = []
-:nnoremap <expr> GG ":let positions += ['".screenrow().":".screencol()."']\n"
-:" Start test.
-/^start:
-:normal ztj
-GGk
-:" We should end up in the same column when running these commands on the two
-:" lines.
-:normal ft
-GGk
-:normal $
-GGk
-:normal 0j
-GGk
-:normal ft
-GGk
-:normal $
-GGk
-:normal 0j0j
-GGk
-:" Same for next test block.
-:normal ft
-GGk
-:normal $
-GGk
-:normal 0j
-GGk
-:normal ft
-GGk
-:normal $
-GGk
-:normal 0j0j
-GGk
-:" And check W with multiple tabs and conceals in a line.
-:normal W
-GGk
-:normal W
-GGk
-:normal W
-GGk
-:normal $
-GGk
-:normal 0j
-GGk
-:normal W
-GGk
-:normal W
-GGk
-:normal W
-GGk
-:normal $
-GGk
-:set lbr
-:normal $
-GGk
-:set list listchars=tab:>-
-:normal 0
-GGk
-:normal W
-GGk
-:normal W
-GGk
-:normal W
-GGk
-:normal $
-GGk
-:" Display result.
-:call append('$', 'end:')
-:call append('$', positions)
-:/^end/,$wq! test.out
-ENDTEST
-
-start:
-.concealed. text
-|concealed| text
-
- .concealed. text
- |concealed| text
-
-.a. .b. .c. .d.
-|a| |b| |c| |d|
diff --git a/src/nvim/testdir/test88.ok b/src/nvim/testdir/test88.ok
deleted file mode 100644
index 12949f274a..0000000000
--- a/src/nvim/testdir/test88.ok
+++ /dev/null
@@ -1,29 +0,0 @@
-end:
-2:1
-2:17
-2:20
-3:1
-3:17
-3:20
-5:8
-5:25
-5:28
-6:8
-6:25
-6:28
-8:1
-8:9
-8:17
-8:25
-8:27
-9:1
-9:9
-9:17
-9:25
-9:26
-9:26
-9:1
-9:9
-9:17
-9:25
-9:26
diff --git a/src/nvim/undo.c b/src/nvim/undo.c
index 4a8a24d79d..7d9b2c7c3b 100644
--- a/src/nvim/undo.c
+++ b/src/nvim/undo.c
@@ -1782,7 +1782,13 @@ void undo_time(long step, int sec, int file, int absolute)
/* "target" is the node below which we want to be.
* Init "closest" to a value we can't reach. */
if (absolute) {
- target = step;
+ if (step == 0) {
+ // target 0 does not exist, got to 1 and above it.
+ target = 1;
+ above = true;
+ } else {
+ target = step;
+ }
closest = -1;
} else {
/* When doing computations with time_t subtract starttime, because
diff --git a/src/nvim/version.c b/src/nvim/version.c
index efd3c230a7..ebf21d162f 100644
--- a/src/nvim/version.c
+++ b/src/nvim/version.c
@@ -69,6 +69,14 @@ static char *features[] = {
// clang-format off
static int included_patches[] = {
+ 1654,
+ 1652,
+ 1643,
+ 1641,
+ 1574,
+ 1570,
+ 1511,
+ 1425,
1366,
// 1219 NA
@@ -149,7 +157,7 @@ static int included_patches[] = {
// 1144 NA
// 1143,
// 1142,
- // 1141,
+ 1141,
// 1140,
// 1139 NA
// 1138 NA
@@ -178,7 +186,7 @@ static int included_patches[] = {
// 1115 NA
// 1114,
// 1113,
- // 1112,
+ 1112,
// 1111,
// 1110,
// 1109 NA
@@ -297,7 +305,7 @@ static int included_patches[] = {
// 996 NA
// 995 NA
// 994 NA
- // 993,
+ // 993 NA
// 992 NA
991,
// 990 NA
@@ -316,12 +324,12 @@ static int included_patches[] = {
977,
// 976 NA
975,
- // 974,
- // 973,
+ 974,
+ 973,
972,
// 971 NA
// 970 NA
- // 969,
+ // 969 NA
// 968 NA
// 967 NA
// 966 NA
@@ -329,25 +337,25 @@ static int included_patches[] = {
// 964 NA
963,
// 962 NA
- // 961,
+ 961,
// 960 NA
// 959 NA
- // 958,
+ 958,
// 957,
- // 956,
+ // 956 NA
955,
// 954 NA
953,
- // 952,
+ 952,
// 951,
950,
949,
// 948 NA
- // 947,
+ // 947 NA
946,
945,
944,
- // 943,
+ // 943 NA
// 942,
// 941,
// 940 NA
@@ -365,7 +373,7 @@ static int included_patches[] = {
// 928 NA
// 927 NA
926,
- // 925,
+ 925,
// 924 NA
// 923 NA
922,
@@ -376,17 +384,17 @@ static int included_patches[] = {
// 917 NA
916,
915,
- // 914,
+ // 914 NA
// 913 NA
912,
// 911 NA
// 910 NA
- // 909,
+ // 909 NA
// 908 NA
// 907 NA
// 906 NA
- // 905,
- // 904,
+ // 905 NA
+ // 904 NA
903,
// 902 NA
901,
@@ -398,7 +406,7 @@ static int included_patches[] = {
895,
// 894 NA
893,
- // 892,
+ // 892 NA
891,
// 890 NA
// 889,
@@ -433,7 +441,7 @@ static int included_patches[] = {
// 860 NA
859,
858,
- // 857,
+ 857,
856,
// 855 NA
// 854 NA
diff --git a/src/nvim/window.c b/src/nvim/window.c
index 39106a7b8d..1b8c953596 100644
--- a/src/nvim/window.c
+++ b/src/nvim/window.c
@@ -248,7 +248,7 @@ newwindow:
/* First create a new tab with the window, then go back to
* the old tab and close the window there. */
wp = curwin;
- if (win_new_tabpage((int)Prenum) == OK
+ if (win_new_tabpage((int)Prenum, NULL) == OK
&& valid_tabpage(oldtab)) {
newtab = curtab;
goto_tabpage_tp(oldtab, TRUE, TRUE);
@@ -2952,14 +2952,15 @@ void free_tabpage(tabpage_T *tp)
xfree(tp);
}
-/*
- * Create a new Tab page with one window.
- * It will edit the current buffer, like after ":split".
- * When "after" is 0 put it just after the current Tab page.
- * Otherwise put it just before tab page "after".
- * Return FAIL or OK.
- */
-int win_new_tabpage(int after)
+/// Create a new tabpage with one window.
+///
+/// It will edit the current buffer, like after :split.
+///
+/// @param after Put new tabpage after tabpage "after", or after the current
+/// tabpage in case of 0.
+/// @param filename Will be passed to apply_autocmds().
+/// @return Was the new tabpage created successfully? FAIL or OK.
+int win_new_tabpage(int after, char_u *filename)
{
tabpage_T *tp = curtab;
tabpage_T *newtp;
@@ -2999,10 +3000,12 @@ int win_new_tabpage(int after)
newtp->tp_topframe = topframe;
last_status(FALSE);
-
redraw_all_later(CLEAR);
- apply_autocmds(EVENT_WINENTER, NULL, NULL, FALSE, curbuf);
- apply_autocmds(EVENT_TABENTER, NULL, NULL, FALSE, curbuf);
+
+ apply_autocmds(EVENT_TABNEW, filename, filename, false, curbuf);
+ apply_autocmds(EVENT_WINENTER, NULL, NULL, false, curbuf);
+ apply_autocmds(EVENT_TABENTER, NULL, NULL, false, curbuf);
+
return OK;
}
@@ -3023,7 +3026,7 @@ int may_open_tabpage(void)
if (n != 0) {
cmdmod.tab = 0; /* reset it to avoid doing it twice */
postponed_split_tab = 0;
- return win_new_tabpage(n);
+ return win_new_tabpage(n, NULL);
}
return FAIL;
}
@@ -3047,9 +3050,11 @@ int make_tabpages(int maxcount)
*/
block_autocmds();
- for (todo = count - 1; todo > 0; --todo)
- if (win_new_tabpage(0) == FAIL)
+ for (todo = count - 1; todo > 0; --todo) {
+ if (win_new_tabpage(0, NULL) == FAIL) {
break;
+ }
+ }
unblock_autocmds();
@@ -4619,10 +4624,8 @@ void win_drag_vsep_line(win_T *dragwin, int offset)
#define FRACTION_MULT 16384L
-/*
- * Set wp->w_fraction for the current w_wrow and w_height.
- */
-static void set_fraction(win_T *wp)
+// Set wp->w_fraction for the current w_wrow and w_height.
+void set_fraction(win_T *wp)
{
wp->w_fraction = ((long)wp->w_wrow * FRACTION_MULT + wp->w_height / 2)
/ (long)wp->w_height;
diff --git a/test/functional/api/buffer_spec.lua b/test/functional/api/buffer_spec.lua
index c924988d06..a15d489a1f 100644
--- a/test/functional/api/buffer_spec.lua
+++ b/test/functional/api/buffer_spec.lua
@@ -1,8 +1,8 @@
-- Sanity checks for buffer_* API calls via msgpack-rpc
local helpers = require('test.functional.helpers')
-local clear, nvim, buffer, curbuf, curwin, eq, ok =
- helpers.clear, helpers.nvim, helpers.buffer, helpers.curbuf, helpers.curwin,
- helpers.eq, helpers.ok
+local clear, nvim, buffer = helpers.clear, helpers.nvim, helpers.buffer
+local curbuf, curwin, eq = helpers.curbuf, helpers.curwin, helpers.eq
+local curbufmeths, ok = helpers.curbufmeths, helpers.ok
describe('buffer_* functions', function()
before_each(clear)
@@ -35,10 +35,11 @@ describe('buffer_* functions', function()
eq('', curbuf('get_line', 0))
end)
- it('get_line: out-of-bounds returns empty string', function()
+ it('get_line: out-of-bounds is an error', function()
curbuf('set_line', 0, 'line1.a')
- eq('', curbuf('get_line', 1))
- eq('', curbuf('get_line', -2))
+ eq(1, curbuf('line_count')) -- sanity
+ eq(false, pcall(curbuf, 'get_line', 1))
+ eq(false, pcall(curbuf, 'get_line', -2))
end)
it('set_line, del_line: out-of-bounds is an error', function()
@@ -68,14 +69,16 @@ describe('buffer_* functions', function()
eq({}, curbuf('get_line_slice', -4, -5, true, true))
end)
- it('set_line_slice: out-of-bounds is an error', function()
+ it('set_line_slice: out-of-bounds extends past end', function()
curbuf('set_line_slice', 0, 0, true, true, {'a', 'b', 'c'})
eq({'a', 'b', 'c'}, curbuf('get_line_slice', 0, 2, true, true)) --sanity
eq({'c'}, curbuf('get_line_slice', -1, 4, true, true))
eq({'a', 'b', 'c'}, curbuf('get_line_slice', 0, 5, true, true))
- eq(false, pcall(curbuf, 'set_line_slice', 4, 5, true, true, {'d'}))
- eq(false, pcall(curbuf, 'set_line_slice', -4, -5, true, true, {'d'}))
+ curbuf('set_line_slice', 4, 5, true, true, {'d'})
+ eq({'a', 'b', 'c', 'd'}, curbuf('get_line_slice', 0, 5, true, true))
+ curbuf('set_line_slice', -4, -5, true, true, {'e'})
+ eq({'e', 'a', 'b', 'c', 'd'}, curbuf('get_line_slice', 0, 5, true, true))
end)
it('works', function()
@@ -101,6 +104,136 @@ describe('buffer_* functions', function()
end)
end)
+ describe('{get,set}_lines', function()
+ local get_lines, set_lines = curbufmeths.get_lines, curbufmeths.set_lines
+ local line_count = curbufmeths.line_count
+
+ it('has correct line_count when inserting and deleting', function()
+ eq(1, line_count())
+ set_lines(-1, -1, true, {'line'})
+ eq(2, line_count())
+ set_lines(-1, -1, true, {'line'})
+ eq(3, line_count())
+ set_lines(-2, -1, true, {})
+ eq(2, line_count())
+ set_lines(-2, -1, true, {})
+ set_lines(-2, -1, true, {})
+ -- There's always at least one line
+ eq(1, line_count())
+ end)
+
+ it('can get, set and delete a single line', function()
+ eq({''}, get_lines(0, 1, true))
+ set_lines(0, 1, true, {'line1'})
+ eq({'line1'}, get_lines(0, 1, true))
+ set_lines(0, 1, true, {'line2'})
+ eq({'line2'}, get_lines(0, 1, true))
+ set_lines(0, 1, true, {})
+ eq({''}, get_lines(0, 1, true))
+ end)
+
+ it('can get a single line with strict indexing', function()
+ set_lines(0, 1, true, {'line1.a'})
+ eq(1, line_count()) -- sanity
+ eq(false, pcall(get_lines, 1, 2, true))
+ eq(false, pcall(get_lines, -3, -2, true))
+ end)
+
+ it('can get a single line with non-strict indexing', function()
+ set_lines(0, 1, true, {'line1.a'})
+ eq(1, line_count()) -- sanity
+ eq({}, get_lines(1, 2, false))
+ eq({}, get_lines(-3, -2, false))
+ end)
+
+ it('can set and delete a single line with strict indexing', function()
+ set_lines(0, 1, true, {'line1.a'})
+ eq(false, pcall(set_lines, 1, 2, true, {'line1.b'}))
+ eq(false, pcall(set_lines, -3, -2, true, {'line1.c'}))
+ eq({'line1.a'}, get_lines(0, -1, true))
+ eq(false, pcall(set_lines, 1, 2, true, {}))
+ eq(false, pcall(set_lines, -3, -2, true, {}))
+ eq({'line1.a'}, get_lines(0, -1, true))
+ end)
+
+ it('can set and delete a single line with non-strict indexing', function()
+ set_lines(0, 1, true, {'line1.a'})
+ set_lines(1, 2, false, {'line1.b'})
+ set_lines(-4, -3, false, {'line1.c'})
+ eq({'line1.c', 'line1.a', 'line1.b'}, get_lines(0, -1, true))
+ set_lines(3, 4, false, {})
+ set_lines(-5, -4, false, {})
+ eq({'line1.c', 'line1.a', 'line1.b'}, get_lines(0, -1, true))
+ end)
+
+ it('can handle NULs', function()
+ set_lines(0, 1, true, {'ab\0cd'})
+ eq({'ab\0cd'}, get_lines(0, -1, true))
+ end)
+
+ it('works with multiple lines', function()
+ eq({''}, get_lines(0, -1, true))
+ -- Replace buffer
+ for _, mode in pairs({false, true}) do
+ set_lines(0, -1, mode, {'a', 'b', 'c'})
+ eq({'a', 'b', 'c'}, get_lines(0, -1, mode))
+ eq({'b', 'c'}, get_lines(1, -1, mode))
+ eq({'b'}, get_lines(1, 2, mode))
+ eq({}, get_lines(1, 1, mode))
+ eq({'a', 'b'}, get_lines(0, -2, mode))
+ eq({'b'}, get_lines(1, -2, mode))
+ eq({'b', 'c'}, get_lines(-3, -1, mode))
+ set_lines(1, 2, mode, {'a', 'b', 'c'})
+ eq({'a', 'a', 'b', 'c', 'c'}, get_lines(0, -1, mode))
+ set_lines(-2, -1, mode, {'a', 'b', 'c'})
+ eq({'a', 'a', 'b', 'c', 'a', 'b', 'c'},
+ get_lines(0, -1, mode))
+ set_lines(0, -4, mode, {})
+ eq({'a', 'b', 'c'}, get_lines(0, -1, mode))
+ set_lines(0, -1, mode, {})
+ eq({''}, get_lines(0, -1, mode))
+ end
+ end)
+
+ it('can get line ranges with non-strict indexing', function()
+ set_lines(0, -1, true, {'a', 'b', 'c'})
+ eq({'a', 'b', 'c'}, get_lines(0, -1, true)) --sanity
+
+ eq({}, get_lines(3, 4, false))
+ eq({}, get_lines(3, 10, false))
+ eq({}, get_lines(-5, -5, false))
+ eq({}, get_lines(3, -1, false))
+ eq({}, get_lines(-3, -4, false))
+ end)
+
+ it('can get line ranges with strict indexing', function()
+ set_lines(0, -1, true, {'a', 'b', 'c'})
+ eq({'a', 'b', 'c'}, get_lines(0, -1, true)) --sanity
+
+ eq(false, pcall(get_lines, 3, 4, true))
+ eq(false, pcall(get_lines, 3, 10, true))
+ eq(false, pcall(get_lines, -5, -5, true))
+ -- empty or inverted ranges are not errors
+ eq({}, get_lines(3, -1, true))
+ eq({}, get_lines(-3, -4, true))
+ end)
+
+ it('set_line_slice: out-of-bounds can extend past end', function()
+ set_lines(0, -1, true, {'a', 'b', 'c'})
+ eq({'a', 'b', 'c'}, get_lines(0, -1, true)) --sanity
+
+ eq({'c'}, get_lines(-2, 5, false))
+ eq({'a', 'b', 'c'}, get_lines(0, 6, false))
+ eq(false, pcall(set_lines, 4, 6, true, {'d'}))
+ set_lines(4, 6, false, {'d'})
+ eq({'a', 'b', 'c', 'd'}, get_lines(0, -1, true))
+ eq(false, pcall(set_lines, -6, -6, true, {'e'}))
+ set_lines(-6, -6, false, {'e'})
+ eq({'e', 'a', 'b', 'c', 'd'}, get_lines(0, -1, true))
+ end)
+
+ end)
+
describe('{get,set}_var', function()
it('works', function()
curbuf('set_var', 'lua', {1, 2, {['3'] = 1}})
diff --git a/test/functional/api/server_requests_spec.lua b/test/functional/api/server_requests_spec.lua
index c0099e44c4..1b33275803 100644
--- a/test/functional/api/server_requests_spec.lua
+++ b/test/functional/api/server_requests_spec.lua
@@ -165,8 +165,8 @@ describe('server -> client', function()
eq('SOME TEXT', eval("rpcrequest(vim, 'buffer_get_line', "..buf..", 0)"))
- -- Call get_line_slice(buf, range [0,0], includes start, includes end)
- eq({'SOME TEXT'}, eval("rpcrequest(vim, 'buffer_get_line_slice', "..buf..", 0, 0, 1, 1)"))
+ -- Call get_lines(buf, range [0,0], strict_indexing)
+ eq({'SOME TEXT'}, eval("rpcrequest(vim, 'buffer_get_lines', "..buf..", 0, 1, 1)"))
end)
it('returns an error if the request failed', function()
diff --git a/test/functional/api/vim_spec.lua b/test/functional/api/vim_spec.lua
index 9c9759adf6..99f67fe43a 100644
--- a/test/functional/api/vim_spec.lua
+++ b/test/functional/api/vim_spec.lua
@@ -3,7 +3,7 @@ local helpers = require('test.functional.helpers')
local Screen = require('test.functional.ui.screen')
local clear, nvim, eq, neq = helpers.clear, helpers.nvim, helpers.eq, helpers.neq
local ok, nvim_async, feed = helpers.ok, helpers.nvim_async, helpers.feed
-local os_is_windows = helpers.os_is_windows
+local os_name = helpers.os_name
describe('vim_* functions', function()
before_each(clear)
@@ -17,7 +17,7 @@ describe('vim_* functions', function()
nvim('command', 'w')
local f = io.open(fname)
ok(f ~= nil)
- if os_is_windows() then
+ if os_name() == 'windows' then
eq('testing\r\napi\r\n', f:read('*a'))
else
eq('testing\napi\n', f:read('*a'))
diff --git a/test/functional/autocmd/autocmd_spec.lua b/test/functional/autocmd/autocmd_spec.lua
new file mode 100644
index 0000000000..3c813abc2e
--- /dev/null
+++ b/test/functional/autocmd/autocmd_spec.lua
@@ -0,0 +1,31 @@
+local helpers = require('test.functional.helpers')
+
+local clear = helpers.clear
+local command = helpers.command
+local eval = helpers.eval
+
+describe('autocmds:', function()
+ before_each(clear)
+
+ it(':tabnew triggers events in the correct order', function()
+ local expected = {
+ 'WinLeave',
+ 'TabLeave',
+ 'TabNew',
+ 'WinEnter',
+ 'TabEnter',
+ 'BufLeave',
+ 'BufEnter'
+ }
+ command('let g:foo = []')
+ command('autocmd BufEnter * :call add(g:foo, "BufEnter")')
+ command('autocmd BufLeave * :call add(g:foo, "BufLeave")')
+ command('autocmd TabEnter * :call add(g:foo, "TabEnter")')
+ command('autocmd TabLeave * :call add(g:foo, "TabLeave")')
+ command('autocmd TabNew * :call add(g:foo, "TabNew")')
+ command('autocmd WinEnter * :call add(g:foo, "WinEnter")')
+ command('autocmd WinLeave * :call add(g:foo, "WinLeave")')
+ command('tabnew')
+ assert.same(expected, eval('g:foo'))
+ end)
+end)
diff --git a/test/functional/autocmd/tabnew_spec.lua b/test/functional/autocmd/tabnew_spec.lua
index 5ab504889b..aaf9db0a99 100644
--- a/test/functional/autocmd/tabnew_spec.lua
+++ b/test/functional/autocmd/tabnew_spec.lua
@@ -1,22 +1,28 @@
local helpers = require('test.functional.helpers')
-local clear, nvim, eq = helpers.clear, helpers.nvim, helpers.eq
-describe('TabNew', function()
- setup(clear)
- describe('au TabNew', function()
- describe('with * as <afile>', function()
- it('matches when opening any new tab', function()
- nvim('command', 'au! TabNew * echom "tabnew:".tabpagenr().":".bufnr("")')
- eq("\ntabnew:2:1", nvim('command_output', 'tabnew'))
- eq("\ntabnew:3:2\n\"test.x\" [New File]", nvim('command_output', 'tabnew test.x'))
- end)
- end)
- describe('with FILE as <afile>', function()
- it('matches when opening a new tab for FILE', function()
- local tmp_path = nvim('eval', 'tempname()')
- nvim('command', 'au! TabNew '..tmp_path..' echom "tabnew:match"')
- eq("\ntabnew:4:3\ntabnew:match\n\""..tmp_path.."\" [New File]", nvim('command_output', 'tabnew '..tmp_path))
- end)
- end)
- end)
+local clear = helpers.clear
+local command = helpers.command
+local eq = helpers.eq
+local eval = helpers.eval
+
+describe('autocmd TabNew', function()
+ before_each(clear)
+
+ it('matches when opening any new tab', function()
+ command('autocmd! TabNew * let g:test = "tabnew:".tabpagenr().":".bufnr("")')
+ command('tabnew')
+ eq('tabnew:2:1', eval('g:test'))
+ command('tabnew test.x')
+ eq('tabnew:3:2', eval('g:test'))
+ end)
+
+ it('matches when opening a new tab for FILE', function()
+ local tmp_path = helpers.funcs.tempname()
+ command('let g:test = "foo"')
+ command('autocmd! TabNew ' .. tmp_path .. ' let g:test = "bar"')
+ command('tabnew ' .. tmp_path ..'X')
+ eq('foo', eval('g:test'))
+ command('tabnew ' .. tmp_path)
+ eq('bar', eval('g:test'))
+ end)
end)
diff --git a/test/functional/autocmd/textyankpost_spec.lua b/test/functional/autocmd/textyankpost_spec.lua
new file mode 100644
index 0000000000..0e46aa5641
--- /dev/null
+++ b/test/functional/autocmd/textyankpost_spec.lua
@@ -0,0 +1,216 @@
+local helpers = require('test.functional.helpers')
+local clear, eval, eq, insert = helpers.clear, helpers.eval, helpers.eq, helpers.insert
+local feed, execute, expect, command = helpers.feed, helpers.execute, helpers.expect, helpers.command
+local curbufmeths, funcs, neq = helpers.curbufmeths, helpers.funcs, helpers.neq
+
+describe('TextYankPost', function()
+ before_each(function()
+ clear()
+
+ -- emulate the clipboard so system clipboard isn't affected
+ execute('let &rtp = "test/functional/fixtures,".&rtp')
+
+ execute('let g:count = 0')
+ execute('autocmd TextYankPost * let g:event = copy(v:event)')
+ execute('autocmd TextYankPost * let g:count += 1')
+
+ curbufmeths.set_lines(0, -1, true, {
+ 'foo\0bar',
+ 'baz text',
+ })
+ end)
+
+ it('is executed after yank and handles register types', function()
+ feed('yy')
+ eq({
+ operator = 'y',
+ regcontents = { 'foo\nbar' },
+ regname = '',
+ regtype = 'V'
+ }, eval('g:event'))
+ eq(1, eval('g:count'))
+
+ -- v:event is cleared after the autocommand is done
+ eq({}, eval('v:event'))
+
+ feed('+yw')
+ eq({
+ operator = 'y',
+ regcontents = { 'baz ' },
+ regname = '',
+ regtype = 'v'
+ }, eval('g:event'))
+ eq(2, eval('g:count'))
+
+ feed('<c-v>eky')
+ eq({
+ operator = 'y',
+ regcontents = { 'foo', 'baz' },
+ regname = '',
+ regtype = "\0223" -- ^V + block width
+ }, eval('g:event'))
+ eq(3, eval('g:count'))
+ end)
+
+ it('makes v:event immutable', function()
+ feed('yy')
+ eq({
+ operator = 'y',
+ regcontents = { 'foo\nbar' },
+ regname = '',
+ regtype = 'V'
+ }, eval('g:event'))
+
+ execute('set debug=msg')
+ -- the regcontents should not be changed without copy.
+ local status, err = pcall(command,'call extend(g:event.regcontents, ["more text"])')
+ eq(status,false)
+ neq(nil, string.find(err, ':E742:'))
+
+ -- can't mutate keys inside the autocommand
+ execute('autocmd! TextYankPost * let v:event.regcontents = 0')
+ status, err = pcall(command,'normal yy')
+ eq(status,false)
+ neq(nil, string.find(err, ':E46:'))
+
+ -- can't add keys inside the autocommand
+ execute('autocmd! TextYankPost * let v:event.mykey = 0')
+ status, err = pcall(command,'normal yy')
+ eq(status,false)
+ neq(nil, string.find(err, ':E742:'))
+ end)
+
+ it('is not invoked recursively', function()
+ execute('autocmd TextYankPost * normal "+yy')
+ feed('yy')
+ eq({
+ operator = 'y',
+ regcontents = { 'foo\nbar' },
+ regname = '',
+ regtype = 'V'
+ }, eval('g:event'))
+ eq(1, eval('g:count'))
+ eq({ 'foo\nbar' }, funcs.getreg('+',1,1))
+ end)
+
+ it('is executed after delete and change', function()
+ feed('dw')
+ eq({
+ operator = 'd',
+ regcontents = { 'foo' },
+ regname = '',
+ regtype = 'v'
+ }, eval('g:event'))
+ eq(1, eval('g:count'))
+
+ feed('dd')
+ eq({
+ operator = 'd',
+ regcontents = { '\nbar' },
+ regname = '',
+ regtype = 'V'
+ }, eval('g:event'))
+ eq(2, eval('g:count'))
+
+ feed('cwspam<esc>')
+ eq({
+ operator = 'c',
+ regcontents = { 'baz' },
+ regname = '',
+ regtype = 'v'
+ }, eval('g:event'))
+ eq(3, eval('g:count'))
+ end)
+
+ it('is not executed after black-hole operation', function()
+ feed('"_dd')
+ eq(0, eval('g:count'))
+
+ feed('"_cwgood<esc>')
+ eq(0, eval('g:count'))
+
+ expect([[
+ good text]])
+ feed('"_yy')
+ eq(0, eval('g:count'))
+
+ execute('delete _')
+ eq(0, eval('g:count'))
+ end)
+
+ it('gives the correct register name', function()
+ feed('$"byiw')
+ eq({
+ operator = 'y',
+ regcontents = { 'bar' },
+ regname = 'b',
+ regtype = 'v'
+ }, eval('g:event'))
+
+ feed('"*yy')
+ eq({
+ operator = 'y',
+ regcontents = { 'foo\nbar' },
+ regname = '*',
+ regtype = 'V'
+ }, eval('g:event'))
+
+ execute("set clipboard=unnamed")
+
+ -- regname still shows the name the user requested
+ feed('yy')
+ eq({
+ operator = 'y',
+ regcontents = { 'foo\nbar' },
+ regname = '',
+ regtype = 'V'
+ }, eval('g:event'))
+
+ feed('"*yy')
+ eq({
+ operator = 'y',
+ regcontents = { 'foo\nbar' },
+ regname = '*',
+ regtype = 'V'
+ }, eval('g:event'))
+ end)
+
+ it('works with Ex commands', function()
+ execute('1delete +')
+ eq({
+ operator = 'd',
+ regcontents = { 'foo\nbar' },
+ regname = '+',
+ regtype = 'V'
+ }, eval('g:event'))
+ eq(1, eval('g:count'))
+
+ execute('yank')
+ eq({
+ operator = 'y',
+ regcontents = { 'baz text' },
+ regname = '',
+ regtype = 'V'
+ }, eval('g:event'))
+ eq(2, eval('g:count'))
+
+ execute('normal yw')
+ eq({
+ operator = 'y',
+ regcontents = { 'baz ' },
+ regname = '',
+ regtype = 'v'
+ }, eval('g:event'))
+ eq(3, eval('g:count'))
+
+ execute('normal! dd')
+ eq({
+ operator = 'd',
+ regcontents = { 'baz text' },
+ regname = '',
+ regtype = 'V'
+ }, eval('g:event'))
+ eq(4, eval('g:count'))
+ end)
+
+end)
diff --git a/test/functional/eval/operators_spec.lua b/test/functional/eval/operators_spec.lua
new file mode 100644
index 0000000000..bc9a17935c
--- /dev/null
+++ b/test/functional/eval/operators_spec.lua
@@ -0,0 +1,28 @@
+local helpers = require('test.functional.helpers')
+local eq = helpers.eq
+local eval = helpers.eval
+local clear = helpers.clear
+
+describe('Division operator', function()
+ before_each(clear)
+
+ it('returns infinity on {positive}/0.0', function()
+ eq('str2float(\'inf\')', eval('string(1.0/0.0)'))
+ eq('str2float(\'inf\')', eval('string(1.0e-100/0.0)'))
+ eq('str2float(\'inf\')', eval('string(1.0e+100/0.0)'))
+ eq('str2float(\'inf\')', eval('string((1.0/0.0)/0.0)'))
+ end)
+
+ it('returns -infinity on {negative}/0.0', function()
+ eq('-str2float(\'inf\')', eval('string((-1.0)/0.0)'))
+ eq('-str2float(\'inf\')', eval('string((-1.0e-100)/0.0)'))
+ eq('-str2float(\'inf\')', eval('string((-1.0e+100)/0.0)'))
+ eq('-str2float(\'inf\')', eval('string((-1.0/0.0)/0.0)'))
+ end)
+
+ it('returns NaN on 0.0/0.0', function()
+ eq('str2float(\'nan\')', eval('string(0.0/0.0)'))
+ eq('str2float(\'nan\')', eval('string(-(0.0/0.0))'))
+ eq('str2float(\'nan\')', eval('string((-0.0)/0.0)'))
+ end)
+end)
diff --git a/test/functional/eval/string_spec.lua b/test/functional/eval/string_spec.lua
new file mode 100644
index 0000000000..f7f5dca70a
--- /dev/null
+++ b/test/functional/eval/string_spec.lua
@@ -0,0 +1,175 @@
+local helpers = require('test.functional.helpers')
+local clear = helpers.clear
+local eq = helpers.eq
+local command = helpers.command
+local meths = helpers.meths
+local eval = helpers.eval
+local exc_exec = helpers.exc_exec
+local redir_exec = helpers.redir_exec
+local funcs = helpers.funcs
+local write_file = helpers.write_file
+
+describe('string() function', function()
+ before_each(clear)
+
+ describe('used to represent floating-point values', function()
+ it('dumps NaN values', function()
+ eq('str2float(\'nan\')', eval('string(str2float(\'nan\'))'))
+ end)
+
+ it('dumps infinite values', function()
+ eq('str2float(\'inf\')', eval('string(str2float(\'inf\'))'))
+ eq('-str2float(\'inf\')', eval('string(str2float(\'-inf\'))'))
+ end)
+
+ it('dumps regular values', function()
+ eq('1.5', funcs.string(1.5))
+ eq('1.56e-20', funcs.string(1.56000e-020))
+ eq('0.0', eval('string(0.0)'))
+ end)
+
+ it('dumps values with at most six digits after the decimal point',
+ function()
+ eq('1.234568e-20', funcs.string(1.23456789123456789123456789e-020))
+ eq('1.234568', funcs.string(1.23456789123456789123456789))
+ end)
+
+ it('dumps values with at most seven digits before the decimal point',
+ function()
+ eq('1234567.891235', funcs.string(1234567.89123456789123456789))
+ eq('1.234568e7', funcs.string(12345678.9123456789123456789))
+ end)
+
+ it('dumps negative values', function()
+ eq('-1.5', funcs.string(-1.5))
+ eq('-1.56e-20', funcs.string(-1.56000e-020))
+ eq('-1.234568e-20', funcs.string(-1.23456789123456789123456789e-020))
+ eq('-1.234568', funcs.string(-1.23456789123456789123456789))
+ eq('-1234567.891235', funcs.string(-1234567.89123456789123456789))
+ eq('-1.234568e7', funcs.string(-12345678.9123456789123456789))
+ end)
+ end)
+
+ describe('used to represent numbers', function()
+ it('dumps regular values', function()
+ eq('0', funcs.string(0))
+ eq('-1', funcs.string(-1))
+ eq('1', funcs.string(1))
+ end)
+
+ it('dumps large values', function()
+ eq('2147483647', funcs.string(2^31-1))
+ eq('-2147483648', funcs.string(-2^31))
+ end)
+ end)
+
+ describe('used to represent strings', function()
+ it('dumps regular strings', function()
+ eq('\'test\'', funcs.string('test'))
+ end)
+
+ it('dumps empty strings', function()
+ eq('\'\'', funcs.string(''))
+ end)
+
+ it('dumps strings with \' inside', function()
+ eq('\'\'\'\'\'\'\'\'', funcs.string('\'\'\''))
+ eq('\'a\'\'b\'\'\'\'\'', funcs.string('a\'b\'\''))
+ eq('\'\'\'b\'\'\'\'d\'', funcs.string('\'b\'\'d'))
+ eq('\'a\'\'b\'\'c\'\'d\'', funcs.string('a\'b\'c\'d'))
+ end)
+ end)
+
+ describe('used to represent funcrefs', function()
+ local fname = 'Xtest-functional-eval-string_spec-fref-script.vim'
+
+ before_each(function()
+ write_file(fname, [[
+ function Test1()
+ endfunction
+
+ function s:Test2()
+ endfunction
+
+ function g:Test3()
+ endfunction
+
+ let g:Test2_f = function('s:Test2')
+ ]])
+ command('source ' .. fname)
+ end)
+
+ after_each(function()
+ os.remove(fname)
+ end)
+
+ it('dumps references to built-in functions', function()
+ eq('function(\'function\')', eval('string(function("function"))'))
+ end)
+
+ it('dumps references to user functions', function()
+ eq('function(\'Test1\')', eval('string(function("Test1"))'))
+ eq('function(\'g:Test3\')', eval('string(function("g:Test3"))'))
+ end)
+
+ it('dumps references to script functions', function()
+ eq('function(\'<SNR>1_Test2\')', eval('string(Test2_f)'))
+ end)
+ end)
+
+ describe('used to represent lists', function()
+ it('dumps empty list', function()
+ eq('[]', funcs.string({}))
+ end)
+
+ it('dumps nested lists', function()
+ eq('[[[[[]]]]]', funcs.string({{{{{}}}}}))
+ end)
+
+ it('dumps nested non-empty lists', function()
+ eq('[1, [[3, [[5], 4]], 2]]', funcs.string({1, {{3, {{5}, 4}}, 2}}))
+ end)
+
+ it('errors when dumping recursive lists', function()
+ meths.set_var('l', {})
+ eval('add(l, l)')
+ eq('Vim(echo):E724: unable to correctly dump variable with self-referencing container',
+ exc_exec('echo string(l)'))
+ end)
+
+ it('dumps recursive lists despite the error', function()
+ meths.set_var('l', {})
+ eval('add(l, l)')
+ eq('\nE724: unable to correctly dump variable with self-referencing container\n[{E724@0}]',
+ redir_exec('echo string(l)'))
+ eq('\nE724: unable to correctly dump variable with self-referencing container\n[[{E724@1}]]',
+ redir_exec('echo string([l])'))
+ end)
+ end)
+
+ describe('used to represent dictionaries', function()
+ it('dumps empty dictionary', function()
+ eq('{}', eval('string({})'))
+ end)
+
+ it('dumps non-empty dictionary', function()
+ eq('{\'t\'\'est\': 1}', funcs.string({['t\'est']=1}))
+ end)
+
+ it('errors when dumping recursive dictionaries', function()
+ meths.set_var('d', {d=1})
+ eval('extend(d, {"d": d})')
+ eq('Vim(echo):E724: unable to correctly dump variable with self-referencing container',
+ exc_exec('echo string(d)'))
+ end)
+
+ it('dumps recursive dictionaries despite the error', function()
+ meths.set_var('d', {d=1})
+ eval('extend(d, {"d": d})')
+ eq('\nE724: unable to correctly dump variable with self-referencing container\n{\'d\': {E724@0}}',
+ redir_exec('echo string(d)'))
+ eq('\nE724: unable to correctly dump variable with self-referencing container\n{\'out\': {\'d\': {E724@1}}}',
+ redir_exec('echo string({"out": d})'))
+ end)
+ end)
+end)
diff --git a/test/functional/eval/vvar_event_spec.lua b/test/functional/eval/vvar_event_spec.lua
new file mode 100644
index 0000000000..bbac86524f
--- /dev/null
+++ b/test/functional/eval/vvar_event_spec.lua
@@ -0,0 +1,15 @@
+local helpers = require('test.functional.helpers')
+local clear, eval, eq = helpers.clear, helpers.eval, helpers.eq
+local command = helpers.command
+describe('v:event', function()
+ before_each(clear)
+ it('is empty before any autocommand', function()
+ eq({}, eval('v:event'))
+ end)
+
+ it('is immutable', function()
+ eq(false, pcall(command, 'let v:event = {}'))
+ eq(false, pcall(command, 'let v:event.mykey = {}'))
+ end)
+end)
+
diff --git a/test/functional/fixtures/shell-test.c b/test/functional/fixtures/shell-test.c
index 5fa8a58049..d9ec254aff 100644
--- a/test/functional/fixtures/shell-test.c
+++ b/test/functional/fixtures/shell-test.c
@@ -1,25 +1,59 @@
-// A simple implementation of a shell for testing
-// `termopen([&sh, &shcf, '{cmd'}])` and `termopen([&sh])`.
-//
-// If launched with no arguments, prints "ready $ ", otherwise prints
-// "ready $ {cmd}\n".
-
#include <stdio.h>
#include <string.h>
+#include <stdint.h>
+
+static void help(void)
+{
+ puts("A simple implementation of a shell for testing termopen().");
+ puts("");
+ puts("Usage:");
+ puts(" shell-test --help");
+ puts(" Prints this help to stdout.");
+ puts(" shell-test");
+ puts(" shell-test EXE");
+ puts(" Prints \"ready $ \" to stderr.");
+ puts(" shell-test EXE \"prog args...\"");
+ puts(" Prints \"ready $ prog args...\\n\" to stderr.");
+ puts(" shell-test REP {byte} \"line line line\"");
+ puts(" Prints \"{lnr}: line line line\\n\" to stdout {byte} times.");
+ puts(" I.e. for `shell-test REP ab \"test\"'");
+ puts(" 0: test");
+ puts(" ...");
+ puts(" 96: test");
+ puts(" will be printed because byte `a' is equal to 97.");
+}
int main(int argc, char **argv)
{
- fprintf(stderr, "ready $ ");
+ if (argc == 2 && strcmp(argv[1], "--help") == 0) {
+ help();
+ }
- if (argc == 3) {
- // argv should be {"terminal-test", "EXE", "prog args..."}
- if (strcmp(argv[1], "EXE") != 0) {
- fprintf(stderr, "first argument must be 'EXE'\n");
- return 2;
+ if (argc >= 2) {
+ if (strcmp(argv[1], "EXE") == 0) {
+ fprintf(stderr, "ready $ ");
+ if (argc >= 3) {
+ fprintf(stderr, "%s\n", argv[2]);
+ }
+ } else if (strcmp(argv[1], "REP") == 0) {
+ if (argc < 4) {
+ fprintf(stderr, "Not enough REP arguments\n");
+ return 4;
+ }
+ uint8_t number = (uint8_t) *argv[2];
+ for (uint8_t i = 0; i < number; i++) {
+ printf("%d: %s\n", (int) i, argv[3]);
+ }
+ } else {
+ fprintf(stderr, "Unknown first argument\n");
+ return 3;
}
-
- fprintf(stderr, "%s\n", argv[2]);
+ return 0;
+ } else if (argc == 1) {
+ fprintf(stderr, "ready $ ");
+ return 0;
+ } else {
+ fprintf(stderr, "Missing first argument\n");
+ return 2;
}
-
- return 0;
}
diff --git a/test/functional/helpers.lua b/test/functional/helpers.lua
index 1fba15c2c3..4e294029ab 100644
--- a/test/functional/helpers.lua
+++ b/test/functional/helpers.lua
@@ -1,5 +1,4 @@
require('coxpcall')
-local ffi = require('ffi')
local lfs = require('lfs')
local assert = require('luassert')
local Loop = require('nvim.loop')
@@ -133,6 +132,22 @@ local function nvim_eval(expr)
return request('vim_eval', expr)
end
+local os_name = (function()
+ local name = nil
+ return (function()
+ if not name then
+ if nvim_eval('has("win32")') == 1 then
+ name = 'windows'
+ elseif nvim_eval('has("macunix")') == 1 then
+ name = 'osx'
+ else
+ name = 'unix'
+ end
+ end
+ return name
+ end)
+end)()
+
local function nvim_call(name, ...)
return request('vim_call_function', name, {...})
end
@@ -247,7 +262,7 @@ end
local function source(code)
local tmpname = os.tmpname()
- if ffi.os == 'OSX' and string.match(tmpname, '^/tmp') then
+ if os_name() == 'osx' and string.match(tmpname, '^/tmp') then
tmpname = '/private'..tmpname
end
write_file(tmpname, code)
@@ -305,7 +320,7 @@ local function curbuf_contents()
-- previously sent keys are processed(vim_eval is a deferred function, and
-- only processed after all input)
wait()
- return table.concat(curbuf('get_line_slice', 0, -1, true, true), '\n')
+ return table.concat(curbuf('get_lines', 0, -1, true), '\n')
end
local function curwin(method, ...)
@@ -328,24 +343,18 @@ local function expect(contents)
return eq(dedent(contents), curbuf_contents())
end
-local function os_is_windows()
- return nvim_eval('has("win32")') == 1
-end
-
local function rmdir(path)
if lfs.attributes(path, 'mode') ~= 'directory' then
return nil
end
for file in lfs.dir(path) do
- if file == '.' or file == '..' then
- goto continue
- end
- local ret, err = os.remove(path..'/'..file)
- if not ret then
- error('os.remove: '..err)
- return nil
+ if file ~= '.' and file ~= '..' then
+ local ret, err = os.remove(path..'/'..file)
+ if not ret then
+ error('os.remove: '..err)
+ return nil
+ end
end
- ::continue::
end
local ret, err = os.remove(path)
if not ret then
@@ -434,7 +443,7 @@ return {
wait = wait,
set_session = set_session,
write_file = write_file,
- os_is_windows = os_is_windows,
+ os_name = os_name,
rmdir = rmdir,
mkdir = lfs.mkdir,
exc_exec = exc_exec,
diff --git a/test/functional/legacy/036_regexp_character_classes_spec.lua b/test/functional/legacy/036_regexp_character_classes_spec.lua
index 3c264423ff..de080f4b43 100644
--- a/test/functional/legacy/036_regexp_character_classes_spec.lua
+++ b/test/functional/legacy/036_regexp_character_classes_spec.lua
@@ -1,9 +1,9 @@
-- Test character classes in regexp using regexpengine 0, 1, 2.
local helpers = require('test.functional.helpers')
-local ffi = require('ffi')
local clear, execute, expect = helpers.clear, helpers.execute, helpers.expect
local source, write_file = helpers.source, helpers.write_file
+local os_name = helpers.os_name
local function sixlines(text)
local result = ''
@@ -15,7 +15,7 @@ end
local function diff(text, nodedent)
local tmpname = os.tmpname()
- if ffi.os == 'OSX' and string.match(tmpname, '^/tmp') then
+ if os_name() == 'osx' and string.match(tmpname, '^/tmp') then
tmpname = '/private'..tmpname
end
execute('w! '..tmpname)
@@ -30,7 +30,7 @@ local function diff(text, nodedent)
end
describe('character classes in regexp', function()
- local ctrl1 = '\t\x0c\r'
+ local ctrl1 = '\t\012\r'
local punct1 = " !\"#$%&'()#+'-./"
local digits = '0123456789'
local punct2 = ':;<=>?@'
@@ -38,8 +38,8 @@ describe('character classes in regexp', function()
local punct3 = '[\\]^_`'
local lower = 'abcdefghiwxyz'
local punct4 = '{|}~'
- local ctrl2 = '\x7f\x80\x82\x90\x9b'
- local iso_text = '\xa6\xb1\xbc\xc7\xd3\xe9' -- "¦±¼ÇÓé" in utf-8
+ local ctrl2 = '\127\128\130\144\155'
+ local iso_text = '\166\177\188\199\211\233' -- "¦±¼ÇÓé" in utf-8
setup(function()
-- The original test32.in file was not in utf-8 encoding and did also
-- contain some control characters. We use lua escape sequences to write
diff --git a/test/functional/legacy/039_visual_block_mode_commands_spec.lua b/test/functional/legacy/039_visual_block_mode_commands_spec.lua
index 6e1879035b..7195d7d11d 100644
--- a/test/functional/legacy/039_visual_block_mode_commands_spec.lua
+++ b/test/functional/legacy/039_visual_block_mode_commands_spec.lua
@@ -187,7 +187,7 @@ describe('Visual block mode', function()
98<Nul>65
98<Nul>65]]
expected = expected:gsub('<CR>', '\r')
- expected = expected:gsub('<Nul>', '\x00')
+ expected = expected:gsub('<Nul>', '\000')
expect(expected)
end)
diff --git a/test/functional/legacy/061_undo_tree_spec.lua b/test/functional/legacy/061_undo_tree_spec.lua
index ceb114b2a7..6db37bf1ff 100644
--- a/test/functional/legacy/061_undo_tree_spec.lua
+++ b/test/functional/legacy/061_undo_tree_spec.lua
@@ -191,7 +191,7 @@ describe('undo tree:', function()
end)
it('undo an expression-register', function()
- local normal_commands = 'o1\x1ba2\x12=string(123)\n\x1b'
+ local normal_commands = 'o1\027a2\018=string(123)\n\027'
write_file('Xtest.source', normal_commands)
feed('oa<esc>')
diff --git a/test/functional/legacy/083_tag_search_with_file_encoding_spec.lua b/test/functional/legacy/083_tag_search_with_file_encoding_spec.lua
index dc6df007e6..6b5ee60568 100644
--- a/test/functional/legacy/083_tag_search_with_file_encoding_spec.lua
+++ b/test/functional/legacy/083_tag_search_with_file_encoding_spec.lua
@@ -24,7 +24,7 @@ describe('tag search with !_TAG_FILE_ENCODING', function()
]])
write_file('test83-tags2',
'!_TAG_FILE_ENCODING cp932 //\n' ..
- '\x82`\x82a\x82b Xtags2.txt /\x82`\x82a\x82b\n'
+ '\130`\130a\130b Xtags2.txt /\130`\130a\130b\n'
)
-- The last file is very long but repetetive and can be generated on the
-- fly.
@@ -32,7 +32,7 @@ describe('tag search with !_TAG_FILE_ENCODING', function()
!_TAG_FILE_SORTED 1 //
!_TAG_FILE_ENCODING cp932 //
]])
- local line = ' Xtags3.txt /\x82`\x82a\x82b\n'
+ local line = ' Xtags3.txt /\130`\130a\130b\n'
for i = 1, 100 do
text = text .. 'abc' .. i .. line
end
diff --git a/test/functional/legacy/088_conceal_tabs_spec.lua b/test/functional/legacy/088_conceal_tabs_spec.lua
new file mode 100644
index 0000000000..c78f4e5c3e
--- /dev/null
+++ b/test/functional/legacy/088_conceal_tabs_spec.lua
@@ -0,0 +1,96 @@
+-- Tests for correct display (cursor column position) with +conceal and
+-- tabulators.
+
+local helpers = require('test.functional.helpers')
+local feed, insert, clear, execute =
+ helpers.feed, helpers.insert, helpers.clear, helpers.execute
+
+local expect_pos = function(row, col)
+ return helpers.eq({row, col}, helpers.eval('[screenrow(), screencol()]'))
+end
+
+describe('cursor and column position with conceal and tabulators', function()
+ setup(clear)
+
+ it('are working', function()
+ insert([[
+ start:
+ .concealed. text
+ |concealed| text
+
+ .concealed. text
+ |concealed| text
+
+ .a. .b. .c. .d.
+ |a| |b| |c| |d|]])
+
+ -- Conceal settings.
+ execute('set conceallevel=2')
+ execute('set concealcursor=nc')
+ execute('syntax match test /|/ conceal')
+ -- Start test.
+ execute('/^start:')
+ feed('ztj')
+ expect_pos(2, 1)
+ -- We should end up in the same column when running these commands on the
+ -- two lines.
+ feed('ft')
+ expect_pos(2, 17)
+ feed('$')
+ expect_pos(2, 20)
+ feed('0j')
+ expect_pos(3, 1)
+ feed('ft')
+ expect_pos(3, 17)
+ feed('$')
+ expect_pos(3, 20)
+ feed('j0j')
+ expect_pos(5, 8)
+ -- Same for next test block.
+ feed('ft')
+ expect_pos(5, 25)
+ feed('$')
+ expect_pos(5, 28)
+ feed('0j')
+ expect_pos(6, 8)
+ feed('ft')
+ expect_pos(6, 25)
+ feed('$')
+ expect_pos(6, 28)
+ feed('0j0j')
+ expect_pos(8, 1)
+ -- And check W with multiple tabs and conceals in a line.
+ feed('W')
+ expect_pos(8, 9)
+ feed('W')
+ expect_pos(8, 17)
+ feed('W')
+ expect_pos(8, 25)
+ feed('$')
+ expect_pos(8, 27)
+ feed('0j')
+ expect_pos(9, 1)
+ feed('W')
+ expect_pos(9, 9)
+ feed('W')
+ expect_pos(9, 17)
+ feed('W')
+ expect_pos(9, 25)
+ feed('$')
+ expect_pos(9, 26)
+ execute('set lbr')
+ feed('$')
+ expect_pos(9, 26)
+ execute('set list listchars=tab:>-')
+ feed('0')
+ expect_pos(9, 1)
+ feed('W')
+ expect_pos(9, 9)
+ feed('W')
+ expect_pos(9, 17)
+ feed('W')
+ expect_pos(9, 25)
+ feed('$')
+ expect_pos(9, 26)
+ end)
+end)
diff --git a/test/functional/legacy/100_lispwords_spec.lua b/test/functional/legacy/100_lispwords_spec.lua
deleted file mode 100644
index 739a02f0b3..0000000000
--- a/test/functional/legacy/100_lispwords_spec.lua
+++ /dev/null
@@ -1,47 +0,0 @@
--- Tests for 'lispwords' setting being global-local
-
-local helpers = require('test.functional.helpers')
-local source = helpers.source
-local clear, expect = helpers.clear, helpers.expect
-
-describe('lispwords', function()
- setup(clear)
-
- it('global-local', function()
- source([[
- setglobal lispwords=foo,bar,baz
- setlocal lispwords-=foo
- setlocal lispwords+=quux
- redir @A
- echo "Testing 'lispwords' local value"
- setglobal lispwords?
- setlocal lispwords?
- echo &lispwords
- echo ''
- redir end
- setlocal lispwords<
- redir @A
- echo "Testing 'lispwords' value reset"
- setglobal lispwords?
- setlocal lispwords?
- echo &lispwords
- redir end
-
- 0put a
- $d
- ]])
-
- -- Assert buffer contents.
- expect([[
-
- Testing 'lispwords' local value
- lispwords=foo,bar,baz
- lispwords=bar,baz,quux
- bar,baz,quux
-
- Testing 'lispwords' value reset
- lispwords=foo,bar,baz
- lispwords=foo,bar,baz
- foo,bar,baz]])
- end)
-end)
diff --git a/test/functional/legacy/105_filename_modifiers_spec.lua b/test/functional/legacy/105_filename_modifiers_spec.lua
deleted file mode 100644
index 3413667022..0000000000
--- a/test/functional/legacy/105_filename_modifiers_spec.lua
+++ /dev/null
@@ -1,81 +0,0 @@
--- Test filename modifiers.
-
-local helpers = require('test.functional.helpers')
-local clear = helpers.clear
-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/legacy/eval_spec.lua b/test/functional/legacy/eval_spec.lua
index 9304e3b331..d1ed96cc2e 100644
--- a/test/functional/legacy/eval_spec.lua
+++ b/test/functional/legacy/eval_spec.lua
@@ -54,8 +54,8 @@ describe('eval', function()
expect([[
": type v; value: abc (['abc']), expr: abc (['abc'])
- ": type V; value: abc]].."\x00 (['abc']), expr: abc\x00"..[[ (['abc'])
- ": type V; value: abc]].."\r\x00 (['abc\r']), expr: abc\r\x00 (['abc\r"..[['])
+ ": type V; value: abc]].."\000 (['abc']), expr: abc\000"..[[ (['abc'])
+ ": type V; value: abc]].."\r\000 (['abc\r']), expr: abc\r\000 (['abc\r"..[['])
=: type v; value: abc (['abc']), expr: "abc" (['"abc"'])]])
end)
@@ -97,29 +97,29 @@ describe('eval', function()
==
=abcB=
{{{2 setreg('c', 'abcC', 'l')
- c: type V; value: abcC]].."\x00 (['abcC']), expr: abcC\x00"..[[ (['abcC'])
+ c: type V; value: abcC]].."\000 (['abcC']), expr: abcC\000"..[[ (['abcC'])
==
abcC
==
{{{2 setreg('d', 'abcD', 'V')
- d: type V; value: abcD]].."\x00 (['abcD']), expr: abcD\x00"..[[ (['abcD'])
+ d: type V; value: abcD]].."\000 (['abcD']), expr: abcD\000"..[[ (['abcD'])
==
abcD
==
{{{2 setreg('e', 'abcE', 'b')
- e: type ]]..'\x16'..[[4; value: abcE (['abcE']), expr: abcE (['abcE'])
+ e: type ]]..'\022'..[[4; value: abcE (['abcE']), expr: abcE (['abcE'])
==
=abcE=
- {{{2 setreg('f', 'abcF', ']]..'\x16'..[[')
- f: type ]]..'\x16'..[[4; value: abcF (['abcF']), expr: abcF (['abcF'])
+ {{{2 setreg('f', 'abcF', ']]..'\022'..[[')
+ f: type ]]..'\022'..[[4; value: abcF (['abcF']), expr: abcF (['abcF'])
==
=abcF=
{{{2 setreg('g', 'abcG', 'b10')
- g: type ]]..'\x16'..[[10; value: abcG (['abcG']), expr: abcG (['abcG'])
+ g: type ]]..'\022'..[[10; value: abcG (['abcG']), expr: abcG (['abcG'])
==
=abcG =
- {{{2 setreg('h', 'abcH', ']]..'\x16'..[[10')
- h: type ]]..'\x16'..[[10; value: abcH (['abcH']), expr: abcH (['abcH'])
+ {{{2 setreg('h', 'abcH', ']]..'\022'..[[10')
+ h: type ]]..'\022'..[[10; value: abcH (['abcH']), expr: abcH (['abcH'])
==
=abcH =
{{{2 setreg('I', 'abcI')
@@ -132,12 +132,12 @@ describe('eval', function()
==
=abcAabcAc=
{{{2 setreg('A', 'abcAl', 'l')
- A: type V; value: abcAabcAcabcAl]].."\x00 (['abcAabcAcabcAl']), expr: abcAabcAcabcAl\x00"..[[ (['abcAabcAcabcAl'])
+ A: type V; value: abcAabcAcabcAl]].."\000 (['abcAabcAcabcAl']), expr: abcAabcAcabcAl\000"..[[ (['abcAabcAcabcAl'])
==
abcAabcAcabcAl
==
{{{2 setreg('A', 'abcAc2', 'c')
- A: type v; value: abcAabcAcabcAl]].."\x00abcAc2 (['abcAabcAcabcAl', 'abcAc2']), expr: abcAabcAcabcAl\x00"..[[abcAc2 (['abcAabcAcabcAl', 'abcAc2'])
+ A: type v; value: abcAabcAcabcAl]].."\000abcAc2 (['abcAabcAcabcAl', 'abcAc2']), expr: abcAabcAcabcAl\000"..[[abcAc2 (['abcAabcAcabcAl', 'abcAc2'])
==
=abcAabcAcabcAl
abcAc2=
@@ -146,50 +146,50 @@ describe('eval', function()
==
=abcBabcBc=
{{{2 setreg('b', 'abcBb', 'ba')
- b: type ]]..'\x16'..[[5; value: abcBabcBcabcBb (['abcBabcBcabcBb']), expr: abcBabcBcabcBb (['abcBabcBcabcBb'])
+ b: type ]]..'\022'..[[5; value: abcBabcBcabcBb (['abcBabcBcabcBb']), expr: abcBabcBcabcBb (['abcBabcBcabcBb'])
==
=abcBabcBcabcBb=
{{{2 setreg('b', 'abcBc2', 'ca')
- b: type v; value: abcBabcBcabcBb]].."\x00abcBc2 (['abcBabcBcabcBb', 'abcBc2']), expr: abcBabcBcabcBb\x00"..[[abcBc2 (['abcBabcBcabcBb', 'abcBc2'])
+ b: type v; value: abcBabcBcabcBb]].."\000abcBc2 (['abcBabcBcabcBb', 'abcBc2']), expr: abcBabcBcabcBb\000"..[[abcBc2 (['abcBabcBcabcBb', 'abcBc2'])
==
=abcBabcBcabcBb
abcBc2=
{{{2 setreg('b', 'abcBb2', 'b50a')
- b: type ]].."\x1650; value: abcBabcBcabcBb\x00abcBc2abcBb2 (['abcBabcBcabcBb', 'abcBc2abcBb2']), expr: abcBabcBcabcBb\x00"..[[abcBc2abcBb2 (['abcBabcBcabcBb', 'abcBc2abcBb2'])
+ b: type ]].."\02250; value: abcBabcBcabcBb\000abcBc2abcBb2 (['abcBabcBcabcBb', 'abcBc2abcBb2']), expr: abcBabcBcabcBb\000"..[[abcBc2abcBb2 (['abcBabcBcabcBb', 'abcBc2abcBb2'])
==
=abcBabcBcabcBb =
abcBc2abcBb2
{{{2 setreg('C', 'abcCl', 'l')
- C: type V; value: abcC]].."\x00abcCl\x00 (['abcC', 'abcCl']), expr: abcC\x00abcCl\x00"..[[ (['abcC', 'abcCl'])
+ C: type V; value: abcC]].."\000abcCl\000 (['abcC', 'abcCl']), expr: abcC\000abcCl\000"..[[ (['abcC', 'abcCl'])
==
abcC
abcCl
==
{{{2 setreg('C', 'abcCc', 'c')
- C: type v; value: abcC]].."\x00abcCl\x00abcCc (['abcC', 'abcCl', 'abcCc']), expr: abcC\x00abcCl\x00"..[[abcCc (['abcC', 'abcCl', 'abcCc'])
+ C: type v; value: abcC]].."\000abcCl\000abcCc (['abcC', 'abcCl', 'abcCc']), expr: abcC\000abcCl\000"..[[abcCc (['abcC', 'abcCl', 'abcCc'])
==
=abcC
abcCl
abcCc=
{{{2 setreg('D', 'abcDb', 'b')
- D: type ]].."\x165; value: abcD\x00abcDb (['abcD', 'abcDb']), expr: abcD\x00"..[[abcDb (['abcD', 'abcDb'])
+ D: type ]].."\0225; value: abcD\000abcDb (['abcD', 'abcDb']), expr: abcD\000"..[[abcDb (['abcD', 'abcDb'])
==
=abcD =
abcDb
{{{2 setreg('E', 'abcEb', 'b')
- E: type ]].."\x165; value: abcE\x00abcEb (['abcE', 'abcEb']), expr: abcE\x00"..[[abcEb (['abcE', 'abcEb'])
+ E: type ]].."\0225; value: abcE\000abcEb (['abcE', 'abcEb']), expr: abcE\000"..[[abcEb (['abcE', 'abcEb'])
==
=abcE =
abcEb
{{{2 setreg('E', 'abcEl', 'l')
- E: type V; value: abcE]].."\x00abcEb\x00abcEl\x00 (['abcE', 'abcEb', 'abcEl']), expr: abcE\x00abcEb\x00abcEl\x00"..[[ (['abcE', 'abcEb', 'abcEl'])
+ E: type V; value: abcE]].."\000abcEb\000abcEl\000 (['abcE', 'abcEb', 'abcEl']), expr: abcE\000abcEb\000abcEl\000"..[[ (['abcE', 'abcEb', 'abcEl'])
==
abcE
abcEb
abcEl
==
{{{2 setreg('F', 'abcFc', 'c')
- F: type v; value: abcF]].."\x00abcFc (['abcF', 'abcFc']), expr: abcF\x00"..[[abcFc (['abcF', 'abcFc'])
+ F: type v; value: abcF]].."\000abcFc (['abcF', 'abcFc']), expr: abcF\000"..[[abcFc (['abcF', 'abcFc'])
==
=abcF
abcFc=]])
@@ -219,36 +219,36 @@ describe('eval', function()
execute([[call SetReg('F', "\n", 'b')]])
expect([[
- {{{2 setreg('A', ']]..'\x00'..[[')
- A: type V; value: abcA2]].."\x00 (['abcA2']), expr: abcA2\x00"..[[ (['abcA2'])
+ {{{2 setreg('A', ']]..'\000'..[[')
+ A: type V; value: abcA2]].."\000 (['abcA2']), expr: abcA2\000"..[[ (['abcA2'])
==
abcA2
==
- {{{2 setreg('B', ']]..'\x00'..[[', 'c')
- B: type v; value: abcB2]].."\x00 (['abcB2', '']), expr: abcB2\x00"..[[ (['abcB2', ''])
+ {{{2 setreg('B', ']]..'\000'..[[', 'c')
+ B: type v; value: abcB2]].."\000 (['abcB2', '']), expr: abcB2\000"..[[ (['abcB2', ''])
==
=abcB2
=
- {{{2 setreg('C', ']]..'\x00'..[[')
- C: type V; value: abcC2]].."\x00\x00 (['abcC2', '']), expr: abcC2\x00\x00"..[[ (['abcC2', ''])
+ {{{2 setreg('C', ']]..'\000'..[[')
+ C: type V; value: abcC2]].."\000\000 (['abcC2', '']), expr: abcC2\000\000"..[[ (['abcC2', ''])
==
abcC2
==
- {{{2 setreg('D', ']]..'\x00'..[[', 'l')
- D: type V; value: abcD2]].."\x00\x00 (['abcD2', '']), expr: abcD2\x00\x00"..[[ (['abcD2', ''])
+ {{{2 setreg('D', ']]..'\000'..[[', 'l')
+ D: type V; value: abcD2]].."\000\000 (['abcD2', '']), expr: abcD2\000\000"..[[ (['abcD2', ''])
==
abcD2
==
- {{{2 setreg('E', ']]..'\x00'..[[')
- E: type V; value: abcE2]].."\x00\x00 (['abcE2', '']), expr: abcE2\x00\x00"..[[ (['abcE2', ''])
+ {{{2 setreg('E', ']]..'\000'..[[')
+ E: type V; value: abcE2]].."\000\000 (['abcE2', '']), expr: abcE2\000\000"..[[ (['abcE2', ''])
==
abcE2
==
- {{{2 setreg('F', ']]..'\x00'..[[', 'b')
- F: type ]].."\x160; value: abcF2\x00 (['abcF2', '']), expr: abcF2\x00"..[[ (['abcF2', ''])
+ {{{2 setreg('F', ']]..'\000'..[[', 'b')
+ F: type ]].."\0220; value: abcF2\000 (['abcF2', '']), expr: abcF2\000"..[[ (['abcF2', ''])
==
=abcF2=
]])
@@ -282,21 +282,21 @@ describe('eval', function()
==
=abcA3=
{{{2 setreg('b', ['abcB3'], 'l')
- b: type V; value: abcB3]].."\x00 (['abcB3']), expr: abcB3\x00"..[[ (['abcB3'])
+ b: type V; value: abcB3]].."\000 (['abcB3']), expr: abcB3\000"..[[ (['abcB3'])
==
abcB3
==
{{{2 setreg('c', ['abcC3'], 'b')
- c: type ]]..'\x16'..[[5; value: abcC3 (['abcC3']), expr: abcC3 (['abcC3'])
+ c: type ]]..'\022'..[[5; value: abcC3 (['abcC3']), expr: abcC3 (['abcC3'])
==
=abcC3=
{{{2 setreg('d', ['abcD3'])
- d: type V; value: abcD3]].."\x00 (['abcD3']), expr: abcD3\x00"..[[ (['abcD3'])
+ d: type V; value: abcD3]].."\000 (['abcD3']), expr: abcD3\000"..[[ (['abcD3'])
==
abcD3
==
{{{2 setreg('e', [1, 2, 'abc', 3])
- e: type V; value: 1]].."\x002\x00abc\x003\x00 (['1', '2', 'abc', '3']), expr: 1\x002\x00abc\x003\x00"..[[ (['1', '2', 'abc', '3'])
+ e: type V; value: 1]].."\0002\000abc\0003\000 (['1', '2', 'abc', '3']), expr: 1\0002\000abc\0003\000"..[[ (['1', '2', 'abc', '3'])
==
1
2
@@ -304,7 +304,7 @@ describe('eval', function()
3
==
{{{2 setreg('f', [1, 2, 3])
- f: type V; value: 1]].."\x002\x003\x00 (['1', '2', '3']), expr: 1\x002\x003\x00"..[[ (['1', '2', '3'])
+ f: type V; value: 1]].."\0002\0003\000 (['1', '2', '3']), expr: 1\0002\0003\000"..[[ (['1', '2', '3'])
==
1
2
@@ -312,49 +312,49 @@ describe('eval', function()
==
{{{1 Appending lists with setreg()
{{{2 setreg('A', ['abcA3c'], 'c')
- A: type v; value: abcA3]].."\x00abcA3c (['abcA3', 'abcA3c']), expr: abcA3\x00"..[[abcA3c (['abcA3', 'abcA3c'])
+ A: type v; value: abcA3]].."\000abcA3c (['abcA3', 'abcA3c']), expr: abcA3\000"..[[abcA3c (['abcA3', 'abcA3c'])
==
=abcA3
abcA3c=
{{{2 setreg('b', ['abcB3l'], 'la')
- b: type V; value: abcB3]].."\x00abcB3l\x00 (['abcB3', 'abcB3l']), expr: abcB3\x00abcB3l\x00"..[[ (['abcB3', 'abcB3l'])
+ b: type V; value: abcB3]].."\000abcB3l\000 (['abcB3', 'abcB3l']), expr: abcB3\000abcB3l\000"..[[ (['abcB3', 'abcB3l'])
==
abcB3
abcB3l
==
{{{2 setreg('C', ['abcC3b'], 'lb')
- C: type ]].."\x166; value: abcC3\x00abcC3b (['abcC3', 'abcC3b']), expr: abcC3\x00"..[[abcC3b (['abcC3', 'abcC3b'])
+ C: type ]].."\0226; value: abcC3\000abcC3b (['abcC3', 'abcC3b']), expr: abcC3\000"..[[abcC3b (['abcC3', 'abcC3b'])
==
=abcC3 =
abcC3b
{{{2 setreg('D', ['abcD32'])
- D: type V; value: abcD3]].."\x00abcD32\x00 (['abcD3', 'abcD32']), expr: abcD3\x00abcD32\x00"..[[ (['abcD3', 'abcD32'])
+ D: type V; value: abcD3]].."\000abcD32\000 (['abcD3', 'abcD32']), expr: abcD3\000abcD32\000"..[[ (['abcD3', 'abcD32'])
==
abcD3
abcD32
==
{{{2 setreg('A', ['abcA32'])
- A: type V; value: abcA3]].."\x00abcA3c\x00abcA32\x00 (['abcA3', 'abcA3c', 'abcA32']), expr: abcA3\x00abcA3c\x00abcA32\x00"..[[ (['abcA3', 'abcA3c', 'abcA32'])
+ A: type V; value: abcA3]].."\000abcA3c\000abcA32\000 (['abcA3', 'abcA3c', 'abcA32']), expr: abcA3\000abcA3c\000abcA32\000"..[[ (['abcA3', 'abcA3c', 'abcA32'])
==
abcA3
abcA3c
abcA32
==
{{{2 setreg('B', ['abcB3c'], 'c')
- B: type v; value: abcB3]].."\x00abcB3l\x00abcB3c (['abcB3', 'abcB3l', 'abcB3c']), expr: abcB3\x00abcB3l\x00"..[[abcB3c (['abcB3', 'abcB3l', 'abcB3c'])
+ B: type v; value: abcB3]].."\000abcB3l\000abcB3c (['abcB3', 'abcB3l', 'abcB3c']), expr: abcB3\000abcB3l\000"..[[abcB3c (['abcB3', 'abcB3l', 'abcB3c'])
==
=abcB3
abcB3l
abcB3c=
{{{2 setreg('C', ['abcC3l'], 'l')
- C: type V; value: abcC3]].."\x00abcC3b\x00abcC3l\x00 (['abcC3', 'abcC3b', 'abcC3l']), expr: abcC3\x00abcC3b\x00abcC3l\x00"..[[ (['abcC3', 'abcC3b', 'abcC3l'])
+ C: type V; value: abcC3]].."\000abcC3b\000abcC3l\000 (['abcC3', 'abcC3b', 'abcC3l']), expr: abcC3\000abcC3b\000abcC3l\000"..[[ (['abcC3', 'abcC3b', 'abcC3l'])
==
abcC3
abcC3b
abcC3l
==
{{{2 setreg('D', ['abcD3b'], 'b')
- D: type ]].."\x166; value: abcD3\x00abcD32\x00abcD3b (['abcD3', 'abcD32', 'abcD3b']), expr: abcD3\x00abcD32\x00"..[[abcD3b (['abcD3', 'abcD32', 'abcD3b'])
+ D: type ]].."\0226; value: abcD3\000abcD32\000abcD3b (['abcD3', 'abcD32', 'abcD3b']), expr: abcD3\000abcD32\000"..[[abcD3b (['abcD3', 'abcD32', 'abcD3b'])
==
=abcD3 =
abcD32
@@ -370,50 +370,50 @@ describe('eval', function()
expect(
'\n'..
'{{{1 Appending lists with NL with setreg()\n'..
- "{{{2 setreg('A', ['\x00', 'abcA3l2'], 'l')\n"..
- "A: type V; value: abcA3\x00abcA3c\x00abcA32\x00\x00\x00abcA3l2\x00 (['abcA3', 'abcA3c', 'abcA32', '\x00', 'abcA3l2']), expr: abcA3\x00abcA3c\x00abcA32\x00\x00\x00abcA3l2\x00 (['abcA3', 'abcA3c', 'abcA32', '\x00', 'abcA3l2'])\n"..
+ "{{{2 setreg('A', ['\000', 'abcA3l2'], 'l')\n"..
+ "A: type V; value: abcA3\000abcA3c\000abcA32\000\000\000abcA3l2\000 (['abcA3', 'abcA3c', 'abcA32', '\000', 'abcA3l2']), expr: abcA3\000abcA3c\000abcA32\000\000\000abcA3l2\000 (['abcA3', 'abcA3c', 'abcA32', '\000', 'abcA3l2'])\n"..
'==\n'..
'abcA3\n'..
'abcA3c\n'..
'abcA32\n'..
- '\x00\n'..
+ '\000\n'..
'abcA3l2\n'..
'==')
execute('%delete')
execute([=[call SetReg('B', ["\n", 'abcB3c2'], 'c')]=])
expect(
'\n'..
- "{{{2 setreg('B', ['\x00', 'abcB3c2'], 'c')\n"..
- "B: type v; value: abcB3\x00abcB3l\x00abcB3c\x00\x00\x00abcB3c2 (['abcB3', 'abcB3l', 'abcB3c', '\x00', 'abcB3c2']), expr: abcB3\x00abcB3l\x00abcB3c\x00\x00\x00abcB3c2 (['abcB3', 'abcB3l', 'abcB3c', '\x00', 'abcB3c2'])\n"..
+ "{{{2 setreg('B', ['\000', 'abcB3c2'], 'c')\n"..
+ "B: type v; value: abcB3\000abcB3l\000abcB3c\000\000\000abcB3c2 (['abcB3', 'abcB3l', 'abcB3c', '\000', 'abcB3c2']), expr: abcB3\000abcB3l\000abcB3c\000\000\000abcB3c2 (['abcB3', 'abcB3l', 'abcB3c', '\000', 'abcB3c2'])\n"..
'==\n'..
'=abcB3\n'..
'abcB3l\n'..
'abcB3c\n'..
- '\x00\n'..
+ '\000\n'..
'abcB3c2=')
execute('%delete')
execute([=[call SetReg('C', ["\n", 'abcC3b2'], 'b')]=])
expect(
'\n'..
- "{{{2 setreg('C', ['\x00', 'abcC3b2'], 'b')\n"..
- "C: type \x167; value: abcC3\x00abcC3b\x00abcC3l\x00\x00\x00abcC3b2 (['abcC3', 'abcC3b', 'abcC3l', '\x00', 'abcC3b2']), expr: abcC3\x00abcC3b\x00abcC3l\x00\x00\x00abcC3b2 (['abcC3', 'abcC3b', 'abcC3l', '\x00', 'abcC3b2'])\n"..
+ "{{{2 setreg('C', ['\000', 'abcC3b2'], 'b')\n"..
+ "C: type \0227; value: abcC3\000abcC3b\000abcC3l\000\000\000abcC3b2 (['abcC3', 'abcC3b', 'abcC3l', '\000', 'abcC3b2']), expr: abcC3\000abcC3b\000abcC3l\000\000\000abcC3b2 (['abcC3', 'abcC3b', 'abcC3l', '\000', 'abcC3b2'])\n"..
'==\n'..
'=abcC3 =\n'..
' abcC3b\n'..
' abcC3l\n'..
- ' \x00\n'..
+ ' \000\n'..
' abcC3b2')
execute('%delete')
execute([=[call SetReg('D', ["\n", 'abcD3b50'],'b50')]=])
expect(
'\n'..
- "{{{2 setreg('D', ['\x00', 'abcD3b50'], 'b50')\n"..
- "D: type \x1650; value: abcD3\x00abcD32\x00abcD3b\x00\x00\x00abcD3b50 (['abcD3', 'abcD32', 'abcD3b', '\x00', 'abcD3b50']), expr: abcD3\x00abcD32\x00abcD3b\x00\x00\x00abcD3b50 (['abcD3', 'abcD32', 'abcD3b', '\x00', 'abcD3b50'])\n"..
+ "{{{2 setreg('D', ['\000', 'abcD3b50'], 'b50')\n"..
+ "D: type \02250; value: abcD3\000abcD32\000abcD3b\000\000\000abcD3b50 (['abcD3', 'abcD32', 'abcD3b', '\000', 'abcD3b50']), expr: abcD3\000abcD32\000abcD3b\000\000\000abcD3b50 (['abcD3', 'abcD32', 'abcD3b', '\000', 'abcD3b50'])\n"..
'==\n'..
'=abcD3 =\n'..
' abcD32\n'..
' abcD3b\n'..
- ' \x00\n'..
+ ' \000\n'..
' abcD3b50')
end)
@@ -425,14 +425,14 @@ describe('eval', function()
execute([=[call SetReg('a', ['abcA4-0', "\n", "abcA4-2\n", "\nabcA4-3", "abcA4-4\nabcA4-4-2"])]=])
expect(
'\n'..
- "{{{2 setreg('a', ['abcA4-0', '\x00', 'abcA4-2\x00', '\x00abcA4-3', 'abcA4-4\x00abcA4-4-2'])\n"..
- "a: type V; value: abcA4-0\x00\x00\x00abcA4-2\x00\x00\x00abcA4-3\x00abcA4-4\x00abcA4-4-2\x00 (['abcA4-0', '\x00', 'abcA4-2\x00', '\x00abcA4-3', 'abcA4-4\x00abcA4-4-2']), expr: abcA4-0\x00\x00\x00abcA4-2\x00\x00\x00abcA4-3\x00abcA4-4\x00abcA4-4-2\x00 (['abcA4-0', '\x00', 'abcA4-2\x00', '\x00abcA4-3', 'abcA4-4\x00abcA4-4-2'])\n"..
+ "{{{2 setreg('a', ['abcA4-0', '\000', 'abcA4-2\000', '\000abcA4-3', 'abcA4-4\000abcA4-4-2'])\n"..
+ "a: type V; value: abcA4-0\000\000\000abcA4-2\000\000\000abcA4-3\000abcA4-4\000abcA4-4-2\000 (['abcA4-0', '\000', 'abcA4-2\000', '\000abcA4-3', 'abcA4-4\000abcA4-4-2']), expr: abcA4-0\000\000\000abcA4-2\000\000\000abcA4-3\000abcA4-4\000abcA4-4-2\000 (['abcA4-0', '\000', 'abcA4-2\000', '\000abcA4-3', 'abcA4-4\000abcA4-4-2'])\n"..
'==\n'..
'abcA4-0\n'..
- '\x00\n'..
- 'abcA4-2\x00\n'..
- '\x00abcA4-3\n'..
- 'abcA4-4\x00abcA4-4-2\n'..
+ '\000\n'..
+ 'abcA4-2\000\n'..
+ '\000abcA4-3\n'..
+ 'abcA4-4\000abcA4-4-2\n'..
'==')
end)
@@ -441,14 +441,14 @@ describe('eval', function()
execute([=[call SetReg('b', ['abcB4c-0', "\n", "abcB4c-2\n", "\nabcB4c-3", "abcB4c-4\nabcB4c-4-2"], 'c')]=])
expect(
'\n'..
- "{{{2 setreg('b', ['abcB4c-0', '\x00', 'abcB4c-2\x00', '\x00abcB4c-3', 'abcB4c-4\x00abcB4c-4-2'], 'c')\n"..
- "b: type v; value: abcB4c-0\x00\x00\x00abcB4c-2\x00\x00\x00abcB4c-3\x00abcB4c-4\x00abcB4c-4-2 (['abcB4c-0', '\x00', 'abcB4c-2\x00', '\x00abcB4c-3', 'abcB4c-4\x00abcB4c-4-2']), expr: abcB4c-0\x00\x00\x00abcB4c-2\x00\x00\x00abcB4c-3\x00abcB4c-4\x00abcB4c-4-2 (['abcB4c-0', '\x00', 'abcB4c-2\x00', '\x00abcB4c-3', 'abcB4c-4\x00abcB4c-4-2'])\n"..
+ "{{{2 setreg('b', ['abcB4c-0', '\000', 'abcB4c-2\000', '\000abcB4c-3', 'abcB4c-4\000abcB4c-4-2'], 'c')\n"..
+ "b: type v; value: abcB4c-0\000\000\000abcB4c-2\000\000\000abcB4c-3\000abcB4c-4\000abcB4c-4-2 (['abcB4c-0', '\000', 'abcB4c-2\000', '\000abcB4c-3', 'abcB4c-4\000abcB4c-4-2']), expr: abcB4c-0\000\000\000abcB4c-2\000\000\000abcB4c-3\000abcB4c-4\000abcB4c-4-2 (['abcB4c-0', '\000', 'abcB4c-2\000', '\000abcB4c-3', 'abcB4c-4\000abcB4c-4-2'])\n"..
'==\n'..
'=abcB4c-0\n'..
- '\x00\n'..
- 'abcB4c-2\x00\n'..
- '\x00abcB4c-3\n'..
- 'abcB4c-4\x00abcB4c-4-2=')
+ '\000\n'..
+ 'abcB4c-2\000\n'..
+ '\000abcB4c-3\n'..
+ 'abcB4c-4\000abcB4c-4-2=')
end)
it('setting lists with NLs with setreg(), part 3', function()
@@ -456,14 +456,14 @@ describe('eval', function()
execute([=[call SetReg('c', ['abcC4l-0', "\n", "abcC4l-2\n", "\nabcC4l-3", "abcC4l-4\nabcC4l-4-2"], 'l')]=])
expect(
'\n'..
- "{{{2 setreg('c', ['abcC4l-0', '\x00', 'abcC4l-2\x00', '\x00abcC4l-3', 'abcC4l-4\x00abcC4l-4-2'], 'l')\n"..
- "c: type V; value: abcC4l-0\x00\x00\x00abcC4l-2\x00\x00\x00abcC4l-3\x00abcC4l-4\x00abcC4l-4-2\x00 (['abcC4l-0', '\x00', 'abcC4l-2\x00', '\x00abcC4l-3', 'abcC4l-4\x00abcC4l-4-2']), expr: abcC4l-0\x00\x00\x00abcC4l-2\x00\x00\x00abcC4l-3\x00abcC4l-4\x00abcC4l-4-2\x00 (['abcC4l-0', '\x00', 'abcC4l-2\x00', '\x00abcC4l-3', 'abcC4l-4\x00abcC4l-4-2'])\n"..
+ "{{{2 setreg('c', ['abcC4l-0', '\000', 'abcC4l-2\000', '\000abcC4l-3', 'abcC4l-4\000abcC4l-4-2'], 'l')\n"..
+ "c: type V; value: abcC4l-0\000\000\000abcC4l-2\000\000\000abcC4l-3\000abcC4l-4\000abcC4l-4-2\000 (['abcC4l-0', '\000', 'abcC4l-2\000', '\000abcC4l-3', 'abcC4l-4\000abcC4l-4-2']), expr: abcC4l-0\000\000\000abcC4l-2\000\000\000abcC4l-3\000abcC4l-4\000abcC4l-4-2\000 (['abcC4l-0', '\000', 'abcC4l-2\000', '\000abcC4l-3', 'abcC4l-4\000abcC4l-4-2'])\n"..
'==\n'..
'abcC4l-0\n'..
- '\x00\n'..
- 'abcC4l-2\x00\n'..
- '\x00abcC4l-3\n'..
- 'abcC4l-4\x00abcC4l-4-2\n'..
+ '\000\n'..
+ 'abcC4l-2\000\n'..
+ '\000abcC4l-3\n'..
+ 'abcC4l-4\000abcC4l-4-2\n'..
'==')
end)
it('setting lists with NLs with setreg(), part 4', function()
@@ -471,28 +471,28 @@ describe('eval', function()
execute([=[call SetReg('d', ['abcD4b-0', "\n", "abcD4b-2\n", "\nabcD4b-3", "abcD4b-4\nabcD4b-4-2"], 'b')]=])
expect(
'\n'..
- "{{{2 setreg('d', ['abcD4b-0', '\x00', 'abcD4b-2\x00', '\x00abcD4b-3', 'abcD4b-4\x00abcD4b-4-2'], 'b')\n"..
- "d: type \x1619; value: abcD4b-0\x00\x00\x00abcD4b-2\x00\x00\x00abcD4b-3\x00abcD4b-4\x00abcD4b-4-2 (['abcD4b-0', '\x00', 'abcD4b-2\x00', '\x00abcD4b-3', 'abcD4b-4\x00abcD4b-4-2']), expr: abcD4b-0\x00\x00\x00abcD4b-2\x00\x00\x00abcD4b-3\x00abcD4b-4\x00abcD4b-4-2 (['abcD4b-0', '\x00', 'abcD4b-2\x00', '\x00abcD4b-3', 'abcD4b-4\x00abcD4b-4-2'])\n"..
+ "{{{2 setreg('d', ['abcD4b-0', '\000', 'abcD4b-2\000', '\000abcD4b-3', 'abcD4b-4\000abcD4b-4-2'], 'b')\n"..
+ "d: type \02219; value: abcD4b-0\000\000\000abcD4b-2\000\000\000abcD4b-3\000abcD4b-4\000abcD4b-4-2 (['abcD4b-0', '\000', 'abcD4b-2\000', '\000abcD4b-3', 'abcD4b-4\000abcD4b-4-2']), expr: abcD4b-0\000\000\000abcD4b-2\000\000\000abcD4b-3\000abcD4b-4\000abcD4b-4-2 (['abcD4b-0', '\000', 'abcD4b-2\000', '\000abcD4b-3', 'abcD4b-4\000abcD4b-4-2'])\n"..
'==\n'..
'=abcD4b-0 =\n'..
- ' \x00\n'..
- ' abcD4b-2\x00\n'..
- ' \x00abcD4b-3\n'..
- ' abcD4b-4\x00abcD4b-4-2')
+ ' \000\n'..
+ ' abcD4b-2\000\n'..
+ ' \000abcD4b-3\n'..
+ ' abcD4b-4\000abcD4b-4-2')
end)
it('setting lists with NLs with setreg(), part 5', function()
execute('so test_eval_setup.vim')
execute([=[call SetReg('e', ['abcE4b10-0', "\n", "abcE4b10-2\n", "\nabcE4b10-3", "abcE4b10-4\nabcE4b10-4-2"], 'b10')]=])
expect(
'\n'..
- "{{{2 setreg('e', ['abcE4b10-0', '\x00', 'abcE4b10-2\x00', '\x00abcE4b10-3', 'abcE4b10-4\x00abcE4b10-4-2'], 'b10')\n"..
- "e: type \x1610; value: abcE4b10-0\x00\x00\x00abcE4b10-2\x00\x00\x00abcE4b10-3\x00abcE4b10-4\x00abcE4b10-4-2 (['abcE4b10-0', '\x00', 'abcE4b10-2\x00', '\x00abcE4b10-3', 'abcE4b10-4\x00abcE4b10-4-2']), expr: abcE4b10-0\x00\x00\x00abcE4b10-2\x00\x00\x00abcE4b10-3\x00abcE4b10-4\x00abcE4b10-4-2 (['abcE4b10-0', '\x00', 'abcE4b10-2\x00', '\x00abcE4b10-3', 'abcE4b10-4\x00abcE4b10-4-2'])\n"..
+ "{{{2 setreg('e', ['abcE4b10-0', '\000', 'abcE4b10-2\000', '\000abcE4b10-3', 'abcE4b10-4\000abcE4b10-4-2'], 'b10')\n"..
+ "e: type \02210; value: abcE4b10-0\000\000\000abcE4b10-2\000\000\000abcE4b10-3\000abcE4b10-4\000abcE4b10-4-2 (['abcE4b10-0', '\000', 'abcE4b10-2\000', '\000abcE4b10-3', 'abcE4b10-4\000abcE4b10-4-2']), expr: abcE4b10-0\000\000\000abcE4b10-2\000\000\000abcE4b10-3\000abcE4b10-4\000abcE4b10-4-2 (['abcE4b10-0', '\000', 'abcE4b10-2\000', '\000abcE4b10-3', 'abcE4b10-4\000abcE4b10-4-2'])\n"..
'==\n'..
'=abcE4b10-0=\n'..
- ' \x00\n'..
- ' abcE4b10-2\x00\n'..
- ' \x00abcE4b10-3\n'..
- ' abcE4b10-4\x00abcE4b10-4-2')
+ ' \000\n'..
+ ' abcE4b10-2\000\n'..
+ ' \000abcE4b10-3\n'..
+ ' abcE4b10-4\000abcE4b10-4-2')
end)
it('search and expressions', function()
@@ -507,14 +507,14 @@ describe('eval', function()
/: type v; value: abc/ (['abc/']), expr: abc/ (['abc/'])
==
=abc/=
- {{{2 setreg('/', ['abc/]]..'\x00'..[['])
- /: type v; value: abc/]].."\x00 (['abc/\x00']), expr: abc/\x00 (['abc/\x00"..[['])
+ {{{2 setreg('/', ['abc/]]..'\000'..[['])
+ /: type v; value: abc/]].."\000 (['abc/\000']), expr: abc/\000 (['abc/\000"..[['])
==
- =abc/]]..'\x00'..[[=
+ =abc/]]..'\000'..[[=
{{{2 setreg('=', ['"abc/"'])
=: type v; value: abc/ (['abc/']), expr: "abc/" (['"abc/"'])
- {{{2 setreg('=', ['"abc/]]..'\x00'..[["'])
- =: type v; value: abc/]].."\x00 (['abc/\x00"..[[']), expr: "abc/]]..'\x00'..[[" (['"abc/]]..'\x00'..[["'])]])
+ {{{2 setreg('=', ['"abc/]]..'\000'..[["'])
+ =: type v; value: abc/]].."\000 (['abc/\000"..[[']), expr: "abc/]]..'\000'..[[" (['"abc/]]..'\000'..[["'])]])
end)
if has_clipboard() then
diff --git a/test/functional/legacy/fnamemodify_spec.lua b/test/functional/legacy/fnamemodify_spec.lua
new file mode 100644
index 0000000000..2a32aea127
--- /dev/null
+++ b/test/functional/legacy/fnamemodify_spec.lua
@@ -0,0 +1,75 @@
+-- Test filename modifiers.
+
+local helpers = require('test.functional.helpers')
+local clear, source = helpers.clear, helpers.source
+local call, eq, nvim = helpers.call, helpers.eq, helpers.meths
+
+local function expected_empty()
+ eq({}, nvim.get_vvar('errors'))
+end
+
+describe('filename modifiers', function()
+ before_each(function()
+ clear()
+
+ source([=[
+ func Test_fnamemodify()
+ let tmpdir = resolve('/tmp')
+ execute 'cd '. tmpdir
+ set shell=sh
+ set shellslash
+ let $HOME=fnamemodify('.', ':p:h:h:h')
+ call assert_equal('/', fnamemodify('.', ':p')[-1:])
+ call assert_equal('p', fnamemodify('.', ':p:h')[-1:])
+ call assert_equal('t', fnamemodify('test.out', ':p')[-1:])
+ call assert_equal('test.out', fnamemodify('test.out', ':.'))
+ call assert_equal('../testdir/a', fnamemodify('../testdir/a', ':.'))
+ call assert_equal('test.out', fnamemodify('test.out', ':~'))
+ call assert_equal('../testdir/a', fnamemodify('../testdir/a', ':~'))
+ call assert_equal('a', fnamemodify('../testdir/a', ':t'))
+ call assert_equal('', fnamemodify('.', ':p:t'))
+ call assert_equal('test.out', fnamemodify('test.out', ':p:t'))
+ call assert_equal('out', fnamemodify('test.out', ':p:e'))
+ call assert_equal('out', fnamemodify('test.out', ':p:t:e'))
+ call assert_equal('abc.fb2.tar', fnamemodify('abc.fb2.tar.gz', ':r'))
+ call assert_equal('abc.fb2', fnamemodify('abc.fb2.tar.gz', ':r:r'))
+ call assert_equal('abc', fnamemodify('abc.fb2.tar.gz', ':r:r:r'))
+ call assert_equal(tmpdir .'/abc.fb2', substitute(fnamemodify('abc.fb2.tar.gz', ':p:r:r'), '.*\(nvim/testdir/.*\)', '\1', ''))
+ call assert_equal('gz', fnamemodify('abc.fb2.tar.gz', ':e'))
+ call assert_equal('tar.gz', fnamemodify('abc.fb2.tar.gz', ':e:e'))
+ call assert_equal('fb2.tar.gz', fnamemodify('abc.fb2.tar.gz', ':e:e:e'))
+ call assert_equal('fb2.tar.gz', fnamemodify('abc.fb2.tar.gz', ':e:e:e:e'))
+ call assert_equal('tar', fnamemodify('abc.fb2.tar.gz', ':e:e:r'))
+ call assert_equal('''abc def''', fnamemodify('abc def', ':S'))
+ call assert_equal('''abc" "def''', fnamemodify('abc" "def', ':S'))
+ call assert_equal('''abc"%"def''', fnamemodify('abc"%"def', ':S'))
+ call assert_equal('''abc''\'''' ''\''''def''', fnamemodify('abc'' ''def', ':S'))
+ call assert_equal('''abc''\''''%''\''''def''', fnamemodify('abc''%''def', ':S'))
+ new foo.txt
+ call assert_equal(expand('%:r:S'), shellescape(expand('%:r')))
+ call assert_equal('foo,''foo'',foo.txt', join([expand('%:r'), expand('%:r:S'), expand('%')], ','))
+ quit
+
+ call assert_equal("'abc\ndef'", fnamemodify("abc\ndef", ':S'))
+ set shell=tcsh
+ call assert_equal("'abc\\\ndef'", fnamemodify("abc\ndef", ':S'))
+ endfunc
+
+ func Test_expand()
+ new
+ call assert_equal("", expand('%:S'))
+ quit
+ endfunc
+ ]=])
+ end)
+
+ it('is working', function()
+ call('Test_fnamemodify')
+ expected_empty()
+ end)
+
+ it('works for :S in an unnamed buffer', function()
+ call('Test_expand')
+ expected_empty()
+ end)
+end)
diff --git a/test/functional/legacy/lispwords_spec.lua b/test/functional/legacy/lispwords_spec.lua
new file mode 100644
index 0000000000..48df4de55e
--- /dev/null
+++ b/test/functional/legacy/lispwords_spec.lua
@@ -0,0 +1,25 @@
+local helpers = require('test.functional.helpers')
+local clear = helpers.clear
+local eq = helpers.eq
+local eval = helpers.eval
+local execute = helpers.execute
+local source = helpers.source
+
+describe('lispwords', function()
+ before_each(clear)
+
+ it('should be set global-local',function()
+ source([[
+ setglobal lispwords=foo,bar,baz
+ setlocal lispwords-=foo
+ setlocal lispwords+=quux]])
+ eq('foo,bar,baz', eval('&g:lispwords'))
+ eq('bar,baz,quux', eval('&l:lispwords'))
+ eq('bar,baz,quux', eval('&lispwords'))
+
+ execute('setlocal lispwords<')
+ eq('foo,bar,baz', eval('&g:lispwords'))
+ eq('foo,bar,baz', eval('&l:lispwords'))
+ eq('foo,bar,baz', eval('&lispwords'))
+ end)
+end)
diff --git a/test/functional/options/shortmess_spec.lua b/test/functional/options/shortmess_spec.lua
new file mode 100644
index 0000000000..04a64d2943
--- /dev/null
+++ b/test/functional/options/shortmess_spec.lua
@@ -0,0 +1,39 @@
+local helpers = require('test.functional.helpers')
+local Screen = require('test.functional.ui.screen')
+local clear, feed, execute = helpers.clear, helpers.feed, helpers.execute
+
+describe("'shortmess'", function()
+ local screen
+
+ before_each(function()
+ clear()
+ screen = Screen.new(25, 5)
+ screen:attach()
+ end)
+
+ after_each(function()
+ screen:detach()
+ end)
+
+ describe('"F" flag', function()
+ it('hides messages about the files read', function()
+ execute('e test')
+ screen:expect([[
+ ^ |
+ ~ |
+ ~ |
+ ~ |
+ "test" is a directory |
+ ]])
+ execute('set shortmess=F')
+ execute('e test')
+ screen:expect([[
+ ^ |
+ ~ |
+ ~ |
+ ~ |
+ :e test |
+ ]])
+ end)
+ end)
+end)
diff --git a/test/functional/plugin/msgpack_spec.lua b/test/functional/plugin/msgpack_spec.lua
index 18ff0f5156..90cc2af9c0 100644
--- a/test/functional/plugin/msgpack_spec.lua
+++ b/test/functional/plugin/msgpack_spec.lua
@@ -1,6 +1,7 @@
local helpers = require('test.functional.helpers')
local eq, nvim_eval, nvim_command, exc_exec =
helpers.eq, helpers.eval, helpers.command, helpers.exc_exec
+local ok = helpers.ok
local plugin_helpers = require('test.functional.plugin.helpers')
local reset = plugin_helpers.reset
@@ -21,10 +22,8 @@ describe('In autoload/msgpack.vim', function()
end
local nan = -(1.0/0.0-1.0/0.0)
- local minus_nan = 1.0/0.0-1.0/0.0
local inf = 1.0/0.0
local minus_inf = -(1.0/0.0)
- local has_minus_nan = tostring(nan) ~= tostring(minus_nan)
describe('function msgpack#equal', function()
local msgpack_eq = function(expected, a, b)
@@ -160,9 +159,9 @@ describe('In autoload/msgpack.vim', function()
it('compares raw floats correctly', function()
msgpack_eq(1, '0.0', '0.0')
msgpack_eq(1, '(1.0/0.0-1.0/0.0)', '(1.0/0.0-1.0/0.0)')
- if has_minus_nan then
- msgpack_eq(0, '(1.0/0.0-1.0/0.0)', '-(1.0/0.0-1.0/0.0)')
- end
+ -- both (1.0/0.0-1.0/0.0) and -(1.0/0.0-1.0/0.0) now return
+ -- str2float('nan'). ref: @18d1ba3422d
+ msgpack_eq(1, '(1.0/0.0-1.0/0.0)', '-(1.0/0.0-1.0/0.0)')
msgpack_eq(1, '-(1.0/0.0-1.0/0.0)', '-(1.0/0.0-1.0/0.0)')
msgpack_eq(1, '1.0/0.0', '1.0/0.0')
msgpack_eq(1, '-(1.0/0.0)', '-(1.0/0.0)')
@@ -178,10 +177,8 @@ describe('In autoload/msgpack.vim', function()
it('compares float specials with raw floats correctly', function()
msgpack_eq(1, sp('float', '0.0'), '0.0')
msgpack_eq(1, sp('float', '(1.0/0.0-1.0/0.0)'), '(1.0/0.0-1.0/0.0)')
- if has_minus_nan then
- msgpack_eq(0, sp('float', '(1.0/0.0-1.0/0.0)'), '-(1.0/0.0-1.0/0.0)')
- msgpack_eq(0, sp('float', '-(1.0/0.0-1.0/0.0)'), '(1.0/0.0-1.0/0.0)')
- end
+ msgpack_eq(1, sp('float', '(1.0/0.0-1.0/0.0)'), '-(1.0/0.0-1.0/0.0)')
+ msgpack_eq(1, sp('float', '-(1.0/0.0-1.0/0.0)'), '(1.0/0.0-1.0/0.0)')
msgpack_eq(1, sp('float', '-(1.0/0.0-1.0/0.0)'), '-(1.0/0.0-1.0/0.0)')
msgpack_eq(1, sp('float', '1.0/0.0'), '1.0/0.0')
msgpack_eq(1, sp('float', '-(1.0/0.0)'), '-(1.0/0.0)')
@@ -207,10 +204,8 @@ describe('In autoload/msgpack.vim', function()
msgpack_eq(0, sp('float', '0.0'), sp('float', '-(1.0/0.0)'))
msgpack_eq(0, sp('float', '1.0/0.0'), sp('float', '-(1.0/0.0)'))
msgpack_eq(0, sp('float', '(1.0/0.0-1.0/0.0)'), sp('float', '-(1.0/0.0)'))
- if has_minus_nan then
- msgpack_eq(0, sp('float', '(1.0/0.0-1.0/0.0)'),
- sp('float', '-(1.0/0.0-1.0/0.0)'))
- end
+ msgpack_eq(1, sp('float', '(1.0/0.0-1.0/0.0)'),
+ sp('float', '-(1.0/0.0-1.0/0.0)'))
msgpack_eq(1, sp('float', '-(1.0/0.0-1.0/0.0)'),
sp('float', '-(1.0/0.0-1.0/0.0)'))
msgpack_eq(0, sp('float', '(1.0/0.0-1.0/0.0)'), sp('float', '1.0/0.0'))
@@ -392,9 +387,7 @@ describe('In autoload/msgpack.vim', function()
string_eq('0.0', sp('float', '0.0'))
string_eq('inf', sp('float', '(1.0/0.0)'))
string_eq('-inf', sp('float', '-(1.0/0.0)'))
- if has_minus_nan then
- string_eq('-nan', sp('float', '(1.0/0.0-1.0/0.0)'))
- end
+ string_eq('nan', sp('float', '(1.0/0.0-1.0/0.0)'))
string_eq('nan', sp('float', '-(1.0/0.0-1.0/0.0)'))
string_eq('FALSE', sp('boolean', '0'))
string_eq('TRUE', sp('boolean', '1'))
@@ -413,9 +406,7 @@ describe('In autoload/msgpack.vim', function()
string_eq('0.0', '0.0')
string_eq('inf', '(1.0/0.0)')
string_eq('-inf', '-(1.0/0.0)')
- if has_minus_nan then
- string_eq('-nan', '(1.0/0.0-1.0/0.0)')
- end
+ string_eq('nan', '(1.0/0.0-1.0/0.0)')
string_eq('nan', '-(1.0/0.0-1.0/0.0)')
end)
end)
@@ -547,8 +538,11 @@ describe('In autoload/msgpack.vim', function()
end
if expected_val_full == expected_val_full then
eq(expected_val_full, nvim_eval('g:__val'))
- else
- eq(tostring(expected_val_full), tostring(nvim_eval('g:__val')))
+ else -- NaN
+ local nvim_nan = tostring(nvim_eval('g:__val'))
+ -- -NaN is a hardware-specific detail, there's no need to test for it.
+ -- Accept ether 'nan' or '-nan' as the response.
+ ok(nvim_nan == 'nan' or nvim_nan == '-nan')
end
nvim_command('unlet g:__val')
end
@@ -615,7 +609,6 @@ describe('In autoload/msgpack.vim', function()
eval_eq('float', inf, 'inf')
eval_eq('float', minus_inf, '-inf')
eval_eq('float', nan, 'nan')
- eval_eq('float', minus_nan, '-nan')
eval_eq('float', 1.0e10, '1.0e10')
eval_eq('float', 1.0e10, '1.0e+10')
eval_eq('float', -1.0e10, '-1.0e+10')
diff --git a/test/functional/plugin/shada_spec.lua b/test/functional/plugin/shada_spec.lua
index 4100a30452..a3f617eeb0 100644
--- a/test/functional/plugin/shada_spec.lua
+++ b/test/functional/plugin/shada_spec.lua
@@ -2215,7 +2215,7 @@ describe('In plugin/shada.vim', function()
describe('event BufWriteCmd', function()
it('works', function()
nvim('set_var', 'shada#add_own_header', 0)
- curbuf('set_line_slice', 0, 0, true, true, {
+ curbuf('set_lines', 0, 1, true, {
'Jump with timestamp ' .. epoch .. ':',
' % Key________ Description Value',
' + n name \'A\'',
@@ -2271,7 +2271,7 @@ describe('In plugin/shada.vim', function()
describe('event FileWriteCmd', function()
it('works', function()
nvim('set_var', 'shada#add_own_header', 0)
- curbuf('set_line_slice', 0, 0, true, true, {
+ curbuf('set_lines', 0, 1, true, {
'Jump with timestamp ' .. epoch .. ':',
' % Key________ Description Value',
' + n name \'A\'',
@@ -2310,7 +2310,7 @@ describe('In plugin/shada.vim', function()
describe('event FileAppendCmd', function()
it('works', function()
nvim('set_var', 'shada#add_own_header', 0)
- curbuf('set_line_slice', 0, 0, true, true, {
+ curbuf('set_lines', 0, 1, true, {
'Jump with timestamp ' .. epoch .. ':',
' % Key________ Description Value',
' + n name \'A\'',
@@ -2512,7 +2512,7 @@ describe('syntax/shada.vim', function()
it('works', function()
nvim_command('syntax on')
nvim_command('setlocal syntax=shada')
- curbuf('set_line_slice', 0, 0, true, true, {
+ curbuf('set_lines', 0, 1, true, {
'Header with timestamp ' .. epoch .. ':',
' % Key Value',
' + t "test"',
diff --git a/test/functional/preload.lua b/test/functional/preload.lua
index 5f34f7fa6e..1971ef77cc 100644
--- a/test/functional/preload.lua
+++ b/test/functional/preload.lua
@@ -1,5 +1,4 @@
-- Modules loaded here will not be cleared and reloaded by Busted.
-- Busted started doing this to help provide more isolation. See issue #62
-- for more information about this.
-local ffi = require('ffi')
local helpers = require('test.functional.helpers')
diff --git a/test/functional/server/server_spec.lua b/test/functional/server/server_spec.lua
index 649e9dbabe..7f53522c08 100644
--- a/test/functional/server/server_spec.lua
+++ b/test/functional/server/server_spec.lua
@@ -2,7 +2,7 @@
local helpers = require('test.functional.helpers')
local nvim, eq, neq, eval = helpers.nvim, helpers.eq, helpers.neq, helpers.eval
local clear, funcs, meths = helpers.clear, helpers.funcs, helpers.meths
-local os_is_windows = helpers.os_is_windows
+local os_name = helpers.os_name
describe('serverstart(), serverstop()', function()
before_each(clear)
@@ -39,7 +39,7 @@ describe('serverstart(), serverstop()', function()
eq('', meths.get_vvar('servername'))
-- v:servername will take the next available server.
- local servername = (os_is_windows()
+ local servername = (os_name() == 'windows'
and [[\\.\pipe\Xtest-functional-server-server-pipe]]
or 'Xtest-functional-server-server-socket')
funcs.serverstart(servername)
diff --git a/test/functional/terminal/edit_spec.lua b/test/functional/terminal/edit_spec.lua
new file mode 100644
index 0000000000..dcc4a54610
--- /dev/null
+++ b/test/functional/terminal/edit_spec.lua
@@ -0,0 +1,75 @@
+local helpers = require('test.functional.helpers')
+local screen = require('test.functional.ui.screen')
+
+local curbufmeths = helpers.curbufmeths
+local curwinmeths = helpers.curwinmeths
+local nvim_dir = helpers.nvim_dir
+local command = helpers.command
+local meths = helpers.meths
+local clear = helpers.clear
+local eq = helpers.eq
+
+describe(':edit term://*', function()
+ local get_screen = function(columns, lines)
+ local scr = screen.new(columns, lines)
+ scr:attach(false)
+ return scr
+ end
+
+ before_each(function()
+ clear()
+ meths.set_option('shell', nvim_dir .. '/shell-test')
+ meths.set_option('shellcmdflag', 'EXE')
+ end)
+
+ it('runs TermOpen event', function()
+ meths.set_var('termopen_runs', {})
+ command('autocmd TermOpen * :call add(g:termopen_runs, expand("<amatch>"))')
+ command('edit term://')
+ local termopen_runs = meths.get_var('termopen_runs')
+ eq(1, #termopen_runs)
+ eq(termopen_runs[1], termopen_runs[1]:match('^term://.//%d+:$'))
+ end)
+
+ it('runs TermOpen early enough to respect terminal_scrollback_buffer_size', function()
+ local columns, lines = 20, 4
+ local scr = get_screen(columns, lines)
+ local rep = 'a'
+ meths.set_option('shellcmdflag', 'REP ' .. rep)
+ local rep_size = rep:byte()
+ local sb = 10
+ local gsb = 20
+ meths.set_var('terminal_scrollback_buffer_size', gsb)
+ command('autocmd TermOpen * :let b:terminal_scrollback_buffer_size = '
+ .. tostring(sb))
+ command('edit term://foobar')
+ local bufcontents = {}
+ local winheight = curwinmeths.get_height()
+ -- I have no idea why there is + 4 needed. But otherwise it works fine with
+ -- different scrollbacks.
+ local shift = -4
+ local buf_cont_start = rep_size - 1 - sb - winheight - shift
+ local bufline = function(i) return ('%d: foobar'):format(i) end
+ for i = buf_cont_start,(rep_size - 1) do
+ bufcontents[#bufcontents + 1] = bufline(i)
+ end
+ bufcontents[#bufcontents + 1] = ''
+ bufcontents[#bufcontents + 1] = '[Process exited 0]'
+ -- Do not ask me why displayed screen is one line *before* buffer
+ -- contents: buffer starts with 87:, screen with 86:.
+ local exp_screen = '\n'
+ local did_cursor = false
+ for i = 0,(winheight - 1) do
+ local line = bufline(buf_cont_start + i - 1)
+ exp_screen = (exp_screen
+ .. (did_cursor and '' or '^')
+ .. line
+ .. (' '):rep(columns - #line)
+ .. '|\n')
+ did_cursor = true
+ end
+ exp_screen = exp_screen .. (' '):rep(columns) .. '|\n'
+ scr:expect(exp_screen)
+ eq(bufcontents, curbufmeths.get_lines(1, -1, true))
+ end)
+end)
diff --git a/test/functional/terminal/tui_spec.lua b/test/functional/terminal/tui_spec.lua
index 838d05a6df..48376a344f 100644
--- a/test/functional/terminal/tui_spec.lua
+++ b/test/functional/terminal/tui_spec.lua
@@ -41,7 +41,7 @@ describe('tui', function()
-- INSERT -- |
-- TERMINAL -- |
]])
- feed('\x1b')
+ feed('\027')
screen:expect([[
abc |
test1 |
@@ -57,7 +57,7 @@ describe('tui', function()
local keys = 'dfghjkl'
for c in keys:gmatch('.') do
execute('nnoremap <a-'..c..'> ialt-'..c..'<cr><esc>')
- feed('\x1b'..c)
+ feed('\027'..c)
end
screen:expect([[
alt-j |
@@ -87,7 +87,7 @@ describe('tui', function()
-- Example: for input ALT+j:
-- * Vim (Nvim prior to #3982) sets high-bit, inserts "ê".
-- * Nvim (after #3982) inserts "j".
- feed('i\x1bj')
+ feed('i\027j')
screen:expect([[
j{1: } |
~ |
@@ -101,9 +101,9 @@ describe('tui', function()
it('accepts ascii control sequences', function()
feed('i')
- feed('\x16\x07') -- ctrl+g
- feed('\x16\x16') -- ctrl+v
- feed('\x16\x0d') -- ctrl+m
+ feed('\022\007') -- ctrl+g
+ feed('\022\022') -- ctrl+v
+ feed('\022\013') -- ctrl+m
screen:expect([[
{3:^G^V^M}{1: } |
~ |
@@ -116,7 +116,7 @@ describe('tui', function()
end)
it('automatically sends <Paste> for bracketed paste sequences', function()
- feed('i\x1b[200~')
+ feed('i\027[200~')
screen:expect([[
{1: } |
~ |
@@ -136,7 +136,7 @@ describe('tui', function()
-- INSERT (paste) -- |
-- TERMINAL -- |
]])
- feed('\x1b[201~')
+ feed('\027[201~')
screen:expect([[
pasted from terminal{1: } |
~ |
@@ -154,9 +154,9 @@ describe('tui', function()
for i = 1, 3000 do
t[i] = 'item ' .. tostring(i)
end
- feed('i\x1b[200~')
+ feed('i\027[200~')
feed(table.concat(t, '\n'))
- feed('\x1b[201~')
+ feed('\027[201~')
screen:expect([[
item 2997 |
item 2998 |
@@ -204,7 +204,7 @@ describe('tui focus event handling', function()
end)
it('can handle focus events in normal mode', function()
- feed('\x1b[I')
+ feed('\027[I')
screen:expect([[
{1: } |
~ |
@@ -215,7 +215,7 @@ describe('tui focus event handling', function()
-- TERMINAL -- |
]])
- feed('\x1b[O')
+ feed('\027[O')
screen:expect([[
{1: } |
~ |
@@ -230,7 +230,7 @@ describe('tui focus event handling', function()
it('can handle focus events in insert mode', function()
execute('set noshowmode')
feed('i')
- feed('\x1b[I')
+ feed('\027[I')
screen:expect([[
{1: } |
~ |
@@ -240,7 +240,7 @@ describe('tui focus event handling', function()
gained |
-- TERMINAL -- |
]])
- feed('\x1b[O')
+ feed('\027[O')
screen:expect([[
{1: } |
~ |
@@ -254,7 +254,7 @@ describe('tui focus event handling', function()
it('can handle focus events in cmdline mode', function()
feed(':')
- feed('\x1b[I')
+ feed('\027[I')
screen:expect([[
|
~ |
@@ -264,7 +264,7 @@ describe('tui focus event handling', function()
g{1:a}ined |
-- TERMINAL -- |
]])
- feed('\x1b[O')
+ feed('\027[O')
screen:expect([[
|
~ |
@@ -281,7 +281,7 @@ describe('tui focus event handling', function()
execute('set laststatus=0')
execute('set noshowmode')
execute('terminal')
- feed('\x1b[I')
+ feed('\027[I')
screen:expect([[
ready $ |
[Process exited 0]{1: } |
@@ -291,7 +291,7 @@ describe('tui focus event handling', function()
gained |
-- TERMINAL -- |
]])
- feed('\x1b[O')
+ feed('\027[O')
screen:expect([[
ready $ |
[Process exited 0]{1: } |
diff --git a/test/functional/ui/screen.lua b/test/functional/ui/screen.lua
index 80f46326ee..b35e0cde69 100644
--- a/test/functional/ui/screen.lua
+++ b/test/functional/ui/screen.lua
@@ -219,12 +219,23 @@ function Screen:expect(expected, attr_ids, attr_ignore)
local ids = attr_ids or self._default_attr_ids
local ignore = attr_ignore or self._default_attr_ignore
self:wait(function()
+ local actual_rows = {}
for i = 1, self._height do
- local expected_row = expected_rows[i]
- local actual_row = self:_row_repr(self._rows[i], ids, ignore)
- if expected_row ~= actual_row then
- return 'Row '..tostring(i)..' didn\'t match.\nExpected: "'..
- expected_row..'"\nActual: "'..actual_row..'"'
+ actual_rows[i] = self:_row_repr(self._rows[i], ids, ignore)
+ end
+ for i = 1, self._height do
+ if expected_rows[i] ~= actual_rows[i] then
+ local msg_expected_rows = {}
+ for j = 1, #expected_rows do
+ msg_expected_rows[j] = expected_rows[j]
+ end
+ msg_expected_rows[i] = '*' .. msg_expected_rows[i]
+ actual_rows[i] = '*' .. actual_rows[i]
+ return (
+ 'Row ' .. tostring(i) .. ' didn\'t match.\n'
+ .. 'Expected:\n|' .. table.concat(msg_expected_rows, '|\n|') .. '|\n'
+ .. 'Actual:\n|' .. table.concat(actual_rows, '|\n|') .. '|'
+ )
end
end
end)
diff --git a/test/functional/viml/completion_spec.lua b/test/functional/viml/completion_spec.lua
index 4bb9707cda..01b2bad059 100644
--- a/test/functional/viml/completion_spec.lua
+++ b/test/functional/viml/completion_spec.lua
@@ -1,5 +1,6 @@
local helpers = require('test.functional.helpers')
+local Screen = require('test.functional.ui.screen')
local clear, feed = helpers.clear, helpers.feed
local eval, eq, neq = helpers.eval, helpers.eq, helpers.neq
local execute, source, expect = helpers.execute, helpers.source, helpers.expect
@@ -99,6 +100,18 @@ describe('completion', function()
feed('o<C-r>=TestComplete()<CR><ESC>')
eq('', eval('getline(3)'))
end)
+ it('does not change modified state if noinsert', function()
+ execute('set completeopt+=menuone,noinsert')
+ execute('setlocal nomodified')
+ feed('i<C-r>=TestComplete()<CR><ESC>')
+ eq(0, eval('&l:modified'))
+ end)
+ it('does not change modified state if noselect', function()
+ execute('set completeopt+=menuone,noselect')
+ execute('setlocal nomodified')
+ feed('i<C-r>=TestComplete()<CR><ESC>')
+ eq(0, eval('&l:modified'))
+ end)
end)
describe("refresh:always", function()
@@ -141,4 +154,62 @@ describe('completion', function()
June]])
end)
end)
+
+ it('disables folding during completion', function ()
+ execute("set foldmethod=indent")
+ feed('i<Tab>foo<CR><Tab>bar<Esc>ggA<C-x><C-l>')
+ eq(-1, eval('foldclosed(1)'))
+ end)
+
+ it('popupmenu is not interrupted by events', function ()
+ local screen = Screen.new(40, 8)
+ screen:attach()
+ screen:set_default_attr_ignore({{bold=true, foreground=Screen.colors.Blue}})
+ screen:set_default_attr_ids({
+ [1] = {background = Screen.colors.LightMagenta},
+ [2] = {background = Screen.colors.Grey},
+ [3] = {bold = true},
+ [4] = {bold = true, foreground = Screen.colors.SeaGreen},
+ })
+
+ feed('ifoobar fooegg<cr>f<c-p>')
+ screen:expect([[
+ foobar fooegg |
+ fooegg^ |
+ {1:foobar } |
+ {2:fooegg } |
+ ~ |
+ ~ |
+ ~ |
+ {3:-- }{4:match 1 of 2} |
+ ]])
+
+ eval('1 + 1')
+ -- popupmenu still visible
+ screen:expect([[
+ foobar fooegg |
+ fooegg^ |
+ {1:foobar } |
+ {2:fooegg } |
+ ~ |
+ ~ |
+ ~ |
+ {3:-- }{4:match 1 of 2} |
+ ]])
+
+ feed('<c-p>')
+ -- Didn't restart completion: old matches still used
+ screen:expect([[
+ foobar fooegg |
+ foobar^ |
+ {2:foobar } |
+ {1:fooegg } |
+ ~ |
+ ~ |
+ ~ |
+ {3:-- }{4:match 2 of 2} |
+ ]])
+ end)
+
end)
+
diff --git a/test/functional/viml/errorlist_spec.lua b/test/functional/viml/errorlist_spec.lua
index 78e25297f2..30cb86f8d1 100644
--- a/test/functional/viml/errorlist_spec.lua
+++ b/test/functional/viml/errorlist_spec.lua
@@ -3,32 +3,44 @@ local helpers = require('test.functional.helpers')
local clear = helpers.clear
local command = helpers.command
local eq = helpers.eq
+local exc_exec = helpers.exc_exec
local get_cur_win_var = helpers.curwinmeths.get_var
--- local exc_exec = helpers.exc_exec
describe('setqflist()', function()
local setqflist = helpers.funcs.setqflist
before_each(clear)
+ it('requires a list for {list}', function()
+ eq('Vim(call):E714: List required', exc_exec('call setqflist("foo")'))
+ eq('Vim(call):E714: List required', exc_exec('call setqflist(5)'))
+ eq('Vim(call):E714: List required', exc_exec('call setqflist({})'))
+ end)
+
+ it('requires a string for {action}', function()
+ eq('Vim(call):E114: String required', exc_exec('call setqflist([], 5)'))
+ eq('Vim(call):E114: String required', exc_exec('call setqflist([], [])'))
+ eq('Vim(call):E114: String required', exc_exec('call setqflist([], {})'))
+ end)
+
it('sets w:quickfix_title', function()
setqflist({''}, 'r', 'foo')
command('copen')
eq(':foo', get_cur_win_var('quickfix_title'))
end)
- it('expects a proper type for {title}', function()
+ it('requires string or number for {title}', function()
command('copen')
- setqflist({''}, 'r', '5')
+ setqflist({}, 'r', '5')
eq(':5', get_cur_win_var('quickfix_title'))
- setqflist({''}, 'r', 6)
- eq(':setqflist()', get_cur_win_var('quickfix_title'))
- -- local exc = exc_exec('call setqflist([""], "r", function("function"))')
- -- eq('Vim(call):E729: using Funcref as a String', exc)
- -- exc = exc_exec('call setqflist([""], "r", [])')
- -- eq('Vim(call):E730: using List as a String', exc)
- -- exc = exc_exec('call setqflist([""], "r", {})')
- -- eq('Vim(call):E731: using Dictionary as a String', exc)
+ setqflist({}, 'r', 6)
+ eq(':6', get_cur_win_var('quickfix_title'))
+ local exc = exc_exec('call setqflist([], "r", function("function"))')
+ eq('Vim(call):E729: using Funcref as a String', exc)
+ exc = exc_exec('call setqflist([], "r", [])')
+ eq('Vim(call):E730: using List as a String', exc)
+ exc = exc_exec('call setqflist([], "r", {})')
+ eq('Vim(call):E731: using Dictionary as a String', exc)
end)
end)
@@ -37,10 +49,22 @@ describe('setloclist()', function()
before_each(clear)
+ it('requires a list for {list}', function()
+ eq('Vim(call):E714: List required', exc_exec('call setloclist(0, "foo")'))
+ eq('Vim(call):E714: List required', exc_exec('call setloclist(0, 5)'))
+ eq('Vim(call):E714: List required', exc_exec('call setloclist(0, {})'))
+ end)
+
+ it('requires a string for {action}', function()
+ eq('Vim(call):E114: String required', exc_exec('call setloclist(0, [], 5)'))
+ eq('Vim(call):E114: String required', exc_exec('call setloclist(0, [], [])'))
+ eq('Vim(call):E114: String required', exc_exec('call setloclist(0, [], {})'))
+ end)
+
it('sets w:quickfix_title for the correct window', function()
command('rightbelow vsplit')
- setloclist(1, {''}, 'r', 'foo')
- setloclist(2, {''}, 'r', 'bar')
+ setloclist(1, {}, 'r', 'foo')
+ setloclist(2, {}, 'r', 'bar')
command('lopen')
eq(':bar', get_cur_win_var('quickfix_title'))
command('lclose | wincmd w | lopen')
diff --git a/test/functional/viml/function_spec.lua b/test/functional/viml/function_spec.lua
new file mode 100644
index 0000000000..665f5d4467
--- /dev/null
+++ b/test/functional/viml/function_spec.lua
@@ -0,0 +1,29 @@
+local helpers = require('test.functional.helpers')
+
+local clear = helpers.clear
+local eq = helpers.eq
+local exc_exec = helpers.exc_exec
+
+describe('Up to MAX_FUNC_ARGS arguments are handled by', function()
+ local max_func_args = 20 -- from eval.h
+ local range = helpers.funcs.range
+
+ before_each(clear)
+
+ it('printf()', function()
+ local printf = helpers.funcs.printf
+ local rep = helpers.funcs['repeat']
+ local expected = '2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,'
+ eq(expected, printf(rep('%d,', max_func_args-1), unpack(range(2, max_func_args))))
+ local ret = exc_exec('call printf("", 2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21)')
+ eq('Vim(call):E740: Too many arguments for function printf', ret)
+ end)
+
+ it('rpcnotify()', function()
+ local rpcnotify = helpers.funcs.rpcnotify
+ local ret = rpcnotify(0, 'foo', unpack(range(3, max_func_args)))
+ eq(1, ret)
+ ret = exc_exec('call rpcnotify(0, "foo", 3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21)')
+ eq('Vim(call):E740: Too many arguments for function rpcnotify', ret)
+ end)
+end)
diff --git a/test/unit/buffer_spec.lua b/test/unit/buffer_spec.lua
index a2e7bd91af..b7f82064d7 100644
--- a/test/unit/buffer_spec.lua
+++ b/test/unit/buffer_spec.lua
@@ -41,13 +41,13 @@ describe('buffer functions', function()
describe('buf_valid', function()
it('should view NULL as an invalid buffer', function()
- eq(0, buffer.buf_valid(NULL))
+ eq(false, buffer.buf_valid(NULL))
end)
it('should view an open buffer as valid', function()
local buf = buflist_new(path1, buffer.BLN_LISTED)
- eq(1, buffer.buf_valid(buf))
+ eq(true, buffer.buf_valid(buf))
end)
it('should view a closed and hidden buffer as valid', function()
@@ -55,7 +55,7 @@ describe('buffer functions', function()
close_buffer(NULL, buf, 0, 0)
- eq(1, buffer.buf_valid(buf))
+ eq(true, buffer.buf_valid(buf))
end)
it('should view a closed and unloaded buffer as valid', function()
@@ -63,7 +63,7 @@ describe('buffer functions', function()
close_buffer(NULL, buf, buffer.DOBUF_UNLOAD, 0)
- eq(1, buffer.buf_valid(buf))
+ eq(true, buffer.buf_valid(buf))
end)
it('should view a closed and wiped buffer as invalid', function()
@@ -71,7 +71,7 @@ describe('buffer functions', function()
close_buffer(NULL, buf, buffer.DOBUF_WIPE, 0)
- eq(0, buffer.buf_valid(buf))
+ eq(false, buffer.buf_valid(buf))
end)
end)
diff --git a/third-party/CMakeLists.txt b/third-party/CMakeLists.txt
index 08e76ceef0..6f5a5f44dc 100644
--- a/third-party/CMakeLists.txt
+++ b/third-party/CMakeLists.txt
@@ -21,6 +21,9 @@ option(USE_BUNDLED_LIBUV "Use the bundled libuv." ${USE_BUNDLED})
option(USE_BUNDLED_MSGPACK "Use the bundled msgpack." ${USE_BUNDLED})
option(USE_BUNDLED_LUAJIT "Use the bundled version of luajit." ${USE_BUNDLED})
option(USE_BUNDLED_LUAROCKS "Use the bundled version of luarocks." ${USE_BUNDLED})
+#XXX(tarruda): Lua is only used for debugging the functional test client, no
+# build it unless explicitly requested
+option(USE_BUNDLED_LUA "Use the bundled version of lua." OFF)
option(USE_EXISTING_SRC_DIR "Skip download of deps sources in case of existing source directory." OFF)
@@ -80,6 +83,9 @@ set(MSGPACK_SHA256 afda64ca445203bb7092372b822bae8b2539fdcebbfc3f753f393628c2bcf
set(LUAJIT_URL https://github.com/neovim/deps/raw/master/opt/LuaJIT-2.0.4.tar.gz)
set(LUAJIT_SHA256 620fa4eb12375021bef6e4f237cbd2dd5d49e56beb414bee052c746beef1807d)
+set(LUA_URL https://github.com/lua/lua/archive/5.1.5.tar.gz)
+set(LUA_SHA256 1cd642c4c39778306a14e62ccddace5c7a4fb2257b0b06f43bc81cf305c7415f)
+
set(LUAROCKS_URL https://github.com/keplerproject/luarocks/archive/5d8a16526573b36d5b22aa74866120c998466697.tar.gz)
set(LUAROCKS_SHA256 cae709111c5701235770047dfd7169f66b82ae1c7b9b79207f9df0afb722bfd9)
@@ -89,8 +95,8 @@ set(UNIBILIUM_SHA256 623af1099515e673abfd3cae5f2fa808a09ca55dda1c65a7b5c9424eb30
set(LIBTERMKEY_URL http://www.leonerd.org.uk/code/libtermkey/libtermkey-0.18.tar.gz)
set(LIBTERMKEY_SHA256 239746de41c845af52bb3c14055558f743292dd6c24ac26c2d6567a5a6093926)
-set(LIBVTERM_URL https://github.com/neovim/libvterm/archive/1b745d29d45623aa8d22a7b9288c7b0e331c7088.tar.gz)
-set(LIBVTERM_SHA256 3fc75908256c0d158d6c2a32d39f34e86bfd26364f5404b7d9c03bb70cdc3611)
+set(LIBVTERM_URL https://github.com/neovim/libvterm/archive/a9c7c6fd20fa35e0ad3e0e98901ca12dfca9c25c.tar.gz)
+set(LIBVTERM_SHA256 1a4272be91d9614dc183a503786df83b6584e4afaab7feaaa5409f841afbd796)
set(JEMALLOC_URL https://github.com/jemalloc/jemalloc/releases/download/4.0.2/jemalloc-4.0.2.tar.bz2)
set(JEMALLOC_SHA256 0d8a9c8a98adb6983e0ccb521d45d9db1656ef3e71d0b14fb333f2c8138f4611)
@@ -119,6 +125,10 @@ if(USE_BUNDLED_LUAJIT)
include(BuildLuajit)
endif()
+if(USE_BUNDLED_LUA AND NOT CMAKE_CROSSCOMPILING)
+ include(BuildLua)
+endif()
+
if(USE_BUNDLED_LUAROCKS)
include(BuildLuarocks)
endif()
diff --git a/third-party/cmake/BuildLua.cmake b/third-party/cmake/BuildLua.cmake
new file mode 100644
index 0000000000..b24ef089de
--- /dev/null
+++ b/third-party/cmake/BuildLua.cmake
@@ -0,0 +1,85 @@
+include(CMakeParseArguments)
+
+# BuildLua(CONFIGURE_COMMAND ... BUILD_COMMAND ... INSTALL_COMMAND ...)
+# Reusable function to build lua, wraps ExternalProject_Add.
+# Failing to pass a command argument will result in no command being run
+function(BuildLua)
+ cmake_parse_arguments(_lua
+ ""
+ ""
+ "CONFIGURE_COMMAND;BUILD_COMMAND;INSTALL_COMMAND"
+ ${ARGN})
+
+ if(NOT _lua_CONFIGURE_COMMAND AND NOT _lua_BUILD_COMMAND
+ AND NOT _lua_INSTALL_COMMAND)
+ message(FATAL_ERROR "Must pass at least one of CONFIGURE_COMMAND, BUILD_COMMAND, INSTALL_COMMAND")
+ endif()
+
+ ExternalProject_Add(lua
+ PREFIX ${DEPS_BUILD_DIR}
+ URL ${LUA_URL}
+ DOWNLOAD_DIR ${DEPS_DOWNLOAD_DIR}/lua
+ DOWNLOAD_COMMAND ${CMAKE_COMMAND}
+ -DPREFIX=${DEPS_BUILD_DIR}
+ -DDOWNLOAD_DIR=${DEPS_DOWNLOAD_DIR}/lua
+ -DURL=${LUA_URL}
+ -DEXPECTED_SHA256=${LUA_SHA256}
+ -DTARGET=lua
+ -DUSE_EXISTING_SRC_DIR=${USE_EXISTING_SRC_DIR}
+ -P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/DownloadAndExtractFile.cmake
+ CONFIGURE_COMMAND "${_lua_CONFIGURE_COMMAND}"
+ BUILD_IN_SOURCE 1
+ BUILD_COMMAND "${_lua_BUILD_COMMAND}"
+ INSTALL_COMMAND "${_lua_INSTALL_COMMAND}")
+endfunction()
+
+if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
+ set(LUA_TARGET linux)
+elseif(CMAKE_SYSTEM_NAME STREQUAL "Darwin")
+ set(LUA_TARGET macosx)
+elseif(CMAKE_SYSTEM_NAME STREQUAL "FreeBSD")
+ set(LUA_TARGET freebsd)
+elseif(CMAKE_SYSTEM_NAME MATCHES "BSD")
+ set(CMAKE_LUA_TARGET bsd)
+elseif(SYSTEM_NAME MATCHES "^MINGW")
+ set(CMAKE_LUA_TARGET mingw)
+else()
+ if(UNIX)
+ set(LUA_TARGET posix)
+ else()
+ set(LUA_TARGET generic)
+ endif()
+endif()
+
+set(LUA_CONFIGURE_COMMAND
+ sed -e "/^CC/s@gcc@${CMAKE_C_COMPILER} ${CMAKE_C_COMPILER_ARG1}@"
+ -e "/^CFLAGS/s@-O2@-g3@"
+ -e "s@-lreadline@@g"
+ -e "s@-lhistory@@g"
+ -e "s@-lncurses@@g"
+ -i ${DEPS_BUILD_DIR}/src/lua/src/Makefile &&
+ sed -e "/#define LUA_USE_READLINE/d"
+ -i ${DEPS_BUILD_DIR}/src/lua/src/luaconf.h)
+set(LUA_BUILD_COMMAND
+ ${MAKE_PRG} ${LUA_TARGET})
+set(LUA_INSTALL_COMMAND
+ ${MAKE_PRG} INSTALL_TOP=${DEPS_INSTALL_DIR} install)
+
+message(STATUS "Lua target is ${LUA_TARGET}")
+
+BuildLua(CONFIGURE_COMMAND ${LUA_CONFIGURE_COMMAND}
+ BUILD_COMMAND ${LUA_BUILD_COMMAND}
+ INSTALL_COMMAND ${LUA_INSTALL_COMMAND})
+list(APPEND THIRD_PARTY_DEPS lua)
+add_dependencies(lua busted)
+
+set(BUSTED ${DEPS_INSTALL_DIR}/bin/busted)
+set(BUSTED_LUA ${BUSTED}-lua)
+
+add_custom_command(OUTPUT ${BUSTED_LUA}
+ COMMAND sed -e 's/jit//g' < ${BUSTED} > ${BUSTED_LUA} && chmod +x ${BUSTED_LUA}
+ DEPENDS lua)
+add_custom_target(busted-lua
+ DEPENDS ${DEPS_INSTALL_DIR}/bin/busted-lua)
+
+list(APPEND THIRD_PARTY_DEPS busted-lua)