aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-x.ci/before_script.sh4
-rw-r--r--.ci/common/build.sh10
-rwxr-xr-x.ci/install.sh4
-rw-r--r--CMakeLists.txt12
-rw-r--r--ISSUE_TEMPLATE.md9
-rw-r--r--cmake/FindMsgpack.cmake29
-rw-r--r--config/CMakeLists.txt1
-rw-r--r--config/config.h.in1
-rw-r--r--man/nvim.120
-rw-r--r--runtime/CMakeLists.txt13
-rw-r--r--runtime/autoload/man.vim4
-rw-r--r--runtime/autoload/phpcomplete.vim141
-rw-r--r--runtime/autoload/provider/clipboard.vim12
-rw-r--r--runtime/autoload/remote/host.vim22
-rw-r--r--runtime/autoload/tutor.vim3
-rw-r--r--runtime/doc/autocmd.txt9
-rw-r--r--runtime/doc/change.txt44
-rw-r--r--runtime/doc/eval.txt62
-rw-r--r--runtime/doc/help.txt3
-rw-r--r--runtime/doc/insert.txt6
-rw-r--r--runtime/doc/intro.txt2
-rw-r--r--runtime/doc/nvim_provider.txt2
-rw-r--r--runtime/doc/options.txt80
-rw-r--r--runtime/doc/pattern.txt7
-rw-r--r--runtime/doc/repeat.txt3
-rw-r--r--runtime/doc/starting.txt55
-rw-r--r--runtime/doc/syntax.txt30
-rw-r--r--runtime/doc/tabpage.txt23
-rw-r--r--runtime/doc/usr_02.txt6
-rw-r--r--runtime/doc/various.txt1
-rw-r--r--runtime/doc/vim_diff.txt14
-rw-r--r--runtime/filetype.vim10
-rw-r--r--runtime/ftplugin/j.vim7
-rw-r--r--runtime/indent/html.vim45
-rw-r--r--runtime/plugin/rplugin.vim4
-rw-r--r--runtime/syntax/c.vim22
-rw-r--r--runtime/syntax/cpp.vim15
-rw-r--r--runtime/syntax/csh.vim2
-rw-r--r--runtime/syntax/groovy.vim3
-rw-r--r--runtime/syntax/hex.vim95
-rw-r--r--runtime/syntax/php.vim4
-rw-r--r--runtime/syntax/python.vim19
-rw-r--r--runtime/syntax/sh.vim211
-rw-r--r--runtime/syntax/sm.vim4
-rw-r--r--runtime/syntax/srec.vim96
-rw-r--r--runtime/syntax/tex.vim63
-rw-r--r--runtime/syntax/upstreamdat.vim11
-rw-r--r--runtime/syntax/upstreamrpt.vim310
-rw-r--r--runtime/syntax/usw2kagtlog.vim10
-rw-r--r--runtime/syntax/yacc.vim4
-rw-r--r--runtime/syntax/yaml.vim104
-rw-r--r--runtime/vimrc_example.vim8
-rwxr-xr-xscripts/gendeclarations.lua31
-rw-r--r--scripts/genoptions.lua1
-rwxr-xr-xscripts/legacy2luatest.pl2
-rwxr-xr-xscripts/vim-patch.sh231
-rw-r--r--src/nvim/README.md26
-rw-r--r--src/nvim/buffer.c110
-rw-r--r--src/nvim/buffer.h1
-rw-r--r--src/nvim/buffer_defs.h146
-rw-r--r--src/nvim/charset.c220
-rw-r--r--src/nvim/diff.c181
-rw-r--r--src/nvim/edit.c199
-rw-r--r--src/nvim/eval.c650
-rw-r--r--src/nvim/eval_defs.h9
-rw-r--r--src/nvim/ex_cmds.c69
-rw-r--r--src/nvim/ex_docmd.c256
-rw-r--r--src/nvim/ex_getln.c41
-rw-r--r--src/nvim/ex_getln.h19
-rw-r--r--src/nvim/file_search.c86
-rw-r--r--src/nvim/fileio.c32
-rw-r--r--src/nvim/fold.c6
-rw-r--r--src/nvim/getchar.c10
-rw-r--r--src/nvim/globals.h15
-rw-r--r--src/nvim/indent_c.c126
-rw-r--r--src/nvim/keymap.c20
-rw-r--r--src/nvim/keymap.h36
-rw-r--r--src/nvim/log.c4
-rw-r--r--src/nvim/main.c50
-rw-r--r--src/nvim/message.c3
-rw-r--r--src/nvim/move.c12
-rw-r--r--src/nvim/normal.c404
-rw-r--r--src/nvim/ops.c532
-rw-r--r--src/nvim/ops.h64
-rw-r--r--src/nvim/option.c204
-rw-r--r--src/nvim/option_defs.h152
-rw-r--r--src/nvim/options.lua126
-rw-r--r--src/nvim/os/env.c19
-rw-r--r--src/nvim/os/fs.c42
-rw-r--r--src/nvim/os/input.c8
-rw-r--r--src/nvim/os/unix_defs.h2
-rw-r--r--src/nvim/os/win_defs.h1
-rw-r--r--src/nvim/path.c88
-rw-r--r--src/nvim/path.h1
-rw-r--r--src/nvim/po/CMakeLists.txt2
-rw-r--r--src/nvim/popupmnu.c8
-rw-r--r--src/nvim/quickfix.c37
-rw-r--r--src/nvim/regexp.c103
-rw-r--r--src/nvim/regexp_nfa.c56
-rw-r--r--src/nvim/screen.c277
-rw-r--r--src/nvim/screen.h23
-rw-r--r--src/nvim/search.c106
-rw-r--r--src/nvim/shada.c3
-rw-r--r--src/nvim/spell.c4
-rw-r--r--src/nvim/strings.c8
-rw-r--r--src/nvim/syntax.c56
-rw-r--r--src/nvim/tag.c47
-rw-r--r--src/nvim/terminal.c9
-rw-r--r--src/nvim/testdir/Makefile55
-rw-r--r--src/nvim/testdir/test11.in84
-rw-r--r--src/nvim/testdir/test11.ok61
-rw-r--r--src/nvim/testdir/test13.in6
-rw-r--r--src/nvim/testdir/test13.ok1
-rw-r--r--src/nvim/testdir/test30.in58
-rw-r--r--src/nvim/testdir/test30.ok9
-rw-r--r--src/nvim/testdir/test36.in105
-rw-r--r--src/nvim/testdir/test36.ok96
-rw-r--r--src/nvim/testdir/test45.in80
-rw-r--r--src/nvim/testdir/test45.ok18
-rw-r--r--src/nvim/testdir/test47.in45
-rw-r--r--src/nvim/testdir/test47.ok40
-rw-r--r--src/nvim/testdir/test49.vim26
-rw-r--r--src/nvim/testdir/test55.in171
-rw-r--r--src/nvim/testdir/test55.ok61
-rw-r--r--src/nvim/testdir/test83-tags22
-rw-r--r--src/nvim/testdir/test83-tags3102
-rw-r--r--src/nvim/testdir/test83.in75
-rw-r--r--src/nvim/testdir/test83.ok4
-rw-r--r--src/nvim/testdir/test88.in11
-rw-r--r--src/nvim/testdir/test88.ok5
-rw-r--r--src/nvim/testdir/test_charsearch.in25
-rw-r--r--src/nvim/testdir/test_charsearch.ok3
-rw-r--r--src/nvim/testdir/test_command_count.in158
-rw-r--r--src/nvim/testdir/test_command_count.ok38
-rw-r--r--src/nvim/testdir/test_eval.in234
-rw-r--r--src/nvim/testdir/test_eval.okbin10814 -> 0 bytes
-rw-r--r--src/nvim/testdir/test_eval_func.vim12
-rw-r--r--src/nvim/testdir/test_listlbr.in49
-rw-r--r--src/nvim/testdir/test_listlbr.ok24
-rw-r--r--src/nvim/testdir/test_marks.in34
-rw-r--r--src/nvim/testdir/test_marks.ok16
-rw-r--r--src/nvim/tui/tui.c12
-rw-r--r--src/nvim/undo.c7
-rw-r--r--src/nvim/version.c478
-rw-r--r--src/nvim/vim.h12
-rw-r--r--src/nvim/window.c389
-rw-r--r--src/nvim/window.h1
-rw-r--r--test/functional/api/server_requests_spec.lua2
-rw-r--r--test/functional/api/vim_spec.lua16
-rw-r--r--test/functional/autocmd/termclose_spec.lua16
-rw-r--r--test/functional/legacy/003_cindent_spec.lua112
-rw-r--r--test/functional/legacy/011_autocommands_spec.lua230
-rw-r--r--test/functional/legacy/036_regexp_character_classes_spec.lua272
-rw-r--r--test/functional/legacy/039_visual_block_mode_commands_spec.lua2
-rw-r--r--test/functional/legacy/045_folding_spec.lua139
-rw-r--r--test/functional/legacy/057_sort_spec.lua91
-rw-r--r--test/functional/legacy/059_utf8_spell_checking_spec.lua70
-rw-r--r--test/functional/legacy/062_tab_pages_spec.lua22
-rw-r--r--test/functional/legacy/063_match_and_matchadd_spec.lua4
-rw-r--r--test/functional/legacy/083_tag_search_with_file_encoding_spec.lua110
-rw-r--r--test/functional/legacy/091_context_variables_spec.lua5
-rw-r--r--test/functional/legacy/094_visual_mode_operators_spec.lua245
-rw-r--r--test/functional/legacy/autocmd_option_spec.lua43
-rw-r--r--test/functional/legacy/charsearch_spec.lua42
-rw-r--r--test/functional/legacy/command_count_spec.lua243
-rw-r--r--test/functional/legacy/comparators_spec.lua14
-rw-r--r--test/functional/legacy/erasebackword_spec.lua24
-rw-r--r--test/functional/legacy/eval_spec.lua696
-rw-r--r--test/functional/legacy/glob2regpat_spec.lua22
-rw-r--r--test/functional/legacy/increment_spec.lua723
-rw-r--r--test/functional/legacy/listlbr_utf8_spec.lua104
-rw-r--r--test/functional/legacy/match_conceal_spec.lua228
-rw-r--r--test/functional/legacy/options_spec.lua22
-rw-r--r--test/functional/legacy/quickfix_spec.lua17
-rw-r--r--test/functional/legacy/search_mbyte_spec.lua26
-rw-r--r--test/functional/legacy/set_spec.lua15
-rw-r--r--test/functional/legacy/textobjects_spec.lua61
-rw-r--r--test/functional/legacy/utf8_spec.lua55
-rw-r--r--test/functional/shada/shada_spec.lua1
-rw-r--r--test/functional/ui/highlight_spec.lua9
-rw-r--r--test/functional/ui/input_spec.lua9
-rw-r--r--test/functional/ui/mouse_spec.lua169
-rw-r--r--test/functional/viml/completion_spec.lua43
-rw-r--r--test/unit/strings_spec.lua1
184 files changed, 9222 insertions, 3941 deletions
diff --git a/.ci/before_script.sh b/.ci/before_script.sh
index 026ab0afc9..6babc582ea 100755
--- a/.ci/before_script.sh
+++ b/.ci/before_script.sh
@@ -19,6 +19,10 @@ if [[ -n "${LLVM_SYMBOLIZER}" ]] && [[ ! $(type -P "${LLVM_SYMBOLIZER}") ]]; the
echo "\$LLVM_SYMBOLIZER: '${LLVM_SYMBOLIZER}' is not executable."
exit 1
fi
+if [ "${BUILD_32BIT}" = ON ] && [ "${BUILD_MINGW}" = ON ]; then
+ >&2 echo "32-bit MinGW builds not supported."
+ exit 1
+fi
if [[ "${TRAVIS_OS_NAME}" == osx ]]; then
# Adds user to a dummy group.
diff --git a/.ci/common/build.sh b/.ci/common/build.sh
index 3d517b9b09..f635ee4960 100644
--- a/.ci/common/build.sh
+++ b/.ci/common/build.sh
@@ -1,10 +1,5 @@
build_deps() {
if [[ "${BUILD_32BIT}" == ON ]]; then
- if [[ "${BUILD_MINGW}" == ON ]]; then
- >&2 echo "32-bit MinGW builds not supported."
- exit 1
- fi
-
DEPS_CMAKE_FLAGS="${DEPS_CMAKE_FLAGS} ${CMAKE_FLAGS_32BIT}"
fi
if [[ "${BUILD_MINGW}" == ON ]]; then
@@ -42,11 +37,6 @@ build_nvim() {
CMAKE_FLAGS="${CMAKE_FLAGS} -DCLANG_${CLANG_SANITIZER}=ON"
fi
if [[ "${BUILD_32BIT}" == ON ]]; then
- if [[ "${BUILD_MINGW}" == ON ]]; then
- >&2 echo "32-bit MinGW builds not supported."
- exit 1
- fi
-
CMAKE_FLAGS="${CMAKE_FLAGS} ${CMAKE_FLAGS_32BIT}"
fi
if [[ "${BUILD_MINGW}" == ON ]]; then
diff --git a/.ci/install.sh b/.ci/install.sh
index ad3ef1b8b7..fb5d1c09c1 100755
--- a/.ci/install.sh
+++ b/.ci/install.sh
@@ -14,7 +14,9 @@ elif [[ "${BUILD_MINGW}" == ON ]]; then
# binutils-mingw-w64-i686 gcc-mingw-w64-i686 g++-mingw-w64-i686 mingw-w64-dev mingw-w64-tools
echo "Downloading MinGW..."
- curl -sSL "http://downloads.sourceforge.net/project/mingw-w64/Toolchains%20targetting%20Win32/Personal%20Builds/rubenvb/gcc-4.8-release/i686-w64-mingw32-gcc-4.8.0-linux64_rubenvb.tar.xz" | tar xJf - -C "${HOME}/.local"
+ curl -sSL "https://github.com/neovim/deps/raw/master/opt/i686-w64-mingw32-gcc-4.8.0-linux64_rubenvb.tar.xz" \
+ | tar xJf - -C "${HOME}/.local"
+
fi
# Set CC to default to avoid compilation problems
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 6c3f4d927d..527a085d3e 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -55,7 +55,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 2)
+set(NVIM_VERSION_PATCH 3)
set(NVIM_VERSION_PRERELEASE "-dev") # for package maintainers
file(TO_CMAKE_PATH ${CMAKE_CURRENT_LIST_DIR}/.git FORCED_GIT_DIR)
@@ -153,7 +153,11 @@ if(${INIT_FLAGS_NAME})
set(CMAKE_REQUIRED_FLAGS "${${INIT_FLAGS_NAME}}")
endif()
+# Include <string.h> because some toolchains define _FORTIFY_SOURCE=2 in
+# internal header files, which should in turn be #included by <string.h>.
check_c_source_compiles("
+#include <string.h>
+
#if defined(_FORTIFY_SOURCE) && _FORTIFY_SOURCE > 1
#error \"_FORTIFY_SOURCE > 1\"
#endif
@@ -254,6 +258,10 @@ if(CMAKE_COMPILER_IS_GNUCXX AND CMAKE_SYSTEM_NAME STREQUAL "Linux")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--no-undefined")
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,--no-undefined")
set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} -Wl,--no-undefined")
+
+ # For O_CLOEXEC, O_DIRECTORY, and O_NOFOLLOW flags on older systems
+ # (pre POSIX.1-2008: glibc 2.11 and earlier). #4042
+ add_definitions(-D_GNU_SOURCE)
endif()
if(CMAKE_COMPILER_IS_GNUCXX AND CMAKE_SYSTEM_NAME STREQUAL "SunOS")
@@ -279,7 +287,7 @@ include(CheckLibraryExists)
find_package(LibUV REQUIRED)
include_directories(SYSTEM ${LIBUV_INCLUDE_DIRS})
-find_package(Msgpack REQUIRED)
+find_package(Msgpack 1.0.0 REQUIRED)
include_directories(SYSTEM ${MSGPACK_INCLUDE_DIRS})
find_package(LuaJit REQUIRED)
diff --git a/ISSUE_TEMPLATE.md b/ISSUE_TEMPLATE.md
new file mode 100644
index 0000000000..4abcc4eae1
--- /dev/null
+++ b/ISSUE_TEMPLATE.md
@@ -0,0 +1,9 @@
+- Neovim version:
+- Operating system:
+- Terminal emulator:
+
+### Actual behaviour
+
+### Expected behaviour
+
+### Steps to reproduce
diff --git a/cmake/FindMsgpack.cmake b/cmake/FindMsgpack.cmake
index 7d88137915..015737d658 100644
--- a/cmake/FindMsgpack.cmake
+++ b/cmake/FindMsgpack.cmake
@@ -7,7 +7,9 @@
if(NOT MSGPACK_USE_BUNDLED)
find_package(PkgConfig)
if (PKG_CONFIG_FOUND)
- pkg_check_modules(PC_MSGPACK QUIET msgpack)
+ pkg_search_module(PC_MSGPACK QUIET
+ msgpackc>=${Msgpack_FIND_VERSION}
+ msgpack>=${Msgpack_FIND_VERSION})
endif()
else()
set(PC_MSGPACK_INCLUDEDIR)
@@ -19,19 +21,33 @@ endif()
set(MSGPACK_DEFINITIONS ${PC_MSGPACK_CFLAGS_OTHER})
-find_path(MSGPACK_INCLUDE_DIR msgpack.h
+find_path(MSGPACK_INCLUDE_DIR msgpack/version_master.h
HINTS ${PC_MSGPACK_INCLUDEDIR} ${PC_MSGPACK_INCLUDE_DIRS}
${LIMIT_SEARCH})
-# If we're asked to use static linkage, add libmsgpack.a as a preferred library name.
+if(MSGPACK_INCLUDE_DIR)
+ file(READ ${MSGPACK_INCLUDE_DIR}/msgpack/version_master.h msgpack_version_h)
+ string(REGEX REPLACE ".*MSGPACK_VERSION_MAJOR +([0-9]+).*" "\\1" MSGPACK_VERSION_MAJOR "${msgpack_version_h}")
+ string(REGEX REPLACE ".*MSGPACK_VERSION_MINOR +([0-9]+).*" "\\1" MSGPACK_VERSION_MINOR "${msgpack_version_h}")
+ string(REGEX REPLACE ".*MSGPACK_VERSION_REVISION +([0-9]+).*" "\\1" MSGPACK_VERSION_REVISION "${msgpack_version_h}")
+ set(MSGPACK_VERSION_STRING "${MSGPACK_VERSION_MAJOR}.${MSGPACK_VERSION_MINOR}.${MSGPACK_VERSION_REVISION}")
+else()
+ set(MSGPACK_VERSION_STRING)
+endif()
+
+# If we're asked to use static linkage, add libmsgpack{,c}.a as a preferred library name.
if(MSGPACK_USE_STATIC)
list(APPEND MSGPACK_NAMES
+ "${CMAKE_STATIC_LIBRARY_PREFIX}msgpackc${CMAKE_STATIC_LIBRARY_SUFFIX}"
"${CMAKE_STATIC_LIBRARY_PREFIX}msgpack${CMAKE_STATIC_LIBRARY_SUFFIX}")
endif()
-list(APPEND MSGPACK_NAMES msgpack)
+list(APPEND MSGPACK_NAMES msgpackc msgpack)
find_library(MSGPACK_LIBRARY NAMES ${MSGPACK_NAMES}
+ # Check each directory for all names to avoid using headers/libraries from
+ # different places.
+ NAMES_PER_DIR
HINTS ${PC_MSGPACK_LIBDIR} ${PC_MSGPACK_LIBRARY_DIRS}
${LIMIT_SEARCH})
@@ -43,6 +59,7 @@ set(MSGPACK_INCLUDE_DIRS ${MSGPACK_INCLUDE_DIR})
include(FindPackageHandleStandardArgs)
# handle the QUIETLY and REQUIRED arguments and set MSGPACK_FOUND to TRUE
# if all listed variables are TRUE
-find_package_handle_standard_args(Msgpack DEFAULT_MSG
- MSGPACK_LIBRARY MSGPACK_INCLUDE_DIR)
+find_package_handle_standard_args(Msgpack
+ REQUIRED_VARS MSGPACK_LIBRARY MSGPACK_INCLUDE_DIR
+ VERSION_VAR MSGPACK_VERSION_STRING)
diff --git a/config/CMakeLists.txt b/config/CMakeLists.txt
index 2d3c484845..eaf06ba7f2 100644
--- a/config/CMakeLists.txt
+++ b/config/CMakeLists.txt
@@ -26,7 +26,6 @@ if(NOT HAVE_SYS_WAIT_H AND UNIX)
message(SEND_ERROR "header sys/wait.h is required for Unix")
endif()
check_include_files(sys/utsname.h HAVE_SYS_UTSNAME_H)
-check_include_files(unistd.h HAVE_UNISTD_H)
check_include_files(utime.h HAVE_UTIME_H)
# Functions
diff --git a/config/config.h.in b/config/config.h.in
index 1eafc8cb95..27705f8b38 100644
--- a/config/config.h.in
+++ b/config/config.h.in
@@ -39,7 +39,6 @@
#cmakedefine HAVE_STRNCASECMP
#cmakedefine HAVE_SYS_UTSNAME_H
#cmakedefine HAVE_SYS_WAIT_H
-#cmakedefine HAVE_UNISTD_H
#cmakedefine HAVE_UTIME
#cmakedefine HAVE_UTIME_H
#cmakedefine HAVE_UTIMES
diff --git a/man/nvim.1 b/man/nvim.1
index f9c4e24d0b..7e8cd5b809 100644
--- a/man/nvim.1
+++ b/man/nvim.1
@@ -1,4 +1,4 @@
-.Dd November 11, 2015
+.Dd January 28, 2016
.Dt NVIM 1
.Os
.Sh NAME
@@ -373,8 +373,24 @@ Used to set the 'shell' option, which determines the shell used by the
command.
.It Ev NVIM_TUI_ENABLE_CURSOR_SHAPE
If defined, change the cursor shape to a vertical bar while in insert mode.
-Requires that the host terminal support the DECSCUSR CSI escape sequence.
+Requires that the host terminal supports the DECSCUSR CSI escape sequence.
Has no effect in GUIs.
+.Pp
+Depending on the terminal emulator, using this option with
+.Nm
+under
+.Xr tmux 1
+might require adding the following to
+.Pa ~/.tmux.conf :
+.Bd -literal -offset indent
+set -ga terminal-overrides ',*:Ss=\eE[%p1%d q:Se=\eE[2 q'
+.Ed
+.Pp
+See
+.Ic terminal-overrides
+in the
+.Xr tmux 1
+manual page for more information.
.It Ev NVIM_TUI_ENABLE_TRUE_COLOR
If defined, assume the host terminal supports 24 bit colors.
Has no effect in GUIs.
diff --git a/runtime/CMakeLists.txt b/runtime/CMakeLists.txt
index ef8e38b553..cad8da6ffb 100644
--- a/runtime/CMakeLists.txt
+++ b/runtime/CMakeLists.txt
@@ -26,24 +26,21 @@ foreach(DF ${DOCFILES})
list(APPEND BUILDDOCFILES ${GENERATED_RUNTIME_DIR}/doc/${F})
endforeach()
-add_custom_command(OUTPUT ${BUILDDOCFILES}
- COMMAND ${CMAKE_COMMAND} -E copy_directory
+add_custom_command(OUTPUT copy_docfiles
+ COMMAND ${CMAKE_COMMAND} -E copy_directory
${PROJECT_SOURCE_DIR}/runtime/doc ${GENERATED_RUNTIME_DIR}/doc
- DEPENDS
- ${DOCFILES})
+)
add_custom_command(OUTPUT ${GENERATED_HELP_TAGS}
- COMMAND ${CMAKE_COMMAND} -E copy_directory
- ${PROJECT_SOURCE_DIR}/runtime/doc ${GENERATED_RUNTIME_DIR}/doc
COMMAND "${PROJECT_BINARY_DIR}/bin/nvim"
-u NONE
-i NONE
- -es
+ -e
--headless
-c "helptags ++t ."
-c quit
DEPENDS
- ${BUILDDOCFILES}
+ copy_docfiles
nvim
WORKING_DIRECTORY "${GENERATED_RUNTIME_DIR}/doc"
)
diff --git a/runtime/autoload/man.vim b/runtime/autoload/man.vim
index d481d9eaf0..49663d7e5a 100644
--- a/runtime/autoload/man.vim
+++ b/runtime/autoload/man.vim
@@ -75,7 +75,9 @@ function man#get_page(...) abort
setlocal modifiable
silent keepjumps norm! 1G"_dG
- let $MANWIDTH = winwidth(0)
+ if empty($MANWIDTH)
+ let $MANWIDTH = winwidth(0)
+ endif
silent exec 'r!/usr/bin/man '.s:cmd(sect, page).' | col -b'
" Remove blank lines from top and bottom.
while getline(1) =~ '^\s*$'
diff --git a/runtime/autoload/phpcomplete.vim b/runtime/autoload/phpcomplete.vim
index dbc40fdf36..6dcddfd43e 100644
--- a/runtime/autoload/phpcomplete.vim
+++ b/runtime/autoload/phpcomplete.vim
@@ -3,7 +3,7 @@
" Maintainer: Dávid Szabó ( complex857 AT gmail DOT com )
" Previous Maintainer: Mikolaj Machowski ( mikmach AT wp DOT pl )
" URL: https://github.com/shawncplus/phpcomplete.vim
-" Last Change: 2015 Feb 28
+" Last Change: 2015 Apr 02
"
" OPTIONS:
"
@@ -141,71 +141,80 @@ function! phpcomplete#CompletePHP(findstart, base) " {{{
if a:base != ""
let context = substitute(context, '\s*[$a-zA-Z_0-9\x7f-\xff]*$', '', '')
end
+ else
+ let context = ''
end
- let [current_namespace, imports] = phpcomplete#GetCurrentNameSpace(getline(0, line('.')))
+ try
+ let winheight = winheight(0)
+ let winnr = winnr()
- if context =~? '^use\s' || context ==? 'use'
- return phpcomplete#CompleteUse(a:base)
- endif
+ let [current_namespace, imports] = phpcomplete#GetCurrentNameSpace(getline(0, line('.')))
- if context =~ '\(->\|::\)$'
- " {{{
- " Get name of the class
- let classname = phpcomplete#GetClassName(line('.'), context, current_namespace, imports)
-
- " Get location of class definition, we have to iterate through all
- if classname != ''
- if classname =~ '\'
- " split the last \ segment as a classname, everything else is the namespace
- let classname_parts = split(classname, '\')
- let namespace = join(classname_parts[0:-2], '\')
- let classname = classname_parts[-1]
- else
- let namespace = '\'
- endif
- let classlocation = phpcomplete#GetClassLocation(classname, namespace)
- else
- let classlocation = ''
+ if context =~? '^use\s' || context ==? 'use'
+ return phpcomplete#CompleteUse(a:base)
endif
- if classlocation != ''
- if classlocation == 'VIMPHP_BUILTINOBJECT' && has_key(g:php_builtin_classes, tolower(classname))
- return phpcomplete#CompleteBuiltInClass(context, classname, a:base)
+ if context =~ '\(->\|::\)$'
+ " {{{
+ " Get name of the class
+ let classname = phpcomplete#GetClassName(line('.'), context, current_namespace, imports)
+
+ " Get location of class definition, we have to iterate through all
+ if classname != ''
+ if classname =~ '\'
+ " split the last \ segment as a classname, everything else is the namespace
+ let classname_parts = split(classname, '\')
+ let namespace = join(classname_parts[0:-2], '\')
+ let classname = classname_parts[-1]
+ else
+ let namespace = '\'
+ endif
+ let classlocation = phpcomplete#GetClassLocation(classname, namespace)
+ else
+ let classlocation = ''
endif
- if filereadable(classlocation)
- let classfile = readfile(classlocation)
- let classcontent = ''
- let classcontent .= "\n".phpcomplete#GetClassContents(classlocation, classname)
- let sccontent = split(classcontent, "\n")
- let visibility = expand('%:p') == fnamemodify(classlocation, ':p') ? 'private' : 'public'
+ if classlocation != ''
+ if classlocation == 'VIMPHP_BUILTINOBJECT' && has_key(g:php_builtin_classes, tolower(classname))
+ return phpcomplete#CompleteBuiltInClass(context, classname, a:base)
+ endif
- return phpcomplete#CompleteUserClass(context, a:base, sccontent, visibility)
- endif
- endif
+ if filereadable(classlocation)
+ let classfile = readfile(classlocation)
+ let classcontent = ''
+ let classcontent .= "\n".phpcomplete#GetClassContents(classlocation, classname)
+ let sccontent = split(classcontent, "\n")
+ let visibility = expand('%:p') == fnamemodify(classlocation, ':p') ? 'private' : 'public'
- return phpcomplete#CompleteUnknownClass(a:base, context)
- " }}}
- elseif context =~? 'implements'
- return phpcomplete#CompleteClassName(a:base, ['i'], current_namespace, imports)
- elseif context =~? 'extends\s\+.\+$' && a:base == ''
- return ['implements']
- elseif context =~? 'extends'
- let kinds = context =~? 'class\s' ? ['c'] : ['i']
- return phpcomplete#CompleteClassName(a:base, kinds, current_namespace, imports)
- elseif context =~? 'class [a-zA-Z_\x7f-\xff\\][a-zA-Z_0-9\x7f-\xff\\]*'
- " special case when you've typed the class keyword and the name too, only extends and implements allowed there
- return filter(['extends', 'implements'], 'stridx(v:val, a:base) == 0')
- elseif context =~? 'new'
- return phpcomplete#CompleteClassName(a:base, ['c'], current_namespace, imports)
- endif
+ return phpcomplete#CompleteUserClass(context, a:base, sccontent, visibility)
+ endif
+ endif
- if a:base =~ '^\$'
- return phpcomplete#CompleteVariable(a:base)
- else
- return phpcomplete#CompleteGeneral(a:base, current_namespace, imports)
- endif
+ return phpcomplete#CompleteUnknownClass(a:base, context)
+ " }}}
+ elseif context =~? 'implements'
+ return phpcomplete#CompleteClassName(a:base, ['i'], current_namespace, imports)
+ elseif context =~? 'extends\s\+.\+$' && a:base == ''
+ return ['implements']
+ elseif context =~? 'extends'
+ let kinds = context =~? 'class\s' ? ['c'] : ['i']
+ return phpcomplete#CompleteClassName(a:base, kinds, current_namespace, imports)
+ elseif context =~? 'class [a-zA-Z_\x7f-\xff\\][a-zA-Z_0-9\x7f-\xff\\]*'
+ " special case when you've typed the class keyword and the name too, only extends and implements allowed there
+ return filter(['extends', 'implements'], 'stridx(v:val, a:base) == 0')
+ elseif context =~? 'new'
+ return phpcomplete#CompleteClassName(a:base, ['c'], current_namespace, imports)
+ endif
+
+ if a:base =~ '^\$'
+ return phpcomplete#CompleteVariable(a:base)
+ else
+ return phpcomplete#CompleteGeneral(a:base, current_namespace, imports)
+ endif
+ finally
+ silent! exec winnr.'resize '.winheight
+ endtry
endfunction
" }}}
@@ -1523,21 +1532,19 @@ function! phpcomplete#GetClassName(start_line, context, current_namespace, impor
return ''
endif
- if line =~? '\v^\s*(abstract\s+|final\s+)*\s*class'
- let class_name = matchstr(line, '\c\s*class\s*\zs'.class_name_pattern.'\ze')
+ if line =~? '\v^\s*(abstract\s+|final\s+)*\s*class\s'
+ let class_name = matchstr(line, '\cclass\s\+\zs'.class_name_pattern.'\ze')
let extended_class = matchstr(line, '\cclass\s\+'.class_name_pattern.'\s\+extends\s\+\zs'.class_name_pattern.'\ze')
let classname_candidate = a:context =~? 'parent::' ? extended_class : class_name
- else
- let i += 1
- continue
+ if classname_candidate != ''
+ let [classname_candidate, class_candidate_namespace] = phpcomplete#GetCallChainReturnType(classname_candidate, class_candidate_namespace, class_candidate_imports, methodstack)
+ " return absolute classname, without leading \
+ return (class_candidate_namespace == '\' || class_candidate_namespace == '') ? classname_candidate : class_candidate_namespace.'\'.classname_candidate
+ endif
endif
- if classname_candidate != ''
- let [classname_candidate, class_candidate_namespace] = phpcomplete#GetCallChainReturnType(classname_candidate, class_candidate_namespace, class_candidate_imports, methodstack)
- " return absolute classname, without leading \
- return (class_candidate_namespace == '\' || class_candidate_namespace == '') ? classname_candidate : class_candidate_namespace.'\'.classname_candidate
- endif
+ let i += 1
endwhile
elseif a:context =~? '(\s*new\s\+'.class_name_pattern.'\s*)->'
let classname_candidate = matchstr(a:context, '\cnew\s\+\zs'.class_name_pattern.'\ze')
@@ -2031,7 +2038,7 @@ function! phpcomplete#GetClassContentsStructure(file_path, file_lines, class_nam
" remember the window we started at
let phpcomplete_original_window = winnr()
- silent! tab 1new
+ silent! below 1new
silent! 0put =cfile
call search('\c\(class\|interface\|trait\)\_s\+'.a:class_name.'\(\>\|$\)')
let cfline = line('.')
@@ -2370,7 +2377,7 @@ endfunction!
function! phpcomplete#GetCurrentNameSpace(file_lines) " {{{
let original_window = winnr()
- silent! tab 1new
+ silent! below 1new
silent! 0put =a:file_lines
normal! G
diff --git a/runtime/autoload/provider/clipboard.vim b/runtime/autoload/provider/clipboard.vim
index 3728eb9367..5ea9df92fe 100644
--- a/runtime/autoload/provider/clipboard.vim
+++ b/runtime/autoload/provider/clipboard.vim
@@ -37,16 +37,16 @@ if executable('pbcopy')
let s:copy['*'] = s:copy['+']
let s:paste['*'] = s:paste['+']
let s:cache_enabled = 0
-elseif executable('xclip')
- let s:copy['+'] = 'xclip -quiet -i -selection clipboard'
- let s:paste['+'] = 'xclip -o -selection clipboard'
- let s:copy['*'] = 'xclip -quiet -i -selection primary'
- let s:paste['*'] = 'xclip -o -selection primary'
-elseif executable('xsel')
+elseif exists('$DISPLAY') && executable('xsel')
let s:copy['+'] = 'xsel --nodetach -i -b'
let s:paste['+'] = 'xsel -o -b'
let s:copy['*'] = 'xsel --nodetach -i -p'
let s:paste['*'] = 'xsel -o -p'
+elseif exists('$DISPLAY') && executable('xclip')
+ let s:copy['+'] = 'xclip -quiet -i -selection clipboard'
+ let s:paste['+'] = 'xclip -o -selection clipboard'
+ let s:copy['*'] = 'xclip -quiet -i -selection primary'
+ let s:paste['*'] = 'xclip -o -selection primary'
else
echom 'clipboard: No clipboard tool available. See :help nvim-clipboard'
finish
diff --git a/runtime/autoload/remote/host.vim b/runtime/autoload/remote/host.vim
index d04dea180c..24497b10c2 100644
--- a/runtime/autoload/remote/host.vim
+++ b/runtime/autoload/remote/host.vim
@@ -5,7 +5,7 @@ let s:remote_plugins_manifest = fnamemodify(expand($MYVIMRC, 1), ':h')
" Register a host by associating it with a factory(funcref)
-function! remote#host#Register(name, pattern, factory)
+function! remote#host#Register(name, pattern, factory) abort
let s:hosts[a:name] = {'factory': a:factory, 'channel': 0, 'initialized': 0}
let s:plugin_patterns[a:name] = a:pattern
if type(a:factory) == type(1) && a:factory
@@ -19,7 +19,7 @@ endfunction
" as `source`, but it will run as a different process. This can be used by
" plugins that should run isolated from other plugins created for the same host
" type
-function! remote#host#RegisterClone(name, orig_name)
+function! remote#host#RegisterClone(name, orig_name) abort
if !has_key(s:hosts, a:orig_name)
throw 'No host named "'.a:orig_name.'" is registered'
endif
@@ -34,7 +34,7 @@ endfunction
" Get a host channel, bootstrapping it if necessary
-function! remote#host#Require(name)
+function! remote#host#Require(name) abort
if !has_key(s:hosts, a:name)
throw 'No host named "'.a:name.'" is registered'
endif
@@ -51,7 +51,7 @@ function! remote#host#Require(name)
endfunction
-function! remote#host#IsRunning(name)
+function! remote#host#IsRunning(name) abort
if !has_key(s:hosts, a:name)
throw 'No host named "'.a:name.'" is registered'
endif
@@ -72,7 +72,7 @@ endfunction
"
" The third item in a declaration is a boolean: non zero means the command,
" autocommand or function will be executed synchronously with rpcrequest.
-function! remote#host#RegisterPlugin(host, path, specs)
+function! remote#host#RegisterPlugin(host, path, specs) abort
let plugins = remote#host#PluginsForHost(a:host)
for plugin in plugins
@@ -116,14 +116,14 @@ function! remote#host#RegisterPlugin(host, path, specs)
endfunction
-function! remote#host#LoadRemotePlugins()
+function! remote#host#LoadRemotePlugins() abort
if filereadable(s:remote_plugins_manifest)
exe 'source '.s:remote_plugins_manifest
endif
endfunction
-function! s:RegistrationCommands(host)
+function! s:RegistrationCommands(host) abort
" Register a temporary host clone for discovering specs
let host_id = a:host.'-registration-clone'
call remote#host#RegisterClone(host_id, a:host)
@@ -163,7 +163,7 @@ function! s:RegistrationCommands(host)
endfunction
-function! s:UpdateRemotePlugins()
+function! s:UpdateRemotePlugins() abort
let commands = []
let hosts = keys(s:hosts)
for host in hosts
@@ -180,6 +180,8 @@ function! s:UpdateRemotePlugins()
endif
endfor
call writefile(commands, s:remote_plugins_manifest)
+ echomsg printf('remote/host: generated the manifest file in "%s"',
+ \ s:remote_plugins_manifest)
endfunction
@@ -187,7 +189,7 @@ command! UpdateRemotePlugins call s:UpdateRemotePlugins()
let s:plugins_for_host = {}
-function! remote#host#PluginsForHost(host)
+function! remote#host#PluginsForHost(host) abort
if !has_key(s:plugins_for_host, a:host)
let s:plugins_for_host[a:host] = []
end
@@ -198,7 +200,7 @@ endfunction
" Registration of standard hosts
" Python/Python3 {{{
-function! s:RequirePythonHost(host)
+function! s:RequirePythonHost(host) abort
let ver = (a:host.orig_name ==# 'python') ? 2 : 3
" Python host arguments
diff --git a/runtime/autoload/tutor.vim b/runtime/autoload/tutor.vim
index 4d5a10a97c..43d8a87886 100644
--- a/runtime/autoload/tutor.vim
+++ b/runtime/autoload/tutor.vim
@@ -251,13 +251,14 @@ endfunction
" Tutor Cmd: {{{1
function! s:Locale()
- let l:lang = ""
if exists('v:lang') && v:lang =~ '\a\a'
let l:lang = v:lang
elseif $LC_ALL =~ '\a\a'
let l:lang = $LC_ALL
elseif $LANG =~ '\a\a'
let l:lang = $LANG
+ else
+ let l:lang = 'en_US'
endif
return split(l:lang, '_')
endfunction
diff --git a/runtime/doc/autocmd.txt b/runtime/doc/autocmd.txt
index 140a2f2e66..e17281821c 100644
--- a/runtime/doc/autocmd.txt
+++ b/runtime/doc/autocmd.txt
@@ -1,4 +1,4 @@
-*autocmd.txt* For Vim version 7.4. Last change: 2014 Sep 23
+*autocmd.txt* For Vim version 7.4. Last change: 2015 Mar 21
VIM REFERENCE MANUAL by Bram Moolenaar
@@ -973,6 +973,13 @@ WinLeave Before leaving a window. If the window to be
==============================================================================
6. Patterns *autocmd-patterns* *{pat}*
+The {pat} argument can be a comma separated list. This works as if the
+command was given with each pattern separately. Thus this command: >
+ :autocmd BufRead *.txt,*.info set et
+Is equivalent to: >
+ :autocmd BufRead *.txt set et
+ :autocmd BufRead *.info set et
+
The file pattern {pat} is tested for a match against the file name in one of
two ways:
1. When there is no '/' in the pattern, Vim checks for a match against only
diff --git a/runtime/doc/change.txt b/runtime/doc/change.txt
index 42dc84e0de..861f736426 100644
--- a/runtime/doc/change.txt
+++ b/runtime/doc/change.txt
@@ -1,4 +1,4 @@
-*change.txt* For Vim version 7.4. Last change: 2015 Feb 10
+*change.txt* For Vim version 7.4. Last change: 2015 Jun 25
VIM REFERENCE MANUAL by Bram Moolenaar
@@ -366,15 +366,49 @@ Adding and subtracting ~
CTRL-A Add [count] to the number or alphabetic character at
or after the cursor.
+ *v_CTRL-A*
+{Visual}CTRL-A Add [count] to the number or alphabetic character in
+ the highlighted text. {not in Vi}
+
+ *v_g_CTRL-A*
+{Visual}g CTRL-A Add [count] to the number or alphabetic character in
+ the highlighted text. If several lines are
+ highlighted, each one will be incremented by an
+ additional [count] (so effectively creating a
+ [count] incrementing sequence). {not in Vi}
+ For Example, if you have this list of numbers:
+ 1. ~
+ 1. ~
+ 1. ~
+ 1. ~
+ Move to the second "1." and Visually select three
+ lines, pressing g CTRL-A results in:
+ 1. ~
+ 2. ~
+ 3. ~
+ 4. ~
+
*CTRL-X*
CTRL-X Subtract [count] from the number or alphabetic
character at or after the cursor.
+ *v_CTRL-X*
+{Visual}CTRL-X Subtract [count] from the number or alphabetic
+ character in the highlighted text. {not in Vi}
+
+ *v_g_CTRL-X*
+{Visual}g CTRL-X Subtract [count] from the number or alphabetic
+ character in the highlighted text. If several lines
+ are highlighted, each value will be decremented by an
+ additional [count] (so effectively creating a [count]
+ decrementing sequence). {not in Vi}
+
The CTRL-A and CTRL-X commands work for (signed) decimal numbers, unsigned
-binary/octal/hexadecimal numbers and alphabetic characters. This
-depends on the 'nrformats' option.
-- When 'nrformats' includes "bin", Vim considers numbers starting with '0b' or
- '0B' as binary.
+binary/octal/hexadecimal numbers and alphabetic characters.
+
+This depends on the 'nrformats' option:
+- When 'nrformats' includes "bin", Vim assumes numbers starting with '0b' or
+ '0B' are binary.
- When 'nrformats' includes "octal", Vim considers numbers starting with a '0'
to be octal, unless the number includes a '8' or '9'. Other numbers are
decimal and may have a preceding minus sign.
diff --git a/runtime/doc/eval.txt b/runtime/doc/eval.txt
index f0747dad1b..45980f5d94 100644
--- a/runtime/doc/eval.txt
+++ b/runtime/doc/eval.txt
@@ -1,4 +1,4 @@
-*eval.txt* For Vim version 7.4. Last change: 2015 Nov 30
+*eval.txt* For Vim version 7.4. Last change: 2015 Jun 26
VIM REFERENCE MANUAL by Bram Moolenaar
@@ -524,7 +524,7 @@ Funcref to a Dictionary, but the "self" variable is not available then.
To avoid the extra name for the function it can be defined and directly
assigned to a Dictionary in this way: >
:let mydict = {'data': [0, 1, 2, 3]}
- :function mydict.len() dict
+ :function mydict.len()
: return len(self.data)
:endfunction
:echo mydict.len()
@@ -1003,7 +1003,7 @@ function. Example: >
-string *string* *expr-string* *E114*
+string *string* *String* *expr-string* *E114*
------
"string" string constant *expr-quote*
@@ -1019,7 +1019,7 @@ A string constant accepts these special characters:
\X. same as \x.
\u.... character specified with up to 4 hex numbers, stored according to the
current value of 'encoding' (e.g., "\u02a4")
-\U.... same as \u....
+\U.... same as \u but allows up to 8 hex numbers.
\b backspace <BS>
\e escape <Esc>
\f formfeed <FF>
@@ -1862,10 +1862,10 @@ getwinposx() Number X coord in pixels of GUI Vim window
getwinposy() Number Y coord in pixels of GUI Vim window
getwinvar( {nr}, {varname} [, {def}])
any variable {varname} in window {nr}
-glob( {expr} [, {nosuf} [, {list}]])
+glob( {expr} [, {nosuf} [, {list} [, {alllinks}]]])
any expand file wildcards in {expr}
glob2regpat( {expr}) String convert a glob pat into a search pat
-globpath( {path}, {expr} [, {nosuf} [, {list}]])
+globpath( {path}, {expr} [, {nosuf} [, {list} [, {alllinks}]]])
String do glob({expr}) for all dirs in {path}
has( {feature}) Number TRUE if feature {feature} supported
has_key( {dict}, {key}) Number TRUE if {dict} has entry {key}
@@ -2028,7 +2028,7 @@ split( {expr} [, {pat} [, {keepempty}]])
sqrt( {expr}) Float square root of {expr}
str2float( {expr}) Float convert String to Float
str2nr( {expr} [, {base}]) Number convert String to Number
-strchars( {expr}) Number character length of the String {expr}
+strchars( {expr} [, {skipcc}]) Number character length of the String {expr}
strdisplaywidth( {expr} [, {col}]) Number display length of the String {expr}
strftime( {format}[, {time}]) String time in specified format
stridx( {haystack}, {needle}[, {start}])
@@ -3754,7 +3754,7 @@ getwinvar({winnr}, {varname} [, {def}]) *getwinvar()*
:let list_is_on = getwinvar(2, '&list')
:echo "myvar = " . getwinvar(1, 'myvar')
<
-glob({expr} [, {nosuf} [, {list}]]) *glob()*
+glob({expr} [, {nosuf} [, {list} [, {alllinks}]]]) *glob()*
Expand the file wildcards in {expr}. See |wildcards| for the
use of special characters.
@@ -3771,8 +3771,11 @@ glob({expr} [, {nosuf} [, {list}]]) *glob()*
matches, they are separated by <NL> characters.
If the expansion fails, the result is an empty String or List.
+
A name for a non-existing file is not included. A symbolic
link is only included if it points to an existing file.
+ However, when the {alllinks} argument is present and it is
+ non-zero then all symbolic links are included.
For most systems backticks can be used to get files names from
any external command. Example: >
@@ -3791,8 +3794,11 @@ glob2regpat({expr}) *glob2regpat()*
if filename =~ glob2regpat('Make*.mak')
< This is equivalent to: >
if filename =~ '^Make.*\.mak$'
-<
-globpath({path}, {expr} [, {nosuf} [, {list}]]) *globpath()*
+< When {expr} is an empty string the result is "^$", match an
+ empty string.
+
+ *globpath()*
+globpath({path}, {expr} [, {nosuf} [, {list} [, {allinks}]]])
Perform glob() on all directories in {path} and concatenate
the results. Example: >
:echo globpath(&rtp, "syntax/c.vim")
@@ -3818,6 +3824,8 @@ globpath({path}, {expr} [, {nosuf} [, {list}]]) *globpath()*
they are separated by <NL> characters. Example: >
:echo globpath(&rtp, "syntax/c.vim", 0, 1)
<
+ {allinks} is used as with |glob()|.
+
The "**" item can be used to search in a directory tree.
For example, to find all "README.txt" files in the directories
in 'runtimepath' and below: >
@@ -4590,9 +4598,18 @@ matchadd({group}, {pattern}[, {priority}[, {id}]])
message will appear and the match will not be added. An ID
is specified as a positive integer (zero excluded). IDs 1, 2
and 3 are reserved for |:match|, |:2match| and |:3match|,
- respectively. If the {id} argument is not specified,
+ respectively. If the {id} argument is not specified or -1,
|matchadd()| automatically chooses a free ID.
+ The optional {dict} argmument allows for further custom
+ values. Currently this is used to specify a match specifc
+ conceal character that will be shown for |hl-Conceal|
+ highlighted matches. The dict can have the following members:
+
+ conceal Special character to show instead of the
+ match (only for |hl-Conceal| highlighed
+ matches, see |:syn-cchar|)
+
The number of matches is not limited, as it is the case with
the |:match| commands.
@@ -4606,7 +4623,7 @@ matchadd({group}, {pattern}[, {priority}[, {id}]])
available from |getmatches()|. All matches can be deleted in
one operation by |clearmatches()|.
-matchaddpos({group}, {pos}[, {priority}[, {id}]]) *matchaddpos()*
+matchaddpos({group}, {pos}[, {priority}[, {id}[, {dict}]]]) *matchaddpos()*
Same as |matchadd()|, but requires a list of positions {pos}
instead of a pattern. This command is faster than |matchadd()|
because it does not require to handle regular expressions and
@@ -6149,15 +6166,17 @@ str2nr( {expr} [, {base}]) *str2nr()*
Text after the number is silently ignored.
-strchars({expr}) *strchars()*
+strchars({expr} [, {skipcc}]) *strchars()*
The result is a Number, which is the number of characters
- String {expr} occupies. Composing characters are counted
- separately.
+ in String {expr}.
+ When {skipcc} is omitted or zero, composing characters are
+ counted separately.
+ When {skipcc} set to 1, Composing characters are ignored.
Also see |strlen()|, |strdisplaywidth()| and |strwidth()|.
strdisplaywidth({expr}[, {col}]) *strdisplaywidth()*
The result is a Number, which is the number of display cells
- String {expr} occupies on the screen when it starts a {col}.
+ String {expr} occupies on the screen when it starts at {col}.
When {col} is omitted zero is used. Otherwise it is the
screen column where to start. This matters for Tab
characters.
@@ -6223,15 +6242,11 @@ string({expr}) Return {expr} converted to a String. If {expr} is a Number,
*strlen()*
strlen({expr}) The result is a Number, which is the length of the String
{expr} in bytes.
- If you want to count the number of multi-byte characters (not
- counting composing characters) use something like this: >
-
- :let len = strlen(substitute(str, ".", "x", "g"))
-<
If the argument is a Number it is first converted to a String.
For other types an error is given.
- Also see |len()|, |strchars()|, |strdisplaywidth()| and
- |strwidth()|.
+ If you want to count the number of multi-byte characters use
+ |strchars()|.
+ Also see |len()|, |strdisplaywidth()| and |strwidth()|.
strpart({src}, {start}[, {len}]) *strpart()*
The result is a String, which is part of {src}, starting from
@@ -7055,6 +7070,7 @@ statusline Compiled with support for 'statusline', 'rulerformat'
syntax Compiled with syntax highlighting support |syntax|.
syntax_items There are active syntax highlighting items for the
current buffer.
+tablineat 'tabline' option accepts %@Func@ items.
tag_binary Compiled with binary searching in tags files
|tag-binary-search|.
tag_old_static Compiled with support for old static tags
diff --git a/runtime/doc/help.txt b/runtime/doc/help.txt
index 766a440cb3..19bcb35da8 100644
--- a/runtime/doc/help.txt
+++ b/runtime/doc/help.txt
@@ -1,4 +1,4 @@
-*help.txt* For Vim version 7.4. Last change: 2012 Dec 06
+*help.txt* For Vim version 7.4. Last change: 2015 Apr 15
VIM - main help file
k
@@ -23,6 +23,7 @@ Get specific help: It is possible to go directly to whatever you want help
Command-line editing c_ :help c_<Del>
Vim command argument - :help -r
Option ' :help 'textwidth'
+ Regular expression / :help /[
Search for help: Type ":help word", then hit CTRL-D to see matching
help entries for "word".
Or use ":helpgrep word". |:helpgrep|
diff --git a/runtime/doc/insert.txt b/runtime/doc/insert.txt
index cb01d5fe92..f17410d1dc 100644
--- a/runtime/doc/insert.txt
+++ b/runtime/doc/insert.txt
@@ -1,4 +1,4 @@
-*insert.txt* For Vim version 7.4. Last change: 2015 May 22
+*insert.txt* For Vim version 7.4. Last change: 2015 Jun 20
VIM REFERENCE MANUAL by Bram Moolenaar
@@ -78,8 +78,8 @@ CTRL-W Delete the word before the cursor (see |i_backspacing| about
|word-motions|, for the definition of a word.
*i_CTRL-U*
CTRL-U Delete all entered characters before the cursor in the current
- line. If there are no newly entereed characters and
- 'backspace'is not empty, delete all characters before the
+ line. If there are no newly entered characters and
+ 'backspace' is not empty, delete all characters before the
cursor in the current line.
See |i_backspacing| about joining lines.
*i_CTRL-I* *i_<Tab>* *i_Tab*
diff --git a/runtime/doc/intro.txt b/runtime/doc/intro.txt
index fdf106a7bb..cbe017e051 100644
--- a/runtime/doc/intro.txt
+++ b/runtime/doc/intro.txt
@@ -452,7 +452,7 @@ notation meaning equivalent decimal value(s) ~
<C-...> control-key *control* *ctrl* *<C-*
<M-...> alt-key or meta-key *meta* *alt* *<M-*
<A-...> same as <M-...> *<A-*
-<D-...> command-key (Macintosh only) *<D-*
+<D-...> command-key or "super" key *<D-*
<t_xx> key with "xx" entry in termcap
-----------------------------------------------------------------------
diff --git a/runtime/doc/nvim_provider.txt b/runtime/doc/nvim_provider.txt
index a737d51ac4..91cd5fbfc7 100644
--- a/runtime/doc/nvim_provider.txt
+++ b/runtime/doc/nvim_provider.txt
@@ -26,7 +26,7 @@ are now decoupled from Nvim core as providers:
The first example is clipboard integration: in the original Vim source code,
clipboard functions account for more than 1k lines of C source code (and that
-is just on ui.c), all to peform two tasks that are now accomplished with
+is just on ui.c), all to perform two tasks that are now accomplished with
simple shell commands such as xclip or pbcopy/pbpaste.
The other example is Python scripting support: Vim has three files dedicated to
diff --git a/runtime/doc/options.txt b/runtime/doc/options.txt
index 013e7c742c..ced303947b 100644
--- a/runtime/doc/options.txt
+++ b/runtime/doc/options.txt
@@ -50,8 +50,8 @@ achieve special effects. These options come in three forms:
:se[t] {option}&vim Reset option to its Vim default value.
:se[t] all& Set all options, except terminal options, to their
- default value. The values of 'term', 'lines' and
- 'columns' are not changed.
+ default value. The values of 'lines' and 'columns'
+ are not changed.
*:set-args* *E487* *E521*
:se[t] {option}={value} or
@@ -772,14 +772,13 @@ A jump table for the options with a short description can be found at |Q_op|.
putting a ":gui" command in the gvimrc file, before where the value
of 'background' is used (e.g., before ":syntax on").
- For Windows the default is "dark".
- For other systems "dark" is used when 'term' is "linux",
- "screen.linux", "cygwin" or "putty", or $COLORFGBG suggests a dark
- background. Otherwise the default is "light".
+ For Windows the default is "dark". "dark" should be used if $COLORFGBG
+ suggests a dark background (not yet implemented). Otherwise the default
+ is "light".
Normally this option would be set in the vimrc file. Possibly
depending on the terminal name. Example: >
- :if &term == "xterm"
+ :if $TERM == "xterm"
: set background=dark
:endif
< When this option is set, the default settings for the highlight groups
@@ -1361,7 +1360,7 @@ A jump table for the options with a short description can be found at |Q_op|.
option, yank and delete operations (but not put)
will additionally copy the text into register
'*'. See |nvim-clipboard|.
-<
+
*clipboard-autoselect*
autoselect Works like the 'a' flag in 'guioptions': If present,
then whenever Visual mode is started, or the Visual
@@ -3984,8 +3983,9 @@ A jump table for the options with a short description can be found at |Q_op|.
conceal:c Character to show in place of concealed text, when
'conceallevel' is set to 1. A space when omitted.
*lcs-nbsp*
- nbsp:c Character to show for a non-breakable space (character
- 0xA0, 160). Left blank when omitted.
+ nbsp:c Character to show for a non-breakable space character
+ (0xA0 (160 decimal) and U+202F). Left blank when
+ omitted.
The characters ':' and ',' should not be used. UTF-8 characters can
be used when 'encoding' is "utf-8", otherwise only printable
@@ -4395,7 +4395,7 @@ A jump table for the options with a short description can be found at |Q_op|.
recognized as a multi click.
*'nrformats'* *'nf'*
-'nrformats' 'nf' string (default "hex")
+'nrformats' 'nf' string (default "bin,hex")
local to buffer
This defines what bases Vim will consider for numbers when using the
CTRL-A and CTRL-X commands for adding to and subtracting from a number
@@ -4408,6 +4408,9 @@ A jump table for the options with a short description can be found at |Q_op|.
hex If included, numbers starting with "0x" or "0X" will be
considered to be hexadecimal. Example: Using CTRL-X on
"0x100" results in "0x0ff".
+ bin If included, numbers starting with "0b" or "0B" will be
+ considered to be binary. Example: Using CTRL-X on
+ "0b1000" subtracts one, resulting in "0b0111".
Numbers which simply begin with a digit in the range 1-9 are always
considered decimal. This also happens for numbers that are not
recognized as octal or hex.
@@ -6007,11 +6010,39 @@ A jump table for the options with a short description can be found at |Q_op|.
( - Start of item group. Can be used for setting the width and
alignment of a section. Must be followed by %) somewhere.
) - End of item group. No width fields allowed.
- T N For 'tabline': start of tab page N label. Use %T after the last
- label. This information is used for mouse clicks.
- X N For 'tabline': start of close tab N label. Use %X after the
- label, e.g.: %3Xclose%X. Use %999X for a "close current tab"
- mark. This information is used for mouse clicks.
+ T N For 'tabline': start of tab page N label. Use %T or %X to end
+ the label. Clicking this label with left mouse button switches
+ to the specified tab page.
+ X N For 'tabline': start of close tab N label. Use %X or %T to end
+ the label, e.g.: %3Xclose%X. Use %999X for a "close current
+ tab" label. Clicking this label with left mouse button closes
+ specified tab page.
+ @ N For 'tabline': start of execute function label. Use %X or %T to
+ end the label, e.g.: %10@SwitchBuffer@foo.c%X. Clicking this
+ label runs specified function: in the example when clicking once
+ using left mouse button on "foo.c" "SwitchBuffer(10, 1, 'l',
+ ' ')" expression will be run. Function receives the
+ following arguments in order:
+ 1. minwid field value or zero if no N was specified
+ 2. number of mouse clicks to detect multiple clicks
+ 3. mouse button used: "l", "r" or "m" for left, right or middle
+ button respectively; one should not rely on third argument
+ being only "l", "r" or "m": any other non-empty string value
+ that contains only ASCII lower case letters may be expected
+ for other mouse buttons
+ 4. modifiers pressed: string which contains "s" if shift
+ modifier was pressed, "c" for control, "a" for alt and "m"
+ for meta; currently if modifier is not pressed string
+ contains space instead, but one should not rely on presence
+ of spaces or specific order of modifiers: use |stridx()| to
+ test whether some modifier is present; string is guaranteed
+ to contain only ASCII letters and spaces, one letter per
+ modifier; "?" modifier may also be present, but its presence
+ is a bug that denotes that new mouse button recognition was
+ added without modifying code that reacts on mouse clicks on
+ this label.
+ Note: to test whether your version of Neovim contains this
+ feature use `has('tablineat')`.
< - Where to truncate line if too long. Default is at the start.
No width fields allowed.
= - Separation point between left and right aligned items.
@@ -6145,6 +6176,7 @@ A jump table for the options with a short description can be found at |Q_op|.
split If included, split the current window before loading
a buffer for a |quickfix| command that display errors.
Otherwise: do not split, use current window.
+ vsplit Just like "split" but split vertically.
newtab Like "split", but open a new tab page. Overrules
"split" when both are present.
@@ -6338,17 +6370,7 @@ A jump table for the options with a short description can be found at |Q_op|.
mapping which should not change the tagstack.
*'term'* *E529* *E530* *E531*
-'term' string (default is $TERM, if that fails:
- in the GUI: "builtin_gui"
- on Mac: "mac-ansi"
- on Unix: "ansi"
- on Windows: "win32")
- global
- Name of the terminal. Used for choosing the terminal control
- characters. Environment variables are expanded |:set_env|.
- For example: >
- :set term=$TERM
-< See |termcap|.
+'term' Removed. |vim-differences| {Nvim}
*'termbidi'* *'tbidi'*
*'notermbidi'* *'notbidi'*
@@ -6528,9 +6550,7 @@ A jump table for the options with a short description can be found at |Q_op|.
'ttyscroll' 'tsl' Removed. |vim-differences| {Nvim}
*'ttytype'* *'tty'*
-'ttytype' 'tty' string (default from $TERM)
- global
- Alias for 'term', see above.
+'ttytype' 'tty' Alias for 'term'. Removed. |vim-differences| {Nvim}
*'undodir'* *'udir'* *E926*
'undodir' 'udir' string (default "$XDG_DATA_HOME/nvim/undo")
diff --git a/runtime/doc/pattern.txt b/runtime/doc/pattern.txt
index 21eeb9bc41..84dce82176 100644
--- a/runtime/doc/pattern.txt
+++ b/runtime/doc/pattern.txt
@@ -1,4 +1,4 @@
-*pattern.txt* For Vim version 7.4. Last change: 2015 Feb 17
+*pattern.txt* For Vim version 7.4. Last change: 2015 Mar 16
VIM REFERENCE MANUAL by Bram Moolenaar
@@ -1052,7 +1052,10 @@ x A single character, with no special meaning, matches itself
*E769*
When the ']' is not there Vim will not give an error message but
assume no collection is used. Useful to search for '['. However, you
- do get E769 for internal searching.
+ do get E769 for internal searching. And be aware that in a
+ `:substitute` command the whole command becomes the pattern. E.g.
+ ":s/[/x/" searches for "[/x" and replaces it with nothing. It does
+ not search for "[" and replaces it with "x"!
If the sequence begins with "^", it matches any single character NOT
in the collection: "[^xyz]" matches anything but 'x', 'y' and 'z'.
diff --git a/runtime/doc/repeat.txt b/runtime/doc/repeat.txt
index 59dbbf3067..21b5eef811 100644
--- a/runtime/doc/repeat.txt
+++ b/runtime/doc/repeat.txt
@@ -1,4 +1,4 @@
-*repeat.txt* For Vim version 7.4. Last change: 2015 Jan 07
+*repeat.txt* For Vim version 7.4. Last change: 2015 Apr 13
VIM REFERENCE MANUAL by Bram Moolenaar
@@ -583,6 +583,7 @@ For example, to profile the one_script.vim script file: >
:prof[ile] start {fname} *:prof* *:profile* *E750*
Start profiling, write the output in {fname} upon exit.
+ "~/" and environment variables in {fname} will be expanded.
If {fname} already exists it will be silently overwritten.
The variable |v:profiling| is set to one.
diff --git a/runtime/doc/starting.txt b/runtime/doc/starting.txt
index e2473976eb..be108d4633 100644
--- a/runtime/doc/starting.txt
+++ b/runtime/doc/starting.txt
@@ -217,7 +217,7 @@ argument.
:set to display option values.
When 'verbose' is non-zero messages are printed (for
debugging, to stderr).
- 'term' and $TERM are not used.
+ $TERM is not used.
If Vim appears to be stuck try typing "qa!<Enter>". You don't
get a prompt thus you can't see Vim is waiting for you to type
something.
@@ -315,9 +315,10 @@ argument.
When {vimrc} is equal to "NONE" (all uppercase), all
initializations from files and environment variables are
skipped, including reading the |ginit.vim| file when the GUI
- starts. Loading plugins is also skipped.
+ starts. Plugins and syntax highlighting are also skipped.
When {vimrc} is equal to "NORC" (all uppercase), this has the
- same effect as "NONE", but loading plugins is not skipped.
+ same effect as "NONE", but plugins and syntax highlighting are
+ not skipped.
*-i*
-i {shada} The file {shada} is used instead of the default ShaDa
@@ -354,13 +355,10 @@ argument.
At startup, Vim checks environment variables and files and sets values
accordingly. Vim proceeds in this order:
-1. Set the 'shell' and 'term' option *SHELL* *COMSPEC* *TERM*
+1. Set the 'shell' option *SHELL* *COMSPEC* *TERM*
The environment variable SHELL, if it exists, is used to set the
'shell' option. On Windows, the COMSPEC variable is used
if SHELL is not set.
- The environment variable TERM, if it exists, is used to set the 'term'
- option. However, 'term' will change later when starting the GUI (step
- 8 below).
2. Process the arguments
The options and file names from the command that start Vim are
@@ -394,7 +392,8 @@ accordingly. Vim proceeds in this order:
All following initializations until 4. are skipped. $MYVIMRC is not
set.
"vim -u NORC" can be used to skip these initializations without
- reading a file. "vim -u NONE" also skips loading plugins. |-u|
+ reading a file. "vim -u NONE" also skips plugins and syntax
+ highlighting. |-u|
If Vim was started in Ex mode with the "-s" argument, all following
initializations until 4. are skipped. Only the "-u" option is
@@ -427,7 +426,22 @@ accordingly. Vim proceeds in this order:
- The file ".exrc" (for Unix)
"_exrc" (for Win32)
-4. Load the plugin scripts. *load-plugins*
+4. Enable filetype and indent plugins.
+ This does the same as the commands: >
+ :runtime! filetype.vim
+ :runtime! ftplugin.vim
+ :runtime! indent.vim
+< This step is skipped if ":filetype ..." was called before now or if
+ the "-u NONE" command line argument was given.
+
+5. Enable syntax highlighting.
+ This does the same as the command: >
+ :runtime! syntax/syntax.vim
+< Note: This enables filetype detection even if ":filetype off" was
+ called before now.
+ This step is skipped if the "-u NONE" command line argument was given.
+
+6. Load the plugin scripts. *load-plugins*
This does the same as the command: >
:runtime! plugin/**/*.vim
< The result is that all directories in the 'runtimepath' option will be
@@ -443,31 +457,30 @@ accordingly. Vim proceeds in this order:
commands from the command line have not been executed yet. You can
use "--cmd 'set noloadplugins'" |--cmd|.
-5. Set 'shellpipe' and 'shellredir'
+7. Set 'shellpipe' and 'shellredir'
The 'shellpipe' and 'shellredir' options are set according to the
value of the 'shell' option, unless they have been set before.
This means that Vim will figure out the values of 'shellpipe' and
'shellredir' for you, unless you have set them yourself.
-6. Set 'updatecount' to zero, if "-n" command argument used
+8. Set 'updatecount' to zero, if "-n" command argument used
-7. Set binary options
+9. Set binary options
If the "-b" flag was given to Vim, the options for binary editing will
be set now. See |-b|.
-8. Perform GUI initializations
+10. Perform GUI initializations
Only when starting "gvim", the GUI initializations will be done. See
|gui-init|.
-9. Read the ShaDa file
- If the 'shada' option is not empty, the ShaDa file is read. See
- |shada-file|.
+11. Read the ShaDa file
+ See |shada-file|.
-10. Read the quickfix file
+12. Read the quickfix file
If the "-q" flag was given to Vim, the quickfix file is read. If this
fails, Vim exits.
-11. Open all windows
+13. Open all windows
When the |-o| flag was given, windows will be opened (but not
displayed yet).
When the |-p| flag was given, tab pages will be created (but not
@@ -476,7 +489,7 @@ accordingly. Vim proceeds in this order:
If the "-q" flag was given to Vim, the first error is jumped to.
Buffers for all windows will be loaded.
-12. Execute startup commands
+14. Execute startup commands
If a "-t" flag was given to Vim, the tag is jumped to.
The commands given with the |-c| and |+cmd| arguments are executed.
The starting flag is reset, has("vim_starting") will now return zero.
@@ -705,8 +718,8 @@ vimrc file.
These commands will write ":map" and ":set" commands to a file, in such a way
that when these commands are executed, the current key mappings and options
will be set to the same values. The options 'columns', 'endofline',
-'fileformat', 'lines', 'modified', 'scroll', and 'term' are not included,
-because these are terminal or file dependent.
+'fileformat', 'lines', 'modified', and 'scroll' are not included, because
+these are terminal or file dependent.
Note that the options 'binary', 'paste' and 'readonly' are included, this
might not always be what you want.
diff --git a/runtime/doc/syntax.txt b/runtime/doc/syntax.txt
index 78d6fdb1e1..6aed7441a0 100644
--- a/runtime/doc/syntax.txt
+++ b/runtime/doc/syntax.txt
@@ -1,4 +1,4 @@
-*syntax.txt* For Vim version 7.4. Last change: 2015 Feb 22
+*syntax.txt* For Vim version 7.4. Last change: 2015 Mar 29
VIM REFERENCE MANUAL by Bram Moolenaar
@@ -3307,6 +3307,32 @@ must not click outside of the pixel strings, but feel free to improve it.
It will look much better with a font in a quadratic cell size, e.g. for X: >
:set guifont=-*-clean-medium-r-*-*-8-*-*-*-*-80-*
+
+YAML *yaml.vim* *ft-yaml-syntax*
+
+ *g:yaml_schema* *b:yaml_schema*
+A YAML schema is a combination of a set of tags and a mechanism for resolving
+non-specific tags. For user this means that YAML parser may, depending on
+plain scalar contents, treat plain scalar (which can actually be only string
+and nothing else) as a value of the other type: null, boolean, floating-point,
+integer. `g:yaml_schema` option determines according to which schema values
+will be highlighted specially. Supported schemas are
+
+Schema Description ~
+failsafe No additional highlighting.
+json Supports JSON-style numbers, booleans and null.
+core Supports more number, boolean and null styles.
+pyyaml In addition to core schema supports highlighting timestamps,
+ but there are some differences in what is recognized as
+ numbers and many additional boolean values not present in core
+ schema.
+
+Default schema is `core`.
+
+Note that schemas are not actually limited to plain scalars, but this is the
+only difference between schemas defined in YAML specification and the only
+difference defined in the syntax file.
+
==============================================================================
5. Defining a syntax *:syn-define* *E410*
@@ -4632,6 +4658,8 @@ ctermbg={color-nr} *highlight-ctermbg*
Note that for some color terminals these names may result in the wrong
colors!
+ You can also use "NONE" to remove the color.
+
*:hi-normal-cterm*
When setting the "ctermfg" or "ctermbg" colors for the Normal group,
these will become the colors used for the non-highlighted text.
diff --git a/runtime/doc/tabpage.txt b/runtime/doc/tabpage.txt
index 13944dc02a..59c4a28ff2 100644
--- a/runtime/doc/tabpage.txt
+++ b/runtime/doc/tabpage.txt
@@ -197,22 +197,29 @@ REORDERING TAB PAGES:
Move the current tab page to after tab page N. Use zero to
make the current tab page the first one. Without N the tab
page is made the last one. >
+ :.tabmove " do nothing
:-tabmove " move the tab page to the left
- :tabmove " move the tab page to the right
- :.tabmove " as above
- :+tabmove " as above
+ :+tabmove " move the tab page to the right
:0tabmove " move the tab page to the beginning of the tab
" list
- :$tabmove " move the tab page to the end of the tab list
-<
+ :tabmove 0 " as above
+ :tabmove " move the tab page to the last
+ :$tabmove " as above
+ :tabmove $ " as above
+
:tabm[ove] +[N]
:tabm[ove] -[N]
Move the current tab page N places to the right (with +) or to
- the left (with -).
+ the left (with -). >
+ :tabmove - " move the tab page to the left
+ :tabmove -1 " as above
+ :tabmove + " move the tab page to the right
+ :tabmove +1 " as above
+
Note that although it is possible to move a tab behind the N-th one by using
-:Ntabmove, it is impossible to move it by N places by using :+Ntabmove. For
-clarification what +N means in this context see |[range]|.
+:Ntabmove. And move it by N places by using :+Ntabmove. For clarification what
++N means in this context see |[range]|.
LOOPING OVER TAB PAGES:
diff --git a/runtime/doc/usr_02.txt b/runtime/doc/usr_02.txt
index f81a4e3a2c..6a288f8965 100644
--- a/runtime/doc/usr_02.txt
+++ b/runtime/doc/usr_02.txt
@@ -1,4 +1,4 @@
-*usr_02.txt* For Vim version 7.4. Last change: 2010 Jul 20
+*usr_02.txt* For Vim version 7.4. Last change: 2015 Apr 12
VIM USER MANUAL - by Bram Moolenaar
@@ -516,9 +516,11 @@ Summary: *help-summary* >
:help subject()
< Function "subject". >
:help -subject
-< Command-line option "-subject". >
+< Command-line argument "-subject". >
:help +subject
< Compile-time feature "+subject". >
+ :help /*
+< Regular expression item "*" >
:help EventName
< Autocommand event "EventName". >
:help digraphs.txt
diff --git a/runtime/doc/various.txt b/runtime/doc/various.txt
index 26ff8f0783..ff37466a14 100644
--- a/runtime/doc/various.txt
+++ b/runtime/doc/various.txt
@@ -363,6 +363,7 @@ N *+startuptime* |--startuptime| argument
N *+statusline* Options 'statusline', 'rulerformat' and special
formats of 'titlestring' and 'iconstring'
N *+syntax* Syntax highlighting |syntax|
+N *+tablineat* 'tabline' option recognizing %@Func@ items.
N *+tag_binary* binary searching in tags file |tag-binary-search|
N *+tag_old_static* old method for static tags |tag-old-static|
m *+tag_any_white* any white space allowed in tags file |tag-any-white|
diff --git a/runtime/doc/vim_diff.txt b/runtime/doc/vim_diff.txt
index 6609a96e9e..d3768409f5 100644
--- a/runtime/doc/vim_diff.txt
+++ b/runtime/doc/vim_diff.txt
@@ -11,7 +11,7 @@ the "{Nvim}" tag. This document is a complete and centralized list of all
these differences.
1. Configuration |nvim-configuration|
-2. Option defaults |nvim-option-defaults|
+2. Defaults |nvim-defaults|
3. Changed features |nvim-features-changed|
4. New features |nvim-features-new|
5. Missing legacy features |nvim-features-missing|
@@ -28,7 +28,12 @@ these differences.
session information.
==============================================================================
-2. Option defaults *nvim-option-defaults*
+2. Defaults *nvim-defaults*
+
+- Syntax highlighting is enabled by default
+- Filetype-related plugins and scripts are enabled by default
+ Note: these defaults can be disabled with the "-u NONE" command line
+ argument. |-u|
- 'autoindent' is set by default
- 'autoread' is set by default
@@ -45,7 +50,7 @@ these differences.
- 'listchars' defaults to "tab:> ,trail:-,nbsp:+"
- 'mouse' defaults to "a"
- 'nocompatible' is always set
-- 'nrformats' defaults to "hex"
+- 'nrformats' defaults to "bin,hex"
- 'sessionoptions' doesn't include "options"
- 'smarttab' is set by default
- 'tabpagemax' defaults to 50
@@ -207,6 +212,7 @@ Other options:
'shelltype'
'shortname'
'swapsync'
+ 'term'
'termencoding' (Vim 7.4.852 also removed this for Windows)
'textauto'
'textmode'
@@ -214,6 +220,8 @@ Other options:
'toolbariconsize'
'ttybuiltin'
'ttymouse'
+ 'ttyscroll'
+ 'ttytype'
'weirdinvert'
Other commands:
diff --git a/runtime/filetype.vim b/runtime/filetype.vim
index 5dbd1a9a19..d60ab65ce7 100644
--- a/runtime/filetype.vim
+++ b/runtime/filetype.vim
@@ -1,7 +1,7 @@
" Vim support file to detect file types
"
" Maintainer: Bram Moolenaar <Bram@vim.org>
-" Last Change: 2015 Jan 14
+" Last Change: 2015 Apr 06
" Listen very carefully, I will say this only once
if exists("did_load_filetypes")
@@ -868,7 +868,7 @@ func! s:FThtml()
setf xhtml
return
endif
- if getline(n) =~ '{%\s*\(extends\|block\|load\)\>'
+ if getline(n) =~ '{%\s*\(extends\|block\|load\)\>\|{#\s\+'
setf htmldjango
return
endif
@@ -1262,8 +1262,8 @@ au BufNewFile,BufRead */etc/modules.conf,*/etc/modules,*/etc/conf.modules setf m
" Mplayer config
au BufNewFile,BufRead mplayer.conf,*/.mplayer/config setf mplayerconf
-" Moterola S record
-au BufNewFile,BufRead *.s19,*.s28,*.s37 setf srec
+" Motorola S record
+au BufNewFile,BufRead *.s19,*.s28,*.s37,*.mot,*.srec setf srec
" Mrxvtrc
au BufNewFile,BufRead mrxvtrc,.mrxvtrc setf mrxvtrc
@@ -1290,7 +1290,7 @@ au BufNewFile,BufRead *.mush setf mush
au BufNewFile,BufRead Mutt{ng,}rc setf muttrc
" Nano
-au BufNewFile,BufRead */etc/nanorc,.nanorc setf nanorc
+au BufNewFile,BufRead */etc/nanorc,*.nanorc setf nanorc
" Nastran input/DMAP
"au BufNewFile,BufRead *.dat setf nastran
diff --git a/runtime/ftplugin/j.vim b/runtime/ftplugin/j.vim
index 71ac4c5418..774696836f 100644
--- a/runtime/ftplugin/j.vim
+++ b/runtime/ftplugin/j.vim
@@ -2,7 +2,7 @@
" Language: J
" Maintainer: David Bürgin <676c7473@gmail.com>
" URL: https://github.com/glts/vim-j
-" Last Change: 2015-01-11
+" Last Change: 2015-03-27
if exists('b:did_ftplugin')
finish
@@ -16,12 +16,9 @@ setlocal iskeyword=48-57,A-Z,_,a-z
setlocal comments=:NB.
setlocal commentstring=NB.\ %s
setlocal formatoptions-=t
-setlocal shiftwidth=2
-setlocal softtabstop=2
-setlocal expandtab
setlocal matchpairs=(:)
-let b:undo_ftplugin = 'setlocal matchpairs< expandtab< softtabstop< shiftwidth< formatoptions< commentstring< comments< iskeyword<'
+let b:undo_ftplugin = 'setlocal matchpairs< formatoptions< commentstring< comments< iskeyword<'
" Section movement with ]] ][ [[ []. The start/end patterns below are amended
" inside the function in order to avoid matching on the current cursor line.
diff --git a/runtime/indent/html.vim b/runtime/indent/html.vim
index b97a905988..7eb963b7b2 100644
--- a/runtime/indent/html.vim
+++ b/runtime/indent/html.vim
@@ -2,7 +2,7 @@
" Header: "{{{
" Maintainer: Bram Moolenaar
" Original Author: Andy Wokula <anwoku@yahoo.de>
-" Last Change: 2015 Jan 11
+" Last Change: 2015 Jun 12
" Version: 1.0
" Description: HTML indent script with cached state for faster indenting on a
" range of lines.
@@ -94,7 +94,7 @@ func! HtmlIndent_CheckUserSettings()
let autotags = g:html_indent_autotags
endif
let b:hi_removed_tags = {}
- if autotags
+ if len(autotags) > 0
call s:RemoveITags(b:hi_removed_tags, split(autotags, ","))
endif
@@ -245,6 +245,10 @@ call s:AddITags(s:indent_tags, [
\ 'header', 'group', 'keygen', 'mark', 'math', 'meter', 'nav', 'output',
\ 'progress', 'ruby', 'section', 'svg', 'texture', 'time', 'video',
\ 'wbr', 'text'])
+
+" Tags added for web components:
+call s:AddITags(s:indent_tags, [
+ \ 'content', 'shadow', 'template'])
"}}}
" Add Block Tags: these contain alien content
@@ -287,7 +291,7 @@ func! s:CountITags(text)
let s:nextrel = 0 " relative indent steps for next line [unit &sw]:
let s:block = 0 " assume starting outside of a block
let s:countonly = 1 " don't change state
- call substitute(a:text, '<\zs/\=\w\+\>\|<!--\|-->', '\=s:CheckTag(submatch(0))', 'g')
+ call substitute(a:text, '<\zs/\=\w\+\(-\w\+\)*\>\|<!--\|-->', '\=s:CheckTag(submatch(0))', 'g')
let s:countonly = 0
endfunc "}}}
@@ -299,7 +303,7 @@ func! s:CountTagsAndState(text)
let s:nextrel = 0 " relative indent steps for next line [unit &sw]:
let s:block = b:hi_newstate.block
- let tmp = substitute(a:text, '<\zs/\=\w\+\>\|<!--\|-->', '\=s:CheckTag(submatch(0))', 'g')
+ let tmp = substitute(a:text, '<\zs/\=\w\+\(-\w\+\)*\>\|<!--\|-->', '\=s:CheckTag(submatch(0))', 'g')
if s:block == 3
let b:hi_newstate.scripttype = s:GetScriptType(matchstr(tmp, '\C.*<SCRIPT\>\zs[^>]*'))
endif
@@ -311,6 +315,9 @@ func! s:CheckTag(itag)
"{{{
" Returns an empty string or "SCRIPT".
" a:itag can be "tag" or "/tag" or "<!--" or "-->"
+ if (s:CheckCustomTag(a:itag))
+ return ""
+ endif
let ind = s:get_tag(a:itag)
if ind == -1
" closing tag
@@ -365,6 +372,36 @@ func! s:CheckBlockTag(blocktag, ind)
return ""
endfunc "}}}
+" Used by s:CheckTag().
+func! s:CheckCustomTag(ctag)
+ "{{{
+ " Returns 1 if ctag is the tag for a custom element, 0 otherwise.
+ " a:ctag can be "tag" or "/tag" or "<!--" or "-->"
+ let pattern = '\%\(\w\+-\)\+\w\+'
+ if match(a:ctag, pattern) == -1
+ return 0
+ endif
+ if matchstr(a:ctag, '\/\ze.\+') == "/"
+ " closing tag
+ if s:block != 0
+ " ignore ctag within a block
+ return 1
+ endif
+ if s:nextrel == 0
+ let s:curind -= 1
+ else
+ let s:nextrel -= 1
+ endif
+ else
+ " opening tag
+ if s:block != 0
+ return 1
+ endif
+ let s:nextrel += 1
+ endif
+ return 1
+endfunc "}}}
+
" Return the <script> type: either "javascript" or ""
func! s:GetScriptType(str)
"{{{
diff --git a/runtime/plugin/rplugin.vim b/runtime/plugin/rplugin.vim
index 2b2d333738..879775ff0e 100644
--- a/runtime/plugin/rplugin.vim
+++ b/runtime/plugin/rplugin.vim
@@ -1,5 +1,5 @@
-if exists('loaded_remote_plugins') || &cp
+if exists('g:loaded_remote_plugins') || &cp
finish
endif
-let loaded_remote_plugins = 1
+let g:loaded_remote_plugins = 1
call remote#host#LoadRemotePlugins()
diff --git a/runtime/syntax/c.vim b/runtime/syntax/c.vim
index a520e6317f..ac4909edba 100644
--- a/runtime/syntax/c.vim
+++ b/runtime/syntax/c.vim
@@ -1,7 +1,7 @@
" Vim syntax file
" Language: C
" Maintainer: Bram Moolenaar <Bram@vim.org>
-" Last Change: 2015 Feb 27
+" Last Change: 2015 Mar 05
" Quit when a (custom) syntax file was already loaded
if exists("b:current_syntax")
@@ -47,16 +47,17 @@ if !exists("c_no_cformat")
endif
" cCppString: same as cString, but ends at end of line
-if s:ft ==# "cpp" && !exists("cpp_no_cpp11")
+if s:ft ==# "cpp" && !exists("cpp_no_cpp11") && !exists("c_no_cformat")
" ISO C++11
syn region cString start=+\(L\|u\|u8\|U\|R\|LR\|u8R\|uR\|UR\)\="+ skip=+\\\\\|\\"+ end=+"+ contains=cSpecial,cFormat,@Spell extend
syn region cCppString start=+\(L\|u\|u8\|U\|R\|LR\|u8R\|uR\|UR\)\="+ skip=+\\\\\|\\"\|\\$+ excludenl end=+"+ end='$' contains=cSpecial,cFormat,@Spell
-elseif s:ft ==# "c" && !exists("c_no_c11")
+elseif s:ft ==# "c" && !exists("c_no_c11") && !exists("c_no_cformat")
" ISO C99
syn region cString start=+\%(L\|U\|u8\)\="+ skip=+\\\\\|\\"+ end=+"+ contains=cSpecial,cFormat,@Spell extend
syn region cCppString start=+\%(L\|U\|u8\)\="+ skip=+\\\\\|\\"\|\\$+ excludenl end=+"+ end='$' contains=cSpecial,cFormat,@Spell
else
" older C or C++
+ syn match cFormat display "%%" contained
syn region cString start=+L\="+ skip=+\\\\\|\\"+ end=+"+ contains=cSpecial,cFormat,@Spell extend
syn region cCppString start=+L\="+ skip=+\\\\\|\\"\|\\$+ excludenl end=+"+ end='$' contains=cSpecial,cFormat,@Spell
endif
@@ -80,7 +81,11 @@ syn match cSpecialCharacter display "L'\\x\x\+'"
if (s:ft ==# "c" && !exists("c_no_c11")) || (s:ft ==# "cpp" && !exists("cpp_no_cpp11"))
" ISO C11 or ISO C++ 11
- syn region cString start=+\%(U\|u8\=\)"+ skip=+\\\\\|\\"+ end=+"+ contains=cSpecial,cFormat,@Spell extend
+ if exists("c_no_cformat")
+ syn region cString start=+\%(U\|u8\=\)"+ skip=+\\\\\|\\"+ end=+"+ contains=cSpecial,@Spell extend
+ else
+ syn region cString start=+\%(U\|u8\=\)"+ skip=+\\\\\|\\"+ end=+"+ contains=cSpecial,cFormat,@Spell extend
+ endif
syn match cCharacter "[Uu]'[^\\]'"
syn match cCharacter "[Uu]'[^']*'" contains=cSpecial
if exists("c_gnu")
@@ -389,8 +394,13 @@ endif
syn cluster cLabelGroup contains=cUserLabel
syn match cUserCont display "^\s*\I\i*\s*:$" contains=@cLabelGroup
syn match cUserCont display ";\s*\I\i*\s*:$" contains=@cLabelGroup
-syn match cUserCont display "^\s*\I\i*\s*:[^:]"me=e-1 contains=@cLabelGroup
-syn match cUserCont display ";\s*\I\i*\s*:[^:]"me=e-1 contains=@cLabelGroup
+if s:ft ==# 'cpp'
+ syn match cUserCont display "^\s*\%(class\|struct\|enum\)\@!\I\i*\s*:[^:]"me=e-1 contains=@cLabelGroup
+ syn match cUserCont display ";\s*\%(class\|struct\|enum\)\@!\I\i*\s*:[^:]"me=e-1 contains=@cLabelGroup
+else
+ syn match cUserCont display "^\s*\I\i*\s*:[^:]"me=e-1 contains=@cLabelGroup
+ syn match cUserCont display ";\s*\I\i*\s*:[^:]"me=e-1 contains=@cLabelGroup
+endif
syn match cUserLabel display "\I\i*" contained
diff --git a/runtime/syntax/cpp.vim b/runtime/syntax/cpp.vim
index 15f0cbb4ff..526ecbcd53 100644
--- a/runtime/syntax/cpp.vim
+++ b/runtime/syntax/cpp.vim
@@ -1,8 +1,8 @@
" Vim syntax file
" Language: C++
-" Current Maintainer: vim-jp (https://github.com/vim-jp/cpp-vim)
+" Current Maintainer: vim-jp (https://github.com/vim-jp/vim-cpp)
" Previous Maintainer: Ken Shan <ccshan@post.harvard.edu>
-" Last Change: 2014 May 14
+" Last Change: 2015 Mar 1
" For version 5.x: Clear all syntax items
" For version 6.x: Quit when a syntax file was already loaded
@@ -32,14 +32,21 @@ syn match cppCast "\<\(const\|static\|dynamic\|reinterpret\)_cast\s*$"
syn keyword cppStorageClass mutable
syn keyword cppStructure class typename template namespace
syn keyword cppBoolean true false
+syn keyword cppConstant __cplusplus
" C++ 11 extensions
if !exists("cpp_no_cpp11")
syn keyword cppType override final
syn keyword cppExceptions noexcept
- syn keyword cppStorageClass constexpr decltype
+ syn keyword cppStorageClass constexpr decltype thread_local
syn keyword cppConstant nullptr
- syn region cppRawString matchgroup=cppRawDelimiter start=+\%(u8\|[uLU]\)\=R"\z([[:alnum:]_{}[\]#<>%:;.?*\+\-/\^&|~!=,"']\{,16}\)(+ end=+)\z1"+ contains=@Spell
+ syn keyword cppConstant ATOMIC_FLAG_INIT ATOMIC_VAR_INIT
+ syn keyword cppConstant ATOMIC_BOOL_LOCK_FREE ATOMIC_CHAR_LOCK_FREE
+ syn keyword cppConstant ATOMIC_CHAR16_T_LOCK_FREE ATOMIC_CHAR32_T_LOCK_FREE
+ syn keyword cppConstant ATOMIC_WCHAR_T_LOCK_FREE ATOMIC_SHORT_LOCK_FREE
+ syn keyword cppConstant ATOMIC_INT_LOCK_FREE ATOMIC_LONG_LOCK_FREE
+ syn keyword cppConstant ATOMIC_LLONG_LOCK_FREE ATOMIC_POINTER_LOCK_FREE
+ syn region cppRawString matchgroup=cppRawDelimiter start=+\%(u8\|[uLU]\)\=R"\z([[:alnum:]_{}[\]#<>%:;.?*\+\-/\^&|~!=,"']\{,16}\)(+ end=+)\z1"+ contains=@Spell
endif
" The minimum and maximum operators in GNU C++
diff --git a/runtime/syntax/csh.vim b/runtime/syntax/csh.vim
index a67cb09189..9dc2c4ef56 100644
--- a/runtime/syntax/csh.vim
+++ b/runtime/syntax/csh.vim
@@ -1,8 +1,8 @@
" Vim syntax file
" Language: C-shell (csh)
" Maintainer: Charles E. Campbell <NdrOchipS@PcampbellAfamily.Mbiz>
-" Version: 11
" Last Change: Oct 23, 2014
+" Version: 11
" URL: http://www.drchip.org/astronaut/vim/index.html#SYNTAX_CSH
" For version 5.x: Clear all syntax items
diff --git a/runtime/syntax/groovy.vim b/runtime/syntax/groovy.vim
index c745960bd5..65dbf17728 100644
--- a/runtime/syntax/groovy.vim
+++ b/runtime/syntax/groovy.vim
@@ -4,7 +4,7 @@
" Maintainer: Tobias Rapp <yahuxo@gmx.de>
" Version: 0.1.13
" URL: http://www.vim.org/scripts/script.php?script_id=945
-" Last Change: 2013 Apr 24
+" Last Change: 2015 Apr 13
" THE ORIGINAL AUTHOR'S NOTES:
"
@@ -220,7 +220,6 @@ syn region groovyComment start="/\*" end="\*/" contains=@groovyCommen
syn match groovyCommentStar contained "^\s*\*[^/]"me=e-1
syn match groovyCommentStar contained "^\s*\*$"
syn match groovyLineComment "//.*" contains=@groovyCommentSpecial2,groovyTodo,@Spell
-syn match groovyLineComment "#.*" contains=@groovyCommentSpecial2,groovyTodo,@Spell
GroovyHiLink groovyCommentString groovyString
GroovyHiLink groovyComment2String groovyString
GroovyHiLink groovyCommentCharacter groovyCharacter
diff --git a/runtime/syntax/hex.vim b/runtime/syntax/hex.vim
index 40c655395f..40f7f0dd10 100644
--- a/runtime/syntax/hex.vim
+++ b/runtime/syntax/hex.vim
@@ -1,7 +1,29 @@
" Vim syntax file
-" Language: Intel hex MCS51
-" Maintainer: Sams Ricahrd <sams@ping.at>
-" Last Change: 2003 Apr 25
+" Language: Intel HEX
+" Maintainer: Markus Heidelberg <markus.heidelberg@web.de>
+" Previous version: Sams Ricahrd <sams@ping.at>
+" Last Change: 2015 Feb 24
+
+" Each record (line) is built as follows:
+"
+" field digits states
+"
+" +----------+
+" | start | 1 (':') hexRecStart
+" +----------+
+" | count | 2 hexDataByteCount
+" +----------+
+" | address | 4 hexNoAddress, hexDataAddress, (hexAddressFieldUnknown)
+" +----------+
+" | type | 2 hexRecType, (hexRecTypeUnknown)
+" +----------+
+" | data | 0..510 hexDataOdd, hexDataEven, hexExtendedAddress, hexStartAddress, (hexDataFieldUnknown, hexDataUnexpected)
+" +----------+
+" | checksum | 2 hexChecksum
+" +----------+
+"
+" States in parentheses in the upper format description indicate that they
+" should not appear in a valid file.
" For version 5.x: Clear all syntax items
" For version 6.x: Quit when a syntax file was already loaded
@@ -11,21 +33,39 @@ elseif exists("b:current_syntax")
finish
endif
-syn case ignore
+syn match hexRecStart "^:"
+
+syn match hexDataByteCount "^:[0-9a-fA-F]\{2}" contains=hexRecStart nextgroup=hexAddress
+
+syn match hexAddress "[0-9a-fA-F]\{4}" transparent contained nextgroup=hexRecTypeUnknown,hexRecType
+" The address field groups include the record type field in the last 2
+" characters, the proper match for highlighting follows below.
+syn match hexAddressFieldUnknown "^:[0-9a-fA-F]\{8}" contains=hexDataByteCount nextgroup=hexDataFieldUnknown,hexChecksum
+syn match hexDataAddress "^:[0-9a-fA-F]\{6}00" contains=hexDataByteCount nextgroup=hexDataOdd,hexChecksum
+syn match hexNoAddress "^:[0-9a-fA-F]\{6}01" contains=hexDataByteCount nextgroup=hexDataUnexpected,hexChecksum
+syn match hexNoAddress "^:[0-9a-fA-F]\{6}0[24]" contains=hexDataByteCount nextgroup=hexExtendedAddress
+syn match hexNoAddress "^:[0-9a-fA-F]\{6}0[35]" contains=hexDataByteCount nextgroup=hexStartAddress
+
+syn match hexRecTypeUnknown "[0-9a-fA-F]\{2}" contained
+syn match hexRecType "0[0-5]" contained
+
+syn match hexDataFieldUnknown "[0-9a-fA-F]\{2}" contained nextgroup=hexDataFieldUnknown,hexChecksum
+" alternating highlight per byte for easier reading
+syn match hexDataOdd "[0-9a-fA-F]\{2}" contained nextgroup=hexDataEven,hexChecksum
+syn match hexDataEven "[0-9a-fA-F]\{2}" contained nextgroup=hexDataOdd,hexChecksum
+" data bytes which should not exist
+syn match hexDataUnexpected "[0-9a-fA-F]\{2}" contained nextgroup=hexDataUnexpected,hexChecksum
+" Data digit pair regex usage also results in only highlighting the checksum
+" if the number of data characters is even.
-" storage types
+" special data fields
+syn match hexExtendedAddress "[0-9a-fA-F]\{4}" contained nextgroup=hexDataUnexpected,hexChecksum
+syn match hexStartAddress "[0-9a-fA-F]\{8}" contained nextgroup=hexDataUnexpected,hexChecksum
-syn match hexChecksum "[0-9a-fA-F]\{2}$"
-syn match hexAdress "^:[0-9a-fA-F]\{6}" contains=hexDataByteCount
-syn match hexRecType "^:[0-9a-fA-F]\{8}" contains=hexAdress
-syn match hexDataByteCount contained "^:[0-9a-fA-F]\{2}" contains=hexStart
-syn match hexStart contained "^:"
-syn match hexExtAdrRec "^:02000002[0-9a-fA-F]\{4}" contains=hexSpecRec
-syn match hexExtLinAdrRec "^:02000004[0-9a-fA-F]\{4}" contains=hexSpecRec
-syn match hexSpecRec contained "^:0[02]00000[124]" contains=hexStart
-syn match hexEOF "^:00000001" contains=hexStart
+syn match hexChecksum "[0-9a-fA-F]\{2}$" contained
-syn case match
+" Folding Data Records below an Extended Segment/Linear Address Record
+syn region hexExtAdrBlock start="^:[0-9a-fA-F]\{7}[24]" skip="^:[0-9a-fA-F]\{7}0" end="^:"me=s-1 fold transparent
" Define the default highlighting.
" For version 5.7 and earlier: only when not done already
@@ -38,16 +78,21 @@ if version >= 508 || !exists("did_hex_syntax_inits")
command -nargs=+ HiLink hi def link <args>
endif
- " The default methods for highlighting. Can be overridden later
- HiLink hexStart SpecialKey
- HiLink hexDataByteCount Constant
- HiLink hexAdress Comment
- HiLink hexRecType WarningMsg
- HiLink hexChecksum Search
- HiLink hexExtAdrRec hexAdress
- HiLink hexEOF hexSpecRec
- HiLink hexExtLinAdrRec hexAdress
- HiLink hexSpecRec DiffAdd
+ " The default methods for highlighting. Can be overridden later
+ HiLink hexRecStart hexRecType
+ HiLink hexDataByteCount Constant
+ hi def hexAddressFieldUnknown term=italic cterm=italic gui=italic
+ HiLink hexDataAddress Comment
+ HiLink hexNoAddress DiffAdd
+ HiLink hexRecTypeUnknown hexRecType
+ HiLink hexRecType WarningMsg
+ hi def hexDataFieldUnknown term=italic cterm=italic gui=italic
+ hi def hexDataOdd term=bold cterm=bold gui=bold
+ hi def hexDataEven term=NONE cterm=NONE gui=NONE
+ HiLink hexDataUnexpected Error
+ HiLink hexExtendedAddress hexDataAddress
+ HiLink hexStartAddress hexDataAddress
+ HiLink hexChecksum DiffChange
delcommand HiLink
endif
diff --git a/runtime/syntax/php.vim b/runtime/syntax/php.vim
index 860181e0e6..e2d73111e4 100644
--- a/runtime/syntax/php.vim
+++ b/runtime/syntax/php.vim
@@ -1,8 +1,8 @@
" Vim syntax file
" Language: php PHP 3/4/5
" Maintainer: Jason Woofenden <jason@jasonwoof.com>
-" Last Change: Sep 18, 2014
-" URL: https://gitorious.org/jasonwoof/vim-syntax/blobs/master/php.vim
+" Last Change: Mar 24, 2015
+" URL: https://jasonwoof.com/gitweb/?p=vim-syntax.git;a=blob;f=php.vim;hb=HEAD
" Former Maintainers: Peter Hodge <toomuchphp-vim@yahoo.com>
" Debian VIM Maintainers <pkg-vim-maintainers@lists.alioth.debian.org>
"
diff --git a/runtime/syntax/python.vim b/runtime/syntax/python.vim
index d2162dee5a..c608aeedeb 100644
--- a/runtime/syntax/python.vim
+++ b/runtime/syntax/python.vim
@@ -1,9 +1,8 @@
" Vim syntax file
" Language: Python
-" Maintainer: Neil Schemenauer <nas@python.ca>
-" Last Change: 2014 Jul 16
-" Credits: Zvezdan Petkovic <zpetkovic@acm.org>
-" Neil Schemenauer <nas@python.ca>
+" Maintainer: Zvezdan Petkovic <zpetkovic@acm.org>
+" Last Change: 2015 Jun 19
+" Credits: Neil Schemenauer <nas@python.ca>
" Dmitry Vasiliev
"
" This version is a major rewrite by Zvezdan Petkovic.
@@ -95,16 +94,16 @@ syn match pythonComment "#.*$" contains=pythonTodo,@Spell
syn keyword pythonTodo FIXME NOTE NOTES TODO XXX contained
" Triple-quoted strings can contain doctests.
-syn region pythonString
+syn region pythonString matchgroup=pythonQuotes
\ start=+[uU]\=\z(['"]\)+ end="\z1" skip="\\\\\|\\\z1"
\ contains=pythonEscape,@Spell
-syn region pythonString
+syn region pythonString matchgroup=pythonTripleQuotes
\ start=+[uU]\=\z('''\|"""\)+ skip=+\\["']+ end="\z1" keepend
\ contains=pythonEscape,pythonSpaceError,pythonDoctest,@Spell
-syn region pythonRawString
+syn region pythonRawString matchgroup=pythonQuotes
\ start=+[uU]\=[rR]\z(['"]\)+ end="\z1" skip="\\\\\|\\\z1"
\ contains=@Spell
-syn region pythonRawString
+syn region pythonRawString matchgroup=pythonTripleQuotes
\ start=+[uU]\=[rR]\z('''\|"""\)+ end="\z1" keepend
\ contains=pythonSpaceError,pythonDoctest,@Spell
@@ -113,7 +112,7 @@ syn match pythonEscape "\\\o\{1,3}" contained
syn match pythonEscape "\\x\x\{2}" contained
syn match pythonEscape "\%(\\u\x\{4}\|\\U\x\{8}\)" contained
" Python allows case-insensitive Unicode IDs: http://www.unicode.org/charts/
-syn match pythonEscape "\\N{.\{-}}" contained
+syn match pythonEscape "\\N{\a\+\%(\s\a\+\)*}" contained
syn match pythonEscape "\\$"
if exists("python_highlight_all")
@@ -274,6 +273,8 @@ if version >= 508 || !exists("did_python_syn_inits")
HiLink pythonTodo Todo
HiLink pythonString String
HiLink pythonRawString String
+ HiLink pythonQuotes String
+ HiLink pythonTripleQuotes pythonQuotes
HiLink pythonEscape Special
if !exists("python_no_number_highlight")
HiLink pythonNumber Number
diff --git a/runtime/syntax/sh.vim b/runtime/syntax/sh.vim
index f3218ffcb2..4087aff46e 100644
--- a/runtime/syntax/sh.vim
+++ b/runtime/syntax/sh.vim
@@ -2,8 +2,8 @@
" Language: shell (sh) Korn shell (ksh) bash (sh)
" Maintainer: Charles E. Campbell <NdrOchipS@PcampbellAfamily.Mbiz>
" Previous Maintainer: Lennart Schultz <Lennart.Schultz@ecmwf.int>
-" Last Change: Jan 08, 2015
-" Version: 134
+" Last Change: May 29, 2015
+" Version: 137
" URL: http://www.drchip.org/astronaut/vim/index.html#SYNTAX_SH
" For options and settings, please use: :help ft-sh-syntax
" This file includes many ideas from ?ric Brunet (eric.brunet@ens.fr)
@@ -17,7 +17,7 @@ elseif exists("b:current_syntax")
endif
" AFAICT "." should be considered part of the iskeyword. Using iskeywords in
-" syntax is dicey, so the following code permits the user to prevent/override
+" syntax is dicey, so the following code permits the user to
" g:sh_isk set to a string : specify iskeyword.
" g:sh_noisk exists : don't change iskeyword
" g:sh_noisk does not exist : (default) append "." to iskeyword
@@ -104,12 +104,11 @@ syn cluster shErrorList contains=shDoError,shIfError,shInError,shCaseError,shEsa
if exists("b:is_kornshell")
syn cluster ErrorList add=shDTestError
endif
-syn cluster shArithParenList contains=shArithmetic,shCaseEsac,shComment,shDeref,shDerefSimple,shDo,shEcho,shEscape,shIf,shFor,shNumber,shOperator,shPosnParm,shExSingleQuote,shExDoubleQuote,shRedir,shSingleQuote,shDoubleQuote,shStatement,shVariable,shAlias,shTest,shCtrlSeq,shSpecial,shParen,bashSpecialVariables,bashStatement
+syn cluster shArithParenList contains=shArithmetic,shCaseEsac,shComment,shDeref,shDo,shDerefSimple,shEcho,shEscape,shNumber,shOperator,shPosnParm,shExSingleQuote,shExDoubleQuote,shRedir,shSingleQuote,shDoubleQuote,shStatement,shVariable,shAlias,shTest,shCtrlSeq,shSpecial,shParen,bashSpecialVariables,bashStatement,shIf,shFor
syn cluster shArithList contains=@shArithParenList,shParenError
syn cluster shCaseEsacList contains=shCaseStart,shCase,shCaseBar,shCaseIn,shComment,shDeref,shDerefSimple,shCaseCommandSub,shCaseExSingleQuote,shCaseSingleQuote,shCaseDoubleQuote,shCtrlSeq,@shErrorList,shStringSpecial,shCaseRange
syn cluster shCaseList contains=@shCommandSubList,shCaseEsac,shColon,shCommandSub,shComment,shDo,shEcho,shExpr,shFor,shHereDoc,shIf,shRedir,shSetList,shSource,shStatement,shVariable,shCtrlSeq
-"syn cluster shColonList contains=@shCaseList
-syn cluster shCommandSubList contains=shArithmetic,shDeref,shDerefSimple,shEcho,shEscape,shNumber,shOption,shPosnParm,shExSingleQuote,shSingleQuote,shExDoubleQuote,shDoubleQuote,shStatement,shVariable,shSubSh,shAlias,shTest,shCtrlSeq,shSpecial,shCmdParenRegion
+syn cluster shCommandSubList contains=shAlias,shArithmetic,shCmdParenRegion,shCtrlSeq,shDeref,shDerefSimple,shDoubleQuote,shEcho,shEscape,shExDoubleQuote,shExpr,shExSingleQuote,shNumber,shOperator,shOption,shPosnParm,shSingleQuote,shSpecial,shStatement,shSubSh,shTest,shVariable
syn cluster shCurlyList contains=shNumber,shComma,shDeref,shDerefSimple,shDerefSpecial
syn cluster shDblQuoteList contains=shCommandSub,shDeref,shDerefSimple,shEscape,shPosnParm,shCtrlSeq,shSpecial
syn cluster shDerefList contains=shDeref,shDerefSimple,shDerefVar,shDerefSpecial,shDerefWordError,shDerefPPS
@@ -127,9 +126,9 @@ syn cluster shHereList contains=shBeginHere,shHerePayload
syn cluster shHereListDQ contains=shBeginHere,@shDblQuoteList,shHerePayload
syn cluster shIdList contains=shCommandSub,shWrapLineOperator,shSetOption,shDeref,shDerefSimple,shRedir,shExSingleQuote,shExDoubleQuote,shSingleQuote,shDoubleQuote,shExpr,shCtrlSeq,shStringSpecial,shAtExpr
syn cluster shIfList contains=@shLoopList,shDblBrace,shDblParen,shFunctionKey,shFunctionOne,shFunctionTwo
-syn cluster shLoopList contains=@shCaseList,shIf,shFor,shForPP,shTestOpr,shExpr,shDblBrace,shConditional,shCaseEsac,shTest,@shErrorList,shSet,shOption
+syn cluster shLoopList contains=@shCaseList,@shErrorList,shCaseEsac,shConditional,shDblBrace,shExpr,shFor,shForPP,shIf,shOption,shSet,shTest,shTestOpr
syn cluster shSubShList contains=@shCommandSubList,shCaseEsac,shColon,shCommandSub,shComment,shDo,shEcho,shExpr,shFor,shIf,shRedir,shSetList,shSource,shStatement,shVariable,shCtrlSeq,shOperator
-syn cluster shTestList contains=shCharClass,shComment,shCommandSub,shDeref,shDerefSimple,shExDoubleQuote,shDoubleQuote,shExpr,shNumber,shOperator,shExSingleQuote,shSingleQuote,shTestOpr,shTest,shCtrlSeq
+syn cluster shTestList contains=shCharClass,shCommandSub,shComment,shCtrlSeq,shDeref,shDerefSimple,shDoubleQuote,shExDoubleQuote,shExpr,shExSingleQuote,shNumber,shOperator,shSingleQuote,shTest,shTestOpr
" Echo: {{{1
" ====
" This one is needed INSIDE a CommandSub, so that `echo bla` be correct
@@ -182,7 +181,7 @@ syn match shRedir "\d<<-\="
syn match shOperator "<<\|>>" contained
syn match shOperator "[!&;|]" contained
syn match shOperator "\[[[^:]\|\]]" contained
-syn match shOperator "!\==" skipwhite nextgroup=shPattern
+syn match shOperator "[-=/*+%]\==" skipwhite nextgroup=shPattern
syn match shPattern "\<\S\+\())\)\@=" contained contains=shExSingleQuote,shSingleQuote,shExDoubleQuote,shDoubleQuote,shDeref
" Subshells: {{{1
@@ -194,16 +193,15 @@ syn region shSubSh transparent matchgroup=shSubShRegion start="[^(]\zs(" end=")"
"=======
syn region shExpr matchgroup=shRange start="\[" skip=+\\\\\|\\$\|\[+ end="\]" contains=@shTestList,shSpecial
syn region shTest transparent matchgroup=shStatement start="\<test\s" skip=+\\\\\|\\$+ matchgroup=NONE end="[;&|]"me=e-1 end="$" contains=@shExprList1
+syn match shTestOpr contained '[^-+/%]\zs=' skipwhite nextgroup=shTestDoubleQuote,shTestSingleQuote,shTestPattern
syn match shTestOpr contained "<=\|>=\|!=\|==\|-.\>\|-\(nt\|ot\|ef\|eq\|ne\|lt\|le\|gt\|ge\)\>\|[!<>]"
-syn match shTestOpr contained '=' skipwhite nextgroup=shTestDoubleQuote,shTestSingleQuote,shTestPattern
syn match shTestPattern contained '\w\+'
-syn region shTestDoubleQuote contained start='"' skip='\\"' end='"' contains=shBQpairs
+syn region shTestDoubleQuote contained start='\%(\%(\\\\\)*\\\)\@<!"' skip=+\\\\\|\\"+ end='"'
syn match shTestSingleQuote contained '\\.'
syn match shTestSingleQuote contained "'[^']*'"
-syn match shBQpairs contained '\\\\'
if exists("b:is_kornshell") || exists("b:is_bash")
- syn region shDblBrace matchgroup=Delimiter start="\[\[" skip=+\\\\\|\\$+ end="\]\]" contains=@shTestList
- syn region shDblParen matchgroup=Delimiter start="((" skip=+\\\\\|\\$+ end="))" contains=@shTestList
+ syn region shDblBrace matchgroup=Delimiter start="\[\[" skip=+\\\\\|\\$+ end="\]\]" contains=@shTestList,shComment
+ syn region shDblParen matchgroup=Delimiter start="((" skip=+\\\\\|\\$+ end="))" contains=@shTestList,shComment
endif
" Character Class In Range: {{{1
@@ -213,15 +211,16 @@ syn match shCharClass contained "\[:\(backspace\|escape\|return\|xdigit\|alnum
" Loops: do, if, while, until {{{1
" ======
if s:sh_fold_ifdofor
- syn region shDo fold transparent matchgroup=shConditional start="\<do\>" matchgroup=shConditional end="\<done\>" contains=@shLoopList
- syn region shIf fold transparent matchgroup=shConditional start="\<if\_s" matchgroup=shConditional skip=+-fi\>+ end="\<;\_s*then\>" end="\<fi\>" contains=@shIfList
- syn region shFor fold matchgroup=shLoop start="\<for\ze\_s\s*\%(((\)\@!" end="\<in\_s" end="\<do\>"me=e-2 contains=@shLoopList,shDblParen skipwhite nextgroup=shCurlyIn
+ syn region shDo fold transparent matchgroup=shConditional start="\<do\>" matchgroup=shConditional end="\<done\>" contains=@shLoopList
+ syn region shIf fold transparent matchgroup=shConditional start="\<if\_s" matchgroup=shConditional skip=+-fi\>+ end="\<;\_s*then\>" end="\<fi\>" contains=@shIfList
+ syn region shFor fold matchgroup=shLoop start="\<for\ze\_s\s*\%(((\)\@!" end="\<in\_s" end="\<do\>"me=e-2 contains=@shLoopList,shDblParen skipwhite nextgroup=shCurlyIn
+ syn region shForPP fold matchgroup=shLoop start='\<for\>\_s*((' end='))' contains=shTestOpr
else
- syn region shDo transparent matchgroup=shConditional start="\<do\>" matchgroup=shConditional end="\<done\>" contains=@shLoopList
- syn region shIf transparent matchgroup=shConditional start="\<if\_s" matchgroup=shConditional skip=+-fi\>+ end="\<;\_s*then\>" end="\<fi\>" contains=@shIfList
- syn region shFor matchgroup=shLoop start="\<for\ze\_s\s*\%(((\)\@!" end="\<in\>" end="\<do\>"me=e-2 contains=@shLoopList,shDblParen skipwhite nextgroup=shCurlyIn
+ syn region shDo transparent matchgroup=shConditional start="\<do\>" matchgroup=shConditional end="\<done\>" contains=@shLoopList
+ syn region shIf transparent matchgroup=shConditional start="\<if\_s" matchgroup=shConditional skip=+-fi\>+ end="\<;\_s*then\>" end="\<fi\>" contains=@shIfList
+ syn region shFor matchgroup=shLoop start="\<for\ze\_s\s*\%(((\)\@!" end="\<in\>" end="\<do\>"me=e-2 contains=@shLoopList,shDblParen skipwhite nextgroup=shCurlyIn
+ syn region shForPP matchgroup=shLoop start='\<for\>\_s*((' end='))' contains=shTestOpr
endif
-syn region shForPP matchgroup=shLoop start='\<for\>\_s*((' end='))' contains=shTestOpr
if exists("b:is_kornshell") || exists("b:is_bash")
syn cluster shCaseList add=shRepeat
syn cluster shFunctionList add=shRepeat
@@ -322,12 +321,13 @@ elseif !exists("g:sh_no_error")
endif
syn region shSingleQuote matchgroup=shQuote start=+'+ end=+'+ contains=@Spell
syn region shDoubleQuote matchgroup=shQuote start=+\%(\%(\\\\\)*\\\)\@<!"+ skip=+\\"+ end=+"+ contains=@shDblQuoteList,shStringSpecial,@Spell
-"syn region shDoubleQuote matchgroup=shQuote start=+"+ skip=+\\"+ end=+"+ contains=@shDblQuoteList,shStringSpecial,@Spell
-syn match shStringSpecial "[^[:print:] \t]" contained
+syn region shDoubleQuote matchgroup=shQuote start=+"+ skip=+\\"+ end=+"+ contains=@shDblQuoteList,shStringSpecial,@Spell
+syn match shStringSpecial "[^[:print:] \t]" contained
syn match shStringSpecial "\%(\\\\\)*\\[\\"'`$()#]"
-syn match shSpecial "[^\\]\zs\%(\\\\\)*\\[\\"'`$()#]" nextgroup=shMoreSpecial,shComment
-syn match shSpecial "^\%(\\\\\)*\\[\\"'`$()#]" nextgroup=shComment
-syn match shMoreSpecial "\%(\\\\\)*\\[\\"'`$()#]" nextgroup=shMoreSpecial contained
+" COMBAK: why is ,shComment on next line???
+syn match shSpecial "[^\\]\zs\%(\\\\\)*\\[\\"'`$()#]" nextgroup=shMoreSpecial,shComment
+syn match shSpecial "^\%(\\\\\)*\\[\\"'`$()#]" nextgroup=shComment
+syn match shMoreSpecial "\%(\\\\\)*\\[\\"'`$()#]" nextgroup=shMoreSpecial contained
" Comments: {{{1
"==========
@@ -341,42 +341,42 @@ syn match shQuickComment contained "#.*$"
" Here Documents: {{{1
" =========================================
if version < 600
- syn region shHereDoc matchgroup=shRedir01 start="<<\s*\**END[a-zA-Z_0-9]*\**" matchgroup=shRedir01 end="^END[a-zA-Z_0-9]*$" contains=@shDblQuoteList
- syn region shHereDoc matchgroup=shRedir02 start="<<-\s*\**END[a-zA-Z_0-9]*\**" matchgroup=shRedir02 end="^\s*END[a-zA-Z_0-9]*$" contains=@shDblQuoteList
- syn region shHereDoc matchgroup=shRedir03 start="<<\s*\**EOF\**" matchgroup=shRedir03 end="^EOF$" contains=@shDblQuoteList
- syn region shHereDoc matchgroup=shRedir04 start="<<-\s*\**EOF\**" matchgroup=shRedir04 end="^\s*EOF$" contains=@shDblQuoteList
- syn region shHereDoc matchgroup=shRedir05 start="<<\s*\**\.\**" matchgroup=shRedir05 end="^\.$" contains=@shDblQuoteList
- syn region shHereDoc matchgroup=shRedir06 start="<<-\s*\**\.\**" matchgroup=shRedir06 end="^\s*\.$" contains=@shDblQuoteList
+ syn region shHereDoc matchgroup=shHereDoc01 start="<<\s*\**END[a-zA-Z_0-9]*\**" matchgroup=shHereDoc01 end="^END[a-zA-Z_0-9]*$" contains=@shDblQuoteList
+ syn region shHereDoc matchgroup=shHereDoc02 start="<<-\s*\**END[a-zA-Z_0-9]*\**" matchgroup=shHereDoc02 end="^\s*END[a-zA-Z_0-9]*$" contains=@shDblQuoteList
+ syn region shHereDoc matchgroup=shHereDoc03 start="<<\s*\**EOF\**" matchgroup=shHereDoc03 end="^EOF$" contains=@shDblQuoteList
+ syn region shHereDoc matchgroup=shHereDoc04 start="<<-\s*\**EOF\**" matchgroup=shHereDoc04 end="^\s*EOF$" contains=@shDblQuoteList
+ syn region shHereDoc matchgroup=shHereDoc05 start="<<\s*\**\.\**" matchgroup=shHereDoc05 end="^\.$" contains=@shDblQuoteList
+ syn region shHereDoc matchgroup=shHereDoc06 start="<<-\s*\**\.\**" matchgroup=shHereDoc06 end="^\s*\.$" contains=@shDblQuoteList
elseif s:sh_fold_heredoc
- syn region shHereDoc matchgroup=shRedir07 fold start="<<\s*\z([^ \t|]*\)" matchgroup=shRedir07 end="^\z1\s*$" contains=@shDblQuoteList
- syn region shHereDoc matchgroup=shRedir08 fold start="<<\s*\"\z([^ \t|]*\)\"" matchgroup=shRedir08 end="^\z1\s*$"
- syn region shHereDoc matchgroup=shRedir09 fold start="<<\s*'\z([^ \t|]*\)'" matchgroup=shRedir09 end="^\z1\s*$"
- syn region shHereDoc matchgroup=shRedir10 fold start="<<-\s*\z([^ \t|]*\)" matchgroup=shRedir10 end="^\s*\z1\s*$" contains=@shDblQuoteList
- syn region shHereDoc matchgroup=shRedir11 fold start="<<-\s*\"\z([^ \t|]*\)\"" matchgroup=shRedir11 end="^\s*\z1\s*$"
- syn region shHereDoc matchgroup=shRedir12 fold start="<<-\s*'\z([^ \t|]*\)'" matchgroup=shRedir12 end="^\s*\z1\s*$"
- syn region shHereDoc matchgroup=shRedir13 fold start="<<\s*\\\_$\_s*\z([^ \t|]*\)" matchgroup=shRedir13 end="^\z1\s*$"
- syn region shHereDoc matchgroup=shRedir14 fold start="<<\s*\\\_$\_s*\"\z([^ \t|]*\)\"" matchgroup=shRedir14 end="^\z1\s*$"
- syn region shHereDoc matchgroup=shRedir15 fold start="<<-\s*\\\_$\_s*'\z([^ \t|]*\)'" matchgroup=shRedir15 end="^\s*\z1\s*$"
- syn region shHereDoc matchgroup=shRedir16 fold start="<<-\s*\\\_$\_s*\z([^ \t|]*\)" matchgroup=shRedir16 end="^\s*\z1\s*$"
- syn region shHereDoc matchgroup=shRedir17 fold start="<<-\s*\\\_$\_s*\"\z([^ \t|]*\)\"" matchgroup=shRedir17 end="^\s*\z1\s*$"
- syn region shHereDoc matchgroup=shRedir18 fold start="<<\s*\\\_$\_s*'\z([^ \t|]*\)'" matchgroup=shRedir18 end="^\z1\s*$"
- syn region shHereDoc matchgroup=shRedir19 fold start="<<\\\z([^ \t|]*\)" matchgroup=shRedir19 end="^\z1\s*$"
+ syn region shHereDoc matchgroup=shHereDoc07 fold start="<<\s*\z([^ \t|]*\)" matchgroup=shHereDoc07 end="^\z1\s*$" contains=@shDblQuoteList
+ syn region shHereDoc matchgroup=shHereDoc08 fold start="<<\s*\"\z([^ \t|]*\)\"" matchgroup=shHereDoc08 end="^\z1\s*$"
+ syn region shHereDoc matchgroup=shHereDoc09 fold start="<<\s*'\z([^ \t|]*\)'" matchgroup=shHereDoc09 end="^\z1\s*$"
+ syn region shHereDoc matchgroup=shHereDoc10 fold start="<<-\s*\z([^ \t|]*\)" matchgroup=shHereDoc10 end="^\s*\z1\s*$" contains=@shDblQuoteList
+ syn region shHereDoc matchgroup=shHereDoc11 fold start="<<-\s*\"\z([^ \t|]*\)\"" matchgroup=shHereDoc11 end="^\s*\z1\s*$"
+ syn region shHereDoc matchgroup=shHereDoc12 fold start="<<-\s*'\z([^ \t|]*\)'" matchgroup=shHereDoc12 end="^\s*\z1\s*$"
+ syn region shHereDoc matchgroup=shHereDoc13 fold start="<<\s*\\\_$\_s*\z([^ \t|]*\)" matchgroup=shHereDoc13 end="^\z1\s*$"
+ syn region shHereDoc matchgroup=shHereDoc14 fold start="<<\s*\\\_$\_s*\"\z([^ \t|]*\)\"" matchgroup=shHereDoc14 end="^\z1\s*$"
+ syn region shHereDoc matchgroup=shHereDoc15 fold start="<<-\s*\\\_$\_s*'\z([^ \t|]*\)'" matchgroup=shHereDoc15 end="^\s*\z1\s*$"
+ syn region shHereDoc matchgroup=shHereDoc16 fold start="<<-\s*\\\_$\_s*\z([^ \t|]*\)" matchgroup=shHereDoc16 end="^\s*\z1\s*$"
+ syn region shHereDoc matchgroup=shHereDoc17 fold start="<<-\s*\\\_$\_s*\"\z([^ \t|]*\)\"" matchgroup=shHereDoc17 end="^\s*\z1\s*$"
+ syn region shHereDoc matchgroup=shHereDoc18 fold start="<<\s*\\\_$\_s*'\z([^ \t|]*\)'" matchgroup=shHereDoc18 end="^\z1\s*$"
+ syn region shHereDoc matchgroup=shHereDoc19 fold start="<<\\\z([^ \t|]*\)" matchgroup=shHereDoc19 end="^\z1\s*$"
else
- syn region shHereDoc matchgroup=shRedir20 start="<<\s*\\\=\z([^ \t|]*\)" matchgroup=shRedir20 end="^\z1\s*$" contains=@shDblQuoteList
- syn region shHereDoc matchgroup=shRedir21 start="<<\s*\"\z([^ \t|]*\)\"" matchgroup=shRedir21 end="^\z1\s*$"
- syn region shHereDoc matchgroup=shRedir22 start="<<-\s*\z([^ \t|]*\)" matchgroup=shRedir22 end="^\s*\z1\s*$" contains=@shDblQuoteList
- syn region shHereDoc matchgroup=shRedir23 start="<<-\s*'\z([^ \t|]*\)'" matchgroup=shRedir23 end="^\s*\z1\s*$"
- syn region shHereDoc matchgroup=shRedir24 start="<<\s*'\z([^ \t|]*\)'" matchgroup=shRedir24 end="^\z1\s*$"
- syn region shHereDoc matchgroup=shRedir25 start="<<-\s*\"\z([^ \t|]*\)\"" matchgroup=shRedir25 end="^\s*\z1\s*$"
- syn region shHereDoc matchgroup=shRedir26 start="<<\s*\\\_$\_s*\z([^ \t|]*\)" matchgroup=shRedir26 end="^\z1\s*$"
- syn region shHereDoc matchgroup=shRedir27 start="<<-\s*\\\_$\_s*\z([^ \t|]*\)" matchgroup=shRedir27 end="^\s*\z1\s*$"
- syn region shHereDoc matchgroup=shRedir28 start="<<-\s*\\\_$\_s*'\z([^ \t|]*\)'" matchgroup=shRedir28 end="^\s*\z1\s*$"
- syn region shHereDoc matchgroup=shRedir29 start="<<\s*\\\_$\_s*'\z([^ \t|]*\)'" matchgroup=shRedir29 end="^\z1\s*$"
- syn region shHereDoc matchgroup=shRedir30 start="<<\s*\\\_$\_s*\"\z([^ \t|]*\)\"" matchgroup=shRedir30 end="^\z1\s*$"
- syn region shHereDoc matchgroup=shRedir31 start="<<-\s*\\\_$\_s*\"\z([^ \t|]*\)\"" matchgroup=shRedir31 end="^\s*\z1\s*$"
- syn region shHereDoc matchgroup=shRedir32 start="<<\\\z([^ \t|]*\)" matchgroup=shRedir32 end="^\z1\s*$"
+ syn region shHereDoc matchgroup=shHereDoc20 start="<<\s*\\\=\z([^ \t|]*\)" matchgroup=shHereDoc20 end="^\z1\s*$" contains=@shDblQuoteList
+ syn region shHereDoc matchgroup=shHereDoc21 start="<<\s*\"\z([^ \t|]*\)\"" matchgroup=shHereDoc21 end="^\z1\s*$"
+ syn region shHereDoc matchgroup=shHereDoc22 start="<<-\s*\z([^ \t|]*\)" matchgroup=shHereDoc22 end="^\s*\z1\s*$" contains=@shDblQuoteList
+ syn region shHereDoc matchgroup=shHereDoc23 start="<<-\s*'\z([^ \t|]*\)'" matchgroup=shHereDoc23 end="^\s*\z1\s*$"
+ syn region shHereDoc matchgroup=shHereDoc24 start="<<\s*'\z([^ \t|]*\)'" matchgroup=shHereDoc24 end="^\z1\s*$"
+ syn region shHereDoc matchgroup=shHereDoc25 start="<<-\s*\"\z([^ \t|]*\)\"" matchgroup=shHereDoc25 end="^\s*\z1\s*$"
+ syn region shHereDoc matchgroup=shHereDoc26 start="<<\s*\\\_$\_s*\z([^ \t|]*\)" matchgroup=shHereDoc26 end="^\z1\s*$"
+ syn region shHereDoc matchgroup=shHereDoc27 start="<<-\s*\\\_$\_s*\z([^ \t|]*\)" matchgroup=shHereDoc27 end="^\s*\z1\s*$"
+ syn region shHereDoc matchgroup=shHereDoc28 start="<<-\s*\\\_$\_s*'\z([^ \t|]*\)'" matchgroup=shHereDoc28 end="^\s*\z1\s*$"
+ syn region shHereDoc matchgroup=shHereDoc29 start="<<\s*\\\_$\_s*'\z([^ \t|]*\)'" matchgroup=shHereDoc29 end="^\z1\s*$"
+ syn region shHereDoc matchgroup=shHereDoc30 start="<<\s*\\\_$\_s*\"\z([^ \t|]*\)\"" matchgroup=shHereDoc30 end="^\z1\s*$"
+ syn region shHereDoc matchgroup=shHereDoc31 start="<<-\s*\\\_$\_s*\"\z([^ \t|]*\)\"" matchgroup=shHereDoc31 end="^\s*\z1\s*$"
+ syn region shHereDoc matchgroup=shHereDoc32 start="<<\\\z([^ \t|]*\)" matchgroup=shHereDoc32 end="^\z1\s*$"
endif
" Here Strings: {{{1
@@ -389,8 +389,8 @@ endif
" Identifiers: {{{1
"=============
syn match shSetOption "\s\zs[-+][a-zA-Z0-9]\+\>" contained
-syn match shVariable "\<\([bwglsav]:\)\=[a-zA-Z0-9.!@_%+,]*\ze=" nextgroup=shSetIdentifier
-syn match shSetIdentifier "=" contained nextgroup=shCmdParenRegion,shPattern,shDeref,shDerefSimple,shDoubleQuote,shExDoubleQuote,shSingleQuote,shExSingleQuote
+syn match shVariable "\<\([bwglsav]:\)\=[a-zA-Z0-9.!@_%+,]*\ze=" nextgroup=shVarAssign
+syn match shVarAssign "=" contained nextgroup=shCmdParenRegion,shPattern,shDeref,shDerefSimple,shDoubleQuote,shExDoubleQuote,shSingleQuote,shExSingleQuote
syn region shAtExpr contained start="@(" end=")" contains=@shIdList
if exists("b:is_bash")
syn region shSetList oneline matchgroup=shSet start="\<\(declare\|typeset\|local\|export\|unset\)\>\ze[^/]" end="$" matchgroup=shSetListDelim end="\ze[}|);&]" matchgroup=NONE end="\ze\s\+#\|=" contains=@shIdList
@@ -409,19 +409,27 @@ endif
if exists("b:is_bash")
if s:sh_fold_functions
- syn region shFunctionOne fold matchgroup=shFunction start="^\s*\h[-a-zA-Z_0-9]*\s*()\_s*{" end="}" contains=@shFunctionList skipwhite skipnl nextgroup=shFunctionStart,shQuickComment
- syn region shFunctionTwo fold matchgroup=shFunction start="\h[-a-zA-Z_0-9]*\s*\%(()\)\=\_s*{" end="}" contains=shFunctionKey,@shFunctionList contained skipwhite skipnl nextgroup=shFunctionStart,shQuickComment
+ syn region shFunctionOne fold matchgroup=shFunction start="^\s*\h[-a-zA-Z_0-9]*\s*()\_s*{" end="}" contains=@shFunctionList skipwhite skipnl nextgroup=shFunctionStart,shQuickComment
+ syn region shFunctionTwo fold matchgroup=shFunction start="\h[-a-zA-Z_0-9]*\s*\%(()\)\=\_s*{" end="}" contains=shFunctionKey,@shFunctionList contained skipwhite skipnl nextgroup=shFunctionStart,shQuickComment
+ syn region shFunctionThree fold matchgroup=shFunction start="^\s*\h[-a-zA-Z_0-9]*\s*()\_s*(" end=")" contains=@shFunctionList skipwhite skipnl nextgroup=shFunctionStart,shQuickComment
+ syn region shFunctionFour fold matchgroup=shFunction start="\h[-a-zA-Z_0-9]*\s*\%(()\)\=\_s*)" end=")" contains=shFunctionKey,@shFunctionList contained skipwhite skipnl nextgroup=shFunctionStart,shQuickComment
else
- syn region shFunctionOne matchgroup=shFunction start="^\s*\h[-a-zA-Z_0-9]*\s*()\_s*{" end="}" contains=@shFunctionList
- syn region shFunctionTwo matchgroup=shFunction start="\h[-a-zA-Z_0-9]*\s*\%(()\)\=\_s*{" end="}" contains=shFunctionKey,@shFunctionList contained
+ syn region shFunctionOne matchgroup=shFunction start="^\s*\h[-a-zA-Z_0-9]*\s*()\_s*{" end="}" contains=@shFunctionList
+ syn region shFunctionTwo matchgroup=shFunction start="\h[-a-zA-Z_0-9]*\s*\%(()\)\=\_s*{" end="}" contains=shFunctionKey,@shFunctionList contained
+ syn region shFunctionThree matchgroup=shFunction start="^\s*\h[-a-zA-Z_0-9]*\s*()\_s*(" end=")" contains=@shFunctionList
+ syn region shFunctionFour matchgroup=shFunction start="\h[-a-zA-Z_0-9]*\s*\%(()\)\=\_s*(" end=")" contains=shFunctionKey,@shFunctionList contained
endif
else
if s:sh_fold_functions
- syn region shFunctionOne fold matchgroup=shFunction start="^\s*\h\w*\s*()\_s*{" end="}" contains=@shFunctionList skipwhite skipnl nextgroup=shFunctionStart,shQuickComment
- syn region shFunctionTwo fold matchgroup=shFunction start="\h\w*\s*\%(()\)\=\_s*{" end="}" contains=shFunctionKey,@shFunctionList contained skipwhite skipnl nextgroup=shFunctionStart,shQuickComment
+ syn region shFunctionOne fold matchgroup=shFunction start="^\s*\h\w*\s*()\_s*{" end="}" contains=@shFunctionList skipwhite skipnl nextgroup=shFunctionStart,shQuickComment
+ syn region shFunctionTwo fold matchgroup=shFunction start="\h\w*\s*\%(()\)\=\_s*{" end="}" contains=shFunctionKey,@shFunctionList contained skipwhite skipnl nextgroup=shFunctionStart,shQuickComment
+ syn region shFunctionThree fold matchgroup=shFunction start="^\s*\h\w*\s*()\_s*(" end=")" contains=@shFunctionList skipwhite skipnl nextgroup=shFunctionStart,shQuickComment
+ syn region shFunctionFour fold matchgroup=shFunction start="\h\w*\s*\%(()\)\=\_s*(" end=")" contains=shFunctionKey,@shFunctionList contained skipwhite skipnl nextgroup=shFunctionStart,shQuickComment
else
- syn region shFunctionOne matchgroup=shFunction start="^\s*\h\w*\s*()\_s*{" end="}" contains=@shFunctionList
- syn region shFunctionTwo matchgroup=shFunction start="\h\w*\s*\%(()\)\=\_s*{" end="}" contains=shFunctionKey,@shFunctionList contained
+ syn region shFunctionOne matchgroup=shFunction start="^\s*\h\w*\s*()\_s*{" end="}" contains=@shFunctionList
+ syn region shFunctionTwo matchgroup=shFunction start="\h\w*\s*\%(()\)\=\_s*{" end="}" contains=shFunctionKey,@shFunctionList contained
+ syn region shFunctionThree matchgroup=shFunction start="^\s*\h\w*\s*()\_s*(" end=")" contains=@shFunctionList
+ syn region shFunctionFour matchgroup=shFunction start="\h\w*\s*\%(()\)\=\_s*(" end=")" contains=shFunctionKey,@shFunctionList contained
endif
endif
@@ -577,7 +585,7 @@ hi def link shDoubleQuote shString
hi def link shEcho shString
hi def link shEchoDelim shOperator
hi def link shEchoQuote shString
-"hi def link shForPP shLoop
+hi def link shForPP shLoop
hi def link shEmbeddedEcho shString
hi def link shEscape shCommandSub
hi def link shExDoubleQuote shDoubleQuote
@@ -604,7 +612,6 @@ hi def link shTestOpr shConditional
hi def link shTestPattern shString
hi def link shTestDoubleQuote shString
hi def link shTestSingleQuote shString
-hi def link shBQpairs shString
hi def link shVariable shSetList
hi def link shWrapLineOperator shOperator
@@ -661,38 +668,38 @@ hi def link shStatement Statement
hi def link shString String
hi def link shTodo Todo
hi def link shAlias Identifier
-hi def link shRedir01 shRedir
-hi def link shRedir02 shRedir
-hi def link shRedir03 shRedir
-hi def link shRedir04 shRedir
-hi def link shRedir05 shRedir
-hi def link shRedir06 shRedir
-hi def link shRedir07 shRedir
-hi def link shRedir08 shRedir
-hi def link shRedir09 shRedir
-hi def link shRedir10 shRedir
-hi def link shRedir11 shRedir
-hi def link shRedir12 shRedir
-hi def link shRedir13 shRedir
-hi def link shRedir14 shRedir
-hi def link shRedir15 shRedir
-hi def link shRedir16 shRedir
-hi def link shRedir17 shRedir
-hi def link shRedir18 shRedir
-hi def link shRedir19 shRedir
-hi def link shRedir20 shRedir
-hi def link shRedir21 shRedir
-hi def link shRedir22 shRedir
-hi def link shRedir23 shRedir
-hi def link shRedir24 shRedir
-hi def link shRedir25 shRedir
-hi def link shRedir26 shRedir
-hi def link shRedir27 shRedir
-hi def link shRedir28 shRedir
-hi def link shRedir29 shRedir
-hi def link shRedir30 shRedir
-hi def link shRedir31 shRedir
-hi def link shRedir32 shRedir
+hi def link shHereDoc01 shRedir
+hi def link shHereDoc02 shRedir
+hi def link shHereDoc03 shRedir
+hi def link shHereDoc04 shRedir
+hi def link shHereDoc05 shRedir
+hi def link shHereDoc06 shRedir
+hi def link shHereDoc07 shRedir
+hi def link shHereDoc08 shRedir
+hi def link shHereDoc09 shRedir
+hi def link shHereDoc10 shRedir
+hi def link shHereDoc11 shRedir
+hi def link shHereDoc12 shRedir
+hi def link shHereDoc13 shRedir
+hi def link shHereDoc14 shRedir
+hi def link shHereDoc15 shRedir
+hi def link shHereDoc16 shRedir
+hi def link shHereDoc17 shRedir
+hi def link shHereDoc18 shRedir
+hi def link shHereDoc19 shRedir
+hi def link shHereDoc20 shRedir
+hi def link shHereDoc21 shRedir
+hi def link shHereDoc22 shRedir
+hi def link shHereDoc23 shRedir
+hi def link shHereDoc24 shRedir
+hi def link shHereDoc25 shRedir
+hi def link shHereDoc26 shRedir
+hi def link shHereDoc27 shRedir
+hi def link shHereDoc28 shRedir
+hi def link shHereDoc29 shRedir
+hi def link shHereDoc30 shRedir
+hi def link shHereDoc31 shRedir
+hi def link shHereDoc32 shRedir
" Set Current Syntax: {{{1
" ===================
diff --git a/runtime/syntax/sm.vim b/runtime/syntax/sm.vim
index ad96cdb3b5..8fdc14b71a 100644
--- a/runtime/syntax/sm.vim
+++ b/runtime/syntax/sm.vim
@@ -1,8 +1,8 @@
" Vim syntax file
" Language: sendmail
" Maintainer: Charles E. Campbell <NdrOchipS@PcampbellAfamily.Mbiz>
-" Last Change: Jan 13, 2015
-" Version: 6
+" Last Change: Oct 23, 2014
+" Version: 7
" URL: http://www.drchip.org/astronaut/vim/index.html#SYNTAX_SM
if exists("b:current_syntax")
diff --git a/runtime/syntax/srec.vim b/runtime/syntax/srec.vim
new file mode 100644
index 0000000000..19b6d97426
--- /dev/null
+++ b/runtime/syntax/srec.vim
@@ -0,0 +1,96 @@
+" Vim syntax file
+" Language: Motorola S-Record
+" Maintainer: Markus Heidelberg <markus.heidelberg@web.de>
+" Last Change: 2015 Feb 24
+
+" Each record (line) is built as follows:
+"
+" field digits states
+"
+" +----------+
+" | start | 1 ('S') srecRecStart
+" +----------+
+" | type | 1 srecRecType, (srecRecTypeUnknown)
+" +----------+
+" | count | 2 srecByteCount
+" +----------+
+" | address | 4/6/8 srecNoAddress, srecDataAddress, srecRecCount, srecStartAddress, (srecAddressFieldUnknown)
+" +----------+
+" | data | 0..504/502/500 srecDataOdd, srecDataEven, (srecDataUnexpected)
+" +----------+
+" | checksum | 2 srecChecksum
+" +----------+
+"
+" States in parentheses in the upper format description indicate that they
+" should not appear in a valid file.
+
+" For version 5.x: Clear all syntax items
+" For version 6.x: Quit when a syntax file was already loaded
+if version < 600
+ syntax clear
+elseif exists("b:current_syntax")
+ finish
+endif
+
+syn match srecRecStart "^S"
+
+syn match srecRecTypeUnknown "^S." contains=srecRecStart
+syn match srecRecType "^S[0-35-9]" contains=srecRecStart
+
+syn match srecByteCount "^S.[0-9a-fA-F]\{2}" contains=srecRecTypeUnknown nextgroup=srecAddressFieldUnknown,srecChecksum
+syn match srecByteCount "^S[0-35-9][0-9a-fA-F]\{2}" contains=srecRecType
+
+syn match srecAddressFieldUnknown "[0-9a-fA-F]\{2}" contained nextgroup=srecAddressFieldUnknown,srecChecksum
+
+syn match srecNoAddress "^S0[0-9a-fA-F]\{6}" contains=srecByteCount nextgroup=srecDataOdd,srecChecksum
+syn match srecDataAddress "^S1[0-9a-fA-F]\{6}" contains=srecByteCount nextgroup=srecDataOdd,srecChecksum
+syn match srecDataAddress "^S2[0-9a-fA-F]\{8}" contains=srecByteCount nextgroup=srecDataOdd,srecChecksum
+syn match srecDataAddress "^S3[0-9a-fA-F]\{10}" contains=srecByteCount nextgroup=srecDataOdd,srecChecksum
+syn match srecRecCount "^S5[0-9a-fA-F]\{6}" contains=srecByteCount nextgroup=srecDataUnexpected,srecChecksum
+syn match srecRecCount "^S6[0-9a-fA-F]\{8}" contains=srecByteCount nextgroup=srecDataUnexpected,srecChecksum
+syn match srecStartAddress "^S7[0-9a-fA-F]\{10}" contains=srecByteCount nextgroup=srecDataUnexpected,srecChecksum
+syn match srecStartAddress "^S8[0-9a-fA-F]\{8}" contains=srecByteCount nextgroup=srecDataUnexpected,srecChecksum
+syn match srecStartAddress "^S9[0-9a-fA-F]\{6}" contains=srecByteCount nextgroup=srecDataUnexpected,srecChecksum
+
+" alternating highlight per byte for easier reading
+syn match srecDataOdd "[0-9a-fA-F]\{2}" contained nextgroup=srecDataEven,srecChecksum
+syn match srecDataEven "[0-9a-fA-F]\{2}" contained nextgroup=srecDataOdd,srecChecksum
+" data bytes which should not exist
+syn match srecDataUnexpected "[0-9a-fA-F]\{2}" contained nextgroup=srecDataUnexpected,srecChecksum
+" Data digit pair regex usage also results in only highlighting the checksum
+" if the number of data characters is even.
+
+syn match srecChecksum "[0-9a-fA-F]\{2}$" contained
+
+" Define the default highlighting.
+" For version 5.7 and earlier: only when not done already
+" For version 5.8 and later: only when an item doesn't have highlighting yet
+if version >= 508 || !exists("did_srec_syntax_inits")
+ if version < 508
+ let did_srec_syntax_inits = 1
+ command -nargs=+ HiLink hi link <args>
+ else
+ command -nargs=+ HiLink hi def link <args>
+ endif
+
+ " The default methods for highlighting. Can be overridden later
+ HiLink srecRecStart srecRecType
+ HiLink srecRecTypeUnknown srecRecType
+ HiLink srecRecType WarningMsg
+ HiLink srecByteCount Constant
+ hi def srecAddressFieldUnknown term=italic cterm=italic gui=italic
+ HiLink srecNoAddress DiffAdd
+ HiLink srecDataAddress Comment
+ HiLink srecRecCount srecNoAddress
+ HiLink srecStartAddress srecDataAddress
+ hi def srecDataOdd term=bold cterm=bold gui=bold
+ hi def srecDataEven term=NONE cterm=NONE gui=NONE
+ HiLink srecDataUnexpected Error
+ HiLink srecChecksum DiffChange
+
+ delcommand HiLink
+endif
+
+let b:current_syntax = "srec"
+
+" vim: ts=8
diff --git a/runtime/syntax/tex.vim b/runtime/syntax/tex.vim
index dcdeca2e6c..b95ff4d8cb 100644
--- a/runtime/syntax/tex.vim
+++ b/runtime/syntax/tex.vim
@@ -1,8 +1,8 @@
" Vim syntax file
" Language: TeX
" Maintainer: Charles E. Campbell <NdrchipO@ScampbellPfamily.AbizM>
-" Last Change: Nov 18, 2014
-" Version: 83
+" Last Change: Jun 11, 2015
+" Version: 87
" URL: http://www.drchip.org/astronaut/vim/index.html#SYNTAX_TEX
"
" Notes: {{{1
@@ -207,7 +207,7 @@ if s:tex_fast =~ 'M'
if !exists("s:tex_no_error") || !s:tex_no_error
syn match texMathError "}" contained
endif
- syn region texMathMatcher matchgroup=Delimiter start="{" skip="\\\\\|\\}" end="}" end="%stopzone\>" contained contains=@texMathMatchGroup
+ syn region texMathMatcher matchgroup=Delimiter start="{" skip="\(\\\\\)*\\}" end="}" end="%stopzone\>" contained contains=@texMathMatchGroup
endif
endif
@@ -226,7 +226,7 @@ endif
" TeX/LaTeX delimiters: {{{1
syn match texDelimiter "&"
syn match texDelimiter "\\\\"
-syn match texDelimiter "[{}]"
+"%syn match texDelimiter "[{}]"
" Tex/Latex Options: {{{1
syn match texOption "[^\\]\zs#\d\+\|^#\d\+"
@@ -247,7 +247,7 @@ syn match texLigature "\\\([ijolL]\|ae\|oe\|ss\|AA\|AE\|OE\)$"
" \begin{}/\end{} section markers: {{{1
syn match texBeginEnd "\\begin\>\|\\end\>" nextgroup=texBeginEndName
if s:tex_fast =~ 'm'
- syn region texBeginEndName matchgroup=Delimiter start="{" end="}" contained nextgroup=texBeginEndModifier contains=texComment
+ syn region texBeginEndName matchgroup=Delimiter start="{" end="}" contained nextgroup=texBeginEndModifier contains=texComment
syn region texBeginEndModifier matchgroup=Delimiter start="\[" end="]" contained contains=texComment,@NoSpell
endif
@@ -391,16 +391,23 @@ endif
" particular support for bold and italic {{{1
if s:tex_fast =~ 'b'
if s:tex_conceal =~ 'b'
- syn region texBoldStyle matchgroup=texTypeStyle start="\\textbf\s*{" end="}" concealends contains=@texBoldGroup
- syn region texBoldItalStyle matchgroup=texTypeStyle start="\\textit\s*{" end="}" concealends contains=@texItalGroup
- syn region texItalStyle matchgroup=texTypeStyle start="\\textit\s*{" end="}" concealends contains=@texItalGroup
- syn region texItalBoldStyle matchgroup=texTypeStyle start="\\textbf\s*{" end="}" concealends contains=@texBoldGroup
+ if !exists("g:tex_nospell") || !g:tex_nospell
+ syn region texBoldStyle matchgroup=texTypeStyle start="\\textbf\s*{" matchgroup=texTypeStyle end="}" concealends contains=@texBoldGroup,@Spell
+ syn region texBoldItalStyle matchgroup=texTypeStyle start="\\textit\s*{" matchgroup=texTypeStyle end="}" concealends contains=@texItalGroup,@Spell
+ syn region texItalStyle matchgroup=texTypeStyle start="\\textit\s*{" matchgroup=texTypeStyle end="}" concealends contains=@texItalGroup,@Spell
+ syn region texItalBoldStyle matchgroup=texTypeStyle start="\\textbf\s*{" matchgroup=texTypeStyle end="}" concealends contains=@texBoldGroup,@Spell
+ else
+ syn region texBoldStyle matchgroup=texTypeStyle start="\\textbf\s*{" matchgroup=texTypeStyle end="}" concealends contains=@texBoldGroup
+ syn region texBoldItalStyle matchgroup=texTypeStyle start="\\textit\s*{" matchgroup=texTypeStyle end="}" concealends contains=@texItalGroup
+ syn region texItalStyle matchgroup=texTypeStyle start="\\textit\s*{" matchgroup=texTypeStyle end="}" concealends contains=@texItalGroup
+ syn region texItalBoldStyle matchgroup=texTypeStyle start="\\textbf\s*{" matchgroup=texTypeStyle end="}" concealends contains=@texBoldGroup
+ endif
endif
endif
" Bad Math (mismatched): {{{1
if !exists("g:tex_no_math") && (!exists("s:tex_no_error") || !s:tex_no_error)
- syn match texBadMath "\\end\s*{\s*\(array\|gathered\|bBpvV]matrix\|split\|subequations\|smallmatrix\|xxalignat\)\s*}"
+ syn match texBadMath "\\end\s*{\s*\(array\|gathered\|bBpvV]matrix\|split\|smallmatrix\|xxalignat\)\s*}"
syn match texBadMath "\\end\s*{\s*\(align\|alignat\|displaymath\|displaymath\|eqnarray\|equation\|flalign\|gather\|math\|multline\|xalignat\)\*\=\s*}"
syn match texBadMath "\\[\])]"
endif
@@ -449,24 +456,23 @@ if !exists("g:tex_no_math")
call TexNewMathZone("G","gather",1)
call TexNewMathZone("H","math",1)
call TexNewMathZone("I","multline",1)
- call TexNewMathZone("J","subequations",0)
- call TexNewMathZone("K","xalignat",1)
- call TexNewMathZone("L","xxalignat",0)
+ call TexNewMathZone("J","xalignat",1)
+ call TexNewMathZone("K","xxalignat",0)
" Inline Math Zones: {{{2
if s:tex_fast =~ 'M'
if has("conceal") && &enc == 'utf-8' && s:tex_conceal =~ 'd'
- syn region texMathZoneV matchgroup=Delimiter start="\\(" matchgroup=Delimiter end="\\)\|%stopzone\>" keepend concealends contains=@texMathZoneGroup
- syn region texMathZoneW matchgroup=Delimiter start="\\\[" matchgroup=Delimiter end="\\]\|%stopzone\>" keepend concealends contains=@texMathZoneGroup
- syn region texMathZoneX matchgroup=Delimiter start="\$" skip="\\\\\|\\\$" matchgroup=Delimiter end="\$" end="%stopzone\>" concealends contains=@texMathZoneGroup
- syn region texMathZoneY matchgroup=Delimiter start="\$\$" matchgroup=Delimiter end="\$\$" end="%stopzone\>" concealends keepend contains=@texMathZoneGroup
+ syn region texMathZoneV matchgroup=Delimiter start="\\(" matchgroup=Delimiter end="\\)\|%stopzone\>" keepend concealends contains=@texMathZoneGroup
+ syn region texMathZoneW matchgroup=Delimiter start="\\\[" matchgroup=Delimiter end="\\]\|%stopzone\>" keepend concealends contains=@texMathZoneGroup
+ syn region texMathZoneX matchgroup=Delimiter start="\$" skip="\\\\\|\\\$" matchgroup=Delimiter end="\$" end="%stopzone\>" concealends contains=@texMathZoneGroup
+ syn region texMathZoneY matchgroup=Delimiter start="\$\$" matchgroup=Delimiter end="\$\$" end="%stopzone\>" keepend concealends contains=@texMathZoneGroup
else
- syn region texMathZoneV matchgroup=Delimiter start="\\(" matchgroup=Delimiter end="\\)\|%stopzone\>" keepend contains=@texMathZoneGroup
- syn region texMathZoneW matchgroup=Delimiter start="\\\[" matchgroup=Delimiter end="\\]\|%stopzone\>" keepend contains=@texMathZoneGroup
- syn region texMathZoneX matchgroup=Delimiter start="\$" skip="\\\\\|\\\$" matchgroup=Delimiter end="\$" end="%stopzone\>" contains=@texMathZoneGroup
- syn region texMathZoneY matchgroup=Delimiter start="\$\$" matchgroup=Delimiter end="\$\$" end="%stopzone\>" keepend contains=@texMathZoneGroup
+ syn region texMathZoneV matchgroup=Delimiter start="\\(" matchgroup=Delimiter end="\\)\|%stopzone\>" keepend contains=@texMathZoneGroup
+ syn region texMathZoneW matchgroup=Delimiter start="\\\[" matchgroup=Delimiter end="\\]\|%stopzone\>" keepend contains=@texMathZoneGroup
+ syn region texMathZoneX matchgroup=Delimiter start="\$" skip="\\\\\|\\\$" matchgroup=Delimiter end="\$" end="%stopzone\>" contains=@texMathZoneGroup
+ syn region texMathZoneY matchgroup=Delimiter start="\$\$" matchgroup=Delimiter end="\$\$" end="%stopzone\>" keepend contains=@texMathZoneGroup
endif
- syn region texMathZoneZ matchgroup=texStatement start="\\ensuremath\s*{" matchgroup=texStatement end="}" end="%stopzone\>" contains=@texMathZoneGroup
+ syn region texMathZoneZ matchgroup=texStatement start="\\ensuremath\s*{" matchgroup=texStatement end="}" end="%stopzone\>" contains=@texMathZoneGroup
endif
syn match texMathOper "[_^=]" contained
@@ -576,14 +582,14 @@ else
syn match texComment "%.*$" contains=@texCommentGroup
if s:tex_fast =~ 'c'
syn region texComment start="^\zs\s*%.*\_s*%" skip="^\s*%" end='^\ze\s*[^%]' fold
- syn region texNoSpell contained matchgroup=texComment start="%\s*nospell\s*{" end="%\s*nospell\s*}" fold contains=@texFoldGroup,@NoSpell
- syn region texSpellZone matchgroup=texComment start="%\s*spellzone_start" end="%\s*spellzone_end" fold contains=@Spell,@texFoldGroup
+ syn region texNoSpell contained matchgroup=texComment start="%\s*nospell\s*{" end="%\s*nospell\s*}" fold contains=@texFoldGroup,@NoSpell
+ syn region texSpellZone matchgroup=texComment start="%\s*spellzone_start" end="%\s*spellzone_end" fold contains=@Spell,@texFoldGroup
endif
else
- syn match texComment "%.*$" contains=@texCommentGroup
+ syn match texComment "%.*$" contains=@texCommentGroup
if s:tex_fast =~ 'c'
- syn region texNoSpell contained matchgroup=texComment start="%\s*nospell\s*{" end="%\s*nospell\s*}" contains=@texFoldGroup,@NoSpell
- syn region texSpellZone matchgroup=texComment start="%\s*spellzone_start" end="%\s*spellzone_end" contains=@Spell,@texFoldGroup
+ syn region texNoSpell contained matchgroup=texComment start="%\s*nospell\s*{" end="%\s*nospell\s*}" contains=@texFoldGroup,@NoSpell
+ syn region texSpellZone matchgroup=texComment start="%\s*spellzone_start" end="%\s*spellzone_end" contains=@Spell,@texFoldGroup
endif
endif
endif
@@ -1055,11 +1061,12 @@ if has("conceal") && &enc == 'utf-8'
syn region texSuperscript matchgroup=Delimiter start='\^{' skip="\\\\\|\\[{}]" end='}' contained concealends contains=texSpecialChar,texSuperscripts,texStatement,texSubscript,texSuperscript,texMathMatcher
syn region texSubscript matchgroup=Delimiter start='_{' skip="\\\\\|\\[{}]" end='}' contained concealends contains=texSpecialChar,texSubscripts,texStatement,texSubscript,texSuperscript,texMathMatcher
endif
+ " s:SuperSub:
fun! s:SuperSub(group,leader,pat,cchar)
if a:pat =~ '^\\' || (a:leader == '\^' && a:pat =~ g:tex_superscripts) || (a:leader == '_' && a:pat =~ g:tex_subscripts)
" call Decho("SuperSub: group<".a:group."> leader<".a:leader."> pat<".a:pat."> cchar<".a:cchar.">")
exe 'syn match '.a:group." '".a:leader.a:pat."' contained conceal cchar=".a:cchar
- exe 'syn match '.a:group."s '".a:pat."' contained conceal cchar=".a:cchar.' nextgroup='.a:group.'s'
+ exe 'syn match '.a:group."s '".a:pat ."' contained conceal cchar=".a:cchar.' nextgroup='.a:group.'s'
endif
endfun
call s:SuperSub('texSuperscript','\^','0','⁰')
diff --git a/runtime/syntax/upstreamdat.vim b/runtime/syntax/upstreamdat.vim
index 7be806730d..e3b415a4bc 100644
--- a/runtime/syntax/upstreamdat.vim
+++ b/runtime/syntax/upstreamdat.vim
@@ -1,13 +1,14 @@
" Vim syntax file
" Language: Innovation Data Processing upstream.dat file
" Maintainer: Rob Owens <rowens@fdrinnovation.com>
-" Latest Revision: 2013-06-17
+" Latest Revision: 2013-11-27
" Quit when a syntax file was already loaded
if exists("b:current_syntax")
finish
endif
+" Parameters:
syn keyword upstreamdat_Parameter ACCEPTPCREMOTE
syn keyword upstreamdat_Parameter ACCEPTREMOTE
syn keyword upstreamdat_Parameter ACTION
@@ -291,6 +292,14 @@ syn keyword upstreamdat_Parameter XFERECORDSIZE
syn keyword upstreamdat_Parameter XFERRECSEP
syn keyword upstreamdat_Parameter XFERRECUSECR
+" File Specs:
+syn match upstreamdat_Filespec /file spec\c \d\{1,3}.*/
+
+" Comments:
+syn match upstreamdat_Comment /^#.*/
+
hi def link upstreamdat_Parameter Type
+"hi def link upstreamdat_Filespec Underlined
+hi def link upstreamdat_Comment Comment
let b:current_syntax = "upstreamdat"
diff --git a/runtime/syntax/upstreamrpt.vim b/runtime/syntax/upstreamrpt.vim
new file mode 100644
index 0000000000..170fc8f509
--- /dev/null
+++ b/runtime/syntax/upstreamrpt.vim
@@ -0,0 +1,310 @@
+" Vim syntax file
+" Language: Innovation Data Processing upstream.rpt file
+" Maintainer: Rob Owens <rowens@fdrinnovation.com>
+" Latest Revision: 2014-03-13
+
+" Quit when a syntax file was already loaded
+if exists("b:current_syntax")
+ finish
+endif
+
+setlocal foldmethod=syntax
+
+" Parameters:
+syn keyword upstreamdat_Parameter ACCEPTPCREMOTE
+syn keyword upstreamdat_Parameter ACCEPTREMOTE
+syn keyword upstreamdat_Parameter ACTION
+syn keyword upstreamdat_Parameter ACTIVATEONENTRY
+syn keyword upstreamdat_Parameter ARCHIVEBIT
+syn keyword upstreamdat_Parameter ARCHIVEBIT
+syn keyword upstreamdat_Parameter ASCTOEBC
+syn keyword upstreamdat_Parameter ASRBACKUP
+syn keyword upstreamdat_Parameter ATTENDED
+syn keyword upstreamdat_Parameter AUTHORITATIVE
+syn keyword upstreamdat_Parameter AUTHORITATIVERESTORE
+syn keyword upstreamdat_Parameter AUTHORITATIVERESTORE
+syn keyword upstreamdat_Parameter BACKUPPROFILE
+syn keyword upstreamdat_Parameter BACKUPPROFILE2
+syn keyword upstreamdat_Parameter BACKUPREPARSEFILES
+syn keyword upstreamdat_Parameter BACKUPREPARSEFILES
+syn keyword upstreamdat_Parameter BACKUPVERIFY
+syn keyword upstreamdat_Parameter BLANKTRUNC
+syn keyword upstreamdat_Parameter CALCDASDSIZE
+syn keyword upstreamdat_Parameter CHANGEDIRATTRIBS
+syn keyword upstreamdat_Parameter CHANGEDIRATTRIBS
+syn keyword upstreamdat_Parameter COMPRESSLEVEL
+syn keyword upstreamdat_Parameter CONTROLFILE
+syn keyword upstreamdat_Parameter DASDOVERRIDE
+syn keyword upstreamdat_Parameter DATELIMIT
+syn keyword upstreamdat_Parameter DATELIMIT
+syn keyword upstreamdat_Parameter DAYSOLD
+syn keyword upstreamdat_Parameter DAYSOLD
+syn keyword upstreamdat_Parameter DELETED
+syn keyword upstreamdat_Parameter DELETED
+syn keyword upstreamdat_Parameter DELETEPROMPTS
+syn keyword upstreamdat_Parameter DELETEPROMPTS
+syn keyword upstreamdat_Parameter DESTINATION
+syn keyword upstreamdat_Parameter DESTINATION
+syn keyword upstreamdat_Parameter DIRDELETE
+syn keyword upstreamdat_Parameter DIRECTORVMC
+syn keyword upstreamdat_Parameter DIRONLYRESTOREOK
+syn keyword upstreamdat_Parameter DIRSONLY
+syn keyword upstreamdat_Parameter DIRSONLY
+syn keyword upstreamdat_Parameter DISASTERRECOVERY
+syn keyword upstreamdat_Parameter DISPLAY
+syn keyword upstreamdat_Parameter DRIVEALIAS
+syn keyword upstreamdat_Parameter DRIVEALIAS
+syn keyword upstreamdat_Parameter DUALCOPY
+syn keyword upstreamdat_Parameter DUPDAYS
+syn keyword upstreamdat_Parameter DUPLICATE
+syn keyword upstreamdat_Parameter EBCTOASC
+syn keyword upstreamdat_Parameter ENCRYPT
+syn keyword upstreamdat_Parameter ENCRYPTLEVEL
+syn keyword upstreamdat_Parameter EXCLUDELISTNAME
+syn keyword upstreamdat_Parameter FAILBACKUPONERROR
+syn keyword upstreamdat_Parameter FAILBACKUPONERROR
+syn keyword upstreamdat_Parameter FAILIFNOFILES
+syn keyword upstreamdat_Parameter FAILIFNOFILES
+syn keyword upstreamdat_Parameter FAILIFSKIP
+syn keyword upstreamdat_Parameter FAILJOB
+syn keyword upstreamdat_Parameter FAILRESTOREONERROR
+syn keyword upstreamdat_Parameter FAILRESTOREONERROR
+syn keyword upstreamdat_Parameter FILEDATE
+syn keyword upstreamdat_Parameter FILEDATE
+syn keyword upstreamdat_Parameter FILEDELETE
+syn keyword upstreamdat_Parameter FILEDELETE
+syn keyword upstreamdat_Parameter FILES
+syn keyword upstreamdat_Parameter FILES
+syn keyword upstreamdat_Parameter FILESOPENFORUPDAT
+syn keyword upstreamdat_Parameter FILESOPENFORUPDAT
+syn keyword upstreamdat_Parameter FILETRANSFER
+syn keyword upstreamdat_Parameter GETREMOTEFILES
+syn keyword upstreamdat_Parameter HARDLINKDB
+syn keyword upstreamdat_Parameter HARDLINKS
+syn keyword upstreamdat_Parameter HARDLINKS
+syn keyword upstreamdat_Parameter HIDDENFILES
+syn keyword upstreamdat_Parameter HIDDENFILES
+syn keyword upstreamdat_Parameter HOLDTAPE
+syn keyword upstreamdat_Parameter HOLDUSERDIRS
+syn keyword upstreamdat_Parameter HOSTFILENAME
+syn keyword upstreamdat_Parameter HOSTRECORD
+syn keyword upstreamdat_Parameter HOSTSORT
+syn keyword upstreamdat_Parameter IGNOREPLUGINSFORRESTORE
+syn keyword upstreamdat_Parameter INCRDB
+syn keyword upstreamdat_Parameter INCRDBARCHIVEBIT
+syn keyword upstreamdat_Parameter INCRDBDELETEDFILES
+syn keyword upstreamdat_Parameter INCREMENTAL
+syn keyword upstreamdat_Parameter INCREMENTAL
+syn keyword upstreamdat_Parameter INQOPTIONS
+syn keyword upstreamdat_Parameter INSTALLWIN2KAGENT
+syn keyword upstreamdat_Parameter INSTALLWIN2KAGENT
+syn keyword upstreamdat_Parameter JOBOPTIONS
+syn keyword upstreamdat_Parameter JOBRETURNCODEMAP
+syn keyword upstreamdat_Parameter JOBWAITTIMELIMIT
+syn keyword upstreamdat_Parameter KEEPALIVE
+syn keyword upstreamdat_Parameter LANINTERFACE
+syn keyword upstreamdat_Parameter LANWSNAME
+syn keyword upstreamdat_Parameter LANWSPASSWORD
+syn keyword upstreamdat_Parameter LASTACCESS
+syn keyword upstreamdat_Parameter LASTACCESS
+syn keyword upstreamdat_Parameter LATESTDATE
+syn keyword upstreamdat_Parameter LATESTDATE
+syn keyword upstreamdat_Parameter LATESTTIME
+syn keyword upstreamdat_Parameter LATESTTIME
+syn keyword upstreamdat_Parameter LATESTVERSION
+syn keyword upstreamdat_Parameter LINEBLOCK
+syn keyword upstreamdat_Parameter LINETRUNC
+syn keyword upstreamdat_Parameter LISTENFORREMOTE
+syn keyword upstreamdat_Parameter LOCALBACKUP
+syn keyword upstreamdat_Parameter LOCALBACKUPDIR
+syn keyword upstreamdat_Parameter LOCALBACKUPMAX
+syn keyword upstreamdat_Parameter LOCALBACKUPMAXFILESIZE
+syn keyword upstreamdat_Parameter LOCALBACKUPMAXSIZE
+syn keyword upstreamdat_Parameter LOCALEXCLUDEFILE
+syn keyword upstreamdat_Parameter LOCALPARAMETERS
+syn keyword upstreamdat_Parameter LOCALPASSWORD
+syn keyword upstreamdat_Parameter LOCALRESTORE
+syn keyword upstreamdat_Parameter LOCALUSER
+syn keyword upstreamdat_Parameter LOFS
+syn keyword upstreamdat_Parameter LOGNONFATAL
+syn keyword upstreamdat_Parameter MAXBACKUPFILESFAIL
+syn keyword upstreamdat_Parameter MAXBACKUPTIME
+syn keyword upstreamdat_Parameter MAXDUPS
+syn keyword upstreamdat_Parameter MAXFILENAMESIZE
+syn keyword upstreamdat_Parameter MAXKFILESIZE
+syn keyword upstreamdat_Parameter MAXLOGDAYS
+syn keyword upstreamdat_Parameter MAXRESTOREFILESFAIL
+syn keyword upstreamdat_Parameter MAXRESTORETIME
+syn keyword upstreamdat_Parameter MAXRETRY
+syn keyword upstreamdat_Parameter MAXRPTDAYS
+syn keyword upstreamdat_Parameter MERGE
+syn keyword upstreamdat_Parameter MIGRBITS
+syn keyword upstreamdat_Parameter MIGRBITS
+syn keyword upstreamdat_Parameter MINCOMPRESSSIZE
+syn keyword upstreamdat_Parameter MINIMIZE
+syn keyword upstreamdat_Parameter MODIFYFILE
+syn keyword upstreamdat_Parameter MOUNTPOINTS
+syn keyword upstreamdat_Parameter MOUNTPOINTS
+syn keyword upstreamdat_Parameter NDS
+syn keyword upstreamdat_Parameter NDS
+syn keyword upstreamdat_Parameter NEWFILECOMPARE
+syn keyword upstreamdat_Parameter NFSBELOW
+syn keyword upstreamdat_Parameter NODATAOK
+syn keyword upstreamdat_Parameter NODIRFORINCREMENTAL
+syn keyword upstreamdat_Parameter NODIRFORINCREMENTAL
+syn keyword upstreamdat_Parameter NONFILEDATABITMAP
+syn keyword upstreamdat_Parameter NONFILEDATABITMAP
+syn keyword upstreamdat_Parameter NOPOINTRESTORE
+syn keyword upstreamdat_Parameter NOSPECINHERITANCE
+syn keyword upstreamdat_Parameter NOTIFYEVENTS
+syn keyword upstreamdat_Parameter NOTIFYFAILUREATTACHMENT
+syn keyword upstreamdat_Parameter NOTIFYSUCCESSATTACHMENT
+syn keyword upstreamdat_Parameter NOTIFYTARGETS
+syn keyword upstreamdat_Parameter NOUIDGIDNAMES
+syn keyword upstreamdat_Parameter NOUIDGIDNAMES
+syn keyword upstreamdat_Parameter NOVELLMIGRATE
+syn keyword upstreamdat_Parameter NOVELLMIGRATE
+syn keyword upstreamdat_Parameter NOVELLMIGRATEADDEXT
+syn keyword upstreamdat_Parameter NOVELLMIGRATEADDEXT
+syn keyword upstreamdat_Parameter NOVELLPROFILE
+syn keyword upstreamdat_Parameter NOVELLRECALL
+syn keyword upstreamdat_Parameter NTFSADDPERMISSION
+syn keyword upstreamdat_Parameter NTFSADDPERMISSION
+syn keyword upstreamdat_Parameter NTREGRESTORE
+syn keyword upstreamdat_Parameter OSTYPE
+syn keyword upstreamdat_Parameter OUTPORT
+syn keyword upstreamdat_Parameter PACKFLUSHAFTERFILE
+syn keyword upstreamdat_Parameter PACKRECSIZE
+syn keyword upstreamdat_Parameter PARAMETER
+syn keyword upstreamdat_Parameter PASSWORD
+syn keyword upstreamdat_Parameter PATHNAME
+syn keyword upstreamdat_Parameter PATHNAME
+syn keyword upstreamdat_Parameter PERFORMBITMAP
+syn keyword upstreamdat_Parameter PERFORMNUMRECORDS
+syn keyword upstreamdat_Parameter PERFORMRECORDSIZE
+syn keyword upstreamdat_Parameter PLUGIN
+syn keyword upstreamdat_Parameter PLUGIN
+syn keyword upstreamdat_Parameter PLUGINPARAMETERS
+syn keyword upstreamdat_Parameter PLUGINPARAMETERS
+syn keyword upstreamdat_Parameter POSTJOB
+syn keyword upstreamdat_Parameter PREJOB
+syn keyword upstreamdat_Parameter PRTYCLASS
+syn keyword upstreamdat_Parameter PRTYLEVEL
+syn keyword upstreamdat_Parameter RECALLCLEANUP
+syn keyword upstreamdat_Parameter RECALLOFFLINEFILES
+syn keyword upstreamdat_Parameter RECALLOFFLINEFILES
+syn keyword upstreamdat_Parameter RECORDSIZE
+syn keyword upstreamdat_Parameter REMOTEADDR
+syn keyword upstreamdat_Parameter REMOTEAPPLPREF
+syn keyword upstreamdat_Parameter REMOTEAPPLRETRY
+syn keyword upstreamdat_Parameter REMOTECONNECTTYPE
+syn keyword upstreamdat_Parameter REMOTEFLAGS
+syn keyword upstreamdat_Parameter REMOTEIPADAPTER
+syn keyword upstreamdat_Parameter REMOTELOCALPARAMETERS
+syn keyword upstreamdat_Parameter REMOTELOGMODE
+syn keyword upstreamdat_Parameter REMOTELUNAME
+syn keyword upstreamdat_Parameter REMOTEMAXRETRIES
+syn keyword upstreamdat_Parameter REMOTEMODENAME
+syn keyword upstreamdat_Parameter REMOTEPARAMETERFILE
+syn keyword upstreamdat_Parameter REMOTEPORT
+syn keyword upstreamdat_Parameter REMOTEREQUEST
+syn keyword upstreamdat_Parameter REMOTERESTART
+syn keyword upstreamdat_Parameter REMOTEROUTE
+syn keyword upstreamdat_Parameter REMOTETARGETNAME
+syn keyword upstreamdat_Parameter REMOTETCP
+syn keyword upstreamdat_Parameter REMOTETIMEOUT
+syn keyword upstreamdat_Parameter REMOTETMAXRETRY
+syn keyword upstreamdat_Parameter REMOTETPN
+syn keyword upstreamdat_Parameter REMOTEUSAPPL
+syn keyword upstreamdat_Parameter REMOTEVERIFY
+syn keyword upstreamdat_Parameter REMOTEWTOCOMP
+syn keyword upstreamdat_Parameter REPORTNAME
+syn keyword upstreamdat_Parameter REPORTOPTIONS
+syn keyword upstreamdat_Parameter RESTARTLASTFILE
+syn keyword upstreamdat_Parameter RESTART
+syn keyword upstreamdat_Parameter RESTARTTYPE
+syn keyword upstreamdat_Parameter RESTARTVERSIONDATE
+syn keyword upstreamdat_Parameter RESTOREARCHIVEBIT
+syn keyword upstreamdat_Parameter RESTORECHECKPOINT
+syn keyword upstreamdat_Parameter RESTOREDATELIMIT
+syn keyword upstreamdat_Parameter RESTOREDATELIMIT
+syn keyword upstreamdat_Parameter RESTOREFILEFAIL
+syn keyword upstreamdat_Parameter RESTOREMOUNTPOINTS
+syn keyword upstreamdat_Parameter RESTOREMOUNTPOINTS
+syn keyword upstreamdat_Parameter RESTORESEGMENTS
+syn keyword upstreamdat_Parameter RESTORESEGMENTS
+syn keyword upstreamdat_Parameter RESTORETODIFFFS
+syn keyword upstreamdat_Parameter RETAIN
+syn keyword upstreamdat_Parameter RETAIN
+syn keyword upstreamdat_Parameter ROOTENTRY
+syn keyword upstreamdat_Parameter ROOTENTRY
+syn keyword upstreamdat_Parameter SAN
+syn keyword upstreamdat_Parameter SCHEDULENAME
+syn keyword upstreamdat_Parameter SEGMENTEDFILESIZE
+syn keyword upstreamdat_Parameter SEGMENTEDFILESIZE
+syn keyword upstreamdat_Parameter SEGMENTSIZE
+syn keyword upstreamdat_Parameter SEGMENTSIZE
+syn keyword upstreamdat_Parameter SENDHOSTDETAILS
+syn keyword upstreamdat_Parameter SINGLEFS
+syn keyword upstreamdat_Parameter SIZETRC
+syn keyword upstreamdat_Parameter SKIP
+syn keyword upstreamdat_Parameter SKIPBACKUPSCAN
+syn keyword upstreamdat_Parameter SKIPOLD
+syn keyword upstreamdat_Parameter SKIPOLD
+syn keyword upstreamdat_Parameter SMSTARGETSERVICENAME
+syn keyword upstreamdat_Parameter SMSTSA
+syn keyword upstreamdat_Parameter SOLO
+syn keyword upstreamdat_Parameter SORTBACKUP
+syn keyword upstreamdat_Parameter SOSDISK
+syn keyword upstreamdat_Parameter SOSDISK
+syn keyword upstreamdat_Parameter SOSTIMESTAMP
+syn keyword upstreamdat_Parameter SOSTIMESTAMP
+syn keyword upstreamdat_Parameter SOSTIMESTAMPPATH
+syn keyword upstreamdat_Parameter SOSTIMESTAMPPATH
+syn keyword upstreamdat_Parameter SPECNUMBER
+syn keyword upstreamdat_Parameter SPECNUMBER
+syn keyword upstreamdat_Parameter SPECTYPE
+syn keyword upstreamdat_Parameter SPECTYPE
+syn keyword upstreamdat_Parameter STARTTIME
+syn keyword upstreamdat_Parameter STORAGETYPE
+syn keyword upstreamdat_Parameter SUBDIRECTORIES
+syn keyword upstreamdat_Parameter SUBDIRECTORIES
+syn keyword upstreamdat_Parameter SWITCHTOTAPEMB
+syn keyword upstreamdat_Parameter TCPADDRESS
+syn keyword upstreamdat_Parameter TCPTIMEOUT
+syn keyword upstreamdat_Parameter TIMEOVERRIDE
+syn keyword upstreamdat_Parameter TRACE
+syn keyword upstreamdat_Parameter TRANSLATE
+syn keyword upstreamdat_Parameter ULTRACOMP
+syn keyword upstreamdat_Parameter ULTREG
+syn keyword upstreamdat_Parameter ULTUPD
+syn keyword upstreamdat_Parameter UNCMACHINEALIAS
+syn keyword upstreamdat_Parameter UNCMACHINEALIAS
+syn keyword upstreamdat_Parameter USEALEBRA
+syn keyword upstreamdat_Parameter USECONTROLFILE
+syn keyword upstreamdat_Parameter USEGID
+syn keyword upstreamdat_Parameter USERID
+syn keyword upstreamdat_Parameter USEUID
+syn keyword upstreamdat_Parameter USNOUIDGIDERRORS
+syn keyword upstreamdat_Parameter UTF8
+syn keyword upstreamdat_Parameter VAULTNUMBER
+syn keyword upstreamdat_Parameter VERSIONDATE
+syn keyword upstreamdat_Parameter WRITESPARSE
+syn keyword upstreamdat_Parameter XFERECORDSIZE
+syn keyword upstreamdat_Parameter XFERRECSEP
+syn keyword upstreamdat_Parameter XFERRECUSECR
+
+" File Specs:
+syn match upstreamdat_Filespec /file spec\c \d\{1,3}.*/
+
+" Comments:
+syn match upstreamdat_Comment /^#.*/
+
+" List Of Parameters:
+syn region upstreamdat_Parms start="Current Parameters:" end="End Of Parameters" transparent fold
+
+hi def link upstreamdat_Parameter Type
+"hi def link upstreamdat_Filespec Underlined
+hi def link upstreamdat_Comment Comment
+
+let b:current_syntax = "upstreamdat"
diff --git a/runtime/syntax/usw2kagtlog.vim b/runtime/syntax/usw2kagtlog.vim
index 0a34128f9b..a112340d12 100644
--- a/runtime/syntax/usw2kagtlog.vim
+++ b/runtime/syntax/usw2kagtlog.vim
@@ -1,7 +1,7 @@
" Vim syntax file
" Language: Innovation Data Processing USW2KAgt.log file
" Maintainer: Rob Owens <rowens@fdrinnovation.com>
-" Latest Revision: 2013-09-19
+" Latest Revision: 2014-04-01
" Quit when a syntax file was already loaded
if exists("b:current_syntax")
@@ -17,8 +17,12 @@ syn match usw2kagtlog_MsgI /Msg #\(Agt\|PC\|Srv\)\d\{4,5}I/ nextgroup=usw2kagtlo
syn match usw2kagtlog_MsgW /Msg #\(Agt\|PC\|Srv\)\d\{4,5}W/ nextgroup=usw2kagtlog_Process skipwhite
" Processes:
syn region usw2kagtlog_Process start="(" end=")" contained
-syn region usw2kagtlog_Process start="Starting the processing for a \zs\"" end="\ze client request"
-syn region usw2kagtlog_Process start="Ending the processing for a \zs\"" end="\ze client request"
+"syn region usw2kagtlog_Process start="Starting the processing for a \zs\"" end="\ze client request"
+"syn region usw2kagtlog_Process start="Ending the processing for a \zs\"" end="\ze client request"
+"syn region usw2kagtlog_Process start="Starting the processing for a \zs\"" end="\ze client\s\{0,1}\r\{0,1}\s\{1,9}request"
+"syn region usw2kagtlog_Process start="Ending the processing for a \zs\"" end="\ze client\s\{0,1}\r\{0,1}\s\{1,9}request"
+syn region usw2kagtlog_Process start="Starting the processing for a \zs\"" end="\ze client"
+syn region usw2kagtlog_Process start="Ending the processing for a \zs\"" end="\ze client"
" IP Address:
syn match usw2kagtlog_IPaddr / \d\{1,3}\.\d\{1,3}\.\d\{1,3}\.\d\{1,3}/
" Profile:
diff --git a/runtime/syntax/yacc.vim b/runtime/syntax/yacc.vim
index 9dc6cccb2d..977ffa75e4 100644
--- a/runtime/syntax/yacc.vim
+++ b/runtime/syntax/yacc.vim
@@ -1,8 +1,8 @@
" Vim syntax file
" Language: Yacc
" Maintainer: Charles E. Campbell <NdrOchipS@PcampbellAfamily.Mbiz>
-" Last Change: Jan 14, 2015
-" Version: 12
+" Last Change: Apr 02, 2015
+" Version: 13
" URL: http://mysite.verizon.net/astronaut/vim/index.html#vimlinks_syntax
"
" Options: {{{1
diff --git a/runtime/syntax/yaml.vim b/runtime/syntax/yaml.vim
index 073dbf7418..626dc8a77f 100644
--- a/runtime/syntax/yaml.vim
+++ b/runtime/syntax/yaml.vim
@@ -2,7 +2,7 @@
" Language: YAML (YAML Ain't Markup Language) 1.2
" Maintainer: Nikolai Pavlov <zyx.vim@gmail.com>
" First author: Nikolai Weibull <now@bitwi.se>
-" Latest Revision: 2010-10-08
+" Latest Revision: 2015-03-28
if exists('b:current_syntax')
finish
@@ -11,13 +11,40 @@ endif
let s:cpo_save = &cpo
set cpo&vim
-let s:ns_char = '\%(\%([\n\r\uFEFF \t]\)\@!\p\)'
-let s:ns_word_char = '\%(\w\|-\)'
-let s:ns_uri_char = '\%(%\x\x\|'.s:ns_word_char.'\|[#/;?:@&=+$,.!~*''()\[\]]\)'
+" Choose the schema to use
+" TODO: Validate schema
+if !exists('b:yaml_schema')
+ if exists('g:yaml_schema')
+ let b:yaml_schema = g:yaml_schema
+ else
+ let b:yaml_schema = 'core'
+ endif
+endif
+
+let s:ns_char = '\%([\n\r\uFEFF \t]\@!\p\)'
+let s:ns_word_char = '[[:alnum:]_\-]'
+let s:ns_uri_char = '\%(%\x\x\|'.s:ns_word_char.'\|[#/;?:@&=+$,.!~*''()[\]]\)'
let s:ns_tag_char = '\%(%\x\x\|'.s:ns_word_char.'\|[#/;?:@&=+$.~*''()]\)'
-let s:c_ns_anchor_char = '\%(\%([\n\r\uFEFF \t,\[\]{}]\)\@!\p\)'
-let s:c_indicator = '[\-?:,\[\]{}#&*!|>''"%@`]'
-let s:c_flow_indicator = '[,\[\]{}]'
+let s:c_ns_anchor_char = '\%([\n\r\uFEFF \t,[\]{}]\@!\p\)'
+let s:c_indicator = '[\-?:,[\]{}#&*!|>''"%@`]'
+let s:c_flow_indicator = '[,[\]{}]'
+
+let s:ns_char_without_c_indicator = substitute(s:ns_char, '\v\C[\zs', '\=s:c_indicator[1:-2]', '')
+
+let s:_collection = '[^\@!\(\%(\\\.\|\[^\\\]]\)\+\)]'
+let s:_neg_collection = '[^\(\%(\\\.\|\[^\\\]]\)\+\)]'
+function s:SimplifyToAssumeAllPrintable(p)
+ return substitute(a:p, '\V\C\\%('.s:_collection.'\\@!\\p\\)', '[^\1]', '')
+endfunction
+let s:ns_char = s:SimplifyToAssumeAllPrintable(s:ns_char)
+let s:ns_char_without_c_indicator = s:SimplifyToAssumeAllPrintable(s:ns_char_without_c_indicator)
+let s:c_ns_anchor_char = s:SimplifyToAssumeAllPrintable(s:c_ns_anchor_char)
+
+function s:SimplifyAdjacentCollections(p)
+ return substitute(a:p, '\V\C'.s:_collection.'\\|'.s:_collection, '[\1\2]', 'g')
+endfunction
+let s:ns_uri_char = s:SimplifyAdjacentCollections(s:ns_uri_char)
+let s:ns_tag_char = s:SimplifyAdjacentCollections(s:ns_tag_char)
let s:c_verbatim_tag = '!<'.s:ns_uri_char.'\+>'
let s:c_named_tag_handle = '!'.s:ns_word_char.'\+!'
@@ -46,11 +73,15 @@ let s:ns_tag_prefix = s:ns_local_tag_prefix.
let s:ns_plain_safe_out = s:ns_char
let s:ns_plain_safe_in = '\%('.s:c_flow_indicator.'\@!'.s:ns_char.'\)'
-let s:ns_plain_first_in = '\%('.s:c_indicator.'\@!'.s:ns_char.'\|[?:\-]\%('.s:ns_plain_safe_in.'\)\@=\)'
-let s:ns_plain_first_out = '\%('.s:c_indicator.'\@!'.s:ns_char.'\|[?:\-]\%('.s:ns_plain_safe_out.'\)\@=\)'
+let s:ns_plain_safe_in = substitute(s:ns_plain_safe_in, '\V\C\\%('.s:_collection.'\\@!'.s:_neg_collection.'\\)', '[^\1\2]', '')
+let s:ns_plain_safe_in_without_colhash = substitute(s:ns_plain_safe_in, '\V\C'.s:_neg_collection, '[^\1:#]', '')
+let s:ns_plain_safe_out_without_colhash = substitute(s:ns_plain_safe_out, '\V\C'.s:_neg_collection, '[^\1:#]', '')
-let s:ns_plain_char_in = '\%('.s:ns_char.'#\|:'.s:ns_plain_safe_in.'\|[:#]\@!'.s:ns_plain_safe_in.'\)'
-let s:ns_plain_char_out = '\%('.s:ns_char.'#\|:'.s:ns_plain_safe_out.'\|[:#]\@!'.s:ns_plain_safe_out.'\)'
+let s:ns_plain_first_in = '\%('.s:ns_char_without_c_indicator.'\|[?:\-]\%('.s:ns_plain_safe_in.'\)\@=\)'
+let s:ns_plain_first_out = '\%('.s:ns_char_without_c_indicator.'\|[?:\-]\%('.s:ns_plain_safe_out.'\)\@=\)'
+
+let s:ns_plain_char_in = '\%('.s:ns_char.'#\|:'.s:ns_plain_safe_in.'\|'.s:ns_plain_safe_in_without_colhash.'\)'
+let s:ns_plain_char_out = '\%('.s:ns_char.'#\|:'.s:ns_plain_safe_out.'\|'.s:ns_plain_safe_out_without_colhash.'\)'
let s:ns_plain_out = s:ns_plain_first_out . s:ns_plain_char_out.'*'
let s:ns_plain_in = s:ns_plain_first_in . s:ns_plain_char_in.'*'
@@ -89,9 +120,11 @@ syn match yamlSingleEscape contained "''"
syn match yamlBlockScalarHeader contained '\s\+\zs[|>]\%([+-]\=[1-9]\|[1-9]\=[+-]\)\='
+syn cluster yamlConstant contains=yamlBool,yamlNull
+
syn cluster yamlFlow contains=yamlFlowString,yamlFlowMapping,yamlFlowCollection
syn cluster yamlFlow add=yamlFlowMappingKey,yamlFlowMappingMerge
-syn cluster yamlFlow add=yamlConstant,yamlPlainScalar,yamlFloat
+syn cluster yamlFlow add=@yamlConstant,yamlPlainScalar,yamlFloat
syn cluster yamlFlow add=yamlTimestamp,yamlInteger,yamlMappingKeyStart
syn cluster yamlFlow add=yamlComment
syn region yamlFlowMapping matchgroup=yamlFlowIndicator start='{' end='}' contains=@yamlFlow
@@ -103,15 +136,15 @@ execute 'syn match yamlPlainScalar contained /'.s:ns_plain_in.'/'
syn match yamlMappingKeyStart '?\ze\s'
syn match yamlMappingKeyStart '?' contained
-execute 'syn match yamlFlowMappingKey /'.s:ns_plain_in.'\ze\s*:/ contained '.
+execute 'syn match yamlFlowMappingKey /\%#=1'.s:ns_plain_in.'\%(\s\+'.s:ns_plain_in.'\)*\ze\s*:/ contained '.
\'nextgroup=yamlKeyValueDelimiter'
syn match yamlFlowMappingMerge /<<\ze\s*:/ contained nextgroup=yamlKeyValueDelimiter
syn match yamlBlockCollectionItemStart '^\s*\zs-\%(\s\+-\)*\s' nextgroup=yamlBlockMappingKey,yamlBlockMappingMerge
" Use the old regexp engine, the NFA engine doesn't like all the \@ items.
-execute 'syn match yamlBlockMappingKey /\%#=1^\s*\zs'.s:ns_plain_out.'\ze\s*:\%(\s\|$\)/ '.
+execute 'syn match yamlBlockMappingKey /\%#=1^\s*\zs'.s:ns_plain_out.'\%(\s\+'.s:ns_plain_out.'\)*\ze\s*:\%(\s\|$\)/ '.
\'nextgroup=yamlKeyValueDelimiter'
-execute 'syn match yamlBlockMappingKey /\%#=1\s*\zs'.s:ns_plain_out.'\ze\s*:\%(\s\|$\)/ contained '.
+execute 'syn match yamlBlockMappingKey /\%#=1\s*\zs'.s:ns_plain_out.'\%(\s\+'.s:ns_plain_out.'\)*\ze\s*:\%(\s\|$\)/ contained '.
\'nextgroup=yamlKeyValueDelimiter'
syn match yamlBlockMappingMerge /^\s*\zs<<\ze:\%(\s\|$\)/ nextgroup=yamlKeyValueDelimiter
syn match yamlBlockMappingMerge /<<\ze\s*:\%(\s\|$\)/ nextgroup=yamlKeyValueDelimiter contained
@@ -119,14 +152,32 @@ syn match yamlBlockMappingMerge /<<\ze\s*:\%(\s\|$\)/ nextgroup=yamlKeyValueDeli
syn match yamlKeyValueDelimiter /\s*:/ contained
syn match yamlKeyValueDelimiter /\s*:/ contained
-syn keyword yamlConstant true True TRUE false False FALSE
-syn keyword yamlConstant null Null NULL
-syn match yamlConstant '\<\~\>'
-
-syn match yamlTimestamp /\%([\[\]{}, \t]\@!\p\)\@<!\%(\d\{4}-\d\d\=-\d\d\=\%(\%([Tt]\|\s\+\)\%(\d\d\=\):\%(\d\d\):\%(\d\d\)\%(\.\%(\d*\)\)\=\%(\s*\%(Z\|[+-]\d\d\=\%(:\d\d\)\=\)\)\=\)\=\)\%([\[\]{}, \t]\@!\p\)\@!/
+syn cluster yamlScalarWithSpecials contains=yamlPlainScalar,yamlBlockMappingKey,yamlFlowMappingKey
+
+let s:_bounder = s:SimplifyToAssumeAllPrintable('\%([[\]{}, \t]\@!\p\)')
+if b:yaml_schema is# 'json'
+ syn keyword yamlNull null contained containedin=@yamlScalarWithSpecials
+ syn keyword yamlBool true false
+ exe 'syn match yamlInteger /'.s:_bounder.'\@1<!\%(0\|-\=[1-9][0-9]*\)'.s:_bounder.'\@!/ contained containedin=@yamlScalarWithSpecials'
+ exe 'syn match yamlFloat /'.s:_bounder.'\@1<!\%(-\=[1-9][0-9]*\%(\.[0-9]*\)\=\(e[-+]\=[0-9]\+\)\=\|0\|-\=\.inf\|\.nan\)'.s:_bounder.'\@!/ contained containedin=@yamlScalarWithSpecials'
+elseif b:yaml_schema is# 'core'
+ syn keyword yamlNull null Null NULL contained containedin=@yamlScalarWithSpecials
+ syn keyword yamlBool true True TRUE false False FALSE contained containedin=@yamlScalarWithSpecials
+ exe 'syn match yamlNull /'.s:_bounder.'\@1<!\~'.s:_bounder.'\@!/ contained containedin=@yamlScalarWithSpecials'
+ exe 'syn match yamlInteger /'.s:_bounder.'\@1<!\%([+-]\=\%(0\%(b[0-1_]\+\|[0-7_]\+\|x[0-9a-fA-F_]\+\)\=\|\%([1-9][0-9_]*\%(:[0-5]\=\d\)\+\)\)\|[1-9][0-9_]*\)'.s:_bounder.'\@!/ contained containedin=@yamlScalarWithSpecials'
+ exe 'syn match yamlFloat /'.s:_bounder.'\@1<!\%([+-]\=\%(\%(\d[0-9_]*\)\.[0-9_]*\%([eE][+-]\=\d\+\)\=\|\.[0-9_]\+\%([eE][-+]\=[0-9]\+\)\=\|\d[0-9_]*\%(:[0-5]\=\d\)\+\.[0-9_]*\|\.\%(inf\|Inf\|INF\)\)\|\%(\.\%(nan\|NaN\|NAN\)\)\)'.s:_bounder.'\@!/ contained containedin=@yamlScalarWithSpecials'
+elseif b:yaml_schema is# 'pyyaml'
+ syn keyword yamlNull null Null NULL contained containedin=@yamlScalarWithSpecials
+ syn keyword yamlBool true True TRUE false False FALSE yes Yes YES no No NO on On ON off Off OFF contained containedin=@yamlScalarWithSpecials
+ exe 'syn match yamlNull /'.s:_bounder.'\@1<!\~'.s:_bounder.'\@!/ contained containedin=@yamlScalarWithSpecials'
+ exe 'syn match yamlFloat /'.s:_bounder.'\@1<!\%(\v[-+]?%(\d[0-9_]*)\.[0-9_]*%([eE][-+]\d+)?|\.[0-9_]+%([eE][-+]\d+)?|[-+]?\d[0-9_]*%(\:[0-5]?\d)+\.[0-9_]*|[-+]?\.%(inf|Inf|INF)|\.%(nan|NaN|NAN)\m\)'.s:_bounder.'\@!/ contained containedin=@yamlScalarWithSpecials'
+ exe 'syn match yamlInteger /'.s:_bounder.'\@1<!\%(\v[-+]?0b[0-1_]+|[-+]?0[0-7_]+|[-+]?%(0|[1-9][0-9_]*)|[-+]?0x[0-9a-fA-F_]+|[-+]?[1-9][0-9_]*%(:[0-5]?\d)+\m\)'.s:_bounder.'\@!/ contained containedin=@yamlScalarWithSpecials'
+ exe 'syn match yamlTimestamp /'.s:_bounder.'\@1<!\%(\v\d\d\d\d\-\d\d\-\d\d|\d\d\d\d \-\d\d? \-\d\d?%([Tt]|[ \t]+)\d\d?\:\d\d \:\d\d %(\.\d*)?%([ \t]*%(Z|[-+]\d\d?%(\:\d\d)?))?\m\)'.s:_bounder.'\@!/ contained containedin=@yamlScalarWithSpecials'
+elseif b:yaml_schema is# 'failsafe'
+ " Nothing
+endif
+unlet s:_bounder
-syn match yamlInteger /\%([\[\]{}, \t]\@!\p\)\@<!\%([+-]\=\%(0\%(b[0-1_]\+\|[0-7_]\+\|x[0-9a-fA-F_]\+\)\=\|\%([1-9][0-9_]*\%(:[0-5]\=\d\)\+\)\)\|[1-9][0-9_]*\)\%([\[\]{}, \t]\@!\p\)\@!/
-syn match yamlFloat /\%([\[\]{}, \t]\@!\p\)\@<!\%([+-]\=\%(\%(\d[0-9_]*\)\.[0-9_]*\%([eE][+-]\d\+\)\=\|\.[0-9_]\+\%([eE][-+][0-9]\+\)\=\|\d[0-9_]*\%(:[0-5]\=\d\)\+\.[0-9_]*\|\.\%(inf\|Inf\|INF\)\)\|\%(\.\%(nan\|NaN\|NAN\)\)\)\%([\[\]{}, \t]\@!\p\)\@!/
execute 'syn match yamlNodeTag '.string(s:c_ns_tag_property)
execute 'syn match yamlAnchor '.string(s:c_ns_anchor_property)
@@ -170,6 +221,9 @@ hi def link yamlKeyValueDelimiter Special
hi def link yamlConstant Constant
+hi def link yamlNull yamlConstant
+hi def link yamlBool yamlConstant
+
hi def link yamlAnchor Type
hi def link yamlAlias Type
hi def link yamlNodeTag Type
@@ -180,8 +234,10 @@ hi def link yamlTimestamp Number
let b:current_syntax = "yaml"
-unlet s:ns_word_char s:ns_uri_char s:c_verbatim_tag s:c_named_tag_handle s:c_secondary_tag_handle s:c_primary_tag_handle s:c_tag_handle s:ns_tag_char s:c_ns_shorthand_tag s:c_non_specific_tag s:c_ns_tag_property s:c_ns_anchor_char s:c_ns_anchor_name s:c_ns_anchor_property s:c_ns_alias_node s:ns_char s:ns_directive_name s:ns_local_tag_prefix s:ns_global_tag_prefix s:ns_tag_prefix s:c_indicator s:ns_plain_safe_out s:c_flow_indicator s:ns_plain_safe_in s:ns_plain_first_in s:ns_plain_first_out s:ns_plain_char_in s:ns_plain_char_out s:ns_plain_out s:ns_plain_in
+unlet s:ns_word_char s:ns_uri_char s:c_verbatim_tag s:c_named_tag_handle s:c_secondary_tag_handle s:c_primary_tag_handle s:c_tag_handle s:ns_tag_char s:c_ns_shorthand_tag s:c_non_specific_tag s:c_ns_tag_property s:c_ns_anchor_char s:c_ns_anchor_name s:c_ns_anchor_property s:c_ns_alias_node s:ns_char s:ns_directive_name s:ns_local_tag_prefix s:ns_global_tag_prefix s:ns_tag_prefix s:c_indicator s:ns_plain_safe_out s:c_flow_indicator s:ns_plain_safe_in s:ns_plain_first_in s:ns_plain_first_out s:ns_plain_char_in s:ns_plain_char_out s:ns_plain_out s:ns_plain_in s:ns_char_without_c_indicator s:ns_plain_safe_in_without_colhash s:ns_plain_safe_out_without_colhash
+unlet s:_collection s:_neg_collection
+delfunction s:SimplifyAdjacentCollections
+delfunction s:SimplifyToAssumeAllPrintable
let &cpo = s:cpo_save
unlet s:cpo_save
-
diff --git a/runtime/vimrc_example.vim b/runtime/vimrc_example.vim
index 97f646b91a..c53dde8ceb 100644
--- a/runtime/vimrc_example.vim
+++ b/runtime/vimrc_example.vim
@@ -1,8 +1,8 @@
" An example for a vimrc file.
"
" To use it, copy it to
-" for Unix: ~/.vimrc
-" for Windows: $VIM\_vimrc
+" for Unix: $HOME/.config/nvim/init.vim
+" for Windows: %LOCALAPPDATA%\nvim\init.vim
set backup " keep a backup file (restore to previous version)
set undofile " keep an undo file (undo changes after closing)
@@ -34,10 +34,8 @@ augroup vimrcEx
" When editing a file, always jump to the last known cursor position.
" Don't do it when the position is invalid or when inside an event handler
- " Also don't do it when the mark is in the first line, that is the default
- " position when opening a file.
autocmd BufReadPost *
- \ if line("'\"") > 1 && line("'\"") <= line("$") |
+ \ if line("'\"") >= 1 && line("'\"") <= line("$") |
\ execute "normal! g`\"" |
\ endif
diff --git a/scripts/gendeclarations.lua b/scripts/gendeclarations.lua
index 4e74e4e301..637f4cdffa 100755
--- a/scripts/gendeclarations.lua
+++ b/scripts/gendeclarations.lua
@@ -239,23 +239,24 @@ end
non_static = non_static .. footer
static = static .. footer
-local F
-F = io.open(static_fname, 'w')
-F:write(static)
-F:close()
--- Before generating the non-static headers, check if the current file(if
--- exists) is different from the new one. If they are the same, we won't touch
--- the current version to avoid triggering an unnecessary rebuilds of modules
+-- Before generating the headers, check if the current file (if exists) is
+-- different from the new one. If they are the same, we won't touch the
+-- current version to avoid triggering an unnecessary rebuilds of modules
-- that depend on this one
-F = io.open(non_static_fname, 'r')
-if F ~= nil then
- if F:read('*a') == non_static then
- os.exit(0)
+local update_changed = function (fname, contents)
+ local F = io.open(fname, 'r')
+ if F ~= nil then
+ if F:read('*a') == contents then
+ return
+ end
+ io.close(F)
end
- io.close(F)
+
+ F = io.open(fname, 'w')
+ F:write(contents)
+ F:close()
end
-F = io.open(non_static_fname, 'w')
-F:write(non_static)
-F:close()
+update_changed(static_fname, static)
+update_changed(non_static_fname, non_static)
diff --git a/scripts/genoptions.lua b/scripts/genoptions.lua
index 2859ca1795..da53d010bd 100644
--- a/scripts/genoptions.lua
+++ b/scripts/genoptions.lua
@@ -39,6 +39,7 @@ local redraw_flags={
local list_flags={
comma='P_COMMA',
+ onecomma='P_ONECOMMA',
flags='P_FLAGLIST',
flagscomma='P_COMMA|P_FLAGLIST',
}
diff --git a/scripts/legacy2luatest.pl b/scripts/legacy2luatest.pl
index ebd8dad1e1..8155353fc7 100755
--- a/scripts/legacy2luatest.pl
+++ b/scripts/legacy2luatest.pl
@@ -287,7 +287,7 @@ local feed, insert, source = helpers.feed, helpers.insert, helpers.source
local clear, execute, expect = helpers.clear, helpers.execute, helpers.expect
describe('$test_name', function()
- setup(clear)
+ before_each(clear)
it('is working', function()
@{[join "\n", map { /^$/ ? '' : ' ' . $_ } @{$test_body_lines}]}
diff --git a/scripts/vim-patch.sh b/scripts/vim-patch.sh
index bdd3d6209b..7612a2ada0 100755
--- a/scripts/vim-patch.sh
+++ b/scripts/vim-patch.sh
@@ -5,9 +5,12 @@ set -u
set -o pipefail
readonly NEOVIM_SOURCE_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
-readonly VIM_SOURCE_DIR_DEFAULT=${NEOVIM_SOURCE_DIR}/.vim-src
+readonly VIM_SOURCE_DIR_DEFAULT="${NEOVIM_SOURCE_DIR}/.vim-src"
readonly VIM_SOURCE_DIR="${VIM_SOURCE_DIR:-${VIM_SOURCE_DIR_DEFAULT}}"
readonly BASENAME="$(basename "${0}")"
+readonly BRANCH_PREFIX="vim-"
+
+CREATED_FILES=()
usage() {
echo "Helper script for porting Vim patches. For more information, see"
@@ -21,6 +24,7 @@ usage() {
echo " -p {vim-revision} Download and apply the Vim patch vim-revision."
echo " vim-revision can be a version number of the "
echo " format '7.4.xxx' or a Git commit hash."
+ echo " -s Submit a vim-patch pull request to Neovim."
echo " -r {pr-number} Review a vim-patch pull request to Neovim."
echo
echo "Set VIM_SOURCE_DIR to change where Vim's sources are stored."
@@ -35,6 +39,27 @@ check_executable() {
fi
}
+clean_files() {
+ if [[ ${#CREATED_FILES[@]} -eq 0 ]]; then
+ return
+ fi
+
+ echo
+ echo "Created files:"
+ local file
+ for file in ${CREATED_FILES[@]}; do
+ echo " • ${file}"
+ done
+
+ read -p "Delete these files (Y/n)? " -n 1 -r reply
+ echo
+ if [[ "${reply}" =~ ^[Yy]$ ]]; then
+ rm -- ${CREATED_FILES[@]}
+ else
+ echo "You can use 'git clean' to remove these files when you're done."
+ fi
+}
+
get_vim_sources() {
check_executable git
@@ -66,22 +91,26 @@ assign_commit_details() {
# Interpret parameter as version number (tag).
vim_version="${1}"
vim_tag="v${1}"
- vim_commit=$( cd "${VIM_SOURCE_DIR}" \
- && git log -1 --format="%H" ${vim_tag} )
+ vim_commit=$(cd "${VIM_SOURCE_DIR}" \
+ && git log -1 --format="%H" ${vim_tag})
local strip_commit_line=true
else
# Interpret parameter as commit hash.
vim_version="${1:0:7}"
- vim_commit="${1}"
+ vim_commit=$(cd "${VIM_SOURCE_DIR}" \
+ && git log -1 --format="%H" ${vim_version})
local strip_commit_line=false
fi
vim_commit_url="https://github.com/vim/vim/commit/${vim_commit}"
- vim_message="$(git log -1 --pretty='format:%B' "${vim_commit}")"
+ vim_message="$(cd "${VIM_SOURCE_DIR}" \
+ && git log -1 --pretty='format:%B' "${vim_commit}" \
+ | sed -e 's/\(#[0-9]*\)/vim\/vim\1/g')"
if [[ ${strip_commit_line} == "true" ]]; then
# Remove first line of commit message.
vim_message="$(echo "${vim_message}" | sed -e '1d')"
fi
+ patch_file="vim-${vim_version}.patch"
}
get_vim_patch() {
@@ -96,66 +125,108 @@ get_vim_patch() {
echo
echo "✔ Found Vim revision '${vim_commit}'."
- # Collect patch details and store into variables.
- vim_full="$(git show -1 --pretty=medium "${vim_commit}")"
# Patch surgery: preprocess the patch.
# - transform src/ paths to src/nvim/
- vim_diff="$(git show -1 "${vim_commit}" \
+ local vim_full="$(git show -1 --pretty=medium "${vim_commit}" \
| LC_ALL=C sed -e 's/\( [ab]\/src\)/\1\/nvim/g')"
- neovim_message="$(commit_message)"
- neovim_pr="
-\`\`\`
-${vim_message}
-\`\`\`
-
-${vim_commit_url}
-
-Original patch:
-
-\`\`\`diff
-${vim_diff}
-\`\`\`"
- neovim_branch="vim-${vim_version}"
+ local neovim_branch="${BRANCH_PREFIX}${vim_version}"
- echo
- echo "Creating Git branch."
cd "${NEOVIM_SOURCE_DIR}"
- output="$(git checkout -b "${neovim_branch}" 2>&1)" &&
- echo "✔ ${output}" ||
- (echo "✘ ${output}"; false)
+ local checked_out_branch="$(git rev-parse --abbrev-ref HEAD)"
+ if [[ "${checked_out_branch}" == ${BRANCH_PREFIX}* ]]; then
+ echo "✔ Current branch '${checked_out_branch}' seems to be a vim-patch"
+ echo " branch; not creating a new branch."
+ else
+ echo
+ echo "Fetching 'upstream/master'."
+ output="$(git fetch upstream master 2>&1)" &&
+ echo "✔ ${output}" ||
+ (echo "✘ ${output}"; false)
+
+ echo
+ echo "Creating new branch '${neovim_branch}' based on 'upstream/master'."
+ cd "${NEOVIM_SOURCE_DIR}"
+ output="$(git checkout -b "${neovim_branch}" upstream/master 2>&1)" &&
+ echo "✔ ${output}" ||
+ (echo "✘ ${output}"; false)
+ fi
echo
echo "Creating empty commit with correct commit message."
- output="$(git commit --allow-empty --file 2>&1 - <<< "${neovim_message}")" &&
+ output="$(commit_message | git commit --allow-empty --file 2>&1 -)" &&
echo "✔ ${output}" ||
(echo "✘ ${output}"; false)
echo
echo "Creating files."
- echo "${vim_diff}" > "${NEOVIM_SOURCE_DIR}/${neovim_branch}.diff"
- echo "✔ Saved diff to '${NEOVIM_SOURCE_DIR}/${neovim_branch}.diff'."
- echo "${vim_full}" > "${NEOVIM_SOURCE_DIR}/${neovim_branch}.patch"
- echo "✔ Saved full commit details to '${NEOVIM_SOURCE_DIR}/${neovim_branch}.patch'."
- echo "${neovim_pr}" > "${NEOVIM_SOURCE_DIR}/${neovim_branch}.pr"
- echo "✔ Saved suggested PR description to '${NEOVIM_SOURCE_DIR}/${neovim_branch}.pr'."
- echo "You can use 'git clean' to remove these files when you're done."
+ echo "${vim_full}" > "${NEOVIM_SOURCE_DIR}/${patch_file}"
+ echo "✔ Saved full commit details to '${NEOVIM_SOURCE_DIR}/${patch_file}'."
echo
echo "Instructions:"
echo
echo " Proceed to port the patch."
- echo " You might want to try 'patch -p1 < ${neovim_branch}.diff' first."
+ echo " You might want to try 'patch -p1 < ${patch_file}' first."
+ echo
+ echo " If the patch contains a new test, consider porting it to Lua."
+ echo " You might want to try 'scripts/legacy2luatest.pl'."
echo
echo " Stage your changes ('git add ...') and use 'git commit --amend' to commit."
echo
- echo " Push your changes with 'git push origin ${neovim_branch}' and create a"
- echo " pull request called '[RFC] vim-patch:${vim_version}'. You might want "
- echo " to use the text in '${neovim_branch}.pr' as the description of this pull request."
+ echo " To port additional patches related to ${vim_version} and add them to the current"
+ echo " branch, call '${BASENAME} -p' again. Please use this only if it wouldn't make"
+ echo " sense to send in each patch individually, as it will increase the size of the"
+ echo " pull request and make it harder to review."
+ echo
+ echo " When you are finished, use '${BASENAME} -s' to submit a pull request."
echo
echo " See https://github.com/neovim/neovim/wiki/Merging-patches-from-upstream-vim"
echo " for more information."
}
+submit_pr() {
+ check_executable git
+ check_executable hub
+
+ cd "${NEOVIM_SOURCE_DIR}"
+ local checked_out_branch="$(git rev-parse --abbrev-ref HEAD)"
+ if [[ "${checked_out_branch}" != ${BRANCH_PREFIX}* ]]; then
+ echo "✘ Current branch '${checked_out_branch}' doesn't seem to be a vim-patch branch."
+ exit 1
+ fi
+
+ local pr_body="$(git log --reverse --format='#### %s%n%n%b%n' upstream/master..HEAD)"
+ local patches=("$(git log --reverse --format='%s' upstream/master..HEAD)")
+ patches=(${patches[@]//vim-patch:}) # Remove 'vim-patch:' prefix for each item in array.
+ local pr_title="${patches[@]}" # Create space-separated string from array.
+ pr_title="${pr_title// /,}" # Replace spaces with commas.
+
+ local pr_message="$(printf '[RFC] vim-patch:%s\n\n%s\n' "${pr_title#,}" "${pr_body}")"
+
+ echo "Pushing to 'origin/${checked_out_branch}'."
+ output="$(git push origin "${checked_out_branch}" 2>&1)" &&
+ echo "✔ ${output}" ||
+ (echo "✘ ${output}"; git reset --soft HEAD^1; false)
+
+ echo
+ echo "Creating pull request."
+ output="$(hub pull-request -F - 2>&1 <<< "${pr_message}")" &&
+ echo "✔ ${output}" ||
+ (echo "✘ ${output}"; false)
+
+ echo
+ echo "Cleaning up files."
+ local patch_file
+ for patch_file in ${patches[@]}; do
+ patch_file="vim-${patch_file}.patch"
+ if [[ ! -f "${NEOVIM_SOURCE_DIR}/${patch_file}" ]]; then
+ continue
+ fi
+ rm -- "${NEOVIM_SOURCE_DIR}/${patch_file}"
+ echo "✔ Removed '${NEOVIM_SOURCE_DIR}/${patch_file}'."
+ done
+}
+
list_vim_patches() {
get_vim_sources
@@ -189,7 +260,8 @@ list_vim_patches() {
echo "Instructions:"
echo
echo " To port one of the above patches to Neovim, execute"
- echo " this script with the patch revision as argument."
+ echo " this script with the patch revision as argument and"
+ echo " follow the instructions."
echo
echo " Examples: '${BASENAME} -p 7.4.487'"
echo " '${BASENAME} -p 1e8ebf870720e7b671f98f22d653009826304c4f'"
@@ -198,32 +270,28 @@ list_vim_patches() {
echo " Out-of-order patches increase the possibility of bugs."
}
-review_pr() {
- check_executable curl
- check_executable nvim
-
- get_vim_sources
-
- local pr="${1}"
- echo
- echo "Downloading data for pull request #${pr}."
+review_commit() {
+ local neovim_commit_url="${1}"
+ local neovim_patch_url="${neovim_commit_url}.patch"
local git_patch_prefix='Subject: \[PATCH\] '
- local neovim_patch="$(curl -Ssf "https://patch-diff.githubusercontent.com/raw/neovim/neovim/pull/${pr}.patch")"
- echo "${neovim_patch}" > a
+ local neovim_patch="$(curl -Ssf "${neovim_patch_url}")"
local vim_version="$(head -n 4 <<< "${neovim_patch}" | sed -n "s/${git_patch_prefix}vim-patch:\([a-z0-9.]*\)$/\1/p")"
+ echo
if [[ -n "${vim_version}" ]]; then
echo "✔ Detected Vim patch '${vim_version}'."
else
echo "✘ Could not detect the Vim patch number."
- echo " This script assumes that the PR contains a single commit"
- echo " with 'vim-patch:XXX' as its title."
+ echo " This script assumes that the PR contains only commits"
+ echo " with 'vim-patch:XXX' in their title."
exit 1
fi
assign_commit_details "${vim_version}"
+ local vim_patch_url="${vim_commit_url}.patch"
+
local expected_commit_message="$(commit_message)"
local message_length="$(wc -l <<< "${expected_commit_message}")"
local commit_message="$(tail -n +4 <<< "${neovim_patch}" | head -n "${message_length}")"
@@ -235,26 +303,57 @@ review_pr() {
echo "${expected_commit_message}"
echo " Actual:"
echo "${commit_message#${git_patch_prefix}}"
- exit 1
fi
- local base_name="vim-${vim_version}"
echo
echo "Creating files."
- curl -Ssfo "${NEOVIM_SOURCE_DIR}/n${base_name}.diff" "https://patch-diff.githubusercontent.com/raw/neovim/neovim/pull/${pr}.diff"
- echo "✔ Saved pull request diff to '${NEOVIM_SOURCE_DIR}/n${base_name}.diff'."
- echo "${neovim_patch}" > "${NEOVIM_SOURCE_DIR}/n${base_name}.patch"
- echo "✔ Saved full pull request commit details to '${NEOVIM_SOURCE_DIR}/n${base_name}.patch'."
- git show "${vim_commit}" > "${NEOVIM_SOURCE_DIR}/${base_name}.diff"
- echo "✔ Saved Vim diff to '${NEOVIM_SOURCE_DIR}/${base_name}.diff'."
- echo "You can use 'git clean' to remove these files when you're done."
+ echo "${neovim_patch}" > "${NEOVIM_SOURCE_DIR}/n${patch_file}"
+ echo "✔ Saved pull request diff to '${NEOVIM_SOURCE_DIR}/n${patch_file}'."
+ CREATED_FILES+=("${NEOVIM_SOURCE_DIR}/n${patch_file}")
+
+ curl -Ssfo "${NEOVIM_SOURCE_DIR}/${patch_file}" "${vim_patch_url}"
+ echo "✔ Saved Vim diff to '${NEOVIM_SOURCE_DIR}/${patch_file}'."
+ CREATED_FILES+=("${NEOVIM_SOURCE_DIR}/${patch_file}")
echo
echo "Launching nvim."
- exec nvim -O "${NEOVIM_SOURCE_DIR}/${base_name}.diff" "${NEOVIM_SOURCE_DIR}/n${base_name}.diff"
+ nvim -c "cd ${NEOVIM_SOURCE_DIR}" \
+ -O "${NEOVIM_SOURCE_DIR}/${patch_file}" "${NEOVIM_SOURCE_DIR}/n${patch_file}"
}
-while getopts "hlp:r:" opt; do
+review_pr() {
+ check_executable curl
+ check_executable nvim
+ check_executable jq
+
+ get_vim_sources
+
+ local pr="${1}"
+ echo
+ echo "Downloading data for pull request #${pr}."
+
+ local pr_commit_urls=($(curl -Ssf "https://api.github.com/repos/neovim/neovim/pulls/${pr}/commits" \
+ | jq -r '.[].html_url'))
+
+ echo "Found ${#pr_commit_urls[@]} commit(s)."
+
+ local pr_commit_url
+ local reply
+ for pr_commit_url in ${pr_commit_urls[@]}; do
+ review_commit "${pr_commit_url}"
+ if [[ "${pr_commit_url}" != "${pr_commit_urls[-1]}" ]]; then
+ read -p "Continue with next commit (Y/n)? " -n 1 -r reply
+ echo
+ if [[ ! "${reply}" =~ ^[Yy]$ ]]; then
+ break
+ fi
+ fi
+ done
+
+ clean_files
+}
+
+while getopts "hlp:r:s" opt; do
case ${opt} in
h)
usage
@@ -272,6 +371,10 @@ while getopts "hlp:r:" opt; do
review_pr "${OPTARG}"
exit 0
;;
+ s)
+ submit_pr
+ exit 0
+ ;;
*)
exit 1
;;
diff --git a/src/nvim/README.md b/src/nvim/README.md
index e4939d94fd..f16c6de12f 100644
--- a/src/nvim/README.md
+++ b/src/nvim/README.md
@@ -11,7 +11,7 @@ that are constantly changing. As the code becomes more organized and stable,
this document will be updated to reflect the changes.
If you are looking for module-specific details, it is best to read the source
-code. Some files are extensively commented at the top(eg: terminal.c,
+code. Some files are extensively commented at the top (e.g. terminal.c,
screen.c).
### Top-level program loops
@@ -43,13 +43,13 @@ a typical editing session:
Note that we have split user actions into sequences of inputs that change the
state of the editor. While there's no documentation about a "g command
-mode"(step 16), internally it is implemented similarly to "operator-pending
+mode" (step 16), internally it is implemented similarly to "operator-pending
mode".
From this we can see that Vim has the behavior of a input-driven state
-machine(more specifically, a pushdown automaton since it requires a stack for
+machine (more specifically, a pushdown automaton since it requires a stack for
transitioning back from states). Assuming each state has a callback responsible
-for handling keys, this pseudocode(a python-like language) shows a good
+for handling keys, this pseudocode (a python-like language) shows a good
representation of the main program loop:
```py
@@ -129,20 +129,20 @@ def insert_state(data, key):
While the actual code is much more complicated, the above gives an idea of how
Neovim is organized internally. Some states like the `g_command_state` or
`get_operator_count_state` do not have a dedicated `state_enter` callback, but
-are implicitly embedded into other states(this will change later as we continue
+are implicitly embedded into other states (this will change later as we continue
the refactoring effort). To start reading the actual code, here's the
recommended order:
-1. `state_enter()` function(state.c). This is the actual program loop,
+1. `state_enter()` function (state.c). This is the actual program loop,
note that a `VimState` structure is used, which contains function pointers
for the callback and state data.
-2. `main()` function(main.c). After all startup, `normal_enter` is called
+2. `main()` function (main.c). After all startup, `normal_enter` is called
at the end of function to enter normal mode.
-3. `normal_enter()` function(normal.c) is a small wrapper for setting
+3. `normal_enter()` function (normal.c) is a small wrapper for setting
up the NormalState structure and calling `state_enter`.
-4. `normal_check()` function(normal.c) is called before each iteration of
+4. `normal_check()` function (normal.c) is called before each iteration of
normal mode.
-5. `normal_execute()` function(normal.c) is called when a key is read in normal
+5. `normal_execute()` function (normal.c) is called when a key is read in normal
mode.
The basic structure described for normal mode in 3, 4 and 5 is used for other
@@ -159,7 +159,7 @@ asynchronous events, which can include:
- msgpack-rpc requests
- job control callbacks
-- timers(not implemented yet but the support code is already there)
+- timers (not implemented yet but the support code is already there)
Neovim implements this functionality by entering another event loop while
waiting for characters, so instead of:
@@ -180,11 +180,11 @@ def state_enter(state_callback, data):
while state_callback(data, event) # invoke the callback for the current state
```
-where `event` is something the operating system delivers to us, including(but
+where `event` is something the operating system delivers to us, including (but
not limited to) user input. The `read_next_event()` part is internally
implemented by libuv, the platform layer used by Neovim.
Since Neovim inherited its code from Vim, the states are not prepared to receive
-"arbitrary events", so we use a special key to represent those(When a state
+"arbitrary events", so we use a special key to represent those (When a state
receives an "arbitrary event", it normally doesn't do anything other update the
screen).
diff --git a/src/nvim/buffer.c b/src/nvim/buffer.c
index a6e3fedd3f..c05090bbf6 100644
--- a/src/nvim/buffer.c
+++ b/src/nvim/buffer.c
@@ -22,6 +22,7 @@
#include "nvim/api/private/handle.h"
#include "nvim/ascii.h"
+#include "nvim/assert.h"
#include "nvim/vim.h"
#include "nvim/buffer.h"
#include "nvim/charset.h"
@@ -1600,21 +1601,28 @@ int buflist_getfile(int n, linenr_T lnum, int options, int forceit)
col = 0;
if (options & GETF_SWITCH) {
- /* If 'switchbuf' contains "useopen": jump to first window containing
- * "buf" if one exists */
- if (swb_flags & SWB_USEOPEN)
+ // If 'switchbuf' contains "useopen": jump to first window containing
+ // "buf" if one exists
+ if (swb_flags & SWB_USEOPEN) {
wp = buf_jump_open_win(buf);
- /* If 'switchbuf' contains "usetab": jump to first window in any tab
- * page containing "buf" if one exists */
- if (wp == NULL && (swb_flags & SWB_USETAB))
+ }
+
+ // If 'switchbuf' contains "usetab": jump to first window in any tab
+ // page containing "buf" if one exists
+ if (wp == NULL && (swb_flags & SWB_USETAB)) {
wp = buf_jump_open_tab(buf);
- /* If 'switchbuf' contains "split" or "newtab" and the current buffer
- * isn't empty: open new window */
- if (wp == NULL && (swb_flags & (SWB_SPLIT | SWB_NEWTAB)) && !bufempty()) {
- if (swb_flags & SWB_NEWTAB) /* Open in a new tab */
+ }
+
+ // If 'switchbuf' contains "split", "vsplit" or "newtab" and the
+ // current buffer isn't empty: open new tab or window
+ if (wp == NULL && (swb_flags & (SWB_VSPLIT | SWB_SPLIT | SWB_NEWTAB))
+ && !bufempty()) {
+ if (swb_flags & SWB_NEWTAB) {
tabpage_new();
- else if (win_split(0, 0) == FAIL) /* Open in a new window */
+ } else if (win_split(0, (swb_flags & SWB_VSPLIT) ? WSP_VERT : 0)
+ == FAIL) {
return FAIL;
+ }
RESET_BINDING(curwin);
}
}
@@ -1733,12 +1741,15 @@ int buflist_findpat(
int toggledollar;
if (pattern_end == pattern + 1 && (*pattern == '%' || *pattern == '#')) {
- if (*pattern == '%')
+ if (*pattern == '%') {
match = curbuf->b_fnum;
- else
+ } else {
match = curwin->w_alt_fnum;
- if (diffmode && !diff_mode_buf(buflist_findnr(match)))
+ }
+ buf_T *found_buf = buflist_findnr(match);
+ if (diffmode && !(found_buf && diff_mode_buf(found_buf))) {
match = -1;
+ }
}
/*
* Try four ways of matching a listed buffer:
@@ -2826,7 +2837,7 @@ typedef enum {
/// @param fillchar Character to use when filling empty space in the statusline
/// @param maxwidth The maximum width to make the statusline
/// @param hltab HL attributes (can be NULL)
-/// @param tabtab tab page nrs (can be NULL)
+/// @param tabtab Tab clicks definition (can be NULL).
///
/// @return The final width of the statusline
int build_stl_str_hl(
@@ -2838,13 +2849,15 @@ int build_stl_str_hl(
int fillchar,
int maxwidth,
struct stl_hlrec *hltab,
- struct stl_hlrec *tabtab
+ StlClickRecord *tabtab
)
{
int groupitem[STL_MAX_ITEM];
struct stl_item {
// Where the item starts in the status line output buffer
- char_u *start;
+ char_u *start;
+ // Function to run for ClickFunc items.
+ char *cmd;
// The minimum width of the item
int minwid;
// The maximum width of the item
@@ -2856,10 +2869,10 @@ int build_stl_str_hl(
Middle,
Highlight,
TabPage,
+ ClickFunc,
Trunc
- } type;
- } item[STL_MAX_ITEM];
-
+ } type;
+ } item[STL_MAX_ITEM];
#define TMPLEN 70
char_u tmp[TMPLEN];
char_u *usefmt = fmt;
@@ -3164,6 +3177,24 @@ int build_stl_str_hl(
continue;
}
+ if (*fmt_p == STL_CLICK_FUNC) {
+ fmt_p++;
+ char *t = (char *) fmt_p;
+ while (*fmt_p != STL_CLICK_FUNC && *fmt_p) {
+ fmt_p++;
+ }
+ if (*fmt_p != STL_CLICK_FUNC) {
+ break;
+ }
+ item[curitem].type = ClickFunc;
+ item[curitem].start = out_p;
+ item[curitem].cmd = xmemdupz(t, (size_t) (((char *) fmt_p - t)));
+ item[curitem].minwid = minwid;
+ fmt_p++;
+ curitem++;
+ continue;
+ }
+
// Denotes the end of the minwid
// the maxwid may follow immediately after
if (*fmt_p == '.') {
@@ -3281,6 +3312,7 @@ int build_stl_str_hl(
}
break;
}
+
case STL_LINE:
num = (wp->w_buffer->b_ml.ml_flags & ML_EMPTY)
? 0L : (long)(wp->w_cursor.lnum);
@@ -3821,16 +3853,37 @@ int build_stl_str_hl(
// Store the info about tab pages labels.
if (tabtab != NULL) {
- struct stl_hlrec *sp = tabtab;
+ StlClickRecord *cur_tab_rec = tabtab;
for (long l = 0; l < itemcnt; l++) {
if (item[l].type == TabPage) {
- sp->start = item[l].start;
- sp->userhl = item[l].minwid;
- sp++;
+ cur_tab_rec->start = (char *) item[l].start;
+ if (item[l].minwid == 0) {
+ cur_tab_rec->def.type = kStlClickDisabled;
+ cur_tab_rec->def.tabnr = 0;
+ } else {
+ int tabnr = item[l].minwid;
+ if (item[l].minwid > 0) {
+ cur_tab_rec->def.type = kStlClickTabSwitch;
+ } else {
+ cur_tab_rec->def.type = kStlClickTabClose;
+ tabnr = -tabnr;
+ }
+ cur_tab_rec->def.tabnr = tabnr;
+ }
+ cur_tab_rec->def.func = NULL;
+ cur_tab_rec++;
+ } else if (item[l].type == ClickFunc) {
+ cur_tab_rec->start = (char *) item[l].start;
+ cur_tab_rec->def.type = kStlClickFuncRun;
+ cur_tab_rec->def.tabnr = item[l].minwid;
+ cur_tab_rec->def.func = item[l].cmd;
+ cur_tab_rec++;
}
}
- sp->start = NULL;
- sp->userhl = 0;
+ cur_tab_rec->start = NULL;
+ cur_tab_rec->def.type = kStlClickDisabled;
+ cur_tab_rec->def.tabnr = 0;
+ cur_tab_rec->def.func = NULL;
}
return width;
@@ -3852,6 +3905,11 @@ void get_rel_pos(win_T *wp, char_u *buf, int buflen)
above = wp->w_topline - 1;
above += diff_check_fill(wp, wp->w_topline) - wp->w_topfill;
+ if (wp->w_topline == 1 && wp->w_topfill >= 1) {
+ // All buffer lines are displayed and there is an indication
+ // of filler lines, that can be considered seeing all lines.
+ above = 0;
+ }
below = wp->w_buffer->b_ml.ml_line_count - wp->w_botline + 1;
if (below <= 0)
STRLCPY(buf, (above == 0 ? _("All") : _("Bot")), buflen);
diff --git a/src/nvim/buffer.h b/src/nvim/buffer.h
index 49025d3925..d51a2f7dae 100644
--- a/src/nvim/buffer.h
+++ b/src/nvim/buffer.h
@@ -4,6 +4,7 @@
#include "nvim/window.h"
#include "nvim/pos.h" // for linenr_T
#include "nvim/ex_cmds_defs.h" // for exarg_T
+#include "nvim/screen.h" // for StlClickRecord
// Values for buflist_getfile()
enum getf_values {
diff --git a/src/nvim/buffer_defs.h b/src/nvim/buffer_defs.h
index 78d9a9484e..bdea609820 100644
--- a/src/nvim/buffer_defs.h
+++ b/src/nvim/buffer_defs.h
@@ -592,71 +592,72 @@ struct file_buffer {
int b_p_scriptID[BV_COUNT]; /* SIDs for buffer-local options */
- int b_p_ai; /* 'autoindent' */
- int b_p_ai_nopaste; /* b_p_ai saved for paste mode */
- char_u *b_p_bkc; ///< 'backupcopy'
- unsigned int b_bkc_flags; ///< flags for 'backupcopy'
- int b_p_ci; /* 'copyindent' */
- int b_p_bin; /* 'binary' */
- int b_p_bomb; /* 'bomb' */
- char_u *b_p_bh; /* 'bufhidden' */
- char_u *b_p_bt; /* 'buftype' */
- int b_p_bl; /* 'buflisted' */
- int b_p_cin; /* 'cindent' */
- char_u *b_p_cino; /* 'cinoptions' */
- char_u *b_p_cink; /* 'cinkeys' */
- char_u *b_p_cinw; /* 'cinwords' */
- char_u *b_p_com; /* 'comments' */
- char_u *b_p_cms; /* 'commentstring' */
- char_u *b_p_cpt; /* 'complete' */
- char_u *b_p_cfu; /* 'completefunc' */
- char_u *b_p_ofu; /* 'omnifunc' */
- int b_p_eol; /* 'endofline' */
- int b_p_fixeol; /* 'fixendofline' */
- int b_p_et; /* 'expandtab' */
- int b_p_et_nobin; /* b_p_et saved for binary mode */
- char_u *b_p_fenc; /* 'fileencoding' */
- char_u *b_p_ff; /* 'fileformat' */
- char_u *b_p_ft; /* 'filetype' */
- char_u *b_p_fo; /* 'formatoptions' */
- char_u *b_p_flp; /* 'formatlistpat' */
- int b_p_inf; /* 'infercase' */
- char_u *b_p_isk; /* 'iskeyword' */
- char_u *b_p_def; /* 'define' local value */
- char_u *b_p_inc; /* 'include' */
- char_u *b_p_inex; /* 'includeexpr' */
- uint32_t b_p_inex_flags; /* flags for 'includeexpr' */
- char_u *b_p_inde; /* 'indentexpr' */
- uint32_t b_p_inde_flags; /* flags for 'indentexpr' */
- char_u *b_p_indk; /* 'indentkeys' */
- char_u *b_p_fex; /* 'formatexpr' */
- uint32_t b_p_fex_flags; /* flags for 'formatexpr' */
- char_u *b_p_kp; /* 'keywordprg' */
- int b_p_lisp; /* 'lisp' */
- char_u *b_p_mps; /* 'matchpairs' */
- int b_p_ml; /* 'modeline' */
- int b_p_ml_nobin; /* b_p_ml saved for binary mode */
- int b_p_ma; /* 'modifiable' */
- char_u *b_p_nf; /* 'nrformats' */
- int b_p_pi; /* 'preserveindent' */
- char_u *b_p_qe; /* 'quoteescape' */
- int b_p_ro; /* 'readonly' */
- long b_p_sw; /* 'shiftwidth' */
- int b_p_si; /* 'smartindent' */
- long b_p_sts; /* 'softtabstop' */
- long b_p_sts_nopaste; /* b_p_sts saved for paste mode */
- char_u *b_p_sua; /* 'suffixesadd' */
- bool b_p_swf; /* 'swapfile' */
- long b_p_smc; /* 'synmaxcol' */
- char_u *b_p_syn; /* 'syntax' */
- long b_p_ts; /* 'tabstop' */
- long b_p_tw; /* 'textwidth' */
- long b_p_tw_nobin; /* b_p_tw saved for binary mode */
- long b_p_tw_nopaste; /* b_p_tw saved for paste mode */
- long b_p_wm; /* 'wrapmargin' */
- long b_p_wm_nobin; /* b_p_wm saved for binary mode */
- long b_p_wm_nopaste; /* b_p_wm saved for paste mode */
- char_u *b_p_keymap; /* 'keymap' */
+ int b_p_ai; ///< 'autoindent'
+ int b_p_ai_nopaste; ///< b_p_ai saved for paste mode
+ char_u *b_p_bkc; ///< 'backupco
+ unsigned int b_bkc_flags; ///< flags for 'backupco
+ int b_p_ci; ///< 'copyindent'
+ int b_p_bin; ///< 'binary'
+ int b_p_bomb; ///< 'bomb'
+ char_u *b_p_bh; ///< 'bufhidden'
+ char_u *b_p_bt; ///< 'buftype'
+ int b_p_bl; ///< 'buflisted'
+ int b_p_cin; ///< 'cindent'
+ char_u *b_p_cino; ///< 'cinoptions'
+ char_u *b_p_cink; ///< 'cinkeys'
+ char_u *b_p_cinw; ///< 'cinwords'
+ char_u *b_p_com; ///< 'comments'
+ char_u *b_p_cms; ///< 'commentstring'
+ char_u *b_p_cpt; ///< 'complete'
+ char_u *b_p_cfu; ///< 'completefunc'
+ char_u *b_p_ofu; ///< 'omnifunc'
+ int b_p_eol; ///< 'endofline'
+ int b_p_fixeol; ///< 'fixendofline'
+ int b_p_et; ///< 'expandtab'
+ int b_p_et_nobin; ///< b_p_et saved for binary mode
+ int b_p_et_nopaste; ///< b_p_et saved for paste mode
+ char_u *b_p_fenc; ///< 'fileencoding'
+ char_u *b_p_ff; ///< 'fileformat'
+ char_u *b_p_ft; ///< 'filetype'
+ char_u *b_p_fo; ///< 'formatoptions'
+ char_u *b_p_flp; ///< 'formatlistpat'
+ int b_p_inf; ///< 'infercase'
+ char_u *b_p_isk; ///< 'iskeyword'
+ char_u *b_p_def; ///< 'define' local value
+ char_u *b_p_inc; ///< 'include'
+ char_u *b_p_inex; ///< 'includeexpr'
+ uint32_t b_p_inex_flags; ///< flags for 'includeexpr'
+ char_u *b_p_inde; ///< 'indentexpr'
+ uint32_t b_p_inde_flags; ///< flags for 'indentexpr'
+ char_u *b_p_indk; ///< 'indentkeys'
+ char_u *b_p_fex; ///< 'formatexpr'
+ uint32_t b_p_fex_flags; ///< flags for 'formatexpr'
+ char_u *b_p_kp; ///< 'keywordprg'
+ int b_p_lisp; ///< 'lisp'
+ char_u *b_p_mps; ///< 'matchpairs'
+ int b_p_ml; ///< 'modeline'
+ int b_p_ml_nobin; ///< b_p_ml saved for binary mode
+ int b_p_ma; ///< 'modifiable'
+ char_u *b_p_nf; ///< 'nrformats'
+ int b_p_pi; ///< 'preserveindent'
+ char_u *b_p_qe; ///< 'quoteescape'
+ int b_p_ro; ///< 'readonly'
+ long b_p_sw; ///< 'shiftwidth'
+ int b_p_si; ///< 'smartindent'
+ long b_p_sts; ///< 'softtabstop'
+ long b_p_sts_nopaste; ///< b_p_sts saved for paste mode
+ char_u *b_p_sua; ///< 'suffixesadd'
+ bool b_p_swf; ///< 'swapfile'
+ long b_p_smc; ///< 'synmaxcol'
+ char_u *b_p_syn; ///< 'syntax'
+ long b_p_ts; ///< 'tabstop'
+ long b_p_tw; ///< 'textwidth'
+ long b_p_tw_nobin; ///< b_p_tw saved for binary mode
+ long b_p_tw_nopaste; ///< b_p_tw saved for paste mode
+ long b_p_wm; ///< 'wrapmargin'
+ long b_p_wm_nobin; ///< b_p_wm saved for binary mode
+ long b_p_wm_nopaste; ///< b_p_wm saved for paste mode
+ char_u *b_p_keymap; ///< 'keymap'
/* local values for options which are normally global */
char_u *b_p_gp; /* 'grepprg' local value */
@@ -904,13 +905,14 @@ struct posmatch
typedef struct matchitem matchitem_T;
struct matchitem {
matchitem_T *next;
- int id; /* match ID */
- int priority; /* match priority */
- char_u *pattern; /* pattern to highlight */
- int hlg_id; /* highlight group ID */
- regmmatch_T match; /* regexp program for pattern */
- posmatch_T pos; // position matches
- match_T hl; /* struct for doing the actual highlighting */
+ int id; ///< match ID
+ int priority; ///< match priority
+ char_u *pattern; ///< pattern to highlight
+ int hlg_id; ///< highlight group ID
+ regmmatch_T match; ///< regexp program for pattern
+ posmatch_T pos; ///< position matches
+ match_T hl; ///< struct for doing the actual highlighting
+ int conceal_char; ///< cchar for Conceal highlighting
};
/*
diff --git a/src/nvim/charset.c b/src/nvim/charset.c
index e0c9443511..4e329b5cd8 100644
--- a/src/nvim/charset.c
+++ b/src/nvim/charset.c
@@ -799,32 +799,35 @@ unsigned int win_linetabsize(win_T *wp, char_u *line, colnr_T len)
return (unsigned int)col;
}
-/// Return TRUE if 'c' is a normal identifier character:
-///
+/// Check that "c" is a normal identifier character:
/// Letters and characters from the 'isident' option.
///
-/// @param c
-///
-/// @return TRUE if 'c' is a normal identifier character.
-int vim_isIDc(int c)
+/// @param c character to check
+bool vim_isIDc(int c)
+ FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT
{
return c > 0 && c < 0x100 && (chartab[c] & CT_ID_CHAR);
}
-/// return TRUE if 'c' is a keyword character: Letters and characters from
-/// 'iskeyword' option for current buffer.
-///
+/// Check that "c" is a keyword character:
+/// Letters and characters from 'iskeyword' option for current buffer.
/// For multi-byte characters mb_get_class() is used (builtin rules).
///
-/// @param c
-///
-/// @return TRUE if 'c' is a keyword character.
-int vim_iswordc(int c)
+/// @param c character to check
+bool vim_iswordc(int c)
+ FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT
{
return vim_iswordc_buf(c, curbuf);
}
-int vim_iswordc_buf(int c, buf_T *buf)
+/// Check that "c" is a keyword character:
+/// Letters and characters from 'iskeyword' option for given buffer.
+/// For multi-byte characters mb_get_class() is used (builtin rules).
+///
+/// @param c character to check
+/// @param buf buffer whose keywords to use
+bool vim_iswordc_buf(int c, buf_T *buf)
+ FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ARG(2)
{
if (c >= 0x100) {
if (enc_dbcs != 0) {
@@ -840,10 +843,11 @@ int vim_iswordc_buf(int c, buf_T *buf)
/// Just like vim_iswordc() but uses a pointer to the (multi-byte) character.
///
-/// @param p
+/// @param p pointer to the multi-byte character
///
-/// @return TRUE if 'p' points to a keyword character.
-int vim_iswordp(char_u *p)
+/// @return true if "p" points to a keyword character.
+bool vim_iswordp(char_u *p)
+ FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ALL
{
if (has_mbyte && (MB_BYTE2LEN(*p) > 1)) {
return mb_get_class(p) >= 2;
@@ -851,7 +855,15 @@ int vim_iswordp(char_u *p)
return GET_CHARTAB(curbuf, *p) != 0;
}
-int vim_iswordp_buf(char_u *p, buf_T *buf)
+/// Just like vim_iswordc_buf() but uses a pointer to the (multi-byte)
+/// character.
+///
+/// @param p pointer to the multi-byte character
+/// @param buf buffer whose keywords to use
+///
+/// @return true if "p" points to a keyword character.
+bool vim_iswordp_buf(char_u *p, buf_T *buf)
+ FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ALL
{
if (has_mbyte && (MB_BYTE2LEN(*p) > 1)) {
return mb_get_class(p) >= 2;
@@ -859,26 +871,24 @@ int vim_iswordp_buf(char_u *p, buf_T *buf)
return GET_CHARTAB(buf, *p) != 0;
}
-/// return TRUE if 'c' is a valid file-name character
+/// Check that "c" is a valid file-name character.
/// Assume characters above 0x100 are valid (multi-byte).
///
-/// @param c
-///
-/// @return TRUE if 'c' is a valid file name character.
-int vim_isfilec(int c)
+/// @param c character to check
+bool vim_isfilec(int c)
+ FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT
{
return c >= 0x100 || (c > 0 && (chartab[c] & CT_FNAME_CHAR));
}
-/// return TRUE if 'c' is a valid file-name character or a wildcard character
+/// Check that "c" is a valid file-name character or a wildcard character
/// Assume characters above 0x100 are valid (multi-byte).
/// Explicitly interpret ']' as a wildcard character as path_has_wildcard("]")
/// returns false.
///
-/// @param c
-///
-/// @return TRUE if 'c' is a valid file-name character or wildcard character.
-int vim_isfilec_or_wc(int c)
+/// @param c character to check
+bool vim_isfilec_or_wc(int c)
+ FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT
{
char_u buf[2];
buf[0] = (char_u)c;
@@ -886,14 +896,12 @@ int vim_isfilec_or_wc(int c)
return vim_isfilec(c) || c == ']' || path_has_wildcard(buf);
}
-/// return TRUE if 'c' is a printable character
-/// Assume characters above 0x100 are printable (multi-byte), except for
-/// Unicode.
+/// Check that "c" is a printable character.
+/// Assume characters above 0x100 are printable for double-byte encodings.
///
-/// @param c
-///
-/// @return TRUE if 'c' a printable character.
-int vim_isprintc(int c)
+/// @param c character to check
+bool vim_isprintc(int c)
+ FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT
{
if (enc_utf8 && (c >= 0x100)) {
return utf_printable(c);
@@ -901,16 +909,17 @@ int vim_isprintc(int c)
return c >= 0x100 || (c > 0 && (chartab[c] & CT_PRINT_CHAR));
}
-/// Strict version of vim_isprintc(c), don't return TRUE if "c" is the head
+/// Strict version of vim_isprintc(c), don't return true if "c" is the head
/// byte of a double-byte character.
///
-/// @param c
+/// @param c character to check
///
-/// @return TRUE if 'c' is a printable character.
-int vim_isprintc_strict(int c)
+/// @return true if "c" is a printable character.
+bool vim_isprintc_strict(int c)
+ FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT
{
if ((enc_dbcs != 0) && (c < 0x100) && (MB_BYTE2LEN(c) > 1)) {
- return FALSE;
+ return false;
}
if (enc_utf8 && (c >= 0x100)) {
@@ -921,7 +930,7 @@ int vim_isprintc_strict(int c)
/// like chartabsize(), but also check for line breaks on the screen
///
-/// @param line
+/// @param line
/// @param s
/// @param col
///
@@ -1144,35 +1153,33 @@ static int win_nolbr_chartabsize(win_T *wp, char_u *s, colnr_T col, int *headp)
return n;
}
-/// Return TRUE if virtual column "vcol" is in the rightmost column of window
-/// "wp".
+/// Check that virtual column "vcol" is in the rightmost column of window "wp".
///
-/// @param wp
-/// @param vcol
-///
-/// @return TRUE if the virtual column is in the rightmost column.
-int in_win_border(win_T *wp, colnr_T vcol)
+/// @param wp window
+/// @param vcol column number
+bool in_win_border(win_T *wp, colnr_T vcol)
+ FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ARG(1)
{
int width1; // width of first line (after line number)
int width2; // width of further lines
if (wp->w_width == 0) {
// there is no border
- return FALSE;
+ return false;
}
width1 = wp->w_width - win_col_off(wp);
if ((int)vcol < width1 - 1) {
- return FALSE;
+ return false;
}
if ((int)vcol == width1 - 1) {
- return TRUE;
+ return true;
}
width2 = width1 + win_col_off2(wp);
if (width2 <= 0) {
- return FALSE;
+ return false;
}
return (vcol - width1) % width2 == width2 - 1;
}
@@ -1571,10 +1578,14 @@ static char_u latin1lower[257] =
"\xdf\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee"
"\xef\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff";
-int vim_islower(int c)
+/// Check that the character is lower-case
+///
+/// @param c character to check
+bool vim_islower(int c)
+ FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ALL
{
if (c <= '@') {
- return FALSE;
+ return false;
}
if (c >= 0x80) {
@@ -1588,7 +1599,7 @@ int vim_islower(int c)
}
// islower() can't handle these chars and may crash
- return FALSE;
+ return false;
}
if (enc_latin1like) {
@@ -1598,10 +1609,14 @@ int vim_islower(int c)
return islower(c);
}
-int vim_isupper(int c)
+/// Check that the character is upper-case
+///
+/// @param c character to check
+bool vim_isupper(int c)
+ FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ALL
{
if (c <= '@') {
- return FALSE;
+ return false;
}
if (c >= 0x80) {
@@ -1614,8 +1629,8 @@ int vim_isupper(int c)
return iswupper(c);
}
- // islower() can't handle these chars and may crash
- return FALSE;
+ // isupper() can't handle these chars and may crash
+ return false;
}
if (enc_latin1like) {
@@ -1744,12 +1759,10 @@ long getdigits_long(char_u **pp)
return (long)number;
}
-/// Return TRUE if "lbuf" is empty or only contains blanks.
+/// Check that "lbuf" is empty or only contains blanks.
///
-/// @param lbuf
-///
-/// @return TRUE if `lbuf` is empty or only contains blanks.
-int vim_isblankline(char_u *lbuf)
+/// @param lbuf line buffer to check
+bool vim_isblankline(char_u *lbuf)
{
char_u *p = skipwhite(lbuf);
return *p == NUL || *p == '\r' || *p == '\n';
@@ -1767,58 +1780,57 @@ int vim_isblankline(char_u *lbuf)
/// If "len" is not NULL, the length of the number in characters is returned.
/// If "nptr" is not NULL, the signed result is returned in it.
/// If "unptr" is not NULL, the unsigned result is returned in it.
-/// If "dobin" is non-zero recognize binary numbers, when > 1 always assume
-/// binary number.
-/// If "dooct" is non-zero recognize octal numbers, when > 1 always assume
-/// octal number.
-/// If "dohex" is non-zero recognize hex numbers, when > 1 always assume
-/// hex number.
+/// If "what" contains STR2NR_BIN recognize binary numbers.
+/// If "what" contains STR2NR_OCT recognize octal numbers.
+/// If "what" contains STR2NR_HEX recognize hex numbers.
+/// If "what" contains STR2NR_FORCE always assume bin/oct/hex.
+/// If maxlen > 0, check at a maximum maxlen chars.
///
/// @param start
/// @param prep Returns type of number 0 = decimal, 'x' or 'X' is hex,
-// '0' = octal, 'b' or 'B' is bin
+/// '0' = octal, 'b' or 'B' is bin
/// @param len Returns the detected length of number.
-/// @param dobin recognize binary number
-/// @param dooct recognize octal number
-/// @param dohex recognize hex number
+/// @param what Recognizes what number passed.
/// @param nptr Returns the signed result.
/// @param unptr Returns the unsigned result.
-void vim_str2nr(char_u *start, int *prep, int *len,
- int dobin, int dooct, int dohex,
- long *nptr, unsigned long *unptr)
+/// @param maxlen Max length of string to check.
+void vim_str2nr(char_u *start, int *prep, int *len, int what,
+ long *nptr, unsigned long *unptr, int maxlen)
{
char_u *ptr = start;
int pre = 0; // default is decimal
- int negative = false;
+ bool negative = false;
unsigned long un = 0;
- int n;
if (ptr[0] == '-') {
negative = true;
ptr++;
}
- // Recognize hex, octal, and bin.
- if ((ptr[0] == '0') && (ptr[1] != '8') && (ptr[1] != '9')) {
+ // Recognize hex, octal and bin.
+ if ((ptr[0] == '0') && (ptr[1] != '8') && (ptr[1] != '9')
+ && (maxlen == 0 || maxlen > 1)) {
pre = ptr[1];
- if (dohex
+ if ((what & STR2NR_HEX)
&& ((pre == 'X') || (pre == 'x'))
- && ascii_isxdigit(ptr[2])) {
+ && ascii_isxdigit(ptr[2])
+ && (maxlen == 0 || maxlen > 2)) {
// hexadecimal
ptr += 2;
- } else if (dobin
+ } else if ((what & STR2NR_BIN)
&& ((pre == 'B') || (pre == 'b'))
- && ascii_isbdigit(ptr[2])) {
+ && ascii_isbdigit(ptr[2])
+ && (maxlen == 0 || maxlen > 2)) {
// binary
ptr += 2;
} else {
- // default is decimal
+ // decimal or octal, default is decimal
pre = 0;
- if (dooct) {
+ if (what & STR2NR_OCT) {
// Don't interpret "0", "08" or "0129" as octal.
- for (n = 1; ascii_isdigit(ptr[n]); ++n) {
+ for (int n = 1; ascii_isdigit(ptr[n]); ++n) {
if (ptr[n] > '7') {
// can't be octal
pre = 0;
@@ -1828,13 +1840,17 @@ void vim_str2nr(char_u *start, int *prep, int *len,
// assume octal
pre = '0';
}
+ if (n == maxlen) {
+ break;
+ }
}
}
}
}
// Do the string-to-numeric conversion "manually" to avoid sscanf quirks.
- if ((pre == 'B') || (pre == 'b') || (dobin > 1)) {
+ int n = 1;
+ if ((pre == 'B') || (pre == 'b') || what == STR2NR_BIN + STR2NR_FORCE) {
// bin
if (pre != 0) {
n += 2; // skip over "0b"
@@ -1842,14 +1858,21 @@ void vim_str2nr(char_u *start, int *prep, int *len,
while ('0' <= *ptr && *ptr <= '1') {
un = 2 * un + (unsigned long)(*ptr - '0');
ptr++;
+ if (n++ == maxlen) {
+ break;
+ }
}
- } else if ((pre == '0') || (dooct > 1)) {
+ } else if ((pre == '0') || what == STR2NR_OCT + STR2NR_FORCE) {
// octal
while ('0' <= *ptr && *ptr <= '7') {
un = 8 * un + (unsigned long)(*ptr - '0');
ptr++;
+ if (n++ == maxlen) {
+ break;
+ }
}
- } else if (pre != 0 || dohex > 1) {
+ } else if ((pre == 'X') || (pre == 'x')
+ || what == STR2NR_HEX + STR2NR_FORCE) {
// hex
if (pre != 0) {
n += 2; // skip over "0x"
@@ -1857,12 +1880,18 @@ void vim_str2nr(char_u *start, int *prep, int *len,
while (ascii_isxdigit(*ptr)) {
un = 16 * un + (unsigned long)hex2nr(*ptr);
ptr++;
+ if (n++ == maxlen) {
+ break;
+ }
}
} else {
// decimal
while (ascii_isdigit(*ptr)) {
un = 10 * un + (unsigned long)(*ptr - '0');
ptr++;
+ if (n++ == maxlen) {
+ break;
+ }
}
}
@@ -1906,8 +1935,8 @@ int hex2nr(int c)
return c - '0';
}
-/// Return true if "str" starts with a backslash that should be removed.
-/// For WIN32 this is only done when the character after the
+/// Check that "str" starts with a backslash that should be removed.
+/// For Windows this is only done when the character after the
/// backslash is not a normal file name character.
/// '$' is a valid file name character, we don't remove the backslash before
/// it. This means it is not possible to use an environment variable after a
@@ -1918,10 +1947,9 @@ int hex2nr(int c)
/// character, assume that all multi-byte characters are valid file name
/// characters.
///
-/// @param str
-///
-/// @return true if `str` starts with a backslash that should be removed.
+/// @param str file path string to check
bool rem_backslash(const char_u *str)
+ FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ALL
{
#ifdef BACKSLASH_IN_FILENAME
return str[0] == '\\'
diff --git a/src/nvim/diff.c b/src/nvim/diff.c
index ce79158050..0be8b3c514 100644
--- a/src/nvim/diff.c
+++ b/src/nvim/diff.c
@@ -763,8 +763,8 @@ void ex_diffupdate(exarg_T *eap)
// Make a difference between the first buffer and every other.
for (idx_new = idx_orig + 1; idx_new < DB_COUNT; ++idx_new) {
buf_T *buf = curtab->tp_diffbuf[idx_new];
- if (buf == NULL) {
- continue;
+ if (buf == NULL || buf->b_ml.ml_mfp == NULL) {
+ continue; // skip buffer that isn't loaded
}
if (diff_write(buf, tmp_new) == FAIL) {
@@ -1057,27 +1057,28 @@ void diff_win_options(win_T *wp, int addbuf)
newFoldLevel();
curwin = old_curwin;
- wp->w_p_diff = TRUE;
-
// Use 'scrollbind' and 'cursorbind' when available
- if (!wp->w_p_diff_saved) {
+ if (!wp->w_p_diff) {
wp->w_p_scb_save = wp->w_p_scb;
}
wp->w_p_scb = TRUE;
- if (!wp->w_p_diff_saved) {
+ if (!wp->w_p_diff) {
wp->w_p_crb_save = wp->w_p_crb;
}
wp->w_p_crb = TRUE;
- if (!wp->w_p_diff_saved) {
+ if (!wp->w_p_diff) {
wp->w_p_wrap_save = wp->w_p_wrap;
}
wp->w_p_wrap = FALSE;
curwin = wp;
curbuf = curwin->w_buffer;
- if (!wp->w_p_diff_saved) {
+ if (!wp->w_p_diff) {
+ if (wp->w_p_diff_saved) {
+ free_string_option(wp->w_p_fdm_save);
+ }
wp->w_p_fdm_save = vim_strsave(wp->w_p_fdm);
}
set_string_option_direct((char_u *)"fdm", -1, (char_u *)"diff",
@@ -1085,7 +1086,7 @@ void diff_win_options(win_T *wp, int addbuf)
curwin = old_curwin;
curbuf = curwin->w_buffer;
- if (!wp->w_p_diff_saved) {
+ if (!wp->w_p_diff) {
wp->w_p_fdc_save = wp->w_p_fdc;
wp->w_p_fen_save = wp->w_p_fen;
wp->w_p_fdl_save = wp->w_p_fdl;
@@ -1104,6 +1105,8 @@ void diff_win_options(win_T *wp, int addbuf)
// Saved the current values, to be restored in ex_diffoff().
wp->w_p_diff_saved = TRUE;
+ wp->w_p_diff = true;
+
if (addbuf) {
diff_buf_add(wp->w_buffer);
}
@@ -1116,68 +1119,50 @@ void diff_win_options(win_T *wp, int addbuf)
/// @param eap
void ex_diffoff(exarg_T *eap)
{
- win_T *old_curwin = curwin;
- int diffwin = FALSE;
+ int diffwin = false;
FOR_ALL_WINDOWS_IN_TAB(wp, curtab) {
if (eap->forceit ? wp->w_p_diff : (wp == curwin)) {
- // Set 'diff', 'scrollbind' off and 'wrap' on. If option values
- // were saved in diff_win_options() restore them.
- wp->w_p_diff = FALSE;
-
- if (wp->w_p_scb) {
- wp->w_p_scb = wp->w_p_diff_saved ? wp->w_p_scb_save : FALSE;
- }
-
- if (wp->w_p_crb) {
- wp->w_p_crb = wp->w_p_diff_saved ? wp->w_p_crb_save : FALSE;
- }
-
- if (!wp->w_p_wrap) {
- wp->w_p_wrap = wp->w_p_diff_saved ? wp->w_p_wrap_save : TRUE;
- }
- curwin = wp;
- curbuf = curwin->w_buffer;
+ // Set 'diff' off. If option values were saved in
+ // diff_win_options(), restore the ones whose settings seem to have
+ // been left over from diff mode.
+ wp->w_p_diff = false;
if (wp->w_p_diff_saved) {
- free_string_option(wp->w_p_fdm);
- wp->w_p_fdm = wp->w_p_fdm_save;
- wp->w_p_fdm_save = empty_option;
- } else {
- set_string_option_direct((char_u *)"fdm", -1,
- (char_u *)"manual", OPT_LOCAL | OPT_FREE, 0);
- }
- curwin = old_curwin;
- curbuf = curwin->w_buffer;
+ if (wp->w_p_scb) {
+ wp->w_p_scb = wp->w_p_scb_save;
+ }
- if (wp->w_p_fdc == diff_foldcolumn) {
- wp->w_p_fdc = wp->w_p_diff_saved ? wp->w_p_fdc_save : 0;
- }
+ if (wp->w_p_crb) {
+ wp->w_p_crb = wp->w_p_crb_save;
+ }
- if ((wp->w_p_fdl == 0)
- && wp->w_p_diff_saved) {
- wp->w_p_fdl = wp->w_p_fdl_save;
- }
+ if (!wp->w_p_wrap) {
+ wp->w_p_wrap = wp->w_p_wrap_save;
+ }
- if (wp->w_p_fen) {
+ free_string_option(wp->w_p_fdm);
+ wp->w_p_fdm = vim_strsave(wp->w_p_fdm_save);
+ if (wp->w_p_fdc == diff_foldcolumn) {
+ wp->w_p_fdc = wp->w_p_fdc_save;
+ }
+ if (wp->w_p_fdl == 0) {
+ wp->w_p_fdl = wp->w_p_fdl_save;
+ }
// Only restore 'foldenable' when 'foldmethod' is not
// "manual", otherwise we continue to show the diff folds.
- if (foldmethodIsManual(wp) || !wp->w_p_diff_saved) {
- wp->w_p_fen = FALSE;
- } else {
- wp->w_p_fen = wp->w_p_fen_save;
+ if (wp->w_p_fen) {
+ wp->w_p_fen = foldmethodIsManual(wp) ? false : wp->w_p_fen_save;
}
- }
- foldUpdateAll(wp);
+ foldUpdateAll(wp);
- // make sure topline is not halfway through a fold
- changed_window_setting_win(wp);
+ // make sure topline is not halfway through a fold
+ changed_window_setting_win(wp);
+ }
// Note: 'sbo' is not restored, it's a global option.
diff_buf_adjust(wp);
-
- wp->w_p_diff_saved = FALSE;
}
diffwin |= wp->w_p_diff;
}
@@ -1546,37 +1531,37 @@ int diff_check(win_T *wp, linenr_T lnum)
return maxcount - dp->df_count[idx];
}
-/// Compare two entries in diff "*dp" and return TRUE if they are equal.
+/// Compare two entries in diff "dp" and return true if they are equal.
///
-/// @param dp
-/// @param idx1 First entry in diff "*dp"
-/// @param idx2 Second entry in diff "*dp"
+/// @param dp diff
+/// @param idx1 first entry in diff "dp"
+/// @param idx2 second entry in diff "dp"
///
-/// @return return TRUE if two entires are equal.
-static int diff_equal_entry(diff_T *dp, int idx1, int idx2)
+/// @return true if two entires are equal.
+static bool diff_equal_entry(diff_T *dp, int idx1, int idx2)
+ FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ARG(1)
{
if (dp->df_count[idx1] != dp->df_count[idx2]) {
- return FALSE;
+ return false;
}
if (diff_check_sanity(curtab, dp) == FAIL) {
- return FALSE;
+ return false;
}
- int i;
- for (i = 0; i < dp->df_count[idx1]; ++i) {
+ for (int i = 0; i < dp->df_count[idx1]; i++) {
char_u *line = vim_strsave(ml_get_buf(curtab->tp_diffbuf[idx1],
- dp->df_lnum[idx1] + i, FALSE));
+ dp->df_lnum[idx1] + i, false));
int cmp = diff_cmp(line, ml_get_buf(curtab->tp_diffbuf[idx2],
- dp->df_lnum[idx2] + i, FALSE));
+ dp->df_lnum[idx2] + i, false));
xfree(line);
if (cmp != 0) {
- return FALSE;
+ return false;
}
}
- return TRUE;
+ return true;
}
/// Compare strings "s1" and "s2" according to 'diffopt'.
@@ -1845,28 +1830,30 @@ int diffopt_changed(void)
return OK;
}
-/// Return TRUE if 'diffopt' contains "horizontal".
-///
-/// @return TRUE if 'diffopt' contains "horizontal"
-int diffopt_horizontal(void)
+/// Check that "diffopt" contains "horizontal".
+bool diffopt_horizontal(void)
+ FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT
{
return (diff_flags & DIFF_HORIZONTAL) != 0;
}
/// Find the difference within a changed line.
///
-/// @param startp first char of the change
-/// @param endp last char of the change
+/// @param wp window whose current buffer to check
+/// @param lnum line number to check within the buffer
+/// @param startp first char of the change
+/// @param endp last char of the change
///
-/// @returns TRUE if the line was added, no other buffer has it.
-int diff_find_change(win_T *wp, linenr_T lnum, int *startp, int *endp)
+/// @return true if the line was added, no other buffer has it.
+bool diff_find_change(win_T *wp, linenr_T lnum, int *startp, int *endp)
+ FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ALL
{
char_u *line_new;
int si_org;
int si_new;
int ei_org;
int ei_new;
- int added = TRUE;
+ bool added = true;
// Make a copy of the line, the next ml_get() will invalidate it.
char_u *line_org = vim_strsave(ml_get_buf(wp->w_buffer, lnum, FALSE));
@@ -1875,7 +1862,7 @@ int diff_find_change(win_T *wp, linenr_T lnum, int *startp, int *endp)
if (idx == DB_COUNT) {
// cannot happen
xfree(line_org);
- return FALSE;
+ return false;
}
// search for a change that includes "lnum" in the list of diffblocks.
@@ -1888,7 +1875,7 @@ int diff_find_change(win_T *wp, linenr_T lnum, int *startp, int *endp)
if ((dp == NULL) || (diff_check_sanity(curtab, dp) == FAIL)) {
xfree(line_org);
- return FALSE;
+ return false;
}
int off = lnum - dp->df_lnum[idx];
@@ -1899,7 +1886,7 @@ int diff_find_change(win_T *wp, linenr_T lnum, int *startp, int *endp)
if (off >= dp->df_count[i]) {
continue;
}
- added = FALSE;
+ added = false;
line_new = ml_get_buf(curtab->tp_diffbuf[i],
dp->df_lnum[i] + off, FALSE);
@@ -1971,21 +1958,22 @@ int diff_find_change(win_T *wp, linenr_T lnum, int *startp, int *endp)
return added;
}
-/// Return TRUE if line "lnum" is not close to a diff block, this line should
+/// Check that line "lnum" is not close to a diff block, this line should
/// be in a fold.
///
-/// @param wp
-/// @param lnum
+/// @param wp window containing the buffer to check
+/// @param lnum line number to check within the buffer
///
-/// @return FALSE if there are no diff blocks at all in this window.
-int diff_infold(win_T *wp, linenr_T lnum)
+/// @return false if there are no diff blocks at all in this window.
+bool diff_infold(win_T *wp, linenr_T lnum)
+ FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ARG(1)
{
- int other = FALSE;
+ bool other = false;
diff_T *dp;
// Return if 'diff' isn't set.
if (!wp->w_p_diff) {
- return FALSE;
+ return false;
}
int idx = -1;
@@ -1994,13 +1982,13 @@ int diff_infold(win_T *wp, linenr_T lnum)
if (curtab->tp_diffbuf[i] == wp->w_buffer) {
idx = i;
} else if (curtab->tp_diffbuf[i] != NULL) {
- other = TRUE;
+ other = true;
}
}
// return here if there are no diffs in the window
if ((idx == -1) || !other) {
- return FALSE;
+ return false;
}
if (curtab->tp_diff_invalid) {
@@ -2010,7 +1998,7 @@ int diff_infold(win_T *wp, linenr_T lnum)
// Return if there are no diff blocks. All lines will be folded.
if (curtab->tp_first_diff == NULL) {
- return TRUE;
+ return true;
}
for (dp = curtab->tp_first_diff; dp != NULL; dp = dp->df_next) {
@@ -2021,10 +2009,10 @@ int diff_infold(win_T *wp, linenr_T lnum)
// If this change ends before the line we have a match.
if (dp->df_lnum[idx] + dp->df_count[idx] + diff_context > lnum) {
- return FALSE;
+ return false;
}
}
- return TRUE;
+ return true;
}
/// "dp" and "do" commands.
@@ -2387,12 +2375,11 @@ static void diff_fold_update(diff_T *dp, int skip_idx)
}
}
-/// Checks if the buffer is in diff-mode.
-///
-/// @param buf The buffer to check.
+/// Checks that the buffer is in diff-mode.
///
-/// @return TRUE if buffer "buf" is in diff-mode.
+/// @param buf buffer to check.
bool diff_mode_buf(buf_T *buf)
+ FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ARG(1)
{
FOR_ALL_TABS(tp) {
if (diff_buf_idx_tp(buf, tp) != DB_COUNT) {
diff --git a/src/nvim/edit.c b/src/nvim/edit.c
index ccfc9b4803..6313ea2e81 100644
--- a/src/nvim/edit.c
+++ b/src/nvim/edit.c
@@ -1247,7 +1247,7 @@ normalchar:
static void insert_do_complete(InsertState *s)
{
compl_busy = true;
- if (ins_complete(s->c) == FAIL) {
+ if (ins_complete(s->c, true) == FAIL) {
compl_cont_status = 0;
}
compl_busy = false;
@@ -2321,9 +2321,10 @@ static int ins_compl_make_cyclic(void)
*/
void set_completion(colnr_T startcol, list_T *list)
{
- /* If already doing completions stop it. */
- if (ctrl_x_mode != 0)
+ // If already doing completions stop it.
+ if (ctrl_x_mode != 0) {
ins_compl_prep(' ');
+ }
ins_compl_clear();
if (stop_arrow() == FAIL)
@@ -2349,16 +2350,23 @@ void set_completion(colnr_T startcol, list_T *list)
compl_started = TRUE;
compl_used_match = TRUE;
compl_cont_status = 0;
+ int save_w_wrow = curwin->w_wrow;
compl_curr_match = compl_first_match;
if (compl_no_insert) {
- ins_complete(K_DOWN);
+ ins_complete(K_DOWN, false);
} else {
- ins_complete(Ctrl_N);
+ ins_complete(Ctrl_N, false);
if (compl_no_select) {
- ins_complete(Ctrl_P);
+ ins_complete(Ctrl_P, false);
}
}
+
+ // Lazily show the popup menu, unless we got interrupted.
+ if (!compl_interrupted) {
+ show_pum(save_w_wrow);
+ }
+
ui_flush();
}
@@ -2464,6 +2472,14 @@ void ins_compl_show_pum(void)
/* Need to build the popup menu list. */
compl_match_arraysize = 0;
compl = compl_first_match;
+ /*
+ * If it's user complete function and refresh_always,
+ * not use "compl_leader" as prefix filter.
+ */
+ if (ins_compl_need_restart()){
+ xfree(compl_leader);
+ compl_leader = NULL;
+ }
if (compl_leader != NULL)
lead_len = (int)STRLEN(compl_leader);
do {
@@ -2548,8 +2564,12 @@ void ins_compl_show_pum(void)
}
}
- /* Compute the screen column of the start of the completed text.
- * Use the cursor to get all wrapping and other settings right. */
+ // In Replace mode when a $ is displayed at the end of the line only
+ // part of the screen would be updated. We do need to redraw here.
+ dollar_vcol = -1;
+
+ // Compute the screen column of the start of the completed text.
+ // Use the cursor to get all wrapping and other settings right.
col = curwin->w_cursor.col;
curwin->w_cursor.col = compl_col;
pum_display(compl_match_array, compl_match_arraysize, cur);
@@ -2923,20 +2943,17 @@ static void ins_compl_new_leader(void)
ins_bytes(compl_leader + ins_compl_len());
compl_used_match = FALSE;
- if (compl_started)
+ if (compl_started) {
ins_compl_set_original_text(compl_leader);
- else {
- spell_bad_len = 0; /* need to redetect bad word */
- /*
- * Matches were cleared, need to search for them now. First display
- * the changed text before the cursor. Set "compl_restarting" to
- * avoid that the first match is inserted.
- */
- update_screen(0);
- compl_restarting = TRUE;
- if (ins_complete(Ctrl_N) == FAIL)
+ } else {
+ spell_bad_len = 0; // need to redetect bad word
+ // Matches were cleared, need to search for them now.
+ // Set "compl_restarting" to avoid that the first match is inserted.
+ compl_restarting = true;
+ if (ins_complete(Ctrl_N, true) == FAIL) {
compl_cont_status = 0;
- compl_restarting = FALSE;
+ }
+ compl_restarting = false;
}
compl_enter_selects = !compl_used_match;
@@ -2944,8 +2961,9 @@ static void ins_compl_new_leader(void)
/* Show the popup menu with a different set of matches. */
ins_compl_show_pum();
- /* Don't let Enter select the original text when there is no popup menu. */
- if (compl_match_array == NULL)
+ /* Don't let Enter select the original text when there is no popup menu.
+ * Don't let Enter select when use user function and refresh_always is set */
+ if (compl_match_array == NULL || ins_compl_need_restart())
compl_enter_selects = FALSE;
}
@@ -2976,27 +2994,18 @@ static void ins_compl_addleader(int c)
(*mb_char2bytes)(c, buf);
buf[cc] = NUL;
ins_char_bytes(buf, cc);
- if (compl_opt_refresh_always)
- AppendToRedobuff(buf);
} else {
ins_char(c);
- if (compl_opt_refresh_always)
- AppendCharToRedobuff(c);
}
/* If we didn't complete finding matches we must search again. */
if (ins_compl_need_restart())
ins_compl_restart();
- /* When 'always' is set, don't reset compl_leader. While completing,
- * cursor doesn't point original position, changing compl_leader would
- * break redo. */
- if (!compl_opt_refresh_always) {
- xfree(compl_leader);
- compl_leader = vim_strnsave(get_cursor_line_ptr() + compl_col,
- (int)(curwin->w_cursor.col - compl_col));
- ins_compl_new_leader();
- }
+ xfree(compl_leader);
+ compl_leader = vim_strnsave(get_cursor_line_ptr() + compl_col,
+ (int)(curwin->w_cursor.col - compl_col));
+ ins_compl_new_leader();
}
/*
@@ -3005,6 +3014,10 @@ static void ins_compl_addleader(int c)
*/
static void ins_compl_restart(void)
{
+ /* update screen before restart.
+ * so if complete is blocked,
+ * will stay to the last popup menu and reduce flicker */
+ update_screen(0);
ins_compl_free();
compl_started = FALSE;
compl_matches = 0;
@@ -4292,7 +4305,7 @@ static int ins_compl_use_match(int c)
* Called when character "c" was typed, which has a meaning for completion.
* Returns OK if completion was done, FAIL if something failed.
*/
-static int ins_complete(int c)
+static int ins_complete(int c, bool enable_pum)
{
char_u *line;
int startcol = 0; /* column where searched text starts */
@@ -4775,20 +4788,9 @@ static int ins_complete(int c)
}
}
- /* Show the popup menu, unless we got interrupted. */
- if (!compl_interrupted) {
- /* RedrawingDisabled may be set when invoked through complete(). */
- n = RedrawingDisabled;
- RedrawingDisabled = 0;
-
- /* If the cursor moved we need to remove the pum first. */
- setcursor();
- if (save_w_wrow != curwin->w_wrow)
- ins_compl_del_pum();
-
- ins_compl_show_pum();
- setcursor();
- RedrawingDisabled = n;
+ // Show the popup menu, unless we got interrupted.
+ if (enable_pum && !compl_interrupted) {
+ show_pum(save_w_wrow);
}
compl_was_interrupted = compl_interrupted;
compl_interrupted = FALSE;
@@ -4941,15 +4943,10 @@ int get_literal(void)
return cc;
}
-/*
- * Insert character, taking care of special keys and mod_mask
- */
-static void
-insert_special (
- int c,
- int allow_modmask,
- int ctrlv /* c was typed after CTRL-V */
-)
+/// Insert character, taking care of special keys and mod_mask
+///
+/// @param ctrlv `c` was typed after CTRL-V
+static void insert_special(int c, int allow_modmask, int ctrlv)
{
char_u *p;
int len;
@@ -4961,6 +4958,9 @@ insert_special (
* Only use mod_mask for special keys, to avoid things like <S-Space>,
* unless 'allow_modmask' is TRUE.
*/
+ if (mod_mask & MOD_MASK_CMD) { // Command-key never produces a normal key.
+ allow_modmask = true;
+ }
if (IS_SPECIAL(c) || (mod_mask && allow_modmask)) {
p = get_special_key_name(c, mod_mask);
len = (int)STRLEN(p);
@@ -7586,27 +7586,35 @@ static int ins_bs(int c, int mode, int *inserted_space_p)
* happen when using 'sts' and 'linebreak'. */
if (vcol >= start_vcol)
ins_bs_one(&vcol);
- }
- /*
- * Delete upto starting point, start of line or previous word.
- */
- else do {
- if (!revins_on) /* put cursor on char to be deleted */
- dec_cursor();
- /* start of word? */
- if (mode == BACKSPACE_WORD && !ascii_isspace(gchar_cursor())) {
- mode = BACKSPACE_WORD_NOT_SPACE;
- temp = vim_iswordc(gchar_cursor());
+ // Delete upto starting point, start of line or previous word.
+ } else {
+ int cclass = 0, prev_cclass = 0;
+
+ if (has_mbyte) {
+ cclass = mb_get_class(get_cursor_pos_ptr());
+ }
+ do {
+ if (!revins_on) { // put cursor on char to be deleted
+ dec_cursor();
+ }
+ cc = gchar_cursor();
+ // look multi-byte character class
+ if (has_mbyte) {
+ prev_cclass = cclass;
+ cclass = mb_get_class(get_cursor_pos_ptr());
}
- /* end of word? */
- else if (mode == BACKSPACE_WORD_NOT_SPACE
- && (ascii_isspace(cc = gchar_cursor())
- || vim_iswordc(cc) != temp)) {
- if (!revins_on)
+ if (mode == BACKSPACE_WORD && !ascii_isspace(cc)) { // start of word?
+ mode = BACKSPACE_WORD_NOT_SPACE;
+ temp = vim_iswordc(cc);
+ } else if (mode == BACKSPACE_WORD_NOT_SPACE
+ && ((ascii_isspace(cc) || vim_iswordc(cc) != temp)
+ || prev_cclass != cclass)) { // end of word?
+ if (!revins_on) {
inc_cursor();
- else if (State & REPLACE_FLAG)
+ } else if (State & REPLACE_FLAG) {
dec_cursor();
+ }
break;
}
if (State & REPLACE_FLAG)
@@ -7639,18 +7647,18 @@ static int ins_bs(int c, int mode, int *inserted_space_p)
(curwin->w_cursor.col > mincol
&& (curwin->w_cursor.lnum != Insstart_orig.lnum
|| curwin->w_cursor.col != Insstart_orig.col)));
- did_backspace = TRUE;
+ }
+ did_backspace = true;
}
- did_si = FALSE;
- can_si = FALSE;
- can_si_back = FALSE;
- if (curwin->w_cursor.col <= 1)
- did_ai = FALSE;
- /*
- * It's a little strange to put backspaces into the redo
- * buffer, but it makes auto-indent a lot easier to deal
- * with.
- */
+ did_si = false;
+ can_si = false;
+ can_si_back = false;
+ if (curwin->w_cursor.col <= 1) {
+ did_ai = false;
+ }
+ // It's a little strange to put backspaces into the redo
+ // buffer, but it makes auto-indent a lot easier to deal
+ // with.
AppendCharToRedobuff(c);
/* If deleted before the insertion point, adjust it */
@@ -8508,3 +8516,20 @@ static char_u *do_insert_char_pre(int c)
return res;
}
+
+static void show_pum(int save_w_wrow)
+{
+ // RedrawingDisabled may be set when invoked through complete().
+ int n = RedrawingDisabled;
+ RedrawingDisabled = 0;
+
+ // If the cursor moved we need to remove the pum first.
+ setcursor();
+ if (save_w_wrow != curwin->w_wrow) {
+ ins_compl_del_pum();
+ }
+
+ ins_compl_show_pum();
+ setcursor();
+ RedrawingDisabled = n;
+}
diff --git a/src/nvim/eval.c b/src/nvim/eval.c
index a5a8671697..b011ee9d54 100644
--- a/src/nvim/eval.c
+++ b/src/nvim/eval.c
@@ -1147,7 +1147,7 @@ int call_vim_function(
len = 0;
} else {
// Recognize a number argument, the others must be strings.
- vim_str2nr(argv[i], NULL, &len, true, true, true, &n, NULL);
+ vim_str2nr(argv[i], NULL, &len, STR2NR_ALL, &n, NULL, 0);
}
if (len != 0 && len == (int)STRLEN(argv[i])) {
argvars[i].v_type = VAR_NUMBER;
@@ -1700,12 +1700,13 @@ static char_u *list_arg_vars(exarg_T *eap, char_u *arg, int *first)
}
error = TRUE;
} else {
- if (tofree != NULL)
+ if (tofree != NULL) {
name = tofree;
- if (get_var_tv(name, len, &tv, TRUE, FALSE) == FAIL)
- error = TRUE;
- else {
- /* handle d.key, l[idx], f(expr) */
+ }
+ if (get_var_tv(name, len, &tv, NULL, true, false) == FAIL) {
+ error = true;
+ } else {
+ // handle d.key, l[idx], f(expr)
arg_subsc = arg;
if (handle_subscript(&arg, &tv, TRUE, TRUE) == FAIL)
error = TRUE;
@@ -2176,10 +2177,10 @@ get_lval (
if (len == -1)
clear_tv(&var1);
break;
- }
- /* existing variable, need to check if it can be changed */
- else if (var_check_ro(lp->ll_di->di_flags, name))
+ } else if (var_check_ro(lp->ll_di->di_flags, name, false)) {
+ // existing variable, need to check if it can be changed
return NULL;
+ }
if (len == -1)
clear_tv(&var1);
@@ -2274,11 +2275,16 @@ static void set_var_lval(lval_T *lp, char_u *endp, typval_T *rettv, int copy, ch
if (op != NULL && *op != '=') {
typval_T tv;
- /* handle +=, -= and .= */
+ // handle +=, -= and .=
+ di = NULL;
if (get_var_tv(lp->ll_name, (int)STRLEN(lp->ll_name),
- &tv, TRUE, FALSE) == OK) {
- if (tv_op(&tv, rettv, op) == OK)
- set_var(lp->ll_name, &tv, FALSE);
+ &tv, &di, true, false) == OK) {
+ if ((di == NULL
+ || (!var_check_ro(di->di_flags, lp->ll_name, false) &&
+ !tv_check_lock(di->di_tv.v_lock, lp->ll_name, false)))
+ && tv_op(&tv, rettv, op) == OK) {
+ set_var(lp->ll_name, &tv, false);
+ }
clear_tv(&tv);
}
} else
@@ -2286,16 +2292,17 @@ static void set_var_lval(lval_T *lp, char_u *endp, typval_T *rettv, int copy, ch
*endp = cc;
}
} else if (tv_check_lock(lp->ll_newkey == NULL
- ? lp->ll_tv->v_lock
- : lp->ll_tv->vval.v_dict->dv_lock, lp->ll_name))
- ;
- else if (lp->ll_range) {
+ ? lp->ll_tv->v_lock
+ : lp->ll_tv->vval.v_dict->dv_lock,
+ lp->ll_name, false)) {
+ } else if (lp->ll_range) {
listitem_T *ll_li = lp->ll_li;
int ll_n1 = lp->ll_n1;
// Check whether any of the list items is locked
- for (listitem_T *ri = rettv->vval.v_list->lv_first; ri != NULL && ll_li != NULL; ) {
- if (tv_check_lock(ll_li->li_tv.v_lock, lp->ll_name)) {
+ for (listitem_T *ri = rettv->vval.v_list->lv_first;
+ ri != NULL && ll_li != NULL; ) {
+ if (tv_check_lock(ll_li->li_tv.v_lock, lp->ll_name, false)) {
return;
}
ri = ri->li_next;
@@ -2890,16 +2897,19 @@ static int do_unlet_var(lval_T *lp, char_u *name_end, int forceit)
else if (do_unlet(lp->ll_name, forceit) == FAIL)
ret = FAIL;
*name_end = cc;
- } else if (tv_check_lock(lp->ll_tv->v_lock, lp->ll_name))
+ } else if ((lp->ll_list != NULL
+ && tv_check_lock(lp->ll_list->lv_lock, lp->ll_name, false))
+ || (lp->ll_dict != NULL
+ && tv_check_lock(lp->ll_dict->dv_lock, lp->ll_name, false))) {
return FAIL;
- else if (lp->ll_range) {
+ } else if (lp->ll_range) {
listitem_T *li;
listitem_T *ll_li = lp->ll_li;
int ll_n1 = lp->ll_n1;
while (ll_li != NULL && (lp->ll_empty2 || lp->ll_n2 >= ll_n1)) {
li = ll_li->li_next;
- if (tv_check_lock(ll_li->li_tv.v_lock, lp->ll_name)) {
+ if (tv_check_lock(ll_li->li_tv.v_lock, lp->ll_name, false)) {
return false;
}
ll_li = li;
@@ -2953,17 +2963,30 @@ int do_unlet(char_u *name, int forceit)
hashtab_T *ht;
hashitem_T *hi;
char_u *varname;
+ dict_T *d;
dictitem_T *di;
dict_T *dict;
ht = find_var_ht_dict(name, &varname, &dict);
if (ht != NULL && *varname != NUL) {
+ if (ht == &globvarht) {
+ d = &globvardict;
+ } else if (current_funccal != NULL
+ && ht == &current_funccal->l_vars.dv_hashtab) {
+ d = &current_funccal->l_vars;
+ } else {
+ di = find_var_in_ht(ht, *name, (char_u *)"", false);
+ d = di->di_tv.vval.v_dict;
+ }
+
hi = hash_find(ht, varname);
if (!HASHITEM_EMPTY(hi)) {
di = HI2DI(hi);
- if (var_check_fixed(di->di_flags, name)
- || var_check_ro(di->di_flags, name))
+ if (var_check_fixed(di->di_flags, name, false)
+ || var_check_ro(di->di_flags, name, false)
+ || tv_check_lock(d->dv_lock, name, false)) {
return FAIL;
+ }
typval_T oldtv;
bool watched = is_watched(dict);
@@ -3029,12 +3052,13 @@ static int do_lock_var(lval_T *lp, char_u *name_end, int deep, int lock)
li = li->li_next;
++lp->ll_n1;
}
- } else if (lp->ll_list != NULL)
- /* (un)lock a List item. */
+ } else if (lp->ll_list != NULL) {
+ // (un)lock a List item.
item_lock(&lp->ll_li->li_tv, deep, lock);
- else
- /* un(lock) a Dictionary item. */
+ } else {
+ // (un)lock a Dictionary item.
item_lock(&lp->ll_di->di_tv, deep, lock);
+ }
return ret;
}
@@ -3556,9 +3580,10 @@ static int eval4(char_u **arg, typval_T *rettv, int evaluate)
type = TYPE_SEQUAL;
break;
case 'i': if (p[1] == 's') {
- if (p[2] == 'n' && p[3] == 'o' && p[4] == 't')
+ if (p[2] == 'n' && p[3] == 'o' && p[4] == 't') {
len = 5;
- if (!vim_isIDc(p[len])) {
+ }
+ if (!isalnum(p[len]) && p[len] != '_') {
type = len == 2 ? TYPE_EQUAL : TYPE_NEQUAL;
type_is = TRUE;
}
@@ -4122,7 +4147,7 @@ static int eval7(
rettv->vval.v_float = f;
}
} else {
- vim_str2nr(*arg, NULL, &len, true, true, true, &n, NULL);
+ vim_str2nr(*arg, NULL, &len, STR2NR_ALL, &n, NULL, 0);
*arg += len;
if (evaluate) {
rettv->v_type = VAR_NUMBER;
@@ -4223,7 +4248,7 @@ static int eval7(
ret = FAIL;
}
} else if (evaluate) {
- ret = get_var_tv(s, len, rettv, true, false);
+ ret = get_var_tv(s, len, rettv, NULL, true, false);
} else {
ret = OK;
}
@@ -4638,10 +4663,13 @@ static int get_string_tv(char_u **arg, typval_T *rettv, int evaluate)
int n, nr;
int c = toupper(*p);
- if (c == 'X')
+ if (c == 'X') {
n = 2;
- else
+ } else if (*p == 'u') {
n = 4;
+ } else {
+ n = 8;
+ }
nr = 0;
while (--n >= 0 && ascii_isxdigit(p[1])) {
++p;
@@ -6052,7 +6080,7 @@ dictitem_T *dictitem_alloc(char_u *key) FUNC_ATTR_NONNULL_RET
#ifndef __clang_analyzer__
STRCPY(di->di_key, key);
#endif
- di->di_flags = 0;
+ di->di_flags = DI_FLAGS_ALLOC;
return di;
}
@@ -6064,7 +6092,7 @@ static dictitem_T *dictitem_copy(dictitem_T *org) FUNC_ATTR_NONNULL_RET
dictitem_T *di = xmalloc(sizeof(dictitem_T) + STRLEN(org->di_key));
STRCPY(di->di_key, org->di_key);
- di->di_flags = 0;
+ di->di_flags = DI_FLAGS_ALLOC;
copy_tv(&org->di_tv, &di->di_tv);
return di;
@@ -6092,7 +6120,9 @@ static void dictitem_remove(dict_T *dict, dictitem_T *item)
void dictitem_free(dictitem_T *item)
{
clear_tv(&item->di_tv);
- xfree(item);
+ if (item->di_flags & DI_FLAGS_ALLOC) {
+ xfree(item);
+ }
}
/// Make a copy of dictionary
@@ -7188,9 +7218,9 @@ static struct fst {
{ "getwinposx", 0, 0, f_getwinposx },
{ "getwinposy", 0, 0, f_getwinposy },
{ "getwinvar", 2, 3, f_getwinvar },
- { "glob", 1, 3, f_glob },
+ { "glob", 1, 4, f_glob },
{ "glob2regpat", 1, 1, f_glob2regpat },
- { "globpath", 2, 4, f_globpath },
+ { "globpath", 2, 5, f_globpath },
{ "has", 1, 1, f_has },
{ "has_key", 2, 2, f_has_key },
{ "haslocaldir", 0, 0, f_haslocaldir },
@@ -7241,8 +7271,8 @@ static struct fst {
{ "maparg", 1, 4, f_maparg },
{ "mapcheck", 1, 3, f_mapcheck },
{ "match", 2, 4, f_match },
- { "matchadd", 2, 4, f_matchadd },
- { "matchaddpos", 2, 4, f_matchaddpos },
+ { "matchadd", 2, 5, f_matchadd },
+ { "matchaddpos", 2, 5, f_matchaddpos },
{ "matcharg", 1, 1, f_matcharg },
{ "matchdelete", 1, 1, f_matchdelete },
{ "matchend", 2, 4, f_matchend },
@@ -7316,7 +7346,7 @@ static struct fst {
{ "sqrt", 1, 1, f_sqrt },
{ "str2float", 1, 1, f_str2float },
{ "str2nr", 1, 2, f_str2nr },
- { "strchars", 1, 1, f_strchars },
+ { "strchars", 1, 2, f_strchars },
{ "strdisplaywidth", 1, 2, f_strdisplaywidth },
{ "strftime", 1, 2, f_strftime },
{ "stridx", 2, 3, f_stridx },
@@ -7834,7 +7864,8 @@ static void f_add(typval_T *argvars, typval_T *rettv)
rettv->vval.v_number = 1; /* Default: Failed */
if (argvars[0].v_type == VAR_LIST) {
if ((l = argvars[0].vval.v_list) != NULL
- && !tv_check_lock(l->lv_lock, (char_u *)_("add() argument"))) {
+ && !tv_check_lock(l->lv_lock,
+ (char_u *)N_("add() argument"), true)) {
list_append_tv(l, &argvars[1]);
copy_tv(&argvars[0], rettv);
}
@@ -9109,9 +9140,10 @@ static void f_exists(typval_T *argvars, typval_T *rettv)
name = p;
len = get_name_len(&p, &tofree, TRUE, FALSE);
if (len > 0) {
- if (tofree != NULL)
+ if (tofree != NULL) {
name = tofree;
- n = (get_var_tv(name, len, &tv, FALSE, TRUE) == OK);
+ }
+ n = (get_var_tv(name, len, &tv, NULL, false, true) == OK);
if (n) {
/* handle d.key, l[idx], f(expr) */
n = (handle_subscript(&p, &tv, TRUE, FALSE) == OK);
@@ -9209,6 +9241,7 @@ void dict_extend(dict_T *d1, dict_T *d2, char_u *action)
hashitem_T *hi2;
int todo;
bool watched = is_watched(d1);
+ char_u *arg_errmsg = (char_u *)N_("extend() argument");
todo = (int)d2->dv_hashtab.ht_used;
for (hi2 = d2->dv_hashtab.ht_array; todo > 0; ++hi2) {
@@ -9242,6 +9275,11 @@ void dict_extend(dict_T *d1, dict_T *d2, char_u *action)
} else if (*action == 'f' && HI2DI(hi2) != di1) {
typval_T oldtv;
+ if (tv_check_lock(di1->di_tv.v_lock, arg_errmsg, true)
+ || var_check_ro(di1->di_flags, arg_errmsg, true)) {
+ break;
+ }
+
if (watched) {
copy_tv(&di1->di_tv, &oldtv);
}
@@ -9264,7 +9302,7 @@ void dict_extend(dict_T *d1, dict_T *d2, char_u *action)
*/
static void f_extend(typval_T *argvars, typval_T *rettv)
{
- char *arg_errmsg = N_("extend() argument");
+ char_u *arg_errmsg = (char_u *)N_("extend() argument");
if (argvars[0].v_type == VAR_LIST && argvars[1].v_type == VAR_LIST) {
list_T *l1, *l2;
@@ -9274,7 +9312,7 @@ static void f_extend(typval_T *argvars, typval_T *rettv)
l1 = argvars[0].vval.v_list;
l2 = argvars[1].vval.v_list;
- if (l1 != NULL && !tv_check_lock(l1->lv_lock, (char_u *)_(arg_errmsg))
+ if (l1 != NULL && !tv_check_lock(l1->lv_lock, arg_errmsg, true)
&& l2 != NULL) {
if (argvars[2].v_type != VAR_UNKNOWN) {
before = get_tv_number_chk(&argvars[2], &error);
@@ -9304,7 +9342,7 @@ static void f_extend(typval_T *argvars, typval_T *rettv)
d1 = argvars[0].vval.v_dict;
d2 = argvars[1].vval.v_dict;
- if (d1 != NULL && !tv_check_lock(d1->dv_lock, (char_u *)_(arg_errmsg))
+ if (d1 != NULL && !tv_check_lock(d1->dv_lock, arg_errmsg, true)
&& d2 != NULL) {
/* Check the third argument. */
if (argvars[2].v_type != VAR_UNKNOWN) {
@@ -9450,19 +9488,21 @@ static void filter_map(typval_T *argvars, typval_T *rettv, int map)
int rem;
int todo;
char_u *ermsg = (char_u *)(map ? "map()" : "filter()");
- char *arg_errmsg = (map ? N_("map() argument")
- : N_("filter() argument"));
+ char_u *arg_errmsg = (char_u *)(map ? N_("map() argument")
+ : N_("filter() argument"));
int save_did_emsg;
int idx = 0;
if (argvars[0].v_type == VAR_LIST) {
if ((l = argvars[0].vval.v_list) == NULL
- || tv_check_lock(l->lv_lock, (char_u *)_(arg_errmsg)))
+ || (!map && tv_check_lock(l->lv_lock, arg_errmsg, true))) {
return;
+ }
} else if (argvars[0].v_type == VAR_DICT) {
if ((d = argvars[0].vval.v_dict) == NULL
- || tv_check_lock(d->dv_lock, (char_u *)_(arg_errmsg)))
+ || (!map && tv_check_lock(d->dv_lock, arg_errmsg, true))) {
return;
+ }
} else {
EMSG2(_(e_listdictarg), ermsg);
return;
@@ -9491,17 +9531,26 @@ static void filter_map(typval_T *argvars, typval_T *rettv, int map)
for (hi = ht->ht_array; todo > 0; ++hi) {
if (!HASHITEM_EMPTY(hi)) {
--todo;
+
di = HI2DI(hi);
- if (tv_check_lock(di->di_tv.v_lock,
- (char_u *)_(arg_errmsg)))
+ if (map
+ && (tv_check_lock(di->di_tv.v_lock, arg_errmsg, true)
+ || var_check_ro(di->di_flags, arg_errmsg, true))) {
break;
+ }
+
vimvars[VV_KEY].vv_str = vim_strsave(di->di_key);
int r = filter_map_one(&di->di_tv, expr, map, &rem);
clear_tv(&vimvars[VV_KEY].vv_tv);
if (r == FAIL || did_emsg)
break;
- if (!map && rem)
+ if (!map && rem) {
+ if (var_check_fixed(di->di_flags, arg_errmsg, true)
+ || var_check_ro(di->di_flags, arg_errmsg, true)) {
+ break;
+ }
dictitem_remove(d, di);
+ }
}
}
hash_unlock(ht);
@@ -9509,8 +9558,9 @@ static void filter_map(typval_T *argvars, typval_T *rettv, int map)
vimvars[VV_KEY].vv_type = VAR_NUMBER;
for (li = l->lv_first; li != NULL; li = nli) {
- if (tv_check_lock(li->li_tv.v_lock, (char_u *)_(arg_errmsg)))
+ if (map && tv_check_lock(li->li_tv.v_lock, arg_errmsg, true)) {
break;
+ }
nli = li->li_next;
vimvars[VV_KEY].vv_nr = idx;
if (filter_map_one(&li->li_tv, expr, map, &rem) == FAIL
@@ -10373,6 +10423,14 @@ static void f_getmatches(typval_T *argvars, typval_T *rettv)
dict_add_nr_str(dict, "group", 0L, syn_id2name(cur->hlg_id));
dict_add_nr_str(dict, "priority", (long)cur->priority, NULL);
dict_add_nr_str(dict, "id", (long)cur->id, NULL);
+
+ if (cur->conceal_char) {
+ char_u buf[MB_MAXBYTES + 1];
+
+ buf[(*mb_char2bytes)((int)cur->conceal_char, buf)] = NUL;
+ dict_add_nr_str(dict, "conceal", 0L, (char_u *)&buf);
+ }
+
list_append_dict(rettv->vval.v_list, dict);
cur = cur->next;
}
@@ -10544,9 +10602,10 @@ static void f_gettabvar(typval_T *argvars, typval_T *rettv)
varname = get_tv_string_chk(&argvars[1]);
tp = find_tabpage((int)get_tv_number_chk(&argvars[0], NULL));
if (tp != NULL && varname != NULL) {
- /* Set tp to be our tabpage, temporarily. Also set the window to the
- * first window in the tabpage, otherwise the window is not valid. */
- if (switch_win(&oldcurwin, &oldtabpage, tp->tp_firstwin, tp, TRUE) == OK) {
+ // Set tp to be our tabpage, temporarily. Also set the window to the
+ // first window in the tabpage, otherwise the window is not valid.
+ win_T *window = tp->tp_firstwin == NULL ? firstwin : tp->tp_firstwin;
+ if (switch_win(&oldcurwin, &oldtabpage, window, tp, true) == OK) {
// look up the variable
// Let gettabvar({nr}, "") return the "t:" dictionary.
v = find_var_in_ht(&tp->tp_vars->dv_hashtab, 't', varname, FALSE);
@@ -10639,11 +10698,11 @@ getwinvar (
int off /* 1 for gettabwinvar() */
)
{
- win_T *win, *oldcurwin;
- char_u *varname;
- dictitem_T *v;
- tabpage_T *tp = NULL;
- tabpage_T *oldtabpage = NULL;
+ win_T *win, *oldcurwin;
+ char_u *varname;
+ dictitem_T *v;
+ tabpage_T *tp = NULL;
+ tabpage_T *oldtabpage = NULL;
bool done = false;
if (off == 1)
@@ -10658,12 +10717,16 @@ getwinvar (
rettv->vval.v_string = NULL;
if (win != NULL && varname != NULL) {
- /* Set curwin to be our win, temporarily. Also set the tabpage,
- * otherwise the window is not valid. */
- if (switch_win(&oldcurwin, &oldtabpage, win, tp, TRUE) == OK) {
- if (*varname == '&') { /* window-local-option */
- if (get_option_tv(&varname, rettv, 1) == OK)
+ // Set curwin to be our win, temporarily. Also set the tabpage,
+ // otherwise the window is not valid. Only do this when needed,
+ // autocommands get blocked.
+ bool need_switch_win = tp != curtab || win != curwin;
+ if (!need_switch_win
+ || switch_win(&oldcurwin, &oldtabpage, win, tp, true) == OK) {
+ if (*varname == '&') { // window-local-option
+ if (get_option_tv(&varname, rettv, 1) == OK) {
done = true;
+ }
} else {
// Look up the variable.
// Let getwinvar({nr}, "") return the "w:" dictionary.
@@ -10675,8 +10738,10 @@ getwinvar (
}
}
- /* restore previous notion of curwin */
- restore_win(oldcurwin, oldtabpage, TRUE);
+ if (need_switch_win) {
+ // restore previous notion of curwin
+ restore_win(oldcurwin, oldtabpage, true);
+ }
}
if (!done && argvars[off + 2].v_type != VAR_UNKNOWN)
@@ -10701,10 +10766,15 @@ static void f_glob(typval_T *argvars, typval_T *rettv)
if (argvars[1].v_type != VAR_UNKNOWN) {
if (get_tv_number_chk(&argvars[1], &error))
options |= WILD_KEEP_ALL;
- if (argvars[2].v_type != VAR_UNKNOWN
- && get_tv_number_chk(&argvars[2], &error)) {
- rettv->v_type = VAR_LIST;
- rettv->vval.v_list = NULL;
+ if (argvars[2].v_type != VAR_UNKNOWN) {
+ if (get_tv_number_chk(&argvars[2], &error)) {
+ rettv->v_type = VAR_LIST;
+ rettv->vval.v_list = NULL;
+ }
+ if (argvars[3].v_type != VAR_UNKNOWN
+ && get_tv_number_chk(&argvars[3], &error)) {
+ options |= WILD_ALLLINKS;
+ }
}
}
if (!error) {
@@ -10743,10 +10813,15 @@ static void f_globpath(typval_T *argvars, typval_T *rettv)
flags |= WILD_KEEP_ALL;
}
- if (argvars[3].v_type != VAR_UNKNOWN
- && get_tv_number_chk(&argvars[3], &error)) {
- rettv->v_type = VAR_LIST;
- rettv->vval.v_list = NULL;
+ if (argvars[3].v_type != VAR_UNKNOWN) {
+ if (get_tv_number_chk(&argvars[3], &error)) {
+ rettv->v_type = VAR_LIST;
+ rettv->vval.v_list = NULL;
+ }
+ if (argvars[4].v_type != VAR_UNKNOWN
+ && get_tv_number_chk(&argvars[4], &error)) {
+ flags |= WILD_ALLLINKS;
+ }
}
}
@@ -10773,15 +10848,15 @@ static void f_globpath(typval_T *argvars, typval_T *rettv)
}
}
-/*
- * "glob2regpat()" function
- */
+// "glob2regpat()" function
static void f_glob2regpat(typval_T *argvars, typval_T *rettv)
{
- char_u *pat = get_tv_string_chk(&argvars[0]);
+ char_u *pat = get_tv_string_chk(&argvars[0]); // NULL on type error
- rettv->v_type = VAR_STRING;
- rettv->vval.v_string = file_pat_to_reg_pat(pat, NULL, NULL, FALSE);
+ rettv->v_type = VAR_STRING;
+ rettv->vval.v_string = (pat == NULL)
+ ? NULL
+ : file_pat_to_reg_pat(pat, NULL, NULL, false);
}
/*
@@ -10881,6 +10956,7 @@ static void f_has(typval_T *argvars, typval_T *rettv)
#if !defined(UNIX)
"system", // TODO(SplinterOfChaos): This IS defined for UNIX!
#endif
+ "tablineat",
"tag_binary",
"tag_old_static",
"termresponse",
@@ -10938,8 +11014,6 @@ static void f_has(typval_T *argvars, typval_T *rettv)
#endif
} else if (STRICMP(name, "syntax_items") == 0) {
n = syntax_present(curwin);
- } else if (STRICMP(name, "gui_running") == 0) {
- n = ui_rgb_attached();
}
}
@@ -11394,14 +11468,18 @@ static void f_insert(typval_T *argvars, typval_T *rettv)
list_T *l;
int error = FALSE;
- if (argvars[0].v_type != VAR_LIST)
+ if (argvars[0].v_type != VAR_LIST) {
EMSG2(_(e_listarg), "insert()");
- else if ((l = argvars[0].vval.v_list) != NULL
- && !tv_check_lock(l->lv_lock, (char_u *)_("insert() argument"))) {
- if (argvars[2].v_type != VAR_UNKNOWN)
+ } else if ((l = argvars[0].vval.v_list) != NULL
+ && !tv_check_lock(l->lv_lock,
+ (char_u *)N_("insert() argument"), true)) {
+ if (argvars[2].v_type != VAR_UNKNOWN) {
before = get_tv_number_chk(&argvars[2], &error);
- if (error)
- return; /* type error; errmsg already given */
+ }
+ if (error) {
+ // type error; errmsg already given
+ return;
+ }
if (before == l->lv_len)
item = NULL;
@@ -12424,7 +12502,8 @@ static void f_matchadd(typval_T *argvars, typval_T *rettv)
char_u *pat = get_tv_string_buf_chk(&argvars[1], buf); /* pattern */
int prio = 10; /* default priority */
int id = -1;
- int error = FALSE;
+ int error = false;
+ char_u *conceal_char = NULL;
rettv->vval.v_number = -1;
@@ -12432,17 +12511,31 @@ static void f_matchadd(typval_T *argvars, typval_T *rettv)
return;
if (argvars[2].v_type != VAR_UNKNOWN) {
prio = get_tv_number_chk(&argvars[2], &error);
- if (argvars[3].v_type != VAR_UNKNOWN)
+ if (argvars[3].v_type != VAR_UNKNOWN) {
id = get_tv_number_chk(&argvars[3], &error);
+ if (argvars[4].v_type != VAR_UNKNOWN) {
+ if (argvars[4].v_type != VAR_DICT) {
+ EMSG(_(e_dictreq));
+ return;
+ }
+ if (dict_find(argvars[4].vval.v_dict,
+ (char_u *)"conceal", -1) != NULL) {
+ conceal_char = get_dict_string(argvars[4].vval.v_dict,
+ (char_u *)"conceal", false);
+ }
+ }
+ }
}
- if (error == TRUE)
+ if (error == true) {
return;
+ }
if (id >= 1 && id <= 3) {
EMSGN("E798: ID is reserved for \":match\": %" PRId64, id);
return;
}
- rettv->vval.v_number = match_add(curwin, grp, pat, prio, id, NULL);
+ rettv->vval.v_number = match_add(curwin, grp, pat, prio, id, NULL,
+ conceal_char);
}
static void f_matchaddpos(typval_T *argvars, typval_T *rettv) FUNC_ATTR_NONNULL_ALL
@@ -12470,12 +12563,24 @@ static void f_matchaddpos(typval_T *argvars, typval_T *rettv) FUNC_ATTR_NONNULL_
int error = false;
int prio = 10;
int id = -1;
+ char_u *conceal_char = NULL;
if (argvars[2].v_type != VAR_UNKNOWN) {
- prio = get_tv_number_chk(&argvars[2], &error);
- if (argvars[3].v_type != VAR_UNKNOWN) {
- id = get_tv_number_chk(&argvars[3], &error);
+ prio = get_tv_number_chk(&argvars[2], &error);
+ if (argvars[3].v_type != VAR_UNKNOWN) {
+ id = get_tv_number_chk(&argvars[3], &error);
+ if (argvars[4].v_type != VAR_UNKNOWN) {
+ if (argvars[4].v_type != VAR_DICT) {
+ EMSG(_(e_dictreq));
+ return;
+ }
+ if (dict_find(argvars[4].vval.v_dict,
+ (char_u *)"conceal", -1) != NULL) {
+ conceal_char = get_dict_string(argvars[4].vval.v_dict,
+ (char_u *)"conceal", false);
+ }
}
+ }
}
if (error == true) {
return;
@@ -12487,7 +12592,8 @@ static void f_matchaddpos(typval_T *argvars, typval_T *rettv) FUNC_ATTR_NONNULL_
return;
}
- rettv->vval.v_number = match_add(curwin, group, NULL, prio, id, l);
+ rettv->vval.v_number = match_add(curwin, group, NULL, prio, id, l,
+ conceal_char);
}
/*
@@ -13855,19 +13961,20 @@ static void f_remove(typval_T *argvars, typval_T *rettv)
char_u *key;
dict_T *d;
dictitem_T *di;
- char *arg_errmsg = N_("remove() argument");
+ char_u *arg_errmsg = (char_u *)N_("remove() argument");
if (argvars[0].v_type == VAR_DICT) {
- if (argvars[2].v_type != VAR_UNKNOWN)
+ if (argvars[2].v_type != VAR_UNKNOWN) {
EMSG2(_(e_toomanyarg), "remove()");
- else if ((d = argvars[0].vval.v_dict) != NULL
- && !tv_check_lock(d->dv_lock, (char_u *)_(arg_errmsg))) {
+ } else if ((d = argvars[0].vval.v_dict) != NULL
+ && !tv_check_lock(d->dv_lock, arg_errmsg, true)) {
key = get_tv_string_chk(&argvars[1]);
if (key != NULL) {
di = dict_find(d, key, -1);
- if (di == NULL)
+ if (di == NULL) {
EMSG2(_(e_dictkey), key);
- else {
+ } else if (!var_check_fixed(di->di_flags, arg_errmsg, true)
+ && !var_check_ro(di->di_flags, arg_errmsg, true)) {
*rettv = di->di_tv;
init_tv(&di->di_tv);
dictitem_remove(d, di);
@@ -13877,11 +13984,11 @@ static void f_remove(typval_T *argvars, typval_T *rettv)
}
}
}
- } else if (argvars[0].v_type != VAR_LIST)
+ } else if (argvars[0].v_type != VAR_LIST) {
EMSG2(_(e_listdictarg), "remove()");
- else if ((l = argvars[0].vval.v_list) != NULL
- && !tv_check_lock(l->lv_lock, (char_u *)_(arg_errmsg))) {
- int error = FALSE;
+ } else if ((l = argvars[0].vval.v_list) != NULL
+ && !tv_check_lock(l->lv_lock, arg_errmsg, true)) {
+ int error = (int)false;
idx = get_tv_number_chk(&argvars[1], &error);
if (error)
@@ -14155,10 +14262,11 @@ static void f_reverse(typval_T *argvars, typval_T *rettv)
list_T *l;
listitem_T *li, *ni;
- if (argvars[0].v_type != VAR_LIST)
+ if (argvars[0].v_type != VAR_LIST) {
EMSG2(_(e_listarg), "reverse()");
- else if ((l = argvars[0].vval.v_list) != NULL
- && !tv_check_lock(l->lv_lock, (char_u *)_("reverse() argument"))) {
+ } else if ((l = argvars[0].vval.v_list) != NULL
+ && !tv_check_lock(l->lv_lock,
+ (char_u *)N_("reverse() argument"), true)) {
li = l->lv_last;
l->lv_first = l->lv_last = NULL;
l->lv_len = 0;
@@ -15159,6 +15267,7 @@ static void f_setmatches(typval_T *argvars, typval_T *rettv)
list_T *l;
listitem_T *li;
dict_T *d;
+ list_T *s = NULL;
rettv->vval.v_number = -1;
if (argvars[0].v_type != VAR_LIST) {
@@ -15177,7 +15286,8 @@ static void f_setmatches(typval_T *argvars, typval_T *rettv)
return;
}
if (!(dict_find(d, (char_u *)"group", -1) != NULL
- && dict_find(d, (char_u *)"pattern", -1) != NULL
+ && (dict_find(d, (char_u *)"pattern", -1) != NULL
+ || dict_find(d, (char_u *)"pos1", -1) != NULL)
&& dict_find(d, (char_u *)"priority", -1) != NULL
&& dict_find(d, (char_u *)"id", -1) != NULL)) {
EMSG(_(e_invarg));
@@ -15189,11 +15299,51 @@ static void f_setmatches(typval_T *argvars, typval_T *rettv)
clear_matches(curwin);
li = l->lv_first;
while (li != NULL) {
+ int i = 0;
+ char_u buf[5];
+ dictitem_T *di;
+
d = li->li_tv.vval.v_dict;
- match_add(curwin, get_dict_string(d, (char_u *)"group", FALSE),
- get_dict_string(d, (char_u *)"pattern", FALSE),
- (int)get_dict_number(d, (char_u *)"priority"),
- (int)get_dict_number(d, (char_u *)"id"), NULL);
+ if (dict_find(d, (char_u *)"pattern", -1) == NULL) {
+ if (s == NULL) {
+ s = list_alloc();
+ if (s == NULL) {
+ return;
+ }
+ }
+
+ // match from matchaddpos()
+ for (i = 1; i < 9; ++i) {
+ snprintf((char *)buf, sizeof(buf), (char *)"pos%d", i);
+ if ((di = dict_find(d, (char_u *)buf, -1)) != NULL) {
+ if (di->di_tv.v_type != VAR_LIST) {
+ return;
+ }
+
+ list_append_tv(s, &di->di_tv);
+ s->lv_refcount++;
+ } else {
+ break;
+ }
+ }
+ }
+
+ char_u *group = get_dict_string(d, (char_u *)"group", false);
+ int priority = get_dict_number(d, (char_u *)"priority");
+ int id = get_dict_number(d, (char_u *)"id");
+ char_u *conceal = dict_find(d, (char_u *)"conceal", -1) != NULL
+ ? get_dict_string(d, (char_u *)"conceal",
+ false)
+ : NULL;
+ if (i == 0) {
+ match_add(curwin, group,
+ get_dict_string(d, (char_u *)"pattern", false),
+ priority, id, NULL, conceal);
+ } else {
+ match_add(curwin, group, NULL, priority, id, s, conceal);
+ list_unref(s);
+ s = NULL;
+ }
li = li->li_next;
}
rettv->vval.v_number = 0;
@@ -15416,26 +15566,32 @@ static void setwinvar(typval_T *argvars, typval_T *rettv, int off)
varname = get_tv_string_chk(&argvars[off + 1]);
varp = &argvars[off + 2];
- if (win != NULL && varname != NULL && varp != NULL
- && switch_win(&save_curwin, &save_curtab, win, tp, TRUE) == OK) {
- if (*varname == '&') {
- long numval;
- char_u *strval;
- int error = FALSE;
-
- ++varname;
- numval = get_tv_number_chk(varp, &error);
- strval = get_tv_string_buf_chk(varp, nbuf);
- if (!error && strval != NULL)
- set_option_value(varname, numval, strval, OPT_LOCAL);
- } else {
- winvarname = xmalloc(STRLEN(varname) + 3);
- STRCPY(winvarname, "w:");
- STRCPY(winvarname + 2, varname);
- set_var(winvarname, varp, TRUE);
- xfree(winvarname);
+ if (win != NULL && varname != NULL && varp != NULL) {
+ bool need_switch_win = tp != curtab || win != curwin;
+ if (!need_switch_win
+ || switch_win(&save_curwin, &save_curtab, win, tp, true) == OK) {
+ if (*varname == '&') {
+ long numval;
+ char_u *strval;
+ int error = false;
+
+ ++varname;
+ numval = get_tv_number_chk(varp, &error);
+ strval = get_tv_string_buf_chk(varp, nbuf);
+ if (!error && strval != NULL) {
+ set_option_value(varname, numval, strval, OPT_LOCAL);
+ }
+ } else {
+ winvarname = xmalloc(STRLEN(varname) + 3);
+ STRCPY(winvarname, "w:");
+ STRCPY(winvarname + 2, varname);
+ set_var(winvarname, varp, true);
+ xfree(winvarname);
+ }
+ }
+ if (need_switch_win) {
+ restore_win(save_curwin, save_curtab, true);
}
- restore_win(save_curwin, save_curtab, TRUE);
}
}
@@ -15654,8 +15810,12 @@ static void do_sort_uniq(typval_T *argvars, typval_T *rettv, bool sort)
EMSG2(_(e_listarg), sort ? "sort()" : "uniq()");
} else {
l = argvars[0].vval.v_list;
- if (l == NULL || tv_check_lock(l->lv_lock,
- (char_u *)(sort ? _("sort() argument") : _("uniq() argument")))) {
+ if (l == NULL ||
+ tv_check_lock(l->lv_lock,
+ (char_u *)(sort
+ ? N_("sort() argument")
+ : N_("uniq() argument")),
+ true)) {
return;
}
rettv->vval.v_list = l;
@@ -15987,6 +16147,7 @@ static void f_str2nr(typval_T *argvars, typval_T *rettv)
int base = 10;
char_u *p;
long n;
+ int what;
if (argvars[1].v_type != VAR_UNKNOWN) {
base = get_tv_number(&argvars[1]);
@@ -16000,11 +16161,20 @@ static void f_str2nr(typval_T *argvars, typval_T *rettv)
if (*p == '+') {
p = skipwhite(p + 1);
}
- vim_str2nr(p, NULL, NULL,
- base == 2 ? 2 : 0,
- base == 8 ? 2 : 0,
- base == 16 ? 2 : 0,
- &n, NULL);
+ switch (base) {
+ case 2:
+ what = STR2NR_BIN + STR2NR_FORCE;
+ break;
+ case 8:
+ what = STR2NR_OCT + STR2NR_FORCE;
+ break;
+ case 16:
+ what = STR2NR_HEX + STR2NR_FORCE;
+ break;
+ default:
+ what = 0;
+ }
+ vim_str2nr(p, NULL, NULL, what, &n, NULL, 0);
rettv->vval.v_number = n;
}
@@ -16116,13 +16286,23 @@ static void f_strlen(typval_T *argvars, typval_T *rettv)
static void f_strchars(typval_T *argvars, typval_T *rettv)
{
char_u *s = get_tv_string(&argvars[0]);
+ int skipcc = 0;
varnumber_T len = 0;
+ int (*func_mb_ptr2char_adv)(char_u **pp);
- while (*s != NUL) {
- mb_cptr2char_adv(&s);
- ++len;
+ if (argvars[1].v_type != VAR_UNKNOWN) {
+ skipcc = get_tv_number_chk(&argvars[1], NULL);
+ }
+ if (skipcc < 0 || skipcc > 1) {
+ EMSG(_(e_invarg));
+ } else {
+ func_mb_ptr2char_adv = skipcc ? mb_ptr2char_adv : mb_cptr2char_adv;
+ while (*s != NUL) {
+ func_mb_ptr2char_adv(&s);
+ ++len;
+ }
+ rettv->vval.v_number = len;
}
- rettv->vval.v_number = len;
}
/*
@@ -17924,23 +18104,23 @@ void set_vim_var_list(int idx, list_T *val)
}
/// Set Dictionary v: variable to "val".
-void set_vim_var_dict(int idx, dict_T *val) FUNC_ATTR_NONNULL_ALL
+void set_vim_var_dict(int idx, dict_T *val)
{
dict_unref(vimvars[idx].vv_dict);
+ vimvars[idx].vv_dict = val;
- // Set readonly
- int todo = (int)val->dv_hashtab.ht_used;
- for (hashitem_T *hi = val->dv_hashtab.ht_array; todo > 0 ; ++hi) {
- if (HASHITEM_EMPTY(hi)) {
- continue;
+ 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;
}
-
- --todo;
- HI2DI(hi)->di_flags = DI_FLAGS_RO | DI_FLAGS_FIX;
}
-
- vimvars[idx].vv_dict = val;
- ++val->dv_refcount;
}
/*
@@ -18058,10 +18238,11 @@ char_u *set_cmdarg(exarg_T *eap, char_u *oldarg)
static int
get_var_tv (
char_u *name,
- int len, /* length of "name" */
- typval_T *rettv, /* NULL when only checking existence */
- int verbose, /* may give error message */
- int no_autoload /* do not use script autoloading */
+ int len, // length of "name"
+ typval_T *rettv, // NULL when only checking existence
+ dictitem_T **dip, // non-NULL when typval's dict item is needed
+ int verbose, // may give error message
+ int no_autoload // do not use script autoloading
)
{
int ret = OK;
@@ -18087,8 +18268,12 @@ get_var_tv (
*/
else {
v = find_var(name, NULL, no_autoload);
- if (v != NULL)
+ if (v != NULL) {
tv = &v->di_tv;
+ if (dip != NULL) {
+ *dip = v;
+ }
+ }
}
if (tv == NULL) {
@@ -18286,7 +18471,7 @@ long get_tv_number_chk(typval_T *varp, int *denote)
case VAR_STRING:
if (varp->vval.v_string != NULL) {
vim_str2nr(varp->vval.v_string, NULL, NULL,
- true, true, true, &n, NULL);
+ STR2NR_ALL, &n, NULL, 0);
}
return n;
case VAR_LIST:
@@ -18479,6 +18664,9 @@ static hashtab_T *find_var_ht_dict(char_u *name, uint8_t **varname, dict_T **d)
hashitem_T *hi;
*d = NULL;
+ if (name[0] == NUL) {
+ return NULL;
+ }
if (name[1] != ':') {
// name has implicit scope
if (name[0] == ':' || name[0] == AUTOLOAD_CHAR) {
@@ -18528,6 +18716,7 @@ end:
}
// Find the hashtab used for a variable name.
+// Return NULL if the name is not valid.
// Set "varname" to the start of name without ':'.
static hashtab_T *find_var_ht(uint8_t *name, uint8_t **varname)
{
@@ -18635,14 +18824,16 @@ static void vars_clear_ext(hashtab_T *ht, int free_val)
if (!HASHITEM_EMPTY(hi)) {
--todo;
- /* Free the variable. Don't remove it from the hashtab,
- * ht_array might change then. hash_clear() takes care of it
- * later. */
+ // Free the variable. Don't remove it from the hashtab,
+ // ht_array might change then. hash_clear() takes care of it
+ // later.
v = HI2DI(hi);
- if (free_val)
+ if (free_val) {
clear_tv(&v->di_tv);
- if ((v->di_flags & DI_FLAGS_FIX) == 0)
+ }
+ if (v->di_flags & DI_FLAGS_ALLOC) {
xfree(v);
+ }
}
}
hash_clear(ht);
@@ -18749,10 +18940,11 @@ set_var (
return;
if (v != NULL) {
- /* existing variable, need to clear the value */
- if (var_check_ro(v->di_flags, name)
- || tv_check_lock(v->di_tv.v_lock, name))
+ // existing variable, need to clear the value
+ if (var_check_ro(v->di_flags, name, false)
+ || tv_check_lock(v->di_tv.v_lock, name, false)) {
return;
+ }
if (v->di_tv.v_type != tv->v_type
&& !((v->di_tv.v_type == VAR_STRING
|| v->di_tv.v_type == VAR_NUMBER)
@@ -18767,10 +18959,8 @@ set_var (
return;
}
- /*
- * Handle setting internal v: variables separately: we don't change
- * the type.
- */
+ // Handle setting internal v: variables separately where needed to
+ // prevent changing the type.
if (ht == &vimvarht) {
if (v->di_tv.v_type == VAR_STRING) {
xfree(v->di_tv.vval.v_string);
@@ -18781,9 +18971,8 @@ set_var (
v->di_tv.vval.v_string = tv->vval.v_string;
tv->vval.v_string = NULL;
}
- } else if (v->di_tv.v_type != VAR_NUMBER)
- EMSG2(_(e_intern2), "set_var()");
- else {
+ return;
+ } else if (v->di_tv.v_type == VAR_NUMBER) {
v->di_tv.vval.v_number = get_tv_number(tv);
if (STRCMP(varname, "searchforward") == 0)
set_search_direction(v->di_tv.vval.v_number ? '/' : '?');
@@ -18791,8 +18980,10 @@ set_var (
no_hlsearch = !v->di_tv.vval.v_number;
redraw_all_later(SOME_VALID);
}
+ return;
+ } else if (v->di_tv.v_type != tv->v_type) {
+ EMSG2(_(e_intern2), "set_var()");
}
- return;
}
if (watched) {
@@ -18816,7 +19007,7 @@ set_var (
xfree(v);
return;
}
- v->di_flags = 0;
+ v->di_flags = DI_FLAGS_ALLOC;
}
if (copy || tv->v_type == VAR_NUMBER || tv->v_type == VAR_FLOAT) {
@@ -18837,34 +19028,31 @@ set_var (
}
}
-/*
- * Return TRUE if di_flags "flags" indicates variable "name" is read-only.
- * Also give an error message.
- */
-static int var_check_ro(int flags, char_u *name)
+// Return true if di_flags "flags" indicates variable "name" is read-only.
+// Also give an error message.
+static bool var_check_ro(int flags, char_u *name, bool use_gettext)
{
if (flags & DI_FLAGS_RO) {
- EMSG2(_(e_readonlyvar), name);
- return TRUE;
+ EMSG2(_(e_readonlyvar), use_gettext ? (char_u *)_(name) : name);
+ return true;
}
if ((flags & DI_FLAGS_RO_SBX) && sandbox) {
- EMSG2(_(e_readonlysbx), name);
- return TRUE;
+ EMSG2(_(e_readonlysbx), use_gettext ? (char_u *)_(name) : name);
+ return true;
}
- return FALSE;
+ return false;
}
-/*
- * Return TRUE if di_flags "flags" indicates variable "name" is fixed.
- * Also give an error message.
- */
-static int var_check_fixed(int flags, char_u *name)
+// Return true if di_flags "flags" indicates variable "name" is fixed.
+// Also give an error message.
+static bool var_check_fixed(int flags, char_u *name, bool use_gettext)
{
if (flags & DI_FLAGS_FIX) {
- EMSG2(_("E795: Cannot delete variable %s"), name);
- return TRUE;
+ EMSG2(_("E795: Cannot delete variable %s"),
+ use_gettext ? (char_u *)_(name) : name);
+ return true;
}
- return FALSE;
+ return false;
}
/*
@@ -18912,23 +19100,28 @@ static int valid_varname(char_u *varname)
return TRUE;
}
-/*
- * Return TRUE if typeval "tv" is set to be locked (immutable).
- * Also give an error message, using "name".
- */
-static int tv_check_lock(int lock, char_u *name)
+// Return true if typeval "tv" is set to be locked (immutable).
+// Also give an error message, using "name" or _("name") when use_gettext is
+// true.
+static bool tv_check_lock(int lock, char_u *name, bool use_gettext)
{
if (lock & VAR_LOCKED) {
EMSG2(_("E741: Value is locked: %s"),
- name == NULL ? (char_u *)_("Unknown") : name);
- return TRUE;
+ name == NULL
+ ? (char_u *)_("Unknown")
+ : use_gettext ? (char_u *)_(name)
+ : name);
+ return true;
}
if (lock & VAR_FIXED) {
EMSG2(_("E742: Cannot change value of %s"),
- name == NULL ? (char_u *)_("Unknown") : name);
- return TRUE;
+ name == NULL
+ ? (char_u *)_("Unknown")
+ : use_gettext ? (char_u *)_(name)
+ : name);
+ return true;
}
- return FALSE;
+ return false;
}
/*
@@ -19521,7 +19714,10 @@ void ex_function(exarg_T *eap)
break;
}
}
- ++p; /* skip the ')' */
+ if (*p != ')') {
+ goto erret;
+ }
+ ++p; // skip the ')'
/* find extra arguments "range", "dict" and "abort" */
for (;; ) {
@@ -19745,13 +19941,14 @@ void ex_function(exarg_T *eap)
goto erret;
}
if (fudi.fd_di == NULL) {
- /* Can't add a function to a locked dictionary */
- if (tv_check_lock(fudi.fd_dict->dv_lock, eap->arg))
+ if (tv_check_lock(fudi.fd_dict->dv_lock, eap->arg, false)) {
+ // Can't add a function to a locked dictionary
goto erret;
- }
- /* Can't change an existing function if it is locked */
- else if (tv_check_lock(fudi.fd_di->di_tv.v_lock, eap->arg))
+ }
+ } else if (tv_check_lock(fudi.fd_di->di_tv.v_lock, eap->arg, false)) {
+ // Can't change an existing function if it is locked
goto erret;
+ }
/* Give the function a sequential number. Can only be used with a
* Funcref! */
@@ -20707,7 +20904,7 @@ call_user_func (
v->di_flags = DI_FLAGS_RO | DI_FLAGS_FIX;
} else {
v = xmalloc(sizeof(dictitem_T) + STRLEN(name));
- v->di_flags = DI_FLAGS_RO;
+ v->di_flags = DI_FLAGS_RO | DI_FLAGS_FIX | DI_FLAGS_ALLOC;
}
STRCPY(v->di_key, name);
hash_add(&fc->l_avars.dv_hashtab, DI2HIKEY(v));
@@ -20729,14 +20926,18 @@ call_user_func (
save_sourcing_name = sourcing_name;
save_sourcing_lnum = sourcing_lnum;
sourcing_lnum = 1;
- sourcing_name = xmalloc((save_sourcing_name == NULL ? 0 : STRLEN(save_sourcing_name))
- + STRLEN(fp->uf_name) + 13);
+ // need space for function name + ("function " + 3) or "[number]"
+ size_t len = (save_sourcing_name == NULL ? 0 : STRLEN(save_sourcing_name))
+ + STRLEN(fp->uf_name) + 20;
+ sourcing_name = xmalloc(len);
{
if (save_sourcing_name != NULL
- && STRNCMP(save_sourcing_name, "function ", 9) == 0)
- sprintf((char *)sourcing_name, "%s..", save_sourcing_name);
- else
+ && STRNCMP(save_sourcing_name, "function ", 9) == 0) {
+ vim_snprintf((char *)sourcing_name, len, "%s[%zu]..",
+ save_sourcing_name, save_sourcing_lnum);
+ } else {
STRCPY(sourcing_name, "function ");
+ }
cat_func_name(sourcing_name + STRLEN(sourcing_name), fp);
if (p_verbose >= 12) {
@@ -22002,7 +22203,6 @@ static void on_process_exit(Process *proc, int status, void *d)
char msg[22];
snprintf(msg, sizeof msg, "\r\n[Process exited %d]", proc->status);
terminal_close(data->term, msg);
- apply_autocmds(EVENT_TERMCLOSE, NULL, NULL, false, curbuf);
}
if (data->status_ptr) {
diff --git a/src/nvim/eval_defs.h b/src/nvim/eval_defs.h
index ed419268d2..cdad1f3197 100644
--- a/src/nvim/eval_defs.h
+++ b/src/nvim/eval_defs.h
@@ -101,10 +101,11 @@ struct dictitem_S {
typedef struct dictitem_S dictitem_T;
-#define DI_FLAGS_RO 1 /* "di_flags" value: read-only variable */
-#define DI_FLAGS_RO_SBX 2 /* "di_flags" value: read-only in the sandbox */
-#define DI_FLAGS_FIX 4 /* "di_flags" value: fixed variable, not allocated */
-#define DI_FLAGS_LOCK 8 /* "di_flags" value: locked variable */
+#define DI_FLAGS_RO 1 // "di_flags" value: read-only variable
+#define DI_FLAGS_RO_SBX 2 // "di_flags" value: read-only in the sandbox
+#define DI_FLAGS_FIX 4 // "di_flags" value: fixed: no :unlet or remove()
+#define DI_FLAGS_LOCK 8 // "di_flags" value: locked variable
+#define DI_FLAGS_ALLOC 16 // "di_flags" value: separately allocated
/*
* Structure to hold info about a Dictionary.
diff --git a/src/nvim/ex_cmds.c b/src/nvim/ex_cmds.c
index 407dded6af..ad21e71c51 100644
--- a/src/nvim/ex_cmds.c
+++ b/src/nvim/ex_cmds.c
@@ -342,27 +342,27 @@ void ex_sort(exarg_T *eap)
char_u *s;
char_u *s2;
char_u c; // temporary character storage
- int unique = false;
+ bool unique = false;
long deleted;
colnr_T start_col;
colnr_T end_col;
- int sort_bin; // sort on bin number
- int sort_oct; // sort on octal number
- int sort_hex; // sort on hex number
+ int sort_what = 0;
// Sorting one line is really quick!
if (count <= 1) {
return;
}
- if (u_save((linenr_T)(eap->line1 - 1), (linenr_T)(eap->line2 + 1)) == FAIL)
+ if (u_save((linenr_T)(eap->line1 - 1), (linenr_T)(eap->line2 + 1)) == FAIL) {
return;
+ }
sortbuf1 = NULL;
sortbuf2 = NULL;
regmatch.regprog = NULL;
sorti_T *nrs = xmalloc(count * sizeof(sorti_T));
- sort_abort = sort_ic = sort_rx = sort_nr = sort_bin = sort_oct = sort_hex = 0;
+ sort_abort = sort_ic = sort_rx = sort_nr = 0;
+ size_t format_found = 0;
for (p = eap->arg; *p != NUL; ++p) {
if (ascii_iswhite(*p)) {
@@ -372,12 +372,16 @@ void ex_sort(exarg_T *eap)
sort_rx = true;
} else if (*p == 'n') {
sort_nr = 2;
+ format_found++;
} else if (*p == 'b') {
- sort_bin = 2;
+ sort_what = STR2NR_BIN + STR2NR_FORCE;
+ format_found++;
} else if (*p == 'o') {
- sort_oct = 2;
+ sort_what = STR2NR_OCT + STR2NR_FORCE;
+ format_found++;
} else if (*p == 'x') {
- sort_hex = 2;
+ sort_what = STR2NR_HEX + STR2NR_FORCE;
+ format_found++;
} else if (*p == 'u') {
unique = true;
} else if (*p == '"') {
@@ -415,13 +419,13 @@ void ex_sort(exarg_T *eap)
}
// Can only have one of 'n', 'b', 'o' and 'x'.
- if (sort_nr + sort_bin + sort_oct + sort_hex > 2) {
+ if (format_found > 1) {
EMSG(_(e_invarg));
goto sortend;
}
// From here on "sort_nr" is used as a flag for any number sorting.
- sort_nr += sort_bin + sort_oct + sort_hex;
+ sort_nr += sort_what;
// Make an array with all line numbers. This avoids having to copy all
// the lines into allocated memory.
@@ -457,22 +461,23 @@ void ex_sort(exarg_T *eap)
*s2 = NUL;
// Sorting on number: Store the number itself.
p = s + start_col;
- if (sort_hex) {
+ if (sort_what & STR2NR_HEX) {
s = skiptohex(p);
- } else if (sort_bin) {
+ } else if (sort_what & STR2NR_BIN) {
s = (char_u*) skiptobin((char*) p);
} else {
s = skiptodigit(p);
}
if (s > p && s[-1] == '-') {
- --s; // include preceding negative sign
+ // include preceding negative sign
+ s--;
}
if (*s == NUL) {
// empty line should sort before any number
nrs[lnum - eap->line1].start_col_nr = -MAXLNUM;
} else {
- vim_str2nr(s, NULL, NULL, sort_bin, sort_oct, sort_hex,
- &nrs[lnum - eap->line1].start_col_nr, NULL);
+ vim_str2nr(s, NULL, NULL, sort_what,
+ &nrs[lnum - eap->line1].start_col_nr, NULL, 0);
}
*s2 = c;
} else {
@@ -685,9 +690,17 @@ int do_move(linenr_T line1, linenr_T line2, linenr_T dest)
{
char_u *str;
linenr_T l;
- linenr_T extra; /* Num lines added before line1 */
- linenr_T num_lines; /* Num lines moved */
- linenr_T last_line; /* Last line in file after adding new text */
+ linenr_T extra; // Num lines added before line1
+ linenr_T num_lines; // Num lines moved
+ linenr_T last_line; // Last line in file after adding new text
+
+ // Moving lines seems to corrupt the folds, delete folding info now
+ // and recreate it when finished. Don't do this for manual folding, it
+ // would delete all folds.
+ bool isFolded = hasAnyFolding(curwin) && !foldmethodIsManual(curwin);
+ if (isFolded) {
+ deleteFoldRecurse(&curwin->w_folds);
+ }
if (dest >= line1 && dest < line2) {
EMSG(_("E134: Move lines into themselves"));
@@ -772,8 +785,14 @@ int do_move(linenr_T line1, linenr_T line2, linenr_T dest)
if (dest > last_line + 1)
dest = last_line + 1;
changed_lines(line1, 0, dest, 0L);
- } else
+ } else {
changed_lines(dest + 1, 0, line1 + num_lines, 0L);
+ }
+
+ // recreate folds
+ if (isFolded) {
+ foldUpdateAll(curwin);
+ }
return OK;
}
@@ -4760,6 +4779,7 @@ void ex_helptags(exarg_T *eap)
WILD_LIST_NOTFOUND|WILD_SILENT, WILD_EXPAND_FREE);
if (dirname == NULL || !os_isdir(dirname)) {
EMSG2(_("E150: Not a directory: %s"), eap->arg);
+ xfree(dirname);
return;
}
@@ -4857,16 +4877,13 @@ helptags_one (
int fi;
char_u *s;
char_u *fname;
- int dirlen;
int utf8 = MAYBE;
int this_utf8;
int firstline;
int mix = FALSE; /* detected mixed encodings */
- /*
- * Find all *.txt files.
- */
- dirlen = (int)STRLEN(dir);
+ // Find all *.txt files.
+ size_t dirlen = STRLEN(dir);
STRCPY(NameBuff, dir);
STRCAT(NameBuff, "/**/*");
STRCAT(NameBuff, ext);
@@ -4888,7 +4905,7 @@ helptags_one (
*/
STRCPY(NameBuff, dir);
add_pathsep((char *)NameBuff);
- STRCAT(NameBuff, tagfname);
+ STRNCAT(NameBuff, tagfname, sizeof(NameBuff) - dirlen - 2);
fd_tags = mch_fopen((char *)NameBuff, "w");
if (fd_tags == NULL) {
EMSG2(_("E152: Cannot open %s for writing"), NameBuff);
diff --git a/src/nvim/ex_docmd.c b/src/nvim/ex_docmd.c
index cbe7c1a231..2d17b31f0f 100644
--- a/src/nvim/ex_docmd.c
+++ b/src/nvim/ex_docmd.c
@@ -381,15 +381,14 @@ int do_cmdline(char_u *cmdline, LineGetter fgetline,
suppress_errthrow = FALSE;
}
- /*
- * If requested, store and reset the global values controlling the
- * exception handling (used when debugging). Otherwise clear it to avoid
- * a bogus compiler warning when the optimizer uses inline functions...
- */
- if (flags & DOCMD_EXCRESET)
+ // If requested, store and reset the global values controlling the
+ // exception handling (used when debugging). Otherwise clear it to avoid
+ // a bogus compiler warning when the optimizer uses inline functions...
+ if (flags & DOCMD_EXCRESET) {
save_dbg_stuff(&debug_saved);
- else
- memset(&debug_saved, 0, 1);
+ } else {
+ memset(&debug_saved, 0, sizeof(debug_saved));
+ }
initial_trylevel = trylevel;
@@ -1702,9 +1701,9 @@ static char_u * do_one_cmd(char_u **cmdlinep,
p = vim_strnsave(ea.cmd, p - ea.cmd);
int ret = apply_autocmds(EVENT_CMDUNDEFINED, p, p, TRUE, NULL);
xfree(p);
- if (ret && !aborting()) {
- p = find_command(&ea, NULL);
- }
+ // If the autocommands did something and didn't cause an error, try
+ // finding the command again.
+ p = (ret && !aborting()) ? find_command(&ea, NULL) : NULL;
}
if (p == NULL) {
@@ -2348,8 +2347,11 @@ static char_u *find_command(exarg_T *eap, int *full)
eap->cmdidx = CMD_k;
++p;
} else if (p[0] == 's'
- && ((p[1] == 'c' && p[2] != 's' && p[2] != 'r'
- && p[3] != 'i' && p[4] != 'p')
+ && ((p[1] == 'c'
+ && (p[2] == NUL
+ || (p[2] != 's' && p[2] != 'r'
+ && (p[3] == NUL
+ || (p[3] != 'i' && p[4] != 'p')))))
|| p[1] == 'g'
|| (p[1] == 'i' && p[2] != 'm' && p[2] != 'l' && p[2] != 'g')
|| p[1] == 'I'
@@ -2676,16 +2678,25 @@ set_one_cmd_context (
p = cmd + 1;
} else {
p = cmd;
- while (ASCII_ISALPHA(*p) || *p == '*') /* Allow * wild card */
- ++p;
- /* check for non-alpha command */
- if (p == cmd && vim_strchr((char_u *)"@*!=><&~#", *p) != NULL)
- ++p;
- /* for python 3.x: ":py3*" commands completion */
+ while (ASCII_ISALPHA(*p) || *p == '*') { // Allow * wild card
+ p++;
+ }
+ // a user command may contain digits
+ if (ASCII_ISUPPER(cmd[0])) {
+ while (ASCII_ISALNUM(*p) || *p == '*') {
+ p++;
+ }
+ }
+ // for python 3.x: ":py3*" commands completion
if (cmd[0] == 'p' && cmd[1] == 'y' && p == cmd + 2 && *p == '3') {
- ++p;
- while (ASCII_ISALPHA(*p) || *p == '*')
- ++p;
+ p++;
+ while (ASCII_ISALPHA(*p) || *p == '*') {
+ p++;
+ }
+ }
+ // check for non-alpha command
+ if (p == cmd && vim_strchr((char_u *)"@*!=><&~#", *p) != NULL) {
+ p++;
}
len = (int)(p - cmd);
@@ -2699,9 +2710,11 @@ set_one_cmd_context (
(size_t)len) == 0)
break;
- if (cmd[0] >= 'A' && cmd[0] <= 'Z')
- while (ASCII_ISALNUM(*p) || *p == '*') /* Allow * wild card */
- ++p;
+ if (cmd[0] >= 'A' && cmd[0] <= 'Z') {
+ while (ASCII_ISALNUM(*p) || *p == '*') { // Allow * wild card
+ p++;
+ }
+ }
}
/*
@@ -5656,8 +5669,13 @@ static void ex_quit(exarg_T *eap)
|| (only_one_window() && check_changed_any(eap->forceit))) {
not_exiting();
} else {
- if (only_one_window()) {
- // quit last window
+ // quit last window
+ // Note: only_one_window() returns true, even so a help window is
+ // still open. In that case only quit, if no address has been
+ // specified. Example:
+ // :h|wincmd w|1q - don't quit
+ // :h|wincmd w|q - quit
+ if (only_one_window() && (firstwin == lastwin || eap->addr_count == 0)) {
getout(0);
}
/* close window; may free buffer */
@@ -6345,7 +6363,7 @@ static void ex_tabnext(exarg_T *eap)
*/
static void ex_tabmove(exarg_T *eap)
{
- int tab_number = 9999;
+ int tab_number;
if (eap->arg && *eap->arg != NUL) {
char_u *p = eap->arg;
@@ -6361,17 +6379,35 @@ static void ex_tabmove(exarg_T *eap)
} else
p = eap->arg;
- if (p == skipdigits(p)) {
- /* No numbers as argument. */
- eap->errmsg = e_invarg;
- return;
+ if (relative == 0) {
+ if (STRCMP(p, "$") == 0) {
+ tab_number = LAST_TAB_NR;
+ } else if (p == skipdigits(p)) {
+ // No numbers as argument.
+ eap->errmsg = e_invarg;
+ return;
+ } else {
+ tab_number = getdigits(&p);
+ }
+ } else {
+ if (*p != NUL) {
+ tab_number = getdigits(&p);
+ } else {
+ tab_number = 1;
+ }
+ tab_number = tab_number * relative + tabpage_index(curtab);
+ if (relative == -1) {
+ --tab_number;
+ }
}
-
- tab_number = getdigits_int(&p);
- if (relative != 0)
- tab_number = tab_number * relative + tabpage_index(curtab) - 1; ;
- } else if (eap->addr_count != 0)
+ } else if (eap->addr_count != 0) {
tab_number = eap->line2;
+ if (**eap->cmdlinep == '-') {
+ --tab_number;
+ }
+ } else {
+ tab_number = LAST_TAB_NR;
+ }
tabpage_move(tab_number);
}
@@ -8257,16 +8293,22 @@ static char_u *arg_all(void)
retval[len] = ' ';
++len;
}
- for (; *p != NUL; ++p) {
- if (*p == ' ' || *p == '\\') {
- /* insert a backslash */
- if (retval != NULL)
+ for (; *p != NUL; p++) {
+ if (*p == ' '
+#ifndef BACKSLASH_IN_FILENAME
+ || *p == '\\'
+#endif
+ ) {
+ // insert a backslash
+ if (retval != NULL) {
retval[len] = '\\';
- ++len;
+ }
+ len++;
}
- if (retval != NULL)
+ if (retval != NULL) {
retval[len] = *p;
- ++len;
+ }
+ len++;
}
}
@@ -8345,8 +8387,7 @@ makeopens (
{
int only_save_windows = TRUE;
int nr;
- int cnr = 1;
- int restore_size = TRUE;
+ int restore_size = true;
win_T *wp;
char_u *sname;
win_T *edited_win = NULL;
@@ -8463,7 +8504,8 @@ makeopens (
tab_firstwin = firstwin; /* first window in tab page "tabnr" */
tab_topframe = topframe;
for (tabnr = 1;; ++tabnr) {
- int need_tabnew = FALSE;
+ int need_tabnew = false;
+ int cnr = 1;
if ((ssop_flags & SSOP_TABPAGES)) {
tabpage_T *tp = find_tabpage(tabnr);
@@ -8742,19 +8784,18 @@ static int ses_do_frame(frame_T *fr)
return FALSE;
}
-/*
- * Return non-zero if window "wp" is to be stored in the Session.
- */
+/// Return non-zero if window "wp" is to be stored in the Session.
static int ses_do_win(win_T *wp)
{
if (wp->w_buffer->b_fname == NULL
- /* When 'buftype' is "nofile" can't restore the window contents. */
- || bt_nofile(wp->w_buffer)
- )
+ // When 'buftype' is "nofile" can't restore the window contents.
+ || (!wp->w_buffer->terminal && bt_nofile(wp->w_buffer))) {
return ssop_flags & SSOP_BLANK;
- if (wp->w_buffer->b_help)
+ }
+ if (wp->w_buffer->b_help) {
return ssop_flags & SSOP_HELP;
- return TRUE;
+ }
+ return true;
}
/*
@@ -9190,9 +9231,9 @@ char_u *get_behave_arg(expand_T *xp, int idx)
return NULL;
}
-static int filetype_detect = FALSE;
-static int filetype_plugin = FALSE;
-static int filetype_indent = FALSE;
+static TriState filetype_detect = kNone;
+static TriState filetype_plugin = kNone;
+static TriState filetype_indent = kNone;
/*
* ":filetype [plugin] [indent] {on,off,detect}"
@@ -9206,27 +9247,27 @@ static int filetype_indent = FALSE;
static void ex_filetype(exarg_T *eap)
{
char_u *arg = eap->arg;
- int plugin = FALSE;
- int indent = FALSE;
+ bool plugin = false;
+ bool indent = false;
if (*eap->arg == NUL) {
/* Print current status. */
smsg("filetype detection:%s plugin:%s indent:%s",
- filetype_detect ? "ON" : "OFF",
- filetype_plugin ? (filetype_detect ? "ON" : "(on)") : "OFF",
- filetype_indent ? (filetype_detect ? "ON" : "(on)") : "OFF");
+ filetype_detect == kTrue ? "ON" : "OFF",
+ filetype_plugin == kTrue ? (filetype_detect == kTrue ? "ON" : "(on)") : "OFF", // NOLINT(whitespace/line_length)
+ filetype_indent == kTrue ? (filetype_detect == kTrue ? "ON" : "(on)") : "OFF"); // NOLINT(whitespace/line_length)
return;
}
/* Accept "plugin" and "indent" in any order. */
for (;; ) {
if (STRNCMP(arg, "plugin", 6) == 0) {
- plugin = TRUE;
+ plugin = true;
arg = skipwhite(arg + 6);
continue;
}
if (STRNCMP(arg, "indent", 6) == 0) {
- indent = TRUE;
+ indent = true;
arg = skipwhite(arg + 6);
continue;
}
@@ -9234,15 +9275,15 @@ static void ex_filetype(exarg_T *eap)
}
if (STRCMP(arg, "on") == 0 || STRCMP(arg, "detect") == 0) {
if (*arg == 'o' || !filetype_detect) {
- source_runtime((char_u *)FILETYPE_FILE, TRUE);
- filetype_detect = TRUE;
+ source_runtime((char_u *)FILETYPE_FILE, true);
+ filetype_detect = kTrue;
if (plugin) {
- source_runtime((char_u *)FTPLUGIN_FILE, TRUE);
- filetype_plugin = TRUE;
+ source_runtime((char_u *)FTPLUGIN_FILE, true);
+ filetype_plugin = kTrue;
}
if (indent) {
- source_runtime((char_u *)INDENT_FILE, TRUE);
- filetype_indent = TRUE;
+ source_runtime((char_u *)INDENT_FILE, true);
+ filetype_indent = kTrue;
}
}
if (*arg == 'd') {
@@ -9252,21 +9293,37 @@ static void ex_filetype(exarg_T *eap)
} else if (STRCMP(arg, "off") == 0) {
if (plugin || indent) {
if (plugin) {
- source_runtime((char_u *)FTPLUGOF_FILE, TRUE);
- filetype_plugin = FALSE;
+ source_runtime((char_u *)FTPLUGOF_FILE, true);
+ filetype_plugin = kFalse;
}
if (indent) {
- source_runtime((char_u *)INDOFF_FILE, TRUE);
- filetype_indent = FALSE;
+ source_runtime((char_u *)INDOFF_FILE, true);
+ filetype_indent = kFalse;
}
} else {
- source_runtime((char_u *)FTOFF_FILE, TRUE);
- filetype_detect = FALSE;
+ source_runtime((char_u *)FTOFF_FILE, true);
+ filetype_detect = kFalse;
}
} else
EMSG2(_(e_invarg2), arg);
}
+/// Do ":filetype plugin indent on" if user did not already do some
+/// permutation thereof.
+void filetype_maybe_enable(void)
+{
+ if (filetype_detect == kNone
+ && filetype_plugin == kNone
+ && filetype_indent == kNone) {
+ source_runtime((char_u *)FILETYPE_FILE, true);
+ filetype_detect = kTrue;
+ source_runtime((char_u *)FTPLUGIN_FILE, true);
+ filetype_plugin = kTrue;
+ source_runtime((char_u *)INDENT_FILE, true);
+ filetype_indent = kTrue;
+ }
+}
+
/*
* ":setfiletype {name}"
*/
@@ -9304,59 +9361,62 @@ static void ex_nohlsearch(exarg_T *eap)
redraw_all_later(SOME_VALID);
}
-/*
- * ":[N]match {group} {pattern}"
- * Sets nextcmd to the start of the next command, if any. Also called when
- * skipping commands to find the next command.
- */
+// ":[N]match {group} {pattern}"
+// Sets nextcmd to the start of the next command, if any. Also called when
+// skipping commands to find the next command.
static void ex_match(exarg_T *eap)
{
- char_u *p;
- char_u *g = NULL;
- char_u *end;
+ char_u *p;
+ char_u *g = NULL;
+ char_u *end;
int c;
int id;
- if (eap->line2 <= 3)
+ if (eap->line2 <= 3) {
id = eap->line2;
- else {
+ } else {
EMSG(e_invcmd);
return;
}
- /* First clear any old pattern. */
- if (!eap->skip)
- match_delete(curwin, id, FALSE);
+ // First clear any old pattern.
+ if (!eap->skip) {
+ match_delete(curwin, id, false);
+ }
- if (ends_excmd(*eap->arg))
+ if (ends_excmd(*eap->arg)) {
end = eap->arg;
- else if ((STRNICMP(eap->arg, "none", 4) == 0
- && (ascii_iswhite(eap->arg[4]) || ends_excmd(eap->arg[4]))))
+ } else if ((STRNICMP(eap->arg, "none", 4) == 0
+ && (ascii_iswhite(eap->arg[4]) || ends_excmd(eap->arg[4])))) {
end = eap->arg + 4;
- else {
+ } else {
p = skiptowhite(eap->arg);
- if (!eap->skip)
+ if (!eap->skip) {
g = vim_strnsave(eap->arg, (int)(p - eap->arg));
+ }
p = skipwhite(p);
if (*p == NUL) {
- /* There must be two arguments. */
+ // There must be two arguments.
+ xfree(g);
EMSG2(_(e_invarg2), eap->arg);
return;
}
- end = skip_regexp(p + 1, *p, TRUE, NULL);
+ end = skip_regexp(p + 1, *p, true, NULL);
if (!eap->skip) {
if (*end != NUL && !ends_excmd(*skipwhite(end + 1))) {
+ xfree(g);
eap->errmsg = e_trailing;
return;
}
if (*end != *p) {
+ xfree(g);
EMSG2(_(e_invarg2), p);
return;
}
c = *end;
*end = NUL;
- match_add(curwin, g, p + 1, 10, id, NULL);
+ match_add(curwin, g, p + 1, 10, id, NULL, NULL);
xfree(g);
*end = c;
}
diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c
index 87a6bf8901..39bff9b2ad 100644
--- a/src/nvim/ex_getln.c
+++ b/src/nvim/ex_getln.c
@@ -2957,20 +2957,37 @@ ExpandOne (
}
}
- /* Find longest common part */
+ // Find longest common part
if (mode == WILD_LONGEST && xp->xp_numfiles > 0) {
size_t len;
- for (len = 0; xp->xp_files[0][len]; ++len) {
- for (i = 0; i < xp->xp_numfiles; ++i) {
+ size_t mb_len = 1;
+ int c0;
+ int ci;
+
+ for (len = 0; xp->xp_files[0][len]; len += mb_len) {
+ if (has_mbyte) {
+ mb_len = (* mb_ptr2len)(&xp->xp_files[0][len]);
+ c0 = (* mb_ptr2char)(&xp->xp_files[0][len]);
+ } else {
+ c0 = xp->xp_files[0][len];
+ }
+ for (i = 1; i < xp->xp_numfiles; ++i) {
+ if (has_mbyte) {
+ ci =(* mb_ptr2char)(&xp->xp_files[i][len]);
+ } else {
+ ci = xp->xp_files[i][len];
+ }
+
if (p_fic && (xp->xp_context == EXPAND_DIRECTORIES
|| xp->xp_context == EXPAND_FILES
|| xp->xp_context == EXPAND_SHELLCMD
|| xp->xp_context == EXPAND_BUFFERS)) {
- if (TOLOWER_LOC(xp->xp_files[i][len]) !=
- TOLOWER_LOC(xp->xp_files[0][len]))
+ if (vim_tolower(c0) != vim_tolower(ci)) {
break;
- } else if (xp->xp_files[i][len] != xp->xp_files[0][len])
+ }
+ } else if (c0 != ci) {
break;
+ }
}
if (i < xp->xp_numfiles) {
if (!(options & WILD_NO_BEEP)) {
@@ -2979,8 +2996,9 @@ ExpandOne (
break;
}
}
+
ss = (char_u *)xstrndup((char *)xp->xp_files[0], len);
- findex = -1; /* next p_wc gets first one */
+ findex = -1; // next p_wc gets first one
}
// Concatenate all matching names
@@ -3701,6 +3719,9 @@ ExpandFromContext (
flags |= EW_KEEPALL;
if (options & WILD_SILENT)
flags |= EW_SILENT;
+ if (options & WILD_ALLLINKS) {
+ flags |= EW_ALLLINKS;
+ }
if (xp->xp_context == EXPAND_FILES
|| xp->xp_context == EXPAND_DIRECTORIES
@@ -4783,7 +4804,7 @@ int get_list_range(char_u **str, int *num1, int *num2)
*str = skipwhite(*str);
if (**str == '-' || ascii_isdigit(**str)) { // parse "from" part of range
- vim_str2nr(*str, NULL, &len, false, false, false, &num, NULL);
+ vim_str2nr(*str, NULL, &len, 0, &num, NULL, 0);
*str += len;
*num1 = (int)num;
first = true;
@@ -4791,7 +4812,7 @@ int get_list_range(char_u **str, int *num1, int *num2)
*str = skipwhite(*str);
if (**str == ',') { // parse "to" part of range
*str = skipwhite(*str + 1);
- vim_str2nr(*str, NULL, &len, false, false, false, &num, NULL);
+ vim_str2nr(*str, NULL, &len, 0, &num, NULL, 0);
if (len > 0) {
*num2 = (int)num;
*str = skipwhite(*str + len);
@@ -5133,6 +5154,8 @@ static int ex_window(void)
/* Don't execute autocommands while deleting the window. */
block_autocmds();
+ // Avoid command-line window first character being concealed
+ curwin->w_p_cole = 0;
wp = curwin;
bp = curbuf;
win_goto(old_curwin);
diff --git a/src/nvim/ex_getln.h b/src/nvim/ex_getln.h
index c537d681c6..21da8b9d42 100644
--- a/src/nvim/ex_getln.h
+++ b/src/nvim/ex_getln.h
@@ -14,15 +14,16 @@
#define WILD_LONGEST 7
#define WILD_ALL_KEEP 8
-#define WILD_LIST_NOTFOUND 1
-#define WILD_HOME_REPLACE 2
-#define WILD_USE_NL 4
-#define WILD_NO_BEEP 8
-#define WILD_ADD_SLASH 16
-#define WILD_KEEP_ALL 32
-#define WILD_SILENT 64
-#define WILD_ESCAPE 128
-#define WILD_ICASE 256
+#define WILD_LIST_NOTFOUND 0x01
+#define WILD_HOME_REPLACE 0x02
+#define WILD_USE_NL 0x04
+#define WILD_NO_BEEP 0x08
+#define WILD_ADD_SLASH 0x10
+#define WILD_KEEP_ALL 0x20
+#define WILD_SILENT 0x40
+#define WILD_ESCAPE 0x80
+#define WILD_ICASE 0x100
+#define WILD_ALLLINKS 0x200
/// Present history tables
typedef enum {
diff --git a/src/nvim/file_search.c b/src/nvim/file_search.c
index 4f345158cf..2929790ebf 100644
--- a/src/nvim/file_search.c
+++ b/src/nvim/file_search.c
@@ -484,28 +484,21 @@ vim_findfile_init (
len = (int)(p - search_ctx->ffsc_fix_path) - 1;
STRNCAT(ff_expand_buffer, search_ctx->ffsc_fix_path, len);
add_pathsep((char *)ff_expand_buffer);
- } else
+ } else {
len = (int)STRLEN(search_ctx->ffsc_fix_path);
+ }
if (search_ctx->ffsc_wc_path != NULL) {
wc_path = vim_strsave(search_ctx->ffsc_wc_path);
temp = xmalloc(STRLEN(search_ctx->ffsc_wc_path)
+ STRLEN(search_ctx->ffsc_fix_path + len)
+ 1);
- }
-
- if (temp == NULL || wc_path == NULL) {
- xfree(buf);
- xfree(temp);
+ STRCPY(temp, search_ctx->ffsc_fix_path + len);
+ STRCAT(temp, search_ctx->ffsc_wc_path);
+ xfree(search_ctx->ffsc_wc_path);
xfree(wc_path);
- goto error_return;
+ search_ctx->ffsc_wc_path = temp;
}
-
- STRCPY(temp, search_ctx->ffsc_fix_path + len);
- STRCAT(temp, search_ctx->ffsc_wc_path);
- xfree(search_ctx->ffsc_wc_path);
- xfree(wc_path);
- search_ctx->ffsc_wc_path = temp;
}
xfree(buf);
}
@@ -1046,41 +1039,44 @@ static ff_visited_list_hdr_T *ff_get_visited_list(char_u *filename, ff_visited_l
return retptr;
}
-/*
- * check if two wildcard paths are equal. Returns TRUE or FALSE.
- * They are equal if:
- * - both paths are NULL
- * - they have the same length
- * - char by char comparison is OK
- * - the only differences are in the counters behind a '**', so
- * '**\20' is equal to '**\24'
- */
-static int ff_wc_equal(char_u *s1, char_u *s2)
+// Check if two wildcard paths are equal.
+// They are equal if:
+// - both paths are NULL
+// - they have the same length
+// - char by char comparison is OK
+// - the only differences are in the counters behind a '**', so
+// '**\20' is equal to '**\24'
+static bool ff_wc_equal(char_u *s1, char_u *s2)
{
- int i;
+ int i, j;
+ int c1 = NUL;
+ int c2 = NUL;
int prev1 = NUL;
int prev2 = NUL;
- if (s1 == s2)
- return TRUE;
-
- if (s1 == NULL || s2 == NULL)
- return FALSE;
+ if (s1 == s2) {
+ return true;
+ }
- if (STRLEN(s1) != STRLEN(s2))
- return FAIL;
+ if (s1 == NULL || s2 == NULL) {
+ return false;
+ }
- for (i = 0; s1[i] != NUL && s2[i] != NUL; i += MB_PTR2LEN(s1 + i)) {
- int c1 = PTR2CHAR(s1 + i);
- int c2 = PTR2CHAR(s2 + i);
+ for (i = 0, j = 0; s1[i] != NUL && s2[j] != NUL;) {
+ c1 = PTR2CHAR(s1 + i);
+ c2 = PTR2CHAR(s2 + j);
if ((p_fic ? vim_tolower(c1) != vim_tolower(c2) : c1 != c2)
- && (prev1 != '*' || prev2 != '*'))
- return FAIL;
+ && (prev1 != '*' || prev2 != '*')) {
+ return false;
+ }
prev2 = prev1;
prev1 = c1;
+
+ i += MB_PTR2LEN(s1 + i);
+ j += MB_PTR2LEN(s2 + j);
}
- return TRUE;
+ return s1[i] == s2[j];
}
/*
@@ -1111,10 +1107,11 @@ static int ff_check_visited(ff_visited_T **visited_list, char_u *fname, char_u *
if ((url && fnamecmp(vp->ffv_fname, ff_expand_buffer) == 0)
|| (!url && vp->file_id_valid
&& os_fileid_equal(&(vp->file_id), &file_id))) {
- /* are the wildcard parts equal */
- if (ff_wc_equal(vp->ffv_wc_path, wc_path) == TRUE)
- /* already visited */
+ // are the wildcard parts equal
+ if (ff_wc_equal(vp->ffv_wc_path, wc_path)) {
+ // already visited
return FAIL;
+ }
}
}
@@ -1340,6 +1337,7 @@ void free_findfile(void)
*
* options:
* FNAME_MESS give error message when not found
+ * FNAME_UNESC unescape backslashes
*
* Uses NameBuff[]!
*
@@ -1385,6 +1383,14 @@ find_file_in_path_option (
xfree(ff_file_to_find);
ff_file_to_find = vim_strsave(NameBuff);
+ if (options & FNAME_UNESC) {
+ // Change all "\ " to " ".
+ for (ptr = ff_file_to_find; *ptr != NUL; ++ptr) {
+ if (ptr[0] == '\\' && ptr[1] == ' ') {
+ memmove(ptr, ptr + 1, STRLEN(ptr));
+ }
+ }
+ }
}
rel_to_curdir = (ff_file_to_find[0] == '.'
diff --git a/src/nvim/fileio.c b/src/nvim/fileio.c
index 26376afa27..383cd47dbe 100644
--- a/src/nvim/fileio.c
+++ b/src/nvim/fileio.c
@@ -1543,12 +1543,12 @@ rewind_retry:
if (fileformat == EOL_UNKNOWN) {
/* First try finding a NL, for Dos and Unix */
if (try_dos || try_unix) {
- for (p = ptr; p < ptr + size; ++p) {
- // Reset the carriage return counter.
- if (try_mac) {
- try_mac = 1;
- }
+ // Reset the carriage return counter.
+ if (try_mac) {
+ try_mac = 1;
+ }
+ for (p = ptr; p < ptr + size; ++p) {
if (*p == NL) {
if (!try_unix
|| (try_dos && p > ptr && p[-1] == CAR))
@@ -6305,7 +6305,7 @@ bool has_event(int event) FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT
/// @param force When true, ignore autocmd_busy
/// @param group autocmd group ID or AUGROUP_ALL
/// @param buf Buffer for <abuf>
-/// @param exarg Ex command arguments
+/// @param eap Ex command arguments
///
/// @return true if some commands were executed.
static bool apply_autocmds_group(event_T event, char_u *fname, char_u *fname_io,
@@ -7106,6 +7106,7 @@ char_u * file_pat_to_reg_pat(
char *allow_dirs, // Result passed back out in here
int no_bslash // Don't use a backward slash as pathsep
)
+ FUNC_ATTR_NONNULL_ARG(1)
{
const char_u *endp;
char_u *reg_pat;
@@ -7118,6 +7119,10 @@ char_u * file_pat_to_reg_pat(
if (pat_end == NULL)
pat_end = pat + STRLEN(pat);
+ if (pat_end == pat) {
+ return (char_u *)xstrdup("^$");
+ }
+
size_t size = 2; // '^' at start, '$' at end.
for (p = pat; p < pat_end; p++) {
@@ -7155,10 +7160,11 @@ char_u * file_pat_to_reg_pat(
else
reg_pat[i++] = '^';
endp = pat_end - 1;
- if (*endp == '*') {
- while (endp - pat > 0 && *endp == '*')
+ if (endp >= pat && *endp == '*') {
+ while (endp - pat > 0 && *endp == '*') {
endp--;
- add_dollar = FALSE;
+ }
+ add_dollar = false;
}
for (p = pat; *p && nested >= 0 && p <= endp; p++) {
switch (*p) {
@@ -7213,12 +7219,12 @@ char_u * file_pat_to_reg_pat(
#ifdef BACKSLASH_IN_FILENAME
&& no_bslash
#endif
- )
+ ) {
reg_pat[i++] = '?';
- else if (*p == ',' || *p == '%' || *p == '#'
- || *p == ' ' || *p == '{' || *p == '}')
+ } else if (*p == ',' || *p == '%' || *p == '#'
+ || ascii_isspace(*p) || *p == '{' || *p == '}') {
reg_pat[i++] = *p;
- else if (*p == '\\' && p[1] == '\\' && p[2] == '{') {
+ } else if (*p == '\\' && p[1] == '\\' && p[2] == '{') {
reg_pat[i++] = '\\';
reg_pat[i++] = '{';
p += 2;
diff --git a/src/nvim/fold.c b/src/nvim/fold.c
index 2e32e78062..6c135ef47b 100644
--- a/src/nvim/fold.c
+++ b/src/nvim/fold.c
@@ -767,9 +767,9 @@ void foldUpdate(win_T *wp, linenr_T top, linenr_T bot)
return;
}
- /* Mark all folds from top to bot as maybe-small. */
- (void)foldFind(&curwin->w_folds, top, &fp);
- while (fp < (fold_T *)curwin->w_folds.ga_data + curwin->w_folds.ga_len
+ // Mark all folds from top to bot as maybe-small.
+ (void)foldFind(&wp->w_folds, top, &fp);
+ while (fp < (fold_T *)wp->w_folds.ga_data + wp->w_folds.ga_len
&& fp->fd_top < bot) {
fp->fd_small = MAYBE;
++fp;
diff --git a/src/nvim/getchar.c b/src/nvim/getchar.c
index 89d22ad811..73b3de0b5d 100644
--- a/src/nvim/getchar.c
+++ b/src/nvim/getchar.c
@@ -1380,13 +1380,15 @@ int vgetc(void)
} else {
mod_mask = 0x0;
last_recorded_len = 0;
- for (;; ) { /* this is done twice if there are modifiers */
- if (mod_mask) { /* no mapping after modifier has been read */
+ for (;; ) { // this is done twice if there are modifiers
+ bool did_inc = false;
+ if (mod_mask) { // no mapping after modifier has been read
++no_mapping;
++allow_keys;
+ did_inc = true; // mod_mask may change value
}
- c = vgetorpeek(TRUE);
- if (mod_mask) {
+ c = vgetorpeek(true);
+ if (did_inc) {
--no_mapping;
--allow_keys;
}
diff --git a/src/nvim/globals.h b/src/nvim/globals.h
index b45f13de4c..69e65c3208 100644
--- a/src/nvim/globals.h
+++ b/src/nvim/globals.h
@@ -100,6 +100,12 @@
# define VIMRC_FILE ".nvimrc"
#endif
+typedef enum {
+ kNone = -1,
+ kFalse = 0,
+ kTrue = 1,
+} TriState;
+
/* Values for "starting" */
#define NO_SCREEN 2 /* no screen updating yet */
#define NO_BUFFERS 1 /* not all buffers loaded yet */
@@ -159,15 +165,6 @@ EXTERN int Screen_mco INIT(= 0); /* value of p_mco used when
* These are single-width. */
EXTERN schar_T *ScreenLines2 INIT(= NULL);
-/*
- * Indexes for tab page line:
- * N > 0 for label of tab page N
- * N == 0 for no label
- * N < 0 for closing tab page -N
- * N == -999 for closing current tab page
- */
-EXTERN short *TabPageIdxs INIT(= NULL);
-
EXTERN int screen_Rows INIT(= 0); /* actual size of ScreenLines[] */
EXTERN int screen_Columns INIT(= 0); /* actual size of ScreenLines[] */
diff --git a/src/nvim/indent_c.c b/src/nvim/indent_c.c
index 340287499e..17fadc4bfd 100644
--- a/src/nvim/indent_c.c
+++ b/src/nvim/indent_c.c
@@ -69,23 +69,33 @@ find_start_comment ( /* XXX */
return pos;
}
-/*
- * Find the start of a comment or raw string, not knowing if we are in a
- * comment or raw string right now.
- * Search starts at w_cursor.lnum and goes backwards.
- * Return NULL when not inside a comment or raw string.
- * "CORS" -> Comment Or Raw String
- */
+/// Find the start of a comment or raw string, not knowing if we are in a
+/// comment or raw string right now.
+/// Search starts at w_cursor.lnum and goes backwards.
+///
+/// @returns NULL when not inside a comment or raw string.
+///
+/// @note "CORS" -> Comment Or Raw String
static pos_T *ind_find_start_CORS(void)
-{ /* XXX */
- pos_T *comment_pos = find_start_comment(curbuf->b_ind_maxcomment);
- pos_T *rs_pos = find_start_rawstring(curbuf->b_ind_maxcomment);
-
- /* If comment_pos is before rs_pos the raw string is inside the comment.
- * If rs_pos is before comment_pos the comment is inside the raw string. */
- if (comment_pos == NULL || (rs_pos != NULL && lt(*rs_pos, *comment_pos)))
- return rs_pos;
- return comment_pos;
+{
+ // XXX
+ static pos_T comment_pos_copy;
+
+ pos_T *comment_pos = find_start_comment(curbuf->b_ind_maxcomment);
+ if (comment_pos != NULL) {
+ // Need to make a copy of the static pos in findmatchlimit(),
+ // calling find_start_rawstring() may change it.
+ comment_pos_copy = *comment_pos;
+ comment_pos = &comment_pos_copy;
+ }
+ pos_T *rs_pos = find_start_rawstring(curbuf->b_ind_maxcomment);
+
+ // If comment_pos is before rs_pos the raw string is inside the comment.
+ // If rs_pos is before comment_pos the comment is inside the raw string.
+ if (comment_pos == NULL || (rs_pos != NULL && lt(*rs_pos, *comment_pos))) {
+ return rs_pos;
+ }
+ return comment_pos;
}
/*
@@ -847,13 +857,27 @@ static int cin_isfuncdecl(char_u **sp, linenr_T first_lnum, linenr_T min_lnum)
return FALSE;
while (*s && *s != '(' && *s != ';' && *s != '\'' && *s != '"') {
- if (cin_iscomment(s)) /* ignore comments */
+ // ignore comments
+ if (cin_iscomment(s)) {
s = cin_skipcomment(s);
- else
- ++s;
+ } else if (*s == ':') {
+ if (*(s + 1) == ':') {
+ s += 2;
+ } else {
+ // To avoid a mistake in the following situation:
+ // A::A(int a, int b)
+ // : a(0) // <--not a function decl
+ // , b(0)
+ // {...
+ return false;
+ }
+ } else {
+ s++;
+ }
+ }
+ if (*s != '(') {
+ return false; // ';', ' or " before any () or no '('
}
- if (*s != '(')
- return FALSE; /* ';', ' or " before any () or no '(' */
while (*s && *s != ';' && *s != '\'' && *s != '"') {
if (*s == ')' && cin_nocode(s + 1)) {
@@ -1122,13 +1146,21 @@ static int cin_is_cpp_baseclass(cpp_baseclass_cache_T *cached) {
pos->lnum = lnum;
line = ml_get(lnum);
- s = cin_skipcomment(line);
+ s = line;
for (;; ) {
if (*s == NUL) {
- if (lnum == curwin->w_cursor.lnum)
+ if (lnum == curwin->w_cursor.lnum) {
break;
- /* Continue in the cursor line. */
+ }
+ // Continue in the cursor line.
line = ml_get(++lnum);
+ s = line;
+ }
+ if (s == line) {
+ // don't recognize "case (foo):" as a baseclass */
+ if (cin_iscase(s, false)) {
+ break;
+ }
s = cin_skipcomment(line);
if (*s == NUL)
continue;
@@ -2707,7 +2739,8 @@ int get_c_indent(void)
if (terminated == 0 || (lookfor != LOOKFOR_UNTERM
&& terminated == ',')) {
- if (*skipwhite(l) == '[' || l[STRLEN(l) - 1] == '[') {
+ if (lookfor != LOOKFOR_ENUM_OR_INIT
+ && (*skipwhite(l) == '[' || l[STRLEN(l) - 1] == '[')) {
amount += ind_continuation;
}
// If we're in the middle of a paren thing, Go back to the line
@@ -2915,34 +2948,35 @@ int get_c_indent(void)
continue;
}
- /* Ignore unterminated lines in between, but
- * reduce indent. */
- if (amount > cur_amount)
+ // Ignore unterminated lines in between, but
+ // reduce indent.
+ if (amount > cur_amount) {
amount = cur_amount;
+ }
} else {
- /*
- * Found first unterminated line on a row, may
- * line up with this line, remember its indent
- * 100 +
- * -> here;
- */
+ // Found first unterminated line on a row, may
+ // line up with this line, remember its indent
+ // 100 + // NOLINT(whitespace/tab)
+ // -> here; // NOLINT(whitespace/tab)
l = get_cursor_line_ptr();
amount = cur_amount;
- if (*skipwhite(l) == ']' || l[STRLEN(l) - 1] == ']') {
+
+ n = (int)STRLEN(l);
+ if (terminated == ','
+ && (*skipwhite(l) == ']'
+ || (n >=2 && l[n - 2] == ']'))) {
break;
}
- /*
- * If previous line ends in ',', check whether we
- * are in an initialization or enum
- * struct xxx =
- * {
- * sizeof a,
- * 124 };
- * or a normal possible continuation line.
- * but only, of no other statement has been found
- * yet.
- */
+ // If previous line ends in ',', check whether we
+ // are in an initialization or enum
+ // struct xxx =
+ // {
+ // sizeof a,
+ // 124 };
+ // or a normal possible continuation line.
+ // but only, of no other statement has been found
+ // yet.
if (lookfor == LOOKFOR_INITIAL && terminated == ',') {
if (curbuf->b_ind_js) {
// Search for a line ending in a comma
diff --git a/src/nvim/keymap.c b/src/nvim/keymap.c
index 7054bb822a..6c75d8bdf4 100644
--- a/src/nvim/keymap.c
+++ b/src/nvim/keymap.c
@@ -1,8 +1,3 @@
-/*
- * functions that use lookup tables for various things, generally to do with
- * special key codes.
- */
-
#include <assert.h>
#include <inttypes.h>
#include <limits.h>
@@ -39,7 +34,8 @@ static struct modmasktable {
{MOD_MASK_MULTI_CLICK, MOD_MASK_2CLICK, (char_u)'2'},
{MOD_MASK_MULTI_CLICK, MOD_MASK_3CLICK, (char_u)'3'},
{MOD_MASK_MULTI_CLICK, MOD_MASK_4CLICK, (char_u)'4'},
- /* 'A' must be the last one */
+ {MOD_MASK_CMD, MOD_MASK_CMD, (char_u)'D'},
+ // 'A' must be the last one
{MOD_MASK_ALT, MOD_MASK_ALT, (char_u)'A'},
{0, 0, NUL}
};
@@ -574,7 +570,7 @@ int find_special_key(
if (bp[0] == 't' && bp[1] == '_' && bp[2] && bp[3]) {
bp += 3; // skip t_xx, xx may be '-' or '>'
} else if (STRNICMP(bp, "char-", 5) == 0) {
- vim_str2nr(bp + 5, NULL, &l, true, true, true, NULL, NULL);
+ vim_str2nr(bp + 5, NULL, &l, STR2NR_ALL, NULL, NULL, 0);
bp += l + 5;
break;
}
@@ -600,7 +596,7 @@ int find_special_key(
if (STRNICMP(last_dash + 1, "char-", 5) == 0
&& ascii_isdigit(last_dash[6])) {
// <Char-123> or <Char-033> or <Char-0x33>
- vim_str2nr(last_dash + 6, NULL, NULL, true, true, true, NULL, &n);
+ vim_str2nr(last_dash + 6, NULL, NULL, STR2NR_ALL, NULL, &n, 0);
key = (int)n;
} else {
/*
@@ -658,9 +654,11 @@ static int extract_modifiers(int key, int *modp)
{
int modifiers = *modp;
- if ((modifiers & MOD_MASK_SHIFT) && ASCII_ISALPHA(key)) {
- key = TOUPPER_ASC(key);
- modifiers &= ~MOD_MASK_SHIFT;
+ if (!(modifiers & MOD_MASK_CMD)) { // Command-key is special
+ if ((modifiers & MOD_MASK_SHIFT) && ASCII_ISALPHA(key)) {
+ key = TOUPPER_ASC(key);
+ modifiers &= ~MOD_MASK_SHIFT;
+ }
}
if ((modifiers & MOD_MASK_CTRL)
&& ((key >= '?' && key <= '_') || ASCII_ISALPHA(key))) {
diff --git a/src/nvim/keymap.h b/src/nvim/keymap.h
index 766362d145..8f9980c6b4 100644
--- a/src/nvim/keymap.h
+++ b/src/nvim/keymap.h
@@ -112,11 +112,11 @@
#define TO_SPECIAL(a, b) ((a) == KS_SPECIAL ? K_SPECIAL : (a) == \
KS_ZERO ? K_ZERO : TERMCAP2KEY(a, b))
-/*
- * Codes for keys that do not have a termcap name.
- *
- * K_SPECIAL KS_EXTRA KE_xxx
- */
+// Codes for keys that do not have a termcap name.
+//
+// K_SPECIAL KS_EXTRA KE_xxx
+//
+// Entries must be in the range 0x02-0x7f (see comment at K_SPECIAL).
enum key_extra {
KE_NAME = 3 /* name of this terminal entry */
@@ -436,11 +436,12 @@ enum key_extra {
/* 0x01 cannot be used, because the modifier must be 0x02 or higher */
#define MOD_MASK_SHIFT 0x02
#define MOD_MASK_CTRL 0x04
-#define MOD_MASK_ALT 0x08 /* aka META */
-#define MOD_MASK_META 0x10 /* META when it's different from ALT */
-#define MOD_MASK_2CLICK 0x20 /* use MOD_MASK_MULTI_CLICK */
-#define MOD_MASK_3CLICK 0x40 /* use MOD_MASK_MULTI_CLICK */
-#define MOD_MASK_4CLICK 0x60 /* use MOD_MASK_MULTI_CLICK */
+#define MOD_MASK_ALT 0x08 // aka META
+#define MOD_MASK_META 0x10 // META when it's different from ALT
+#define MOD_MASK_2CLICK 0x20 // use MOD_MASK_MULTI_CLICK
+#define MOD_MASK_3CLICK 0x40 // use MOD_MASK_MULTI_CLICK
+#define MOD_MASK_4CLICK 0x60 // use MOD_MASK_MULTI_CLICK
+#define MOD_MASK_CMD 0x80 // "super" key (OSX/Mac: command-key)
#define MOD_MASK_MULTI_CLICK (MOD_MASK_2CLICK|MOD_MASK_3CLICK| \
MOD_MASK_4CLICK)
@@ -451,14 +452,13 @@ enum key_extra {
*/
#define MAX_KEY_NAME_LEN 25
-/* Maximum length of a special key event as tokens. This includes modifiers.
- * The longest event is something like <M-C-S-T-4-LeftDrag> which would be the
- * following string of tokens:
- *
- * <K_SPECIAL> <KS_MODIFIER> bitmask <K_SPECIAL> <KS_EXTRA> <KT_LEFTDRAG>.
- *
- * This is a total of 6 tokens, and is currently the longest one possible.
- */
+// Maximum length of a special key event as tokens. This includes modifiers.
+// The longest event is something like <M-C-S-T-4-LeftDrag> which would be the
+// following string of tokens:
+//
+// <K_SPECIAL> <KS_MODIFIER> bitmask <K_SPECIAL> <KS_EXTRA> <KE_LEFTDRAG>.
+//
+// This is a total of 6 tokens, and is currently the longest one possible.
#define MAX_KEY_CODE_LEN 6
diff --git a/src/nvim/log.c b/src/nvim/log.c
index 5767da03af..773d497881 100644
--- a/src/nvim/log.c
+++ b/src/nvim/log.c
@@ -10,10 +10,6 @@
#include "nvim/os/os.h"
#include "nvim/os/time.h"
-#ifdef HAVE_UNISTD_H
-# include <unistd.h>
-#endif
-
#define USR_LOG_FILE "$HOME" _PATHSEPSTR ".nvimlog"
static uv_mutex_t mutex;
diff --git a/src/nvim/main.c b/src/nvim/main.c
index cef10d12d5..d3cdfe3edf 100644
--- a/src/nvim/main.c
+++ b/src/nvim/main.c
@@ -219,9 +219,10 @@ int main(int argc, char **argv)
{
argv0 = (char *)path_tail((char_u *)argv[0]);
- char_u *fname = NULL; /* file name from command line */
- mparm_T params; /* various parameters passed between
- * main() and other functions. */
+ char_u *fname = NULL; // file name from command line
+ mparm_T params; // various parameters passed between
+ // main() and other functions.
+ char_u *cwd = NULL; // current workding dir on startup
time_init();
/* Many variables are in "params" so that we can pass them to invoked
@@ -331,6 +332,14 @@ int main(int argc, char **argv)
/* Source startup scripts. */
source_startup_scripts(&params);
+ // If using the runtime (-u is not NONE), enable syntax & filetype plugins.
+ if (params.use_vimrc != NULL && strcmp(params.use_vimrc, "NONE") != 0) {
+ // Does ":filetype plugin indent on".
+ filetype_maybe_enable();
+ // Sources syntax/syntax.vim, which calls `:filetype on`.
+ syn_maybe_on();
+ }
+
/*
* Read all the plugin files.
* Only when compiled with +eval, since most plugins need it.
@@ -461,11 +470,10 @@ int main(int argc, char **argv)
TIME_MSG("jump to first error");
}
- /*
- * If opened more than one window, start editing files in the other
- * windows.
- */
- edit_buffers(&params);
+ // If opened more than one window, start editing files in the other
+ // windows.
+ edit_buffers(&params, cwd);
+ xfree(cwd);
if (params.diff_mode) {
/* set options in each window for "nvim -d". */
@@ -1182,12 +1190,19 @@ static char_u *get_fname(mparm_T *parmp)
* Expand wildcards in file names.
*/
if (!parmp->literal) {
- /* Temporarily add '(' and ')' to 'isfname'. These are valid
- * filename characters but are excluded from 'isfname' to make
- * "gf" work on a file name in parenthesis (e.g.: see vim.h). */
+ cwd = xmalloc(MAXPATHL);
+ if (cwd != NULL) {
+ os_dirname(cwd, MAXPATHL);
+ }
+ // Temporarily add '(' and ')' to 'isfname'. These are valid
+ // filename characters but are excluded from 'isfname' to make
+ // "gf" work on a file name in parenthesis (e.g.: see vim.h).
do_cmdline_cmd(":set isf+=(,)");
alist_expand(NULL, 0);
do_cmdline_cmd(":set isf&");
+ if (cwd != NULL) {
+ os_chdir((char *)cwd);
+ }
}
#endif
return alist_name(&GARGLIST[0]);
@@ -1417,11 +1432,9 @@ static void create_windows(mparm_T *parmp)
}
}
-/*
- * If opened more than one window, start editing files in the other
- * windows. make_windows() has already opened the windows.
- */
-static void edit_buffers(mparm_T *parmp)
+/// If opened more than one window, start editing files in the other
+/// windows. make_windows() has already opened the windows.
+static void edit_buffers(mparm_T *parmp, char_u *cwd)
{
int arg_idx; /* index in argument list */
int i;
@@ -1442,7 +1455,10 @@ static void edit_buffers(mparm_T *parmp)
arg_idx = 1;
for (i = 1; i < parmp->window_count; ++i) {
- /* When w_arg_idx is -1 remove the window (see create_windows()). */
+ if (cwd != NULL) {
+ os_chdir((char *)cwd);
+ }
+ // When w_arg_idx is -1 remove the window (see create_windows()).
if (curwin->w_arg_idx == -1) {
++arg_idx;
win_close(curwin, TRUE);
diff --git a/src/nvim/message.c b/src/nvim/message.c
index 00f4c0a85c..1dd71baaa4 100644
--- a/src/nvim/message.c
+++ b/src/nvim/message.c
@@ -1396,7 +1396,8 @@ void msg_prt_line(char_u *s, int list)
c = *p_extra++;
} else if (has_mbyte && (l = (*mb_ptr2len)(s)) > 1) {
col += (*mb_ptr2cells)(s);
- if (lcs_nbsp != NUL && list && mb_ptr2char(s) == 160) {
+ if (lcs_nbsp != NUL && list
+ && (mb_ptr2char(s) == 160 || mb_ptr2char(s) == 0x202f)) {
mb_char2bytes(lcs_nbsp, buf);
buf[(*mb_ptr2len)(buf)] = NUL;
} else {
diff --git a/src/nvim/move.c b/src/nvim/move.c
index eb55397511..ba79c0411a 100644
--- a/src/nvim/move.c
+++ b/src/nvim/move.c
@@ -1288,9 +1288,10 @@ void scroll_cursor_top(int min_scroll, int always)
* - at least 'scrolloff' lines above and below the cursor
*/
validate_cheight();
- int used = curwin->w_cline_height;
- if (curwin->w_cursor.lnum < curwin->w_topline)
+ int used = curwin->w_cline_height; // includes filler lines above
+ if (curwin->w_cursor.lnum < curwin->w_topline) {
scrolled = used;
+ }
if (hasFolding(curwin->w_cursor.lnum, &top, &bot)) {
--top;
@@ -1301,9 +1302,10 @@ void scroll_cursor_top(int min_scroll, int always)
}
new_topline = top + 1;
- /* count filler lines of the cursor window as context */
+ // "used" already contains the number of filler lines above, don't add it
+ // again.
+ // Hide filler lines above cursor line by adding them to "extra".
int extra = diff_check_fill(curwin, curwin->w_cursor.lnum);
- used += extra;
/*
* Check if the lines from "top" to "bot" fit in the window. If they do,
@@ -1312,7 +1314,7 @@ void scroll_cursor_top(int min_scroll, int always)
while (top > 0) {
int i = hasFolding(top, &top, NULL)
? 1 // count one logical line for a sequence of folded lines
- : plines(top);
+ : plines_nofill(top);
used += i;
if (extra + i <= off && bot < curbuf->b_ml.ml_line_count) {
if (hasFolding(bot, NULL, &bot))
diff --git a/src/nvim/normal.c b/src/nvim/normal.c
index 2f57d8c610..e064d34e09 100644
--- a/src/nvim/normal.c
+++ b/src/nvim/normal.c
@@ -1414,11 +1414,12 @@ void do_pending_operator(cmdarg_T *cap, int old_col, bool gui_yank)
int lbr_saved = curwin->w_p_lbr;
- /* The visual area is remembered for redo */
- static int redo_VIsual_mode = NUL; /* 'v', 'V', or Ctrl-V */
- static linenr_T redo_VIsual_line_count; /* number of lines */
- static colnr_T redo_VIsual_vcol; /* number of cols or end column */
- static long redo_VIsual_count; /* count for Visual operator */
+ // The visual area is remembered for redo
+ static int redo_VIsual_mode = NUL; // 'v', 'V', or Ctrl-V
+ static linenr_T redo_VIsual_line_count; // number of lines
+ static colnr_T redo_VIsual_vcol; // number of cols or end column
+ static long redo_VIsual_count; // count for Visual operator
+ static int redo_VIsual_arg; // extra argument
bool include_line_break = false;
old_cursor = curwin->w_cursor;
@@ -1430,6 +1431,9 @@ void do_pending_operator(cmdarg_T *cap, int old_col, bool gui_yank)
|| VIsual_active
) && oap->op_type != OP_NOP) {
// Avoid a problem with unwanted linebreaks in block mode
+ if (curwin->w_p_lbr) {
+ curwin->w_valid &= ~VALID_VIRTCOL;
+ }
curwin->w_p_lbr = false;
oap->is_VIsual = VIsual_active;
if (oap->motion_force == 'V')
@@ -1534,9 +1538,11 @@ void do_pending_operator(cmdarg_T *cap, int old_col, bool gui_yank)
curbuf->b_visual_mode_eval = VIsual_mode;
}
- /* In Select mode, a linewise selection is operated upon like a
- * characterwise selection. */
- if (VIsual_select && VIsual_mode == 'V') {
+ // In Select mode, a linewise selection is operated upon like a
+ // characterwise selection.
+ // Special case: gH<Del> deletes the last line.
+ if (VIsual_select && VIsual_mode == 'V'
+ && cap->oap->op_type != OP_DELETE) {
if (lt(VIsual, curwin->w_cursor)) {
VIsual.col = 0;
curwin->w_cursor.col =
@@ -1598,55 +1604,7 @@ void do_pending_operator(cmdarg_T *cap, int old_col, bool gui_yank)
virtual_op = virtual_active();
if (VIsual_active || redo_VIsual_busy) {
- if (VIsual_mode == Ctrl_V) { /* block mode */
- colnr_T start, end;
-
- oap->motion_type = MBLOCK;
-
- getvvcol(curwin, &(oap->start),
- &oap->start_vcol, NULL, &oap->end_vcol);
- if (!redo_VIsual_busy) {
- getvvcol(curwin, &(oap->end), &start, NULL, &end);
-
- if (start < oap->start_vcol)
- oap->start_vcol = start;
- if (end > oap->end_vcol) {
- if (*p_sel == 'e' && start >= 1
- && start - 1 >= oap->end_vcol)
- oap->end_vcol = start - 1;
- else
- oap->end_vcol = end;
- }
- }
-
- /* if '$' was used, get oap->end_vcol from longest line */
- if (curwin->w_curswant == MAXCOL) {
- curwin->w_cursor.col = MAXCOL;
- oap->end_vcol = 0;
- for (curwin->w_cursor.lnum = oap->start.lnum;
- curwin->w_cursor.lnum <= oap->end.lnum;
- ++curwin->w_cursor.lnum) {
- getvvcol(curwin, &curwin->w_cursor, NULL, NULL, &end);
- if (end > oap->end_vcol)
- oap->end_vcol = end;
- }
- } else if (redo_VIsual_busy)
- oap->end_vcol = oap->start_vcol + redo_VIsual_vcol - 1;
- /*
- * Correct oap->end.col and oap->start.col to be the
- * upper-left and lower-right corner of the block area.
- *
- * (Actually, this does convert column positions into character
- * positions)
- */
- curwin->w_cursor.lnum = oap->end.lnum;
- coladvance(oap->end_vcol);
- oap->end = curwin->w_cursor;
-
- curwin->w_cursor = oap->start;
- coladvance(oap->start_vcol);
- oap->start = curwin->w_cursor;
- }
+ get_op_vcol(oap, redo_VIsual_vcol, true);
if (!redo_VIsual_busy && !gui_yank) {
/*
@@ -1701,6 +1659,7 @@ void do_pending_operator(cmdarg_T *cap, int old_col, bool gui_yank)
redo_VIsual_vcol = resel_VIsual_vcol;
redo_VIsual_line_count = resel_VIsual_line_count;
redo_VIsual_count = cap->count0;
+ redo_VIsual_arg = cap->arg;
}
}
@@ -1719,20 +1678,15 @@ void do_pending_operator(cmdarg_T *cap, int old_col, bool gui_yank)
&& (include_line_break || !virtual_op)
) {
oap->inclusive = false;
- /* Try to include the newline, unless it's an operator
- * that works on lines only. */
- if (*p_sel != 'o' && !op_on_lines(oap->op_type)) {
- if (oap->end.lnum < curbuf->b_ml.ml_line_count) {
- ++oap->end.lnum;
- oap->end.col = 0;
- oap->end.coladd = 0;
- ++oap->line_count;
- } else {
- /* Cannot move below the last line, make the op
- * inclusive to tell the operation to include the
- * line break. */
- oap->inclusive = true;
- }
+ // Try to include the newline, unless it's an operator
+ // that works on lines only.
+ if (*p_sel != 'o'
+ && !op_on_lines(oap->op_type)
+ && oap->end.lnum < curbuf->b_ml.ml_line_count) {
+ oap->end.lnum++;
+ oap->end.col = 0;
+ oap->end.coladd = 0;
+ oap->line_count++;
}
}
}
@@ -1750,10 +1704,7 @@ void do_pending_operator(cmdarg_T *cap, int old_col, bool gui_yank)
VIsual_active = false;
setmouse();
mouse_dragging = 0;
- if (mode_displayed)
- clear_cmdline = true; /* unshow visual mode later */
- else
- clear_showcmd();
+ may_clear_cmdline();
if ((oap->op_type == OP_YANK
|| oap->op_type == OP_COLON
|| oap->op_type == OP_FUNCTION
@@ -1894,9 +1845,14 @@ void do_pending_operator(cmdarg_T *cap, int old_col, bool gui_yank)
else
restart_edit_save = 0;
restart_edit = 0;
+
// Restore linebreak, so that when the user edits it looks as before.
- curwin->w_p_lbr = lbr_saved;
- /* Reset finish_op now, don't want it set inside edit(). */
+ if (curwin->w_p_lbr != lbr_saved) {
+ curwin->w_p_lbr = lbr_saved;
+ get_op_vcol(oap, redo_VIsual_mode, false);
+ }
+
+ // Reset finish_op now, don't want it set inside edit().
finish_op = false;
if (op_change(oap)) /* will call edit() */
cap->retval |= CA_COMMAND_BUSY;
@@ -1974,7 +1930,10 @@ void do_pending_operator(cmdarg_T *cap, int old_col, bool gui_yank)
restart_edit = 0;
// Restore linebreak, so that when the user edits it looks as before.
- curwin->w_p_lbr = lbr_saved;
+ if (curwin->w_p_lbr != lbr_saved) {
+ curwin->w_p_lbr = lbr_saved;
+ get_op_vcol(oap, redo_VIsual_mode, false);
+ }
op_insert(oap, cap->count1);
@@ -1997,7 +1956,11 @@ void do_pending_operator(cmdarg_T *cap, int old_col, bool gui_yank)
CancelRedo();
} else {
// Restore linebreak, so that when the user edits it looks as before.
- curwin->w_p_lbr = lbr_saved;
+ if (curwin->w_p_lbr != lbr_saved) {
+ curwin->w_p_lbr = lbr_saved;
+ get_op_vcol(oap, redo_VIsual_mode, false);
+ }
+
op_replace(oap, cap->nchar);
}
break;
@@ -2026,6 +1989,20 @@ void do_pending_operator(cmdarg_T *cap, int old_col, bool gui_yank)
deleteFold(oap->start.lnum, oap->end.lnum,
oap->op_type == OP_FOLDDELREC, oap->is_VIsual);
break;
+
+ case OP_NR_ADD:
+ case OP_NR_SUB:
+ if (empty_region_error) {
+ vim_beep(BO_OPER);
+ CancelRedo();
+ } else {
+ VIsual_active = true;
+ curwin->w_p_lbr = lbr_saved;
+ op_addsub(oap, cap->count1, redo_VIsual_arg);
+ VIsual_active = false;
+ }
+ check_cursor_col();
+ break;
default:
clearopbeep(oap);
}
@@ -2367,8 +2344,9 @@ do_mouse (
if (mouse_row == 0 && firstwin->w_winrow > 0) {
if (is_drag) {
if (in_tab_line) {
- c1 = TabPageIdxs[mouse_col];
- tabpage_move(c1 <= 0 ? 9999 : c1 - 1);
+ tabpage_move(tab_page_click_defs[mouse_col].type == kStlClickTabClose
+ ? 9999
+ : tab_page_click_defs[mouse_col].tabnr - 1);
}
return false;
}
@@ -2378,41 +2356,114 @@ do_mouse (
&& cmdwin_type == 0
&& mouse_col < Columns) {
in_tab_line = true;
- c1 = TabPageIdxs[mouse_col];
- if (c1 >= 0) {
- if ((mod_mask & MOD_MASK_MULTI_CLICK) == MOD_MASK_2CLICK) {
- /* double click opens new page */
- end_visual_mode();
- tabpage_new();
- tabpage_move(c1 == 0 ? 9999 : c1 - 1);
- } else {
- /* Go to specified tab page, or next one if not clicking
- * on a label. */
- goto_tabpage(c1);
-
- /* It's like clicking on the status line of a window. */
- if (curwin != old_curwin)
+ c1 = tab_page_click_defs[mouse_col].tabnr;
+ switch (tab_page_click_defs[mouse_col].type) {
+ case kStlClickDisabled: {
+ break;
+ }
+ case kStlClickTabClose: {
+ tabpage_T *tp;
+
+ // Close the current or specified tab page.
+ if (c1 == 999) {
+ tp = curtab;
+ } else {
+ tp = find_tabpage(c1);
+ }
+ if (tp == curtab) {
+ if (first_tabpage->tp_next != NULL) {
+ tabpage_close(false);
+ }
+ } else if (tp != NULL) {
+ tabpage_close_other(tp, false);
+ }
+ break;
+ }
+ case kStlClickTabSwitch: {
+ if ((mod_mask & MOD_MASK_MULTI_CLICK) == MOD_MASK_2CLICK) {
+ // double click opens new page
end_visual_mode();
+ tabpage_new();
+ tabpage_move(c1 == 0 ? 9999 : c1 - 1);
+ } else {
+ // Go to specified tab page, or next one if not clicking
+ // on a label.
+ goto_tabpage(c1);
+
+ // It's like clicking on the status line of a window.
+ if (curwin != old_curwin) {
+ end_visual_mode();
+ }
+ }
+ break;
+ }
+ case kStlClickFuncRun: {
+ typval_T argv[] = {
+ {
+ .v_lock = VAR_FIXED,
+ .v_type = VAR_NUMBER,
+ .vval = {
+ .v_number = (varnumber_T) tab_page_click_defs[mouse_col].tabnr
+ },
+ },
+ {
+ .v_lock = VAR_FIXED,
+ .v_type = VAR_NUMBER,
+ .vval = {
+ .v_number = (((mod_mask & MOD_MASK_MULTI_CLICK)
+ == MOD_MASK_4CLICK)
+ ? 4
+ : ((mod_mask & MOD_MASK_MULTI_CLICK)
+ == MOD_MASK_3CLICK)
+ ? 3
+ : ((mod_mask & MOD_MASK_MULTI_CLICK)
+ == MOD_MASK_2CLICK)
+ ? 2
+ : 1)
+ },
+ },
+ {
+ .v_lock = VAR_FIXED,
+ .v_type = VAR_STRING,
+ .vval = { .v_string = (char_u *) (which_button == MOUSE_LEFT
+ ? "l"
+ : which_button == MOUSE_RIGHT
+ ? "r"
+ : which_button == MOUSE_MIDDLE
+ ? "m"
+ : "?") },
+ },
+ {
+ .v_lock = VAR_FIXED,
+ .v_type = VAR_STRING,
+ .vval = {
+ .v_string = (char_u[]) {
+ (char_u) (mod_mask & MOD_MASK_SHIFT ? 's' : ' '),
+ (char_u) (mod_mask & MOD_MASK_CTRL ? 'c' : ' '),
+ (char_u) (mod_mask & MOD_MASK_ALT ? 'a' : ' '),
+ (char_u) (mod_mask & MOD_MASK_META ? 'm' : ' '),
+ NUL
+ }
+ },
+ }
+ };
+ typval_T rettv;
+ int doesrange;
+ (void) call_func((char_u *) tab_page_click_defs[mouse_col].func,
+ (int) strlen(tab_page_click_defs[mouse_col].func),
+ &rettv, ARRAY_SIZE(argv), argv,
+ curwin->w_cursor.lnum, curwin->w_cursor.lnum,
+ &doesrange, true, NULL);
+ clear_tv(&rettv);
+ break;
}
- } else if (c1 < 0) {
- tabpage_T *tp;
-
- /* Close the current or specified tab page. */
- if (c1 == -999)
- tp = curtab;
- else
- tp = find_tabpage(-c1);
- if (tp == curtab) {
- if (first_tabpage->tp_next != NULL)
- tabpage_close(false);
- } else if (tp != NULL)
- tabpage_close_other(tp, false);
}
}
return true;
} else if (is_drag && in_tab_line) {
- c1 = TabPageIdxs[mouse_col];
- tabpage_move(c1 <= 0 ? 9999 : c1 - 1);
+ tabpage_move(tab_page_click_defs[mouse_col].type == kStlClickTabClose
+ ? 9999
+ : tab_page_click_defs[mouse_col].tabnr - 1);
in_tab_line = false;
return false;
}
@@ -2885,10 +2936,7 @@ void end_visual_mode(void)
if (!virtual_active())
curwin->w_cursor.coladd = 0;
- if (mode_displayed)
- clear_cmdline = true; /* unshow visual mode later */
- else
- clear_showcmd();
+ may_clear_cmdline();
adjust_cursor_eol();
}
@@ -3154,10 +3202,19 @@ static void unshift_special(cmdarg_T *cap)
cap->cmdchar = simplify_key(cap->cmdchar, &mod_mask);
}
-/*
- * Routines for displaying a partly typed command
- */
+/// If the mode is currently displayed clear the command line or update the
+/// command displayed.
+static void may_clear_cmdline(void)
+{
+ if (mode_displayed) {
+ // unshow visual mode later
+ clear_cmdline = true;
+ } else {
+ clear_showcmd();
+ }
+}
+// Routines for displaying a partly typed command
# define SHOWCMD_BUFLEN SHOWCMD_COLS + 1 + 30
static char_u showcmd_buf[SHOWCMD_BUFLEN];
static char_u old_showcmd_buf[SHOWCMD_BUFLEN]; /* For push_showcmd() */
@@ -3536,9 +3593,16 @@ static void nv_help(cmdarg_T *cap)
*/
static void nv_addsub(cmdarg_T *cap)
{
- if (!checkclearopq(cap->oap)
- && do_addsub(cap->cmdchar, cap->count1))
+ if (!VIsual_active && cap->oap->op_type == OP_NOP) {
prep_redo_cmd(cap);
+ cap->oap->op_type = cap->cmdchar == Ctrl_A ? OP_NR_ADD : OP_NR_SUB;
+ op_addsub(cap->oap, cap->count1, cap->arg);
+ cap->oap->op_type = OP_NOP;
+ } else if (VIsual_active) {
+ nv_operator(cap);
+ } else {
+ clearop(cap->oap);
+ }
}
/*
@@ -6360,9 +6424,20 @@ static void nv_g_cmd(cmdarg_T *cap)
bool flag = false;
switch (cap->nchar) {
- /*
- * "gR": Enter virtual replace mode.
- */
+ // "g^A/g^X": Sequentially increment visually selected region.
+ case Ctrl_A:
+ case Ctrl_X:
+ if (VIsual_active) {
+ cap->arg = true;
+ cap->cmdchar = cap->nchar;
+ cap->nchar = NUL;
+ nv_addsub(cap);
+ } else {
+ clearopbeep(oap);
+ }
+ break;
+
+ // "gR": Enter virtual replace mode.
case 'R':
cap->arg = true;
nv_Replace(cap);
@@ -6877,10 +6952,16 @@ static void n_opencmd(cmdarg_T *cap)
(cap->cmdchar == 'o' ? 1 : 0))
)
&& open_line(cap->cmdchar == 'O' ? BACKWARD : FORWARD,
- has_format_option(FO_OPEN_COMS) ? OPENLINE_DO_COM :
- 0, 0)) {
- if (curwin->w_p_cole > 0 && oldline != curwin->w_cursor.lnum)
+ has_format_option(FO_OPEN_COMS)
+ ? OPENLINE_DO_COM : 0,
+ 0)) {
+ if (curwin->w_p_cole > 0 && oldline != curwin->w_cursor.lnum) {
update_single_line(curwin, oldline);
+ }
+ if (curwin->w_p_cul) {
+ // force redraw of cursorline
+ curwin->w_valid &= ~VALID_CROW;
+ }
invoke_edit(cap, false, cap->cmdchar, true);
}
}
@@ -7664,6 +7745,10 @@ static void nv_put(cmdarg_T *cap)
if (was_visual) {
curbuf->b_visual.vi_start = curbuf->b_op_start;
curbuf->b_visual.vi_end = curbuf->b_op_end;
+ // need to adjust cursor position
+ if (*p_sel == 'e') {
+ inc(&curbuf->b_visual.vi_end);
+ }
}
/* When all lines were selected and deleted do_put() leaves an empty
@@ -7698,6 +7783,75 @@ static void nv_open(cmdarg_T *cap)
n_opencmd(cap);
}
+// Calculate start/end virtual columns for operating in block mode.
+static void get_op_vcol(
+ oparg_T *oap,
+ colnr_T redo_VIsual_vcol,
+ bool initial // when true: adjust position for 'selectmode'
+)
+{
+ colnr_T start;
+ colnr_T end;
+
+ if (VIsual_mode != Ctrl_V
+ || (!initial && oap->end.col < curwin->w_width)) {
+ return;
+ }
+
+ oap->motion_type = MBLOCK;
+
+ // prevent from moving onto a trail byte
+ if (has_mbyte) {
+ mb_adjustpos(curwin->w_buffer, &oap->end);
+ }
+
+ getvvcol(curwin, &(oap->start), &oap->start_vcol, NULL, &oap->end_vcol);
+ if (!redo_VIsual_busy) {
+ getvvcol(curwin, &(oap->end), &start, NULL, &end);
+
+ if (start < oap->start_vcol) {
+ oap->start_vcol = start;
+ }
+ if (end > oap->end_vcol) {
+ if (initial && *p_sel == 'e'
+ && start >= 1
+ && start - 1 >= oap->end_vcol) {
+ oap->end_vcol = start - 1;
+ } else {
+ oap->end_vcol = end;
+ }
+ }
+ }
+
+ // if '$' was used, get oap->end_vcol from longest line
+ if (curwin->w_curswant == MAXCOL) {
+ curwin->w_cursor.col = MAXCOL;
+ oap->end_vcol = 0;
+ for (curwin->w_cursor.lnum = oap->start.lnum;
+ curwin->w_cursor.lnum <= oap->end.lnum; ++curwin->w_cursor.lnum) {
+ getvvcol(curwin, &curwin->w_cursor, NULL, NULL, &end);
+ if (end > oap->end_vcol) {
+ oap->end_vcol = end;
+ }
+ }
+ } else if (redo_VIsual_busy) {
+ oap->end_vcol = oap->start_vcol + redo_VIsual_vcol - 1;
+ }
+
+ // Correct oap->end.col and oap->start.col to be the
+ // upper-left and lower-right corner of the block area.
+ //
+ // (Actually, this does convert column positions into character
+ // positions)
+ curwin->w_cursor.lnum = oap->end.lnum;
+ coladvance(oap->end_vcol);
+ oap->end = curwin->w_cursor;
+
+ curwin->w_cursor = oap->start;
+ coladvance(oap->start_vcol);
+ oap->start = curwin->w_cursor;
+}
+
// Handle an arbitrary event in normal mode
static void nv_event(cmdarg_T *cap)
{
diff --git a/src/nvim/ops.c b/src/nvim/ops.c
index 19dbd0f9f6..b1adc85e1d 100644
--- a/src/nvim/ops.c
+++ b/src/nvim/ops.c
@@ -87,34 +87,36 @@ struct block_def {
*/
static char opchars[][3] =
{
- {NUL, NUL, FALSE}, /* OP_NOP */
- {'d', NUL, FALSE}, /* OP_DELETE */
- {'y', NUL, FALSE}, /* OP_YANK */
- {'c', NUL, FALSE}, /* OP_CHANGE */
- {'<', NUL, TRUE}, /* OP_LSHIFT */
- {'>', NUL, TRUE}, /* OP_RSHIFT */
- {'!', NUL, TRUE}, /* OP_FILTER */
- {'g', '~', FALSE}, /* OP_TILDE */
- {'=', NUL, TRUE}, /* OP_INDENT */
- {'g', 'q', TRUE}, /* OP_FORMAT */
- {':', NUL, TRUE}, /* OP_COLON */
- {'g', 'U', FALSE}, /* OP_UPPER */
- {'g', 'u', FALSE}, /* OP_LOWER */
- {'J', NUL, TRUE}, /* DO_JOIN */
- {'g', 'J', TRUE}, /* DO_JOIN_NS */
- {'g', '?', FALSE}, /* OP_ROT13 */
- {'r', NUL, FALSE}, /* OP_REPLACE */
- {'I', NUL, FALSE}, /* OP_INSERT */
- {'A', NUL, FALSE}, /* OP_APPEND */
- {'z', 'f', TRUE}, /* OP_FOLD */
- {'z', 'o', TRUE}, /* OP_FOLDOPEN */
- {'z', 'O', TRUE}, /* OP_FOLDOPENREC */
- {'z', 'c', TRUE}, /* OP_FOLDCLOSE */
- {'z', 'C', TRUE}, /* OP_FOLDCLOSEREC */
- {'z', 'd', TRUE}, /* OP_FOLDDEL */
- {'z', 'D', TRUE}, /* OP_FOLDDELREC */
- {'g', 'w', TRUE}, /* OP_FORMAT2 */
- {'g', '@', FALSE}, /* OP_FUNCTION */
+ { NUL, NUL, false }, // OP_NOP
+ { 'd', NUL, false }, // OP_DELETE
+ { 'y', NUL, false }, // OP_YANK
+ { 'c', NUL, false }, // OP_CHANGE
+ { '<', NUL, true }, // OP_LSHIFT
+ { '>', NUL, true }, // OP_RSHIFT
+ { '!', NUL, true }, // OP_FILTER
+ { 'g', '~', false }, // OP_TILDE
+ { '=', NUL, true }, // OP_INDENT
+ { 'g', 'q', true }, // OP_FORMAT
+ { ':', NUL, true }, // OP_COLON
+ { 'g', 'U', false }, // OP_UPPER
+ { 'g', 'u', false }, // OP_LOWER
+ { 'J', NUL, true }, // DO_JOIN
+ { 'g', 'J', true }, // DO_JOIN_NS
+ { 'g', '?', false }, // OP_ROT13
+ { 'r', NUL, false }, // OP_REPLACE
+ { 'I', NUL, false }, // OP_INSERT
+ { 'A', NUL, false }, // OP_APPEND
+ { 'z', 'f', true }, // OP_FOLD
+ { 'z', 'o', true }, // OP_FOLDOPEN
+ { 'z', 'O', true }, // OP_FOLDOPENREC
+ { 'z', 'c', true }, // OP_FOLDCLOSE
+ { 'z', 'C', true }, // OP_FOLDCLOSEREC
+ { 'z', 'd', true }, // OP_FOLDDEL
+ { 'z', 'D', true }, // OP_FOLDDELREC
+ { 'g', 'w', true }, // OP_FORMAT2
+ { 'g', '@', false }, // OP_FUNCTION
+ { Ctrl_A, NUL, false }, // OP_NR_ADD
+ { Ctrl_X, NUL, false }, // OP_NR_SUB
};
/*
@@ -125,13 +127,27 @@ int get_op_type(int char1, int char2)
{
int i;
- if (char1 == 'r') /* ignore second character */
+ if (char1 == 'r') {
+ // ignore second character
return OP_REPLACE;
- if (char1 == '~') /* when tilde is an operator */
+ }
+ if (char1 == '~') {
+ // when tilde is an operator
return OP_TILDE;
- for (i = 0;; i++)
- if (opchars[i][0] == char1 && opchars[i][1] == char2)
+ }
+ if (char1 == 'g' && char2 == Ctrl_A) {
+ // add
+ return OP_NR_ADD;
+ }
+ if (char1 == 'g' && char2 == Ctrl_X) {
+ // subtract
+ return OP_NR_SUB;
+ }
+ for (i = 0;; i++) {
+ if (opchars[i][0] == char1 && opchars[i][1] == char2) {
break;
+ }
+ }
return i;
}
@@ -1539,55 +1555,31 @@ int op_delete(oparg_T *oap)
if (gchar_cursor() != NUL)
curwin->w_cursor.coladd = 0;
}
- if (oap->op_type == OP_DELETE
- && oap->inclusive
- && oap->end.lnum == curbuf->b_ml.ml_line_count
- && n > (int)STRLEN(ml_get(oap->end.lnum))) {
- /* Special case: gH<Del> deletes the last line. */
- del_lines(1L, FALSE);
- } else {
- (void)del_bytes((long)n, !virtual_op, oap->op_type == OP_DELETE
- && !oap->is_VIsual
- );
- }
- } else { /* delete characters between lines */
+
+ (void)del_bytes((long)n, !virtual_op,
+ oap->op_type == OP_DELETE && !oap->is_VIsual);
+ } else {
+ // delete characters between lines
pos_T curpos;
- int delete_last_line;
/* save deleted and changed lines for undo */
if (u_save((linenr_T)(curwin->w_cursor.lnum - 1),
(linenr_T)(curwin->w_cursor.lnum + oap->line_count)) == FAIL)
return FAIL;
- delete_last_line = (oap->end.lnum == curbuf->b_ml.ml_line_count);
- truncate_line(TRUE); /* delete from cursor to end of line */
-
- curpos = curwin->w_cursor; /* remember curwin->w_cursor */
- ++curwin->w_cursor.lnum;
- del_lines(oap->line_count - 2, FALSE);
+ truncate_line(true); // delete from cursor to end of line
- if (delete_last_line)
- oap->end.lnum = curbuf->b_ml.ml_line_count;
+ curpos = curwin->w_cursor; // remember curwin->w_cursor
+ curwin->w_cursor.lnum++;
+ del_lines(oap->line_count - 2, false);
+ // delete from start of line until op_end
n = (oap->end.col + 1 - !oap->inclusive);
- if (oap->inclusive && delete_last_line
- && n > (int)STRLEN(ml_get(oap->end.lnum))) {
- /* Special case: gH<Del> deletes the last line. */
- del_lines(1L, FALSE);
- curwin->w_cursor = curpos; /* restore curwin->w_cursor */
- if (curwin->w_cursor.lnum > curbuf->b_ml.ml_line_count)
- curwin->w_cursor.lnum = curbuf->b_ml.ml_line_count;
- } else {
- /* delete from start of line until op_end */
- curwin->w_cursor.col = 0;
- (void)del_bytes((long)n, !virtual_op, oap->op_type == OP_DELETE
- && !oap->is_VIsual
- );
- curwin->w_cursor = curpos; /* restore curwin->w_cursor */
- }
- if (curwin->w_cursor.lnum < curbuf->b_ml.ml_line_count) {
- do_join(2, FALSE, FALSE, FALSE, false);
- }
+ curwin->w_cursor.col = 0;
+ (void)del_bytes((long)n, !virtual_op,
+ oap->op_type == OP_DELETE && !oap->is_VIsual);
+ curwin->w_cursor = curpos; // restore curwin->w_cursor
+ (void)do_join(2, false, false, false, false);
}
}
@@ -2672,17 +2664,27 @@ void do_put(int regname, yankreg_T *reg, int dir, long count, int flags)
if (y_type == MLINE) {
if (flags & PUT_LINE_SPLIT) {
- /* "p" or "P" in Visual mode: split the lines to put the text in
- * between. */
- if (u_save_cursor() == FAIL)
+ // "p" or "P" in Visual mode: split the lines to put the text in
+ // between.
+ if (u_save_cursor() == FAIL) {
goto end;
- ptr = vim_strsave(get_cursor_pos_ptr());
- ml_append(curwin->w_cursor.lnum, ptr, (colnr_T)0, FALSE);
+ }
+ char_u *p = get_cursor_pos_ptr();
+ if (dir == FORWARD && *p != NUL) {
+ mb_ptr_adv(p);
+ }
+ ptr = vim_strsave(p);
+ ml_append(curwin->w_cursor.lnum, ptr, (colnr_T)0, false);
xfree(ptr);
- ptr = vim_strnsave(get_cursor_line_ptr(), curwin->w_cursor.col);
- ml_replace(curwin->w_cursor.lnum, ptr, FALSE);
- ++nr_lines;
+ oldp = get_cursor_line_ptr();
+ p = oldp + curwin->w_cursor.col;
+ if (dir == FORWARD && *p != NUL) {
+ mb_ptr_adv(p);
+ }
+ ptr = vim_strnsave(oldp, p - oldp);
+ ml_replace(curwin->w_cursor.lnum, ptr, false);
+ nr_lines++;
dir = FORWARD;
}
if (flags & PUT_LINE_FORWARD) {
@@ -4181,134 +4183,241 @@ static void block_prep(oparg_T *oap, struct block_def *bdp, linenr_T lnum, int i
bdp->textstart = pstart;
}
-
-static void reverse_line(char_u *s)
+/// Handle the add/subtract operator.
+///
+/// @param[in] oap Arguments of operator.
+/// @param[in] Prenum1 Amount of addition or subtraction.
+/// @param[in] g_cmd Prefixed with `g`.
+void op_addsub(oparg_T *oap, linenr_T Prenum1, bool g_cmd)
{
- int i, j;
- char_u c;
+ pos_T pos;
+ struct block_def bd;
+ ssize_t change_cnt = 0;
+ linenr_T amount = Prenum1;
- if ((i = (int)STRLEN(s) - 1) <= 0)
- return;
+ if (!VIsual_active) {
+ pos = curwin->w_cursor;
+ if (u_save_cursor() == FAIL) {
+ return;
+ }
+ change_cnt = do_addsub(oap->op_type, &pos, 0, amount);
+ if (change_cnt) {
+ changed_lines(pos.lnum, 0, pos.lnum + 1, 0L);
+ }
+ } else {
+ int one_change;
+ int length;
+ pos_T startpos;
+
+ if (u_save((linenr_T)(oap->start.lnum - 1),
+ (linenr_T)(oap->end.lnum + 1)) == FAIL) {
+ return;
+ }
- curwin->w_cursor.col = i - curwin->w_cursor.col;
- for (j = 0; j < i; j++, i--) {
- c = s[i]; s[i] = s[j]; s[j] = c;
+ pos = oap->start;
+ for (; pos.lnum <= oap->end.lnum; ++pos.lnum) {
+ if (oap->motion_type == MBLOCK) {
+ // Visual block mode
+ block_prep(oap, &bd, pos.lnum, false);
+ pos.col = bd.textcol;
+ length = bd.textlen;
+ } else if (oap->motion_type == MLINE) {
+ curwin->w_cursor.col = 0;
+ pos.col = 0;
+ length = (colnr_T)STRLEN(ml_get(pos.lnum));
+ } else {
+ // oap->motion_type == MCHAR
+ if (!oap->inclusive) {
+ dec(&(oap->end));
+ }
+ length = (colnr_T)STRLEN(ml_get(pos.lnum));
+ pos.col = 0;
+ if (pos.lnum == oap->start.lnum) {
+ pos.col += oap->start.col;
+ length -= oap->start.col;
+ }
+ if (pos.lnum == oap->end.lnum) {
+ length = (int)STRLEN(ml_get(oap->end.lnum));
+ if (oap->end.col >= length) {
+ oap->end.col = length - 1;
+ }
+ length = oap->end.col - pos.col + 1;
+ }
+ }
+ one_change = do_addsub(oap->op_type, &pos, length, amount);
+ if (one_change) {
+ // Remember the start position of the first change.
+ if (change_cnt == 0) {
+ startpos = curbuf->b_op_start;
+ }
+ change_cnt++;
+ }
+
+ if (g_cmd && one_change) {
+ amount += Prenum1;
+ }
+ }
+ if (change_cnt) {
+ changed_lines(oap->start.lnum, 0, oap->end.lnum + 1, 0L);
+ }
+
+ if (!change_cnt && oap->is_VIsual) {
+ // No change: need to remove the Visual selection
+ redraw_curbuf_later(INVERTED);
+ }
+
+ // Set '[ mark if something changed. Keep the last end
+ // position from do_addsub().
+ if (change_cnt > 0) {
+ curbuf->b_op_start = startpos;
+ }
+
+ if (change_cnt > p_report) {
+ if (change_cnt == 1) {
+ MSG(_("1 line changed"));
+ } else {
+ smsg((char *)_("%" PRId64 " lines changed"), (int64_t)change_cnt);
+ }
+ }
}
}
-# define RLADDSUBFIX(ptr) if (curwin->w_p_rl) reverse_line(ptr);
-
/// Add or subtract from a number in a line.
///
-/// @param command CTRL-A for add, CTRL-X for subtract
-// @param Prenum1 number to add or subtract
+/// @param op_type OP_NR_ADD or OP_NR_SUB.
+/// @param pos Cursor position.
+/// @param length Target number length.
+/// @param Prenum1 Amount of addition or subtraction.
///
-/// @return FAIL for failure, OK otherwise
-int do_addsub(int command, linenr_T Prenum1)
+/// @return true if some character was changed.
+int do_addsub(int op_type, pos_T *pos, int length, linenr_T Prenum1)
{
int col;
char_u *buf1;
char_u buf2[NUMBUFLEN];
- int pre; // 'X' or 'x': hex; '0': octal; 'B' or 'b': bin
- static int hexupper = false; // 0xABC
- unsigned long n, oldn;
+ int pre; // 'X' or 'x': hex; '0': octal; 'B' or 'b': bin
+ static bool hexupper = false; // 0xABC
+ unsigned long n;
+ unsigned long oldn;
char_u *ptr;
int c;
- int length = 0; // character length of the number
int todel;
- int dohex;
- int dooct;
- int dobin;
- int doalp;
+ bool dohex;
+ bool dooct;
+ bool dobin;
+ bool doalp;
int firstdigit;
- int negative;
- int subtract;
+ bool subtract;
+ bool negative = false;
+ bool was_positive = true;
+ bool visual = VIsual_active;
+ bool did_change = false;
+ pos_T save_cursor = curwin->w_cursor;
+ int maxlen = 0;
+ pos_T startpos;
+ pos_T endpos;
dohex = (vim_strchr(curbuf->b_p_nf, 'x') != NULL); // "heX"
dooct = (vim_strchr(curbuf->b_p_nf, 'o') != NULL); // "Octal"
dobin = (vim_strchr(curbuf->b_p_nf, 'b') != NULL); // "Bin"
doalp = (vim_strchr(curbuf->b_p_nf, 'p') != NULL); // "alPha"
- ptr = get_cursor_line_ptr();
- RLADDSUBFIX(ptr);
+ curwin->w_cursor = *pos;
+ ptr = ml_get(pos->lnum);
+ col = pos->col;
+
+ if (*ptr == NUL) {
+ goto theend;
+ }
// First check if we are on a hexadecimal number, after the "0x".
- col = curwin->w_cursor.col;
+ if (!VIsual_active) {
+ if (dobin) {
+ while (col > 0 && ascii_isbdigit(ptr[col])) {
+ col--;
+ }
+ }
- if (dobin) {
- while (col > 0 && ascii_isbdigit(ptr[col])) {
- col--;
+ if (dohex) {
+ while (col > 0 && ascii_isxdigit(ptr[col])) {
+ col--;
+ }
}
- }
+ if (dobin
+ && dohex
+ && !((col > 0
+ && (ptr[col] == 'X' ||
+ ptr[col] == 'x')
+ && ptr[col - 1] == '0'
+ && ascii_isxdigit(ptr[col + 1])))) {
+ // In case of binary/hexadecimal pattern overlap match, rescan
- if (dohex) {
- while (col > 0 && ascii_isxdigit(ptr[col])) {
- col--;
+ col = curwin->w_cursor.col;
+
+ while (col > 0 && ascii_isdigit(ptr[col])) {
+ col--;
+ }
}
- }
- if (dobin
- && dohex
- && !((col > 0
- && (ptr[col] == 'X' ||
- ptr[col] == 'x')
- && ptr[col - 1] == '0'
- && ascii_isxdigit(ptr[col + 1])))) {
- // In case of binary/hexadecimal pattern overlap match, rescan
- col = curwin->w_cursor.col;
+ if ((dohex
+ && col > 0
+ && (ptr[col] == 'X'
+ || ptr[col] == 'x')
+ && ptr[col - 1] == '0'
+ && ascii_isxdigit(ptr[col + 1])) ||
+ (dobin
+ && col > 0
+ && (ptr[col] == 'B'
+ || ptr[col] == 'b')
+ && ptr[col - 1] == '0'
+ && ascii_isbdigit(ptr[col + 1]))) {
+ // Found hexadecimal or binary number, move to its start.
+ col--;
+ } else {
+ // Search forward and then backward to find the start of number.
+ col = pos->col;
+
+ while (ptr[col] != NUL
+ && !ascii_isdigit(ptr[col])
+ && !(doalp && ASCII_ISALPHA(ptr[col]))) {
+ col++;
+ }
- while (col > 0 && ascii_isdigit(ptr[col])) {
+ while (col > 0
+ && ascii_isdigit(ptr[col - 1])
+ && !(doalp && ASCII_ISALPHA(ptr[col]))) {
col--;
}
+ }
}
- if ((dohex
- && col > 0
- && (ptr[col] == 'X'
- || ptr[col] == 'x')
- && ptr[col - 1] == '0'
- && ascii_isxdigit(ptr[col + 1])) ||
- (dobin
- && col > 0
- && (ptr[col] == 'B'
- || ptr[col] == 'b')
- && ptr[col - 1] == '0'
- && ascii_isbdigit(ptr[col + 1]))) {
- // Found hexadecimal or binary number, move to its start.
- col--;
- } else {
- // Search forward and then backward to find the start of number.
- col = curwin->w_cursor.col;
-
- while (ptr[col] != NUL
- && !ascii_isdigit(ptr[col])
- && !(doalp && ASCII_ISALPHA(ptr[col]))) {
+ if (visual) {
+ while (ptr[col] != NUL && length > 0 && !ascii_isdigit(ptr[col]) &&
+ !(doalp && ASCII_ISALPHA(ptr[col]))) {
col++;
+ length--;
}
- while (col > 0
- && ascii_isdigit(ptr[col - 1])
- && !(doalp && ASCII_ISALPHA(ptr[col]))) {
- col--;
+ if (length == 0) {
+ goto theend;
+ }
+
+ if (col > pos->col && ptr[col - 1] == '-') {
+ negative = true;
+ was_positive = false;
}
}
// If a number was found, and saving for undo works, replace the number.
firstdigit = ptr[col];
- RLADDSUBFIX(ptr);
- if ((!ascii_isdigit(firstdigit) && !(doalp && ASCII_ISALPHA(firstdigit)))
- || u_save_cursor() != OK) {
+ if (!ascii_isdigit(firstdigit) && !(doalp && ASCII_ISALPHA(firstdigit))) {
beep_flush();
- return FAIL;
+ goto theend;
}
- // get ptr again, because u_save() may have changed it
- ptr = get_cursor_line_ptr();
- RLADDSUBFIX(ptr);
-
if (doalp && ASCII_ISALPHA(firstdigit)) {
// decrement or increment alphabetic character
- if (command == Ctrl_X) {
+ if (op_type == OP_NR_SUB) {
if (CharOrd(firstdigit) < Prenum1) {
if (isupper(firstdigit)) {
firstdigit = 'A';
@@ -4330,28 +4439,44 @@ int do_addsub(int command, linenr_T Prenum1)
}
}
curwin->w_cursor.col = col;
+ if (!did_change) {
+ startpos = curwin->w_cursor;
+ }
+ did_change = true;
(void)del_char(false);
ins_char(firstdigit);
+ endpos = curwin->w_cursor;
+ curwin->w_cursor.col = col;
} else {
- negative = false;
- if (col > 0 && ptr[col - 1] == '-') { // negative number
- --col;
+ if (col > 0 && ptr[col - 1] == '-' && !visual) {
+ // negative number
+ col--;
negative = true;
}
// get the number value (unsigned)
- vim_str2nr(ptr + col, &pre, &length, dobin, dooct, dohex, NULL, &n);
+ if (visual && VIsual_mode != 'V') {
+ maxlen = (curbuf->b_visual.vi_curswant == MAXCOL
+ ? (int)STRLEN(ptr) - col
+ : length);
+ }
+
+ vim_str2nr(ptr + col, &pre, &length,
+ 0 + (dobin ? STR2NR_BIN : 0)
+ + (dooct ? STR2NR_OCT : 0)
+ + (dohex ? STR2NR_HEX : 0),
+ NULL, &n, maxlen);
// ignore leading '-' for hex, octal and bin numbers
if (pre && negative) {
- ++col;
- --length;
+ col++;
+ length--;
negative = false;
}
// add or subtract
subtract = false;
- if (command == Ctrl_X) {
+ if (op_type == OP_NR_SUB) {
subtract ^= true;
}
if (negative) {
@@ -4370,7 +4495,8 @@ int do_addsub(int command, linenr_T Prenum1)
n = 1 + (n ^ (unsigned long)-1);
negative ^= true;
}
- } else { /* add */
+ } else {
+ // add
if (n < oldn) {
n = (n ^ (unsigned long)-1);
negative ^= true;
@@ -4381,15 +4507,25 @@ int do_addsub(int command, linenr_T Prenum1)
}
}
+ if (visual && !was_positive && !negative && col > 0) {
+ // need to remove the '-'
+ col--;
+ length++;
+ }
+
// Delete the old number.
curwin->w_cursor.col = col;
+ if (!did_change) {
+ startpos = curwin->w_cursor;
+ }
+ did_change = true;
todel = length;
c = gchar_cursor();
// Don't include the '-' in the length, only the length of the part
// after it is kept the same.
if (c == '-') {
- --length;
+ length--;
}
while (todel-- > 0) {
if (c < 0x100 && isalpha(c)) {
@@ -4405,47 +4541,52 @@ int do_addsub(int command, linenr_T Prenum1)
}
// Prepare the leading characters in buf1[].
- // When there are many leading zeros it could be very long. Allocate
- // a bit too much.
+ // When there are many leading zeros it could be very long.
+ // Allocate a bit too much.
buf1 = xmalloc(length + NUMBUFLEN);
+ if (buf1 == NULL) {
+ goto theend;
+ }
ptr = buf1;
- if (negative) {
+ if (negative && (!visual || (visual && was_positive))) {
*ptr++ = '-';
}
if (pre) {
*ptr++ = '0';
- --length;
+ length--;
}
if (pre == 'b' || pre == 'B' ||
pre == 'x' || pre == 'X') {
*ptr++ = pre;
- --length;
+ length--;
}
// Put the number characters in buf2[].
if (pre == 'b' || pre == 'B') {
size_t bits = 0;
- size_t pos = 0;
+ size_t i = 0;
// leading zeros
- for (bits = 8 * sizeof(unsigned long); bits > 0; bits--) {
- if ((n >> (bits - 1)) & 0x1) { break; }
+ for (bits = 8 * sizeof(n); bits > 0; bits--) {
+ if ((n >> (bits - 1)) & 0x1) {
+ break;
+ }
}
while (bits > 0) {
- buf2[pos++] = ((n >> --bits) & 0x1) ? '1' : '0';
+ buf2[i++] = ((n >> --bits) & 0x1) ? '1' : '0';
}
- buf2[pos] = '\0';
+ buf2[i] = '\0';
} else if (pre == 0) {
- snprintf((char *)buf2, NUMBUFLEN, "%" PRIu64, (uint64_t)n);
+ vim_snprintf((char *)buf2, ARRAY_SIZE(buf2), "%" PRIu64, (uint64_t)n);
} else if (pre == '0') {
- snprintf((char *)buf2, NUMBUFLEN, "%" PRIo64, (uint64_t)n);
+ vim_snprintf((char *)buf2, ARRAY_SIZE(buf2), "%" PRIo64, (uint64_t)n);
} else if (pre && hexupper) {
- snprintf((char *)buf2, NUMBUFLEN, "%" PRIX64, (uint64_t)n);
+ vim_snprintf((char *)buf2, ARRAY_SIZE(buf2), "%" PRIX64, (uint64_t)n);
} else {
- snprintf((char *)buf2, NUMBUFLEN, "%" PRIx64, (uint64_t)n);
+ vim_snprintf((char *)buf2, ARRAY_SIZE(buf2), "%" PRIx64, (uint64_t)n);
}
length -= (int)STRLEN(buf2);
@@ -4460,14 +4601,29 @@ int do_addsub(int command, linenr_T Prenum1)
}
*ptr = NUL;
STRCAT(buf1, buf2);
- ins_str(buf1); /* insert the new number */
+ ins_str(buf1); // insert the new number
xfree(buf1);
+ endpos = curwin->w_cursor;
+ if (did_change && curwin->w_cursor.col) {
+ curwin->w_cursor.col--;
+ }
}
- --curwin->w_cursor.col;
- curwin->w_set_curswant = true;
- ptr = ml_get_buf(curbuf, curwin->w_cursor.lnum, true);
- RLADDSUBFIX(ptr);
- return OK;
+
+ if (did_change) {
+ // set the '[ and '] marks
+ curbuf->b_op_start = startpos;
+ curbuf->b_op_end = endpos;
+ if (curbuf->b_op_end.col > 0) {
+ curbuf->b_op_end.col--;
+ }
+ }
+
+theend:
+ if (visual) {
+ curwin->w_cursor = save_cursor;
+ }
+
+ return did_change;
}
/*
diff --git a/src/nvim/ops.h b/src/nvim/ops.h
index 507f933acf..f33e87572f 100644
--- a/src/nvim/ops.h
+++ b/src/nvim/ops.h
@@ -35,37 +35,39 @@ typedef int (*Indenter)(void);
#define PLUS_REGISTER 38
#define NUM_REGISTERS 39
-/*
- * Operator IDs; The order must correspond to opchars[] in ops.c!
- */
-#define OP_NOP 0 /* no pending operation */
-#define OP_DELETE 1 /* "d" delete operator */
-#define OP_YANK 2 /* "y" yank operator */
-#define OP_CHANGE 3 /* "c" change operator */
-#define OP_LSHIFT 4 /* "<" left shift operator */
-#define OP_RSHIFT 5 /* ">" right shift operator */
-#define OP_FILTER 6 /* "!" filter operator */
-#define OP_TILDE 7 /* "g~" switch case operator */
-#define OP_INDENT 8 /* "=" indent operator */
-#define OP_FORMAT 9 /* "gq" format operator */
-#define OP_COLON 10 /* ":" colon operator */
-#define OP_UPPER 11 /* "gU" make upper case operator */
-#define OP_LOWER 12 /* "gu" make lower case operator */
-#define OP_JOIN 13 /* "J" join operator, only for Visual mode */
-#define OP_JOIN_NS 14 /* "gJ" join operator, only for Visual mode */
-#define OP_ROT13 15 /* "g?" rot-13 encoding */
-#define OP_REPLACE 16 /* "r" replace chars, only for Visual mode */
-#define OP_INSERT 17 /* "I" Insert column, only for Visual mode */
-#define OP_APPEND 18 /* "A" Append column, only for Visual mode */
-#define OP_FOLD 19 /* "zf" define a fold */
-#define OP_FOLDOPEN 20 /* "zo" open folds */
-#define OP_FOLDOPENREC 21 /* "zO" open folds recursively */
-#define OP_FOLDCLOSE 22 /* "zc" close folds */
-#define OP_FOLDCLOSEREC 23 /* "zC" close folds recursively */
-#define OP_FOLDDEL 24 /* "zd" delete folds */
-#define OP_FOLDDELREC 25 /* "zD" delete folds recursively */
-#define OP_FORMAT2 26 /* "gw" format operator, keeps cursor pos */
-#define OP_FUNCTION 27 /* "g@" call 'operatorfunc' */
+// Operator IDs; The order must correspond to opchars[] in ops.c!
+#define OP_NOP 0 // no pending operation
+#define OP_DELETE 1 // "d" delete operator
+#define OP_YANK 2 // "y" yank operator
+#define OP_CHANGE 3 // "c" change operator
+#define OP_LSHIFT 4 // "<" left shift operator
+#define OP_RSHIFT 5 // ">" right shift operator
+#define OP_FILTER 6 // "!" filter operator
+#define OP_TILDE 7 // "g~" switch case operator
+#define OP_INDENT 8 // "=" indent operator
+#define OP_FORMAT 9 // "gq" format operator
+#define OP_COLON 10 // ":" colon operator
+#define OP_UPPER 11 // "gU" make upper case operator
+#define OP_LOWER 12 // "gu" make lower case operator
+#define OP_JOIN 13 // "J" join operator, only for Visual mode
+#define OP_JOIN_NS 14 // "gJ" join operator, only for Visual mode
+#define OP_ROT13 15 // "g?" rot-13 encoding
+#define OP_REPLACE 16 // "r" replace chars, only for Visual mode
+#define OP_INSERT 17 // "I" Insert column, only for Visual mode
+#define OP_APPEND 18 // "A" Append column, only for Visual mode
+#define OP_FOLD 19 // "zf" define a fold
+#define OP_FOLDOPEN 20 // "zo" open folds
+#define OP_FOLDOPENREC 21 // "zO" open folds recursively
+#define OP_FOLDCLOSE 22 // "zc" close folds
+#define OP_FOLDCLOSEREC 23 // "zC" close folds recursively
+#define OP_FOLDDEL 24 // "zd" delete folds
+#define OP_FOLDDELREC 25 // "zD" delete folds recursively
+#define OP_FORMAT2 26 // "gw" format operator, keeps cursor pos
+#define OP_FUNCTION 27 // "g@" call 'operatorfunc'
+#define OP_NR_ADD 28 // "<C-A>" Add to the number or alphabetic
+ // character (OP_ADD conflicts with Perl)
+#define OP_NR_SUB 29 // "<C-X>" Subtract from the number or
+ // alphabetic character
/// Flags for get_reg_contents().
enum GRegFlags {
diff --git a/src/nvim/option.c b/src/nvim/option.c
index b4054dc28c..0f6874e941 100644
--- a/src/nvim/option.c
+++ b/src/nvim/option.c
@@ -168,11 +168,12 @@ static int p_ml_nobin;
static long p_tw_nobin;
static long p_wm_nobin;
-/* Saved values for when 'paste' is set */
+// Saved values for when 'paste' is set.
+static int p_ai_nopaste;
+static int p_et_nopaste;
+static long p_sts_nopaste;
static long p_tw_nopaste;
static long p_wm_nopaste;
-static long p_sts_nopaste;
-static int p_ai_nopaste;
typedef struct vimoption {
char *fullname; /* full option name */
@@ -218,20 +219,22 @@ typedef struct vimoption {
#define P_RALL 0x6000U /* redraw all windows */
#define P_RCLR 0x7000U /* clear and redraw all */
-#define P_COMMA 0x8000U /* comma separated list */
-#define P_NODUP 0x10000U /* don't allow duplicate strings */
-#define P_FLAGLIST 0x20000U /* list of single-char flags */
-
-#define P_SECURE 0x40000U /* cannot change in modeline or secure mode */
-#define P_GETTEXT 0x80000U /* expand default value with _() */
-#define P_NOGLOB 0x100000U /* do not use local value for global vimrc */
-#define P_NFNAME 0x200000U /* only normal file name chars allowed */
-#define P_INSECURE 0x400000U /* option was set from a modeline */
-#define P_PRI_MKRC 0x800000U /* priority for :mkvimrc (setting option has
- side effects) */
-#define P_NO_ML 0x1000000U /* not allowed in modeline */
-#define P_CURSWANT 0x2000000U /* update curswant required; not needed when
- * there is a redraw flag */
+#define P_COMMA 0x8000U ///< comma separated list
+#define P_ONECOMMA 0x18000U ///< P_COMMA and cannot have two consecutive
+ ///< commas
+#define P_NODUP 0x20000U ///< don't allow duplicate strings
+#define P_FLAGLIST 0x40000U ///< list of single-char flags
+
+#define P_SECURE 0x80000U ///< cannot change in modeline or secure mode
+#define P_GETTEXT 0x100000U ///< expand default value with _()
+#define P_NOGLOB 0x200000U ///< do not use local value for global vimrc
+#define P_NFNAME 0x400000U ///< only normal file name chars allowed
+#define P_INSECURE 0x800000U ///< option was set from a modeline
+#define P_PRI_MKRC 0x1000000U ///< priority for :mkvimrc (setting option
+ ///< has side effects)
+#define P_NO_ML 0x2000000U ///< not allowed in modeline
+#define P_CURSWANT 0x4000000U ///< update curswant required; not needed
+ ///< when there is a redraw flag
#define HIGHLIGHT_INIT \
"8:SpecialKey,~:EndOfBuffer,z:TermCursor,Z:TermCursorNC,@:NonText," \
@@ -708,15 +711,11 @@ void set_init_1(void)
/* Must be before option_expand(), because that one needs vim_isIDc() */
didset_options();
- /* Use the current chartab for the generic chartab. */
+ // Use the current chartab for the generic chartab. This is not in
+ // didset_options() because it only depends on 'encoding'.
init_spell_chartab();
/*
- * initialize the table for 'breakat'.
- */
- fill_breakat_flags();
-
- /*
* Expand environment variables and things like "~" for the defaults.
* If option_expand() returns non-NULL the variable is expanded. This can
* only happen for non-indirect options.
@@ -748,14 +747,8 @@ void set_init_1(void)
}
}
- /* Initialize the highlight_attr[] table. */
- highlight_changed();
-
save_file_ff(curbuf); /* Buffer is unchanged */
- /* Parse default for 'wildmode' */
- check_opt_wim();
-
/* Detect use of mlterm.
* Mlterm is a terminal emulator akin to xterm that has some special
* abilities (bidi namely).
@@ -765,11 +758,7 @@ void set_init_1(void)
if (os_env_exists("MLTERM"))
set_option_value((char_u *)"tbidi", 1L, NULL, 0);
- /* Parse default for 'fillchars'. */
- (void)set_chars_option(&p_fcs);
-
- /* Parse default for 'listchars'. */
- (void)set_chars_option(&p_lcs);
+ didset_options2();
// enc_locale() will try to find the encoding of the current locale.
// This will be used when 'default' is used as encoding specifier
@@ -1148,9 +1137,12 @@ do_set (
*/
arg += 3;
if (*arg == '&') {
- ++arg;
- /* Only for :set command set global value of local options. */
+ arg++;
+ // Only for :set command set global value of local options.
set_options_default(OPT_FREE | opt_flags);
+ didset_options();
+ didset_options2();
+ redraw_all_later(CLEAR);
} else {
showoptions(1, opt_flags);
did_show = TRUE;
@@ -1432,7 +1424,7 @@ do_set (
} else if (*arg == '-' || ascii_isdigit(*arg)) {
// Allow negative (for 'undolevels'), octal and
// hex numbers.
- vim_str2nr(arg, NULL, &i, true, true, true, &value, NULL);
+ vim_str2nr(arg, NULL, &i, STR2NR_ALL, &value, NULL, 0);
if (arg[i] != NUL && !ascii_iswhite(arg[i])) {
errmsg = e_invarg;
goto skip;
@@ -1673,6 +1665,13 @@ do_set (
&& *newval != NUL);
if (adding) {
i = (int)STRLEN(origval);
+ // Strip a trailing comma, would get 2.
+ if (comma && i > 1
+ && (flags & P_ONECOMMA) == P_ONECOMMA
+ && origval[i - 1] == ','
+ && origval[i - 2] != '\\') {
+ i--;
+ }
memmove(newval + i + comma, newval,
STRLEN(newval) + 1);
memmove(newval, origval, (size_t)i);
@@ -2063,9 +2062,31 @@ static void didset_options(void)
(void)spell_check_msm();
(void)spell_check_sps();
(void)compile_cap_prog(curwin->w_s);
- /* set cedit_key */
+ (void)did_set_spell_option(true);
+ // set cedit_key
(void)check_cedit();
briopt_check(curwin);
+ // initialize the table for 'breakat'.
+ fill_breakat_flags();
+}
+
+// More side effects of setting options.
+static void didset_options2(void)
+{
+ // Initialize the highlight_attr[] table.
+ (void)highlight_changed();
+
+ // Parse default for 'clipboard'.
+ (void)opt_strings_flags(p_cb, p_cb_values, &cb_flags, true);
+
+ // Parse default for 'fillchars'.
+ (void)set_chars_option(&p_fcs);
+
+ // Parse default for 'listchars'.
+ (void)set_chars_option(&p_lcs);
+
+ // Parse default for 'wildmode'.
+ check_opt_wim();
}
/*
@@ -2844,22 +2865,7 @@ did_set_string_option (
|| varp == &(curwin->w_s->b_p_spf)) {
// When 'spelllang' or 'spellfile' is set and there is a window for this
// buffer in which 'spell' is set load the wordlists.
- if (varp == &(curwin->w_s->b_p_spf)) {
- int l = (int)STRLEN(curwin->w_s->b_p_spf);
- if (l > 0
- && (l < 4 || STRCMP(curwin->w_s->b_p_spf + l - 4, ".add") != 0)) {
- errmsg = e_invarg;
- }
- }
-
- if (errmsg == NULL) {
- FOR_ALL_WINDOWS_IN_TAB(wp, curtab) {
- if (wp->w_buffer == curbuf && wp->w_p_spell) {
- errmsg = did_set_spelllang(wp);
- break;
- }
- }
- }
+ errmsg = did_set_spell_option(varp == &(curwin->w_s->b_p_spf));
}
/* When 'spellcapcheck' is set compile the regexp program. */
else if (varp == &(curwin->w_s->b_p_spc)) {
@@ -3415,6 +3421,30 @@ char_u *check_stl_option(char_u *s)
return NULL;
}
+static char_u *did_set_spell_option(bool is_spellfile)
+{
+ char_u *errmsg = NULL;
+
+ if (is_spellfile) {
+ int l = (int)STRLEN(curwin->w_s->b_p_spf);
+ if (l > 0
+ && (l < 4 || STRCMP(curwin->w_s->b_p_spf + l - 4, ".add") != 0)) {
+ errmsg = e_invarg;
+ }
+ }
+
+ if (errmsg == NULL) {
+ FOR_ALL_WINDOWS_IN_TAB(wp, curtab) {
+ if (wp->w_buffer == curbuf && wp->w_p_spell) {
+ errmsg = did_set_spelllang(wp);
+ break;
+ }
+ }
+ }
+
+ return errmsg;
+}
+
/*
* Set curbuf->b_cap_prog to the regexp program for 'spellcapcheck'.
* Return error message when failed, NULL when OK.
@@ -5494,6 +5524,7 @@ void buf_copy_options(buf_T *buf, int flags)
buf->b_p_et = p_et;
buf->b_p_fixeol = p_fixeol;
buf->b_p_et_nobin = p_et_nobin;
+ buf->b_p_et_nopaste = p_et_nopaste;
buf->b_p_ml = p_ml;
buf->b_p_ml_nobin = p_ml_nobin;
buf->b_p_inf = p_inf;
@@ -6151,6 +6182,7 @@ static void paste_option_changed(void)
{
static int old_p_paste = FALSE;
static int save_sm = 0;
+ static int save_sta = 0;
static int save_ru = 0;
static int save_ri = 0;
static int save_hkmap = 0;
@@ -6167,40 +6199,44 @@ static void paste_option_changed(void)
buf->b_p_wm_nopaste = buf->b_p_wm;
buf->b_p_sts_nopaste = buf->b_p_sts;
buf->b_p_ai_nopaste = buf->b_p_ai;
+ buf->b_p_et_nopaste = buf->b_p_et;
}
- /* save global options */
+ // save global options
save_sm = p_sm;
+ save_sta = p_sta;
save_ru = p_ru;
save_ri = p_ri;
save_hkmap = p_hkmap;
- /* save global values for local buffer options */
+ // save global values for local buffer options
+ p_ai_nopaste = p_ai;
+ p_et_nopaste = p_et;
+ p_sts_nopaste = p_sts;
p_tw_nopaste = p_tw;
p_wm_nopaste = p_wm;
- p_sts_nopaste = p_sts;
- p_ai_nopaste = p_ai;
}
- /*
- * Always set the option values, also when 'paste' is set when it is
- * already on.
- */
- /* set options for each buffer */
+ // Always set the option values, also when 'paste' is set when it is
+ // already on.
+ // set options for each buffer
FOR_ALL_BUFFERS(buf) {
- buf->b_p_tw = 0; /* textwidth is 0 */
- buf->b_p_wm = 0; /* wrapmargin is 0 */
- buf->b_p_sts = 0; /* softtabstop is 0 */
- buf->b_p_ai = 0; /* no auto-indent */
- }
-
- /* set global options */
- p_sm = 0; /* no showmatch */
- if (p_ru)
- status_redraw_all(); /* redraw to remove the ruler */
- p_ru = 0; /* no ruler */
- p_ri = 0; /* no reverse insert */
- p_hkmap = 0; /* no Hebrew keyboard */
- /* set global values for local buffer options */
+ buf->b_p_tw = 0; // textwidth is 0
+ buf->b_p_wm = 0; // wrapmargin is 0
+ buf->b_p_sts = 0; // softtabstop is 0
+ buf->b_p_ai = 0; // no auto-indent
+ buf->b_p_et = 0; // no expandtab
+ }
+
+ // set global options
+ p_sm = 0; // no showmatch
+ p_sta = 0; // no smarttab
+ if (p_ru) {
+ status_redraw_all(); // redraw to remove the ruler
+ }
+ p_ru = 0; // no ruler
+ p_ri = 0; // no reverse insert
+ p_hkmap = 0; // no Hebrew keyboard
+ // set global values for local buffer options
p_tw = 0;
p_wm = 0;
p_sts = 0;
@@ -6216,20 +6252,24 @@ static void paste_option_changed(void)
buf->b_p_wm = buf->b_p_wm_nopaste;
buf->b_p_sts = buf->b_p_sts_nopaste;
buf->b_p_ai = buf->b_p_ai_nopaste;
+ buf->b_p_et = buf->b_p_et_nopaste;
}
/* restore global options */
p_sm = save_sm;
- if (p_ru != save_ru)
- status_redraw_all(); /* redraw to draw the ruler */
+ p_sta = save_sta;
+ if (p_ru != save_ru) {
+ status_redraw_all(); // redraw to draw the ruler
+ }
p_ru = save_ru;
p_ri = save_ri;
p_hkmap = save_hkmap;
- /* set global values for local buffer options */
+ // set global values for local buffer options
+ p_ai = p_ai_nopaste;
+ p_et = p_et_nopaste;
+ p_sts = p_sts_nopaste;
p_tw = p_tw_nopaste;
p_wm = p_wm_nopaste;
- p_sts = p_sts_nopaste;
- p_ai = p_ai_nopaste;
}
old_p_paste = p_paste;
diff --git a/src/nvim/option_defs.h b/src/nvim/option_defs.h
index 7a837de45c..10706a0753 100644
--- a/src/nvim/option_defs.h
+++ b/src/nvim/option_defs.h
@@ -209,44 +209,58 @@
#define COM_ALL "nbsmexflrO" /* all flags for 'comments' option */
#define COM_MAX_LEN 50 /* maximum length of a part */
-/* flags for 'statusline' option */
-#define STL_FILEPATH 'f' /* path of file in buffer */
-#define STL_FULLPATH 'F' /* full path of file in buffer */
-#define STL_FILENAME 't' /* last part (tail) of file path */
-#define STL_COLUMN 'c' /* column og cursor*/
-#define STL_VIRTCOL 'v' /* virtual column */
-#define STL_VIRTCOL_ALT 'V' /* - with 'if different' display */
-#define STL_LINE 'l' /* line number of cursor */
-#define STL_NUMLINES 'L' /* number of lines in buffer */
-#define STL_BUFNO 'n' /* current buffer number */
-#define STL_KEYMAP 'k' /* 'keymap' when active */
-#define STL_OFFSET 'o' /* offset of character under cursor*/
-#define STL_OFFSET_X 'O' /* - in hexadecimal */
-#define STL_BYTEVAL 'b' /* byte value of character */
-#define STL_BYTEVAL_X 'B' /* - in hexadecimal */
-#define STL_ROFLAG 'r' /* readonly flag */
-#define STL_ROFLAG_ALT 'R' /* - other display */
-#define STL_HELPFLAG 'h' /* window is showing a help file */
-#define STL_HELPFLAG_ALT 'H' /* - other display */
-#define STL_FILETYPE 'y' /* 'filetype' */
-#define STL_FILETYPE_ALT 'Y' /* - other display */
-#define STL_PREVIEWFLAG 'w' /* window is showing the preview buf */
-#define STL_PREVIEWFLAG_ALT 'W' /* - other display */
-#define STL_MODIFIED 'm' /* modified flag */
-#define STL_MODIFIED_ALT 'M' /* - other display */
-#define STL_QUICKFIX 'q' /* quickfix window description */
-#define STL_PERCENTAGE 'p' /* percentage through file */
-#define STL_ALTPERCENT 'P' /* percentage as TOP BOT ALL or NN% */
-#define STL_ARGLISTSTAT 'a' /* argument list status as (x of y) */
-#define STL_PAGENUM 'N' /* page number (when printing)*/
-#define STL_VIM_EXPR '{' /* start of expression to substitute */
-#define STL_MIDDLEMARK '=' /* separation between left and right */
-#define STL_TRUNCMARK '<' /* truncation mark if line is too long*/
-#define STL_USER_HL '*' /* highlight from (User)1..9 or 0 */
-#define STL_HIGHLIGHT '#' /* highlight name */
-#define STL_TABPAGENR 'T' /* tab page label nr */
-#define STL_TABCLOSENR 'X' /* tab page close nr */
-#define STL_ALL ((char_u *) "fFtcvVlLknoObBrRhHmYyWwMqpPaN{#")
+/// 'statusline' option flags
+enum {
+ STL_FILEPATH = 'f', ///< Path of file in buffer.
+ STL_FULLPATH = 'F', ///< Full path of file in buffer.
+ STL_FILENAME = 't', ///< Last part (tail) of file path.
+ STL_COLUMN = 'c', ///< Column og cursor.
+ STL_VIRTCOL = 'v', ///< Virtual column.
+ STL_VIRTCOL_ALT = 'V', ///< - with 'if different' display.
+ STL_LINE = 'l', ///< Line number of cursor.
+ STL_NUMLINES = 'L', ///< Number of lines in buffer.
+ STL_BUFNO = 'n', ///< Current buffer number.
+ STL_KEYMAP = 'k', ///< 'keymap' when active.
+ STL_OFFSET = 'o', ///< Offset of character under cursor.
+ STL_OFFSET_X = 'O', ///< - in hexadecimal.
+ STL_BYTEVAL = 'b', ///< Byte value of character.
+ STL_BYTEVAL_X = 'B', ///< - in hexadecimal.
+ STL_ROFLAG = 'r', ///< Readonly flag.
+ STL_ROFLAG_ALT = 'R', ///< - other display.
+ STL_HELPFLAG = 'h', ///< Window is showing a help file.
+ STL_HELPFLAG_ALT = 'H', ///< - other display.
+ STL_FILETYPE = 'y', ///< 'filetype'.
+ STL_FILETYPE_ALT = 'Y', ///< - other display.
+ STL_PREVIEWFLAG = 'w', ///< Window is showing the preview buf.
+ STL_PREVIEWFLAG_ALT = 'W', ///< - other display.
+ STL_MODIFIED = 'm', ///< Modified flag.
+ STL_MODIFIED_ALT = 'M', ///< - other display.
+ STL_QUICKFIX = 'q', ///< Quickfix window description.
+ STL_PERCENTAGE = 'p', ///< Percentage through file.
+ STL_ALTPERCENT = 'P', ///< Percentage as TOP BOT ALL or NN%.
+ STL_ARGLISTSTAT = 'a', ///< Argument list status as (x of y).
+ STL_PAGENUM = 'N', ///< Page number (when printing).
+ STL_VIM_EXPR = '{', ///< Start of expression to substitute.
+ STL_MIDDLEMARK = '=', ///< Separation between left and right.
+ STL_TRUNCMARK = '<', ///< Truncation mark if line is too long.
+ STL_USER_HL = '*', ///< Highlight from (User)1..9 or 0.
+ STL_HIGHLIGHT = '#', ///< Highlight name.
+ STL_TABPAGENR = 'T', ///< Tab page label nr.
+ STL_TABCLOSENR = 'X', ///< Tab page close nr.
+ STL_CLICK_FUNC = '@', ///< Click region start.
+};
+/// C string containing all 'statusline' option flags
+#define STL_ALL ((char_u[]) { \
+ STL_FILEPATH, STL_FULLPATH, STL_FILENAME, STL_COLUMN, STL_VIRTCOL, \
+ STL_VIRTCOL_ALT, STL_LINE, STL_NUMLINES, STL_BUFNO, STL_KEYMAP, STL_OFFSET, \
+ STL_OFFSET_X, STL_BYTEVAL, STL_BYTEVAL_X, STL_ROFLAG, STL_ROFLAG_ALT, \
+ STL_HELPFLAG, STL_HELPFLAG_ALT, STL_FILETYPE, STL_FILETYPE_ALT, \
+ STL_PREVIEWFLAG, STL_PREVIEWFLAG_ALT, STL_MODIFIED, STL_MODIFIED_ALT, \
+ STL_QUICKFIX, STL_PERCENTAGE, STL_ALTPERCENT, STL_ARGLISTSTAT, STL_PAGENUM, \
+ STL_VIM_EXPR, STL_MIDDLEMARK, STL_TRUNCMARK, STL_USER_HL, STL_HIGHLIGHT, \
+ STL_TABPAGENR, STL_TABCLOSENR, STL_CLICK_FUNC, \
+ 0, \
+})
/* flags used for parsed 'wildmode' */
#define WIM_FULL 1
@@ -557,41 +571,43 @@ EXTERN char_u *p_su; // 'suffixes'
EXTERN char_u *p_swb; // 'switchbuf'
EXTERN unsigned swb_flags;
#ifdef IN_OPTION_C
-static char *(p_swb_values[]) = {"useopen", "usetab", "split", "newtab", NULL};
+static char *(p_swb_values[]) =
+ { "useopen", "usetab", "split", "newtab", "vsplit", NULL };
#endif
#define SWB_USEOPEN 0x001
#define SWB_USETAB 0x002
#define SWB_SPLIT 0x004
#define SWB_NEWTAB 0x008
-EXTERN int p_tbs; /* 'tagbsearch' */
-EXTERN long p_tl; /* 'taglength' */
-EXTERN int p_tr; /* 'tagrelative' */
-EXTERN char_u *p_tags; /* 'tags' */
-EXTERN int p_tgst; /* 'tagstack' */
-EXTERN int p_tbidi; /* 'termbidi' */
-EXTERN int p_terse; /* 'terse' */
-EXTERN int p_to; /* 'tildeop' */
-EXTERN int p_timeout; /* 'timeout' */
-EXTERN long p_tm; /* 'timeoutlen' */
-EXTERN int p_title; /* 'title' */
-EXTERN long p_titlelen; /* 'titlelen' */
-EXTERN char_u *p_titleold; /* 'titleold' */
-EXTERN char_u *p_titlestring; /* 'titlestring' */
-EXTERN char_u *p_tsr; /* 'thesaurus' */
-EXTERN int p_ttimeout; /* 'ttimeout' */
-EXTERN long p_ttm; /* 'ttimeoutlen' */
-EXTERN char_u *p_udir; /* 'undodir' */
-EXTERN long p_ul; /* 'undolevels' */
-EXTERN long p_ur; /* 'undoreload' */
-EXTERN long p_uc; /* 'updatecount' */
-EXTERN long p_ut; /* 'updatetime' */
-EXTERN char_u *p_fcs; /* 'fillchar' */
-EXTERN char_u *p_shada; /* 'shada' */
-EXTERN char_u *p_vdir; /* 'viewdir' */
-EXTERN char_u *p_vop; /* 'viewoptions' */
-EXTERN unsigned vop_flags; /* uses SSOP_ flags */
-EXTERN int p_vb; /* 'visualbell' */
-EXTERN char_u *p_ve; /* 'virtualedit' */
+#define SWB_VSPLIT 0x010
+EXTERN int p_tbs; ///< 'tagbsearch'
+EXTERN long p_tl; ///< 'taglength'
+EXTERN int p_tr; ///< 'tagrelative'
+EXTERN char_u *p_tags; ///< 'tags'
+EXTERN int p_tgst; ///< 'tagstack'
+EXTERN int p_tbidi; ///< 'termbidi'
+EXTERN int p_terse; ///< 'terse'
+EXTERN int p_to; ///< 'tildeop'
+EXTERN int p_timeout; ///< 'timeout'
+EXTERN long p_tm; ///< 'timeoutlen'
+EXTERN int p_title; ///< 'title'
+EXTERN long p_titlelen; ///< 'titlelen'
+EXTERN char_u *p_titleold; ///< 'titleold'
+EXTERN char_u *p_titlestring; ///< 'titlestring'
+EXTERN char_u *p_tsr; ///< 'thesaurus'
+EXTERN int p_ttimeout; ///< 'ttimeout'
+EXTERN long p_ttm; ///< 'ttimeoutlen'
+EXTERN char_u *p_udir; ///< 'undodir'
+EXTERN long p_ul; ///< 'undolevels'
+EXTERN long p_ur; ///< 'undoreload'
+EXTERN long p_uc; ///< 'updatecount'
+EXTERN long p_ut; ///< 'updatetime'
+EXTERN char_u *p_fcs; ///< 'fillchar'
+EXTERN char_u *p_shada; ///< 'shada'
+EXTERN char_u *p_vdir; ///< 'viewdir'
+EXTERN char_u *p_vop; ///< 'viewoptions'
+EXTERN unsigned vop_flags; ///< uses SSOP_ flags
+EXTERN int p_vb; ///< 'visualbell'
+EXTERN char_u *p_ve; ///< 'virtualedit'
EXTERN unsigned ve_flags;
# ifdef IN_OPTION_C
static char *(p_ve_values[]) = {"block", "insert", "all", "onemore", NULL};
diff --git a/src/nvim/options.lua b/src/nvim/options.lua
index 3dd37cb5dc..df77c374ec 100644
--- a/src/nvim/options.lua
+++ b/src/nvim/options.lua
@@ -15,7 +15,7 @@
-- }
-- }
-- types: bool, number, string
--- lists: (nil), comma, flags, flagscomma
+-- lists: (nil), comma, onecomma, flags, flagscomma
-- scopes: global, buffer, window
-- redraw options: statuslines, current_window, current_buffer, all_windows,
-- everything, curswant
@@ -133,7 +133,7 @@ return {
},
{
full_name='backspace', abbreviation='bs',
- type='string', list='comma', scope={'global'},
+ type='string', list='onecomma', scope={'global'},
deny_duplicates=true,
vim=true,
varname='p_bs',
@@ -149,7 +149,7 @@ return {
},
{
full_name='backupcopy', abbreviation='bkc',
- type='string', list='comma', scope={'global', 'buffer'},
+ type='string', list='onecomma', scope={'global', 'buffer'},
deny_duplicates=true,
vim=true,
varname='p_bkc',
@@ -161,7 +161,7 @@ return {
},
{
full_name='backupdir', abbreviation='bdir',
- type='string', list='comma', scope={'global'},
+ type='string', list='onecomma', scope={'global'},
deny_duplicates=true,
secure=true,
vi_def=true,
@@ -179,7 +179,7 @@ return {
},
{
full_name='backupskip', abbreviation='bsk',
- type='string', list='comma', scope={'global'},
+ type='string', list='onecomma', scope={'global'},
vi_def=true,
varname='p_bsk',
defaults={if_true={vi=""}}
@@ -227,7 +227,7 @@ return {
},
{
full_name='breakindentopt', abbreviation='briopt',
- type='string', list='comma', scope={'window'},
+ type='string', list='onecomma', scope={'window'},
deny_duplicates=true,
vi_def=true,
alloced=true,
@@ -268,7 +268,7 @@ return {
},
{
full_name='casemap', abbreviation='cmp',
- type='string', list='comma', scope={'global'},
+ type='string', list='onecomma', scope={'global'},
deny_duplicates=true,
vi_def=true,
varname='p_cmp',
@@ -307,7 +307,7 @@ return {
},
{
full_name='cinkeys', abbreviation='cink',
- type='string', list='comma', scope={'buffer'},
+ type='string', list='onecomma', scope={'buffer'},
deny_duplicates=true,
vi_def=true,
alloced=true,
@@ -316,7 +316,7 @@ return {
},
{
full_name='cinoptions', abbreviation='cino',
- type='string', list='comma', scope={'buffer'},
+ type='string', list='onecomma', scope={'buffer'},
deny_duplicates=true,
vi_def=true,
alloced=true,
@@ -325,7 +325,7 @@ return {
},
{
full_name='cinwords', abbreviation='cinw',
- type='string', list='comma', scope={'buffer'},
+ type='string', list='onecomma', scope={'buffer'},
deny_duplicates=true,
vi_def=true,
alloced=true,
@@ -334,7 +334,7 @@ return {
},
{
full_name='clipboard', abbreviation='cb',
- type='string', list='comma', scope={'global'},
+ type='string', list='onecomma', scope={'global'},
deny_duplicates=true,
vi_def=true,
varname='p_cb',
@@ -357,7 +357,7 @@ return {
},
{
full_name='colorcolumn', abbreviation='cc',
- type='string', list='comma', scope={'window'},
+ type='string', list='onecomma', scope={'window'},
deny_duplicates=true,
vi_def=true,
redraw={'current_window'},
@@ -375,7 +375,7 @@ return {
},
{
full_name='comments', abbreviation='com',
- type='string', list='comma', scope={'buffer'},
+ type='string', list='onecomma', scope={'buffer'},
deny_duplicates=true,
vi_def=true,
alloced=true,
@@ -403,7 +403,7 @@ return {
},
{
full_name='complete', abbreviation='cpt',
- type='string', list='comma', scope={'buffer'},
+ type='string', list='onecomma', scope={'buffer'},
deny_duplicates=true,
alloced=true,
varname='p_cpt',
@@ -435,7 +435,7 @@ return {
},
{
full_name='completeopt', abbreviation='cot',
- type='string', list='comma', scope={'global'},
+ type='string', list='onecomma', scope={'global'},
deny_duplicates=true,
vi_def=true,
varname='p_cot',
@@ -483,7 +483,7 @@ return {
},
{
full_name='cscopequickfix', abbreviation='csqf',
- type='string', list='comma', scope={'global'},
+ type='string', list='onecomma', scope={'global'},
deny_duplicates=true,
vi_def=true,
varname='p_csqf',
@@ -568,7 +568,7 @@ return {
},
{
full_name='dictionary', abbreviation='dict',
- type='string', list='comma', scope={'global', 'buffer'},
+ type='string', list='onecomma', scope={'global', 'buffer'},
deny_duplicates=true,
vi_def=true,
expand=true,
@@ -594,7 +594,7 @@ return {
},
{
full_name='diffopt', abbreviation='dip',
- type='string', list='comma', scope={'global'},
+ type='string', list='onecomma', scope={'global'},
deny_duplicates=true,
vi_def=true,
alloced=true,
@@ -612,7 +612,7 @@ return {
},
{
full_name='directory', abbreviation='dir',
- type='string', list='comma', scope={'global'},
+ type='string', list='onecomma', scope={'global'},
deny_duplicates=true,
secure=true,
vi_def=true,
@@ -622,7 +622,7 @@ return {
},
{
full_name='display', abbreviation='dy',
- type='string', list='comma', scope={'global'},
+ type='string', list='onecomma', scope={'global'},
deny_duplicates=true,
vim=true,
redraw={'all_windows'},
@@ -696,7 +696,7 @@ return {
},
{
full_name='errorformat', abbreviation='efm',
- type='string', list='comma', scope={'global', 'buffer'},
+ type='string', list='onecomma', scope={'global', 'buffer'},
deny_duplicates=true,
vi_def=true,
varname='p_efm',
@@ -711,7 +711,7 @@ return {
},
{
full_name='eventignore', abbreviation='ei',
- type='string', list='comma', scope={'global'},
+ type='string', list='onecomma', scope={'global'},
deny_duplicates=true,
vi_def=true,
varname='p_ei',
@@ -745,7 +745,7 @@ return {
},
{
full_name='fileencodings', abbreviation='fencs',
- type='string', list='comma', scope={'global'},
+ type='string', list='onecomma', scope={'global'},
vi_def=true,
varname='p_fencs',
defaults={if_true={vi="ucs-bom,utf-8,default,latin1"}}
@@ -762,7 +762,7 @@ return {
},
{
full_name='fileformats', abbreviation='ffs',
- type='string', list='comma', scope={'global'},
+ type='string', list='onecomma', scope={'global'},
deny_duplicates=true,
vim=true,
varname='p_ffs',
@@ -791,7 +791,7 @@ return {
},
{
full_name='fillchars', abbreviation='fcs',
- type='string', list='comma', scope={'global'},
+ type='string', list='onecomma', scope={'global'},
deny_duplicates=true,
vi_def=true,
redraw={'all_windows'},
@@ -815,7 +815,7 @@ return {
},
{
full_name='foldclose', abbreviation='fcl',
- type='string', list='comma', scope={'global'},
+ type='string', list='onecomma', scope={'global'},
deny_duplicates=true,
vi_def=true,
redraw={'current_window'},
@@ -871,7 +871,7 @@ return {
},
{
full_name='foldmarker', abbreviation='fmr',
- type='string', list='comma', scope={'window'},
+ type='string', list='onecomma', scope={'window'},
deny_duplicates=true,
vi_def=true,
vim=true,
@@ -904,7 +904,7 @@ return {
},
{
full_name='foldopen', abbreviation='fdo',
- type='string', list='comma', scope={'global'},
+ type='string', list='onecomma', scope={'global'},
deny_duplicates=true,
vi_def=true,
redraw={'curswant'},
@@ -972,7 +972,7 @@ return {
},
{
full_name='grepformat', abbreviation='gfm',
- type='string', list='comma', scope={'global'},
+ type='string', list='onecomma', scope={'global'},
deny_duplicates=true,
vi_def=true,
varname='p_gefm',
@@ -995,7 +995,7 @@ return {
},
{
full_name='guicursor', abbreviation='gcr',
- type='string', list='comma', scope={'global'},
+ type='string', list='onecomma', scope={'global'},
deny_duplicates=true,
vi_def=true,
varname='p_guicursor',
@@ -1003,7 +1003,7 @@ return {
},
{
full_name='guifont', abbreviation='gfn',
- type='string', list='comma', scope={'global'},
+ type='string', list='onecomma', scope={'global'},
deny_duplicates=true,
vi_def=true,
redraw={'everything'},
@@ -1011,14 +1011,14 @@ return {
},
{
full_name='guifontset', abbreviation='gfs',
- type='string', list='comma', scope={'global'},
+ type='string', list='onecomma', scope={'global'},
vi_def=true,
redraw={'everything'},
enable_if=false,
},
{
full_name='guifontwide', abbreviation='gfw',
- type='string', list='comma', scope={'global'},
+ type='string', list='onecomma', scope={'global'},
deny_duplicates=true,
vi_def=true,
redraw={'everything'},
@@ -1070,7 +1070,7 @@ return {
},
{
full_name='helplang', abbreviation='hlg',
- type='string', list='comma', scope={'global'},
+ type='string', list='onecomma', scope={'global'},
vi_def=true,
varname='p_hlg',
defaults={if_true={vi=""}}
@@ -1084,7 +1084,7 @@ return {
},
{
full_name='highlight', abbreviation='hl',
- type='string', list='comma', scope={'global'},
+ type='string', list='onecomma', scope={'global'},
deny_duplicates=true,
vi_def=true,
redraw={'everything'},
@@ -1213,7 +1213,7 @@ return {
},
{
full_name='indentkeys', abbreviation='indk',
- type='string', list='comma', scope={'buffer'},
+ type='string', list='onecomma', scope={'buffer'},
deny_duplicates=true,
vi_def=true,
alloced=true,
@@ -1297,7 +1297,7 @@ return {
},
{
full_name='keymodel', abbreviation='km',
- type='string', list='comma', scope={'global'},
+ type='string', list='onecomma', scope={'global'},
deny_duplicates=true,
vi_def=true,
varname='p_km',
@@ -1316,7 +1316,7 @@ return {
},
{
full_name='langmap', abbreviation='lmap',
- type='string', list='comma', scope={'global'},
+ type='string', list='onecomma', scope={'global'},
deny_duplicates=true,
secure=true,
vi_def=true,
@@ -1385,7 +1385,7 @@ return {
},
{
full_name='lispwords', abbreviation='lw',
- type='string', list='comma', scope={'global', 'buffer'},
+ type='string', list='onecomma', scope={'global', 'buffer'},
deny_duplicates=true,
vi_def=true,
varname='p_lispwords', pv_name='p_lw',
@@ -1400,7 +1400,7 @@ return {
},
{
full_name='listchars', abbreviation='lcs',
- type='string', list='comma', scope={'global'},
+ type='string', list='onecomma', scope={'global'},
deny_duplicates=true,
vim=true,
redraw={'all_windows'},
@@ -1441,7 +1441,7 @@ return {
},
{
full_name='matchpairs', abbreviation='mps',
- type='string', list='comma', scope={'buffer'},
+ type='string', list='onecomma', scope={'buffer'},
deny_duplicates=true,
vi_def=true,
alloced=true,
@@ -1581,7 +1581,7 @@ return {
},
{
full_name='mouseshape', abbreviation='mouses',
- type='string', list='comma', scope={'global'},
+ type='string', list='onecomma', scope={'global'},
deny_duplicates=true,
vi_def=true,
enable_if=false,
@@ -1595,7 +1595,7 @@ return {
},
{
full_name='nrformats', abbreviation='nf',
- type='string', list='comma', scope={'buffer'},
+ type='string', list='onecomma', scope={'buffer'},
deny_duplicates=true,
alloced=true,
varname='p_nf',
@@ -1762,7 +1762,7 @@ return {
},
{
full_name='printoptions', abbreviation='popt',
- type='string', list='comma', scope={'global'},
+ type='string', list='onecomma', scope={'global'},
deny_duplicates=true,
vi_def=true,
varname='p_popt',
@@ -1877,7 +1877,7 @@ return {
},
{
full_name='runtimepath', abbreviation='rtp',
- type='string', list='comma', scope={'global'},
+ type='string', list='onecomma', scope={'global'},
deny_duplicates=true,
secure=true,
vi_def=true,
@@ -1919,7 +1919,7 @@ return {
},
{
full_name='scrollopt', abbreviation='sbo',
- type='string', list='comma', scope={'global'},
+ type='string', list='onecomma', scope={'global'},
deny_duplicates=true,
vi_def=true,
varname='p_sbo',
@@ -1949,7 +1949,7 @@ return {
},
{
full_name='selectmode', abbreviation='slm',
- type='string', list='comma', scope={'global'},
+ type='string', list='onecomma', scope={'global'},
deny_duplicates=true,
vi_def=true,
varname='p_slm',
@@ -1957,7 +1957,7 @@ return {
},
{
full_name='sessionoptions', abbreviation='ssop',
- type='string', list='comma', scope={'global'},
+ type='string', list='onecomma', scope={'global'},
deny_duplicates=true,
vim=true,
varname='p_ssop',
@@ -1968,7 +1968,7 @@ return {
},
{
full_name='shada', abbreviation='sd',
- type='string', list='comma', scope={'global'},
+ type='string', list='onecomma', scope={'global'},
deny_duplicates=true,
secure=true,
varname='p_shada',
@@ -2192,7 +2192,7 @@ return {
},
{
full_name='spellfile', abbreviation='spf',
- type='string', list='comma', scope={'buffer'},
+ type='string', list='onecomma', scope={'buffer'},
secure=true,
vi_def=true,
alloced=true,
@@ -2202,7 +2202,7 @@ return {
},
{
full_name='spelllang', abbreviation='spl',
- type='string', list='comma', scope={'buffer'},
+ type='string', list='onecomma', scope={'buffer'},
vi_def=true,
alloced=true,
expand=true,
@@ -2212,7 +2212,7 @@ return {
},
{
full_name='spellsuggest', abbreviation='sps',
- type='string', list='comma', scope={'global'},
+ type='string', list='onecomma', scope={'global'},
secure=true,
vi_def=true,
expand=true,
@@ -2252,7 +2252,7 @@ return {
},
{
full_name='suffixes', abbreviation='su',
- type='string', list='comma', scope={'global'},
+ type='string', list='onecomma', scope={'global'},
deny_duplicates=true,
vi_def=true,
varname='p_su',
@@ -2260,7 +2260,7 @@ return {
},
{
full_name='suffixesadd', abbreviation='sua',
- type='string', list='comma', scope={'buffer'},
+ type='string', list='onecomma', scope={'buffer'},
deny_duplicates=true,
vi_def=true,
alloced=true,
@@ -2277,7 +2277,7 @@ return {
},
{
full_name='switchbuf', abbreviation='swb',
- type='string', list='comma', scope={'global'},
+ type='string', list='onecomma', scope={'global'},
deny_duplicates=true,
vi_def=true,
varname='p_swb',
@@ -2347,7 +2347,7 @@ return {
},
{
full_name='tags', abbreviation='tag',
- type='string', list='comma', scope={'global', 'buffer'},
+ type='string', list='onecomma', scope={'global', 'buffer'},
deny_duplicates=true,
vi_def=true,
expand=true,
@@ -2393,7 +2393,7 @@ return {
},
{
full_name='thesaurus', abbreviation='tsr',
- type='string', list='comma', scope={'global', 'buffer'},
+ type='string', list='onecomma', scope={'global', 'buffer'},
deny_duplicates=true,
vi_def=true,
expand=true,
@@ -2478,7 +2478,7 @@ return {
},
{
full_name='undodir', abbreviation='udir',
- type='string', list='comma', scope={'global'},
+ type='string', list='onecomma', scope={'global'},
deny_duplicates=true,
secure=true,
vi_def=true,
@@ -2549,7 +2549,7 @@ return {
},
{
full_name='viewoptions', abbreviation='vop',
- type='string', list='comma', scope={'global'},
+ type='string', list='onecomma', scope={'global'},
deny_duplicates=true,
vi_def=true,
varname='p_vop',
@@ -2557,7 +2557,7 @@ return {
},
{
full_name='viminfo', abbreviation='vi',
- type='string', list='comma', scope={'global'},
+ type='string', list='onecomma', scope={'global'},
deny_duplicates=true,
secure=true,
varname='p_shada',
@@ -2565,7 +2565,7 @@ return {
},
{
full_name='virtualedit', abbreviation='ve',
- type='string', list='comma', scope={'global'},
+ type='string', list='onecomma', scope={'global'},
deny_duplicates=true,
vi_def=true,
vim=true,
@@ -2610,7 +2610,7 @@ return {
},
{
full_name='wildignore', abbreviation='wig',
- type='string', list='comma', scope={'global'},
+ type='string', list='onecomma', scope={'global'},
deny_duplicates=true,
vi_def=true,
varname='p_wig',
@@ -2632,7 +2632,7 @@ return {
},
{
full_name='wildmode', abbreviation='wim',
- type='string', list='comma', scope={'global'},
+ type='string', list='onecomma', scope={'global'},
deny_duplicates=true,
vim=true,
varname='p_wim',
diff --git a/src/nvim/os/env.c b/src/nvim/os/env.c
index c1804067e9..41ce8ddbc2 100644
--- a/src/nvim/os/env.c
+++ b/src/nvim/os/env.c
@@ -262,8 +262,25 @@ void expand_env_esc(char_u *srcp, char_u *dst, int dstlen, bool esc, bool one,
startstr_len = (int)STRLEN(startstr);
src = skipwhite(srcp);
- --dstlen; // leave one char space for "\,"
+ dstlen--; // leave one char space for "\,"
while (*src && dstlen > 0) {
+ // Skip over `=expr`.
+ if (src[0] == '`' && src[1] == '=') {
+ var = src;
+ src += 2;
+ (void)skip_expr(&src);
+ if (*src == '`') {
+ src++;
+ }
+ size_t len = (size_t)(src - var);
+ if (len > (size_t)dstlen) {
+ len = (size_t)dstlen;
+ }
+ memcpy((char *)dst, (char *)var, len);
+ dst += len;
+ dstlen -= (int)len;
+ continue;
+ }
copy_char = true;
if ((*src == '$') || (*src == '~' && at_start)) {
mustfree = false;
diff --git a/src/nvim/os/fs.c b/src/nvim/os/fs.c
index 21f0fc6f41..2e671653ed 100644
--- a/src/nvim/os/fs.c
+++ b/src/nvim/os/fs.c
@@ -146,6 +146,16 @@ static bool is_executable_in_path(const char_u *name, char_u **abspath)
}
size_t buf_len = STRLEN(name) + STRLEN(path) + 2;
+
+#ifdef WIN32
+ const char *pathext = os_getenv("PATHEXT");
+ if (!pathext) {
+ pathext = ".com;.exe;.bat;.cmd";
+ }
+
+ buf_len += STRLEN(pathext);
+#endif
+
char_u *buf = xmalloc(buf_len);
// Walk through all entries in $PATH to check if "name" exists there and
@@ -169,6 +179,38 @@ static bool is_executable_in_path(const char_u *name, char_u **abspath)
return true;
}
+#ifdef WIN32
+ // Try appending file extensions from $PATHEXT to the name.
+ char *buf_end = xstrchrnul((char *)buf, '\0');
+ for (const char *ext = pathext; *ext; ext++) {
+ // Skip the extension if there is no suffix after a '.'.
+ if (ext[0] == '.' && (ext[1] == '\0' || ext[1] == ';')) {
+ *ext++;
+
+ continue;
+ }
+
+ const char *ext_end = xstrchrnul(ext, ENV_SEPCHAR);
+ STRLCPY(buf_end, ext, ext_end - ext + 1);
+
+ if (is_executable(buf)) {
+ // Check if the caller asked for a copy of the path.
+ if (abspath != NULL) {
+ *abspath = save_absolute_path(buf);
+ }
+
+ xfree(buf);
+
+ return true;
+ }
+
+ if (*ext_end != ENV_SEPCHAR) {
+ break;
+ }
+ ext = ext_end;
+ }
+#endif
+
if (*e != ENV_SEPCHAR) {
// End of $PATH without finding any executable called name.
xfree(buf);
diff --git a/src/nvim/os/input.c b/src/nvim/os/input.c
index e632544856..f317fd6b5a 100644
--- a/src/nvim/os/input.c
+++ b/src/nvim/os/input.c
@@ -250,6 +250,14 @@ static unsigned int handle_mouse_event(char **ptr, uint8_t *buf,
int col, row, advance;
if (sscanf(*ptr, "<%d,%d>%n", &col, &row, &advance) != EOF && advance) {
if (col >= 0 && row >= 0) {
+ // Make sure the mouse position is valid. Some terminals may
+ // return weird values.
+ if (col >= Columns) {
+ col = (int)Columns - 1;
+ }
+ if (row >= Rows) {
+ row = (int)Rows - 1;
+ }
mouse_row = row;
mouse_col = col;
}
diff --git a/src/nvim/os/unix_defs.h b/src/nvim/os/unix_defs.h
index 78fc9331d1..690a39c3cd 100644
--- a/src/nvim/os/unix_defs.h
+++ b/src/nvim/os/unix_defs.h
@@ -2,7 +2,7 @@
#define NVIM_OS_UNIX_DEFS_H
// Windows doesn't have unistd.h, so we include it here to avoid numerous
-// instances of `#ifdef HAVE_UNISTD_H'.
+// instances of `#ifdef WIN32'.
#include <unistd.h>
// POSIX.1-2008 says that NAME_MAX should be in here
diff --git a/src/nvim/os/win_defs.h b/src/nvim/os/win_defs.h
index ba96347a12..242d355f77 100644
--- a/src/nvim/os/win_defs.h
+++ b/src/nvim/os/win_defs.h
@@ -3,6 +3,7 @@
#include <windows.h>
#include <sys/stat.h>
+#include <io.h>
#include <stdio.h>
// Windows does not have S_IFLNK but libuv defines it
diff --git a/src/nvim/path.c b/src/nvim/path.c
index 5ac3d07f67..5cd93ab811 100644
--- a/src/nvim/path.c
+++ b/src/nvim/path.c
@@ -556,8 +556,9 @@ static size_t do_path_expand(garray_T *gap, const char_u *path,
return 0;
}
- /* make room for file name */
- buf = xmalloc(STRLEN(path) + BASENAMELEN + 5);
+ // 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.
@@ -681,11 +682,16 @@ static size_t do_path_expand(garray_T *gap, const char_u *path,
/* remove backslashes for the remaining components only */
(void)do_path_expand(gap, buf, len + 1, flags, false);
} else {
- /* no more wildcards, check if there is a match */
- /* remove backslashes for the remaining components only */
- if (*path_end != NUL)
+ FileInfo file_info;
+
+ // no more wildcards, check if there is a match
+ // remove backslashes for the remaining components only
+ if (*path_end != NUL) {
backslash_halve(buf + len + 1);
- if (os_file_exists(buf)) { /* add existing file */
+ }
+ // add existing file or symbolic link
+ if ((flags & EW_ALLLINKS) ? os_fileinfo_link((char *)buf, &file_info)
+ : os_file_exists(buf)) {
addfile(gap, buf, flags);
}
}
@@ -1153,12 +1159,17 @@ int gen_expand_wildcards(int num_pat, char_u **pat, int *num_file,
add_pat = -1;
p = pat[i];
- if (vim_backtick(p))
+ if (vim_backtick(p)) {
add_pat = expand_backtick(&ga, p, flags);
- else {
- /*
- * First expand environment variables, "~/" and "~user/".
- */
+ if (add_pat == -1) {
+ recursive = false;
+ FreeWild(ga.ga_len, (char_u **)ga.ga_data);
+ *num_file = 0;
+ *file = NULL;
+ return FAIL;
+ }
+ } else {
+ // First expand environment variables, "~/" and "~user/".
if (has_env_var(p) || *p == '~') {
p = expand_env_save_opt(p, true);
if (p == NULL)
@@ -1241,13 +1252,10 @@ static int vim_backtick(char_u *p)
return *p == '`' && *(p + 1) != NUL && *(p + STRLEN(p) - 1) == '`';
}
-/*
- * Expand an item in `backticks` by executing it as a command.
- * Currently only works when pat[] starts and ends with a `.
- * Returns number of file names found.
- */
-static int
-expand_backtick (
+// Expand an item in `backticks` by executing it as a command.
+// Currently only works when pat[] starts and ends with a `.
+// Returns number of file names found, -1 if an error is encountered.
+static int expand_backtick(
garray_T *gap,
char_u *pat,
int flags /* EW_* flags */
@@ -1268,8 +1276,9 @@ expand_backtick (
buffer = get_cmd_output(cmd, NULL,
(flags & EW_SILENT) ? kShellOptSilent : 0, NULL);
xfree(cmd);
- if (buffer == NULL)
- return 0;
+ if (buffer == NULL) {
+ return -1;
+ }
cmd = buffer;
while (*cmd != NUL) {
@@ -1294,26 +1303,28 @@ expand_backtick (
return cnt;
}
-/*
- * Add a file to a file list. Accepted flags:
- * EW_DIR add directories
- * EW_FILE add files
- * EW_EXEC add executable files
- * EW_NOTFOUND add even when it doesn't exist
- * EW_ADDSLASH add slash after directory name
- */
-void
-addfile (
+// Add a file to a file list. Accepted flags:
+// EW_DIR add directories
+// EW_FILE add files
+// EW_EXEC add executable files
+// EW_NOTFOUND add even when it doesn't exist
+// EW_ADDSLASH add slash after directory name
+// EW_ALLLINKS add symlink also when the referred file does not exist
+void addfile(
garray_T *gap,
char_u *f, /* filename */
int flags
)
{
bool isdir;
+ FileInfo file_info;
- /* if the file/dir doesn't exist, may not add it */
- if (!(flags & EW_NOTFOUND) && !os_file_exists(f))
+ // if the file/dir/link doesn't exist, may not add it
+ if (!(flags & EW_NOTFOUND) &&
+ ((flags & EW_ALLLINKS) ?
+ !os_fileinfo_link((char *)f, &file_info) : !os_file_exists(f))) {
return;
+ }
#ifdef FNAME_ILLEGAL
/* if the file/dir contains illegal characters, don't add it */
@@ -1768,19 +1779,20 @@ bool same_directory(char_u *f1, char_u *f2)
*/
int pathcmp(const char *p, const char *q, int maxlen)
{
- int i;
+ int i, j;
int c1, c2;
const char *s = NULL;
- for (i = 0; maxlen < 0 || i < maxlen; i += MB_PTR2LEN((char_u *)p + i)) {
+ for (i = 0, j = 0; maxlen < 0 || (i < maxlen && j < maxlen);) {
c1 = PTR2CHAR((char_u *)p + i);
- c2 = PTR2CHAR((char_u *)q + i);
+ c2 = PTR2CHAR((char_u *)q + j);
/* End of "p": check if "q" also ends or just has a slash. */
if (c1 == NUL) {
if (c2 == NUL) /* full match */
return 0;
s = q;
+ i = j;
break;
}
@@ -1804,9 +1816,13 @@ int pathcmp(const char *p, const char *q, int maxlen)
return p_fic ? vim_toupper(c1) - vim_toupper(c2)
: c1 - c2; /* no match */
}
+
+ i += MB_PTR2LEN((char_u *)p + i);
+ j += MB_PTR2LEN((char_u *)q + j);
}
- if (s == NULL) /* "i" ran into "maxlen" */
+ if (s == NULL) { // "i" or "j" ran into "maxlen"
return 0;
+ }
c1 = PTR2CHAR((char_u *)s + i);
c2 = PTR2CHAR((char_u *)s + i + MB_PTR2LEN((char_u *)s + i));
diff --git a/src/nvim/path.h b/src/nvim/path.h
index 628ea335ed..eac367d0ac 100644
--- a/src/nvim/path.h
+++ b/src/nvim/path.h
@@ -20,6 +20,7 @@
#define EW_KEEPDOLLAR 0x800 /* do not escape $, $var is expanded */
/* Note: mostly EW_NOTFOUND and EW_SILENT are mutually exclusive: EW_NOTFOUND
* is used when executing commands and EW_SILENT for interactive expanding. */
+#define EW_ALLLINKS 0x1000 // also links not pointing to existing file
/// Return value for the comparison of two files. Also @see path_full_compare.
typedef enum file_comparison {
diff --git a/src/nvim/po/CMakeLists.txt b/src/nvim/po/CMakeLists.txt
index 6687918df4..d1e08db65e 100644
--- a/src/nvim/po/CMakeLists.txt
+++ b/src/nvim/po/CMakeLists.txt
@@ -72,7 +72,7 @@ if(HAVE_WORKING_LIBINTL AND GETTEXT_FOUND AND XGETTEXT_PRG AND ICONV_PRG)
install_helper(
FILES ${moFile}
- DESTINATION ${CMAKE_INSTALL_LOCALEDIR}/${name}/LC_MESSAGES
+ DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/nvim/runtime/lang/${name}/LC_MESSAGES
RENAME nvim.mo)
list(APPEND LANGUAGE_MO_FILES ${moFile})
diff --git a/src/nvim/popupmnu.c b/src/nvim/popupmnu.c
index 001740943f..5ad621e666 100644
--- a/src/nvim/popupmnu.c
+++ b/src/nvim/popupmnu.c
@@ -545,7 +545,11 @@ static int pum_set_selected(int n, int repeat)
g_do_tagpreview = (int)p_pvh;
}
RedrawingDisabled++;
+ // Prevent undo sync here, if an autocommand syncs undo weird
+ // things can happen to the undo tree.
+ no_u_sync++;
resized = prepare_tagpreview(false);
+ no_u_sync--;
RedrawingDisabled--;
g_do_tagpreview = 0;
@@ -629,7 +633,9 @@ static int pum_set_selected(int n, int repeat)
// the window when needed, otherwise it will always be
// redraw.
if (resized) {
+ no_u_sync++;
win_enter(curwin_save, true);
+ no_u_sync--;
update_topline();
}
@@ -640,7 +646,9 @@ static int pum_set_selected(int n, int repeat)
pum_do_redraw = FALSE;
if (!resized && win_valid(curwin_save)) {
+ no_u_sync++;
win_enter(curwin_save, true);
+ no_u_sync--;
}
// May need to update the screen again when there are
diff --git a/src/nvim/quickfix.c b/src/nvim/quickfix.c
index 3abf43cb8c..f3abf864fb 100644
--- a/src/nvim/quickfix.c
+++ b/src/nvim/quickfix.c
@@ -1606,13 +1606,12 @@ win_found:
}
if (qf_ptr->qf_col > 0) {
curwin->w_cursor.col = qf_ptr->qf_col - 1;
- if (qf_ptr->qf_viscol == TRUE) {
- /*
- * Check each character from the beginning of the error
- * line up to the error column. For each tab character
- * found, reduce the error column value by the length of
- * a tab character.
- */
+ curwin->w_cursor.coladd = 0;
+ if (qf_ptr->qf_viscol == true) {
+ // Check each character from the beginning of the error
+ // line up to the error column. For each tab character
+ // found, reduce the error column value by the length of
+ // a tab character.
line = get_cursor_line_ptr();
screen_col = 0;
for (char_col = 0; char_col < curwin->w_cursor.col; ++char_col) {
@@ -2117,14 +2116,10 @@ void ex_copen(exarg_T *eap)
prevwin = win;
}
- /*
- * Fill the buffer with the quickfix list.
- */
- qf_fill_buffer(qi);
+ qf_set_title_var(qi);
- if (qi->qf_lists[qi->qf_curlist].qf_title != NULL) {
- qf_set_title_var(qi);
- }
+ // Fill the buffer with the quickfix list.
+ qf_fill_buffer(qi);
curwin->w_cursor.lnum = qi->qf_lists[qi->qf_curlist].qf_index;
curwin->w_cursor.col = 0;
@@ -2256,16 +2251,13 @@ static void qf_update_buffer(qf_info_T *qi)
/* set curwin/curbuf to buf and save a few things */
aucmd_prepbuf(&aco, buf);
- qf_fill_buffer(qi);
-
- if (qi->qf_lists[qi->qf_curlist].qf_title != NULL
- && (win = qf_find_win(qi)) != NULL) {
+ if ((win = qf_find_win(qi)) != NULL) {
curwin_save = curwin;
curwin = win;
qf_set_title_var(qi);
curwin = curwin_save;
-
}
+ qf_fill_buffer(qi);
/* restore curwin/curbuf and a few other things */
aucmd_restbuf(&aco);
@@ -2274,10 +2266,13 @@ static void qf_update_buffer(qf_info_T *qi)
}
}
+// Set "w:quickfix_title" if "qi" has a title.
static void qf_set_title_var(qf_info_T *qi)
{
- set_internal_string_var((char_u *)"w:quickfix_title",
- qi->qf_lists[qi->qf_curlist].qf_title);
+ if (qi->qf_lists[qi->qf_curlist].qf_title != NULL) {
+ set_internal_string_var((char_u *)"w:quickfix_title",
+ qi->qf_lists[qi->qf_curlist].qf_title);
+ }
}
/*
diff --git a/src/nvim/regexp.c b/src/nvim/regexp.c
index 39001939d8..608aa38466 100644
--- a/src/nvim/regexp.c
+++ b/src/nvim/regexp.c
@@ -796,13 +796,14 @@ static void reg_equi_class(int c)
if (enc_utf8 || STRCMP(p_enc, "latin1") == 0
|| STRCMP(p_enc, "iso-8859-15") == 0) {
switch (c) {
- case 'A': case '\300': case '\301': case '\302':
+ // Do not use '\300' style, it results in a negative number.
+ case 'A': case 0xc0: case 0xc1: case 0xc2:
+ case 0xc3: case 0xc4: case 0xc5:
CASEMBC(0x100) CASEMBC(0x102) CASEMBC(0x104) CASEMBC(0x1cd)
CASEMBC(0x1de) CASEMBC(0x1e0) CASEMBC(0x1ea2)
- case '\303': case '\304': case '\305':
- regmbc('A'); regmbc('\300'); regmbc('\301');
- regmbc('\302'); regmbc('\303'); regmbc('\304');
- regmbc('\305');
+ regmbc('A'); regmbc(0xc0); regmbc(0xc1);
+ regmbc(0xc2); regmbc(0xc3); regmbc(0xc4);
+ regmbc(0xc5);
REGMBC(0x100) REGMBC(0x102) REGMBC(0x104)
REGMBC(0x1cd) REGMBC(0x1de) REGMBC(0x1e0)
REGMBC(0x1ea2)
@@ -810,9 +811,9 @@ static void reg_equi_class(int c)
case 'B': CASEMBC(0x1e02) CASEMBC(0x1e06)
regmbc('B'); REGMBC(0x1e02) REGMBC(0x1e06)
return;
- case 'C': case '\307':
+ case 'C': case 0xc7:
CASEMBC(0x106) CASEMBC(0x108) CASEMBC(0x10a) CASEMBC(0x10c)
- regmbc('C'); regmbc('\307');
+ regmbc('C'); regmbc(0xc7);
REGMBC(0x106) REGMBC(0x108) REGMBC(0x10a)
REGMBC(0x10c)
return;
@@ -821,11 +822,11 @@ static void reg_equi_class(int c)
regmbc('D'); REGMBC(0x10e) REGMBC(0x110)
REGMBC(0x1e0a) REGMBC(0x1e0e) REGMBC(0x1e10)
return;
- case 'E': case '\310': case '\311': case '\312': case '\313':
+ case 'E': case 0xc8: case 0xc9: case 0xca: case 0xcb:
CASEMBC(0x112) CASEMBC(0x114) CASEMBC(0x116) CASEMBC(0x118)
CASEMBC(0x11a) CASEMBC(0x1eba) CASEMBC(0x1ebc)
- regmbc('E'); regmbc('\310'); regmbc('\311');
- regmbc('\312'); regmbc('\313');
+ regmbc('E'); regmbc(0xc8); regmbc(0xc9);
+ regmbc(0xca); regmbc(0xcb);
REGMBC(0x112) REGMBC(0x114) REGMBC(0x116)
REGMBC(0x118) REGMBC(0x11a) REGMBC(0x1eba)
REGMBC(0x1ebc)
@@ -845,11 +846,11 @@ static void reg_equi_class(int c)
regmbc('H'); REGMBC(0x124) REGMBC(0x126)
REGMBC(0x1e22) REGMBC(0x1e26) REGMBC(0x1e28)
return;
- case 'I': case '\314': case '\315': case '\316': case '\317':
+ case 'I': case 0xcc: case 0xcd: case 0xce: case 0xcf:
CASEMBC(0x128) CASEMBC(0x12a) CASEMBC(0x12c) CASEMBC(0x12e)
CASEMBC(0x130) CASEMBC(0x1cf) CASEMBC(0x1ec8)
- regmbc('I'); regmbc('\314'); regmbc('\315');
- regmbc('\316'); regmbc('\317');
+ regmbc('I'); regmbc(0xcc); regmbc(0xcd);
+ regmbc(0xce); regmbc(0xcf);
REGMBC(0x128) REGMBC(0x12a) REGMBC(0x12c)
REGMBC(0x12e) REGMBC(0x130) REGMBC(0x1cf)
REGMBC(0x1ec8)
@@ -871,20 +872,20 @@ static void reg_equi_class(int c)
case 'M': CASEMBC(0x1e3e) CASEMBC(0x1e40)
regmbc('M'); REGMBC(0x1e3e) REGMBC(0x1e40)
return;
- case 'N': case '\321':
+ case 'N': case 0xd1:
CASEMBC(0x143) CASEMBC(0x145) CASEMBC(0x147) CASEMBC(0x1e44)
CASEMBC(0x1e48)
- regmbc('N'); regmbc('\321');
+ regmbc('N'); regmbc(0xd1);
REGMBC(0x143) REGMBC(0x145) REGMBC(0x147)
REGMBC(0x1e44) REGMBC(0x1e48)
return;
- case 'O': case '\322': case '\323': case '\324': case '\325':
- case '\326': case '\330':
+ case 'O': case 0xd2: case 0xd3: case 0xd4: case 0xd5:
+ case 0xd6: case 0xd8:
CASEMBC(0x14c) CASEMBC(0x14e) CASEMBC(0x150) CASEMBC(0x1a0)
CASEMBC(0x1d1) CASEMBC(0x1ea) CASEMBC(0x1ec) CASEMBC(0x1ece)
- regmbc('O'); regmbc('\322'); regmbc('\323');
- regmbc('\324'); regmbc('\325'); regmbc('\326');
- regmbc('\330');
+ regmbc('O'); regmbc(0xd2); regmbc(0xd3);
+ regmbc(0xd4); regmbc(0xd5); regmbc(0xd6);
+ regmbc(0xd8);
REGMBC(0x14c) REGMBC(0x14e) REGMBC(0x150)
REGMBC(0x1a0) REGMBC(0x1d1) REGMBC(0x1ea)
REGMBC(0x1ec) REGMBC(0x1ece)
@@ -907,12 +908,12 @@ static void reg_equi_class(int c)
regmbc('T'); REGMBC(0x162) REGMBC(0x164)
REGMBC(0x166) REGMBC(0x1e6a) REGMBC(0x1e6e)
return;
- case 'U': case '\331': case '\332': case '\333': case '\334':
+ case 'U': case 0xd9: case 0xda: case 0xdb: case 0xdc:
CASEMBC(0x168) CASEMBC(0x16a) CASEMBC(0x16c) CASEMBC(0x16e)
CASEMBC(0x170) CASEMBC(0x172) CASEMBC(0x1af) CASEMBC(0x1d3)
CASEMBC(0x1ee6)
- regmbc('U'); regmbc('\331'); regmbc('\332');
- regmbc('\333'); regmbc('\334');
+ regmbc('U'); regmbc(0xd9); regmbc(0xda);
+ regmbc(0xdb); regmbc(0xdc);
REGMBC(0x168) REGMBC(0x16a) REGMBC(0x16c)
REGMBC(0x16e) REGMBC(0x170) REGMBC(0x172)
REGMBC(0x1af) REGMBC(0x1d3) REGMBC(0x1ee6)
@@ -928,10 +929,10 @@ static void reg_equi_class(int c)
case 'X': CASEMBC(0x1e8a) CASEMBC(0x1e8c)
regmbc('X'); REGMBC(0x1e8a) REGMBC(0x1e8c)
return;
- case 'Y': case '\335':
+ case 'Y': case 0xdd:
CASEMBC(0x176) CASEMBC(0x178) CASEMBC(0x1e8e) CASEMBC(0x1ef2)
CASEMBC(0x1ef6) CASEMBC(0x1ef8)
- regmbc('Y'); regmbc('\335');
+ regmbc('Y'); regmbc(0xdd);
REGMBC(0x176) REGMBC(0x178) REGMBC(0x1e8e)
REGMBC(0x1ef2) REGMBC(0x1ef6) REGMBC(0x1ef8)
return;
@@ -941,13 +942,13 @@ static void reg_equi_class(int c)
REGMBC(0x17d) REGMBC(0x1b5) REGMBC(0x1e90)
REGMBC(0x1e94)
return;
- case 'a': case '\340': case '\341': case '\342':
- case '\343': case '\344': case '\345':
+ case 'a': case 0xe0: case 0xe1: case 0xe2:
+ case 0xe3: case 0xe4: case 0xe5:
CASEMBC(0x101) CASEMBC(0x103) CASEMBC(0x105) CASEMBC(0x1ce)
CASEMBC(0x1df) CASEMBC(0x1e1) CASEMBC(0x1ea3)
- regmbc('a'); regmbc('\340'); regmbc('\341');
- regmbc('\342'); regmbc('\343'); regmbc('\344');
- regmbc('\345');
+ regmbc('a'); regmbc(0xe0); regmbc(0xe1);
+ regmbc(0xe2); regmbc(0xe3); regmbc(0xe4);
+ regmbc(0xe5);
REGMBC(0x101) REGMBC(0x103) REGMBC(0x105)
REGMBC(0x1ce) REGMBC(0x1df) REGMBC(0x1e1)
REGMBC(0x1ea3)
@@ -955,9 +956,9 @@ static void reg_equi_class(int c)
case 'b': CASEMBC(0x1e03) CASEMBC(0x1e07)
regmbc('b'); REGMBC(0x1e03) REGMBC(0x1e07)
return;
- case 'c': case '\347':
+ case 'c': case 0xe7:
CASEMBC(0x107) CASEMBC(0x109) CASEMBC(0x10b) CASEMBC(0x10d)
- regmbc('c'); regmbc('\347');
+ regmbc('c'); regmbc(0xe7);
REGMBC(0x107) REGMBC(0x109) REGMBC(0x10b)
REGMBC(0x10d)
return;
@@ -966,11 +967,11 @@ static void reg_equi_class(int c)
regmbc('d'); REGMBC(0x10f) REGMBC(0x111)
REGMBC(0x1e0b) REGMBC(0x1e0f) REGMBC(0x1e11)
return;
- case 'e': case '\350': case '\351': case '\352': case '\353':
+ case 'e': case 0xe8: case 0xe9: case 0xea: case 0xeb:
CASEMBC(0x113) CASEMBC(0x115) CASEMBC(0x117) CASEMBC(0x119)
CASEMBC(0x11b) CASEMBC(0x1ebb) CASEMBC(0x1ebd)
- regmbc('e'); regmbc('\350'); regmbc('\351');
- regmbc('\352'); regmbc('\353');
+ regmbc('e'); regmbc(0xe8); regmbc(0xe9);
+ regmbc(0xea); regmbc(0xeb);
REGMBC(0x113) REGMBC(0x115) REGMBC(0x117)
REGMBC(0x119) REGMBC(0x11b) REGMBC(0x1ebb)
REGMBC(0x1ebd)
@@ -991,11 +992,11 @@ static void reg_equi_class(int c)
REGMBC(0x1e23) REGMBC(0x1e27) REGMBC(0x1e29)
REGMBC(0x1e96)
return;
- case 'i': case '\354': case '\355': case '\356': case '\357':
+ case 'i': case 0xec: case 0xed: case 0xee: case 0xef:
CASEMBC(0x129) CASEMBC(0x12b) CASEMBC(0x12d) CASEMBC(0x12f)
CASEMBC(0x1d0) CASEMBC(0x1ec9)
- regmbc('i'); regmbc('\354'); regmbc('\355');
- regmbc('\356'); regmbc('\357');
+ regmbc('i'); regmbc(0xec); regmbc(0xed);
+ regmbc(0xee); regmbc(0xef);
REGMBC(0x129) REGMBC(0x12b) REGMBC(0x12d)
REGMBC(0x12f) REGMBC(0x1d0) REGMBC(0x1ec9)
return;
@@ -1016,20 +1017,20 @@ static void reg_equi_class(int c)
case 'm': CASEMBC(0x1e3f) CASEMBC(0x1e41)
regmbc('m'); REGMBC(0x1e3f) REGMBC(0x1e41)
return;
- case 'n': case '\361':
+ case 'n': case 0xf1:
CASEMBC(0x144) CASEMBC(0x146) CASEMBC(0x148) CASEMBC(0x149)
CASEMBC(0x1e45) CASEMBC(0x1e49)
- regmbc('n'); regmbc('\361');
+ regmbc('n'); regmbc(0xf1);
REGMBC(0x144) REGMBC(0x146) REGMBC(0x148)
REGMBC(0x149) REGMBC(0x1e45) REGMBC(0x1e49)
return;
- case 'o': case '\362': case '\363': case '\364': case '\365':
- case '\366': case '\370':
+ case 'o': case 0xf2: case 0xf3: case 0xf4: case 0xf5:
+ case 0xf6: case 0xf8:
CASEMBC(0x14d) CASEMBC(0x14f) CASEMBC(0x151) CASEMBC(0x1a1)
CASEMBC(0x1d2) CASEMBC(0x1eb) CASEMBC(0x1ed) CASEMBC(0x1ecf)
- regmbc('o'); regmbc('\362'); regmbc('\363');
- regmbc('\364'); regmbc('\365'); regmbc('\366');
- regmbc('\370');
+ regmbc('o'); regmbc(0xf2); regmbc(0xf3);
+ regmbc(0xf4); regmbc(0xf5); regmbc(0xf6);
+ regmbc(0xf8);
REGMBC(0x14d) REGMBC(0x14f) REGMBC(0x151)
REGMBC(0x1a1) REGMBC(0x1d2) REGMBC(0x1eb)
REGMBC(0x1ed) REGMBC(0x1ecf)
@@ -1052,12 +1053,12 @@ static void reg_equi_class(int c)
regmbc('t'); REGMBC(0x163) REGMBC(0x165) REGMBC(0x167)
REGMBC(0x1e6b) REGMBC(0x1e6f) REGMBC(0x1e97)
return;
- case 'u': case '\371': case '\372': case '\373': case '\374':
+ case 'u': case 0xf9: case 0xfa: case 0xfb: case 0xfc:
CASEMBC(0x169) CASEMBC(0x16b) CASEMBC(0x16d) CASEMBC(0x16f)
CASEMBC(0x171) CASEMBC(0x173) CASEMBC(0x1b0) CASEMBC(0x1d4)
CASEMBC(0x1ee7)
- regmbc('u'); regmbc('\371'); regmbc('\372');
- regmbc('\373'); regmbc('\374');
+ regmbc('u'); regmbc(0xf9); regmbc(0xfa);
+ regmbc(0xfb); regmbc(0xfc);
REGMBC(0x169) REGMBC(0x16b) REGMBC(0x16d)
REGMBC(0x16f) REGMBC(0x171) REGMBC(0x173)
REGMBC(0x1b0) REGMBC(0x1d4) REGMBC(0x1ee7)
@@ -1074,10 +1075,10 @@ static void reg_equi_class(int c)
case 'x': CASEMBC(0x1e8b) CASEMBC(0x1e8d)
regmbc('x'); REGMBC(0x1e8b) REGMBC(0x1e8d)
return;
- case 'y': case '\375': case '\377':
+ case 'y': case 0xfd: case 0xff:
CASEMBC(0x177) CASEMBC(0x1e8f) CASEMBC(0x1e99)
CASEMBC(0x1ef3) CASEMBC(0x1ef7) CASEMBC(0x1ef9)
- regmbc('y'); regmbc('\375'); regmbc('\377');
+ regmbc('y'); regmbc(0xfd); regmbc(0xff);
REGMBC(0x177) REGMBC(0x1e8f) REGMBC(0x1e99)
REGMBC(0x1ef3) REGMBC(0x1ef7) REGMBC(0x1ef9)
return;
@@ -4186,7 +4187,7 @@ regmatch (
/* When only a composing char is given match at any
* position where that composing char appears. */
status = RA_NOMATCH;
- for (i = 0; reginput[i] != NUL; i += utf_char2len(inpc)) {
+ for (i = 0; reginput[i] != NUL; i += utf_ptr2len(reginput + i)) {
inpc = mb_ptr2char(reginput + i);
if (!utf_iscomposing(inpc)) {
if (i > 0)
diff --git a/src/nvim/regexp_nfa.c b/src/nvim/regexp_nfa.c
index 1fd024a062..e2849fb17a 100644
--- a/src/nvim/regexp_nfa.c
+++ b/src/nvim/regexp_nfa.c
@@ -4048,6 +4048,7 @@ skip_add:
sub->list.multi[subidx].start_col =
(colnr_T)(reginput - regline + off);
}
+ sub->list.multi[subidx].end_lnum = -1;
} else {
if (subidx < sub->in_use) {
save_ptr = sub->list.line[subidx].start;
@@ -4762,48 +4763,54 @@ static int skip_to_start(int c, colnr_T *colp)
*/
static long find_match_text(colnr_T startcol, int regstart, char_u *match_text)
{
- colnr_T col = startcol;
- int c1, c2;
- int len1, len2;
- int match;
+#define PTR2LEN(x) enc_utf8 ? utf_ptr2len(x) : MB_PTR2LEN(x)
- for (;; ) {
- match = TRUE;
- len2 = MB_CHAR2LEN(regstart); /* skip regstart */
- for (len1 = 0; match_text[len1] != NUL; len1 += MB_CHAR2LEN(c1)) {
- c1 = PTR2CHAR(match_text + len1);
- c2 = PTR2CHAR(regline + col + len2);
- if (c1 != c2 && (!ireg_ic || vim_tolower(c1) != vim_tolower(c2))) {
- match = FALSE;
+ colnr_T col = startcol;
+ int regstart_len = PTR2LEN(regline + startcol);
+
+ for (;;) {
+ bool match = true;
+ char_u *s1 = match_text;
+ char_u *s2 = regline + col + regstart_len; // skip regstart
+ while (*s1) {
+ int c1_len = PTR2LEN(s1);
+ int c1 = PTR2CHAR(s1);
+ int c2_len = PTR2LEN(s2);
+ int c2 = PTR2CHAR(s2);
+
+ if ((c1 != c2 && (!ireg_ic || vim_tolower(c1) != vim_tolower(c2))) ||
+ c1_len != c2_len) {
+ match = false;
break;
}
- len2 += MB_CHAR2LEN(c2);
+ s1 += c1_len;
+ s2 += c2_len;
}
if (match
- /* check that no composing char follows */
- && !(enc_utf8
- && STRLEN(regline) > (size_t)(col + len2)
- && utf_iscomposing(PTR2CHAR(regline + col + len2)))
- ) {
+ // check that no composing char follows
+ && !(enc_utf8 && utf_iscomposing(PTR2CHAR(s2)))) {
cleanup_subexpr();
if (REG_MULTI) {
reg_startpos[0].lnum = reglnum;
reg_startpos[0].col = col;
reg_endpos[0].lnum = reglnum;
- reg_endpos[0].col = col + len2;
+ reg_endpos[0].col = s2 - regline;
} else {
reg_startp[0] = regline + col;
- reg_endp[0] = regline + col + len2;
+ reg_endp[0] = s2;
}
return 1L;
}
- /* Try finding regstart after the current match. */
- col += MB_CHAR2LEN(regstart); /* skip regstart */
- if (skip_to_start(regstart, &col) == FAIL)
+ // Try finding regstart after the current match.
+ col += regstart_len; // skip regstart
+ if (skip_to_start(regstart, &col) == FAIL) {
break;
+ }
}
return 0L;
+
+#undef PTR2LEN
}
/*
@@ -6173,7 +6180,8 @@ static long nfa_regtry(nfa_regprog_T *prog, colnr_T col)
if (prog->reghasz == REX_SET) {
cleanup_zsubexpr();
re_extmatch_out = make_extmatch();
- for (i = 0; i < subs.synt.in_use; i++) {
+ // Loop over \z1, \z2, etc. There is no \z0.
+ for (i = 1; i < subs.synt.in_use; i++) {
if (REG_MULTI) {
struct multipos *mpos = &subs.synt.list.multi[i];
diff --git a/src/nvim/screen.c b/src/nvim/screen.c
index 9a64a7c3a9..3b5836f0b5 100644
--- a/src/nvim/screen.c
+++ b/src/nvim/screen.c
@@ -147,6 +147,9 @@ static foldinfo_T win_foldinfo; /* info for 'foldcolumn' */
*/
static schar_T *current_ScreenLine;
+StlClickDefinition *tab_page_click_defs = NULL;
+long tab_page_click_defs_size = 0;
+
# define SCREEN_LINE(r, o, e, c, rl) screen_line((r), (o), (e), (c), (rl))
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "screen.c.generated.h"
@@ -2196,11 +2199,13 @@ win_line (
int syntax_seqnr = 0;
int prev_syntax_id = 0;
int conceal_attr = hl_attr(HLF_CONCEAL);
- int is_concealing = FALSE;
- int boguscols = 0; /* nonexistent columns added to force
- wrapping */
- int vcol_off = 0; /* offset for concealed characters */
- int did_wcol = FALSE;
+ int is_concealing = false;
+ int boguscols = 0; ///< nonexistent columns added to
+ ///< force wrapping
+ int vcol_off = 0; ///< offset for concealed characters
+ int did_wcol = false;
+ int match_conc = false; ///< cchar for match functions
+ int has_match_conc = false; ///< match wants to conceal
int old_boguscols = 0;
# define VCOL_HLC (vcol - vcol_off)
# define FIX_FOR_BOGUSCOLS \
@@ -2427,13 +2432,18 @@ win_line (
}
}
- /* find start of trailing whitespace */
- if (wp->w_p_list && lcs_trail) {
- trailcol = (colnr_T)STRLEN(ptr);
- while (trailcol > (colnr_T)0 && ascii_iswhite(ptr[trailcol - 1]))
- --trailcol;
- trailcol += (colnr_T) (ptr - line);
- extra_check = TRUE;
+ if (wp->w_p_list) {
+ if (lcs_space || lcs_trail) {
+ extra_check = true;
+ }
+ // find start of trailing whitespace
+ if (lcs_trail) {
+ trailcol = (colnr_T)STRLEN(ptr);
+ while (trailcol > (colnr_T)0 && ascii_iswhite(ptr[trailcol - 1])) {
+ trailcol--;
+ }
+ trailcol += (colnr_T) (ptr - line);
+ }
}
/*
@@ -2630,11 +2640,10 @@ win_line (
extra_check = true;
}
- /*
- * Repeat for the whole displayed line.
- */
+ // Repeat for the whole displayed line.
for (;; ) {
- /* Skip this quickly when working on the text. */
+ has_match_conc = false;
+ // Skip this quickly when working on the text.
if (draw_state != WL_LINE) {
if (draw_state == WL_CMDLINE - 1 && n_extra == 0) {
draw_state = WL_CMDLINE;
@@ -2881,8 +2890,16 @@ win_line (
shl->endcol = tmp_col;
}
shl->attr_cur = shl->attr;
+ if (cur != NULL && syn_name2id((char_u *)"Conceal")
+ == cur->hlg_id) {
+ has_match_conc = true;
+ match_conc = cur->conceal_char;
+ } else {
+ has_match_conc = match_conc = false;
+ }
} else if (v == (long)shl->endcol) {
shl->attr_cur = 0;
+ prev_syntax_id = 0;
next_search_hl(wp, shl, lnum, (colnr_T)v, cur);
pos_inprogress = !(cur == NULL || cur->pos.cur == 0);
@@ -3198,26 +3215,7 @@ win_line (
}
}
- ++ptr;
-
- // 'list': change char 160 to lcs_nbsp and space to lcs_space.
- if (wp->w_p_list
- && (((c == 160 || (mb_utf8 && mb_c == 160)) && lcs_nbsp)
- || (c == ' ' && lcs_space && ptr - line <= trailcol))) {
- c = (c == ' ') ? lcs_space : lcs_nbsp;
- if (area_attr == 0 && search_attr == 0) {
- n_attr = 1;
- extra_attr = hl_attr(HLF_8);
- saved_attr2 = char_attr; /* save current attr */
- }
- mb_c = c;
- if (enc_utf8 && (*mb_char2len)(c) > 1) {
- mb_utf8 = TRUE;
- u8cc[0] = 0;
- c = 0xc0;
- } else
- mb_utf8 = FALSE;
- }
+ ptr++;
if (extra_check) {
bool can_spell = true;
@@ -3364,6 +3362,28 @@ win_line (
}
}
+ // 'list': change char 160 to lcs_nbsp and space to lcs_space.
+ if (wp->w_p_list
+ && (((c == 160
+ || (mb_utf8 && (mb_c == 160 || mb_c == 0x202f)))
+ && lcs_nbsp)
+ || (c == ' ' && lcs_space && ptr - line <= trailcol))) {
+ c = (c == ' ') ? lcs_space : lcs_nbsp;
+ if (area_attr == 0 && search_attr == 0) {
+ n_attr = 1;
+ extra_attr = hl_attr(HLF_8);
+ saved_attr2 = char_attr; // save current attr
+ }
+ mb_c = c;
+ if (enc_utf8 && (*mb_char2len)(c) > 1) {
+ mb_utf8 = true;
+ u8cc[0] = 0;
+ c = 0xc0;
+ } else {
+ mb_utf8 = false;
+ }
+ }
+
if (trailcol != MAXCOL && ptr > line + trailcol && c == ' ') {
c = lcs_trail;
if (!attr_pri) {
@@ -3409,7 +3429,7 @@ win_line (
int i;
int saved_nextra = n_extra;
- if ((is_concealing || boguscols > 0) && vcol_off > 0) {
+ if (vcol_off > 0) {
// there are characters to conceal
tab_len += vcol_off;
}
@@ -3439,25 +3459,31 @@ win_line (
// n_extra will be increased by FIX_FOX_BOGUSCOLS
// macro below, so need to adjust for that here
- if ((is_concealing || boguscols > 0) && vcol_off > 0) {
+ if (vcol_off > 0) {
n_extra -= vcol_off;
}
}
- /* Tab alignment should be identical regardless of
- * 'conceallevel' value. So tab compensates of all
- * previous concealed characters, and thus resets vcol_off
- * and boguscols accumulated so far in the line. Note that
- * the tab can be longer than 'tabstop' when there
- * are concealed characters. */
- FIX_FOR_BOGUSCOLS;
- // Make sure that the highlighting for the tab char will be correctly
- // set further below (effectively reverts the FIX_FOR_BOGSUCOLS
- // macro).
- if (old_boguscols > 0 && n_extra > tab_len && wp->w_p_list
- && lcs_tab1) {
- tab_len += n_extra - tab_len;
+
+ {
+ int vc_saved = vcol_off;
+
+ // Tab alignment should be identical regardless of
+ // 'conceallevel' value. So tab compensates of all
+ // previous concealed characters, and thus resets
+ // vcol_off and boguscols accumulated so far in the
+ // line. Note that the tab can be longer than
+ // 'tabstop' when there are concealed characters.
+ FIX_FOR_BOGUSCOLS;
+
+ // Make sure, the highlighting for the tab char will be
+ // correctly set further below (effectively reverts the
+ // FIX_FOR_BOGSUCOLS macro.
+ if (n_extra == tab_len + vc_saved && wp->w_p_list && lcs_tab1) {
+ tab_len += vc_saved;
+ }
}
- mb_utf8 = FALSE; /* don't draw as UTF-8 */
+
+ mb_utf8 = (int)false; // don't draw as UTF-8
if (wp->w_p_list) {
c = lcs_tab1;
if (wp->w_p_lbr) {
@@ -3592,24 +3618,28 @@ win_line (
}
}
- if ( wp->w_p_cole > 0
- && (wp != curwin || lnum != wp->w_cursor.lnum ||
- conceal_cursor_line(wp))
- && (syntax_flags & HL_CONCEAL) != 0
- && !(lnum_in_visual_area
- && vim_strchr(wp->w_p_cocu, 'v') == NULL)) {
+ if (wp->w_p_cole > 0
+ && (wp != curwin || lnum != wp->w_cursor.lnum ||
+ conceal_cursor_line(wp))
+ && ((syntax_flags & HL_CONCEAL) != 0 || has_match_conc)
+ && !(lnum_in_visual_area
+ && vim_strchr(wp->w_p_cocu, 'v') == NULL)) {
char_attr = conceal_attr;
if (prev_syntax_id != syntax_seqnr
- && (syn_get_sub_char() != NUL || wp->w_p_cole == 1)
+ && (syn_get_sub_char() != NUL || match_conc
+ || wp->w_p_cole == 1)
&& wp->w_p_cole != 3) {
- /* First time at this concealed item: display one
- * character. */
- if (syn_get_sub_char() != NUL)
+ // First time at this concealed item: display one
+ // character.
+ if (match_conc) {
+ c = match_conc;
+ } else if (syn_get_sub_char() != NUL) {
c = syn_get_sub_char();
- else if (lcs_conceal != NUL)
+ } else if (lcs_conceal != NUL) {
c = lcs_conceal;
- else
+ } else {
c = ' ';
+ }
prev_syntax_id = syntax_seqnr;
@@ -3968,20 +3998,24 @@ win_line (
ScreenAttrs[off] = char_attr;
if (has_mbyte && (*mb_char2cells)(mb_c) > 1) {
- /* Need to fill two screen columns. */
- ++off;
- ++col;
- if (enc_utf8)
- /* UTF-8: Put a 0 in the second screen char. */
+ // Need to fill two screen columns.
+ off++;
+ col++;
+ if (enc_utf8) {
+ // UTF-8: Put a 0 in the second screen char.
ScreenLines[off] = 0;
- else
- /* DBCS: Put second byte in the second screen char. */
+ } else {
+ // DBCS: Put second byte in the second screen char.
ScreenLines[off] = mb_c & 0xff;
- ++vcol;
- /* When "tocol" is halfway through a character, set it to the end of
- * the character, otherwise highlighting won't stop. */
- if (tocol == vcol)
- ++tocol;
+ }
+ if (draw_state > WL_NR && filler_todo <= 0) {
+ vcol++;
+ }
+ // When "tocol" is halfway through a character, set it to the end of
+ // the character, otherwise highlighting won't stop.
+ if (tocol == vcol) {
+ tocol++;
+ }
if (wp->w_p_rl) {
/* now it's time to backup one cell */
--off;
@@ -4998,8 +5032,8 @@ win_redr_custom (
char_u *stl;
char_u *p;
struct stl_hlrec hltab[STL_MAX_ITEM];
- struct stl_hlrec tabtab[STL_MAX_ITEM];
- int use_sandbox = FALSE;
+ StlClickRecord tabtab[STL_MAX_ITEM];
+ int use_sandbox = false;
win_T *ewp;
int p_crb_save;
@@ -5115,20 +5149,24 @@ win_redr_custom (
screen_puts(p >= buf + len ? (char_u *)"" : p, row, col, curattr);
if (wp == NULL) {
- /* Fill the TabPageIdxs[] array for clicking in the tab pagesline. */
+ // Fill the tab_page_click_defs array for clicking in the tab pages line.
col = 0;
len = 0;
p = buf;
- fillchar = 0;
+ StlClickDefinition cur_click_def = {
+ .type = kStlClickDisabled,
+ };
for (n = 0; tabtab[n].start != NULL; n++) {
- len += vim_strnsize(p, (int)(tabtab[n].start - p));
- while (col < len)
- TabPageIdxs[col++] = fillchar;
- p = tabtab[n].start;
- fillchar = tabtab[n].userhl;
+ len += vim_strnsize(p, (int)(tabtab[n].start - (char *) p));
+ while (col < len) {
+ tab_page_click_defs[col++] = cur_click_def;
+ }
+ p = (char_u *) tabtab[n].start;
+ cur_click_def = tabtab[n].def;
+ }
+ while (col < Columns) {
+ tab_page_click_defs[col++] = cur_click_def;
}
- while (col < Columns)
- TabPageIdxs[col++] = fillchar;
}
theend:
@@ -5947,9 +5985,9 @@ void screenalloc(bool doclear)
sattr_T *new_ScreenAttrs;
unsigned *new_LineOffset;
char_u *new_LineWraps;
- short *new_TabPageIdxs;
- static int entered = FALSE; /* avoid recursiveness */
- static int done_outofmem_msg = FALSE; /* did outofmem message */
+ StlClickDefinition *new_tab_page_click_defs;
+ static bool entered = false; // avoid recursiveness
+ static bool done_outofmem_msg = false;
int retry_count = 0;
const bool l_enc_utf8 = enc_utf8;
const int l_enc_dbcs = enc_dbcs;
@@ -6022,7 +6060,8 @@ retry:
new_ScreenAttrs = xmalloc((size_t)((Rows + 1) * Columns * sizeof(sattr_T)));
new_LineOffset = xmalloc((size_t)(Rows * sizeof(unsigned)));
new_LineWraps = xmalloc((size_t)(Rows * sizeof(char_u)));
- new_TabPageIdxs = xmalloc((size_t)(Columns * sizeof(short)));
+ new_tab_page_click_defs = xcalloc(
+ (size_t) Columns, sizeof(*new_tab_page_click_defs));
FOR_ALL_TAB_WINDOWS(tp, wp) {
win_alloc_lines(wp);
@@ -6040,7 +6079,7 @@ retry:
|| new_ScreenAttrs == NULL
|| new_LineOffset == NULL
|| new_LineWraps == NULL
- || new_TabPageIdxs == NULL
+ || new_tab_page_click_defs == NULL
|| outofmem) {
if (ScreenLines != NULL || !done_outofmem_msg) {
/* guess the size */
@@ -6066,8 +6105,8 @@ retry:
new_LineOffset = NULL;
xfree(new_LineWraps);
new_LineWraps = NULL;
- xfree(new_TabPageIdxs);
- new_TabPageIdxs = NULL;
+ xfree(new_tab_page_click_defs);
+ new_tab_page_click_defs = NULL;
} else {
done_outofmem_msg = FALSE;
@@ -6146,7 +6185,8 @@ retry:
ScreenAttrs = new_ScreenAttrs;
LineOffset = new_LineOffset;
LineWraps = new_LineWraps;
- TabPageIdxs = new_TabPageIdxs;
+ tab_page_click_defs = new_tab_page_click_defs;
+ tab_page_click_defs_size = Columns;
/* It's important that screen_Rows and screen_Columns reflect the actual
* size of ScreenLines[]. Set them before calling anything. */
@@ -6185,7 +6225,25 @@ void free_screenlines(void)
xfree(ScreenAttrs);
xfree(LineOffset);
xfree(LineWraps);
- xfree(TabPageIdxs);
+ clear_tab_page_click_defs(tab_page_click_defs, tab_page_click_defs_size);
+ xfree(tab_page_click_defs);
+}
+
+/// Clear tab_page_click_defs table
+///
+/// @param[out] tpcd Table to clear.
+/// @param[in] tpcd_size Size of the table.
+void clear_tab_page_click_defs(StlClickDefinition *const tpcd,
+ const long tpcd_size)
+{
+ if (tpcd != NULL) {
+ for (long i = 0; i < tpcd_size; i++) {
+ if (i == 0 || tpcd[i].func != tpcd[i - 1].func) {
+ xfree(tpcd[i].func);
+ }
+ }
+ memset(tpcd, 0, (size_t) tpcd_size * sizeof(tpcd[0]));
+ }
}
void screenclear(void)
@@ -6793,9 +6851,9 @@ static void draw_tabline(void)
return;
- /* Init TabPageIdxs[] to zero: Clicking outside of tabs has no effect. */
- for (scol = 0; scol < Columns; ++scol)
- TabPageIdxs[scol] = 0;
+ // Init TabPageIdxs[] to zero: Clicking outside of tabs has no effect.
+ assert(Columns == tab_page_click_defs_size);
+ clear_tab_page_click_defs(tab_page_click_defs, tab_page_click_defs_size);
/* Use the 'tabline' option if it's set. */
if (*p_tal != NUL) {
@@ -6893,11 +6951,16 @@ static void draw_tabline(void)
}
screen_putchar(' ', 0, col++, attr);
- /* Store the tab page number in TabPageIdxs[], so that
- * jump_to_mouse() knows where each one is. */
- ++tabcount;
- while (scol < col)
- TabPageIdxs[scol++] = tabcount;
+ // Store the tab page number in tab_page_click_defs[], so that
+ // jump_to_mouse() knows where each one is.
+ tabcount++;
+ while (scol < col) {
+ tab_page_click_defs[scol++] = (StlClickDefinition) {
+ .type = kStlClickTabSwitch,
+ .tabnr = tabcount,
+ .func = NULL,
+ };
+ }
}
if (use_sep_chars)
@@ -6909,7 +6972,11 @@ static void draw_tabline(void)
/* Put an "X" for closing the current tab if there are several. */
if (first_tabpage->tp_next != NULL) {
screen_putchar('X', 0, (int)Columns - 1, attr_nosel);
- TabPageIdxs[Columns - 1] = -999;
+ tab_page_click_defs[Columns - 1] = (StlClickDefinition) {
+ .type = kStlClickTabClose,
+ .tabnr = 999,
+ .func = NULL,
+ };
}
}
diff --git a/src/nvim/screen.h b/src/nvim/screen.h
index debf86ae67..81a8b9ed4c 100644
--- a/src/nvim/screen.h
+++ b/src/nvim/screen.h
@@ -16,6 +16,29 @@
#define NOT_VALID 40 /* buffer needs complete redraw */
#define CLEAR 50 /* screen messed up, clear it */
+/// Status line click definition
+typedef struct {
+ enum {
+ kStlClickDisabled = 0, ///< Clicks to this area are ignored.
+ kStlClickTabSwitch, ///< Switch to the given tab.
+ kStlClickTabClose, ///< Close given tab.
+ kStlClickFuncRun, ///< Run user function.
+ } type; ///< Type of the click.
+ int tabnr; ///< Tab page number.
+ char *func; ///< Function to run.
+} StlClickDefinition;
+
+/// Used for tabline clicks
+typedef struct {
+ StlClickDefinition def; ///< Click definition.
+ const char *start; ///< Location where region starts.
+} StlClickRecord;
+
+/// Array defining what should be done when tabline is clicked
+extern StlClickDefinition *tab_page_click_defs;
+
+/// Size of the tab_page_click_defs array
+extern long tab_page_click_defs_size;
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "screen.h.generated.h"
diff --git a/src/nvim/search.c b/src/nvim/search.c
index 18a72524cb..fffae1ecb2 100644
--- a/src/nvim/search.c
+++ b/src/nvim/search.c
@@ -497,6 +497,7 @@ int searchit(
pos_T start_pos;
int at_first_line;
int extra_col;
+ int start_char_len;
int match_ok;
long nmatched;
int submatch = 0;
@@ -519,16 +520,21 @@ int searchit(
// When not accepting a match at the start position set "extra_col" to a
// non-zero value. Don't do that when starting at MAXCOL, since MAXCOL + 1
// is zero.
- if ((options & SEARCH_START) || pos->col == MAXCOL) {
- extra_col = 0;
- } else if (dir != BACKWARD && has_mbyte
- && pos->lnum >= 1 && pos->lnum <= buf->b_ml.ml_line_count
- && pos->col < MAXCOL - 2) {
+ if (pos->col == MAXCOL) {
+ start_char_len = 0;
+ } else if (has_mbyte
+ && pos->lnum >= 1 && pos->lnum <= buf->b_ml.ml_line_count
+ && pos->col < MAXCOL - 2) {
// Watch out for the "col" being MAXCOL - 2, used in a closed fold.
- ptr = ml_get_buf(buf, pos->lnum, FALSE) + pos->col;
- extra_col = *ptr == NUL ? 1 : (*mb_ptr2len)(ptr);
+ ptr = ml_get_buf(buf, pos->lnum, false) + pos->col;
+ start_char_len = *ptr == NUL ? 1 : (*mb_ptr2len)(ptr);
} else {
- extra_col = 1;
+ start_char_len = 1;
+ }
+ if (dir == FORWARD) {
+ extra_col = (options & SEARCH_START) ? 0 : start_char_len;
+ } else {
+ extra_col = (options & SEARCH_START) ? start_char_len : 0;
}
start_pos = *pos; /* remember start pos for detecting no match */
@@ -621,43 +627,39 @@ int searchit(
break;
}
matchcol = endpos.col;
- /* for empty match: advance one char */
- if (matchcol == matchpos.col
- && ptr[matchcol] != NUL) {
- if (has_mbyte)
- matchcol +=
- (*mb_ptr2len)(ptr + matchcol);
- else
- ++matchcol;
- }
+ // for empty match (matchcol == matchpos.col): advance one char
} else {
+ // Prepare to start after first matched character.
matchcol = matchpos.col;
- if (ptr[matchcol] != NUL) {
- if (has_mbyte)
- matchcol += (*mb_ptr2len)(ptr
- + matchcol);
- else
- ++matchcol;
- }
}
- if (matchcol == 0 && (options & SEARCH_START))
+
+ if (matchcol == matchpos.col && ptr[matchcol] != NUL) {
+ matchcol += MB_PTR2LEN(ptr + matchcol);
+ }
+
+ if (matchcol == 0 && (options & SEARCH_START)) {
break;
- if (STRLEN(ptr) <= (size_t)matchcol || ptr[matchcol] == NUL
- || (nmatched = vim_regexec_multi(&regmatch,
- win, buf, lnum + matchpos.lnum,
- matchcol,
- tm
- )) == 0) {
- match_ok = FALSE;
+ }
+
+ if (ptr[matchcol] == NUL ||
+ (nmatched = vim_regexec_multi(&regmatch, win, buf, lnum,
+ matchcol, tm)) == 0) {
+ match_ok = false;
break;
}
matchpos = regmatch.startpos[0];
endpos = regmatch.endpos[0];
submatch = first_submatch(&regmatch);
- /* Need to get the line pointer again, a
- * multi-line search may have made it invalid. */
- ptr = ml_get_buf(buf, lnum + matchpos.lnum, FALSE);
+ // This while-loop only works with matchpos.lnum == 0.
+ // For bigger values the next line pointer ptr might not be a
+ // buffer line.
+ if (matchpos.lnum != 0) {
+ break;
+ }
+ // Need to get the line pointer again, a multi-line search may
+ // have made it invalid.
+ ptr = ml_get_buf(buf, lnum, false);
}
if (!match_ok)
continue;
@@ -683,16 +685,14 @@ int searchit(
|| (lnum + regmatch.endpos[0].lnum
== start_pos.lnum
&& (int)regmatch.endpos[0].col - 1
- + extra_col
- <= (int)start_pos.col))
+ < (int)start_pos.col + extra_col))
: (lnum + regmatch.startpos[0].lnum
< start_pos.lnum
|| (lnum + regmatch.startpos[0].lnum
== start_pos.lnum
&& (int)regmatch.startpos[0].col
- + extra_col
- <= (int)start_pos.col)))) {
- match_ok = TRUE;
+ < (int)start_pos.col + extra_col)))) {
+ match_ok = true;
matchpos = regmatch.startpos[0];
endpos = regmatch.endpos[0];
submatch = first_submatch(&regmatch);
@@ -3080,18 +3080,18 @@ current_block (
} else
old_end = VIsual;
- /*
- * Search backwards for unclosed '(', '{', etc..
- * Put this position in start_pos.
- * Ignore quotes here.
- */
+ // Search backwards for unclosed '(', '{', etc..
+ // Put this position in start_pos.
+ // Ignore quotes here. Keep the "M" flag in 'cpo', as that is what the
+ // user wants.
save_cpo = p_cpo;
- p_cpo = (char_u *)"%";
+ p_cpo = (char_u *)(vim_strchr(p_cpo, CPO_MATCHBSL) != NULL ? "%M" : "%");
while (count-- > 0) {
- if ((pos = findmatch(NULL, what)) == NULL)
+ if ((pos = findmatch(NULL, what)) == NULL) {
break;
+ }
curwin->w_cursor = *pos;
- start_pos = *pos; /* the findmatch for end_pos will overwrite *pos */
+ start_pos = *pos; // the findmatch for end_pos will overwrite *pos
}
p_cpo = save_cpo;
@@ -3144,10 +3144,12 @@ current_block (
}
if (VIsual_active) {
- if (*p_sel == 'e')
- ++curwin->w_cursor.col;
- if (sol && gchar_cursor() != NUL)
- inc(&curwin->w_cursor); /* include the line break */
+ if (*p_sel == 'e') {
+ inc(&curwin->w_cursor);
+ }
+ if (sol && gchar_cursor() != NUL) {
+ inc(&curwin->w_cursor); // include the line break
+ }
VIsual = start_pos;
VIsual_mode = 'v';
redraw_curbuf_later(INVERTED); /* update the inversion */
diff --git a/src/nvim/shada.c b/src/nvim/shada.c
index dcdf2195f8..def2de9b1a 100644
--- a/src/nvim/shada.c
+++ b/src/nvim/shada.c
@@ -6,9 +6,6 @@
#include <inttypes.h>
#include <errno.h>
#include <fcntl.h>
-#ifdef HAVE_UNISTD_H
-# include <unistd.h>
-#endif
#include <assert.h>
#include <msgpack.h>
diff --git a/src/nvim/spell.c b/src/nvim/spell.c
index b2028109be..cc7dc6210c 100644
--- a/src/nvim/spell.c
+++ b/src/nvim/spell.c
@@ -12910,8 +12910,8 @@ void ex_spelldump(exarg_T *eap)
do_cmdline_cmd("new");
// enable spelling locally in the new window
- set_option_value((char_u*)"spell", TRUE, (char_u*)"", OPT_LOCAL);
- set_option_value((char_u*)"spl", dummy, spl, OPT_LOCAL);
+ set_option_value((char_u*)"spell", true, (char_u*)"", OPT_LOCAL);
+ set_option_value((char_u*)"spl", dummy, spl, OPT_LOCAL);
xfree(spl);
if (!bufempty() || !buf_valid(curbuf))
diff --git a/src/nvim/strings.c b/src/nvim/strings.c
index fe91141375..37a0fb82da 100644
--- a/src/nvim/strings.c
+++ b/src/nvim/strings.c
@@ -425,9 +425,13 @@ char_u *vim_strchr(const char_u *string, int c)
const char_u *p = string;
if (enc_utf8 && c >= 0x80) {
while (*p != NUL) {
- if (utf_ptr2char(p) == c)
+ int l = (*mb_ptr2len)(p);
+
+ // Avoid matching an illegal byte here.
+ if (l > 1 && utf_ptr2char(p) == c) {
return (char_u *) p;
- p += (*mb_ptr2len)(p);
+ }
+ p += l;
}
return NULL;
}
diff --git a/src/nvim/syntax.c b/src/nvim/syntax.c
index 24422c71fb..478fa973a1 100644
--- a/src/nvim/syntax.c
+++ b/src/nvim/syntax.c
@@ -41,6 +41,8 @@
#include "nvim/os/os.h"
#include "nvim/os/time.h"
+static bool did_syntax_onoff = false;
+
// Structure that stores information about a highlight group.
// The ID of a highlight group is also called group ID. It is the index in
// the highlight_ga array PLUS ONE.
@@ -3004,14 +3006,19 @@ static void syn_cmd_spell(exarg_T *eap, int syncing)
return;
next = skiptowhite(arg);
- if (STRNICMP(arg, "toplevel", 8) == 0 && next - arg == 8)
+ if (STRNICMP(arg, "toplevel", 8) == 0 && next - arg == 8) {
curwin->w_s->b_syn_spell = SYNSPL_TOP;
- else if (STRNICMP(arg, "notoplevel", 10) == 0 && next - arg == 10)
+ } else if (STRNICMP(arg, "notoplevel", 10) == 0 && next - arg == 10) {
curwin->w_s->b_syn_spell = SYNSPL_NOTOP;
- else if (STRNICMP(arg, "default", 7) == 0 && next - arg == 7)
+ } else if (STRNICMP(arg, "default", 7) == 0 && next - arg == 7) {
curwin->w_s->b_syn_spell = SYNSPL_DEFAULT;
- else
+ } else {
EMSG2(_("E390: Illegal argument: %s"), arg);
+ return;
+ }
+
+ // assume spell checking changed, force a redraw
+ redraw_win_later(curwin, NOT_VALID);
}
/*
@@ -3281,17 +3288,28 @@ static void syn_cmd_off(exarg_T *eap, int syncing)
}
static void syn_cmd_onoff(exarg_T *eap, char *name)
+ FUNC_ATTR_NONNULL_ALL
{
- char buf[100];
-
+ did_syntax_onoff = true;
eap->nextcmd = check_nextcmd(eap->arg);
if (!eap->skip) {
- strcpy(buf, "so ");
+ char buf[100];
+ strncpy(buf, "so ", 4);
vim_snprintf(buf + 3, sizeof(buf) - 3, SYNTAX_FNAME, name);
do_cmdline_cmd(buf);
}
}
+void syn_maybe_on(void)
+{
+ if (!did_syntax_onoff) {
+ exarg_T ea;
+ ea.arg = (char_u *)"";
+ ea.skip = false;
+ syn_cmd_onoff(&ea, "syntax");
+ }
+}
+
/*
* Handle ":syntax [list]" command: list current syntax words.
*/
@@ -4183,12 +4201,16 @@ static void syn_cmd_keyword(exarg_T *eap, int syncing)
break;
if (p[1] == NUL) {
EMSG2(_("E789: Missing ']': %s"), kw);
- kw = p + 2; /* skip over the NUL */
- break;
+ goto error;
}
if (p[1] == ']') {
- kw = p + 1; /* skip over the "]" */
- break;
+ if (p[2] != NUL) {
+ EMSG3(_("E890: trailing char after ']': %s]%s"),
+ kw, &p[2]);
+ goto error;
+ }
+ kw = p + 1;
+ break; // skip over the "]"
}
if (has_mbyte) {
int l = (*mb_ptr2len)(p + 1);
@@ -4203,6 +4225,7 @@ static void syn_cmd_keyword(exarg_T *eap, int syncing)
}
}
+error:
xfree(keyword_copy);
xfree(syn_opt_arg.cont_in_list);
xfree(syn_opt_arg.next_list);
@@ -4843,9 +4866,10 @@ static char_u *get_syn_pattern(char_u *arg, synpat_T *ci)
int idx;
char_u *cpo_save;
- /* need at least three chars */
- if (arg == NULL || arg[1] == NUL || arg[2] == NUL)
+ // need at least three chars
+ if (arg == NULL || arg[0] == NUL || arg[1] == NUL || arg[2] == NUL) {
return NULL;
+ }
end = skip_regexp(arg + 1, *arg, TRUE, NULL);
if (*end != *arg) { /* end delimiter not found */
@@ -5395,8 +5419,10 @@ void ex_ownsyntax(exarg_T *eap)
if (curwin->w_s == &curwin->w_buffer->b_s) {
curwin->w_s = xmalloc(sizeof(synblock_T));
memset(curwin->w_s, 0, sizeof(synblock_T));
- // TODO: Keep the spell checking as it was.
- curwin->w_p_spell = FALSE; /* No spell checking */
+ hash_init(&curwin->w_s->b_keywtab);
+ hash_init(&curwin->w_s->b_keywtab_ic);
+ // TODO: Keep the spell checking as it was. NOLINT(readability/todo)
+ curwin->w_p_spell = false; // No spell checking
clear_string_option(&curwin->w_s->b_p_spc);
clear_string_option(&curwin->w_s->b_p_spf);
clear_string_option(&curwin->w_s->b_p_spl);
diff --git a/src/nvim/tag.c b/src/nvim/tag.c
index d832924efd..8fcb02c3b6 100644
--- a/src/nvim/tag.c
+++ b/src/nvim/tag.c
@@ -445,17 +445,10 @@ do_tag (
tagmatchname = vim_strsave(name);
}
- /*
- * If a count is supplied to the ":tag <name>" command, then
- * jump to count'th matching tag.
- */
- if (type == DT_TAG && *tag != NUL && count > 0)
- cur_match = count - 1;
-
- if (type == DT_SELECT || type == DT_JUMP
- || type == DT_LTAG
- )
+ if (type == DT_TAG || type == DT_SELECT || type == DT_JUMP
+ || type == DT_LTAG) {
cur_match = MAXCOL - 1;
+ }
max_num_matches = cur_match + 1;
/* when the argument starts with '/', use it as a regexp */
@@ -506,18 +499,19 @@ do_tag (
EMSG2(_("E426: tag not found: %s"), name);
g_do_tagpreview = 0;
} else {
- int ask_for_selection = FALSE;
+ bool ask_for_selection = false;
if (type == DT_CSCOPE && num_matches > 1) {
cs_print_tags();
- ask_for_selection = TRUE;
- } else if (type == DT_SELECT ||
- (type == DT_JUMP && num_matches > 1)) {
- /*
- * List all the matching tags.
- * Assume that the first match indicates how long the tags can
- * be, and align the file names to that.
- */
+ ask_for_selection = true;
+ } else if (type == DT_TAG) {
+ // If a count is supplied to the ":tag <name>" command, then
+ // jump to count'th matching tag.
+ cur_match = count > 0 ? count - 1 : 0;
+ } else if (type == DT_SELECT || (type == DT_JUMP && num_matches > 1)) {
+ // List all the matching tags.
+ // Assume that the first match indicates how long the tags can
+ // be, and align the file names to that.
parse_match(matches[0], &tagp);
taglen = (int)(tagp.tagname_end - tagp.tagname + 2);
if (taglen < 18)
@@ -666,9 +660,10 @@ do_tag (
msg_putchar('\n');
os_breakcheck();
}
- if (got_int)
- got_int = FALSE; /* only stop the listing */
- ask_for_selection = TRUE;
+ if (got_int) {
+ got_int = false; // only stop the listing
+ }
+ ask_for_selection = true;
} else if (type == DT_LTAG) {
list_T *list;
char_u tag_name[128 + 1];
@@ -801,10 +796,8 @@ do_tag (
cur_match = 0; /* Jump to the first tag */
}
- if (ask_for_selection == TRUE) {
- /*
- * Ask to select a tag from the list.
- */
+ if (ask_for_selection) {
+ // Ask to select a tag from the list.
i = prompt_for_number(NULL);
if (i <= 0 || i > num_matches || got_int) {
/* no valid choice: don't change anything */
@@ -851,7 +844,7 @@ do_tag (
ic = (matches[cur_match][0] & MT_IC_OFF);
- if (type != DT_SELECT && type != DT_JUMP
+ if (type != DT_TAG && type != DT_SELECT && type != DT_JUMP
&& type != DT_CSCOPE
&& (num_matches > 1 || ic)
&& !skip_msg) {
diff --git a/src/nvim/terminal.c b/src/nvim/terminal.c
index 0a7807d811..fb74569e3b 100644
--- a/src/nvim/terminal.c
+++ b/src/nvim/terminal.c
@@ -236,7 +236,7 @@ Terminal *terminal_open(TerminalOptions opts)
set_option_value((uint8_t *)"relativenumber", false, NULL, OPT_LOCAL);
RESET_BINDING(curwin);
// Apply TermOpen autocmds so the user can configure the terminal
- apply_autocmds(EVENT_TERMOPEN, NULL, NULL, true, curbuf);
+ apply_autocmds(EVENT_TERMOPEN, NULL, NULL, false, curbuf);
// Configure the scrollback buffer. Try to get the size from:
//
@@ -288,8 +288,9 @@ void terminal_close(Terminal *term, char *msg)
term->forward_mouse = false;
term->closed = true;
+ buf_T *buf = handle_get_buffer(term->buf_handle);
+
if (!msg || exiting) {
- buf_T *buf = handle_get_buffer(term->buf_handle);
// If no msg was given, this was called by close_buffer(buffer.c). Or if
// exiting, we must inform the buffer the terminal no longer exists so that
// close_buffer() doesn't call this again.
@@ -304,6 +305,10 @@ void terminal_close(Terminal *term, char *msg)
} else {
terminal_receive(term, msg, strlen(msg));
}
+
+ if (buf) {
+ apply_autocmds(EVENT_TERMCLOSE, NULL, NULL, false, buf);
+ }
}
void terminal_resize(Terminal *term, uint16_t width, uint16_t height)
diff --git a/src/nvim/testdir/Makefile b/src/nvim/testdir/Makefile
index aaa6f4b97e..63ca4cf6c4 100644
--- a/src/nvim/testdir/Makefile
+++ b/src/nvim/testdir/Makefile
@@ -7,28 +7,37 @@ export SHELL := sh
VIMPROG := ../../../build/bin/nvim
SCRIPTSOURCE := ../../../runtime
-SCRIPTS := test_eval.out \
- test8.out test10.out \
- test11.out test12.out test13.out test14.out \
- test17.out \
- test24.out \
- test30.out \
- test32.out test34.out \
- test36.out test37.out test40.out \
- test42.out test45.out \
- test47.out test48.out test49.out \
- test52.out test53.out test55.out \
- test64.out \
- test68.out test69.out \
- test73.out \
- test79.out \
- test83.out \
- test88.out \
- test_listlbr.out \
- test_breakindent.out \
- test_charsearch.out \
- test_close_count.out \
- test_command_count.out \
+SCRIPTS := \
+ test8.out \
+ test10.out \
+ test12.out \
+ test13.out \
+ test14.out \
+ test17.out \
+ test24.out \
+ test30.out \
+ test32.out \
+ test34.out \
+ test37.out \
+ test40.out \
+ test42.out \
+ test47.out \
+ test48.out \
+ test49.out \
+ test52.out \
+ test53.out \
+ test55.out \
+ test64.out \
+ test68.out \
+ test69.out \
+ test73.out \
+ test79.out \
+ test88.out \
+ test_listlbr.out \
+ test_breakindent.out \
+ test_close_count.out \
+ test_marks.out \
+ test_match_conceal.out \
NEW_TESTS =
@@ -132,7 +141,7 @@ test1.out: .gdbinit test1.in
# Check if the test.out file matches test.ok.
@/bin/sh -c "if test -f test.out; then \
- if diff test.out $*.ok; then \
+ if diff -u test.out $*.ok; then \
mv -f test.out $*.out; \
else \
echo $* FAILED >> test.log; \
diff --git a/src/nvim/testdir/test11.in b/src/nvim/testdir/test11.in
deleted file mode 100644
index 9e9e257c1d..0000000000
--- a/src/nvim/testdir/test11.in
+++ /dev/null
@@ -1,84 +0,0 @@
-Tests for autocommands:
-- FileWritePre writing a compressed file
-- FileReadPost reading a compressed file
-- BufNewFile reading a file template
-- BufReadPre decompressing the file to be read
-- FilterReadPre substituting characters in the temp file
-- FilterReadPost substituting characters after filtering
-- FileReadPre set options for decompression
-- FileReadPost decompress the file
-
-Note: This test is skipped if "gzip" is not available.
-$GZIP is made empty, "-v" would cause trouble.
-Use a FileChangedShell autocommand to avoid a prompt for "Xtestfile.gz" being
-modified outside of Vim (noticed on Solaris).
-
-STARTTEST
-:so small.vim
-:" drop out when there is no gzip program
-:if !executable("gzip")
-: e! test.ok
-: w! test.out
-: qa!
-:endif
-:let $GZIP = ""
-:au FileChangedShell * echo "caught FileChangedShell"
-:set bin
-:au FileWritePre *.gz '[,']!gzip
-:au FileWritePost *.gz undo
-:/^start of testfile/,/^end of testfile/w! Xtestfile.gz
-:au FileReadPost *.gz '[,']!gzip -d
-:$r Xtestfile.gz " Read and decompress the testfile
-:?startstart?,$w! test.out " Write contents of this file
-:au BufNewFile *.c read Xtest.c
-:/^start of test.c/+1,/^end of test.c/-1w! Xtest.c
-:e! foo.c " Will load Xtest.c
-:au FileAppendPre *.out '[,']s/new/NEW/
-:au FileAppendPost *.out !cat Xtest.c >>test.out
-:w>>test.out " Append it to the output file
-:au! FileAppendPre
-:" setup autocommands to decompress before reading and re-compress afterwards
-:au BufReadPre *.gz exe '!gzip -d ' . shellescape(expand("<afile>"))
-:au BufReadPre *.gz call rename(expand("<afile>:r"), expand("<afile>"))
-:au BufReadPost *.gz call rename(expand("<afile>"), expand("<afile>:r"))
-:au BufReadPost *.gz exe '!gzip ' . shellescape(expand("<afile>:r"))
-:e! Xtestfile.gz " Edit compressed file
-:w>>test.out " Append it to the output file
-:set shelltemp " need temp files here
-:au FilterReadPre *.out call rename(expand("<afile>"), expand("<afile>") . ".t")
-:au FilterReadPre *.out exe 'silent !sed s/e/E/ ' . shellescape(expand("<afile>")) . ".t >" . shellescape(expand("<afile>"))
-:au FilterReadPre *.out exe 'silent !rm ' . shellescape(expand("<afile>")) . '.t'
-:au FilterReadPost *.out '[,']s/x/X/g
-:e! test.out " Edit the output file
-:23,$!cat
-:23,$s/\r$// " remove CR for when sed adds them
-:au! FileReadPre *.gz exe 'silent !gzip -d ' . shellescape(expand("<afile>"))
-:au FileReadPre *.gz call rename(expand("<afile>:r"), expand("<afile>"))
-:au! FileReadPost *.gz '[,']s/l/L/
-:$r Xtestfile.gz " Read compressed file
-:w " write it, after filtering
-:au! " remove all autocommands
-:e " Edit test.out again
-:set nobin ff& " use the default fileformat for writing
-:w
-:qa!
-ENDTEST
-
-startstart
-start of testfile
-line 2 Abcdefghijklmnopqrstuvwxyz
-line 3 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
-line 4 Abcdefghijklmnopqrstuvwxyz
-line 5 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
-line 6 Abcdefghijklmnopqrstuvwxyz
-line 7 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
-line 8 Abcdefghijklmnopqrstuvwxyz
-line 9 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
-line 10 Abcdefghijklmnopqrstuvwxyz
-end of testfile
-
-start of test.c
-/*
- * Here is a new .c file
- */
-end of test.c
diff --git a/src/nvim/testdir/test11.ok b/src/nvim/testdir/test11.ok
deleted file mode 100644
index af8c5ce261..0000000000
--- a/src/nvim/testdir/test11.ok
+++ /dev/null
@@ -1,61 +0,0 @@
-startstart
-start of testfile
-line 2 Abcdefghijklmnopqrstuvwxyz
-line 3 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
-line 4 Abcdefghijklmnopqrstuvwxyz
-line 5 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
-line 6 Abcdefghijklmnopqrstuvwxyz
-line 7 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
-line 8 Abcdefghijklmnopqrstuvwxyz
-line 9 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
-line 10 Abcdefghijklmnopqrstuvwxyz
-end of testfile
-
-start of test.c
-/*
- * Here is a new .c file
- */
-end of test.c
-start of testfile
-line 2 Abcdefghijklmnopqrstuvwxyz
-line 3 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
-line 4 Abcdefghijklmnopqrstuvwxyz
-linE 5 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
-linE 6 AbcdefghijklmnopqrstuvwXyz
-linE 7 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
-linE 8 AbcdefghijklmnopqrstuvwXyz
-linE 9 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
-linE 10 AbcdefghijklmnopqrstuvwXyz
-End of testfile
-
-/*
- * HEre is a NEW .c file
- */
-/*
- * HEre is a new .c file
- */
-start of tEstfile
-linE 2 AbcdefghijklmnopqrstuvwXyz
-linE 3 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
-linE 4 AbcdefghijklmnopqrstuvwXyz
-linE 5 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
-linE 6 AbcdefghijklmnopqrstuvwXyz
-linE 7 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
-linE 8 AbcdefghijklmnopqrstuvwXyz
-linE 9 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
-linE 10 AbcdefghijklmnopqrstuvwXyz
-End of testfile
-/*
- * HEre is a new .c file
- */
-start of testfiLe
-Line 2 Abcdefghijklmnopqrstuvwxyz
-Line 3 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
-Line 4 Abcdefghijklmnopqrstuvwxyz
-Line 5 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
-Line 6 Abcdefghijklmnopqrstuvwxyz
-Line 7 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
-Line 8 Abcdefghijklmnopqrstuvwxyz
-Line 9 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
-Line 10 Abcdefghijklmnopqrstuvwxyz
-end of testfiLe
diff --git a/src/nvim/testdir/test13.in b/src/nvim/testdir/test13.in
index cb8a6fff89..6713f80e88 100644
--- a/src/nvim/testdir/test13.in
+++ b/src/nvim/testdir/test13.in
@@ -48,6 +48,12 @@ otestje3
:au BufWipeout Xtestje1 buf Xtestje1
:bwipe
:w >>test.out
+:only
+:new|set buftype=help
+:wincmd w
+:1quit
+:$put ='Final line'
+:$w >>test.out
:qa!
ENDTEST
diff --git a/src/nvim/testdir/test13.ok b/src/nvim/testdir/test13.ok
index 0f1fc347a4..66ebce63f7 100644
--- a/src/nvim/testdir/test13.ok
+++ b/src/nvim/testdir/test13.ok
@@ -28,3 +28,4 @@ testje1
contents
contents
end of testfile
+Final line
diff --git a/src/nvim/testdir/test30.in b/src/nvim/testdir/test30.in
index 3f7b9eb472..2a89eac73d 100644
--- a/src/nvim/testdir/test30.in
+++ b/src/nvim/testdir/test30.in
@@ -7,32 +7,27 @@ STARTTEST
:" first write three test files, one in each format
:set fileformat=unix
:set fileformats=
-:/^1/w! XX1
-:/^2/w! XX2
-:/^3/w! XX3
-:/^4/w! XX4
-:/^5/w! XX5
-:/^6/w! XX6
-:/^7/w! XX7
-:/^8/w! XX8
-:/^9/w! XX9
-:/^10/w! XX10
:/^unix/;/eof/-1w! XXUnix
:/^dos/;/eof/-1w! XXDos
:set bin noeol
:$w! XXMac
+Gonoeol
+:$w! XXEol
:set nobin eol
+:enew!
:bwipe XXUnix XXDos XXMac
:" create mixed format files
:if has("win32")
: !copy /b XXUnix+XXDos XXUxDs
: !copy /b XXUnix+XXMac XXUxMac
: !copy /b XXDos+XXMac XXDosMac
+: !copy /b XXMac+XXEol XXMacEol
: !copy /b XXUnix+XXDos+XXMac XXUxDsMc
:else
: !cat XXUnix XXDos >XXUxDs
: !cat XXUnix XXMac >XXUxMac
: !cat XXDos XXMac >XXDosMac
+: !cat XXMac XXEol >XXMacEol
: !cat XXUnix XXDos XXMac >XXUxDsMc
:endif
:"
@@ -97,26 +92,48 @@ STARTTEST
:e! XXDosMac
:w! XXtt53
:bwipe XXDosMac
+:e! XXEol
+ggO=&ffs
+:=&ff
+:w! XXtt54
+:bwipe XXEol
:set fileformats=dos,mac
:e! XXUxDs
:w! XXtt61
:bwipe XXUxDs
:e! XXUxMac
-:w! XXtt62
+ggO=&ffs
+:=&ff
+:w! XXtt62
:bwipe XXUxMac
:e! XXUxDsMc
:w! XXtt63
:bwipe XXUxDsMc
+:e! XXMacEol
+ggO=&ffs
+:=&ff
+:w! XXtt64
+:bwipe XXMacEol
:"
:" try reading and writing with 'fileformats' set to three formats
:set fileformats=unix,dos,mac
:e! XXUxDsMc
:w! XXtt71
:bwipe XXUxDsMc
+:e! XXEol
+ggO=&ffs
+:=&ff
+:w! XXtt72
+:bwipe XXEol
:set fileformats=mac,dos,unix
:e! XXUxDsMc
:w! XXtt81
:bwipe XXUxDsMc
+:e! XXEol
+ggO=&ffs
+:=&ff
+:w! XXtt82
+:bwipe XXEol
:" try with 'binary' set
:set fileformats=mac,unix,dos
:set binary
@@ -150,11 +167,15 @@ ggdGaEND:w >>XXtt01
:w >>XXtt51
:w >>XXtt52
:w >>XXtt53
+:w >>XXtt54
:w >>XXtt61
:w >>XXtt62
:w >>XXtt63
+:w >>XXtt64
:w >>XXtt71
+:w >>XXtt72
:w >>XXtt81
+:w >>XXtt82
:w >>XXtt91
:w >>XXtt92
:w >>XXtt93
@@ -181,11 +202,15 @@ Go4:$r XXtt41
Go5:$r XXtt51
:$r XXtt52
:$r XXtt53
+:$r XXtt54
Go6:$r XXtt61
:$r XXtt62
:$r XXtt63
+:$r XXtt64
Go7:$r XXtt71
+:$r XXtt72
Go8:$r XXtt81
+:$r XXtt82
Go9:$r XXtt91
:$r XXtt92
:$r XXtt93
@@ -195,17 +220,6 @@ Go10:$r XXUnix
:qa!
ENDTEST
-1
-2
-3
-4
-5
-6
-7
-8
-9
-10
-
unix
unix
eof
diff --git a/src/nvim/testdir/test30.ok b/src/nvim/testdir/test30.ok
index 380ce67061..b35f4f5904 100644
--- a/src/nvim/testdir/test30.ok
+++ b/src/nvim/testdir/test30.ok
@@ -70,12 +70,16 @@ END
dos
dos
mac mac END
+unix,mac:unix
+noeol
+END
6
unix
unix
dos
dos
END
+dos,mac:dos
unix
unix
mac mac
@@ -86,6 +90,7 @@ dos
dos
mac mac
END
+dos,mac:mac mac mac noeol END
7
unix
unix
@@ -93,6 +98,9 @@ dos
dos
mac mac
END
+unix,dos,mac:unix
+noeol
+END
8
unix
unix
@@ -100,6 +108,7 @@ dos
dos
mac mac
END
+mac,dos,unix:mac noeol END
9
unix
unix
diff --git a/src/nvim/testdir/test36.in b/src/nvim/testdir/test36.in
deleted file mode 100644
index 8cdb5262bd..0000000000
--- a/src/nvim/testdir/test36.in
+++ /dev/null
@@ -1,105 +0,0 @@
-Test character classes in regexp using regexpengine 0, 1, 2.
-
-STARTTEST
-/^start-here/+1
-Y:s/\%#=0\d//g
-p:s/\%#=1\d//g
-p:s/\%#=2\d//g
-p:s/\%#=0[0-9]//g
-p:s/\%#=1[0-9]//g
-p:s/\%#=2[0-9]//g
-p:s/\%#=0\D//g
-p:s/\%#=1\D//g
-p:s/\%#=2\D//g
-p:s/\%#=0[^0-9]//g
-p:s/\%#=1[^0-9]//g
-p:s/\%#=2[^0-9]//g
-p:s/\%#=0\o//g
-p:s/\%#=1\o//g
-p:s/\%#=2\o//g
-p:s/\%#=0[0-7]//g
-p:s/\%#=1[0-7]//g
-p:s/\%#=2[0-7]//g
-p:s/\%#=0\O//g
-p:s/\%#=1\O//g
-p:s/\%#=2\O//g
-p:s/\%#=0[^0-7]//g
-p:s/\%#=1[^0-7]//g
-p:s/\%#=2[^0-7]//g
-p:s/\%#=0\x//g
-p:s/\%#=1\x//g
-p:s/\%#=2\x//g
-p:s/\%#=0[0-9A-Fa-f]//g
-p:s/\%#=1[0-9A-Fa-f]//g
-p:s/\%#=2[0-9A-Fa-f]//g
-p:s/\%#=0\X//g
-p:s/\%#=1\X//g
-p:s/\%#=2\X//g
-p:s/\%#=0[^0-9A-Fa-f]//g
-p:s/\%#=1[^0-9A-Fa-f]//g
-p:s/\%#=2[^0-9A-Fa-f]//g
-p:s/\%#=0\w//g
-p:s/\%#=1\w//g
-p:s/\%#=2\w//g
-p:s/\%#=0[0-9A-Za-z_]//g
-p:s/\%#=1[0-9A-Za-z_]//g
-p:s/\%#=2[0-9A-Za-z_]//g
-p:s/\%#=0\W//g
-p:s/\%#=1\W//g
-p:s/\%#=2\W//g
-p:s/\%#=0[^0-9A-Za-z_]//g
-p:s/\%#=1[^0-9A-Za-z_]//g
-p:s/\%#=2[^0-9A-Za-z_]//g
-p:s/\%#=0\h//g
-p:s/\%#=1\h//g
-p:s/\%#=2\h//g
-p:s/\%#=0[A-Za-z_]//g
-p:s/\%#=1[A-Za-z_]//g
-p:s/\%#=2[A-Za-z_]//g
-p:s/\%#=0\H//g
-p:s/\%#=1\H//g
-p:s/\%#=2\H//g
-p:s/\%#=0[^A-Za-z_]//g
-p:s/\%#=1[^A-Za-z_]//g
-p:s/\%#=2[^A-Za-z_]//g
-p:s/\%#=0\a//g
-p:s/\%#=1\a//g
-p:s/\%#=2\a//g
-p:s/\%#=0[A-Za-z]//g
-p:s/\%#=1[A-Za-z]//g
-p:s/\%#=2[A-Za-z]//g
-p:s/\%#=0\A//g
-p:s/\%#=1\A//g
-p:s/\%#=2\A//g
-p:s/\%#=0[^A-Za-z]//g
-p:s/\%#=1[^A-Za-z]//g
-p:s/\%#=2[^A-Za-z]//g
-p:s/\%#=0\l//g
-p:s/\%#=1\l//g
-p:s/\%#=2\l//g
-p:s/\%#=0[a-z]//g
-p:s/\%#=1[a-z]//g
-p:s/\%#=2[a-z]//g
-p:s/\%#=0\L//g
-p:s/\%#=1\L//g
-p:s/\%#=2\L//g
-p:s/\%#=0[^a-z]//g
-p:s/\%#=1[^a-z]//g
-p:s/\%#=2[^a-z]//g
-p:s/\%#=0\u//g
-p:s/\%#=1\u//g
-p:s/\%#=2\u//g
-p:s/\%#=0[A-Z]//g
-p:s/\%#=1[A-Z]//g
-p:s/\%#=2[A-Z]//g
-p:s/\%#=0\U//g
-p:s/\%#=1\U//g
-p:s/\%#=2\U//g
-p:s/\%#=0[^A-Z]//g
-p:s/\%#=1[^A-Z]//g
-p:s/\%#=2[^A-Z]//g
-:/^start-here/+1,$wq! test.out
-ENDTEST
-
-start-here
- !"#$%&'()#+'-./0123456789:;<=>?@ABCDEFGHIXYZ[\]^_`abcdefghiwxyz{|}~
diff --git a/src/nvim/testdir/test36.ok b/src/nvim/testdir/test36.ok
deleted file mode 100644
index f72a74b2b7..0000000000
--- a/src/nvim/testdir/test36.ok
+++ /dev/null
@@ -1,96 +0,0 @@
- !"#$%&'()#+'-./:;<=>?@ABCDEFGHIXYZ[\]^_`abcdefghiwxyz{|}~
- !"#$%&'()#+'-./:;<=>?@ABCDEFGHIXYZ[\]^_`abcdefghiwxyz{|}~
- !"#$%&'()#+'-./:;<=>?@ABCDEFGHIXYZ[\]^_`abcdefghiwxyz{|}~
- !"#$%&'()#+'-./:;<=>?@ABCDEFGHIXYZ[\]^_`abcdefghiwxyz{|}~
- !"#$%&'()#+'-./:;<=>?@ABCDEFGHIXYZ[\]^_`abcdefghiwxyz{|}~
- !"#$%&'()#+'-./:;<=>?@ABCDEFGHIXYZ[\]^_`abcdefghiwxyz{|}~
-0123456789
-0123456789
-0123456789
-0123456789
-0123456789
-0123456789
- !"#$%&'()#+'-./89:;<=>?@ABCDEFGHIXYZ[\]^_`abcdefghiwxyz{|}~
- !"#$%&'()#+'-./89:;<=>?@ABCDEFGHIXYZ[\]^_`abcdefghiwxyz{|}~
- !"#$%&'()#+'-./89:;<=>?@ABCDEFGHIXYZ[\]^_`abcdefghiwxyz{|}~
- !"#$%&'()#+'-./89:;<=>?@ABCDEFGHIXYZ[\]^_`abcdefghiwxyz{|}~
- !"#$%&'()#+'-./89:;<=>?@ABCDEFGHIXYZ[\]^_`abcdefghiwxyz{|}~
- !"#$%&'()#+'-./89:;<=>?@ABCDEFGHIXYZ[\]^_`abcdefghiwxyz{|}~
-01234567
-01234567
-01234567
-01234567
-01234567
-01234567
- !"#$%&'()#+'-./:;<=>?@GHIXYZ[\]^_`ghiwxyz{|}~
- !"#$%&'()#+'-./:;<=>?@GHIXYZ[\]^_`ghiwxyz{|}~
- !"#$%&'()#+'-./:;<=>?@GHIXYZ[\]^_`ghiwxyz{|}~
- !"#$%&'()#+'-./:;<=>?@GHIXYZ[\]^_`ghiwxyz{|}~
- !"#$%&'()#+'-./:;<=>?@GHIXYZ[\]^_`ghiwxyz{|}~
- !"#$%&'()#+'-./:;<=>?@GHIXYZ[\]^_`ghiwxyz{|}~
-0123456789ABCDEFabcdef
-0123456789ABCDEFabcdef
-0123456789ABCDEFabcdef
-0123456789ABCDEFabcdef
-0123456789ABCDEFabcdef
-0123456789ABCDEFabcdef
- !"#$%&'()#+'-./:;<=>?@[\]^`{|}~
- !"#$%&'()#+'-./:;<=>?@[\]^`{|}~
- !"#$%&'()#+'-./:;<=>?@[\]^`{|}~
- !"#$%&'()#+'-./:;<=>?@[\]^`{|}~
- !"#$%&'()#+'-./:;<=>?@[\]^`{|}~
- !"#$%&'()#+'-./:;<=>?@[\]^`{|}~
-0123456789ABCDEFGHIXYZ_abcdefghiwxyz
-0123456789ABCDEFGHIXYZ_abcdefghiwxyz
-0123456789ABCDEFGHIXYZ_abcdefghiwxyz
-0123456789ABCDEFGHIXYZ_abcdefghiwxyz
-0123456789ABCDEFGHIXYZ_abcdefghiwxyz
-0123456789ABCDEFGHIXYZ_abcdefghiwxyz
- !"#$%&'()#+'-./0123456789:;<=>?@[\]^`{|}~
- !"#$%&'()#+'-./0123456789:;<=>?@[\]^`{|}~
- !"#$%&'()#+'-./0123456789:;<=>?@[\]^`{|}~
- !"#$%&'()#+'-./0123456789:;<=>?@[\]^`{|}~
- !"#$%&'()#+'-./0123456789:;<=>?@[\]^`{|}~
- !"#$%&'()#+'-./0123456789:;<=>?@[\]^`{|}~
-ABCDEFGHIXYZ_abcdefghiwxyz
-ABCDEFGHIXYZ_abcdefghiwxyz
-ABCDEFGHIXYZ_abcdefghiwxyz
-ABCDEFGHIXYZ_abcdefghiwxyz
-ABCDEFGHIXYZ_abcdefghiwxyz
-ABCDEFGHIXYZ_abcdefghiwxyz
- !"#$%&'()#+'-./0123456789:;<=>?@[\]^_`{|}~
- !"#$%&'()#+'-./0123456789:;<=>?@[\]^_`{|}~
- !"#$%&'()#+'-./0123456789:;<=>?@[\]^_`{|}~
- !"#$%&'()#+'-./0123456789:;<=>?@[\]^_`{|}~
- !"#$%&'()#+'-./0123456789:;<=>?@[\]^_`{|}~
- !"#$%&'()#+'-./0123456789:;<=>?@[\]^_`{|}~
-ABCDEFGHIXYZabcdefghiwxyz
-ABCDEFGHIXYZabcdefghiwxyz
-ABCDEFGHIXYZabcdefghiwxyz
-ABCDEFGHIXYZabcdefghiwxyz
-ABCDEFGHIXYZabcdefghiwxyz
-ABCDEFGHIXYZabcdefghiwxyz
- !"#$%&'()#+'-./0123456789:;<=>?@ABCDEFGHIXYZ[\]^_`{|}~
- !"#$%&'()#+'-./0123456789:;<=>?@ABCDEFGHIXYZ[\]^_`{|}~
- !"#$%&'()#+'-./0123456789:;<=>?@ABCDEFGHIXYZ[\]^_`{|}~
- !"#$%&'()#+'-./0123456789:;<=>?@ABCDEFGHIXYZ[\]^_`{|}~
- !"#$%&'()#+'-./0123456789:;<=>?@ABCDEFGHIXYZ[\]^_`{|}~
- !"#$%&'()#+'-./0123456789:;<=>?@ABCDEFGHIXYZ[\]^_`{|}~
-abcdefghiwxyz
-abcdefghiwxyz
-abcdefghiwxyz
-abcdefghiwxyz
-abcdefghiwxyz
-abcdefghiwxyz
- !"#$%&'()#+'-./0123456789:;<=>?@[\]^_`abcdefghiwxyz{|}~
- !"#$%&'()#+'-./0123456789:;<=>?@[\]^_`abcdefghiwxyz{|}~
- !"#$%&'()#+'-./0123456789:;<=>?@[\]^_`abcdefghiwxyz{|}~
- !"#$%&'()#+'-./0123456789:;<=>?@[\]^_`abcdefghiwxyz{|}~
- !"#$%&'()#+'-./0123456789:;<=>?@[\]^_`abcdefghiwxyz{|}~
- !"#$%&'()#+'-./0123456789:;<=>?@[\]^_`abcdefghiwxyz{|}~
-ABCDEFGHIXYZ
-ABCDEFGHIXYZ
-ABCDEFGHIXYZ
-ABCDEFGHIXYZ
-ABCDEFGHIXYZ
-ABCDEFGHIXYZ
diff --git a/src/nvim/testdir/test45.in b/src/nvim/testdir/test45.in
deleted file mode 100644
index e5af5073d9..0000000000
--- a/src/nvim/testdir/test45.in
+++ /dev/null
@@ -1,80 +0,0 @@
-Tests for folding. vim: set ft=vim :
-
-STARTTEST
-:so small.vim
-:" We also need the +syntax feature here.
-:if !has("syntax")
- e! test.ok
- w! test.out
- qa!
-:endif
-:" basic test if a fold can be created, opened, moving to the end and closed
-/^1
-zf2j:call append("$", "manual " . getline(foldclosed(".")))
-zo:call append("$", foldclosed("."))
-]z:call append("$", getline("."))
-zc:call append("$", getline(foldclosed(".")))
-:" test folding with markers.
-:set fdm=marker fdl=1 fdc=3
-/^5
-:call append("$", "marker " . foldlevel("."))
-[z:call append("$", foldlevel("."))
-jo{{ r{jj:call append("$", foldlevel("."))
-kYpj:call append("$", foldlevel("."))
-:" test folding with indent
-:set fdm=indent sw=2
-/^2 b
-i jI :call append("$", "indent " . foldlevel("."))
-k:call append("$", foldlevel("."))
-:" test syntax folding
-:set fdm=syntax fdl=0
-:syn region Hup start="dd" end="ii" fold contains=Fd1,Fd2,Fd3
-:syn region Fd1 start="ee" end="ff" fold contained
-:syn region Fd2 start="gg" end="hh" fold contained
-:syn region Fd3 start="commentstart" end="commentend" fold contained
-Gzk:call append("$", "folding " . getline("."))
-k:call append("$", getline("."))
-jAcommentstart Acommentend:set fdl=1
-3j:call append("$", getline("."))
-:set fdl=0
-zO j:call append("$", getline("."))
-:" test expression folding
-:fun Flvl()
- let l = getline(v:lnum)
- if l =~ "bb$"
- return 2
- elseif l =~ "gg$"
- return "s1"
- elseif l =~ "ii$"
- return ">2"
- elseif l =~ "kk$"
- return "0"
- endif
- return "="
-endfun
-:set fdm=expr fde=Flvl()
-/bb$
-:call append("$", "expr " . foldlevel("."))
-/hh$
-:call append("$", foldlevel("."))
-/ii$
-:call append("$", foldlevel("."))
-/kk$
-:call append("$", foldlevel("."))
-:/^last/+1,$w! test.out
-:delfun Flvl
-:qa!
-ENDTEST
-
-1 aa
-2 bb
-3 cc
-4 dd {{{
-5 ee {{{ }}}
-6 ff }}}
-7 gg
-8 hh
-9 ii
-a jj
-b kk
-last
diff --git a/src/nvim/testdir/test45.ok b/src/nvim/testdir/test45.ok
deleted file mode 100644
index f04996e337..0000000000
--- a/src/nvim/testdir/test45.ok
+++ /dev/null
@@ -1,18 +0,0 @@
-manual 1 aa
--1
-3 cc
-1 aa
-marker 2
-1
-1
-0
-indent 2
-1
-folding 9 ii
- 3 cc
-7 gg
-8 hh
-expr 2
-1
-2
-0
diff --git a/src/nvim/testdir/test47.in b/src/nvim/testdir/test47.in
index 13ad82462f..f15eaf0f8f 100644
--- a/src/nvim/testdir/test47.in
+++ b/src/nvim/testdir/test47.in
@@ -1,5 +1,7 @@
Tests for vertical splits and filler lines in diff mode
+Also tests restoration of saved options by :diffoff.
+
STARTTEST
:so small.vim
:" Disable the title to avoid xterm keeping the wrong one.
@@ -10,8 +12,19 @@ pkdd:w! Xtest
ddGpkkrXoxxx:w! Xtest2
:file Nop
ggoyyyjjjozzzz
+:set foldmethod=marker foldcolumn=4
+:redir => nodiffsettings
+:silent! :set diff? fdm? fdc? scb? crb? wrap?
+:redir END
:vert diffsplit Xtest
:vert diffsplit Xtest2
+:redir => diffsettings
+:silent! :set diff? fdm? fdc? scb? crb? wrap?
+:redir END
+:let diff_fdm = &fdm
+:let diff_fdc = &fdc
+:" repeat entering diff mode here to see if this saves the wrong settings
+:diffthis
:" jump to second window for a moment to have filler line appear at start of
:" first window
ggpgg:let one = winline()
@@ -36,8 +49,36 @@ j:let three = three . "-" . winline()
:call append("$", two)
:call append("$", three)
:$-2,$w! test.out
-:" Test that diffing shows correct filler lines
+:"
+:" Test diffoff
:diffoff!
+1
+:let &diff = 1
+:let &fdm = diff_fdm
+:let &fdc = diff_fdc
+4
+:diffoff!
+:$put =nodiffsettings
+:$put =diffsettings
+1
+:redir => nd1
+:silent! :set diff? fdm? fdc? scb? crb? wrap?
+:redir END
+
+:redir => nd2
+:silent! :set diff? fdm? fdc? scb? crb? wrap?
+:redir END
+
+:redir => nd3
+:silent! :set diff? fdm? fdc? scb? crb? wrap?
+:redir END
+
+:$put =nd1
+:$put =nd2
+:$put =nd3
+:$-39,$w >> test.out
+:"
+:" Test that diffing shows correct filler lines
:windo :bw!
:enew
:put =range(4,10)
@@ -51,7 +92,7 @@ j:let three = three . "-" . winline()
:enew
:put =w0
:.w >> test.out
-:unlet! one two three w0
+:unlet! one two three nodiffsettings diffsettings diff_fdm diff_fdc nd1 nd2 nd3 w0
:qa!
ENDTEST
diff --git a/src/nvim/testdir/test47.ok b/src/nvim/testdir/test47.ok
index b1cba92b1c..83e96571ad 100644
--- a/src/nvim/testdir/test47.ok
+++ b/src/nvim/testdir/test47.ok
@@ -1,4 +1,44 @@
2-4-5-6-8-9
1-2-4-5-8
2-3-4-5-6-7-8
+
+
+nodiff
+ foldmethod=marker
+ foldcolumn=4
+noscrollbind
+nocursorbind
+ wrap
+
+
+ diff
+ foldmethod=diff
+ foldcolumn=2
+ scrollbind
+ cursorbind
+nowrap
+
+
+nodiff
+ foldmethod=marker
+ foldcolumn=4
+noscrollbind
+nocursorbind
+ wrap
+
+
+nodiff
+ foldmethod=marker
+ foldcolumn=4
+noscrollbind
+nocursorbind
+ wrap
+
+
+nodiff
+ foldmethod=marker
+ foldcolumn=4
+noscrollbind
+nocursorbind
+ wrap
1
diff --git a/src/nvim/testdir/test49.vim b/src/nvim/testdir/test49.vim
index afee9d882c..70d388b06a 100644
--- a/src/nvim/testdir/test49.vim
+++ b/src/nvim/testdir/test49.vim
@@ -1,6 +1,6 @@
" Vim script language tests
" Author: Servatius Brandt <Servatius.Brandt@fujitsu-siemens.com>
-" Last Change: 2013 Jun 06
+" Last Change: 2015 Sep 25
"-------------------------------------------------------------------------------
" Test environment {{{1
@@ -5188,19 +5188,19 @@ catch /.*/
Xpath 65536 " X: 65536
let exception = v:exception
let throwpoint = v:throwpoint
- call CHECK(1, "oops", '\<F\.\.G\.\.T\>', '\<2\>')
+ call CHECK(1, "oops", '\<F\[1]\.\.G\[1]\.\.T\>', '\<2\>')
exec "let exception = v:exception"
exec "let throwpoint = v:throwpoint"
- call CHECK(2, "oops", '\<F\.\.G\.\.T\>', '\<2\>')
+ call CHECK(2, "oops", '\<F\[1]\.\.G\[1]\.\.T\>', '\<2\>')
CmdException
CmdThrowpoint
- call CHECK(3, "oops", '\<F\.\.G\.\.T\>', '\<2\>')
+ call CHECK(3, "oops", '\<F\[1]\.\.G\[1]\.\.T\>', '\<2\>')
call FuncException()
call FuncThrowpoint()
- call CHECK(4, "oops", '\<F\.\.G\.\.T\>', '\<2\>')
+ call CHECK(4, "oops", '\<F\[1]\.\.G\[1]\.\.T\>', '\<2\>')
exec "source" scriptException
exec "source" scriptThrowPoint
- call CHECK(5, "oops", '\<F\.\.G\.\.T\>', '\<2\>')
+ call CHECK(5, "oops", '\<F\[1]\.\.G\[1]\.\.T\>', '\<2\>')
try
Xpath 131072 " X: 131072
call G("arrgh", 4)
@@ -5208,7 +5208,7 @@ catch /.*/
Xpath 262144 " X: 262144
let exception = v:exception
let throwpoint = v:throwpoint
- call CHECK(6, "arrgh", '\<G\.\.T\>', '\<4\>')
+ call CHECK(6, "arrgh", '\<G\[1]\.\.T\>', '\<4\>')
try
Xpath 524288 " X: 524288
let g:arg = "autsch"
@@ -5226,7 +5226,7 @@ catch /.*/
Xpath 2097152 " X: 2097152
let exception = v:exception
let throwpoint = v:throwpoint
- call CHECK(8, "arrgh", '\<G\.\.T\>', '\<4\>')
+ call CHECK(8, "arrgh", '\<G\[1]\.\.T\>', '\<4\>')
try
Xpath 4194304 " X: 4194304
let g:arg = "brrrr"
@@ -5242,27 +5242,27 @@ catch /.*/
Xpath 16777216 " X: 16777216
let exception = v:exception
let throwpoint = v:throwpoint
- call CHECK(10, "arrgh", '\<G\.\.T\>', '\<4\>')
+ call CHECK(10, "arrgh", '\<G\[1]\.\.T\>', '\<4\>')
endtry
Xpath 33554432 " X: 33554432
let exception = v:exception
let throwpoint = v:throwpoint
- call CHECK(11, "arrgh", '\<G\.\.T\>', '\<4\>')
+ call CHECK(11, "arrgh", '\<G\[1]\.\.T\>', '\<4\>')
endtry
Xpath 67108864 " X: 67108864
let exception = v:exception
let throwpoint = v:throwpoint
- call CHECK(12, "arrgh", '\<G\.\.T\>', '\<4\>')
+ call CHECK(12, "arrgh", '\<G\[1]\.\.T\>', '\<4\>')
finally
Xpath 134217728 " X: 134217728
let exception = v:exception
let throwpoint = v:throwpoint
- call CHECK(13, "oops", '\<F\.\.G\.\.T\>', '\<2\>')
+ call CHECK(13, "oops", '\<F\[1]\.\.G\[1]\.\.T\>', '\<2\>')
endtry
Xpath 268435456 " X: 268435456
let exception = v:exception
let throwpoint = v:throwpoint
- call CHECK(14, "oops", '\<F\.\.G\.\.T\>', '\<2\>')
+ call CHECK(14, "oops", '\<F\[1]\.\.G\[1]\.\.T\>', '\<2\>')
finally
Xpath 536870912 " X: 536870912
let exception = v:exception
diff --git a/src/nvim/testdir/test55.in b/src/nvim/testdir/test55.in
index c4e82d429c..9e3c1168cc 100644
--- a/src/nvim/testdir/test55.in
+++ b/src/nvim/testdir/test55.in
@@ -282,6 +282,177 @@ let l = [0, 1, 2, 3]
: $put =ps
: endfor
:endfor
+:"
+:" Unletting locked variables
+:$put ='Unletting:'
+:for depth in range(5)
+: $put ='depth is ' . depth
+: for u in range(3)
+: unlet l
+: let l = [0, [1, [2, 3]], {4: 5, 6: {7: 8}}]
+: exe "lockvar " . depth . " l"
+: if u == 1
+: exe "unlockvar l"
+: elseif u == 2
+: exe "unlockvar " . depth . " l"
+: endif
+: let ps = islocked("l").islocked("l[1]").islocked("l[1][1]").islocked("l[1][1][0]").'-'.islocked("l[2]").islocked("l[2]['6']").islocked("l[2]['6'][7]")
+: $put =ps
+: let ps = ''
+: try
+: unlet l[2]['6'][7]
+: let ps .= 'p'
+: catch
+: let ps .= 'F'
+: endtry
+: try
+: unlet l[2][6]
+: let ps .= 'p'
+: catch
+: let ps .= 'F'
+: endtry
+: try
+: unlet l[2]
+: let ps .= 'p'
+: catch
+: let ps .= 'F'
+: endtry
+: try
+: unlet l[1][1][0]
+: let ps .= 'p'
+: catch
+: let ps .= 'F'
+: endtry
+: try
+: unlet l[1][1]
+: let ps .= 'p'
+: catch
+: let ps .= 'F'
+: endtry
+: try
+: unlet l[1]
+: let ps .= 'p'
+: catch
+: let ps .= 'F'
+: endtry
+: try
+: unlet l
+: let ps .= 'p'
+: catch
+: let ps .= 'F'
+: endtry
+: $put =ps
+: endfor
+:endfor
+:"
+:" Locked variables and :unlet or list / dict functions
+:$put ='Locks and commands or functions:'
+:"
+:$put ='No :unlet after lock on dict:'
+:unlet! d
+:let d = {'a': 99, 'b': 100}
+:lockvar 1 d
+:try
+: unlet d.a
+: $put ='did :unlet'
+:catch
+: $put =v:exception[:16]
+:endtry
+:$put =string(d)
+:"
+:$put =':unlet after lock on dict item:'
+:unlet! d
+:let d = {'a': 99, 'b': 100}
+:lockvar d.a
+:try
+: unlet d.a
+: $put ='did :unlet'
+:catch
+: $put =v:exception[:16]
+:endtry
+:$put =string(d)
+:"
+:$put ='filter() after lock on dict item:'
+:unlet! d
+:let d = {'a': 99, 'b': 100}
+:lockvar d.a
+:try
+: call filter(d, 'v:key != "a"')
+: $put ='did filter()'
+:catch
+: $put =v:exception[:16]
+:endtry
+:$put =string(d)
+:"
+:$put ='map() after lock on dict:'
+:unlet! d
+:let d = {'a': 99, 'b': 100}
+:lockvar 1 d
+:try
+: call map(d, 'v:val + 200')
+: $put ='did map()'
+:catch
+: $put =v:exception[:16]
+:endtry
+:$put =string(d)
+:"
+:$put ='No extend() after lock on dict item:'
+:unlet! d
+:let d = {'a': 99, 'b': 100}
+:lockvar d.a
+:try
+: $put =string(extend(d, {'a': 123}))
+: $put ='did extend()'
+:catch
+: $put =v:exception[:14]
+:endtry
+:$put =string(d)
+:"
+:$put ='No remove() of write-protected scope-level variable:'
+:fun! Tfunc(this_is_a_loooooooooong_parameter_name)
+: try
+: $put =string(remove(a:, 'this_is_a_loooooooooong_parameter_name'))
+: $put ='did remove()'
+: catch
+: $put =v:exception[:14]
+: endtry
+:endfun
+:call Tfunc('testval')
+:"
+:$put ='No extend() of write-protected scope-level variable:'
+:fun! Tfunc(this_is_a_loooooooooong_parameter_name)
+: try
+: $put =string(extend(a:, {'this_is_a_loooooooooong_parameter_name': 1234}))
+: $put ='did extend()'
+: catch
+: $put =v:exception[:14]
+: endtry
+:endfun
+:call Tfunc('testval')
+:"
+:$put ='No :unlet of variable in locked scope:'
+:let b:testvar = 123
+:lockvar 1 b:
+:try
+: unlet b:testvar
+: $put ='b:testvar was :unlet: '. (!exists('b:testvar'))
+:catch
+: $put =v:exception[:16]
+:endtry
+:unlockvar 1 b:
+:unlet! b:testvar
+:"
+:$put ='No :let += of locked list variable:'
+:let l = ['a', 'b', 3]
+:lockvar 1 l
+:try
+: let l += ['x']
+: $put ='did :let +='
+:catch
+: $put =v:exception[:14]
+:endtry
+:$put =string(l)
+:"
:unlet l
:let l = [1, 2, 3, 4]
:lockvar! l
diff --git a/src/nvim/testdir/test55.ok b/src/nvim/testdir/test55.ok
index ba029b2898..607a95ead9 100644
--- a/src/nvim/testdir/test55.ok
+++ b/src/nvim/testdir/test55.ok
@@ -86,6 +86,67 @@ FFFFFFF
FFpFFpp
0000-000
ppppppp
+Unletting:
+depth is 0
+0000-000
+ppppppp
+0000-000
+ppppppp
+0000-000
+ppppppp
+depth is 1
+1000-000
+ppFppFp
+0000-000
+ppppppp
+0000-000
+ppppppp
+depth is 2
+1100-100
+pFFpFFp
+0000-000
+ppppppp
+0000-000
+ppppppp
+depth is 3
+1110-110
+FFFFFFp
+0010-010
+FppFppp
+0000-000
+ppppppp
+depth is 4
+1111-111
+FFFFFFp
+0011-011
+FppFppp
+0000-000
+ppppppp
+Locks and commands or functions:
+No :unlet after lock on dict:
+Vim(unlet):E741:
+{'a': 99, 'b': 100}
+:unlet after lock on dict item:
+did :unlet
+{'b': 100}
+filter() after lock on dict item:
+did filter()
+{'b': 100}
+map() after lock on dict:
+did map()
+{'a': 299, 'b': 300}
+No extend() after lock on dict item:
+Vim(put):E741:
+{'a': 99, 'b': 100}
+No remove() of write-protected scope-level variable:
+Vim(put):E795:
+No extend() of write-protected scope-level variable:
+Vim(put):E742:
+No :unlet of variable in locked scope:
+Vim(unlet):E741:
+No :let += of locked list variable:
+Vim(let):E741:
+['a', 'b', 3]
[1, 2, 3, 4]
[1, 2, 3, 4]
[1, 2, 3, 4]
diff --git a/src/nvim/testdir/test83-tags2 b/src/nvim/testdir/test83-tags2
deleted file mode 100644
index 7f9f21b0eb..0000000000
--- a/src/nvim/testdir/test83-tags2
+++ /dev/null
@@ -1,2 +0,0 @@
-!_TAG_FILE_ENCODING cp932 //
-`ab Xtags2.txt /`ab
diff --git a/src/nvim/testdir/test83-tags3 b/src/nvim/testdir/test83-tags3
deleted file mode 100644
index 0cb6591562..0000000000
--- a/src/nvim/testdir/test83-tags3
+++ /dev/null
@@ -1,102 +0,0 @@
-!_TAG_FILE_SORTED 1 //
-!_TAG_FILE_ENCODING cp932 //
-abc1 Xtags3.txt /`ab
-abc2 Xtags3.txt /`ab
-abc3 Xtags3.txt /`ab
-abc4 Xtags3.txt /`ab
-abc5 Xtags3.txt /`ab
-abc6 Xtags3.txt /`ab
-abc7 Xtags3.txt /`ab
-abc8 Xtags3.txt /`ab
-abc9 Xtags3.txt /`ab
-abc10 Xtags3.txt /`ab
-abc11 Xtags3.txt /`ab
-abc12 Xtags3.txt /`ab
-abc13 Xtags3.txt /`ab
-abc14 Xtags3.txt /`ab
-abc15 Xtags3.txt /`ab
-abc16 Xtags3.txt /`ab
-abc17 Xtags3.txt /`ab
-abc18 Xtags3.txt /`ab
-abc19 Xtags3.txt /`ab
-abc20 Xtags3.txt /`ab
-abc21 Xtags3.txt /`ab
-abc22 Xtags3.txt /`ab
-abc23 Xtags3.txt /`ab
-abc24 Xtags3.txt /`ab
-abc25 Xtags3.txt /`ab
-abc26 Xtags3.txt /`ab
-abc27 Xtags3.txt /`ab
-abc28 Xtags3.txt /`ab
-abc29 Xtags3.txt /`ab
-abc30 Xtags3.txt /`ab
-abc31 Xtags3.txt /`ab
-abc32 Xtags3.txt /`ab
-abc33 Xtags3.txt /`ab
-abc34 Xtags3.txt /`ab
-abc35 Xtags3.txt /`ab
-abc36 Xtags3.txt /`ab
-abc37 Xtags3.txt /`ab
-abc38 Xtags3.txt /`ab
-abc39 Xtags3.txt /`ab
-abc40 Xtags3.txt /`ab
-abc41 Xtags3.txt /`ab
-abc42 Xtags3.txt /`ab
-abc43 Xtags3.txt /`ab
-abc44 Xtags3.txt /`ab
-abc45 Xtags3.txt /`ab
-abc46 Xtags3.txt /`ab
-abc47 Xtags3.txt /`ab
-abc48 Xtags3.txt /`ab
-abc49 Xtags3.txt /`ab
-abc50 Xtags3.txt /`ab
-abc51 Xtags3.txt /`ab
-abc52 Xtags3.txt /`ab
-abc53 Xtags3.txt /`ab
-abc54 Xtags3.txt /`ab
-abc55 Xtags3.txt /`ab
-abc56 Xtags3.txt /`ab
-abc57 Xtags3.txt /`ab
-abc58 Xtags3.txt /`ab
-abc59 Xtags3.txt /`ab
-abc60 Xtags3.txt /`ab
-abc61 Xtags3.txt /`ab
-abc62 Xtags3.txt /`ab
-abc63 Xtags3.txt /`ab
-abc64 Xtags3.txt /`ab
-abc65 Xtags3.txt /`ab
-abc66 Xtags3.txt /`ab
-abc67 Xtags3.txt /`ab
-abc68 Xtags3.txt /`ab
-abc69 Xtags3.txt /`ab
-abc70 Xtags3.txt /`ab
-abc71 Xtags3.txt /`ab
-abc72 Xtags3.txt /`ab
-abc73 Xtags3.txt /`ab
-abc74 Xtags3.txt /`ab
-abc75 Xtags3.txt /`ab
-abc76 Xtags3.txt /`ab
-abc77 Xtags3.txt /`ab
-abc78 Xtags3.txt /`ab
-abc79 Xtags3.txt /`ab
-abc80 Xtags3.txt /`ab
-abc81 Xtags3.txt /`ab
-abc82 Xtags3.txt /`ab
-abc83 Xtags3.txt /`ab
-abc84 Xtags3.txt /`ab
-abc85 Xtags3.txt /`ab
-abc86 Xtags3.txt /`ab
-abc87 Xtags3.txt /`ab
-abc88 Xtags3.txt /`ab
-abc89 Xtags3.txt /`ab
-abc90 Xtags3.txt /`ab
-abc91 Xtags3.txt /`ab
-abc92 Xtags3.txt /`ab
-abc93 Xtags3.txt /`ab
-abc94 Xtags3.txt /`ab
-abc95 Xtags3.txt /`ab
-abc96 Xtags3.txt /`ab
-abc97 Xtags3.txt /`ab
-abc98 Xtags3.txt /`ab
-abc99 Xtags3.txt /`ab
-abc100 Xtags3.txt /`ab
diff --git a/src/nvim/testdir/test83.in b/src/nvim/testdir/test83.in
deleted file mode 100644
index d54b1bcddd..0000000000
--- a/src/nvim/testdir/test83.in
+++ /dev/null
@@ -1,75 +0,0 @@
-Tests for tag search with !_TAG_FILE_ENCODING.
-
-STARTTEST
-:so mbyte.vim
-:if !has('iconv') || iconv("\x82\x60", "cp932", "utf-8") != "\uff21"
-: e! test.ok
-: w! test.out
-: qa!
-:endif
-
-:/^text for tags1$/,/^text for tags1$/+1w! Xtags1.txt
-:/^text for tags2$/,/^text for tags2$/+1w! Xtags2.txt
-:/^text for tags3$/,/^text for tags3$/+1w! Xtags3.txt
-:/^tags1$/+1,/^tags1-end$/-1w! Xtags1
-
-ggdG
-
-:call setline('.', 'Results of test83')
-
-:" case1:
-:new
-:set tags=Xtags1
-:let v:errmsg = ''
-:tag abcdefghijklmnopqrs
-:if v:errmsg =~ 'E426:' || getline('.') != 'abcdefghijklmnopqrs'
-: close
-: put ='case1: failed'
-:else
-: close
-: put ='case1: ok'
-:endif
-
-:" case2:
-:new
-:set tags=test83-tags2
-:let v:errmsg = ''
-:tag /.BC
-:if v:errmsg =~ 'E426:' || getline('.') != 'ABC'
-: close
-: put ='case2: failed'
-:else
-: close
-: put ='case2: ok'
-:endif
-
-:" case3:
-:new
-:set tags=test83-tags3
-:let v:errmsg = ''
-:tag abc50
-:if v:errmsg =~ 'E426:' || getline('.') != 'ABC'
-: close
-: put ='case3: failed'
-:else
-: close
-: put ='case3: ok'
-:endif
-:close
-
-:wq! test.out
-ENDTEST
-
-text for tags1
-abcdefghijklmnopqrs
-
-text for tags2
-ABC
-
-text for tags3
-ABC
-
-tags1
-!_TAG_FILE_ENCODING utf-8 //
-abcdefghijklmnopqrs Xtags1.txt /abcdefghijklmnopqrs
-tags1-end
diff --git a/src/nvim/testdir/test83.ok b/src/nvim/testdir/test83.ok
deleted file mode 100644
index 61a1a04a18..0000000000
--- a/src/nvim/testdir/test83.ok
+++ /dev/null
@@ -1,4 +0,0 @@
-Results of test83
-case1: ok
-case2: ok
-case3: ok
diff --git a/src/nvim/testdir/test88.in b/src/nvim/testdir/test88.in
index c2e6a752fa..9e43f703e9 100644
--- a/src/nvim/testdir/test88.in
+++ b/src/nvim/testdir/test88.in
@@ -71,6 +71,17 @@ 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)
diff --git a/src/nvim/testdir/test88.ok b/src/nvim/testdir/test88.ok
index e29698b7bd..12949f274a 100644
--- a/src/nvim/testdir/test88.ok
+++ b/src/nvim/testdir/test88.ok
@@ -22,3 +22,8 @@ end:
9:25
9:26
9:26
+9:1
+9:9
+9:17
+9:25
+9:26
diff --git a/src/nvim/testdir/test_charsearch.in b/src/nvim/testdir/test_charsearch.in
deleted file mode 100644
index 5085cb39bc..0000000000
--- a/src/nvim/testdir/test_charsearch.in
+++ /dev/null
@@ -1,25 +0,0 @@
-Test for character searches
-
-STARTTEST
-:so small.vim
-:" check that "fe" and ";" work
-/^X
-ylfep;;p,,p:
-:" check that save/restore works
-/^Y
-ylfep:let csave = getcharsearch()
-fip:call setcharsearch(csave)
-;p;p:
-:" check that setcharsearch() changes the settins.
-/^Z
-ylfep:call setcharsearch({'char': 'k'})
-;p:call setcharsearch({'forward': 0})
-$;p:call setcharseearch({'until'}: 1})
-;;p:
-:/^X/,$w! test.out
-:qa!
-ENDTEST
-
-Xabcdefghijkemnopqretuvwxyz
-Yabcdefghijkemnopqretuvwxyz
-Zabcdefghijkemnokqretkvwxyz
diff --git a/src/nvim/testdir/test_charsearch.ok b/src/nvim/testdir/test_charsearch.ok
deleted file mode 100644
index a0c90e24f9..0000000000
--- a/src/nvim/testdir/test_charsearch.ok
+++ /dev/null
@@ -1,3 +0,0 @@
-XabcdeXfghijkeXmnopqreXtuvwxyz
-YabcdeYfghiYjkeYmnopqreYtuvwxyz
-ZabcdeZfghijkZemnokZqretkZvwxyz
diff --git a/src/nvim/testdir/test_command_count.in b/src/nvim/testdir/test_command_count.in
deleted file mode 100644
index 170c810923..0000000000
--- a/src/nvim/testdir/test_command_count.in
+++ /dev/null
@@ -1,158 +0,0 @@
-Test for user command counts vim: set ft=vim :
-
-STARTTEST
-:so tiny.vim
-:lang C
-:let g:lines = []
-:com -range=% RangeLines :call add(g:lines, 'RangeLines '.<line1>.' '.<line2>)
-:com -range -addr=arguments RangeArguments :call add(g:lines, 'RangeArguments '.<line1>.' '.<line2>)
-:com -range=% -addr=arguments RangeArgumentsAll :call add(g:lines, 'RangeArgumentsAll '.<line1>.' '.<line2>)
-:com -range -addr=loaded_buffers RangeLoadedBuffers :call add(g:lines, 'RangeLoadedBuffers '.<line1>.' '.<line2>)
-:com -range=% -addr=loaded_buffers RangeLoadedBuffersAll :call add(g:lines, 'RangeLoadedBuffersAll '.<line1>.' '.<line2>)
-:com -range -addr=buffers RangeBuffers :call add(g:lines, 'RangeBuffers '.<line1>.' '.<line2>)
-:com -range=% -addr=buffers RangeBuffersAll :call add(g:lines, 'RangeBuffersAll '.<line1>.' '.<line2>)
-:com -range -addr=windows RangeWindows :call add(g:lines, 'RangeWindows '.<line1>.' '.<line2>)
-:com -range=% -addr=windows RangeWindowsAll :call add(g:lines, 'RangeWindowsAll '.<line1>.' '.<line2>)
-:com -range -addr=tabs RangeTabs :call add(g:lines, 'RangeTabs '.<line1>.' '.<line2>)
-:com -range=% -addr=tabs RangeTabsAll :call add(g:lines, 'RangeTabsAll '.<line1>.' '.<line2>)
-:set hidden
-:arga a b c d
-:argdo echo "loading buffers"
-:argu 3
-:.-,$-RangeArguments
-:%RangeArguments
-:RangeArgumentsAll
-:N
-:.RangeArguments
-:split|split|split|split
-:3wincmd w
-:.,$RangeWindows
-:%RangeWindows
-:RangeWindowsAll
-:only
-:blast|bd
-:.,$RangeLoadedBuffers
-:%RangeLoadedBuffers
-:RangeLoadedBuffersAll
-:.,$RangeBuffers
-:%RangeBuffers
-:RangeBuffersAll
-:tabe|tabe|tabe|tabe
-:normal 2gt
-:.,$RangeTabs
-:%RangeTabs
-:RangeTabsAll
-:1tabonly
-:s/\n/\r\r\r\r\r/
-:2ma<
-:$-ma>
-:'<,'>RangeLines
-:com -range=% -buffer LocalRangeLines :call add(g:lines, 'LocalRangeLines '.<line1>.' '.<line2>)
-:'<,'>LocalRangeLines
-:b1
-ENDTEST
-
-STARTTEST
-:call add(g:lines, '')
-:%argd
-:arga a b c d
-:let v:errmsg = ''
-:5argu
-:call add(g:lines, '5argu ' . v:errmsg)
-:$argu
-:call add(g:lines, '4argu ' . expand('%:t'))
-:let v:errmsg = ''
-:1argu
-:call add(g:lines, '1argu ' . expand('%:t'))
-:let v:errmsg = ''
-:100b
-:call add(g:lines, '100b ' . v:errmsg)
-:split|split|split|split
-:let v:errmsg = ''
-:0close
-:call add(g:lines, '0close ' . v:errmsg)
-:$wincmd w
-:$close
-:call add(g:lines, '$close ' . winnr())
-:let v:errmsg = ''
-:$+close
-:call add(g:lines, '$+close ' . v:errmsg)
-:$tabe
-:call add(g:lines, '$tabe ' . tabpagenr())
-:let v:errmsg = ''
-:$+tabe
-:call add(g:lines, '$+tabe ' . v:errmsg)
-:only!
-:e x
-:0tabm
-:normal 1gt
-:call add(g:lines, '0tabm ' . expand('%:t'))
-:tabonly!
-:only!
-:e! test.out
-:call append(0, g:lines)
-:unlet g:lines
-:w|bd
-:b1
-ENDTEST
-
-STARTTEST
-:let g:lines = []
-:func BufStatus()
-: call add(g:lines, 'aaa: ' . buflisted(g:buf_aaa) . ' bbb: ' . buflisted(g:buf_bbb) . ' ccc: ' . buflisted(g:buf_ccc))
-:endfunc
-:se nohidden
-:e aaa
-:let buf_aaa = bufnr('%')
-:e bbb
-:let buf_bbb = bufnr('%')
-:e ccc
-:let buf_ccc = bufnr('%')
-:b1
-:call BufStatus()
-:exe buf_bbb . "," . buf_ccc . "bdelete"
-:call BufStatus()
-:exe buf_aaa . "bdelete"
-:call BufStatus()
-:e! test.out
-:call append('$', g:lines)
-:unlet g:lines
-:delfunc BufStatus
-:w|bd
-:b1
-ENDTEST
-
-STARTTEST
-:se hidden
-:only!
-:let g:lines = []
-:%argd
-:arga a b c d e f
-:3argu
-:let args = ''
-:.,$-argdo let args .= ' '.expand('%')
-:call add(g:lines, 'argdo:' . args)
-:split|split|split|split
-:2wincmd w
-:let windows = ''
-:.,$-windo let windows .= ' '.winnr()
-:call add(g:lines, 'windo:'. windows)
-:b2
-:let buffers = ''
-:.,$-bufdo let buffers .= ' '.bufnr('%')
-:call add(g:lines, 'bufdo:' . buffers)
-:3bd
-:let buffers = ''
-:3,7bufdo let buffers .= ' '.bufnr('%')
-:call add(g:lines, 'bufdo:' . buffers)
-:tabe|tabe|tabe|tabe
-:normal! 2gt
-:let tabpages = ''
-:.,$-tabdo let tabpages .= ' '.tabpagenr()
-:call add(g:lines, 'tabdo:' . tabpages)
-:e! test.out
-:call append('$', g:lines)
-:w|qa!
-ENDTEST
-
-
diff --git a/src/nvim/testdir/test_command_count.ok b/src/nvim/testdir/test_command_count.ok
deleted file mode 100644
index e74155ec1b..0000000000
--- a/src/nvim/testdir/test_command_count.ok
+++ /dev/null
@@ -1,38 +0,0 @@
-RangeArguments 2 4
-RangeArguments 1 5
-RangeArgumentsAll 1 5
-RangeArguments 2 2
-RangeWindows 3 5
-RangeWindows 1 5
-RangeWindowsAll 1 5
-RangeLoadedBuffers 2 4
-RangeLoadedBuffers 1 4
-RangeLoadedBuffersAll 1 4
-RangeBuffers 2 5
-RangeBuffers 1 5
-RangeBuffersAll 1 5
-RangeTabs 2 5
-RangeTabs 1 5
-RangeTabsAll 1 5
-RangeLines 2 5
-LocalRangeLines 2 5
-
-5argu E16: Invalid range
-4argu d
-1argu a
-100b E16: Invalid range
-0close
-$close 3
-$+close E16: Invalid range
-$tabe 2
-$+tabe E16: Invalid range
-0tabm x
-
-aaa: 1 bbb: 1 ccc: 1
-aaa: 1 bbb: 0 ccc: 0
-aaa: 0 bbb: 0 ccc: 0
-argdo: c d e
-windo: 2 3 4
-bufdo: 2 3 4 5 6 7 8 9 10 15
-bufdo: 4 5 6 7
-tabdo: 2 3 4
diff --git a/src/nvim/testdir/test_eval.in b/src/nvim/testdir/test_eval.in
deleted file mode 100644
index 54cdb03ba2..0000000000
--- a/src/nvim/testdir/test_eval.in
+++ /dev/null
@@ -1,234 +0,0 @@
-Test for various eval features. vim: set ft=vim :
-
-Note: system clipboard is saved, changed and restored.
-
-clipboard contents
-something else
-
-STARTTEST
-:so small.vim
-:set noswapfile
-:lang C
-:fun AppendRegContents(reg)
- call AppendRegParts(a:reg, getregtype(a:reg), getreg(a:reg), string(getreg(a:reg, 0, 1)), getreg(a:reg, 1), string(getreg(a:reg, 1, 1)))
-:endfun
-:fun AppendRegParts(reg, type, cont, strcont, cont1, strcont1)
- call append('$', printf('%s: type %s; value: %s (%s), expr: %s (%s)', a:reg, a:type, a:cont, a:strcont, a:cont1, a:strcont1))
-endfun
-:command -nargs=? AR :call AppendRegContents(<q-args>)
-:fun SetReg(...)
- call call('setreg', a:000)
- call append('$', printf('{{{2 setreg(%s)', string(a:000)[1:-2]))
- call AppendRegContents(a:1)
- if a:1 isnot# '='
- execute "silent normal! Go==\n==\e\"".a:1."P"
- endif
-endfun
-:fun ErrExe(str)
- call append('$', 'Executing '.a:str)
- try
- execute a:str
- catch
- $put =v:exception
- endtry
-endfun
-:fun Test()
-$put ='{{{1 let tests'
-let @" = 'abc'
-AR "
-let @" = "abc\n"
-AR "
-let @" = "abc\<C-m>"
-AR "
-let @= = '"abc"'
-AR =
-
-$put ='{{{1 Basic setreg tests'
-call SetReg('a', 'abcA', 'c')
-call SetReg('b', 'abcB', 'v')
-call SetReg('c', 'abcC', 'l')
-call SetReg('d', 'abcD', 'V')
-call SetReg('e', 'abcE', 'b')
-call SetReg('f', 'abcF', "\<C-v>")
-call SetReg('g', 'abcG', 'b10')
-call SetReg('h', 'abcH', "\<C-v>10")
-call SetReg('I', 'abcI')
-
-$put ='{{{1 Appending single lines with setreg()'
-call SetReg('A', 'abcAc', 'c')
-call SetReg('A', 'abcAl', 'l')
-call SetReg('A', 'abcAc2','c')
-call SetReg('b', 'abcBc', 'ca')
-call SetReg('b', 'abcBb', 'ba')
-call SetReg('b', 'abcBc2','ca')
-call SetReg('b', 'abcBb2','b50a')
-
-call SetReg('C', 'abcCl', 'l')
-call SetReg('C', 'abcCc', 'c')
-call SetReg('D', 'abcDb', 'b')
-
-call SetReg('E', 'abcEb', 'b')
-call SetReg('E', 'abcEl', 'l')
-call SetReg('F', 'abcFc', 'c')
-
-$put ='{{{1 Appending NL with setreg()'
-call setreg('a', 'abcA2', 'c')
-call setreg('b', 'abcB2', 'v')
-call setreg('c', 'abcC2', 'l')
-call setreg('d', 'abcD2', 'V')
-call setreg('e', 'abcE2', 'b')
-call setreg('f', 'abcF2', "\<C-v>")
-call setreg('g', 'abcG2', 'b10')
-call setreg('h', 'abcH2', "\<C-v>10")
-call setreg('I', 'abcI2')
-
-call SetReg('A', "\n")
-call SetReg('B', "\n", 'c')
-call SetReg('C', "\n")
-call SetReg('D', "\n", 'l')
-call SetReg('E', "\n")
-call SetReg('F', "\n", 'b')
-
-$put ='{{{1 Setting lists with setreg()'
-call SetReg('a', ['abcA3'], 'c')
-call SetReg('b', ['abcB3'], 'l')
-call SetReg('c', ['abcC3'], 'b')
-call SetReg('d', ['abcD3'])
-call SetReg('e', [1, 2, 'abc', 3])
-call SetReg('f', [1, 2, 3])
-
-$put ='{{{1 Appending lists with setreg()'
-call SetReg('A', ['abcA3c'], 'c')
-call SetReg('b', ['abcB3l'], 'la')
-call SetReg('C', ['abcC3b'], 'lb')
-call SetReg('D', ['abcD32'])
-
-call SetReg('A', ['abcA32'])
-call SetReg('B', ['abcB3c'], 'c')
-call SetReg('C', ['abcC3l'], 'l')
-call SetReg('D', ['abcD3b'], 'b')
-
-$put ='{{{1 Appending lists with NL with setreg()'
-call SetReg('A', ["\n", 'abcA3l2'], 'l')
-call SetReg('B', ["\n", 'abcB3c2'], 'c')
-call SetReg('C', ["\n", 'abcC3b2'], 'b')
-call SetReg('D', ["\n", 'abcD3b50'],'b50')
-
-$put ='{{{1 Setting lists with NLs with setreg()'
-call SetReg('a', ['abcA4-0', "\n", "abcA4-2\n", "\nabcA4-3", "abcA4-4\nabcA4-4-2"])
-call SetReg('b', ['abcB4c-0', "\n", "abcB4c-2\n", "\nabcB4c-3", "abcB4c-4\nabcB4c-4-2"], 'c')
-call SetReg('c', ['abcC4l-0', "\n", "abcC4l-2\n", "\nabcC4l-3", "abcC4l-4\nabcC4l-4-2"], 'l')
-call SetReg('d', ['abcD4b-0', "\n", "abcD4b-2\n", "\nabcD4b-3", "abcD4b-4\nabcD4b-4-2"], 'b')
-call SetReg('e', ['abcE4b10-0', "\n", "abcE4b10-2\n", "\nabcE4b10-3", "abcE4b10-4\nabcE4b10-4-2"], 'b10')
-
-$put ='{{{1 Search and expressions'
-call SetReg('/', ['abc/'])
-call SetReg('/', ["abc/\n"])
-call SetReg('=', ['"abc/"'])
-call SetReg('=', ["\"abc/\n\""])
-$put ='{{{1 System clipboard'
-if has('clipboard')
-" Save and restore system clipboard.
-" If no connection to X-Server is possible, test should succeed.
-let _clipreg = ['*', getreg('*'), getregtype('*')]
-let _clipopt = &cb
-let &cb='unnamed'
-5y
-AR *
-tabdo :windo :echo "hi"
-6y
-AR *
-let &cb=_clipopt
-call call('setreg', _clipreg)
-else
- call AppendRegParts('*', 'V', "clipboard contents\n", "['clipboard contents']", "clipboard contents\n", "['clipboard contents']")
- call AppendRegParts('*', 'V', "something else\n", "['something else']", "something else\n", "['something else']")
-endif
-$put ='{{{1 Errors'
-call ErrExe('call setreg()')
-call ErrExe('call setreg(1)')
-call ErrExe('call setreg(1, 2, 3, 4)')
-call ErrExe('call setreg([], 2)')
-call ErrExe('call setreg(1, {})')
-call ErrExe('call setreg(1, 2, [])')
-call ErrExe('call setreg("/", ["1", "2"])')
-call ErrExe('call setreg("=", ["1", "2"])')
-call ErrExe('call setreg(1, ["", "", [], ""])')
-endfun
-:"
-:call Test()
-:"
-:delfunction SetReg
-:delfunction AppendRegContents
-:delfunction ErrExe
-:delfunction Test
-:delcommand AR
-:call garbagecollect(1)
-:"
-:/^start:/+1,$wq! test.out
-:" vim: et ts=4 isk-=\: fmr=???,???
-:call getchar()
-:e test.out
-:%d
-
-:" function name not starting with a capital
-:try
-: func! g:test()
-: echo "test"
-: endfunc
-:catch
-: $put =v:exception
-:endtry
-
-:" function name folowed by #
-:try
-: func! test2() "#
-: echo "test2"
-: endfunc
-:catch
-: $put =v:exception
-:endtry
-
-:" function name includes a colon
-:try
-: func! b:test()
-: echo "test"
-: endfunc
-:catch
-: $put =v:exception
-:endtry
-
-:" function name starting with/without "g:", buffer-local funcref.
-:function! g:Foo(n)
-: $put ='called Foo(' . a:n . ')'
-:endfunction
-:let b:my_func = function('Foo')
-:call b:my_func(1)
-:echo g:Foo(2)
-:echo Foo(3)
-
-:" script-local function used in Funcref must exist.
-:so test_eval_func.vim
-
-:" using $ instead of '$' must give an error
-:try
-: call append($, 'foobar')
-:catch
-: $put =v:exception
-:endtry
-
-:$put ='{{{1 getcurpos/setpos'
-/^012345678
-6l:let sp = getcurpos()
-0:call setpos('.', sp)
-jyl:$put
-
-:/^start:/+1,$wq! test.out
-:" vim: et ts=4 isk-=\: fmr=???,???
-:call getchar()
-ENDTEST
-
-012345678
-012345678
-
-start:
diff --git a/src/nvim/testdir/test_eval.ok b/src/nvim/testdir/test_eval.ok
deleted file mode 100644
index cf7a5cd418..0000000000
--- a/src/nvim/testdir/test_eval.ok
+++ /dev/null
Binary files differ
diff --git a/src/nvim/testdir/test_eval_func.vim b/src/nvim/testdir/test_eval_func.vim
deleted file mode 100644
index 48d01df27d..0000000000
--- a/src/nvim/testdir/test_eval_func.vim
+++ /dev/null
@@ -1,12 +0,0 @@
-" Vim script used in test_eval.in. Needed for script-local function.
-
-func! s:Testje()
- return "foo"
-endfunc
-
-let Bar = function('s:Testje')
-
-$put ='s:Testje exists: ' . exists('s:Testje')
-$put ='func s:Testje exists: ' . exists('*s:Testje')
-$put ='Bar exists: ' . exists('Bar')
-$put ='func Bar exists: ' . exists('*Bar')
diff --git a/src/nvim/testdir/test_listlbr.in b/src/nvim/testdir/test_listlbr.in
index 36235ea915..6084711786 100644
--- a/src/nvim/testdir/test_listlbr.in
+++ b/src/nvim/testdir/test_listlbr.in
@@ -24,20 +24,24 @@ STARTTEST
: $put =g:line
: wincmd p
:endfu
+:"
:let g:test="Test 1: set linebreak"
:redraw!
:let line=ScreenChar(winwidth(0))
:call DoRecordScreen()
+:"
:let g:test="Test 2: set linebreak + set list"
:set linebreak list listchars=
:redraw!
:let line=ScreenChar(winwidth(0))
:call DoRecordScreen()
+:"
:let g:test ="Test 3: set linebreak nolist"
:set nolist linebreak
:redraw!
:let line=ScreenChar(winwidth(0))
:call DoRecordScreen()
+:"
:let g:test ="Test 4: set linebreak with tab and 1 line as long as screen: should break!"
:set nolist linebreak ts=8
:let line="1\t".repeat('a', winwidth(0)-2)
@@ -51,6 +55,7 @@ STARTTEST
:$put =line
:$
:norm! zt
+:"
:let g:test ="Test 5: set linebreak with conceal and set list and tab displayed by different char (line may not be truncated)"
:set cpo&vim list linebreak conceallevel=2 concealcursor=nv listchars=tab:ab
:syn match ConcealVar contained /_/ conceal
@@ -58,13 +63,57 @@ STARTTEST
:let line=ScreenChar(winwidth(0))
:call DoRecordScreen()
:set cpo&vim linebreak
+:"
:let g:test ="Test 6: set linebreak with visual block mode"
:let line="REMOVE: this not"
+:$put =g:test
:$put =line
:let line="REMOVE: aaaaaaaaaaaaa"
:$put =line
:1/^REMOVE:
0jf x:$put
+:set cpo&vim linebreak
+:"
+:let g:test ="Test 7: set linebreak with visual block mode and v_b_A"
+:$put =g:test
+Golong line: 40afoobar aTARGET at end
+:exe "norm! $3B\<C-v>eAx\<Esc>"
+:set cpo&vim linebreak sbr=
+:"
+:let g:test ="Test 8: set linebreak with visual char mode and changing block"
+:$put =g:test
+Go1111-1111-1111-11-1111-1111-11110f-lv3lc2222bgj.
+:"
+:let g:test ="Test 9: using redo after block visual mode"
+:$put =g:test
+Go
+aaa
+aaa
+a2k2j~e.
+:"
+:let g:test ="Test 10: using normal commands after block-visual"
+:$put =g:test
+:set linebreak
+Go
+abcd{ef
+ghijklm
+no}pqrs2k0f{c%
+:"
+:let g:test ="Test 11: using block replace mode after wrapping"
+:$put =g:test
+:set linebreak wrap
+Go150aayypk147|jr0
+:"
+:let g:test ="Test 12: set linebreak list listchars=space:_,tab:>-,tail:-,eol:$"
+:set list listchars=space:_,trail:-,tab:>-,eol:$
+:$put =g:test
+:let line="a aaaaaaaaaaaaaaaaaaaaaa\ta "
+:$put =line
+:$
+:norm! zt
+:redraw!
+:let line=ScreenChar(winwidth(0))
+:call DoRecordScreen()
:%w! test.out
:qa!
ENDTEST
diff --git a/src/nvim/testdir/test_listlbr.ok b/src/nvim/testdir/test_listlbr.ok
index ee74667661..b32a54969e 100644
--- a/src/nvim/testdir/test_listlbr.ok
+++ b/src/nvim/testdir/test_listlbr.ok
@@ -32,7 +32,31 @@ Sabbbbbb bla
~
~
~
+Test 6: set linebreak with visual block mode
this not
aaaaaaaaaaaaa
REMOVE:
REMOVE:
+Test 7: set linebreak with visual block mode and v_b_A
+long line: foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar TARGETx at end
+Test 8: set linebreak with visual char mode and changing block
+1111-2222-1111-11-1111-2222-1111
+Test 9: using redo after block visual mode
+
+AaA
+AaA
+A
+Test 10: using normal commands after block-visual
+
+abcdpqrs
+Test 11: using block replace mode after wrapping
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa0aaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa0aaa
+Test 12: set linebreak list listchars=space:_,tab:>-,tail:-,eol:$
+a aaaaaaaaaaaaaaaaaaaaaa a
+
+Test 12: set linebreak list listchars=space:_,tab:>-,tail:-,eol:$
+a_
+aaaaaaaaaaaaaaaaaaaa
+aa>-----a-$
+~
diff --git a/src/nvim/testdir/test_marks.in b/src/nvim/testdir/test_marks.in
new file mode 100644
index 0000000000..23c2fb65fe
--- /dev/null
+++ b/src/nvim/testdir/test_marks.in
@@ -0,0 +1,34 @@
+Tests for marks.
+
+STARTTEST
+:so small.vim
+:" test that a deleted mark is restored after delete-undo-redo-undo
+:/^\t/+1
+:set nocp viminfo+=nviminfo
+madduu
+:let a = string(getpos("'a"))
+:$put ='Mark after delete-undo-redo-undo: '.a
+:''
+ENDTEST
+
+ textline A
+ textline B
+ textline C
+
+STARTTEST
+:" test that CTRL-A and CTRL-X updates last changed mark '[, '].
+:/^123/
+:execute "normal! \<C-A>`[v`]rAjwvjw\<C-X>`[v`]rX"
+ENDTEST
+
+CTRL-A CTRL-X:
+123 123 123
+123 123 123
+123 123 123
+
+STARTTEST
+:g/^STARTTEST/.,/^ENDTEST/d
+:wq! test.out
+ENDTEST
+
+Results:
diff --git a/src/nvim/testdir/test_marks.ok b/src/nvim/testdir/test_marks.ok
new file mode 100644
index 0000000000..e6c02ee7b0
--- /dev/null
+++ b/src/nvim/testdir/test_marks.ok
@@ -0,0 +1,16 @@
+Tests for marks.
+
+
+ textline A
+ textline B
+ textline C
+
+
+CTRL-A CTRL-X:
+AAA 123 123
+123 XXXXXXX
+XXX 123 123
+
+
+Results:
+Mark after delete-undo-redo-undo: [0, 15, 2, 0]
diff --git a/src/nvim/tui/tui.c b/src/nvim/tui/tui.c
index 7f7d138358..00e2821075 100644
--- a/src/nvim/tui/tui.c
+++ b/src/nvim/tui/tui.c
@@ -845,7 +845,7 @@ static void fix_terminfo(TUIData *data)
if ((term_prog && !strcmp(term_prog, "Konsole"))
|| os_getenv("KONSOLE_DBUS_SESSION") != NULL) {
// Konsole uses a proprietary escape code to set the cursor shape
- // and does not suppport DECSCUSR.
+ // and does not support DECSCUSR.
data->unibi_ext.enter_insert_mode = (int)unibi_add_ext_str(ut, NULL,
TMUX_WRAP("\x1b]50;CursorShape=1;BlinkingCursorEnabled=1\x07"));
data->unibi_ext.enter_replace_mode = (int)unibi_add_ext_str(ut, NULL,
@@ -854,13 +854,15 @@ static void fix_terminfo(TUIData *data)
TMUX_WRAP("\x1b]50;CursorShape=0;BlinkingCursorEnabled=0\x07"));
} else if (!vte_version || atoi(vte_version) >= 3900) {
// Assume that the terminal supports DECSCUSR unless it is an
- // old VTE based terminal
+ // old VTE based terminal. This should not get wrapped for tmux,
+ // which will handle it via its Ss/Se terminfo extension - usually
+ // according to its terminal-overrides.
data->unibi_ext.enter_insert_mode = (int)unibi_add_ext_str(ut, NULL,
- TMUX_WRAP("\x1b[5 q"));
+ "\x1b[5 q");
data->unibi_ext.enter_replace_mode = (int)unibi_add_ext_str(ut, NULL,
- TMUX_WRAP("\x1b[3 q"));
+ "\x1b[3 q");
data->unibi_ext.exit_insert_mode = (int)unibi_add_ext_str(ut, NULL,
- TMUX_WRAP("\x1b[2 q"));
+ "\x1b[2 q");
}
end:
diff --git a/src/nvim/undo.c b/src/nvim/undo.c
index 6b60f95f22..b8cdffcda0 100644
--- a/src/nvim/undo.c
+++ b/src/nvim/undo.c
@@ -2222,12 +2222,17 @@ static void u_undoredo(int undo)
/*
* restore marks from before undo/redo
*/
- for (i = 0; i < NMARKS; ++i)
+ for (i = 0; i < NMARKS; ++i) {
if (curhead->uh_namedm[i].mark.lnum != 0) {
free_fmark(curbuf->b_namedm[i]);
curbuf->b_namedm[i] = curhead->uh_namedm[i];
+ }
+ if (namedm[i].mark.lnum != 0) {
curhead->uh_namedm[i] = namedm[i];
+ } else {
+ curhead->uh_namedm[i].mark.lnum = 0;
}
+ }
if (curhead->uh_visual.vi_start.lnum != 0) {
curbuf->b_visual = curhead->uh_visual;
curhead->uh_visual = visualinfo;
diff --git a/src/nvim/version.c b/src/nvim/version.c
index 9b4c191d89..80b1b236dd 100644
--- a/src/nvim/version.c
+++ b/src/nvim/version.c
@@ -69,6 +69,172 @@ static char *features[] = {
// clang-format off
static int included_patches[] = {
+ 1366,
+
+ // 1219 NA
+ // 1218 NA
+ // 1217 NA
+ // 1216 NA
+ // 1215 NA
+ // 1214 NA
+ // 1213 NA
+ // 1212 NA
+ // 1211 NA
+ // 1210 NA
+ // 1209 NA
+ // 1208 NA
+ // 1207 NA
+ // 1206 NA
+ // 1205 NA
+ // 1204 NA
+ // 1203 NA
+ // 1202 NA
+ // 1201 NA
+ // 1200 NA
+ // 1199 NA
+ // 1198 NA
+ // 1197 NA
+ // 1196 NA
+ // 1195 NA
+ // 1194 NA
+ // 1193 NA
+ // 1192 NA
+ // 1191 NA
+ // 1190 NA
+ // 1189 NA
+ // 1188,
+ // 1187 NA
+ // 1186,
+ // 1185 NA
+ // 1184 NA
+ // 1183 NA
+ // 1182 NA
+ // 1181,
+ 1180,
+ // 1179,
+ // 1178,
+ // 1177 NA
+ // 1176 NA
+ // 1175 NA
+ // 1174 NA
+ // 1173,
+ // 1172 NA
+ // 1171 NA
+ // 1170 NA
+ // 1169 NA
+ // 1168,
+ // 1167,
+ // 1166,
+ // 1165 NA
+ // 1164,
+ // 1163,
+ // 1162 NA
+ // 1161,
+ // 1160,
+ // 1159 NA
+ // 1158 NA
+ // 1157,
+ // 1156,
+ // 1155 NA
+ // 1154,
+ // 1153,
+ // 1152 NA
+ // 1151,
+ // 1150,
+ 1149,
+ // 1148 NA
+ // 1147,
+ // 1146 NA
+ // 1145 NA
+ // 1144 NA
+ // 1143,
+ // 1142,
+ // 1141,
+ // 1140,
+ // 1139 NA
+ // 1138 NA
+ 1137,
+ // 1136,
+ // 1135 NA,
+ // 1134 NA,
+ // 1133 NA
+ // 1132,
+ // 1131 NA
+ // 1130,
+ // 1129 NA
+ // 1128 NA
+ // 1127 NA
+ // 1126,
+ // 1125 NA
+ // 1124 NA
+ // 1123,
+ // 1122 NA
+ // 1121,
+ // 1120,
+ // 1119,
+ // 1118,
+ // 1117,
+ // 1116,
+ // 1115 NA
+ // 1114,
+ // 1113,
+ // 1112,
+ // 1111,
+ // 1110,
+ // 1109 NA
+ // 1108,
+ // 1107,
+ // 1106 NA
+ // 1105,
+ // 1104 NA
+ // 1103 NA
+ // 1102,
+ // 1101,
+ // 1100 NA
+ // 1099 NA
+ // 1098 NA
+ // 1097,
+ // 1096,
+ // 1095 NA
+ // 1094,
+ // 1093,
+ // 1092,
+ // 1091,
+ // 1090,
+ 1089,
+ 1088,
+ 1087,
+ // 1086,
+ 1085,
+ 1084,
+ // 1083 NA,
+ // 1082 NA,
+ 1081,
+ // 1080 NA,
+ // 1079,
+ // 1078 NA,
+ // 1077 NA,
+ 1076,
+ // 1075,
+ // 1074 NA,
+ // 1073,
+ 1072,
+ // 1071,
+ // 1070 NA,
+ // 1069 NA,
+ // 1068,
+ // 1067 NA,
+ // 1066 NA,
+ 1065,
+ // 1064,
+ // 1063 NA,
+ // 1062 NA,
+ // 1061,
+ // 1060 NA,
+ // 1059,
+ // 1058,
+ // 1057,
+ // 1056,
1055,
// 1054,
// 1053,
@@ -79,50 +245,50 @@ static int included_patches[] = {
// 1048,
// 1047,
// 1046,
- // 1045,
- // 1044,
- // 1043,
+ // 1045 NA,
+ // 1044 NA,
+ // 1043 NA,
// 1042,
- // 1041,
- // 1040,
+ 1041,
+ // 1040 NA,
// 1039,
- // 1038,
+ // 1038 NA,
// 1037,
// 1036,
// 1035,
// 1034,
- // 1033,
+ // 1033 NA,
1032,
- // 1031,
+ // 1031 NA,
// 1030,
- // 1029,
- // 1028,
- // 1027,
- // 1026,
- // 1025,
- // 1024,
- // 1023,
- // 1022,
- // 1021,
- // 1020,
- // 1019,
+ 1029,
+ // 1028 NA,
+ 1027,
+ // 1026 NA,
+ // 1025 NA,
+ // 1024 NA,
+ // 1023 NA,
+ // 1022 NA,
+ // 1021 NA,
+ // 1020 NA,
+ // 1019 NA,
// 1018,
// 1017,
- // 1016,
+ // 1016 NA,
// 1015,
- // 1014,
- // 1013,
- // 1012,
- // 1011,
+ // 1014 NA,
+ 1013,
+ // 1012 NA,
+ // 1011 NA,
// 1010,
- // 1009,
- // 1008,
+ // 1009 NA,
+ // 1008 NA,
// 1007,
// 1006,
// 1005,
- // 1004,
- // 1003,
- // 1002,
+ // 1004 NA,
+ // 1003 NA,
+ // 1002 NA,
// 1001,
// 1000,
// 999 NA
@@ -147,7 +313,7 @@ static int included_patches[] = {
980,
// 979 NA
978,
- // 977,
+ 977,
// 976 NA
975,
// 974,
@@ -161,7 +327,7 @@ static int included_patches[] = {
// 966 NA
// 965 NA
// 964 NA
- // 963,
+ 963,
// 962 NA
// 961,
// 960 NA
@@ -175,7 +341,7 @@ static int included_patches[] = {
// 952,
// 951,
950,
- // 949,
+ 949,
// 948 NA
// 947,
946,
@@ -185,34 +351,34 @@ static int included_patches[] = {
// 942,
// 941,
// 940 NA
- // 939,
+ 939,
// 938 NA
- // 937,
- // 936,
- // 935,
+ 937,
+ 936,
+ // 935 NA
// 934 NA
- // 933,
- // 932,
- // 931,
+ 933,
+ 932,
+ // 931 NA
// 930 NA
- // 929,
+ 929,
// 928 NA
// 927 NA
- // 926,
+ 926,
// 925,
// 924 NA
// 923 NA
- // 922,
+ 922,
// 921 NA
// 920 NA
// 919 NA
// 918 NA
// 917 NA
916,
- // 915,
+ 915,
// 914,
// 913 NA
- // 912,
+ 912,
// 911 NA
// 910 NA
// 909,
@@ -221,118 +387,118 @@ static int included_patches[] = {
// 906 NA
// 905,
// 904,
- // 903,
+ 903,
// 902 NA
- // 901,
+ 901,
// 900 NA
// 899 NA
898,
- // 897,
+ // 897 NA
// 896,
- // 895,
+ 895,
// 894 NA
- // 893,
+ 893,
// 892,
- // 891,
+ 891,
// 890 NA
// 889,
- // 888,
- // 887,
+ 888,
+ 887,
// 886 NA
- // 885,
+ 885,
// 884 NA
- // 883,
+ 883,
// 882,
- // 881,
+ 881,
// 880 NA
- // 879,
- // 878,
- // 877,
+ 879,
+ 878,
+ 877,
// 876 NA
// 875 NA
// 874 NA
- // 873,
+ // 873 NA
// 872 NA
// 871,
- // 870,
+ 870,
// 869 NA
- // 868,
+ 868,
// 867 NA
- // 866,
- // 865,
+ // 866 NA
+ // 865 NA
// 864 NA
// 863 NA
// 862 NA
// 861 NA
- // 860,
- // 859,
+ // 860 NA
+ 859,
858,
// 857,
- // 856,
+ 856,
// 855 NA
// 854 NA
- // 853,
+ 853,
// 852 NA
// 851 NA
// 850 NA
849,
- // 848,
- // 847,
+ 848,
+ 847,
// 846 NA
- // 845,
- // 844,
- // 843,
+ 845,
+ 844,
+ 843,
// 842 NA
// 841 NA
// 840 NA
- // 839,
- // 838,
+ // 839 NA
+ // 838 NA
// 837 NA
836,
- // 835,
- // 834,
- // 833,
- // 832,
- // 831,
- // 830,
+ 835,
+ 834,
+ 833,
+ 832,
+ 831,
+ 830,
// 829 NA
- // 828,
- // 827,
+ 828,
+ // 827 NA
826,
- // 825,
+ 825,
// 824 NA
- // 823,
+ 823,
// 822,
- // 821,
- // 820,
+ // 821 NA
+ 820,
// 819,
- // 818,
- // 817,
- // 816,
- // 815,
- // 814,
+ 818,
+ 817,
+ 816,
+ 815,
+ 814,
813,
- // 812,
- // 811,
- // 810,
+ // 812 NA
+ 811,
+ 810,
809,
// 808 NA
- // 807,
- // 806,
- // 805,
- // 804,
+ 807,
+ 806,
+ 805,
+ // 804 NA
803,
802,
- // 801,
- // 800,
+ 801,
+ 800,
799,
- // 798,
+ 798,
// 797,
// 796 NA
795,
// 794 NA
793,
- // 792,
+ 792,
791,
790,
789,
@@ -342,72 +508,72 @@ static int included_patches[] = {
785,
784,
// 783 NA
- // 782,
+ 782,
781,
- // 780 NA
- // 779,
- // 778,
+ 780,
+ 779,
+ 778,
// 777 NA
776,
775,
774,
773,
// 772 NA
- // 771,
+ 771,
// 770 NA
- // 769,
- // 768,
- // 767,
+ 769,
+ 768,
+ // 767 NA
// 766 NA
- // 765,
- // 764,
+ 765,
+ 764,
// 763 NA
// 762 NA
// 761 NA
- // 760,
+ 760,
// 759 NA
- // 758,
+ 758,
// 757 NA
// 756 NA
- // 755,
- // 754,
- // 753,
- // 752,
+ 755,
+ 754,
+ 753,
+ // 752 NA
// 751 NA
// 750 NA
- // 749,
- // 748,
- // 747,
- // 746,
- // 745,
+ 749,
+ 748,
+ 747,
+ 746,
+ 745,
// 744 NA
- // 743,
- // 742,
- // 741,
- // 740,
- // 739,
+ 743,
+ 742,
+ 741,
+ 740,
+ 739,
// 738 NA
- // 737,
+ 737,
736,
- // 735,
- // 734,
+ // 735 NA
+ 734,
// 733,
- // 732,
+ 732,
// 731 NA
// 730 NA
729,
// 728 NA
// 727 NA
// 726 NA
- // 725,
+ // 725 NA
// 724 NA
723,
- // 722,
+ 722,
721,
// 720 NA
719,
- // 718,
- // 717,
+ 718,
+ 717,
716,
715,
714,
@@ -415,36 +581,36 @@ static int included_patches[] = {
712,
711,
710,
- // 709,
- // 708,
+ 709,
+ 708,
707,
706,
// 705 NA
- // 704,
+ 704,
// 703 NA
702,
// 701 NA
- // 700,
+ 700,
699,
- // 698,
- // 697,
+ 698,
+ 697,
696,
695,
- // 694,
- // 693,
+ 694,
+ 693,
// 692 NA
// 691 NA
690,
- // 689,
- // 688,
+ 689,
+ 688,
// 687 NA
686,
- // 685,
- // 684,
+ 685,
+ // 684 NA
// 683 NA
682,
// 681 NA
- // 680,
+ 680,
// 679 NA
// 678 NA
// 677 NA
@@ -462,15 +628,15 @@ static int included_patches[] = {
665,
// 664 NA
// 663 NA
- // 662,
+ 662,
// 661 NA
660,
659,
658,
// 657 NA
- // 656,
+ 656,
655,
- // 654,
+ 654,
653,
// 652 NA
651,
@@ -481,16 +647,16 @@ static int included_patches[] = {
646,
645,
// 644 NA
- // 643,
- // 642,
+ 643,
+ 642,
// 641 NA
640,
- // 639,
+ 639,
// 638 NA
637,
636,
635,
- // 634,
+ 634,
633,
// 632 NA
631,
diff --git a/src/nvim/vim.h b/src/nvim/vim.h
index 2e20d48f90..762d349470 100644
--- a/src/nvim/vim.h
+++ b/src/nvim/vim.h
@@ -30,12 +30,20 @@ Error: configure did not run properly.Check auto/config.log.
/* Can't use "PACKAGE" here, conflicts with a Perl include file. */
#ifndef VIMPACKAGE
-# define VIMPACKAGE "vim"
+# define VIMPACKAGE "nvim"
#endif
#include "nvim/os/os_defs.h" /* bring lots of system header files */
-#define NUMBUFLEN 65 // length of a buffer to store a number in ASCII
+/// length of a buffer to store a number in ASCII (64 bits binary + NUL)
+#define NUMBUFLEN 65
+
+// flags for vim_str2nr()
+#define STR2NR_BIN 1
+#define STR2NR_OCT 2
+#define STR2NR_HEX 4
+#define STR2NR_ALL (STR2NR_BIN + STR2NR_OCT + STR2NR_HEX)
+#define STR2NR_FORCE 8 // only when ONE of the above is used
#define MAX_TYPENR 65535
diff --git a/src/nvim/window.c b/src/nvim/window.c
index 16ff7dfb14..39106a7b8d 100644
--- a/src/nvim/window.c
+++ b/src/nvim/window.c
@@ -1044,19 +1044,21 @@ static void win_init_some(win_T *newp, win_T *oldp)
}
-/*
- * Check if "win" is a pointer to an existing window.
- */
-int win_valid(win_T *win)
+/// Check if "win" is a pointer to an existing window in the current tabpage.
+///
+/// @param win window to check
+bool win_valid(win_T *win) FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT
{
- if (win == NULL)
- return FALSE;
+ if (win == NULL) {
+ return false;
+ }
+
FOR_ALL_WINDOWS_IN_TAB(wp, curtab) {
if (wp == win) {
- return TRUE;
+ return true;
}
}
- return FALSE;
+ return false;
}
/*
@@ -1732,21 +1734,18 @@ close_windows (
shell_new_rows();
}
-/*
- * Return TRUE if the current window is the only window that exists (ignoring
- * "aucmd_win").
- * Returns FALSE if there is a window, possibly in another tab page.
- */
-static int last_window(void)
+/// Check that current window is the last one.
+///
+/// @return true if the current window is the only window that exists, false if
+/// there is another, possibly in another tab page.
+static bool last_window(void) FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT
{
return one_window() && first_tabpage->tp_next == NULL;
}
-/*
- * Return TRUE if there is only one window other than "aucmd_win" in the
- * current tab page.
- */
-bool one_window(void)
+/// Check that current tab page contains no more then one window other than
+/// "aucmd_win".
+bool one_window(void) FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT
{
bool seen_one = false;
@@ -1761,14 +1760,20 @@ bool one_window(void)
return true;
}
-/*
- * Close the possibly last window in a tab page.
- * Returns TRUE when the window was closed already.
- */
-static int close_last_window_tabpage(win_T *win, int free_buf, tabpage_T *prev_curtab)
+/// Close the possibly last window in a tab page.
+///
+/// @param win window to close
+/// @param free_buf whether to free the window's current buffer
+/// @param prev_curtab previous tabpage that will be closed if "win" is the
+/// last window in the tabpage
+///
+/// @return true when the window was closed already.
+static bool close_last_window_tabpage(win_T *win, bool free_buf,
+ tabpage_T *prev_curtab)
+ FUNC_ATTR_NONNULL_ARG(1)
{
if (firstwin != lastwin) {
- return FALSE;
+ return false;
}
buf_T *old_curbuf = curbuf;
@@ -1809,14 +1814,15 @@ static int close_last_window_tabpage(win_T *win, int free_buf, tabpage_T *prev_c
terminal_resize(term, 0, 0);
}
- /* Since goto_tabpage_tp above did not trigger *Enter autocommands, do
- * that now. */
- apply_autocmds(EVENT_TABCLOSED, prev_idx, prev_idx, FALSE, curbuf);
- apply_autocmds(EVENT_WINENTER, NULL, NULL, FALSE, curbuf);
- apply_autocmds(EVENT_TABENTER, NULL, NULL, FALSE, curbuf);
- if (old_curbuf != curbuf)
- apply_autocmds(EVENT_BUFENTER, NULL, NULL, FALSE, curbuf);
- return TRUE;
+ // Since goto_tabpage_tp above did not trigger *Enter autocommands, do
+ // that now.
+ apply_autocmds(EVENT_TABCLOSED, prev_idx, prev_idx, false, curbuf);
+ apply_autocmds(EVENT_WINENTER, NULL, NULL, false, curbuf);
+ apply_autocmds(EVENT_TABENTER, NULL, NULL, false, curbuf);
+ if (old_curbuf != curbuf) {
+ apply_autocmds(EVENT_BUFENTER, NULL, NULL, false, curbuf);
+ }
+ return true;
}
/*
@@ -1907,9 +1913,16 @@ int win_close(win_T *win, int free_buf)
*/
if (win->w_buffer != NULL) {
win->w_closing = true;
- close_buffer(win, win->w_buffer, free_buf ? DOBUF_UNLOAD : 0, TRUE);
- if (win_valid(win))
+ close_buffer(win, win->w_buffer, free_buf ? DOBUF_UNLOAD : 0, true);
+ if (win_valid(win)) {
win->w_closing = false;
+ }
+
+ // Make sure curbuf is valid. It can become invalid if 'bufhidden' is
+ // "wipe".
+ if (!buf_valid(curbuf)) {
+ curbuf = firstbuf;
+ }
}
if (only_one_window() && win_valid(win) && win->w_buffer == NULL
@@ -2301,20 +2314,22 @@ static win_T *frame2win(frame_T *frp)
return frp->fr_win;
}
-/*
- * Return TRUE if frame "frp" contains window "wp".
- */
-static int frame_has_win(frame_T *frp, win_T *wp)
+/// Check that the frame "frp" contains the window "wp".
+///
+/// @param frp frame
+/// @param wp window
+static bool frame_has_win(frame_T *frp, win_T *wp)
+ FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ARG(1)
{
- frame_T *p;
-
- if (frp->fr_layout == FR_LEAF)
+ if (frp->fr_layout == FR_LEAF) {
return frp->fr_win == wp;
-
- for (p = frp->fr_child; p != NULL; p = p->fr_next)
- if (frame_has_win(p, wp))
- return TRUE;
- return FALSE;
+ }
+ for (frame_T *p = frp->fr_child; p != NULL; p = p->fr_next) {
+ if (frame_has_win(p, wp)) {
+ return true;
+ }
+ }
+ return false;
}
/*
@@ -2406,58 +2421,72 @@ frame_new_height (
topfrp->fr_height = height;
}
-/*
- * Return TRUE if height of frame "frp" should not be changed because of
- * the 'winfixheight' option.
- */
-static int frame_fixed_height(frame_T *frp)
+/// Return true if height of frame "frp" should not be changed because of
+/// the 'winfixheight' option.
+///
+/// @param frp frame
+///
+/// @return true if the frame has a fixed height
+static bool frame_fixed_height(frame_T *frp)
+ FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ALL
{
- /* frame with one window: fixed height if 'winfixheight' set. */
- if (frp->fr_win != NULL)
+ // frame with one window: fixed height if 'winfixheight' set.
+ if (frp->fr_win != NULL) {
return frp->fr_win->w_p_wfh;
-
+ }
if (frp->fr_layout == FR_ROW) {
- /* The frame is fixed height if one of the frames in the row is fixed
- * height. */
- for (frp = frp->fr_child; frp != NULL; frp = frp->fr_next)
- if (frame_fixed_height(frp))
- return TRUE;
- return FALSE;
+ // The frame is fixed height if one of the frames in the row is fixed
+ // height.
+ for (frp = frp->fr_child; frp != NULL; frp = frp->fr_next) {
+ if (frame_fixed_height(frp)) {
+ return true;
+ }
+ }
+ return false;
}
- /* frp->fr_layout == FR_COL: The frame is fixed height if all of the
- * frames in the row are fixed height. */
- for (frp = frp->fr_child; frp != NULL; frp = frp->fr_next)
- if (!frame_fixed_height(frp))
- return FALSE;
- return TRUE;
+ // frp->fr_layout == FR_COL: The frame is fixed height if all of the
+ // frames in the row are fixed height.
+ for (frp = frp->fr_child; frp != NULL; frp = frp->fr_next) {
+ if (!frame_fixed_height(frp)) {
+ return false;
+ }
+ }
+ return true;
}
-/*
- * Return TRUE if width of frame "frp" should not be changed because of
- * the 'winfixwidth' option.
- */
-static int frame_fixed_width(frame_T *frp)
+/// Return true if width of frame "frp" should not be changed because of
+/// the 'winfixwidth' option.
+///
+/// @param frp frame
+///
+/// @return true if the frame has a fixed width
+static bool frame_fixed_width(frame_T *frp)
+ FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ALL
{
- /* frame with one window: fixed width if 'winfixwidth' set. */
- if (frp->fr_win != NULL)
+ // frame with one window: fixed width if 'winfixwidth' set.
+ if (frp->fr_win != NULL) {
return frp->fr_win->w_p_wfw;
-
+ }
if (frp->fr_layout == FR_COL) {
- /* The frame is fixed width if one of the frames in the row is fixed
- * width. */
- for (frp = frp->fr_child; frp != NULL; frp = frp->fr_next)
- if (frame_fixed_width(frp))
- return TRUE;
- return FALSE;
+ // The frame is fixed width if one of the frames in the row is fixed
+ // width.
+ for (frp = frp->fr_child; frp != NULL; frp = frp->fr_next) {
+ if (frame_fixed_width(frp)) {
+ return true;
+ }
+ }
+ return false;
}
- /* frp->fr_layout == FR_ROW: The frame is fixed width if all of the
- * frames in the row are fixed width. */
- for (frp = frp->fr_child; frp != NULL; frp = frp->fr_next)
- if (!frame_fixed_width(frp))
- return FALSE;
- return TRUE;
+ // frp->fr_layout == FR_ROW: The frame is fixed width if all of the
+ // frames in the row are fixed width.
+ for (frp = frp->fr_child; frp != NULL; frp = frp->fr_next) {
+ if (!frame_fixed_width(frp)) {
+ return false;
+ }
+ }
+ return true;
}
/*
@@ -3028,10 +3057,10 @@ int make_tabpages(int maxcount)
return count - todo;
}
-/*
- * Return TRUE when "tpc" points to a valid tab page.
- */
-bool valid_tabpage(tabpage_T *tpc)
+/// Check that tpc points to a valid tab page.
+///
+/// @param[in] tpc Tabpage to check.
+bool valid_tabpage(tabpage_T *tpc) FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT
{
FOR_ALL_TABS(tp) {
if (tp == tpc) {
@@ -3252,17 +3281,27 @@ void goto_tabpage_win(tabpage_T *tp, win_T *wp)
}
}
-/*
- * Move the current tab page to before tab page "nr".
- */
+// Move the current tab page to after tab page "nr".
void tabpage_move(int nr)
{
- int n = nr;
- tabpage_T *tp;
+ int n = 1;
+ tabpage_T *tp;
+ tabpage_T *tp_dst;
if (first_tabpage->tp_next == NULL)
return;
+ for (tp = first_tabpage; tp->tp_next != NULL && n < nr; tp = tp->tp_next) {
+ ++n;
+ }
+
+ if (tp == curtab || (nr > 0 && tp->tp_next != NULL
+ && tp->tp_next == curtab)) {
+ return;
+ }
+
+ tp_dst = tp;
+
/* Remove the current tab page from the list of tab pages. */
if (curtab == first_tabpage)
first_tabpage = curtab->tp_next;
@@ -3275,15 +3314,13 @@ void tabpage_move(int nr)
tp->tp_next = curtab->tp_next;
}
- /* Re-insert it at the specified position. */
- if (n <= 0) {
+ // Re-insert it at the specified position.
+ if (nr <= 0) {
curtab->tp_next = first_tabpage;
first_tabpage = curtab;
} else {
- for (tp = first_tabpage; tp->tp_next != NULL && n > 1; tp = tp->tp_next)
- --n;
- curtab->tp_next = tp->tp_next;
- tp->tp_next = curtab;
+ curtab->tp_next = tp_dst->tp_next;
+ tp_dst->tp_next = curtab;
}
/* Need to redraw the tabline. Tab page contents doesn't change. */
@@ -4538,10 +4575,19 @@ void win_drag_vsep_line(win_T *dragwin, int offset)
}
assert(fr);
- if (room < offset) /* Not enough room */
- offset = room; /* Move as far as we can */
- if (offset <= 0) /* No room at all, quit. */
+ // Not enough room
+ if (room < offset) {
+ offset = room; // Move as far as we can
+ }
+
+ // No room at all, quit.
+ if (offset <= 0) {
return;
+ }
+
+ if (fr == NULL) {
+ return; // Safety check, should not happen.
+ }
/* grow frame fr by offset lines */
frame_new_width(fr, fr->fr_width + offset, left, FALSE);
@@ -4837,17 +4883,15 @@ static void frame_add_height(frame_T *frp, int n)
*/
char_u *grab_file_name(long count, linenr_T *file_lnum)
{
+ int options = FNAME_MESS | FNAME_EXP | FNAME_REL | FNAME_UNESC;
if (VIsual_active) {
size_t len;
char_u *ptr;
if (get_visual_text(NULL, &ptr, &len) == FAIL)
return NULL;
- return find_file_name_in_path(ptr, len,
- FNAME_MESS|FNAME_EXP|FNAME_REL,
- count, curbuf->b_ffname);
+ return find_file_name_in_path(ptr, len, options, count, curbuf->b_ffname);
}
- return file_name_at_cursor(FNAME_MESS|FNAME_HYP|FNAME_EXP|FNAME_REL, count,
- file_lnum);
+ return file_name_at_cursor(options | FNAME_HYP, count, file_lnum);
}
/*
@@ -4918,12 +4962,18 @@ file_name_in_line (
* Also allow "://" when ':' is not in 'isfname'.
*/
len = 0;
- while (vim_isfilec(ptr[len])
- || ((options & FNAME_HYP) && path_is_url((char *)ptr + len)))
- if (has_mbyte)
+ while (vim_isfilec(ptr[len]) || (ptr[len] == '\\' && ptr[len + 1] == ' ')
+ || ((options & FNAME_HYP) && path_is_url((char *)ptr + len))) {
+ if (ptr[len] == '\\' && ptr[len + 1] == ' ') {
+ // Skip over the "\" in "\ ".
+ ++len;
+ }
+ if (has_mbyte) {
len += (size_t)(*mb_ptr2len)(ptr + len);
- else
+ } else {
++len;
+ }
+ }
/*
* If there is trailing punctuation, remove it.
@@ -5048,27 +5098,22 @@ int min_rows(void)
return total;
}
-/*
- * Return TRUE if there is only one window (in the current tab page), not
- * counting a help or preview window, unless it is the current window.
- * Does not count "aucmd_win".
- */
-int only_one_window(void)
+/// Check that there is only one window (and only one tab page), not counting a
+/// help or preview window, unless it is the current window. Does not count
+/// "aucmd_win".
+bool only_one_window(void) FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT
{
- int count = 0;
-
- /* If there is another tab page there always is another window. */
- if (first_tabpage->tp_next != NULL)
- return FALSE;
+ // If there is another tab page there always is another window.
+ if (first_tabpage->tp_next != NULL) {
+ return false;
+ }
+ int count = 0;
FOR_ALL_WINDOWS_IN_TAB(wp, curtab) {
if (wp->w_buffer != NULL
&& (!((wp->w_buffer->b_help && !curbuf->b_help)
- || wp->w_p_pvw
- ) || wp == curwin)
- && wp != aucmd_win
- ) {
- ++count;
+ || wp->w_p_pvw) || wp == curwin) && wp != aucmd_win) {
+ count++;
}
}
return count <= 1;
@@ -5306,14 +5351,14 @@ void restore_buffer(buf_T *save_curbuf)
}
-/*
- * Add match to the match list of window 'wp'. The pattern 'pat' will be
- * highlighted with the group 'grp' with priority 'prio'.
- * Optionally, a desired ID 'id' can be specified (greater than or equal to 1).
- * If no particular ID is desired, -1 must be specified for 'id'.
- * Return ID of added match, -1 on failure.
- */
-int match_add(win_T *wp, char_u *grp, char_u *pat, int prio, int id, list_T *pos_list)
+// Add match to the match list of window 'wp'. The pattern 'pat' will be
+// highlighted with the group 'grp' with priority 'prio'.
+// Optionally, a desired ID 'id' can be specified (greater than or equal to 1).
+// If no particular ID is desired, -1 must be specified for 'id'.
+// Return ID of added match, -1 on failure.
+int match_add(win_T *wp, char_u *grp, char_u *pat,
+ int prio, int id, list_T *pos_list,
+ char_u *conceal_char)
{
matchitem_T *cur;
matchitem_T *prev;
@@ -5369,6 +5414,10 @@ int match_add(win_T *wp, char_u *grp, char_u *pat, int prio, int id, list_T *pos
m->match.regprog = regprog;
m->match.rmm_ic = FALSE;
m->match.rmm_maxcol = 0;
+ m->conceal_char = 0;
+ if (conceal_char != NULL) {
+ m->conceal_char = (*mb_ptr2char)(conceal_char);
+ }
// Set up position matches
if (pos_list != NULL)
@@ -5567,38 +5616,42 @@ matchitem_T *get_match(win_T *wp, int id)
}
-/*
- * Return TRUE if "topfrp" and its children are at the right height.
- */
-static int frame_check_height(frame_T *topfrp, int height)
+/// Check that "topfrp" and its children are at the right height.
+///
+/// @param topfrp top frame pointer
+/// @param height expected height
+static bool frame_check_height(frame_T *topfrp, int height)
+ FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ALL
{
- frame_T *frp;
-
- if (topfrp->fr_height != height)
- return FALSE;
-
- if (topfrp->fr_layout == FR_ROW)
- for (frp = topfrp->fr_child; frp != NULL; frp = frp->fr_next)
- if (frp->fr_height != height)
- return FALSE;
-
- return TRUE;
+ if (topfrp->fr_height != height) {
+ return false;
+ }
+ if (topfrp->fr_layout == FR_ROW) {
+ for (frame_T *frp = topfrp->fr_child; frp != NULL; frp = frp->fr_next) {
+ if (frp->fr_height != height) {
+ return false;
+ }
+ }
+ }
+ return true;
}
-/*
- * Return TRUE if "topfrp" and its children are at the right width.
- */
-static int frame_check_width(frame_T *topfrp, int width)
+/// Check that "topfrp" and its children are at the right width.
+///
+/// @param topfrp top frame pointer
+/// @param width expected width
+static bool frame_check_width(frame_T *topfrp, int width)
+ FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ALL
{
- frame_T *frp;
-
- if (topfrp->fr_width != width)
- return FALSE;
-
- if (topfrp->fr_layout == FR_COL)
- for (frp = topfrp->fr_child; frp != NULL; frp = frp->fr_next)
- if (frp->fr_width != width)
- return FALSE;
-
- return TRUE;
+ if (topfrp->fr_width != width) {
+ return false;
+ }
+ if (topfrp->fr_layout == FR_COL) {
+ for (frame_T *frp = topfrp->fr_child; frp != NULL; frp = frp->fr_next) {
+ if (frp->fr_width != width) {
+ return false;
+ }
+ }
+ }
+ return true;
}
diff --git a/src/nvim/window.h b/src/nvim/window.h
index eccc7835a8..2ac4c00c28 100644
--- a/src/nvim/window.h
+++ b/src/nvim/window.h
@@ -10,6 +10,7 @@
#define FNAME_INCL 8 /* apply 'includeexpr' */
#define FNAME_REL 16 /* ".." and "./" are relative to the (current)
file instead of the current directory */
+#define FNAME_UNESC 32 // remove backslashes used for escaping
/*
* arguments for win_split()
diff --git a/test/functional/api/server_requests_spec.lua b/test/functional/api/server_requests_spec.lua
index 16a4423535..c0099e44c4 100644
--- a/test/functional/api/server_requests_spec.lua
+++ b/test/functional/api/server_requests_spec.lua
@@ -43,7 +43,7 @@ describe('server -> client', function()
stop()
end
- local function on_request(method, args)
+ local function on_request()
-- No need to evaluate the args, we are only interested in
-- a response that contains an array with an empty string.
return {1, 2, '', 3, 'asdf'}
diff --git a/test/functional/api/vim_spec.lua b/test/functional/api/vim_spec.lua
index f4a9ddc698..9c9759adf6 100644
--- a/test/functional/api/vim_spec.lua
+++ b/test/functional/api/vim_spec.lua
@@ -144,15 +144,23 @@ describe('vim_* functions', function()
describe('replace_termcodes', function()
it('escapes K_SPECIAL as K_SPECIAL KS_SPECIAL KE_FILLER', function()
- eq(helpers.nvim('replace_termcodes', '\128', true, true, true), '\128\254X')
+ eq('\128\254X', helpers.nvim('replace_termcodes', '\128', true, true, true))
end)
- it('leaves non K_SPECIAL string unchanged', function()
- eq(helpers.nvim('replace_termcodes', 'abc', true, true, true), 'abc')
+ it('leaves non-K_SPECIAL string unchanged', function()
+ eq('abc', helpers.nvim('replace_termcodes', 'abc', true, true, true))
end)
it('converts <expressions>', function()
- eq(helpers.nvim('replace_termcodes', '<Leader>', true, true, true), '\\')
+ eq('\\', helpers.nvim('replace_termcodes', '<Leader>', true, true, true))
+ end)
+
+ it('converts <LeftMouse> to K_SPECIAL KS_EXTRA KE_LEFTMOUSE', function()
+ -- K_SPECIAL KS_EXTRA KE_LEFTMOUSE
+ -- 0x80 0xfd 0x2c
+ -- 128 253 44
+ eq('\128\253\44', helpers.nvim('replace_termcodes',
+ '<LeftMouse>', true, true, true))
end)
end)
diff --git a/test/functional/autocmd/termclose_spec.lua b/test/functional/autocmd/termclose_spec.lua
index 0961340e61..4de3f039c1 100644
--- a/test/functional/autocmd/termclose_spec.lua
+++ b/test/functional/autocmd/termclose_spec.lua
@@ -3,6 +3,7 @@ local Screen = require('test.functional.ui.screen')
local clear, execute, feed, nvim, nvim_dir = helpers.clear,
helpers.execute, helpers.feed, helpers.nvim, helpers.nvim_dir
+local eval, eq = helpers.eval, helpers.eq
describe('TermClose event', function()
local screen
@@ -25,4 +26,19 @@ describe('TermClose event', function()
TermClose works! |
]])
end)
+
+ it('reports the correct <abuf>', function()
+ execute('set hidden')
+ execute('autocmd TermClose * let g:abuf = expand("<abuf>")')
+ execute('edit foo')
+ execute('edit bar')
+ eq(2, eval('bufnr("%")'))
+ execute('terminal')
+ feed('<c-\\><c-n>')
+ eq(3, eval('bufnr("%")'))
+ execute('buffer 1')
+ eq(1, eval('bufnr("%")'))
+ execute('3bdelete!')
+ eq('3', eval('g:abuf'))
+ end)
end)
diff --git a/test/functional/legacy/003_cindent_spec.lua b/test/functional/legacy/003_cindent_spec.lua
index 19694550f4..4b838eda1d 100644
--- a/test/functional/legacy/003_cindent_spec.lua
+++ b/test/functional/legacy/003_cindent_spec.lua
@@ -674,6 +674,13 @@ describe('cindent', function()
{
}
+ A::A(int a, int b)
+ : aa(a),
+ bb(b),
+ cc(c)
+ {
+ }
+
class CAbc :
public BaseClass1,
protected BaseClass2
@@ -919,6 +926,55 @@ describe('cindent', function()
)foo";
}
+ {
+ int a[4] = {
+ [0] = 0,
+ [1] = 1,
+ [2] = 2,
+ [3] = 3,
+ };
+ }
+
+ {
+ a = b[2]
+ + 3;
+ }
+
+ {
+ if (1)
+ /* aaaaa
+ * bbbbb
+ */
+ a = 1;
+ }
+
+ void func()
+ {
+ switch (foo)
+ {
+ case (bar):
+ if (baz())
+ quux();
+ break;
+ case (shmoo):
+ if (!bar)
+ {
+ }
+ case (foo1):
+ switch (bar)
+ {
+ case baz:
+ baz_f();
+ break;
+ }
+ break;
+ default:
+ baz();
+ baz();
+ break;
+ }
+ }
+
/* end of AUTO */
]=])
@@ -1580,6 +1636,13 @@ describe('cindent', function()
{
}
+ A::A(int a, int b)
+ : aa(a),
+ bb(b),
+ cc(c)
+ {
+ }
+
class CAbc :
public BaseClass1,
protected BaseClass2
@@ -1825,6 +1888,55 @@ describe('cindent', function()
)foo";
}
+ {
+ int a[4] = {
+ [0] = 0,
+ [1] = 1,
+ [2] = 2,
+ [3] = 3,
+ };
+ }
+
+ {
+ a = b[2]
+ + 3;
+ }
+
+ {
+ if (1)
+ /* aaaaa
+ * bbbbb
+ */
+ a = 1;
+ }
+
+ void func()
+ {
+ switch (foo)
+ {
+ case (bar):
+ if (baz())
+ quux();
+ break;
+ case (shmoo):
+ if (!bar)
+ {
+ }
+ case (foo1):
+ switch (bar)
+ {
+ case baz:
+ baz_f();
+ break;
+ }
+ break;
+ default:
+ baz();
+ baz();
+ break;
+ }
+ }
+
/* end of AUTO */
]=])
end)
diff --git a/test/functional/legacy/011_autocommands_spec.lua b/test/functional/legacy/011_autocommands_spec.lua
new file mode 100644
index 0000000000..483e465cee
--- /dev/null
+++ b/test/functional/legacy/011_autocommands_spec.lua
@@ -0,0 +1,230 @@
+-- Tests for autocommands
+-- - FileWritePre writing a compressed file
+-- - FileReadPost reading a compressed file
+-- - BufNewFile reading a file template
+-- - BufReadPre decompressing the file to be read
+-- - FilterReadPre substituting characters in the temp file
+-- - FilterReadPost substituting characters after filtering
+-- - FileReadPre set options for decompression
+-- - FileReadPost decompress the file
+-- Note: This test is skipped if "gzip" is not available.
+-- $GZIP is made empty, "-v" would cause trouble.
+-- Use a FileChangedShell autocommand to avoid a prompt for "Xtestfile.gz"
+-- being modified outside of Vim (noticed on Solaris).
+
+local helpers, lfs = require('test.functional.helpers'), require('lfs')
+local clear, execute, expect, eq, neq, dedent, write_file, feed =
+ helpers.clear, helpers.execute, helpers.expect, helpers.eq, helpers.neq,
+ helpers.dedent, helpers.write_file, helpers.feed
+
+local function has_gzip()
+ return os.execute('gzip --help >/dev/null 2>&1') == 0
+end
+
+local function prepare_gz_file(name, text)
+ write_file(name, text..'\n')
+ -- Compress the file with gzip.
+ os.execute('gzip --force '..name)
+ -- This should create the .gz file and delete the original.
+ neq(nil, lfs.attributes(name..'.gz'))
+ eq(nil, lfs.attributes(name))
+end
+
+describe('file reading, writing and bufnew and filter autocommands', function()
+ local text1 = dedent([[
+ start of testfile
+ line 2 Abcdefghijklmnopqrstuvwxyz
+ line 3 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+ line 4 Abcdefghijklmnopqrstuvwxyz
+ line 5 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+ line 6 Abcdefghijklmnopqrstuvwxyz
+ line 7 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+ line 8 Abcdefghijklmnopqrstuvwxyz
+ line 9 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+ line 10 Abcdefghijklmnopqrstuvwxyz
+ end of testfile]])
+ setup(function()
+ write_file('Xtest.c', [[
+ /*
+ * Here is a new .c file
+ */
+ ]])
+ end)
+ before_each(clear)
+ teardown(function()
+ os.remove('Xtestfile.gz')
+ os.remove('Xtest.c')
+ os.remove('test.out')
+ end)
+
+ if not has_gzip() then
+ pending('skipped (missing `gzip` utility)', function() end)
+ else
+
+ it('FileReadPost (using gzip)', function()
+ prepare_gz_file('Xtestfile', text1)
+ execute('let $GZIP = ""')
+ --execute('au FileChangedShell * echo "caught FileChangedShell"')
+ execute('set bin')
+ execute("au FileReadPost *.gz '[,']!gzip -d")
+ -- Read and decompress the testfile.
+ execute('$r Xtestfile.gz')
+ expect('\n'..text1)
+ end)
+
+ it('BufReadPre, BufReadPost (using gzip)', function()
+ prepare_gz_file('Xtestfile', text1)
+ local gzip_data = io.open('Xtestfile.gz'):read('*all')
+ execute('let $GZIP = ""')
+ -- Setup autocommands to decompress before reading and re-compress afterwards.
+ execute("au BufReadPre *.gz exe '!gzip -d ' . shellescape(expand('<afile>'))")
+ execute("au BufReadPre *.gz call rename(expand('<afile>:r'), expand('<afile>'))")
+ execute("au BufReadPost *.gz call rename(expand('<afile>'), expand('<afile>:r'))")
+ execute("au BufReadPost *.gz exe '!gzip ' . shellescape(expand('<afile>:r'))")
+ -- Edit compressed file.
+ execute('e! Xtestfile.gz')
+ -- Discard all prompts and messages.
+ feed('<C-L>')
+ -- Expect the decompressed file in the buffer.
+ expect(text1)
+ -- Expect the original file to be unchanged.
+ eq(gzip_data, io.open('Xtestfile.gz'):read('*all'))
+ end)
+
+ it('FileReadPre, FileReadPost', function()
+ prepare_gz_file('Xtestfile', text1)
+ execute('au! FileReadPre *.gz exe "silent !gzip -d " . shellescape(expand("<afile>"))')
+ execute('au FileReadPre *.gz call rename(expand("<afile>:r"), expand("<afile>"))')
+ execute("au! FileReadPost *.gz '[,']s/l/L/")
+ -- Read compressed file.
+ execute('$r Xtestfile.gz')
+ -- Discard all prompts and messages.
+ feed('<C-L>')
+ expect([[
+
+ start of testfiLe
+ Line 2 Abcdefghijklmnopqrstuvwxyz
+ Line 3 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+ Line 4 Abcdefghijklmnopqrstuvwxyz
+ Line 5 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+ Line 6 Abcdefghijklmnopqrstuvwxyz
+ Line 7 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+ Line 8 Abcdefghijklmnopqrstuvwxyz
+ Line 9 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+ Line 10 Abcdefghijklmnopqrstuvwxyz
+ end of testfiLe]])
+ end)
+
+ end
+
+ it('FileAppendPre, FileAppendPost', function()
+ execute('au BufNewFile *.c read Xtest.c')
+ -- Will load Xtest.c.
+ execute('e! foo.c')
+ execute("au FileAppendPre *.out '[,']s/new/NEW/")
+ execute('au FileAppendPost *.out !cat Xtest.c >>test.out')
+ -- Append it to the output file.
+ execute('w>>test.out')
+ -- Discard all prompts and messages.
+ feed('<C-L>')
+ -- Expect the decompressed file in the buffer.
+ execute('e test.out')
+ expect([[
+
+ /*
+ * Here is a NEW .c file
+ */]])
+ end)
+
+ it('FilterReadPre, FilterReadPost', function()
+ -- Write a special input file for this test block.
+ write_file('test.out', dedent([[
+ startstart
+ ]]) .. text1 .. dedent([[
+
+
+ start of test.c
+ /*
+ * Here is a new .c file
+ */
+ end of test.c
+ ]]) .. text1 .. dedent([[
+
+
+ /*
+ * Here is a NEW .c file
+ */
+ /*
+ * Here is a new .c file
+ */
+ ]]) .. text1 .. dedent([[
+
+ /*
+ * Here is a new .c file
+ */]]))
+ -- Need temp files here.
+ execute('set shelltemp')
+ execute('au FilterReadPre *.out call rename(expand("<afile>"), expand("<afile>") . ".t")')
+ execute('au FilterReadPre *.out exe "silent !sed s/e/E/ " . shellescape(expand("<afile>")) . ".t >" . shellescape(expand("<afile>"))')
+ execute('au FilterReadPre *.out exe "silent !rm " . shellescape(expand("<afile>")) . ".t"')
+ execute("au FilterReadPost *.out '[,']s/x/X/g")
+ -- Edit the output file.
+ execute('e! test.out')
+ execute('23,$!cat')
+ -- Discard all prompts and messages.
+ feed('<C-L>')
+ -- Remove CR for when sed adds them.
+ execute([[23,$s/\r$//]])
+ expect([[
+ startstart
+ start of testfile
+ line 2 Abcdefghijklmnopqrstuvwxyz
+ line 3 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+ line 4 Abcdefghijklmnopqrstuvwxyz
+ line 5 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+ line 6 Abcdefghijklmnopqrstuvwxyz
+ line 7 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+ line 8 Abcdefghijklmnopqrstuvwxyz
+ line 9 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+ line 10 Abcdefghijklmnopqrstuvwxyz
+ end of testfile
+
+ start of test.c
+ /*
+ * Here is a new .c file
+ */
+ end of test.c
+ start of testfile
+ line 2 Abcdefghijklmnopqrstuvwxyz
+ line 3 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+ line 4 Abcdefghijklmnopqrstuvwxyz
+ linE 5 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+ linE 6 AbcdefghijklmnopqrstuvwXyz
+ linE 7 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+ linE 8 AbcdefghijklmnopqrstuvwXyz
+ linE 9 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+ linE 10 AbcdefghijklmnopqrstuvwXyz
+ End of testfile
+
+ /*
+ * HEre is a NEW .c file
+ */
+ /*
+ * HEre is a new .c file
+ */
+ start of tEstfile
+ linE 2 AbcdefghijklmnopqrstuvwXyz
+ linE 3 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+ linE 4 AbcdefghijklmnopqrstuvwXyz
+ linE 5 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+ linE 6 AbcdefghijklmnopqrstuvwXyz
+ linE 7 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+ linE 8 AbcdefghijklmnopqrstuvwXyz
+ linE 9 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+ linE 10 AbcdefghijklmnopqrstuvwXyz
+ End of testfile
+ /*
+ * HEre is a new .c file
+ */]])
+ end)
+end)
diff --git a/test/functional/legacy/036_regexp_character_classes_spec.lua b/test/functional/legacy/036_regexp_character_classes_spec.lua
new file mode 100644
index 0000000000..205922eac2
--- /dev/null
+++ b/test/functional/legacy/036_regexp_character_classes_spec.lua
@@ -0,0 +1,272 @@
+-- Test character classes in regexp using regexpengine 0, 1, 2.
+
+local helpers = require('test.functional.helpers')
+local ffi = require('ffi')
+local feed, insert, source = helpers.feed, helpers.insert, helpers.source
+local clear, execute, expect, eq, eval = helpers.clear, helpers.execute, helpers.expect, helpers.eq, helpers.eval
+local write_file = helpers.write_file
+
+local function sixlines(text)
+ local result = ''
+ for i = 1, 6 do
+ result = result .. text .. '\n'
+ end
+ return result
+end
+
+local function diff(text, nodedent)
+ local tmpname = os.tmpname()
+ if ffi.os == 'OSX' and string.match(tmpname, '^/tmp') then
+ tmpname = '/private'..tmpname
+ end
+ execute('w! '..tmpname)
+ helpers.wait()
+ local data = io.open(tmpname):read('*all')
+ if nodedent then
+ helpers.eq(text, data)
+ else
+ helpers.eq(helpers.dedent(text), data)
+ end
+ os.remove(tmpname)
+end
+
+describe('character classes in regexp', function()
+ local ctrl1 = '\t\x0c\r'
+ local punct1 = " !\"#$%&'()#+'-./"
+ local digits = '0123456789'
+ local punct2 = ':;<=>?@'
+ local upper = 'ABCDEFGHIXYZ'
+ 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
+ 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
+ -- them to the test file.
+ local line = ctrl1..punct1..digits..punct2..upper..punct3..lower..punct4..ctrl2..iso_text
+ write_file('test36.in', sixlines(line))
+ end)
+ before_each(function()
+ clear()
+ execute('e test36.in')
+ end)
+ teardown(function()
+ os.remove('test36.in')
+ end)
+
+ it('is working', function()
+ source([[
+ 1 s/\%#=0\d//g
+ 2 s/\%#=1\d//g
+ 3 s/\%#=2\d//g
+ 4 s/\%#=0[0-9]//g
+ 5 s/\%#=1[0-9]//g
+ 6 s/\%#=2[0-9]//g]])
+ diff(sixlines(ctrl1..punct1..punct2..upper..punct3..lower..punct4..
+ ctrl2..iso_text))
+ end)
+ it('is working', function()
+ source([[
+ 1 s/\%#=0\D//g
+ 2 s/\%#=1\D//g
+ 3 s/\%#=2\D//g
+ 4 s/\%#=0[^0-9]//g
+ 5 s/\%#=1[^0-9]//g
+ 6 s/\%#=2[^0-9]//g]])
+ expect([[
+ 0123456789
+ 0123456789
+ 0123456789
+ 0123456789
+ 0123456789
+ 0123456789]])
+ end)
+ it('is working', function()
+ source([[
+ 1 s/\%#=0\o//g
+ 2 s/\%#=1\o//g
+ 3 s/\%#=2\o//g
+ 4 s/\%#=0[0-7]//g
+ 5 s/\%#=1[0-7]//g
+ 6 s/\%#=2[0-7]//g]])
+ diff(sixlines(ctrl1..punct1..'89'..punct2..upper..punct3..lower..punct4..ctrl2..
+ iso_text))
+ end)
+ it('is working', function()
+ source([[
+ 1 s/\%#=0\O//g
+ 2 s/\%#=1\O//g
+ 3 s/\%#=2\O//g
+ 4 s/\%#=0[^0-7]//g
+ 5 s/\%#=1[^0-7]//g
+ 6 s/\%#=2[^0-7]//g]])
+ expect([[
+ 01234567
+ 01234567
+ 01234567
+ 01234567
+ 01234567
+ 01234567]])
+ end)
+ it('is working', function()
+ source([[
+ 1 s/\%#=0\x//g
+ 2 s/\%#=1\x//g
+ 3 s/\%#=2\x//g
+ 4 s/\%#=0[0-9A-Fa-f]//g
+ 5 s/\%#=1[0-9A-Fa-f]//g
+ 6 s/\%#=2[0-9A-Fa-f]//g]])
+ diff(sixlines(ctrl1..punct1..punct2..'GHIXYZ'..punct3..'ghiwxyz'..punct4..ctrl2..iso_text))
+ end)
+ it('is working', function()
+ source([[
+ 1 s/\%#=0\X//g
+ 2 s/\%#=1\X//g
+ 3 s/\%#=2\X//g
+ 4 s/\%#=0[^0-9A-Fa-f]//g
+ 5 s/\%#=1[^0-9A-Fa-f]//g
+ 6 s/\%#=2[^0-9A-Fa-f]//g]])
+ expect([[
+ 0123456789ABCDEFabcdef
+ 0123456789ABCDEFabcdef
+ 0123456789ABCDEFabcdef
+ 0123456789ABCDEFabcdef
+ 0123456789ABCDEFabcdef
+ 0123456789ABCDEFabcdef]])
+ end)
+ it('is working', function()
+ source([[
+ 1 s/\%#=0\w//g
+ 2 s/\%#=1\w//g
+ 3 s/\%#=2\w//g
+ 4 s/\%#=0[0-9A-Za-z_]//g
+ 5 s/\%#=1[0-9A-Za-z_]//g
+ 6 s/\%#=2[0-9A-Za-z_]//g]])
+ diff(sixlines(ctrl1..punct1..punct2..'[\\]^`'..punct4..ctrl2..iso_text))
+ end)
+ it('is working', function()
+ source([[
+ 1 s/\%#=0\W//g
+ 2 s/\%#=1\W//g
+ 3 s/\%#=2\W//g
+ 4 s/\%#=0[^0-9A-Za-z_]//g
+ 5 s/\%#=1[^0-9A-Za-z_]//g
+ 6 s/\%#=2[^0-9A-Za-z_]//g]])
+ expect([[
+ 0123456789ABCDEFGHIXYZ_abcdefghiwxyz
+ 0123456789ABCDEFGHIXYZ_abcdefghiwxyz
+ 0123456789ABCDEFGHIXYZ_abcdefghiwxyz
+ 0123456789ABCDEFGHIXYZ_abcdefghiwxyz
+ 0123456789ABCDEFGHIXYZ_abcdefghiwxyz
+ 0123456789ABCDEFGHIXYZ_abcdefghiwxyz]])
+ end)
+ it('is working', function()
+ source([[
+ 1 s/\%#=0\h//g
+ 2 s/\%#=1\h//g
+ 3 s/\%#=2\h//g
+ 4 s/\%#=0[A-Za-z_]//g
+ 5 s/\%#=1[A-Za-z_]//g
+ 6 s/\%#=2[A-Za-z_]//g]])
+ diff(sixlines(ctrl1..punct1..digits..punct2..'[\\]^`'..punct4..ctrl2..
+ iso_text))
+ end)
+ it('is working', function()
+ source([[
+ 1 s/\%#=0\H//g
+ 2 s/\%#=1\H//g
+ 3 s/\%#=2\H//g
+ 4 s/\%#=0[^A-Za-z_]//g
+ 5 s/\%#=1[^A-Za-z_]//g
+ 6 s/\%#=2[^A-Za-z_]//g]])
+ expect([[
+ ABCDEFGHIXYZ_abcdefghiwxyz
+ ABCDEFGHIXYZ_abcdefghiwxyz
+ ABCDEFGHIXYZ_abcdefghiwxyz
+ ABCDEFGHIXYZ_abcdefghiwxyz
+ ABCDEFGHIXYZ_abcdefghiwxyz
+ ABCDEFGHIXYZ_abcdefghiwxyz]])
+ end)
+ it('is working', function()
+ source([[
+ 1 s/\%#=0\a//g
+ 2 s/\%#=1\a//g
+ 3 s/\%#=2\a//g
+ 4 s/\%#=0[A-Za-z]//g
+ 5 s/\%#=1[A-Za-z]//g
+ 6 s/\%#=2[A-Za-z]//g]])
+ diff(sixlines(ctrl1..punct1..digits..punct2..punct3..punct4..ctrl2..iso_text))
+ end)
+ it('is working', function()
+ source([[
+ 1 s/\%#=0\A//g
+ 2 s/\%#=1\A//g
+ 3 s/\%#=2\A//g
+ 4 s/\%#=0[^A-Za-z]//g
+ 5 s/\%#=1[^A-Za-z]//g
+ 6 s/\%#=2[^A-Za-z]//g]])
+ expect([[
+ ABCDEFGHIXYZabcdefghiwxyz
+ ABCDEFGHIXYZabcdefghiwxyz
+ ABCDEFGHIXYZabcdefghiwxyz
+ ABCDEFGHIXYZabcdefghiwxyz
+ ABCDEFGHIXYZabcdefghiwxyz
+ ABCDEFGHIXYZabcdefghiwxyz]])
+ end)
+ it('is working', function()
+ source([[
+ 1 s/\%#=0\l//g
+ 2 s/\%#=1\l//g
+ 3 s/\%#=2\l//g
+ 4 s/\%#=0[a-z]//g
+ 5 s/\%#=1[a-z]//g
+ 6 s/\%#=2[a-z]//g]])
+ diff(sixlines(ctrl1..punct1..digits..punct2..upper..punct3..punct4..
+ ctrl2..iso_text))
+ end)
+ it('is working', function()
+ source([[
+ 1 s/\%#=0\L//g
+ 2 s/\%#=1\L//g
+ 3 s/\%#=2\L//g
+ 4 s/\%#=0[^a-z]//g
+ 5 s/\%#=1[^a-z]//g
+ 6 s/\%#=2[^a-z]//g]])
+ expect([[
+ abcdefghiwxyz
+ abcdefghiwxyz
+ abcdefghiwxyz
+ abcdefghiwxyz
+ abcdefghiwxyz
+ abcdefghiwxyz]])
+ end)
+ it('is working', function()
+ source([[
+ 1 s/\%#=0\u//g
+ 2 s/\%#=1\u//g
+ 3 s/\%#=2\u//g
+ 4 s/\%#=0[A-Z]//g
+ 5 s/\%#=1[A-Z]//g
+ 6 s/\%#=2[A-Z]//g]])
+ diff(sixlines(ctrl1..punct1..digits..punct2..punct3..lower..punct4..
+ ctrl2..iso_text))
+ end)
+ it('is working', function()
+ source([[
+ 1 s/\%#=0\U//g
+ 2 s/\%#=1\U//g
+ 3 s/\%#=2\U//g
+ 4 s/\%#=0[^A-Z]//g
+ 5 s/\%#=1[^A-Z]//g
+ 6 s/\%#=2[^A-Z]//g]])
+ expect([[
+ ABCDEFGHIXYZ
+ ABCDEFGHIXYZ
+ ABCDEFGHIXYZ
+ ABCDEFGHIXYZ
+ ABCDEFGHIXYZ
+ ABCDEFGHIXYZ]])
+ end)
+end)
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 55db9169fa..6e1879035b 100644
--- a/test/functional/legacy/039_visual_block_mode_commands_spec.lua
+++ b/test/functional/legacy/039_visual_block_mode_commands_spec.lua
@@ -5,7 +5,7 @@ local helpers = require('test.functional.helpers')
local nvim, eq = helpers.meths, helpers.eq
local insert, feed = helpers.insert, helpers.feed
local clear, expect = helpers.clear, helpers.expect
-local source, execute = helpers.source, helpers.execute
+local execute = helpers.execute
describe('Visual block mode', function()
diff --git a/test/functional/legacy/045_folding_spec.lua b/test/functional/legacy/045_folding_spec.lua
new file mode 100644
index 0000000000..04b623ff3b
--- /dev/null
+++ b/test/functional/legacy/045_folding_spec.lua
@@ -0,0 +1,139 @@
+-- Tests for folding.
+
+local helpers = require('test.functional.helpers')
+local feed, insert, clear, execute, expect =
+ helpers.feed, helpers.insert, helpers.clear, helpers.execute, helpers.expect
+
+describe('folding', function()
+ before_each(clear)
+
+ it('is working', function()
+ insert([[
+ 1 aa
+ 2 bb
+ 3 cc
+ 4 dd {{{
+ 5 ee {{{ }}}
+ 6 ff }}}
+ 7 gg
+ 8 hh
+ 9 ii
+ a jj
+ b kk
+ last]])
+
+ -- Basic test if a fold can be created, opened, moving to the end and
+ -- closed.
+ execute('/^1')
+ feed('zf2j')
+ execute('call append("$", "manual " . getline(foldclosed(".")))')
+ feed('zo')
+ execute('call append("$", foldclosed("."))')
+ feed(']z')
+ execute('call append("$", getline("."))')
+ feed('zc')
+ execute('call append("$", getline(foldclosed(".")))')
+ -- Test folding with markers.
+ execute('set fdm=marker fdl=1 fdc=3')
+ execute('/^5')
+ execute('call append("$", "marker " . foldlevel("."))')
+ feed('[z')
+ execute('call append("$", foldlevel("."))')
+ feed('jo{{ <esc>r{jj')
+ execute('call append("$", foldlevel("."))')
+ feed('kYpj')
+ execute('call append("$", foldlevel("."))')
+ -- Test folding with indent.
+ execute('set fdm=indent sw=2')
+ execute('/^2 b')
+ feed('i <esc>jI <esc>')
+ execute('call append("$", "indent " . foldlevel("."))')
+ feed('k')
+ execute('call append("$", foldlevel("."))')
+ -- Test syntax folding.
+ execute('set fdm=syntax fdl=0')
+ execute('syn region Hup start="dd" end="ii" fold contains=Fd1,Fd2,Fd3')
+ execute('syn region Fd1 start="ee" end="ff" fold contained')
+ execute('syn region Fd2 start="gg" end="hh" fold contained')
+ execute('syn region Fd3 start="commentstart" end="commentend" fold contained')
+ feed('Gzk')
+ execute('call append("$", "folding " . getline("."))')
+ feed('k')
+ execute('call append("$", getline("."))')
+ feed('jAcommentstart <esc>Acommentend<esc>')
+ execute('set fdl=1')
+ feed('3j')
+ execute('call append("$", getline("."))')
+ execute('set fdl=0')
+ feed('zO<C-L>j')
+ execute('call append("$", getline("."))')
+ -- Test expression folding.
+ execute('fun Flvl()')
+ execute(' let l = getline(v:lnum)')
+ execute(' if l =~ "bb$"')
+ execute(' return 2')
+ execute(' elseif l =~ "gg$"')
+ execute(' return "s1"')
+ execute(' elseif l =~ "ii$"')
+ execute(' return ">2"')
+ execute(' elseif l =~ "kk$"')
+ execute(' return "0"')
+ execute(' endif')
+ execute(' return "="')
+ execute('endfun')
+ execute('set fdm=expr fde=Flvl()')
+ execute('/bb$')
+ execute('call append("$", "expr " . foldlevel("."))')
+ execute('/hh$')
+ execute('call append("$", foldlevel("."))')
+ execute('/ii$')
+ execute('call append("$", foldlevel("."))')
+ execute('/kk$')
+ execute('call append("$", foldlevel("."))')
+ execute('0,/^last/delete')
+ execute('delfun Flvl')
+
+ -- Assert buffer contents.
+ expect([[
+ manual 1 aa
+ -1
+ 3 cc
+ 1 aa
+ marker 2
+ 1
+ 1
+ 0
+ indent 2
+ 1
+ folding 9 ii
+ 3 cc
+ 7 gg
+ 8 hh
+ expr 2
+ 1
+ 2
+ 0]])
+ end)
+
+ it('can open after :move', function()
+ insert([[
+ Test fdm=indent and :move bug END
+ line2
+ Test fdm=indent START
+ line3
+ line4]])
+
+ execute('set noai nosta')
+ execute('set fdm=indent')
+ execute('1m1')
+ feed('2jzc')
+ execute('m0')
+
+ expect([[
+ Test fdm=indent START
+ line3
+ line4
+ Test fdm=indent and :move bug END
+ line2]])
+ end)
+end)
diff --git a/test/functional/legacy/057_sort_spec.lua b/test/functional/legacy/057_sort_spec.lua
index 65defbae96..7eed31e292 100644
--- a/test/functional/legacy/057_sort_spec.lua
+++ b/test/functional/legacy/057_sort_spec.lua
@@ -600,39 +600,72 @@ describe(':sort', function()
eq('Vim(sort):E474: Invalid argument', eval('tmpvar'))
expect(text)
end)
-
+
it('binary', function()
insert([[
- 0b111000
- 0b101100
- 0b101001
- 0b101001
- 0b101000
- 0b000000
- 0b001000
- 0b010000
- 0b101000
- 0b100000
- 0b101010
- 0b100010
- 0b100100
- 0b100010]])
+ 0b111000
+ 0b101100
+ 0b101001
+ 0b101001
+ 0b101000
+ 0b000000
+ 0b001000
+ 0b010000
+ 0b101000
+ 0b100000
+ 0b101010
+ 0b100010
+ 0b100100
+ 0b100010]])
execute([[sort b]])
expect([[
- 0b000000
- 0b001000
- 0b010000
- 0b100000
- 0b100010
- 0b100010
- 0b100100
- 0b101000
- 0b101000
- 0b101001
- 0b101001
- 0b101010
- 0b101100
- 0b111000]])
+ 0b000000
+ 0b001000
+ 0b010000
+ 0b100000
+ 0b100010
+ 0b100010
+ 0b100100
+ 0b101000
+ 0b101000
+ 0b101001
+ 0b101001
+ 0b101010
+ 0b101100
+ 0b111000]])
end)
+ it('binary with leading characters', function()
+ insert([[
+ 0b100010
+ 0b010000
+ 0b101001
+ b0b101100
+ 0b100010
+ 0b100100
+ a0b001000
+ 0b101000
+ 0b101000
+ a0b101001
+ ab0b100000
+ 0b101010
+ 0b000000
+ b0b111000]])
+ execute([[sort b]])
+ expect([[
+ 0b000000
+ a0b001000
+ 0b010000
+ ab0b100000
+ 0b100010
+ 0b100010
+ 0b100100
+ 0b101000
+ 0b101000
+ 0b101001
+ a0b101001
+ 0b101010
+ b0b101100
+ b0b111000]])
+ end)
end)
diff --git a/test/functional/legacy/059_utf8_spell_checking_spec.lua b/test/functional/legacy/059_utf8_spell_checking_spec.lua
index 5794e875a0..63df387be3 100644
--- a/test/functional/legacy/059_utf8_spell_checking_spec.lua
+++ b/test/functional/legacy/059_utf8_spell_checking_spec.lua
@@ -31,8 +31,6 @@ describe("spell checking with 'encoding' set to utf-8", function()
RAR ?
BAD !
- #NOSPLITSUGS
-
PFX I N 1
PFX I 0 in .
@@ -92,8 +90,6 @@ describe("spell checking with 'encoding' set to utf-8", function()
RAR ?
BAD !
- #NOSPLITSUGS
-
PFX I N 1
PFX I 0 in .
@@ -300,6 +296,24 @@ describe("spell checking with 'encoding' set to utf-8", function()
tail/123
middle/77,1
]])
+ write_latin1('Xtest8.aff', [[
+ SET ISO8859-1
+
+ NOSPLITSUGS
+ ]])
+ write_latin1('Xtest8.dic', [[
+ 1234
+ foo
+ bar
+ faabar
+ ]])
+ write_latin1('Xtest9.aff', [[
+ ]])
+ write_latin1('Xtest9.dic', [[
+ 1234
+ foo
+ bar
+ ]])
write_latin1('Xtest-sal.aff', [[
SET ISO8859-1
TRY esianrtolcdugmphbyfvkwjkqxz-ëéèêïîäàâöüû'ESIANRTOLCDUGMPHBYFVKWJKQXZ
@@ -314,8 +328,6 @@ describe("spell checking with 'encoding' set to utf-8", function()
RAR ?
BAD !
- #NOSPLITSUGS
-
PFX I N 1
PFX I 0 in .
@@ -483,6 +495,10 @@ describe("spell checking with 'encoding' set to utf-8", function()
os.remove('Xtest6.dic')
os.remove('Xtest7.aff')
os.remove('Xtest7.dic')
+ os.remove('Xtest8.aff')
+ os.remove('Xtest8.dic')
+ os.remove('Xtest9.aff')
+ os.remove('Xtest9.dic')
end)
-- Function to test .aff/.dic with list of good and bad words. This was a
@@ -940,4 +956,46 @@ describe("spell checking with 'encoding' set to utf-8", function()
leadprobar
['leadprebar', 'lead prebar', 'leadbar']]=])
end)
+
+ it('part 8-8', function()
+ insert([[
+ 8good: foo bar faabar
+ bad: foobar barfoo
+ badend
+ ]])
+ -- NOSPLITSUGS
+ test_one(8, 8)
+ -- Assert buffer contents.
+ execute('1,/^test 8-8/-1d')
+ expect([=[
+ test 8-8
+ # file: Xtest.utf-8.spl
+ bar
+ faabar
+ foo
+ -------
+ bad
+ ['bar', 'foo']
+ foobar
+ ['faabar', 'foo bar', 'bar']
+ barfoo
+ ['bar foo', 'bar', 'foo']]=])
+ end)
+
+ it('part 9-9', function()
+ insert([[
+ 9good: 0b1011 0777 1234 0x01ff
+ badend
+ ]])
+ -- NOSPLITSUGS
+ test_one(9, 9)
+ -- Assert buffer contents.
+ execute('1,/^test 9-9/-1d')
+ expect([=[
+ test 9-9
+ # file: Xtest.utf-8.spl
+ bar
+ foo
+ -------]=])
+ end)
end)
diff --git a/test/functional/legacy/062_tab_pages_spec.lua b/test/functional/legacy/062_tab_pages_spec.lua
index 6bbb06f9a7..f1c8b8d58b 100644
--- a/test/functional/legacy/062_tab_pages_spec.lua
+++ b/test/functional/legacy/062_tab_pages_spec.lua
@@ -86,21 +86,35 @@ describe('tab pages', function()
feed('1gt')
eq(1, eval('tabpagenr()'))
execute('tabmove 5')
- eq(6, eval('tabpagenr()'))
- execute('tabmove -2')
+ eq(5, eval('tabpagenr()'))
+ execute('.tabmove')
+ eq(5, eval('tabpagenr()'))
+ execute('tabmove -')
eq(4, eval('tabpagenr()'))
+ execute('tabmove +')
+ eq(5, eval('tabpagenr()'))
+ execute('tabmove -2')
+ eq(3, eval('tabpagenr()'))
execute('tabmove +4')
- eq(8, eval('tabpagenr()'))
+ eq(7, eval('tabpagenr()'))
execute('tabmove')
eq(10, eval('tabpagenr()'))
execute('tabmove -20')
eq(1, eval('tabpagenr()'))
execute('tabmove +20')
eq(10, eval('tabpagenr()'))
+ execute('0tabmove')
+ eq(1, eval('tabpagenr()'))
+ execute('$tabmove')
+ eq(10, eval('tabpagenr()'))
+ execute('tabmove 0')
+ eq(1, eval('tabpagenr()'))
+ execute('tabmove $')
+ eq(10, eval('tabpagenr()'))
execute('3tabmove')
eq(4, eval('tabpagenr()'))
execute('7tabmove 5')
- eq(6, eval('tabpagenr()'))
+ eq(5, eval('tabpagenr()'))
execute('let a="No error caught."')
execute('try')
execute('tabmove foo')
diff --git a/test/functional/legacy/063_match_and_matchadd_spec.lua b/test/functional/legacy/063_match_and_matchadd_spec.lua
index a354d4d328..23b4f4551b 100644
--- a/test/functional/legacy/063_match_and_matchadd_spec.lua
+++ b/test/functional/legacy/063_match_and_matchadd_spec.lua
@@ -89,7 +89,11 @@ describe('063: Test for ":match", "matchadd()" and related functions', function(
execute("call clearmatches()")
execute("call setmatches(ml)")
eq(ml, eval('getmatches()'))
+
+ -- Check that "setmatches()" can correctly restore the matches from matchaddpos()
execute("call clearmatches()")
+ execute("call setmatches(ml)")
+ eq(ml, eval('getmatches()'))
-- Check that "setmatches()" will not add two matches with the same ID. The
-- expected behaviour (for now) is to add the first match but not the
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
new file mode 100644
index 0000000000..dc6df007e6
--- /dev/null
+++ b/test/functional/legacy/083_tag_search_with_file_encoding_spec.lua
@@ -0,0 +1,110 @@
+-- Tests for tag search with !_TAG_FILE_ENCODING.
+
+local helpers = require('test.functional.helpers')
+local insert, source, clear, expect, write_file = helpers.insert,
+ helpers.source, helpers.clear, helpers.expect, helpers.write_file
+
+local function has_iconv()
+ clear() -- ensures session
+ return 1 == helpers.eval('has("iconv")')
+end
+
+describe('tag search with !_TAG_FILE_ENCODING', function()
+ setup(function()
+ clear()
+ -- Create some temp files that are needed for the test run. In the old
+ -- test suite this was done by putting the text inside the file test83.in
+ -- and executing some "/first/,/last/w! tmpfile" commands.
+ write_file('Xtags1.txt', 'text for tags1\nabcdefghijklmnopqrs\n')
+ write_file('Xtags2.txt', 'text for tags2\nABC\n')
+ write_file('Xtags3.txt', 'text for tags3\nABC\n')
+ write_file('Xtags1', [[
+ !_TAG_FILE_ENCODING utf-8 //
+ abcdefghijklmnopqrs Xtags1.txt /abcdefghijklmnopqrs
+ ]])
+ write_file('test83-tags2',
+ '!_TAG_FILE_ENCODING cp932 //\n' ..
+ '\x82`\x82a\x82b Xtags2.txt /\x82`\x82a\x82b\n'
+ )
+ -- The last file is very long but repetetive and can be generated on the
+ -- fly.
+ local text = helpers.dedent([[
+ !_TAG_FILE_SORTED 1 //
+ !_TAG_FILE_ENCODING cp932 //
+ ]])
+ local line = ' Xtags3.txt /\x82`\x82a\x82b\n'
+ for i = 1, 100 do
+ text = text .. 'abc' .. i .. line
+ end
+ write_file('test83-tags3', text)
+ end)
+ teardown(function()
+ os.remove('Xtags1')
+ os.remove('Xtags1.txt')
+ os.remove('Xtags2.txt')
+ os.remove('Xtags3.txt')
+ os.remove('test83-tags2')
+ os.remove('test83-tags3')
+ end)
+
+ if not has_iconv() then
+ pending('skipped (missing iconv)', function() end)
+ else
+ it('is working', function()
+
+ insert('Results of test83')
+
+ -- Case1:
+ source([[
+ new
+ set tags=Xtags1
+ let v:errmsg = ''
+ tag abcdefghijklmnopqrs
+ if v:errmsg =~ 'E426:' || getline('.') != 'abcdefghijklmnopqrs'
+ close
+ put ='case1: failed'
+ else
+ close
+ put ='case1: ok'
+ endif
+ ]])
+
+ -- Case2:
+ source([[
+ new
+ set tags=test83-tags2
+ let v:errmsg = ''
+ tag /.BC
+ if v:errmsg =~ 'E426:' || getline('.') != 'ABC'
+ close
+ put ='case2: failed'
+ else
+ close
+ put ='case2: ok'
+ endif
+ ]])
+
+ -- Case3:
+ source([[
+ new
+ set tags=test83-tags3
+ let v:errmsg = ''
+ tag abc50
+ if v:errmsg =~ 'E426:' || getline('.') != 'ABC'
+ close
+ put ='case3: failed'
+ else
+ close
+ put ='case3: ok'
+ endif
+ ]])
+
+ -- Assert buffer contents.
+ expect([[
+ Results of test83
+ case1: ok
+ case2: ok
+ case3: ok]])
+ end)
+ end
+end)
diff --git a/test/functional/legacy/091_context_variables_spec.lua b/test/functional/legacy/091_context_variables_spec.lua
index ffeb0c657e..2c46ef643c 100644
--- a/test/functional/legacy/091_context_variables_spec.lua
+++ b/test/functional/legacy/091_context_variables_spec.lua
@@ -13,6 +13,9 @@ describe('context variables', function()
-- Test for getbufvar().
-- Use strings to test for memory leaks.
source([[
+ let t:testvar='abcd'
+ $put =string(gettabvar(1, 'testvar'))
+ $put =string(gettabvar(1, 'testvar'))
let b:var_num = '1234'
let def_num = '5678'
$put =string(getbufvar(1, 'var_num'))
@@ -125,6 +128,8 @@ describe('context variables', function()
-- Assert buffer contents.
expect([[
start:
+ 'abcd'
+ 'abcd'
'1234'
'1234'
{'var_num': '1234'}
diff --git a/test/functional/legacy/094_visual_mode_operators_spec.lua b/test/functional/legacy/094_visual_mode_operators_spec.lua
index c4aebe4ecc..4dce39b8d2 100644
--- a/test/functional/legacy/094_visual_mode_operators_spec.lua
+++ b/test/functional/legacy/094_visual_mode_operators_spec.lua
@@ -24,6 +24,27 @@ local function source_user_functions()
]])
end
+local function put_abc()
+ source([[
+ $put ='a'
+ $put ='b'
+ $put ='c']])
+end
+
+local function put_aaabbbccc()
+ source([[
+ $put ='aaa'
+ $put ='bbb'
+ $put ='ccc']])
+end
+
+local function define_select_mode_maps()
+ source([[
+ snoremap <lt>End> <End>
+ snoremap <lt>Down> <Down>
+ snoremap <lt>Del> <Del>]])
+end
+
describe('Visual mode and operator', function()
before_each(function()
clear()
@@ -150,4 +171,228 @@ describe('Visual mode and operator', function()
ok
ok]])
end)
+
+ describe('characterwise visual mode:', function()
+ it('replace last line', function()
+ source([[
+ $put ='a'
+ let @" = 'x']])
+ feed('v$p')
+
+ expect([[
+
+ x]])
+ end)
+
+ it('delete middle line', function()
+ put_abc()
+ feed('kkv$d')
+
+ expect([[
+
+ b
+ c]])
+ end)
+
+ it('delete middle two line', function()
+ put_abc()
+ feed('kkvj$d')
+
+ expect([[
+
+ c]])
+ end)
+
+ it('delete last line', function()
+ put_abc()
+ feed('v$d')
+
+ expect([[
+
+ a
+ b
+ ]])
+ end)
+
+ it('delete last two line', function()
+ put_abc()
+ feed('kvj$d')
+
+ expect([[
+
+ a
+ ]])
+ end)
+ end)
+
+ describe('characterwise select mode:', function()
+ before_each(function()
+ define_select_mode_maps()
+ end)
+
+ it('delete middle line', function()
+ put_abc()
+ feed('kkgh<End><Del>')
+
+ expect([[
+
+ b
+ c]])
+ end)
+
+ it('delete middle two line', function()
+ put_abc()
+ feed('kkgh<Down><End><Del>')
+
+ expect([[
+
+ c]])
+ end)
+
+ it('delete last line', function()
+ put_abc()
+ feed('gh<End><Del>')
+
+ expect([[
+
+ a
+ b
+ ]])
+ end)
+
+ it('delete last two line', function()
+ put_abc()
+ feed('kgh<Down><End><Del>')
+
+ expect([[
+
+ a
+ ]])
+ end)
+ end)
+
+ describe('linewise select mode:', function()
+ before_each(function()
+ define_select_mode_maps()
+ end)
+
+ it('delete middle line', function()
+ put_abc()
+ feed(' kkgH<Del> ')
+
+ expect([[
+
+ b
+ c]])
+ end)
+
+ it('delete middle two line', function()
+ put_abc()
+ feed('kkgH<Down><Del>')
+
+ expect([[
+
+ c]])
+ end)
+
+ it('delete last line', function()
+ put_abc()
+ feed('gH<Del>')
+
+ expect([[
+
+ a
+ b]])
+ end)
+
+ it('delete last two line', function()
+ put_abc()
+ feed('kgH<Down><Del>')
+
+ expect([[
+
+ a]])
+ end)
+ end)
+
+ describe('v_p:', function()
+ it('replace last character with line register at middle line', function()
+ put_aaabbbccc()
+ execute('-2yank')
+ feed('k$vp')
+
+ expect([[
+
+ aaa
+ bb
+ aaa
+
+ ccc]])
+ end)
+
+ it('replace last character with line register at middle line selecting newline', function()
+ put_aaabbbccc()
+ execute('-2yank')
+ feed('k$v$p')
+
+ expect([[
+
+ aaa
+ bb
+ aaa
+ ccc]])
+ end)
+
+ it('replace last character with line register at last line', function()
+ put_aaabbbccc()
+ execute('-2yank')
+ feed('$vp')
+
+ expect([[
+
+ aaa
+ bbb
+ cc
+ aaa
+ ]])
+ end)
+
+ it('replace last character with line register at last line selecting newline', function()
+ put_aaabbbccc()
+ execute('-2yank')
+ feed('$v$p')
+
+ expect([[
+
+ aaa
+ bbb
+ cc
+ aaa
+ ]])
+ end)
+ end)
+
+ it('gv in exclusive select mode after operation', function()
+ source([[
+ $put ='zzz '
+ $put ='äà '
+ set selection=exclusive]])
+ feed('kv3lyjv3lpgvcxxx<Esc>')
+
+ expect([[
+
+ zzz
+ xxx ]])
+ end)
+
+ it('gv in exclusive select mode without operation', function()
+ source([[
+ $put ='zzz '
+ set selection=exclusive]])
+ feed('0v3l<Esc>gvcxxx<Esc>')
+
+ expect([[
+
+ xxx ]])
+ end)
end)
diff --git a/test/functional/legacy/autocmd_option_spec.lua b/test/functional/legacy/autocmd_option_spec.lua
index 855e9c6271..6349371808 100644
--- a/test/functional/legacy/autocmd_option_spec.lua
+++ b/test/functional/legacy/autocmd_option_spec.lua
@@ -2,6 +2,8 @@ local helpers = require('test.functional.helpers')
local nvim = helpers.meths
local clear, eq, neq = helpers.clear, helpers.eq, helpers.neq
local curbuf, buf = helpers.curbuf, helpers.bufmeths
+local curwin = helpers.curwin
+local redir_exec = helpers.redir_exec
local source, execute = helpers.source, helpers.execute
local function declare_hook_function()
@@ -86,7 +88,7 @@ end
local function make_buffer()
local old_buf = curbuf()
- execute('new')
+ execute('botright new')
local new_buf = curbuf()
execute('wincmd p') -- move previous window
@@ -96,6 +98,19 @@ local function make_buffer()
return new_buf
end
+local function get_new_window_number()
+ local old_win = curwin()
+ execute('botright new')
+ local new_win = curwin()
+ local new_winnr = redir_exec('echo winnr()')
+ execute('wincmd p') -- move previous window
+
+ neq(old_win, new_win)
+ eq(old_win, curwin())
+
+ return new_winnr:gsub('\n', '')
+end
+
describe('au OptionSet', function()
describe('with any opton (*)', function()
@@ -248,6 +263,32 @@ describe('au OptionSet', function()
end)
end)
+ describe('being set by setwinvar()', function()
+ it('should not trigger because option name does not match with backup', function()
+ set_hook('backup')
+
+ execute('call setwinvar(1, "&l:bk", 1)')
+ expected_empty()
+ end)
+
+ it('should trigger, use correct option name backup', function()
+ set_hook('backup')
+
+ execute('call setwinvar(1, "&backup", 1)')
+ expected_combination({'backup', 0, 1, 'local'})
+ end)
+
+ it('should not trigger if the current window is different from the targetted window', function()
+ set_hook('cursorcolumn')
+
+ local new_winnr = get_new_window_number()
+
+ execute('call setwinvar(' .. new_winnr .. ', "&cursorcolumn", 1)')
+ -- expected_combination({'cursorcolumn', 0, 1, 'local', {winnr = new_winnr}})
+ expected_empty()
+ end)
+ end)
+
describe('being set by neovim api', function()
it('should trigger if a boolean option be set globally', function()
set_hook('autochdir')
diff --git a/test/functional/legacy/charsearch_spec.lua b/test/functional/legacy/charsearch_spec.lua
new file mode 100644
index 0000000000..4a83801cfc
--- /dev/null
+++ b/test/functional/legacy/charsearch_spec.lua
@@ -0,0 +1,42 @@
+-- Test for character searches
+
+local helpers = require('test.functional.helpers')
+local feed, insert = helpers.feed, helpers.insert
+local clear, execute, expect = helpers.clear, helpers.execute, helpers.expect
+
+describe('charsearch', function()
+ setup(clear)
+
+ it('is working', function()
+ insert([[
+ Xabcdefghijkemnopqretuvwxyz
+ Yabcdefghijkemnopqretuvwxyz
+ Zabcdefghijkemnokqretkvwxyz]])
+
+ -- Check that "fe" and ";" work.
+ execute('/^X')
+ feed('ylfep;;p,,p')
+ -- Check that save/restore works.
+ execute('/^Y')
+ feed('ylfep')
+ execute('let csave = getcharsearch()')
+ feed('fip')
+ execute('call setcharsearch(csave)')
+ feed(';p;p')
+ -- Check that setcharsearch() changes the settings.
+ execute('/^Z')
+ feed('ylfep')
+ execute("call setcharsearch({'char': 'k'})")
+ feed(';p')
+ execute("call setcharsearch({'forward': 0})")
+ feed('$;p')
+ execute("call setcharsearch({'until': 1})")
+ feed(';;p')
+
+ -- Assert buffer contents.
+ expect([[
+ XabcdeXfghijkeXmnopqreXtuvwxyz
+ YabcdeYfghiYjkeYmnopqreYtuvwxyz
+ ZabcdeZfghijkZZemnokqretkZvwxyz]])
+ end)
+end)
diff --git a/test/functional/legacy/command_count_spec.lua b/test/functional/legacy/command_count_spec.lua
new file mode 100644
index 0000000000..d9b4f09263
--- /dev/null
+++ b/test/functional/legacy/command_count_spec.lua
@@ -0,0 +1,243 @@
+-- Test for user command counts
+
+local helpers = require('test.functional.helpers')
+local clear, source, expect = helpers.clear, helpers.source, helpers.expect
+local execute, spawn = helpers.execute, helpers.spawn
+local nvim_prog = helpers.nvim_prog
+
+describe('command_count', function()
+ setup(clear)
+ teardown(function()
+ os.remove('test.out')
+ end)
+
+ it('is working', function()
+ -- It is relevant for the test to load a file initially. If this is
+ -- emulated with :arg the buffer count is wrong as nvim creates an empty
+ -- buffer if it was started without a filename.
+ local nvim2 = spawn({nvim_prog, '-u', 'NONE', '-i', 'NONE', '--embed',
+ 'test_command_count.in'})
+ helpers.set_session(nvim2)
+
+ source([[
+ lang C
+ let g:lines = []
+ com -range=% RangeLines
+ \ :call add(g:lines, 'RangeLines '.<line1>.' '.<line2>)
+ com -range -addr=arguments RangeArguments
+ \ :call add(g:lines, 'RangeArguments '.<line1>.' '.<line2>)
+ com -range=% -addr=arguments RangeArgumentsAll
+ \ :call add(g:lines, 'RangeArgumentsAll '.<line1>.' '.<line2>)
+ com -range -addr=loaded_buffers RangeLoadedBuffers
+ \ :call add(g:lines, 'RangeLoadedBuffers '.<line1>.' '.<line2>)
+ com -range=% -addr=loaded_buffers RangeLoadedBuffersAll
+ \ :call add(g:lines, 'RangeLoadedBuffersAll '.<line1>.' '.<line2>)
+ com -range -addr=buffers RangeBuffers
+ \ :call add(g:lines, 'RangeBuffers '.<line1>.' '.<line2>)
+ com -range=% -addr=buffers RangeBuffersAll
+ \ :call add(g:lines, 'RangeBuffersAll '.<line1>.' '.<line2>)
+ com -range -addr=windows RangeWindows
+ \ :call add(g:lines, 'RangeWindows '.<line1>.' '.<line2>)
+ com -range=% -addr=windows RangeWindowsAll
+ \ :call add(g:lines, 'RangeWindowsAll '.<line1>.' '.<line2>)
+ com -range -addr=tabs RangeTabs
+ \ :call add(g:lines, 'RangeTabs '.<line1>.' '.<line2>)
+ com -range=% -addr=tabs RangeTabsAll
+ \ :call add(g:lines, 'RangeTabsAll '.<line1>.' '.<line2>)
+ set hidden
+ arga a b c d
+ argdo echo "loading buffers"
+ argu 3
+ .-,$-RangeArguments
+ %RangeArguments
+ RangeArgumentsAll
+ N
+ .RangeArguments
+ split
+ split
+ split
+ split
+ 3wincmd w
+ .,$RangeWindows
+ %RangeWindows
+ RangeWindowsAll
+ only
+ blast
+ bd
+ .,$RangeLoadedBuffers
+ %RangeLoadedBuffers
+ RangeLoadedBuffersAll
+ .,$RangeBuffers
+ %RangeBuffers
+ RangeBuffersAll
+ tabe
+ tabe
+ tabe
+ tabe
+ normal 2gt
+ .,$RangeTabs
+ %RangeTabs
+ RangeTabsAll
+ 1tabonly
+ s/\n/\r\r\r\r\r/
+ 2ma<
+ $-ma>
+ '<,'>RangeLines
+ com -range=% -buffer LocalRangeLines
+ \ :call add(g:lines, 'LocalRangeLines '.<line1>.' '.<line2>)
+ '<,'>LocalRangeLines
+ b1
+ call add(g:lines, '')
+ %argd
+ arga a b c d
+ ]])
+ -- This can not be in the source() call as it will produce errors.
+ execute([[let v:errmsg = '']])
+ execute('5argu')
+ execute([[call add(g:lines, '5argu ' . v:errmsg)]])
+ execute('$argu')
+ execute([[call add(g:lines, '4argu ' . expand('%:t'))]])
+ execute([[let v:errmsg = '']])
+ execute('1argu')
+ execute([[call add(g:lines, '1argu ' . expand('%:t'))]])
+ execute([[let v:errmsg = '']])
+ execute('100b')
+ execute([[call add(g:lines, '100b ' . v:errmsg)]])
+ execute('split')
+ execute('split')
+ execute('split')
+ execute('split')
+ execute([[let v:errmsg = '']])
+ execute('0close')
+ execute([[call add(g:lines, '0close ' . v:errmsg)]])
+ execute('$wincmd w')
+ execute('$close')
+ execute([[call add(g:lines, '$close ' . winnr())]])
+ execute([[let v:errmsg = '']])
+ execute('$+close')
+ execute([[call add(g:lines, '$+close ' . v:errmsg)]])
+ execute('$tabe')
+ execute([[call add(g:lines, '$tabe ' . tabpagenr())]])
+ execute([[let v:errmsg = '']])
+ execute('$+tabe')
+ execute([[call add(g:lines, '$+tabe ' . v:errmsg)]])
+ source([[
+ only!
+ e x
+ 0tabm
+ normal 1gt
+ call add(g:lines, '0tabm ' . expand('%:t'))
+ tabonly!
+ only!
+ e! test.out
+ call append(0, g:lines)
+ unlet g:lines
+ w
+ bd
+ b1
+ let g:lines = []
+ func BufStatus()
+ call add(g:lines,
+ \ 'aaa: ' . buflisted(g:buf_aaa) .
+ \ ' bbb: ' . buflisted(g:buf_bbb) .
+ \ ' ccc: ' . buflisted(g:buf_ccc))
+ endfunc
+ se nohidden
+ e aaa
+ let buf_aaa = bufnr('%')
+ e bbb
+ let buf_bbb = bufnr('%')
+ e ccc
+ let buf_ccc = bufnr('%')
+ b1
+ call BufStatus()
+ exe buf_bbb . "," . buf_ccc . "bdelete"
+ call BufStatus()
+ exe buf_aaa . "bdelete"
+ call BufStatus()
+ e! test.out
+ call append('$', g:lines)
+ unlet g:lines
+ delfunc BufStatus
+ w
+ bd
+ b1
+ se hidden
+ only!
+ let g:lines = []
+ %argd
+ arga a b c d e f
+ 3argu
+ let args = ''
+ .,$-argdo let args .= ' '.expand('%')
+ call add(g:lines, 'argdo:' . args)
+ split
+ split
+ split
+ split
+ 2wincmd w
+ let windows = ''
+ .,$-windo let windows .= ' '.winnr()
+ call add(g:lines, 'windo:'. windows)
+ b2
+ let buffers = ''
+ .,$-bufdo let buffers .= ' '.bufnr('%')
+ call add(g:lines, 'bufdo:' . buffers)
+ 3bd
+ let buffers = ''
+ 3,7bufdo let buffers .= ' '.bufnr('%')
+ call add(g:lines, 'bufdo:' . buffers)
+ tabe
+ tabe
+ tabe
+ tabe
+ normal! 2gt
+ let tabpages = ''
+ .,$-tabdo let tabpages .= ' '.tabpagenr()
+ call add(g:lines, 'tabdo:' . tabpages)
+ e! test.out
+ call append('$', g:lines)
+ ]])
+
+ -- Assert buffer contents.
+ expect([[
+ RangeArguments 2 4
+ RangeArguments 1 5
+ RangeArgumentsAll 1 5
+ RangeArguments 2 2
+ RangeWindows 3 5
+ RangeWindows 1 5
+ RangeWindowsAll 1 5
+ RangeLoadedBuffers 2 4
+ RangeLoadedBuffers 1 4
+ RangeLoadedBuffersAll 1 4
+ RangeBuffers 2 5
+ RangeBuffers 1 5
+ RangeBuffersAll 1 5
+ RangeTabs 2 5
+ RangeTabs 1 5
+ RangeTabsAll 1 5
+ RangeLines 2 5
+ LocalRangeLines 2 5
+
+ 5argu E16: Invalid range
+ 4argu d
+ 1argu a
+ 100b E16: Invalid range
+ 0close
+ $close 3
+ $+close E16: Invalid range
+ $tabe 2
+ $+tabe E16: Invalid range
+ 0tabm x
+
+ aaa: 1 bbb: 1 ccc: 1
+ aaa: 1 bbb: 0 ccc: 0
+ aaa: 0 bbb: 0 ccc: 0
+ argdo: c d e
+ windo: 2 3 4
+ bufdo: 2 3 4 5 6 7 8 9 10 15
+ bufdo: 4 5 6 7
+ tabdo: 2 3 4]])
+ end)
+end)
diff --git a/test/functional/legacy/comparators_spec.lua b/test/functional/legacy/comparators_spec.lua
new file mode 100644
index 0000000000..e3fa3eea23
--- /dev/null
+++ b/test/functional/legacy/comparators_spec.lua
@@ -0,0 +1,14 @@
+-- " Test for expression comparators.
+
+local helpers = require('test.functional.helpers')
+local clear, eq = helpers.clear, helpers.eq
+local eval, execute = helpers.eval, helpers.execute
+
+describe('comparators', function()
+ before_each(clear)
+
+ it('is working', function()
+ execute('set isident+=#')
+ eq(1, eval('1 is#1'))
+ end)
+end)
diff --git a/test/functional/legacy/erasebackword_spec.lua b/test/functional/legacy/erasebackword_spec.lua
new file mode 100644
index 0000000000..cb3967b763
--- /dev/null
+++ b/test/functional/legacy/erasebackword_spec.lua
@@ -0,0 +1,24 @@
+-- Test for CTRL-W in Insert mode
+
+local helpers = require('test.functional.helpers')
+local clear, feed, expect = helpers.clear, helpers.feed, helpers.expect
+
+describe('CTRL-W in Insert mode', function()
+ setup(clear)
+
+ it('works for multi-byte characters', function()
+
+ for i = 1, 6 do
+ feed('o wwwこんにちわ世界ワールドvim ' .. string.rep('<C-w>', i) .. '<esc>')
+ end
+
+ expect([[
+
+ wwwこんにちわ世界ワールド
+ wwwこんにちわ世界
+ wwwこんにちわ
+ www
+
+ ]])
+ end)
+end)
diff --git a/test/functional/legacy/eval_spec.lua b/test/functional/legacy/eval_spec.lua
new file mode 100644
index 0000000000..1c81b47ed6
--- /dev/null
+++ b/test/functional/legacy/eval_spec.lua
@@ -0,0 +1,696 @@
+-- Test for various eval features.
+
+local helpers = require('test.functional.helpers')
+local feed, insert, source = helpers.feed, helpers.insert, helpers.source
+local clear, execute, expect = helpers.clear, helpers.execute, helpers.expect
+local eq, eval, write_file = helpers.eq, helpers.eval, helpers.write_file
+
+local function has_clipboard()
+ clear()
+ return 1 == eval("has('clipboard')")
+end
+
+describe('eval', function()
+ setup(function()
+ write_file('test_eval_setup.vim', [[
+ set noswapfile
+ lang C
+
+ fun AppendRegContents(reg)
+ call AppendRegParts(a:reg, getregtype(a:reg), getreg(a:reg), string(getreg(a:reg, 0, 1)), getreg(a:reg, 1), string(getreg(a:reg, 1, 1)))
+ endfun
+
+ fun AppendRegParts(reg, type, cont, strcont, cont1, strcont1)
+ call append('$', printf('%s: type %s; value: %s (%s), expr: %s (%s)', a:reg, a:type, a:cont, a:strcont, a:cont1, a:strcont1))
+ endfun
+
+ command -nargs=? AR :call AppendRegContents(<q-args>)
+
+ fun SetReg(...)
+ call call('setreg', a:000)
+ call append('$', printf('{{{2 setreg(%s)', string(a:000)[1:-2]))
+ call AppendRegContents(a:1)
+ if a:1 isnot# '='
+ execute "silent normal! Go==\n==\e\"".a:1."P"
+ endif
+ endfun
+ ]])
+ end)
+ before_each(clear)
+ teardown(function()
+ os.remove('test_eval_setup.vim')
+ end)
+
+ it(':let', function()
+ execute('so test_eval_setup.vim')
+ execute([[let @" = 'abc']])
+ execute('AR "')
+ execute([[let @" = "abc\n"]])
+ source('AR "')
+ execute([[let @" = "abc\<C-m>"]])
+ execute('AR "')
+ execute([[let @= = '"abc"']])
+ execute('AR =')
+ 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 (['abc']), expr: "abc" (['"abc"'])]])
+ end)
+
+ it('basic setreg() tests', function()
+ execute('so test_eval_setup.vim')
+ insert('{{{1 Basic setreg tests')
+ execute([[call SetReg('a', 'abcA', 'c')]])
+ execute([[call SetReg('b', 'abcB', 'v')]])
+ execute([[call SetReg('c', 'abcC', 'l')]])
+ execute([[call SetReg('d', 'abcD', 'V')]])
+ execute([[call SetReg('e', 'abcE', 'b')]])
+ execute([[call SetReg('f', 'abcF', "\<C-v>")]])
+ execute([[call SetReg('g', 'abcG', 'b10')]])
+ execute([[call SetReg('h', 'abcH', "\<C-v>10")]])
+ execute([[call SetReg('I', 'abcI')]])
+
+ feed('Go{{{1 Appending single lines with setreg()<esc>')
+ execute([[call SetReg('A', 'abcAc', 'c')]])
+ execute([[call SetReg('A', 'abcAl', 'l')]])
+ execute([[call SetReg('A', 'abcAc2','c')]])
+ execute([[call SetReg('b', 'abcBc', 'ca')]])
+ execute([[call SetReg('b', 'abcBb', 'ba')]])
+ execute([[call SetReg('b', 'abcBc2','ca')]])
+ execute([[call SetReg('b', 'abcBb2','b50a')]])
+ execute([[call SetReg('C', 'abcCl', 'l')]])
+ execute([[call SetReg('C', 'abcCc', 'c')]])
+ execute([[call SetReg('D', 'abcDb', 'b')]])
+ execute([[call SetReg('E', 'abcEb', 'b')]])
+ execute([[call SetReg('E', 'abcEl', 'l')]])
+ execute([[call SetReg('F', 'abcFc', 'c')]])
+ expect([[
+ {{{1 Basic setreg tests
+ {{{2 setreg('a', 'abcA', 'c')
+ a: type v; value: abcA (['abcA']), expr: abcA (['abcA'])
+ ==
+ =abcA=
+ {{{2 setreg('b', 'abcB', 'v')
+ b: type v; value: abcB (['abcB']), expr: abcB (['abcB'])
+ ==
+ =abcB=
+ {{{2 setreg('c', 'abcC', 'l')
+ c: type V; value: abcC]].."\x00 (['abcC']), expr: abcC\x00"..[[ (['abcC'])
+ ==
+ abcC
+ ==
+ {{{2 setreg('d', 'abcD', 'V')
+ d: type V; value: abcD]].."\x00 (['abcD']), expr: abcD\x00"..[[ (['abcD'])
+ ==
+ abcD
+ ==
+ {{{2 setreg('e', 'abcE', 'b')
+ e: type ]]..'\x16'..[[4; value: abcE (['abcE']), expr: abcE (['abcE'])
+ ==
+ =abcE=
+ {{{2 setreg('f', 'abcF', ']]..'\x16'..[[')
+ f: type ]]..'\x16'..[[4; value: abcF (['abcF']), expr: abcF (['abcF'])
+ ==
+ =abcF=
+ {{{2 setreg('g', 'abcG', 'b10')
+ g: type ]]..'\x16'..[[10; value: abcG (['abcG']), expr: abcG (['abcG'])
+ ==
+ =abcG =
+ {{{2 setreg('h', 'abcH', ']]..'\x16'..[[10')
+ h: type ]]..'\x16'..[[10; value: abcH (['abcH']), expr: abcH (['abcH'])
+ ==
+ =abcH =
+ {{{2 setreg('I', 'abcI')
+ I: type v; value: abcI (['abcI']), expr: abcI (['abcI'])
+ ==
+ =abcI=
+ {{{1 Appending single lines with setreg()
+ {{{2 setreg('A', 'abcAc', 'c')
+ A: type v; value: abcAabcAc (['abcAabcAc']), expr: abcAabcAc (['abcAabcAc'])
+ ==
+ =abcAabcAc=
+ {{{2 setreg('A', 'abcAl', 'l')
+ A: type V; value: abcAabcAcabcAl]].."\x00 (['abcAabcAcabcAl']), expr: abcAabcAcabcAl\x00"..[[ (['abcAabcAcabcAl'])
+ ==
+ abcAabcAcabcAl
+ ==
+ {{{2 setreg('A', 'abcAc2', 'c')
+ A: type v; value: abcAabcAcabcAl]].."\x00abcAc2 (['abcAabcAcabcAl', 'abcAc2']), expr: abcAabcAcabcAl\x00"..[[abcAc2 (['abcAabcAcabcAl', 'abcAc2'])
+ ==
+ =abcAabcAcabcAl
+ abcAc2=
+ {{{2 setreg('b', 'abcBc', 'ca')
+ b: type v; value: abcBabcBc (['abcBabcBc']), expr: abcBabcBc (['abcBabcBc'])
+ ==
+ =abcBabcBc=
+ {{{2 setreg('b', 'abcBb', 'ba')
+ b: type ]]..'\x16'..[[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'])
+ ==
+ =abcBabcBcabcBb
+ abcBc2=
+ {{{2 setreg('b', 'abcBb2', 'b50a')
+ b: type ]].."\x1650; value: abcBabcBcabcBb\x00abcBc2abcBb2 (['abcBabcBcabcBb', 'abcBc2abcBb2']), expr: abcBabcBcabcBb\x00"..[[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'])
+ ==
+ 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'])
+ ==
+ =abcC
+ abcCl
+ abcCc=
+ {{{2 setreg('D', 'abcDb', 'b')
+ D: type ]].."\x165; value: abcD\x00abcDb (['abcD', 'abcDb']), expr: abcD\x00"..[[abcDb (['abcD', 'abcDb'])
+ ==
+ =abcD =
+ abcDb
+ {{{2 setreg('E', 'abcEb', 'b')
+ E: type ]].."\x165; value: abcE\x00abcEb (['abcE', 'abcEb']), expr: abcE\x00"..[[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'])
+ ==
+ abcE
+ abcEb
+ abcEl
+ ==
+ {{{2 setreg('F', 'abcFc', 'c')
+ F: type v; value: abcF]].."\x00abcFc (['abcF', 'abcFc']), expr: abcF\x00"..[[abcFc (['abcF', 'abcFc'])
+ ==
+ =abcF
+ abcFc=]])
+ end)
+
+ it('appending NL with setreg()', function()
+ execute('so test_eval_setup.vim')
+
+ execute([[call setreg('a', 'abcA2', 'c')]])
+ execute([[call setreg('b', 'abcB2', 'v')]])
+ execute([[call setreg('c', 'abcC2', 'l')]])
+ execute([[call setreg('d', 'abcD2', 'V')]])
+ execute([[call setreg('e', 'abcE2', 'b')]])
+ execute([[call setreg('f', 'abcF2', "\<C-v>")]])
+ -- These registers where set like this in the old test_eval.in but never
+ -- copied to the output buffer with SetReg(). They do not appear in
+ -- test_eval.ok. Therefore they are commented out.
+ --execute([[call setreg('g', 'abcG2', 'b10')]])
+ --execute([[call setreg('h', 'abcH2', "\<C-v>10")]])
+ --execute([[call setreg('I', 'abcI2')]])
+
+ execute([[call SetReg('A', "\n")]])
+ execute([[call SetReg('B', "\n", 'c')]])
+ execute([[call SetReg('C', "\n")]])
+ execute([[call SetReg('D', "\n", 'l')]])
+ execute([[call SetReg('E', "\n")]])
+ execute([[call SetReg('F', "\n", 'b')]])
+ expect([[
+
+ {{{2 setreg('A', ']]..'\x00'..[[')
+ A: type V; value: abcA2]].."\x00 (['abcA2']), expr: abcA2\x00"..[[ (['abcA2'])
+ ==
+ abcA2
+ ==
+ {{{2 setreg('B', ']]..'\x00'..[[', 'c')
+ B: type v; value: abcB2]].."\x00 (['abcB2', '']), expr: abcB2\x00"..[[ (['abcB2', ''])
+ ==
+ =abcB2
+ =
+ {{{2 setreg('C', ']]..'\x00'..[[')
+ C: type V; value: abcC2]].."\x00\x00 (['abcC2', '']), expr: abcC2\x00\x00"..[[ (['abcC2', ''])
+ ==
+ abcC2
+
+ ==
+ {{{2 setreg('D', ']]..'\x00'..[[', 'l')
+ D: type V; value: abcD2]].."\x00\x00 (['abcD2', '']), expr: abcD2\x00\x00"..[[ (['abcD2', ''])
+ ==
+ abcD2
+
+ ==
+ {{{2 setreg('E', ']]..'\x00'..[[')
+ E: type V; value: abcE2]].."\x00\x00 (['abcE2', '']), expr: abcE2\x00\x00"..[[ (['abcE2', ''])
+ ==
+ abcE2
+
+ ==
+ {{{2 setreg('F', ']]..'\x00'..[[', 'b')
+ F: type ]].."\x160; value: abcF2\x00 (['abcF2', '']), expr: abcF2\x00"..[[ (['abcF2', ''])
+ ==
+ =abcF2=
+ ]])
+ end)
+
+ it('setting and appending list with setreg()', function()
+ execute('so test_eval_setup.vim')
+
+ execute([[$put ='{{{1 Setting lists with setreg()']])
+ execute([=[call SetReg('a', ['abcA3'], 'c')]=])
+ execute([=[call SetReg('b', ['abcB3'], 'l')]=])
+ execute([=[call SetReg('c', ['abcC3'], 'b')]=])
+ execute([=[call SetReg('d', ['abcD3'])]=])
+ execute([=[call SetReg('e', [1, 2, 'abc', 3])]=])
+ execute([=[call SetReg('f', [1, 2, 3])]=])
+
+ execute([[$put ='{{{1 Appending lists with setreg()']])
+ execute([=[call SetReg('A', ['abcA3c'], 'c')]=])
+ execute([=[call SetReg('b', ['abcB3l'], 'la')]=])
+ execute([=[call SetReg('C', ['abcC3b'], 'lb')]=])
+ execute([=[call SetReg('D', ['abcD32'])]=])
+ execute([=[call SetReg('A', ['abcA32'])]=])
+ execute([=[call SetReg('B', ['abcB3c'], 'c')]=])
+ execute([=[call SetReg('C', ['abcC3l'], 'l')]=])
+ execute([=[call SetReg('D', ['abcD3b'], 'b')]=])
+ expect([[
+
+ {{{1 Setting lists with setreg()
+ {{{2 setreg('a', ['abcA3'], 'c')
+ a: type v; value: abcA3 (['abcA3']), expr: abcA3 (['abcA3'])
+ ==
+ =abcA3=
+ {{{2 setreg('b', ['abcB3'], 'l')
+ b: type V; value: abcB3]].."\x00 (['abcB3']), expr: abcB3\x00"..[[ (['abcB3'])
+ ==
+ abcB3
+ ==
+ {{{2 setreg('c', ['abcC3'], 'b')
+ c: type ]]..'\x16'..[[5; value: abcC3 (['abcC3']), expr: abcC3 (['abcC3'])
+ ==
+ =abcC3=
+ {{{2 setreg('d', ['abcD3'])
+ d: type V; value: abcD3]].."\x00 (['abcD3']), expr: abcD3\x00"..[[ (['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'])
+ ==
+ 1
+ 2
+ abc
+ 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'])
+ ==
+ 1
+ 2
+ 3
+ ==
+ {{{1 Appending lists with setreg()
+ {{{2 setreg('A', ['abcA3c'], 'c')
+ A: type v; value: abcA3]].."\x00abcA3c (['abcA3', 'abcA3c']), expr: abcA3\x00"..[[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'])
+ ==
+ abcB3
+ abcB3l
+ ==
+ {{{2 setreg('C', ['abcC3b'], 'lb')
+ C: type ]].."\x166; value: abcC3\x00abcC3b (['abcC3', 'abcC3b']), expr: abcC3\x00"..[[abcC3b (['abcC3', 'abcC3b'])
+ ==
+ =abcC3 =
+ abcC3b
+ {{{2 setreg('D', ['abcD32'])
+ D: type V; value: abcD3]].."\x00abcD32\x00 (['abcD3', 'abcD32']), expr: abcD3\x00abcD32\x00"..[[ (['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'])
+ ==
+ 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'])
+ ==
+ =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'])
+ ==
+ 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'])
+ ==
+ =abcD3 =
+ abcD32
+ abcD3b]])
+
+ -- From now on we delete the buffer contents after each expect() to make
+ -- the next expect() easier to write. This is neccessary because null
+ -- bytes on a line by itself don't play well together with the dedent
+ -- function used in expect().
+ execute('%delete')
+ execute([[$put ='{{{1 Appending lists with NL with setreg()']])
+ execute([=[call SetReg('A', ["\n", 'abcA3l2'], 'l')]=])
+ 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"..
+ '==\n'..
+ 'abcA3\n'..
+ 'abcA3c\n'..
+ 'abcA32\n'..
+ '\x00\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"..
+ '==\n'..
+ '=abcB3\n'..
+ 'abcB3l\n'..
+ 'abcB3c\n'..
+ '\x00\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"..
+ '==\n'..
+ '=abcC3 =\n'..
+ ' abcC3b\n'..
+ ' abcC3l\n'..
+ ' \x00\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"..
+ '==\n'..
+ '=abcD3 =\n'..
+ ' abcD32\n'..
+ ' abcD3b\n'..
+ ' \x00\n'..
+ ' abcD3b50')
+ end)
+
+ -- The tests for setting lists with NLs are split into seperate it() blocks
+ -- to make the expect() calls easier to write. Otherwise the null byte can
+ -- make trouble on a line on its own.
+ it('setting lists with NLs with setreg(), part 1', function()
+ execute('so test_eval_setup.vim')
+ 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"..
+ '==\n'..
+ 'abcA4-0\n'..
+ '\x00\n'..
+ 'abcA4-2\x00\n'..
+ '\x00abcA4-3\n'..
+ 'abcA4-4\x00abcA4-4-2\n'..
+ '==')
+ end)
+
+ it('setting lists with NLs with setreg(), part 2', function()
+ execute('so test_eval_setup.vim')
+ 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"..
+ '==\n'..
+ '=abcB4c-0\n'..
+ '\x00\n'..
+ 'abcB4c-2\x00\n'..
+ '\x00abcB4c-3\n'..
+ 'abcB4c-4\x00abcB4c-4-2=')
+ end)
+
+ it('setting lists with NLs with setreg(), part 3', function()
+ execute('so test_eval_setup.vim')
+ 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"..
+ '==\n'..
+ 'abcC4l-0\n'..
+ '\x00\n'..
+ 'abcC4l-2\x00\n'..
+ '\x00abcC4l-3\n'..
+ 'abcC4l-4\x00abcC4l-4-2\n'..
+ '==')
+ end)
+ it('setting lists with NLs with setreg(), part 4', function()
+ execute('so test_eval_setup.vim')
+ 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"..
+ '==\n'..
+ '=abcD4b-0 =\n'..
+ ' \x00\n'..
+ ' abcD4b-2\x00\n'..
+ ' \x00abcD4b-3\n'..
+ ' abcD4b-4\x00abcD4b-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"..
+ '==\n'..
+ '=abcE4b10-0=\n'..
+ ' \x00\n'..
+ ' abcE4b10-2\x00\n'..
+ ' \x00abcE4b10-3\n'..
+ ' abcE4b10-4\x00abcE4b10-4-2')
+ end)
+
+ it('search and expressions', function()
+ execute('so test_eval_setup.vim')
+ execute([=[call SetReg('/', ['abc/'])]=])
+ execute([=[call SetReg('/', ["abc/\n"])]=])
+ execute([=[call SetReg('=', ['"abc/"'])]=])
+ execute([=[call SetReg('=', ["\"abc/\n\""])]=])
+ expect([[
+
+ {{{2 setreg('/', ['abc/'])
+ /: 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"..[['])
+ ==
+ =abc/]]..'\x00'..[[=
+ {{{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'..[["'])]])
+ end)
+
+ if has_clipboard() then
+ it('system clipboard', function()
+ insert([[
+ Some first line (this text was at the top of the old test_eval.in).
+
+ Note: system clipboard is saved, changed and restored.
+
+ clipboard contents
+ something else]])
+ execute('so test_eval_setup.vim')
+ -- Save and restore system clipboard.
+ execute("let _clipreg = ['*', getreg('*'), getregtype('*')]")
+ execute('let _clipopt = &cb')
+ execute("let &cb='unnamed'")
+ execute('5y')
+ execute('AR *')
+ execute('tabdo :windo :echo "hi"')
+ execute('6y')
+ execute('AR *')
+ execute('let &cb=_clipopt')
+ execute("call call('setreg', _clipreg)")
+ expect([[
+ Some first line (this text was at the top of the old test_eval.in).
+
+ Note: system clipboard is saved, changed and restored.
+
+ clipboard contents
+ something else
+ *: type V; value: clipboard contents]]..'\00'..[[ (['clipboard contents']), expr: clipboard contents]]..'\00'..[[ (['clipboard contents'])
+ *: type V; value: something else]]..'\00'..[[ (['something else']), expr: something else]]..'\00'..[[ (['something else'])]])
+ end)
+ else
+ pending('system clipboard not available', function() end)
+ end
+
+ it('errors', function()
+ source([[
+ fun ErrExe(str)
+ call append('$', 'Executing '.a:str)
+ try
+ execute a:str
+ catch
+ $put =v:exception
+ endtry
+ endfun]])
+ execute([[call ErrExe('call setreg()')]])
+ execute([[call ErrExe('call setreg(1)')]])
+ execute([[call ErrExe('call setreg(1, 2, 3, 4)')]])
+ execute([=[call ErrExe('call setreg([], 2)')]=])
+ execute([[call ErrExe('call setreg(1, {})')]])
+ execute([=[call ErrExe('call setreg(1, 2, [])')]=])
+ execute([=[call ErrExe('call setreg("/", ["1", "2"])')]=])
+ execute([=[call ErrExe('call setreg("=", ["1", "2"])')]=])
+ execute([=[call ErrExe('call setreg(1, ["", "", [], ""])')]=])
+ expect([[
+
+ Executing call setreg()
+ Vim(call):E119: Not enough arguments for function: setreg
+ Executing call setreg(1)
+ Vim(call):E119: Not enough arguments for function: setreg
+ Executing call setreg(1, 2, 3, 4)
+ Vim(call):E118: Too many arguments for function: setreg
+ Executing call setreg([], 2)
+ Vim(call):E730: using List as a String
+ Executing call setreg(1, {})
+ Vim(call):E731: using Dictionary as a String
+ Executing call setreg(1, 2, [])
+ Vim(call):E730: using List as a String
+ Executing call setreg("/", ["1", "2"])
+ Vim(call):E883: search pattern and expression register may not contain two or more lines
+ Executing call setreg("=", ["1", "2"])
+ Vim(call):E883: search pattern and expression register may not contain two or more lines
+ Executing call setreg(1, ["", "", [], ""])
+ Vim(call):E730: using List as a String]])
+ end)
+
+ it('function name not starting with a capital', function()
+ execute('try')
+ execute(' func! g:test()')
+ execute(' echo "test"')
+ execute(' endfunc')
+ execute('catch')
+ execute(' let tmp = v:exception')
+ execute('endtry')
+ eq('Vim(function):E128: Function name must start with a capital or "s:": g:test()', eval('tmp'))
+ end)
+
+ it('Function name followed by #', function()
+ execute('try')
+ execute(' func! test2() "#')
+ execute(' echo "test2"')
+ execute(' endfunc')
+ execute('catch')
+ execute(' let tmp = v:exception')
+ execute('endtry')
+ eq('Vim(function):E128: Function name must start with a capital or "s:": test2() "#', eval('tmp'))
+ end)
+
+ it('function name includes a colon', function()
+ execute('try')
+ execute(' func! b:test()')
+ execute(' echo "test"')
+ execute(' endfunc')
+ execute('catch')
+ execute(' let tmp = v:exception')
+ execute('endtry')
+ eq('Vim(function):E128: Function name must start with a capital or "s:": b:test()', eval('tmp'))
+ end)
+
+ it('function name starting with/without "g:", buffer-local funcref', function()
+ execute('function! g:Foo(n)')
+ execute(" $put ='called Foo(' . a:n . ')'")
+ execute('endfunction')
+ execute("let b:my_func = function('Foo')")
+ execute('call b:my_func(1)')
+ execute('echo g:Foo(2)')
+ execute('echo Foo(3)')
+ expect([[
+
+ called Foo(1)
+ called Foo(2)
+ called Foo(3)]])
+ end)
+
+ it('script-local function used in Funcref must exist', function()
+ source([[
+ " Vim script used in test_eval.in. Needed for script-local function.
+
+ func! s:Testje()
+ return "foo"
+ endfunc
+
+ let Bar = function('s:Testje')
+
+ $put ='s:Testje exists: ' . exists('s:Testje')
+ $put ='func s:Testje exists: ' . exists('*s:Testje')
+ $put ='Bar exists: ' . exists('Bar')
+ $put ='func Bar exists: ' . exists('*Bar')
+ ]])
+ expect([[
+
+ s:Testje exists: 0
+ func s:Testje exists: 1
+ Bar exists: 1
+ func Bar exists: 1]])
+ end)
+
+ it("using $ instead of '$' must give an error", function()
+ execute('try')
+ execute(" call append($, 'foobar')")
+ execute('catch')
+ execute(' let tmp = v:exception')
+ execute('endtry')
+ eq('Vim(call):E116: Invalid arguments for function append', eval('tmp'))
+ end)
+
+ it('getcurpos/setpos', function()
+ insert([[
+ 012345678
+ 012345678
+
+ start:]])
+ execute('/^012345678')
+ feed('6l')
+ execute('let sp = getcurpos()')
+ feed('0')
+ execute("call setpos('.', sp)")
+ feed('jyl')
+ execute('$put')
+ expect([[
+ 012345678
+ 012345678
+
+ start:
+ 6]])
+ end)
+end)
diff --git a/test/functional/legacy/glob2regpat_spec.lua b/test/functional/legacy/glob2regpat_spec.lua
new file mode 100644
index 0000000000..0492143616
--- /dev/null
+++ b/test/functional/legacy/glob2regpat_spec.lua
@@ -0,0 +1,22 @@
+-- Tests for signs
+
+local helpers = require('test.functional.helpers')
+local clear, execute = helpers.clear, helpers.execute
+local eq, neq, eval = helpers.eq, helpers.neq, helpers.eval
+
+describe('glob2regpat()', function()
+ before_each(clear)
+
+ it('handles invalid input', function()
+ execute('call glob2regpat(1.33)')
+ helpers.feed('<cr>')
+ neq(nil, string.find(eval('v:errmsg'), '^E806:'))
+ end)
+ it('returns ^$ for empty input', function()
+ eq('^$', eval("glob2regpat('')"))
+ end)
+ it('handles valid input', function()
+ eq('^foo\\.', eval("glob2regpat('foo.*')"))
+ eq('\\.vim$', eval("glob2regpat('*.vim')"))
+ end)
+end)
diff --git a/test/functional/legacy/increment_spec.lua b/test/functional/legacy/increment_spec.lua
new file mode 100644
index 0000000000..6139ec0b67
--- /dev/null
+++ b/test/functional/legacy/increment_spec.lua
@@ -0,0 +1,723 @@
+-- Tests for using Ctrl-A/Ctrl-X on visual selections
+
+local helpers = require('test.functional.helpers')
+local source, execute = helpers.source, helpers.execute
+local call, clear = helpers.call, helpers.clear
+local eq, nvim = helpers.eq, helpers.meths
+
+describe('Ctrl-A/Ctrl-X on visual selections', function()
+
+ before_each(function()
+ clear()
+ source([=[
+ " 1) Ctrl-A on visually selected number
+ " Text:
+ " foobar-10
+ " Expected:
+ " 1) Ctrl-A on start of line:
+ " foobar-9
+ " 2) Ctrl-A on visually selected "-10":
+ " foobar-9
+ " 3) Ctrl-A on visually selected "10":
+ " foobar-11
+ " 4) Ctrl-X on visually selected "-10"
+ " foobar-11
+ " 5) Ctrl-X on visually selected "10"
+ " foobar-9
+ func Test_visual_increment_01()
+ call setline(1, repeat(["foobaar-10"], 5))
+
+ call cursor(1, 1)
+ exec "norm! \<C-A>"
+ call assert_equal("foobaar-9", getline('.'))
+ call assert_equal([0, 1, 9, 0], getpos('.'))
+
+ call cursor(2, 1)
+ exec "norm! f-v$\<C-A>"
+ call assert_equal("foobaar-9", getline('.'))
+ call assert_equal([0, 2, 8, 0], getpos('.'))
+
+ call cursor(3, 1)
+ exec "norm! f1v$\<C-A>"
+ call assert_equal("foobaar-11", getline('.'))
+ call assert_equal([0, 3, 9, 0], getpos('.'))
+
+ call cursor(4, 1)
+ exec "norm! f-v$\<C-X>"
+ call assert_equal("foobaar-11", getline('.'))
+ call assert_equal([0, 4, 8, 0], getpos('.'))
+
+ call cursor(5, 1)
+ exec "norm! f1v$\<C-X>"
+ call assert_equal("foobaar-9", getline('.'))
+ call assert_equal([0, 5, 9, 0], getpos('.'))
+ endfunc
+
+ " 2) Ctrl-A on visually selected lines
+ " Text:
+ " 10
+ " 20
+ " 30
+ " 40
+ "
+ " Expected:
+ " 1) Ctrl-A on visually selected lines:
+ " 11
+ " 21
+ " 31
+ " 41
+ "
+ " 2) Ctrl-X on visually selected lines:
+ " 9
+ " 19
+ " 29
+ " 39
+ func Test_visual_increment_02()
+ call setline(1, ["10", "20", "30", "40"])
+ exec "norm! GV3k$\<C-A>"
+ call assert_equal(["11", "21", "31", "41"], getline(1, '$'))
+ call assert_equal([0, 1, 1, 0], getpos('.'))
+
+ call setline(1, ["10", "20", "30", "40"])
+ exec "norm! GV3k$\<C-X>"
+ call assert_equal(["9", "19", "29", "39"], getline(1, '$'))
+ call assert_equal([0, 1, 1, 0], getpos('.'))
+ endfunc
+
+ " 3) g Ctrl-A on visually selected lines, with non-numbers in between
+ " Text:
+ " 10
+ "
+ " 20
+ "
+ " 30
+ "
+ " 40
+ "
+ " Expected:
+ " 1) 2 g Ctrl-A on visually selected lines:
+ " 12
+ "
+ " 24
+ "
+ " 36
+ "
+ " 48
+ " 2) 2 g Ctrl-X on visually selected lines
+ " 8
+ "
+ " 16
+ "
+ " 24
+ "
+ " 32
+ func Test_visual_increment_03()
+ call setline(1, ["10", "", "20", "", "30", "", "40"])
+ exec "norm! GV6k2g\<C-A>"
+ call assert_equal(["12", "", "24", "", "36", "", "48"], getline(1, '$'))
+ call assert_equal([0, 1, 1, 0], getpos('.'))
+
+ call setline(1, ["10", "", "20", "", "30", "", "40"])
+ exec "norm! GV6k2g\<C-X>"
+ call assert_equal(["8", "", "16", "", "24", "", "32"], getline(1, '$'))
+ call assert_equal([0, 1, 1, 0], getpos('.'))
+ endfunc
+
+ " 4) Ctrl-A on non-number
+ " Text:
+ " foobar-10
+ " Expected:
+ " 1) visually select foobar:
+ " foobar-10
+ func Test_visual_increment_04()
+ call setline(1, ["foobar-10"])
+ exec "norm! vf-\<C-A>"
+ call assert_equal(["foobar-10"], getline(1, '$'))
+ " NOTE: I think this is correct behavior...
+ call assert_equal([0, 1, 1, 0], getpos('.'))
+ endfunc
+
+ " 5) g<Ctrl-A> on letter
+ " Test:
+ " a
+ " a
+ " a
+ " a
+ " Expected:
+ " 1) g Ctrl-A on visually selected lines
+ " b
+ " c
+ " d
+ " e
+ func Test_visual_increment_05()
+ set nrformats+=alpha
+ call setline(1, repeat(["a"], 4))
+ exec "norm! GV3kg\<C-A>"
+ call assert_equal(["b", "c", "d", "e"], getline(1, '$'))
+ call assert_equal([0, 1, 1, 0], getpos('.'))
+ endfunc
+
+ " 6) g<Ctrl-A> on letter
+ " Test:
+ " z
+ " z
+ " z
+ " z
+ " Expected:
+ " 1) g Ctrl-X on visually selected lines
+ " y
+ " x
+ " w
+ " v
+ func Test_visual_increment_06()
+ set nrformats+=alpha
+ call setline(1, repeat(["z"], 4))
+ exec "norm! GV3kg\<C-X>"
+ call assert_equal(["y", "x", "w", "v"], getline(1, '$'))
+ call assert_equal([0, 1, 1, 0], getpos('.'))
+ endfunc
+
+ " 7) <Ctrl-A> on letter
+ " Test:
+ " 2
+ " 1
+ " 0
+ " -1
+ " -2
+ "
+ " Expected:
+ " 1) Ctrl-A on visually selected lines
+ " 3
+ " 2
+ " 1
+ " 0
+ " -1
+ "
+ " 2) Ctrl-X on visually selected lines
+ " 1
+ " 0
+ " -1
+ " -2
+ " -3
+ func Test_visual_increment_07()
+ call setline(1, ["2", "1", "0", "-1", "-2"])
+ exec "norm! GV4k\<C-A>"
+ call assert_equal(["3", "2", "1", "0", "-1"], getline(1, '$'))
+ call assert_equal([0, 1, 1, 0], getpos('.'))
+
+ call setline(1, ["2", "1", "0", "-1", "-2"])
+ exec "norm! GV4k\<C-X>"
+ call assert_equal(["1", "0", "-1", "-2", "-3"], getline(1, '$'))
+ call assert_equal([0, 1, 1, 0], getpos('.'))
+ endfunc
+
+ " 8) Block increment on 0x9
+ " Text:
+ " 0x9
+ " 0x9
+ " Expected:
+ " 1) Ctrl-A on visually block selected region (cursor at beginning):
+ " 0xa
+ " 0xa
+ " 2) Ctrl-A on visually block selected region (cursor at end)
+ " 0xa
+ " 0xa
+ func Test_visual_increment_08()
+ call setline(1, repeat(["0x9"], 2))
+ exec "norm! \<C-V>j$\<C-A>"
+ call assert_equal(["0xa", "0xa"], getline(1, '$'))
+ call assert_equal([0, 1, 1, 0], getpos('.'))
+
+ call setline(1, repeat(["0x9"], 2))
+ exec "norm! gg$\<C-V>+\<C-A>"
+ call assert_equal(["0xa", "0xa"], getline(1, '$'))
+ call assert_equal([0, 1, 1, 0], getpos('.'))
+ endfunc
+
+ " 9) Increment and redo
+ " Text:
+ " 2
+ " 2
+ "
+ " 3
+ " 3
+ "
+ " Expected:
+ " 1) 2 Ctrl-A on first 2 visually selected lines
+ " 4
+ " 4
+ " 2) redo (.) on 3
+ " 5
+ " 5
+ func Test_visual_increment_09()
+ call setline(1, ["2", "2", "", "3", "3", ""])
+ exec "norm! ggVj2\<C-A>"
+ call assert_equal(["4", "4", "", "3", "3", ""], getline(1, '$'))
+ call assert_equal([0, 1, 1, 0], getpos('.'))
+
+ exec "norm! 3j."
+ call assert_equal(["4", "4", "", "5", "5", ""], getline(1, '$'))
+ call assert_equal([0, 4, 1, 0], getpos('.'))
+ endfunc
+
+ " 10) sequentially decrement 1
+ " Text:
+ " 1
+ " 1
+ " 1
+ " 1
+ " Expected:
+ " 1) g Ctrl-X on visually selected lines
+ " 0
+ " -1
+ " -2
+ " -3
+ func Test_visual_increment_10()
+ call setline(1, repeat(["1"], 4))
+ exec "norm! GV3kg\<C-X>"
+ call assert_equal(["0", "-1", "-2", "-3"], getline(1, '$'))
+ call assert_equal([0, 1, 1, 0], getpos('.'))
+ endfunc
+
+ " 11) visually block selected indented lines
+ " Text:
+ " 1
+ " 1
+ " 1
+ " 1
+ " Expexted:
+ " 1) g Ctrl-A on block selected indented lines
+ " 2
+ " 1
+ " 3
+ " 4
+ func Test_visual_increment_11()
+ call setline(1, [" 1", "1", " 1", " 1"])
+ exec "norm! f1\<C-V>3jg\<C-A>"
+ call assert_equal([" 2", "1", " 3", " 4"], getline(1, '$'))
+ call assert_equal([0, 1, 5, 0], getpos('.'))
+ endfunc
+
+ " 12) visually selected several columns
+ " Text:
+ " 0 0
+ " 0 0
+ " 0 0
+ " Expected:
+ " 1) 'v' select last zero and first zeroes
+ " 0 1
+ " 1 0
+ " 1 0
+ func Test_visual_increment_12()
+ call setline(1, repeat(["0 0"], 3))
+ exec "norm! $v++\<C-A>"
+ call assert_equal(["0 1", "1 0", "1 0"], getline(1, '$'))
+ call assert_equal([0, 1, 3, 0], getpos('.'))
+ endfunc
+
+ " 13) visually selected part of columns
+ " Text:
+ " max: 100px
+ " max: 200px
+ " max: 300px
+ " max: 400px
+ " Expected:
+ " 1) 'v' on first two numbers Ctrl-A
+ " max: 110px
+ " max: 220px
+ " max: 330px
+ " max: 400px
+ " 2) 'v' on first two numbers Ctrl-X
+ " max: 90px
+ " max: 190px
+ " max: 290px
+ " max: 400px
+ func Test_visual_increment_13()
+ call setline(1, ["max: 100px", "max: 200px", "max: 300px", "max: 400px"])
+ exec "norm! f1\<C-V>l2j\<C-A>"
+ call assert_equal(["max: 110px", "max: 210px", "max: 310px", "max: 400px"], getline(1, '$'))
+ call assert_equal([0, 1, 6, 0], getpos('.'))
+
+ call setline(1, ["max: 100px", "max: 200px", "max: 300px", "max: 400px"])
+ exec "norm! ggf1\<C-V>l2j\<C-X>"
+ call assert_equal(["max: 90px", "max: 190px", "max: 290px", "max: 400px"], getline(1, '$'))
+ call assert_equal([0, 1, 6, 0], getpos('.'))
+ endfunc
+
+ " 14) redo in block mode
+ " Text:
+ " 1 1
+ " 1 1
+ " Expected:
+ " 1) Ctrl-a on first column, redo on second column
+ " 2 2
+ " 2 2
+ func Test_visual_increment_14()
+ call setline(1, repeat(["1 1"], 2))
+ exec "norm! G\<C-V>k\<C-A>w."
+ call assert_equal(["2 2", "2 2"], getline(1, '$'))
+ call assert_equal([0, 1, 3, 0], getpos('.'))
+ endfunc
+
+ " 15) block select single numbers
+ " Text:
+ " 101
+ " Expected:
+ " 1) Ctrl-a on visually selected zero
+ " 111
+ func Test_visual_increment_15()
+ call setline(1, ["101"])
+ exec "norm! lv\<C-A>"
+ call assert_equal(["111"], getline(1, '$'))
+ call assert_equal([0, 1, 2, 0], getpos('.'))
+ endfunc
+
+ " 16) increment right aligned numbers
+ " Text:
+ " 1
+ " 19
+ " 119
+ " Expected:
+ " 1) Ctrl-a on line selected region
+ " 2
+ " 20
+ " 120
+ func Test_visual_increment_16()
+ call setline(1, [" 1", " 19", " 119"])
+ exec "norm! VG\<C-A>"
+ call assert_equal([" 2", " 20", " 120"], getline(1, '$'))
+ call assert_equal([0, 1, 1, 0], getpos('.'))
+ endfunc
+
+ " 17) block-wise increment and redo
+ " Text:
+ " 100
+ " 1
+ "
+ " 100
+ " 1
+ "
+ " Expected:
+ " 1) Ctrl-V j $ on first block, afterwards '.' on second
+ " 101
+ " 2
+ "
+ " 101
+ " 2
+ func Test_visual_increment_17()
+ call setline(1, [" 100", " 1", "", " 100", " 1"])
+ exec "norm! \<C-V>j$\<C-A>2j."
+ call assert_equal([" 101", " 2", "", " 101", " 1"], getline(1, '$'))
+ call assert_equal([0, 3, 1, 0], getpos('.'))
+ endfunc
+
+ " 18) repeat of g<Ctrl-a>
+ " Text:
+ " 0
+ " 0
+ " 0
+ " 0
+ "
+ " Expected:
+ " 1) V 4j g<ctrl-a>, repeat twice afterwards with .
+ " 3
+ " 6
+ " 9
+ " 12
+ func Test_visual_increment_18()
+ call setline(1, repeat(["0"], 4))
+ exec "norm! GV3kg\<C-A>"
+ exec "norm! .."
+ call assert_equal(["3", "6", "9", "12"], getline(1, '$'))
+ call assert_equal([0, 1, 1, 0], getpos('.'))
+ endfunc
+
+ " 19) increment on number with nrformat including alpha
+ " Text:
+ " 1
+ " 1a
+ "
+ " Expected:
+ " 1) <Ctrl-V>j$ <ctrl-a>
+ " 2
+ " 2a
+ func Test_visual_increment_19()
+ set nrformats+=alpha
+ call setline(1, ["1", "1a"])
+ exec "norm! \<C-V>G$\<C-A>"
+ call assert_equal(["2", "2a"], getline(1, '$'))
+ call assert_equal([0, 1, 1, 0], getpos('.'))
+ endfunc
+
+ " 20) increment a single letter
+ " Text:
+ " a
+ "
+ " Expected:
+ " 1) <Ctrl-a> and cursor is on a
+ " b
+ func Test_visual_increment_20()
+ set nrformats+=alpha
+ call setline(1, ["a"])
+ exec "norm! \<C-A>"
+ call assert_equal(["b"], getline(1, '$'))
+ call assert_equal([0, 1, 1, 0], getpos('.'))
+ endfunc
+
+ " 21) block-wise increment on part of hexadecimal
+ " Text:
+ " 0x123456
+ "
+ " Expected:
+ " 1) Ctrl-V f3 <ctrl-a>
+ " 0x124456
+ func Test_visual_increment_21()
+ call setline(1, ["0x123456"])
+ exec "norm! \<C-V>f3\<C-A>"
+ call assert_equal(["0x124456"], getline(1, '$'))
+ call assert_equal([0, 1, 1, 0], getpos('.'))
+ endfunc
+
+ " 22) Block increment on 0b0
+ " Text:
+ " 0b1
+ " 0b1
+ " Expected:
+ " 1) Ctrl-A on visually block selected region (cursor at beginning):
+ " 0b10
+ " 0b10
+ " 2) Ctrl-A on visually block selected region (cursor at end)
+ " 0b10
+ " 0b10
+ func Test_visual_increment_22()
+ call setline(1, repeat(["0b1"], 2))
+ exec "norm! \<C-V>j$\<C-A>"
+ call assert_equal(repeat(["0b10"], 2), getline(1, '$'))
+ call assert_equal([0, 1, 1, 0], getpos('.'))
+
+ call setline(1, repeat(["0b1"], 2))
+ exec "norm! $\<C-V>+\<C-A>"
+ call assert_equal(repeat(["0b10"], 2), getline(1, '$'))
+ call assert_equal([0, 1, 1, 0], getpos('.'))
+ endfunc
+
+ " 23) block-wise increment on part of binary
+ " Text:
+ " 0b1001
+ "
+ " Expected:
+ " 1) Ctrl-V 5l <ctrl-a>
+ " 0b1011
+ func Test_visual_increment_23()
+ call setline(1, ["0b1001"])
+ exec "norm! \<C-V>4l\<C-A>"
+ call assert_equal(["0b1011"], getline(1, '$'))
+ call assert_equal([0, 1, 1, 0], getpos('.'))
+ endfunc
+
+ " 24) increment hexadecimal
+ " Text:
+ " 0x0b1001
+ "
+ " Expected:
+ " 1) <ctrl-a>
+ " 0x0b1002
+ func Test_visual_increment_24()
+ call setline(1, ["0x0b1001"])
+ exec "norm! \<C-V>$\<C-A>"
+ call assert_equal(["0x0b1002"], getline(1, '$'))
+ call assert_equal([0, 1, 1, 0], getpos('.'))
+ endfunc
+
+ " 25) increment binary with nrformats including alpha
+ " Text:
+ " 0b1001a
+ "
+ " Expected:
+ " 1) <ctrl-a>
+ " 0b1010a
+ func Test_visual_increment_25()
+ set nrformats+=alpha
+ call setline(1, ["0b1001a"])
+ exec "norm! \<C-V>$\<C-A>"
+ call assert_equal(["0b1010a"], getline(1, '$'))
+ call assert_equal([0, 1, 1, 0], getpos('.'))
+ endfunc
+
+ " 26) increment binary with 32 bits
+ " Text:
+ " 0b11111111111111111111111111111110
+ "
+ " Expected:
+ " 1) <ctrl-a>
+ " 0b11111111111111111111111111111111
+ func Test_visual_increment_26()
+ set nrformats+=alpha
+ call setline(1, ["0b11111111111111111111111111111110"])
+ exec "norm! \<C-V>$\<C-A>"
+ call assert_equal(["0b11111111111111111111111111111111"], getline(1, '$'))
+ call assert_equal([0, 1, 1, 0], getpos('.'))
+ set nrformats-=alpha
+ endfunc
+
+ " 27) increment with 'rightreft', if supported
+ func Test_visual_increment_27()
+ if exists('+rightleft')
+ set rightleft
+ call setline(1, ["1234 56"])
+
+ exec "norm! $\<C-A>"
+ call assert_equal(["1234 57"], getline(1, '$'))
+ call assert_equal([0, 1, 7, 0], getpos('.'))
+
+ exec "norm! \<C-A>"
+ call assert_equal(["1234 58"], getline(1, '$'))
+ call assert_equal([0, 1, 7, 0], getpos('.'))
+ set norightleft
+ endif
+ endfunc
+
+ " Tab code and linewise-visual inc/dec
+ func Test_visual_increment_28()
+ call setline(1, ["x\<TAB>10", "\<TAB>-1"])
+ exec "norm! Vj\<C-A>"
+ call assert_equal(["x\<TAB>11", "\<TAB>0"], getline(1, '$'))
+ call assert_equal([0, 1, 1, 0], getpos('.'))
+
+ call setline(1, ["x\<TAB>10", "\<TAB>-1"])
+ exec "norm! ggVj\<C-X>"
+ call assert_equal(["x\<TAB>9", "\<TAB>-2"], getline(1, '$'))
+ call assert_equal([0, 1, 1, 0], getpos('.'))
+ endfunc
+
+ " Tab code and linewise-visual inc/dec with 'nrformats'+=alpha
+ func Test_visual_increment_29()
+ set nrformats+=alpha
+ call setline(1, ["x\<TAB>10", "\<TAB>-1"])
+ exec "norm! Vj\<C-A>"
+ call assert_equal(["y\<TAB>10", "\<TAB>0"], getline(1, '$'))
+ call assert_equal([0, 1, 1, 0], getpos('.'))
+
+ call setline(1, ["x\<TAB>10", "\<TAB>-1"])
+ exec "norm! ggVj\<C-X>"
+ call assert_equal(["w\<TAB>10", "\<TAB>-2"], getline(1, '$'))
+ call assert_equal([0, 1, 1, 0], getpos('.'))
+ endfunc
+
+ " Tab code and character-visual inc/dec
+ func Test_visual_increment_30()
+ call setline(1, ["x\<TAB>10", "\<TAB>-1"])
+ exec "norm! f1vjf1\<C-A>"
+ call assert_equal(["x\<TAB>11", "\<TAB>0"], getline(1, '$'))
+ call assert_equal([0, 1, 3, 0], getpos('.'))
+
+ call setline(1, ["x\<TAB>10", "\<TAB>-1"])
+ exec "norm! ggf1vjf1\<C-X>"
+ call assert_equal(["x\<TAB>9", "\<TAB>-2"], getline(1, '$'))
+ call assert_equal([0, 1, 3, 0], getpos('.'))
+ endfunc
+
+ " Tab code and blockwise-visual inc/dec
+ func Test_visual_increment_31()
+ call setline(1, ["x\<TAB>10", "\<TAB>-1"])
+ exec "norm! f1\<C-V>jl\<C-A>"
+ call assert_equal(["x\<TAB>11", "\<TAB>0"], getline(1, '$'))
+ call assert_equal([0, 1, 3, 0], getpos('.'))
+
+ call setline(1, ["x\<TAB>10", "\<TAB>-1"])
+ exec "norm! ggf1\<C-V>jl\<C-X>"
+ call assert_equal(["x\<TAB>9", "\<TAB>-2"], getline(1, '$'))
+ call assert_equal([0, 1, 3, 0], getpos('.'))
+ endfunc
+
+ " Tab code and blockwise-visual decrement with 'linebreak' and 'showbreak'
+ func Test_visual_increment_32()
+ 28vnew dummy_31
+ set linebreak showbreak=+
+ call setline(1, ["x\<TAB>\<TAB>\<TAB>10", "\<TAB>\<TAB>\<TAB>\<TAB>-1"])
+ exec "norm! ggf0\<C-V>jg_\<C-X>"
+ call assert_equal(["x\<TAB>\<TAB>\<TAB>1-1", "\<TAB>\<TAB>\<TAB>\<TAB>-2"], getline(1, '$'))
+ call assert_equal([0, 1, 6, 0], getpos('.'))
+ bwipe!
+ endfunc
+
+ " Tab code and blockwise-visual increment with $
+ func Test_visual_increment_33()
+ call setline(1, ["\<TAB>123", "456"])
+ exec "norm! gg0\<C-V>j$\<C-A>"
+ call assert_equal(["\<TAB>124", "457"], getline(1, '$'))
+ call assert_equal([0, 1, 1, 0], getpos('.'))
+ endfunc
+
+ " Tab code and blockwise-visual increment and redo
+ func Test_visual_increment_34()
+ call setline(1, ["\<TAB>123", " 456789"])
+ exec "norm! gg0\<C-V>j\<C-A>"
+ call assert_equal(["\<TAB>123", " 457789"], getline(1, '$'))
+ call assert_equal([0, 1, 1, 0], getpos('.'))
+
+ exec "norm! .."
+ call assert_equal(["\<TAB>123", " 459789"], getline(1, '$'))
+ call assert_equal([0, 1, 1, 0], getpos('.'))
+ endfunc
+
+ " Tab code, spaces and character-visual increment and redo
+ func Test_visual_increment_35()
+ call setline(1, ["\<TAB>123", " 123", "\<TAB>123", "\<TAB>123"])
+ exec "norm! ggvjf3\<C-A>..."
+ call assert_equal(["\<TAB>127", " 127", "\<TAB>123", "\<TAB>123"], getline(1, '$'))
+ call assert_equal([0, 1, 2, 0], getpos('.'))
+ endfunc
+
+ " Tab code, spaces and blockwise-visual increment and redo
+ func Test_visual_increment_36()
+ call setline(1, [" 123", "\<TAB>456789"])
+ exec "norm! G0\<C-V>kl\<C-A>"
+ call assert_equal([" 123", "\<TAB>556789"], getline(1, '$'))
+ call assert_equal([0, 1, 1, 0], getpos('.'))
+
+ exec "norm! ..."
+ call assert_equal([" 123", "\<TAB>856789"], getline(1, '$'))
+ call assert_equal([0, 1, 1, 0], getpos('.'))
+ endfunc
+
+ " block-wise increment and dot-repeat
+ " Text:
+ " 1 23
+ " 4 56
+ "
+ " Expected:
+ " 1) f2 Ctrl-V jl <ctrl-a>, repeat twice afterwards with .
+ " 1 26
+ " 4 59
+ "
+ " Try with and without indent.
+ func Test_visual_increment_37()
+ call setline(1, [" 1 23", " 4 56"])
+ exec "norm! ggf2\<C-V>jl\<C-A>.."
+ call assert_equal([" 1 26", " 4 59"], getline(1, 2))
+
+ call setline(1, ["1 23", "4 56"])
+ exec "norm! ggf2\<C-V>jl\<C-A>.."
+ call assert_equal(["1 26", "4 59"], getline(1, 2))
+ endfunc
+
+ " Check redo after the normal mode increment
+ func Test_visual_increment_38()
+ exec "norm! i10\<ESC>5\<C-A>."
+ call assert_equal(["20"], getline(1, '$'))
+ call assert_equal([0, 1, 2, 0], getpos('.'))
+ endfunc
+ ]=])
+ end)
+
+ for i = 1, 38 do
+ local id = string.format('%02d', i)
+
+ it('works on Test ' .. id, function()
+ execute('set nrformats&vi') -- &vi makes Vim compatible
+ call('Test_visual_increment_' .. id)
+ eq({}, nvim.get_vvar('errors'))
+ end)
+ end
+end)
diff --git a/test/functional/legacy/listlbr_utf8_spec.lua b/test/functional/legacy/listlbr_utf8_spec.lua
index 69e7b87a21..df0e817533 100644
--- a/test/functional/legacy/listlbr_utf8_spec.lua
+++ b/test/functional/legacy/listlbr_utf8_spec.lua
@@ -2,6 +2,7 @@
local helpers = require('test.functional.helpers')
local source = helpers.source
+local feed = helpers.feed
local clear, expect = helpers.clear, helpers.expect
describe('linebreak', function()
@@ -32,16 +33,19 @@ describe('linebreak', function()
$put =g:line
wincmd p
endfu
+ "
let g:test ="Test 1: set linebreak + set list + fancy listchars"
exe "set linebreak list listchars=nbsp:\u2423,tab:\u2595\u2014,trail:\u02d1,eol:\ub6"
redraw!
let line=ScreenChar(winwidth(0),4)
call DoRecordScreen()
+ "
let g:test ="Test 2: set nolinebreak list"
set list nolinebreak
redraw!
let line=ScreenChar(winwidth(0),4)
call DoRecordScreen()
+ "
let g:test ="Test 3: set linebreak nolist"
$put =\"\t*mask = nil;\"
$
@@ -50,6 +54,7 @@ describe('linebreak', function()
redraw!
let line=ScreenChar(winwidth(0),4)
call DoRecordScreen()
+ "
let g:test ="Test 4: set linebreak list listchars and concealing"
let c_defines=['#define ABCDE 1','#define ABCDEF 1','#define ABCDEFG 1','#define ABCDEFGH 1', '#define MSG_MODE_FILE 1','#define MSG_MODE_CONSOLE 2','#define MSG_MODE_FILE_AND_CONSOLE 3','#define MSG_MODE_FILE_THEN_CONSOLE 4']
call append('$', c_defines)
@@ -61,6 +66,84 @@ describe('linebreak', function()
redraw!
let line=ScreenChar(winwidth(0),7)
call DoRecordScreen()
+ "
+ let g:test ="Test 5: set linebreak list listchars and concealing part2"
+ let c_defines=['bbeeeeee ; some text']
+ call append('$', c_defines)
+ $
+ norm! zt
+ set nowrap ts=2 list linebreak listchars=tab:>- cole=2 concealcursor=n
+ syn clear
+ syn match meaning /;\s*\zs.*/
+ syn match hasword /^\x\{8}/ contains=word
+ syn match word /\<\x\{8}\>/ contains=beginword,endword contained
+ syn match beginword /\<\x\x/ contained conceal
+ syn match endword /\x\{6}\>/ contained
+ hi meaning guibg=blue
+ hi beginword guibg=green
+ hi endword guibg=red
+ redraw!
+ let line=ScreenChar(winwidth(0),1)
+ call DoRecordScreen()
+ "
+ let g:test ="Test 6: Screenattributes for comment"
+ $put =g:test
+ call append('$', ' /* and some more */')
+ exe "set ft=c ts=7 linebreak list listchars=nbsp:\u2423,tab:\u2595\u2014,trail:\u02d1,eol:\ub6"
+ syntax on
+ hi SpecialKey term=underline ctermfg=red guifg=red
+ let attr=[]
+ nnoremap <expr> GG ":let attr += ['".screenattr(screenrow(),screencol())."']\n"
+ $
+ norm! zt0
+ ]])
+ feed('GGlGGlGGlGGlGGlGGlGGlGGlGGlGGl')
+ source([[
+ call append('$', ['ScreenAttributes for test6:'])
+ if attr[0] != attr[1] && attr[1] != attr[3] && attr[3] != attr[5]
+ call append('$', "Attribut 0 and 1 and 3 and 5 are different!")
+ else
+ call append('$', "Not all attributes are different")
+ endif
+ set cpo&vim linebreak selection=exclusive
+ let g:test ="Test 8: set linebreak with visual block mode and v_b_A and selection=exclusive and multibyte char"
+ $put =g:test
+ ]])
+ feed("Golong line: <Esc>40afoobar <Esc>aTARGETÃ' at end<Esc>")
+ source([[
+ exe "norm! $3B\<C-v>eAx\<Esc>"
+ "
+ let g:test ="Test 9: a multibyte sign and colorcolumn"
+ let attr=[]
+ let attr2=[]
+ $put =''
+ $put ='a b c'
+ $put ='a b c'
+ set list nolinebreak cc=3
+ ]])
+ feed(':sign define foo text=<C-v>uff0b<CR>')
+ source([[
+ sign place 1 name=foo line=50 buffer=2
+ norm! 2kztj
+ let line1=line('.')
+ ]])
+ feed('0GGlGGlGGlGGl')
+ source([[
+ let line2=line('.')
+ let attr2=attr
+ let attr=[]
+ ]])
+ feed('0GGlGGlGGlGGl')
+ source([[
+ redraw!
+ let line=ScreenChar(winwidth(0),3)
+ call DoRecordScreen()
+ " expected: attr[2] is different because of colorcolumn
+ if attr[0] != attr2[0] || attr[1] != attr2[1] || attr[2] != attr2[2]
+ call append('$', "Screen attributes are different!")
+ else
+ call append('$', "Screen attributes are the same!")
+ endif
]])
-- Assert buffer contents.
@@ -102,6 +185,25 @@ describe('linebreak', function()
#define >CDEFGH>----1
#define >_FILE>--------->--->---1
#define >_CONSOLE>---------->---2
- #define >_FILE_AND_CONSOLE>---------3 ]])
+ #define >_FILE_AND_CONSOLE>---------3
+ bbeeeeee ; some text
+
+ Test 5: set linebreak list listchars and concealing part2
+ eeeeee>--->-;>some text
+ Test 6: Screenattributes for comment
+ /* and some more */
+ ScreenAttributes for test6:
+ Attribut 0 and 1 and 3 and 5 are different!
+ Test 8: set linebreak with visual block mode and v_b_A and selection=exclusive and multibyte char
+ long line: foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar TARGETÃx' at end
+
+ a b c
+ a b c
+
+ Test 9: a multibyte sign and colorcolumn
+ ¶
+ +a b c¶
+ a b c¶
+ Screen attributes are the same!]])
end)
end)
diff --git a/test/functional/legacy/match_conceal_spec.lua b/test/functional/legacy/match_conceal_spec.lua
new file mode 100644
index 0000000000..0ffa3cae7a
--- /dev/null
+++ b/test/functional/legacy/match_conceal_spec.lua
@@ -0,0 +1,228 @@
+-- Test for matchadd() and conceal feature
+
+local helpers = require('test.functional.helpers')
+local clear = helpers.clear
+local expect = helpers.expect
+local source = helpers.source
+
+describe('match_conceal', function()
+ before_each(function()
+ clear()
+
+ source([[
+ set wildchar=^E
+ 10new
+ vsp
+ vert resize 20
+ put =\"\#\ This\ is\ a\ Test\"
+ norm! mazt
+
+ fu! ScreenChar(width, lines)
+ let c=''
+ for j in range(1,a:lines)
+ for i in range(1,a:width)
+ let c.=nr2char(screenchar(j, i))
+ endfor
+ let c.="\n"
+ endfor
+ return c
+ endfu
+
+ fu! ScreenAttr(line, pos, eval)
+ let g:attr=[]
+ for col in a:pos
+ call add(g:attr, screenattr(a:line,col))
+ endfor
+ " In case all values are zero, probably the terminal
+ " isn't set correctly, so catch that case
+ let null = (eval(join(g:attr, '+')) == 0)
+ let str=substitute(a:eval, '\d\+', 'g:attr[&]', 'g')
+ if null || eval(str)
+ let g:attr_test="OK: ". str
+ else
+ let g:attr_test="FAILED: ".str
+ let g:attr_test.="\n". join(g:attr, ' ')
+ let g:attr_test.="\n TERM: ". &term
+ endif
+ endfu
+
+ fu! DoRecordScreen()
+ wincmd l
+ $put =printf(\"\n%s\", g:test)
+ $put =g:line
+ $put =g:attr_test
+ wincmd p
+ endfu
+ ]])
+ end)
+
+ it('is working', function()
+ source([=[
+ let g:test ="Test 1: simple addmatch()"
+ call matchadd('Conceal', '\%2l ')
+ redraw!
+ let line=ScreenChar(winwidth(0),1)
+ call ScreenAttr(1,[1,2,7,10,12,16], "0!=1 && 1==2 && 1==3 && 1==4 && 0==5")
+ call DoRecordScreen()
+
+ let g:test ="Test 2: simple addmatch() and conceal (should be: #XThisXisXaXTest)"
+ norm! 'azt
+ call clearmatches()
+ syntax on
+ set concealcursor=n conceallevel=1
+ call matchadd('Conceal', '\%2l ', 10, -1, {'conceal': 'X'})
+ redraw!
+ let line=ScreenChar(winwidth(0),1)
+ call ScreenAttr(1,[1,2,7,10,12,16], "0!=1 && 1==2 && 1==3 && 1==4 && 0==5")
+ call DoRecordScreen()
+
+ let g:test ="Test 3: addmatch() and conceallevel=3 (should be: #ThisisaTest)"
+ norm! 'azt
+ set conceallevel=3
+ call clearmatches()
+ call matchadd('Conceal', '\%2l ', 10, -1, {'conceal': 'X'})
+ redraw!
+ let line=ScreenChar(winwidth(0),1)
+ call ScreenAttr(1,[1,2,7,10,12,16], "0==1 && 1==2 && 1==3 && 1==4 && 0!=5")
+ call DoRecordScreen()
+
+ let g:test ="Test 4: more match() (should be: #Thisisa Test)"
+ norm! 'azt
+ call matchadd('ErrorMsg', '\%2l Test', 20, -1, {'conceal': 'X'})
+ redraw!
+ let line=ScreenChar(winwidth(0),1)
+ call ScreenAttr(1,[1,2,7,10,12,16], "0==1 && 1==2 && 0!=3 && 3==4 && 0!=5 && 3!=5")
+ call DoRecordScreen()
+
+ let g:test ="Test 5/1: default conceal char (should be: # This is a Test)"
+ norm! 'azt
+ call clearmatches()
+ set conceallevel=1
+ call matchadd('Conceal', '\%2l ', 10, -1, {})
+ redraw!
+ let line=ScreenChar(winwidth(0),1)
+ call ScreenAttr(1,[1,2,7,10,12,16], "0!=1 && 1==2 && 1==3 && 1==4 && 0==5")
+ call DoRecordScreen()
+ let g:test ="Test 5/2: default conceal char (should be: #+This+is+a+Test)"
+ norm! 'azt
+ set listchars=conceal:+
+ redraw!
+ let line=ScreenChar(winwidth(0),1)
+ call ScreenAttr(1,[1,2,7,10,12,16], "0!=1 && 1==2 && 1==3 && 1==4 && 0==5")
+ call DoRecordScreen()
+ set listchars&vi
+
+ let g:test ="Test 6/1: syn and match conceal (should be: #ZThisZisZaZTest)"
+ norm! 'azt
+ call clearmatches()
+ set conceallevel=1
+ call matchadd('Conceal', '\%2l ', 10, -1, {'conceal': 'Z'})
+ syn match MyConceal /\%2l / conceal containedin=ALL cchar=*
+ redraw!
+ let line=ScreenChar(winwidth(0),1)
+ call ScreenAttr(1,[1,2,7,10,12,16], "0!=1 && 1==2 && 1==3 && 1==4 && 0==5")
+ call DoRecordScreen()
+ let g:test ="Test 6/2: syn and match conceal (should be: #*This*is*a*Test)"
+ norm! 'azt
+ call clearmatches()
+ redraw!
+ let line=ScreenChar(winwidth(0),1)
+ call ScreenAttr(1,[1,2,7,10,12,16], "0!=1 && 1==2 && 1==3 && 1==4 && 0==5")
+ call DoRecordScreen()
+
+ let g:test ="Test 7/1: clear matches"
+ norm! 'azt
+ syn on
+ call matchadd('Conceal', '\%2l ', 10, -1, {'conceal': 'Z'})
+ let a=getmatches()
+ call clearmatches()
+ redraw!
+ let line=ScreenChar(winwidth(0),1)
+ call ScreenAttr(1,[1,2,7,10,12,16], "0==1 && 0==2 && 0==3 && 0==4 && 0==5")
+ call DoRecordScreen()
+ $put =a
+ call setmatches(a)
+ norm! 'azt
+ let g:test ="Test 7/2: reset match using setmatches()"
+ norm! 'azt
+ redraw!
+ let line=ScreenChar(winwidth(0),1)
+ call ScreenAttr(1,[1,2,7,10,12,16], "0!=1 && 1==2 && 1==3 && 1==4 && 0==5")
+ call DoRecordScreen()
+
+ let g:test ="Test 8: using matchaddpos() (should be #Pis a Test"
+ norm! 'azt
+ call clearmatches()
+ call matchaddpos('Conceal', [[2,2,6]], 10, -1, {'conceal': 'P'})
+ let a=getmatches()
+ redraw!
+ let line=ScreenChar(winwidth(0),1)
+ call ScreenAttr(1,[1,2,7,10,12,16], "0!=1 && 1!=2 && 0==2 && 0==3 && 0!=4 && 0!=5 && 4==5")
+ call DoRecordScreen()
+ $put =a
+
+ let g:test ="Test 9: match using multibyte conceal char (should be: #ˑThisˑisˑaˑTest)"
+ norm! 'azt
+ call clearmatches()
+ call matchadd('Conceal', '\%2l ', 20, -1, {'conceal': "\u02d1"})
+ redraw!
+ let line=ScreenChar(winwidth(0),1)
+ call ScreenAttr(1,[1,2,7,10,12,16], "0!=1 && 1==2 && 1==3 && 1==4 && 0==5")
+ call DoRecordScreen()
+ ]=])
+
+ expect([=[
+
+ # This is a Test
+
+ Test 1: simple addmatch()
+ # This is a Test
+ OK: g:attr[0]!=g:attr[1] && g:attr[1]==g:attr[2] && g:attr[1]==g:attr[3] && g:attr[1]==g:attr[4] && g:attr[0]==g:attr[5]
+
+ Test 2: simple addmatch() and conceal (should be: #XThisXisXaXTest)
+ #XThisXisXaXTest
+ OK: g:attr[0]!=g:attr[1] && g:attr[1]==g:attr[2] && g:attr[1]==g:attr[3] && g:attr[1]==g:attr[4] && g:attr[0]==g:attr[5]
+
+ Test 3: addmatch() and conceallevel=3 (should be: #ThisisaTest)
+ #ThisisaTest
+ OK: g:attr[0]==g:attr[1] && g:attr[1]==g:attr[2] && g:attr[1]==g:attr[3] && g:attr[1]==g:attr[4] && g:attr[0]!=g:attr[5]
+
+ Test 4: more match() (should be: #Thisisa Test)
+ #Thisisa Test
+ OK: g:attr[0]==g:attr[1] && g:attr[1]==g:attr[2] && g:attr[0]!=g:attr[3] && g:attr[3]==g:attr[4] && g:attr[0]!=g:attr[5] && g:attr[3]!=g:attr[5]
+
+ Test 5/1: default conceal char (should be: # This is a Test)
+ # This is a Test
+ OK: g:attr[0]!=g:attr[1] && g:attr[1]==g:attr[2] && g:attr[1]==g:attr[3] && g:attr[1]==g:attr[4] && g:attr[0]==g:attr[5]
+
+ Test 5/2: default conceal char (should be: #+This+is+a+Test)
+ #+This+is+a+Test
+ OK: g:attr[0]!=g:attr[1] && g:attr[1]==g:attr[2] && g:attr[1]==g:attr[3] && g:attr[1]==g:attr[4] && g:attr[0]==g:attr[5]
+
+ Test 6/1: syn and match conceal (should be: #ZThisZisZaZTest)
+ #ZThisZisZaZTest
+ OK: g:attr[0]!=g:attr[1] && g:attr[1]==g:attr[2] && g:attr[1]==g:attr[3] && g:attr[1]==g:attr[4] && g:attr[0]==g:attr[5]
+
+ Test 6/2: syn and match conceal (should be: #*This*is*a*Test)
+ #*This*is*a*Test
+ OK: g:attr[0]!=g:attr[1] && g:attr[1]==g:attr[2] && g:attr[1]==g:attr[3] && g:attr[1]==g:attr[4] && g:attr[0]==g:attr[5]
+
+ Test 7/1: clear matches
+ # This is a Test
+ OK: g:attr[0]==g:attr[1] && g:attr[0]==g:attr[2] && g:attr[0]==g:attr[3] && g:attr[0]==g:attr[4] && g:attr[0]==g:attr[5]
+ {'group': 'Conceal', 'pattern': '\%2l ', 'priority': 10, 'id': 10, 'conceal': 'Z'}
+
+ Test 7/2: reset match using setmatches()
+ #ZThisZisZaZTest
+ OK: g:attr[0]!=g:attr[1] && g:attr[1]==g:attr[2] && g:attr[1]==g:attr[3] && g:attr[1]==g:attr[4] && g:attr[0]==g:attr[5]
+
+ Test 8: using matchaddpos() (should be #Pis a Test
+ #Pis a Test
+ OK: g:attr[0]!=g:attr[1] && g:attr[1]!=g:attr[2] && g:attr[0]==g:attr[2] && g:attr[0]==g:attr[3] && g:attr[0]!=g:attr[4] && g:attr[0]!=g:attr[5] && g:attr[4]==g:attr[5]
+ {'group': 'Conceal', 'id': 11, 'priority': 10, 'pos1': [2, 2, 6], 'conceal': 'P'}
+
+ Test 9: match using multibyte conceal char (should be: #ˑThisˑisˑaˑTest)
+ #ˑThisˑisˑaˑTest
+ OK: g:attr[0]!=g:attr[1] && g:attr[1]==g:attr[2] && g:attr[1]==g:attr[3] && g:attr[1]==g:attr[4] && g:attr[0]==g:attr[5]]=])
+ end)
+end)
diff --git a/test/functional/legacy/options_spec.lua b/test/functional/legacy/options_spec.lua
index 773acb9663..21e99c4aa1 100644
--- a/test/functional/legacy/options_spec.lua
+++ b/test/functional/legacy/options_spec.lua
@@ -1,13 +1,27 @@
--- Test if ":options" throws any exception. The options window seems to mess
--- other tests, so restart nvim in the teardown hook
-
local helpers = require('test.functional.helpers')
local command, clear = helpers.command, helpers.clear
+local source, expect = helpers.source, helpers.expect
describe('options', function()
setup(clear)
- it('is working', function()
+ it('should not throw any exception', function()
command('options')
end)
end)
+
+describe('set', function()
+ setup(clear)
+
+ it("should keep two comma when 'path' is changed", function()
+ source([[
+ set path=foo,,bar
+ set path-=bar
+ set path+=bar
+ $put =&path]])
+
+ expect([[
+
+ foo,,bar]])
+ end)
+end)
diff --git a/test/functional/legacy/quickfix_spec.lua b/test/functional/legacy/quickfix_spec.lua
new file mode 100644
index 0000000000..88f86815b3
--- /dev/null
+++ b/test/functional/legacy/quickfix_spec.lua
@@ -0,0 +1,17 @@
+-- Test for the quickfix commands.
+
+local helpers = require('test.functional.helpers')
+local source, clear = helpers.source, helpers.clear
+
+describe('helpgrep', function()
+ before_each(clear)
+
+ it('works', function()
+ source([[
+ helpgrep quickfix
+ copen
+ " This wipes out the buffer, make sure that doesn't cause trouble.
+ cclose
+ ]])
+ end)
+end)
diff --git a/test/functional/legacy/search_mbyte_spec.lua b/test/functional/legacy/search_mbyte_spec.lua
new file mode 100644
index 0000000000..075b24b897
--- /dev/null
+++ b/test/functional/legacy/search_mbyte_spec.lua
@@ -0,0 +1,26 @@
+local helpers = require('test.functional.helpers')
+local insert = helpers.insert
+local clear, execute, expect = helpers.clear, helpers.execute, helpers.expect
+
+describe('search_mbyte', function()
+ before_each(clear)
+
+ it("search('multi-byte char', 'bce')", function()
+ insert([=[
+ Results:
+
+ Test bce:
+ A]=])
+
+ execute('/^Test bce:/+1')
+ execute([[$put =search('A', 'bce', line('.'))]])
+
+ -- Assert buffer contents.
+ expect([=[
+ Results:
+
+ Test bce:
+ A
+ 4]=])
+ end)
+end)
diff --git a/test/functional/legacy/set_spec.lua b/test/functional/legacy/set_spec.lua
new file mode 100644
index 0000000000..f81fcd3700
--- /dev/null
+++ b/test/functional/legacy/set_spec.lua
@@ -0,0 +1,15 @@
+-- Tests for :set
+
+local helpers = require('test.functional.helpers')
+local clear, execute, eval, eq =
+ helpers.clear, helpers.execute, helpers.eval, helpers.eq
+
+describe(':set', function()
+ before_each(clear)
+
+ it('recognizes a trailing comma with +=', function()
+ execute('set wildignore=*.png,')
+ execute('set wildignore+=*.jpg')
+ eq('*.png,*.jpg', eval('&wildignore'))
+ end)
+end)
diff --git a/test/functional/legacy/textobjects_spec.lua b/test/functional/legacy/textobjects_spec.lua
new file mode 100644
index 0000000000..1e8e0b0bcb
--- /dev/null
+++ b/test/functional/legacy/textobjects_spec.lua
@@ -0,0 +1,61 @@
+local helpers = require('test.functional.helpers')
+local call = helpers.call
+local clear = helpers.clear
+local execute = helpers.execute
+local expect = helpers.expect
+local source = helpers.source
+
+describe('Text object', function()
+ before_each(function()
+ clear()
+ execute('set shada=')
+ source([[
+ function SelectionOut(data)
+ new
+ call setline(1, a:data)
+ call setreg('"', '')
+ normal! ggfrmavi)y
+ $put =getreg('\"')
+ call setreg('"', '')
+ normal! `afbmavi)y
+ $put =getreg('\"')
+ call setreg('"', '')
+ normal! `afgmavi)y
+ $put =getreg('\"')
+ endfunction
+ ]])
+ end)
+
+ it('Test for vi) without cpo-M', function()
+ execute('set cpo-=M')
+ call('SelectionOut', '(red \\(blue) green)')
+
+ expect([[
+ (red \(blue) green)
+ red \(blue
+ red \(blue
+ ]])
+ end)
+
+ it('Test for vi) with cpo-M #1', function()
+ execute('set cpo+=M')
+ call('SelectionOut', '(red \\(blue) green)')
+
+ expect([[
+ (red \(blue) green)
+ red \(blue) green
+ blue
+ red \(blue) green]])
+ end)
+
+ it('Test for vi) with cpo-M #2', function()
+ execute('set cpo+=M')
+ call('SelectionOut', '(red (blue\\) green)')
+
+ expect([[
+ (red (blue\) green)
+ red (blue\) green
+ blue\
+ red (blue\) green]])
+ end)
+end)
diff --git a/test/functional/legacy/utf8_spec.lua b/test/functional/legacy/utf8_spec.lua
index ef717042d0..d33ba6b5fd 100644
--- a/test/functional/legacy/utf8_spec.lua
+++ b/test/functional/legacy/utf8_spec.lua
@@ -3,9 +3,11 @@
local helpers = require('test.functional.helpers')
local clear, feed, insert = helpers.clear, helpers.feed, helpers.insert
local execute, expect = helpers.execute, helpers.expect
+local eq, eval = helpers.eq, helpers.eval
+local source = helpers.source
describe('utf8', function()
- setup(clear)
+ before_each(clear)
it('is working', function()
insert('start:')
@@ -27,4 +29,55 @@ describe('utf8', function()
xあああ
bxbb]])
end)
+
+ it('strchars()', function()
+ eq(1, eval('strchars("a")'))
+ eq(1, eval('strchars("a", 0)'))
+ eq(1, eval('strchars("a", 1)'))
+
+ eq(3, eval('strchars("あいa")'))
+ eq(3, eval('strchars("あいa", 0)'))
+ eq(3, eval('strchars("あいa", 1)'))
+
+ eq(2, eval('strchars("A\\u20dd")'))
+ eq(2, eval('strchars("A\\u20dd", 0)'))
+ eq(1, eval('strchars("A\\u20dd", 1)'))
+
+ eq(3, eval('strchars("A\\u20dd\\u20dd")'))
+ eq(3, eval('strchars("A\\u20dd\\u20dd", 0)'))
+ eq(1, eval('strchars("A\\u20dd\\u20dd", 1)'))
+
+ eq(1, eval('strchars("\\u20dd")'))
+ eq(1, eval('strchars("\\u20dd", 0)'))
+ eq(1, eval('strchars("\\u20dd", 1)'))
+ end)
+
+ it('customlist completion', function()
+ source([[
+ function! CustomComplete1(lead, line, pos)
+ return ['あ', 'い']
+ endfunction
+ command -nargs=1 -complete=customlist,CustomComplete1 Test1 echo]])
+ feed(":Test1 <C-L>'<C-B>$put='<CR>")
+
+ source([[
+ function! CustomComplete2(lead, line, pos)
+ return ['あたし', 'あたま', 'あたりめ']
+ endfunction
+ command -nargs=1 -complete=customlist,CustomComplete2 Test2 echo]])
+ feed(":Test2 <C-L>'<C-B>$put='<CR>")
+
+ source([[
+ function! CustomComplete3(lead, line, pos)
+ return ['Nこ', 'Nん', 'Nぶ']
+ endfunction
+ command -nargs=1 -complete=customlist,CustomComplete3 Test3 echo]])
+ feed(":Test3 <C-L>'<C-B>$put='<CR>")
+
+ expect([[
+
+ Test1
+ Test2 あた
+ Test3 N]])
+ end)
end)
diff --git a/test/functional/shada/shada_spec.lua b/test/functional/shada/shada_spec.lua
index 2bc855a239..822ab3913c 100644
--- a/test/functional/shada/shada_spec.lua
+++ b/test/functional/shada/shada_spec.lua
@@ -174,6 +174,7 @@ describe('ShaDa support code', function()
nvim_command('set shada+=%')
nvim_command('wshada! ' .. shada_fname)
local readme_fname = paths.test_source_path .. '/README.md'
+ readme_fname = helpers.eval( 'resolve("' .. readme_fname .. '")' )
eq({[7]=1, [8]=2, [9]=1, [10]=4, [11]=1}, find_file(readme_fname))
nvim_command('set shada+=r~')
nvim_command('wshada! ' .. shada_fname)
diff --git a/test/functional/ui/highlight_spec.lua b/test/functional/ui/highlight_spec.lua
index f9b112e464..6a89b0983d 100644
--- a/test/functional/ui/highlight_spec.lua
+++ b/test/functional/ui/highlight_spec.lua
@@ -14,15 +14,6 @@ describe('color scheme compatibility', function()
request('vim_set_option', 't_Co', '88')
eq('88', request('vim_eval', '&t_Co'))
end)
-
- it('emulates gui_running when a rgb UI is attached', function()
- eq(0, request('vim_eval', 'has("gui_running")'))
- local screen = Screen.new()
- screen:attach()
- eq(1, request('vim_eval', 'has("gui_running")'))
- screen:detach()
- eq(0, request('vim_eval', 'has("gui_running")'))
- end)
end)
diff --git a/test/functional/ui/input_spec.lua b/test/functional/ui/input_spec.lua
index 4818830940..6f5cadaf81 100644
--- a/test/functional/ui/input_spec.lua
+++ b/test/functional/ui/input_spec.lua
@@ -25,6 +25,9 @@ describe('mappings', function()
add_mapping('<s-up>', '<s-up>')
add_mapping('<c-s-up>', '<c-s-up>')
add_mapping('<c-s-a-up>', '<c-s-a-up>')
+ add_mapping('<c-s-a-d-up>', '<c-s-a-d-up>')
+ add_mapping('<c-d-a>', '<c-d-a>')
+ add_mapping('<d-1>', '<d-1>')
end)
it('ok', function()
@@ -37,6 +40,12 @@ describe('mappings', function()
check_mapping('<s-a-c-up>', '<c-s-a-up>')
check_mapping('<a-c-s-up>', '<c-s-a-up>')
check_mapping('<a-s-c-up>', '<c-s-a-up>')
+ check_mapping('<c-s-a-d-up>', '<c-s-a-d-up>')
+ check_mapping('<s-a-d-c-up>', '<c-s-a-d-up>')
+ check_mapping('<d-s-a-c-up>', '<c-s-a-d-up>')
+ check_mapping('<c-d-a>', '<c-d-a>')
+ check_mapping('<d-c-a>', '<c-d-a>')
+ check_mapping('<d-1>', '<d-1>')
end)
end)
diff --git a/test/functional/ui/mouse_spec.lua b/test/functional/ui/mouse_spec.lua
index b3992c4a89..da9d6a0cd2 100644
--- a/test/functional/ui/mouse_spec.lua
+++ b/test/functional/ui/mouse_spec.lua
@@ -1,7 +1,8 @@
local helpers = require('test.functional.helpers')
local Screen = require('test.functional.ui.screen')
-local clear, feed, nvim = helpers.clear, helpers.feed, helpers.nvim
+local clear, feed, meths = helpers.clear, helpers.feed, helpers.meths
local insert, execute = helpers.insert, helpers.execute
+local eq, funcs = helpers.eq, helpers.funcs
describe('Mouse input', function()
local screen
@@ -13,11 +14,11 @@ describe('Mouse input', function()
before_each(function()
clear()
- nvim('set_option', 'mouse', 'a')
- nvim('set_option', 'listchars', 'eol:$')
+ meths.set_option('mouse', 'a')
+ meths.set_option('listchars', 'eol:$')
-- set mouset to very high value to ensure that even in valgrind/travis,
-- nvim will still pick multiple clicks
- nvim('set_option', 'mouset', 5000)
+ meths.set_option('mouset', 5000)
screen = Screen.new(25, 5)
screen:attach()
screen:set_default_attr_ids({
@@ -58,31 +59,149 @@ describe('Mouse input', function()
]])
end)
- it('left click in tabline switches to tab', function()
+ describe('tabline', function()
local tab_attrs = {
tab = { background=Screen.colors.LightGrey, underline=true },
sel = { bold=true },
fill = { reverse=true }
}
- execute('%delete')
- insert('this is foo')
- execute('silent file foo | tabnew | file bar')
- insert('this is bar')
- screen:expect([[
- {tab: + foo }{sel: + bar }{fill: }{tab:X}|
- this is ba^r |
- ~ |
- ~ |
- |
- ]], tab_attrs)
- feed('<LeftMouse><4,0>')
- screen:expect([[
- {sel: + foo }{tab: + bar }{fill: }{tab:X}|
- this is fo^o |
- ~ |
- ~ |
- |
- ]], tab_attrs)
+
+ it('left click in default tabline (position 4) switches to tab', function()
+ execute('%delete')
+ insert('this is foo')
+ execute('silent file foo | tabnew | file bar')
+ insert('this is bar')
+ screen:expect([[
+ {tab: + foo }{sel: + bar }{fill: }{tab:X}|
+ this is ba^r |
+ ~ |
+ ~ |
+ |
+ ]], tab_attrs)
+ feed('<LeftMouse><4,0>')
+ screen:expect([[
+ {sel: + foo }{tab: + bar }{fill: }{tab:X}|
+ this is fo^o |
+ ~ |
+ ~ |
+ |
+ ]], tab_attrs)
+ end)
+
+ it('left click in default tabline (position 24) closes tab', function()
+ meths.set_option('hidden', true)
+ execute('%delete')
+ insert('this is foo')
+ execute('silent file foo | tabnew | file bar')
+ insert('this is bar')
+ screen:expect([[
+ {tab: + foo }{sel: + bar }{fill: }{tab:X}|
+ this is ba^r |
+ ~ |
+ ~ |
+ |
+ ]], tab_attrs)
+ feed('<LeftMouse><24,0>')
+ screen:expect([[
+ this is fo^o |
+ ~ |
+ ~ |
+ ~ |
+ |
+ ]], tab_attrs)
+ end)
+
+ it('double click in default tabline (position 4) opens new tab', function()
+ meths.set_option('hidden', true)
+ execute('%delete')
+ insert('this is foo')
+ execute('silent file foo | tabnew | file bar')
+ insert('this is bar')
+ screen:expect([[
+ {tab: + foo }{sel: + bar }{fill: }{tab:X}|
+ this is ba^r |
+ ~ |
+ ~ |
+ |
+ ]], tab_attrs)
+ feed('<2-LeftMouse><4,0>')
+ screen:expect([[
+ {sel: Name] }{tab: + foo + bar }{fill: }{tab:X}|
+ ^ |
+ ~ |
+ ~ |
+ |
+ ]], tab_attrs)
+ end)
+
+ describe('%@ label', function()
+ before_each(function()
+ execute([[
+ function Test(...)
+ let g:reply = a:000
+ return copy(a:000) " Check for memory leaks: return should be freed
+ endfunction
+ ]])
+ execute([[
+ function Test2(...)
+ return call('Test', a:000 + [2])
+ endfunction
+ ]])
+ meths.set_option('tabline', '%@Test@test%X-%5@Test2@test2')
+ meths.set_option('showtabline', 2)
+ screen:expect([[
+ {fill:test-test2 }|
+ mouse |
+ support and selectio^n |
+ ~ |
+ |
+ ]], tab_attrs)
+ meths.set_var('reply', {})
+ end)
+
+ local check_reply = function(expected)
+ eq(expected, meths.get_var('reply'))
+ meths.set_var('reply', {})
+ end
+
+ local test_click = function(name, click_str, click_num, mouse_button,
+ modifiers)
+ it(name .. ' works', function()
+ eq(1, funcs.has('tablineat'))
+ feed(click_str .. '<3,0>')
+ check_reply({0, click_num, mouse_button, modifiers})
+ feed(click_str .. '<4,0>')
+ check_reply({})
+ feed(click_str .. '<6,0>')
+ check_reply({5, click_num, mouse_button, modifiers, 2})
+ feed(click_str .. '<13,0>')
+ check_reply({5, click_num, mouse_button, modifiers, 2})
+ end)
+ end
+
+ test_click('single left click', '<LeftMouse>', 1, 'l', ' ')
+ test_click('shifted single left click', '<S-LeftMouse>', 1, 'l', 's ')
+ test_click('shifted single left click with alt modifier',
+ '<S-A-LeftMouse>', 1, 'l', 's a ')
+ test_click('shifted single left click with alt and ctrl modifiers',
+ '<S-C-A-LeftMouse>', 1, 'l', 'sca ')
+ -- <C-RightMouse> does not work
+ test_click('shifted single right click with alt modifier',
+ '<S-A-RightMouse>', 1, 'r', 's a ')
+ -- Modifiers do not work with MiddleMouse
+ test_click('shifted single middle click with alt and ctrl modifiers',
+ '<MiddleMouse>', 1, 'm', ' ')
+ -- Modifiers do not work with N-*Mouse
+ test_click('double left click', '<2-LeftMouse>', 2, 'l', ' ')
+ test_click('triple left click', '<3-LeftMouse>', 3, 'l', ' ')
+ test_click('quadruple left click', '<4-LeftMouse>', 4, 'l', ' ')
+ test_click('double right click', '<2-RightMouse>', 2, 'r', ' ')
+ test_click('triple right click', '<3-RightMouse>', 3, 'r', ' ')
+ test_click('quadruple right click', '<4-RightMouse>', 4, 'r', ' ')
+ test_click('double middle click', '<2-MiddleMouse>', 2, 'm', ' ')
+ test_click('triple middle click', '<3-MiddleMouse>', 3, 'm', ' ')
+ test_click('quadruple middle click', '<4-MiddleMouse>', 4, 'm', ' ')
+ end)
end)
it('left drag changes visual selection', function()
@@ -211,7 +330,7 @@ describe('Mouse input', function()
end)
it('ctrl + left click will search for a tag', function()
- nvim('set_option', 'tags', './non-existent-tags-file')
+ meths.set_option('tags', './non-existent-tags-file')
feed('<C-LeftMouse><0,0>')
screen:expect([[
E433: No tags file |
diff --git a/test/functional/viml/completion_spec.lua b/test/functional/viml/completion_spec.lua
index 12f542de7f..4bb9707cda 100644
--- a/test/functional/viml/completion_spec.lua
+++ b/test/functional/viml/completion_spec.lua
@@ -2,7 +2,7 @@
local helpers = require('test.functional.helpers')
local clear, feed = helpers.clear, helpers.feed
local eval, eq, neq = helpers.eval, helpers.eq, helpers.neq
-local execute, source = helpers.execute, helpers.source
+local execute, source, expect = helpers.execute, helpers.source, helpers.expect
describe('completion', function()
before_each(function()
@@ -100,4 +100,45 @@ describe('completion', function()
eq('', eval('getline(3)'))
end)
end)
+
+ describe("refresh:always", function()
+ before_each(function()
+ source([[
+ function! TestCompletion(findstart, base) abort
+ if a:findstart
+ let line = getline('.')
+ let start = col('.') - 1
+ while start > 0 && line[start - 1] =~ '\a'
+ let start -= 1
+ endwhile
+ return start
+ else
+ let ret = []
+ for m in split("January February March April May June July August September October November December")
+ if m =~ a:base " match by regex
+ call add(ret, m)
+ endif
+ endfor
+ return {'words':ret, 'refresh':'always'}
+ endif
+ endfunction
+
+ set completeopt=menuone,noselect
+ set completefunc=TestCompletion
+ ]])
+ end )
+
+ it('completes on each input char', function ()
+ feed('i<C-x><C-u>gu<Down><C-y>')
+ expect('August')
+ end)
+ it("repeats correctly after backspace #2674", function ()
+ feed('o<C-x><C-u>Ja<BS><C-n><C-n><Esc>')
+ feed('.')
+ expect([[
+
+ June
+ June]])
+ end)
+ end)
end)
diff --git a/test/unit/strings_spec.lua b/test/unit/strings_spec.lua
index b310ccb541..e935d2af6a 100644
--- a/test/unit/strings_spec.lua
+++ b/test/unit/strings_spec.lua
@@ -1,7 +1,6 @@
local helpers = require("test.unit.helpers")
local cimport = helpers.cimport
-local internalize = helpers.internalize
local eq = helpers.eq
local ffi = helpers.ffi
local to_cstr = helpers.to_cstr