aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.ci/clang-asan.sh4
-rw-r--r--.ci/gcc-32.sh3
-rw-r--r--.ci/gcc.sh4
-rw-r--r--cmake/GetGitRevisionDescription.cmake53
-rw-r--r--runtime/autoload/provider/clipboard.vim36
-rw-r--r--runtime/doc/cmdline.txt1
-rw-r--r--runtime/doc/editing.txt141
-rw-r--r--runtime/doc/eval.txt7
-rw-r--r--runtime/doc/filetype.txt35
-rw-r--r--runtime/doc/gui.txt21
-rw-r--r--runtime/doc/index.txt1
-rw-r--r--runtime/doc/insert.txt1
-rw-r--r--runtime/doc/manpages/vim.13
-rw-r--r--runtime/doc/mbyte.txt3
-rw-r--r--runtime/doc/nvim_clipboard.txt30
-rw-r--r--runtime/doc/nvim_intro.txt2
-rw-r--r--runtime/doc/nvim_provider.txt19
-rw-r--r--runtime/doc/nvim_python.txt8
-rw-r--r--runtime/doc/options.txt96
-rw-r--r--runtime/doc/os_mac.txt2
-rw-r--r--runtime/doc/print.txt10
-rw-r--r--runtime/doc/quickref.txt4
-rw-r--r--runtime/doc/recover.txt47
-rw-r--r--runtime/doc/remote_plugin.txt91
-rw-r--r--runtime/doc/spell.txt2
-rw-r--r--runtime/doc/starting.txt18
-rw-r--r--runtime/doc/todo.txt13
-rw-r--r--runtime/doc/undo.txt10
-rw-r--r--runtime/doc/usr_05.txt1
-rw-r--r--runtime/doc/usr_11.txt2
-rw-r--r--runtime/doc/usr_23.txt96
-rw-r--r--runtime/doc/usr_toc.txt5
-rw-r--r--runtime/doc/various.txt1
-rw-r--r--runtime/doc/vi_diff.txt11
-rw-r--r--runtime/menu.vim12
-rw-r--r--runtime/optwin.vim15
-rw-r--r--runtime/print/ebcdic-uk.ps40
-rw-r--r--runtime/syntax/help.vim12
-rw-r--r--runtime/syntax/sed.vim10
-rw-r--r--runtime/syntax/vim.vim16
-rw-r--r--scripts/msgpack-gen.lua7
-rw-r--r--src/nvim/api/buffer.c20
-rw-r--r--src/nvim/api/vim.c6
-rw-r--r--src/nvim/edit.c27
-rw-r--r--src/nvim/eval.c132
-rw-r--r--src/nvim/ex_cmds.c4
-rw-r--r--src/nvim/ex_cmds2.c8
-rw-r--r--src/nvim/ex_docmd.c42
-rw-r--r--src/nvim/ex_getln.c4
-rw-r--r--src/nvim/fold.c5
-rw-r--r--src/nvim/garray.c5
-rw-r--r--src/nvim/garray.h26
-rw-r--r--src/nvim/getchar.c7
-rw-r--r--src/nvim/globals.h4
-rw-r--r--src/nvim/main.c36
-rw-r--r--src/nvim/memory.c37
-rw-r--r--src/nvim/menu.c15
-rw-r--r--src/nvim/message.c13
-rw-r--r--src/nvim/mouse.c11
-rw-r--r--src/nvim/msgpack_rpc/channel.c25
-rw-r--r--src/nvim/msgpack_rpc/defs.h4
-rw-r--r--src/nvim/msgpack_rpc/remote_ui.c280
-rw-r--r--src/nvim/msgpack_rpc/remote_ui.h9
-rw-r--r--src/nvim/normal.c42
-rw-r--r--src/nvim/ops.c485
-rw-r--r--src/nvim/ops.h7
-rw-r--r--src/nvim/option.c13
-rw-r--r--src/nvim/option_defs.h8
-rw-r--r--src/nvim/os/input.c113
-rw-r--r--src/nvim/os/shell.c52
-rw-r--r--src/nvim/os/signal.c2
-rw-r--r--src/nvim/os_unix.c1
-rw-r--r--src/nvim/screen.c43
-rw-r--r--src/nvim/spell.c61
-rw-r--r--src/nvim/strings.c10
-rw-r--r--src/nvim/syntax.c306
-rw-r--r--src/nvim/syntax.h2
-rw-r--r--src/nvim/syntax_defs.h3
-rw-r--r--src/nvim/term.c131
-rw-r--r--src/nvim/testdir/dotest.in2
-rw-r--r--src/nvim/testdir/test14.in6
-rw-r--r--src/nvim/testdir/test17.in6
-rw-r--r--src/nvim/testdir/test40.in1
-rw-r--r--src/nvim/testdir/test48.in2
-rw-r--r--src/nvim/testdir/test60.in1
-rw-r--r--src/nvim/testdir/test68.in4
-rw-r--r--src/nvim/testdir/test69.in8
-rw-r--r--src/nvim/testdir/test90.in2
-rw-r--r--src/nvim/testdir/test_breakindent.in1
-rw-r--r--src/nvim/testdir/test_breakindent.ok8
-rw-r--r--src/nvim/testdir/test_eval.in147
-rw-r--r--src/nvim/testdir/test_eval.okbin432 -> 10578 bytes
-rw-r--r--src/nvim/testdir/test_listlbr.in1
-rw-r--r--src/nvim/testdir/test_listlbr_utf8.in1
-rw-r--r--src/nvim/ui.c445
-rw-r--r--src/nvim/ui.h32
-rw-r--r--src/nvim/version.c6
-rw-r--r--test/functional/api/buffer_spec.lua5
-rw-r--r--test/functional/api/vim_spec.lua9
-rw-r--r--test/functional/clipboard/autoload/provider/clipboard.vim16
-rw-r--r--test/functional/clipboard/clipboard_provider_spec.lua141
-rw-r--r--test/functional/helpers.lua53
-rw-r--r--test/functional/legacy/026_execute_while_if_spec.lua18
-rw-r--r--test/functional/legacy/033_lisp_indent_spec.lua20
-rw-r--r--test/functional/ui/highlight_spec.lua184
-rw-r--r--test/functional/ui/input_spec.lua40
-rw-r--r--test/functional/ui/mouse_spec.lua157
-rw-r--r--test/functional/ui/screen.lua384
-rw-r--r--test/functional/ui/screen_basic_spec.lua224
-rw-r--r--third-party/CMakeLists.txt12
110 files changed, 3481 insertions, 1347 deletions
diff --git a/.ci/clang-asan.sh b/.ci/clang-asan.sh
index 9cc2ad12ad..e0087b17a4 100644
--- a/.ci/clang-asan.sh
+++ b/.ci/clang-asan.sh
@@ -31,7 +31,9 @@ export TSAN_OPTIONS="external_symbolizer_path=$symbolizer:log_path=$tmpdir/tsan"
export UBSAN_OPTIONS="log_path=$tmpdir/ubsan" # not sure if this works
-CMAKE_EXTRA_FLAGS="-DTRAVIS_CI_BUILD=ON -DUSE_GCOV=ON"
+CMAKE_EXTRA_FLAGS="-DTRAVIS_CI_BUILD=ON \
+ -DUSE_GCOV=ON \
+ -DBUSTED_OUTPUT_TYPE=plainTerminal"
# Build and output version info.
$MAKE_CMD CMAKE_EXTRA_FLAGS="$CMAKE_EXTRA_FLAGS -DSANITIZE=ON" nvim
diff --git a/.ci/gcc-32.sh b/.ci/gcc-32.sh
index 13b2d46d8f..e0448894ab 100644
--- a/.ci/gcc-32.sh
+++ b/.ci/gcc-32.sh
@@ -19,7 +19,8 @@ CMAKE_EXTRA_FLAGS="-DTRAVIS_CI_BUILD=ON \
-DCMAKE_SYSTEM_LIBRARY_PATH=/lib32:/usr/lib32:/usr/local/lib32 \
-DFIND_LIBRARY_USE_LIB64_PATHS=OFF \
-DCMAKE_IGNORE_PATH=/lib:/usr/lib:/usr/local/lib \
- -DCMAKE_TOOLCHAIN_FILE=cmake/i386-linux-gnu.toolchain.cmake"
+ -DCMAKE_TOOLCHAIN_FILE=cmake/i386-linux-gnu.toolchain.cmake \
+ -DBUSTED_OUTPUT_TYPE=plainTerminal"
# Build and output version info.
$MAKE_CMD CMAKE_EXTRA_FLAGS="$CMAKE_EXTRA_FLAGS" nvim
diff --git a/.ci/gcc.sh b/.ci/gcc.sh
index 8d09c756a7..ad9cbd33b0 100644
--- a/.ci/gcc.sh
+++ b/.ci/gcc.sh
@@ -15,7 +15,9 @@ setup_prebuilt_deps x64
export VALGRIND=1
export VALGRIND_LOG="$tmpdir/valgrind-%p.log"
-CMAKE_EXTRA_FLAGS="-DTRAVIS_CI_BUILD=ON -DUSE_GCOV=ON"
+CMAKE_EXTRA_FLAGS="-DTRAVIS_CI_BUILD=ON \
+ -DUSE_GCOV=ON \
+ -DBUSTED_OUTPUT_TYPE=plainTerminal"
# Build and output version info.
$MAKE_CMD CMAKE_EXTRA_FLAGS="$CMAKE_EXTRA_FLAGS" nvim
diff --git a/cmake/GetGitRevisionDescription.cmake b/cmake/GetGitRevisionDescription.cmake
index dec748d094..1e0968ec3b 100644
--- a/cmake/GetGitRevisionDescription.cmake
+++ b/cmake/GetGitRevisionDescription.cmake
@@ -43,19 +43,19 @@ get_filename_component(_gitdescmoddir ${CMAKE_CURRENT_LIST_FILE} PATH)
function(get_git_dir _gitdir)
# check GIT_DIR in environment first
- set(GIT_DIR "$ENV{GIT_DIR}")
+ set(GIT_DIR $ENV{GIT_DIR})
if(NOT GIT_DIR)
- set(GIT_PARENT_DIR "${CMAKE_CURRENT_SOURCE_DIR}")
- set(GIT_DIR "${GIT_PARENT_DIR}/.git")
+ set(GIT_PARENT_DIR ${CMAKE_CURRENT_SOURCE_DIR})
+ set(GIT_DIR ${GIT_PARENT_DIR}/.git)
endif()
# .git dir not found, search parent directories
- while(NOT EXISTS "${GIT_DIR}")
- set(GIT_PREVIOUS_PARENT "${GIT_PARENT_DIR}")
+ while(NOT EXISTS ${GIT_DIR})
+ set(GIT_PREVIOUS_PARENT ${GIT_PARENT_DIR})
get_filename_component(GIT_PARENT_DIR ${GIT_PARENT_DIR} PATH)
if(GIT_PARENT_DIR STREQUAL GIT_PREVIOUS_PARENT)
return()
endif()
- set(GIT_DIR "${GIT_PARENT_DIR}/.git")
+ set(GIT_DIR ${GIT_PARENT_DIR}/.git)
endwhile()
# check if this is a submodule
if(NOT IS_DIRECTORY ${GIT_DIR})
@@ -73,24 +73,24 @@ function(get_git_head_revision _refspecvar _hashvar)
return()
endif()
- set(GIT_DATA "${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/git-data")
- if(NOT EXISTS "${GIT_DATA}")
- file(MAKE_DIRECTORY "${GIT_DATA}")
+ set(GIT_DATA ${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/git-data)
+ if(NOT EXISTS ${GIT_DATA})
+ file(MAKE_DIRECTORY ${GIT_DATA})
endif()
- if(NOT EXISTS "${GIT_DIR}/HEAD")
+ if(NOT EXISTS ${GIT_DIR}/HEAD)
return()
endif()
- set(HEAD_FILE "${GIT_DATA}/HEAD")
- configure_file("${GIT_DIR}/HEAD" "${HEAD_FILE}" COPYONLY)
+ set(HEAD_FILE ${GIT_DATA}/HEAD)
+ configure_file(${GIT_DIR}/HEAD ${HEAD_FILE} COPYONLY)
- configure_file("${_gitdescmoddir}/GetGitRevisionDescription.cmake.in"
- "${GIT_DATA}/grabRef.cmake"
+ configure_file(${_gitdescmoddir}/GetGitRevisionDescription.cmake.in
+ ${GIT_DATA}/grabRef.cmake
@ONLY)
- include("${GIT_DATA}/grabRef.cmake")
+ include(${GIT_DATA}/grabRef.cmake)
- set(${_refspecvar} "${HEAD_REF}" PARENT_SCOPE)
- set(${_hashvar} "${HEAD_HASH}" PARENT_SCOPE)
+ set(${_refspecvar} ${HEAD_REF} PARENT_SCOPE)
+ set(${_hashvar} ${HEAD_HASH} PARENT_SCOPE)
endfunction()
function(git_describe _var)
@@ -114,12 +114,12 @@ function(git_describe _var)
endif()
execute_process(COMMAND
- "${GIT_EXECUTABLE}"
+ ${GIT_EXECUTABLE}
describe
${hash}
${ARGN}
WORKING_DIRECTORY
- "${GIT_DIR}"
+ ${GIT_DIR}
RESULT_VARIABLE
res
OUTPUT_VARIABLE
@@ -130,7 +130,7 @@ function(git_describe _var)
set(out "${out}-${res}-NOTFOUND")
endif()
- set(${_var} "${out}" PARENT_SCOPE)
+ set(${_var} ${out} PARENT_SCOPE)
endfunction()
function(git_timestamp _var)
@@ -152,22 +152,23 @@ function(git_timestamp _var)
return()
endif()
- execute_process(COMMAND "${GIT_EXECUTABLE}" log -1 --format="%ci" ${hash} ${ARGN}
- WORKING_DIRECTORY "${GIT_DIR}"
+ execute_process(COMMAND ${GIT_EXECUTABLE} log -1 --format="%ci" ${hash} ${ARGN}
+ WORKING_DIRECTORY ${GIT_DIR}
RESULT_VARIABLE res
OUTPUT_VARIABLE out
ERROR_QUIET
OUTPUT_STRIP_TRAILING_WHITESPACE)
- if(NOT res EQUAL 0)
+ if(res EQUAL 0)
+ string(REGEX REPLACE "[-\" :]" "" out ${out})
+ string(SUBSTRING ${out} 0 12 out)
+ else()
set(out "${out}-${res}-NOTFOUND")
endif()
- string(REGEX REPLACE "[-\" :]" "" out ${out})
- string(SUBSTRING ${out} 0 12 out)
set(${_var} ${out} PARENT_SCOPE)
endfunction()
function(git_get_exact_tag _var)
git_describe(out --exact-match ${ARGN})
- set(${_var} "${out}" PARENT_SCOPE)
+ set(${_var} ${out} PARENT_SCOPE)
endfunction()
diff --git a/runtime/autoload/provider/clipboard.vim b/runtime/autoload/provider/clipboard.vim
index 46c05a882c..458ef6257d 100644
--- a/runtime/autoload/provider/clipboard.vim
+++ b/runtime/autoload/provider/clipboard.vim
@@ -1,11 +1,11 @@
" The clipboard provider uses shell commands to communicate with the clipboard.
" The provider function will only be registered if one of the supported
" commands are available.
-let s:copy = ''
-let s:paste = ''
+let s:copy = {}
+let s:paste = {}
function! s:try_cmd(cmd, ...)
- let out = a:0 ? systemlist(a:cmd, a:1) : systemlist(a:cmd)
+ let out = a:0 ? systemlist(a:cmd, a:1, 1) : systemlist(a:cmd, [''], 1)
if v:shell_error
echo "clipboard: error: ".(len(out) ? out[0] : '')
return ''
@@ -14,14 +14,20 @@ function! s:try_cmd(cmd, ...)
endfunction
if executable('pbcopy')
- let s:copy = 'pbcopy'
- let s:paste = 'pbpaste'
-elseif executable('xsel')
- let s:copy = 'xsel -i -b'
- let s:paste = 'xsel -o -b'
+ let s:copy['+'] = 'pbcopy'
+ let s:paste['+'] = 'pbpaste'
+ let s:copy['*'] = s:copy['+']
+ let s:paste['*'] = s:paste['+']
elseif executable('xclip')
- let s:copy = 'xclip -i -selection clipboard'
- let s:paste = 'xclip -o -selection clipboard'
+ let s:copy['+'] = 'xclip -i -selection clipboard'
+ let s:paste['+'] = 'xclip -o -selection clipboard'
+ let s:copy['*'] = 'xclip -i -selection primary'
+ let s:paste['*'] = 'xclip -o -selection primary'
+elseif executable('xsel')
+ let s:copy['+'] = 'xsel -i -b'
+ let s:paste['+'] = 'xsel -o -b'
+ let s:copy['*'] = 'xsel -i -p'
+ let s:paste['*'] = 'xsel -o -p'
else
echom 'clipboard: No shell command for communicating with the clipboard found.'
finish
@@ -29,14 +35,14 @@ endif
let s:clipboard = {}
-function! s:clipboard.get(...)
- return s:try_cmd(s:paste)
+function! s:clipboard.get(reg)
+ return s:try_cmd(s:paste[a:reg])
endfunction
-function! s:clipboard.set(...)
- call s:try_cmd(s:copy, a:1)
+function! s:clipboard.set(lines, regtype, reg)
+ call s:try_cmd(s:copy[a:reg], a:lines)
endfunction
function! provider#clipboard#Call(method, args)
- return s:clipboard[a:method](a:args)
+ return call(s:clipboard[a:method],a:args,s:clipboard)
endfunction
diff --git a/runtime/doc/cmdline.txt b/runtime/doc/cmdline.txt
index 2892faa496..77813423ba 100644
--- a/runtime/doc/cmdline.txt
+++ b/runtime/doc/cmdline.txt
@@ -1053,7 +1053,6 @@ VARIOUS
The command-line window cannot be used:
- when there already is a command-line window (no nesting)
-- for entering an encryption key or when using inputsecret()
- when Vim was not compiled with the |+vertsplit| feature
Some options are set when the command-line window is opened:
diff --git a/runtime/doc/editing.txt b/runtime/doc/editing.txt
index e4867e7a90..3496a03921 100644
--- a/runtime/doc/editing.txt
+++ b/runtime/doc/editing.txt
@@ -136,22 +136,8 @@ as the original file with 'backupext' appended. The default "~" is a bit
strange to avoid accidentally overwriting existing files. If you prefer ".bak"
change the 'backupext' option. Extra dots are replaced with '_' on MS-DOS
machines, when Vim has detected that an MS-DOS-like filesystem is being used
-(e.g., messydos or crossdos) or when the 'shortname' option is on. The
-backup file can be placed in another directory by setting 'backupdir'.
-
- *auto-shortname*
-Technical: On the Amiga you can use 30 characters for a file name. But on an
- MS-DOS-compatible filesystem only 8 plus 3 characters are
- available. Vim tries to detect the type of filesystem when it is
- creating the .swp file. If an MS-DOS-like filesystem is suspected,
- a flag is set that has the same effect as setting the 'shortname'
- option. This flag will be reset as soon as you start editing a
- new file. The flag will be used when making the file name for the
- ".swp" and ".~" files for the current file. But when you are
- editing a file in a normal filesystem and write to an MS-DOS-like
- filesystem the flag will not have been set. In that case the
- creation of the ".~" file may fail and you will get an error
- message. Use the 'shortname' option in this case.
+(e.g., messydos or crossdos). The backup file can be placed in another
+directory by setting 'backupdir'.
When you started editing without giving a file name, "No File" is displayed in
messages. If the ":write" command is used with a file name argument, the file
@@ -550,10 +536,6 @@ Before editing binary, executable or Vim script files you should set the
option. This will avoid the use of 'fileformat'. Without this you risk that
single <NL> characters are unexpectedly replaced with <CR><NL>.
-You can encrypt files that are written by setting the 'key' option. This
-provides some security against others reading your files. |encryption|
-
-
==============================================================================
3. The argument list *argument-list* *arglist*
@@ -1356,119 +1338,12 @@ There are a few things to remember when editing binary files:
==============================================================================
9. Encryption *encryption*
-Vim is able to write files encrypted, and read them back. The encrypted text
-cannot be read without the right key.
-{only available when compiled with the |+cryptv| feature} *E833*
-
-The text in the swap file and the undo file is also encrypted. *E843*
-However, this is done block-by-block and may reduce the time needed to crack a
-password. You can disable the swap file, but then a crash will cause you to
-lose your work. The undo file can be disabled without much disadvantage. >
- :set noundofile
- :noswapfile edit secrets
-
-Note: The text in memory is not encrypted. A system administrator may be able
-to see your text while you are editing it. When filtering text with
-":!filter" or using ":w !command" the text is not encrypted, this may reveal
-it to others. The 'viminfo' file is not encrypted.
-
-WARNING: If you make a typo when entering the key and then write the file and
-exit, the text will be lost!
-
-The normal way to work with encryption, is to use the ":X" command, which will
-ask you to enter a key. A following write command will use that key to
-encrypt the file. If you later edit the same file, Vim will ask you to enter
-a key. If you type the same key as that was used for writing, the text will
-be readable again. If you use a wrong key, it will be a mess.
-
- *:X*
-:X Prompt for an encryption key. The typing is done without showing the
- actual text, so that someone looking at the display won't see it.
- The typed key is stored in the 'key' option, which is used to encrypt
- the file when it is written. The file will remain unchanged until you
- write it. See also |-x|.
-
-The value of the 'key' options is used when text is written. When the option
-is not empty, the written file will be encrypted, using the value as the
-encryption key. A magic number is prepended, so that Vim can recognize that
-the file is encrypted.
-
-To disable the encryption, reset the 'key' option to an empty value: >
- :set key=
-
-You can use the 'cryptmethod' option to select the type of encryption, use one
-of these two: >
- :setlocal cm=zip " weak method, backwards compatible
- :setlocal cm=blowfish " strong method
-Do this before writing the file. When reading an encrypted file it will be
-set automatically to the method used when that file was written. You can
-change 'cryptmethod' before writing that file to change the method.
-To set the default method, used for new files, use one of these in your
-|vimrc| file: >
- set cm=zip
- set cm=blowfish
-The message given for reading and writing a file will show "[crypted]" when
-using zip, "[blowfish]" when using blowfish.
-
-When writing an undo file, the same key and method will be used for the text
-in the undo file. |persistent-undo|.
-
- *E817* *E818* *E819* *E820*
-When encryption does not work properly, you would be able to write your text
-to a file and never be able to read it back. Therefore a test is performed to
-check if the encryption works as expected. If you get one of these errors
-don't write the file encrypted! You need to rebuild the Vim binary to fix
-this.
-
-*E831* This is an internal error, "cannot happen". If you can reproduce it,
-please report to the developers.
-
-When reading a file that has been encrypted and the 'key' option is not empty,
-it will be used for decryption. If the value is empty, you will be prompted
-to enter the key. If you don't enter a key, or you enter the wrong key, the
-file is edited without being decrypted. There is no warning about using the
-wrong key (this makes brute force methods to find the key more difficult).
-
-If want to start reading a file that uses a different key, set the 'key'
-option to an empty string, so that Vim will prompt for a new one. Don't use
-the ":set" command to enter the value, other people can read the command over
-your shoulder.
-
-Since the value of the 'key' option is supposed to be a secret, its value can
-never be viewed. You should not set this option in a vimrc file.
-
-An encrypted file can be recognized by the "file" command, if you add these
-lines to "/etc/magic", "/usr/share/misc/magic" or wherever your system has the
-"magic" file: >
- 0 string VimCrypt~ Vim encrypted file
- >9 string 01 - "zip" cryptmethod
- >9 string 02 - "blowfish" cryptmethod
-
-
-Notes:
-- Encryption is not possible when doing conversion with 'charconvert'.
-- Text you copy or delete goes to the numbered registers. The registers can
- be saved in the .viminfo file, where they could be read. Change your
- 'viminfo' option to be safe.
-- Someone can type commands in Vim when you walk away for a moment, he should
- not be able to get the key.
-- If you make a typing mistake when entering the key, you might not be able to
- get your text back!
-- If you type the key with a ":set key=value" command, it can be kept in the
- history, showing the 'key' value in a viminfo file.
-- There is never 100% safety. The encryption in Vim has not been tested for
- robustness.
-- The algorithm used for 'cryptmethod' "zip" is breakable. A 4 character key
- in about one hour, a 6 character key in one day (on a Pentium 133 PC). This
- requires that you know some text that must appear in the file. An expert
- can break it for any key. When the text has been decrypted, this also means
- that the key can be revealed, and other files encrypted with the same key
- can be decrypted.
-- Pkzip uses the same encryption as 'cryptmethod' "zip", and US Govt has no
- objection to its export. Pkzip's public file APPNOTE.TXT describes this
- algorithm in detail.
-- Vim originates from the Netherlands. That is where the sources come from.
- Thus the encryption code is not exported from the USA.
+ *:X* *E817* *E818* *E819* *E820*
+Support for editing encrypted files has been removed, but may be added back in
+the future. See the following discussions for more information:
+
+ https://github.com/neovim/neovim/issues/694
+ https://github.com/neovim/neovim/issues/701
==============================================================================
10. Timestamps *timestamp* *timestamps*
diff --git a/runtime/doc/eval.txt b/runtime/doc/eval.txt
index 0778cf6122..46ee28a461 100644
--- a/runtime/doc/eval.txt
+++ b/runtime/doc/eval.txt
@@ -2811,7 +2811,7 @@ exists({expr}) The result is a Number, which is non-zero if {expr} is
For checking for a supported feature use |has()|.
Examples: >
- exists("&shortname")
+ exists("&mouse")
exists("$HOSTNAME")
exists("*strftime")
exists("*s:MyFunc")
@@ -5604,7 +5604,6 @@ setwinvar({nr}, {varname}, {val}) *setwinvar()*
sha256({string}) *sha256()*
Returns a String with 64 hex charactes, which is the SHA256
checksum of {string}.
- {only available when compiled with the |+cryptv| feature}
shellescape({string} [, {special}]) *shellescape()*
Escape {string} for use as a shell command argument.
@@ -6667,7 +6666,6 @@ arp Compiled with ARP support (Amiga).
autocmd Compiled with autocommand support. |autocommand|
balloon_eval Compiled with |balloon-eval| support.
balloon_multiline GUI supports multiline balloons.
-beos BeOS version of Vim.
browse Compiled with |:browse| support, and browse() will
work.
browsefilter Compiled with support for |browsefilter|.
@@ -6681,7 +6679,6 @@ cmdline_hist Compiled with |cmdline-history| support.
cmdline_info Compiled with 'showcmd' and 'ruler' support.
comments Compiled with |'comments'| support.
compatible Compiled to be very Vi compatible.
-cryptv Compiled with encryption support |encryption|.
cscope Compiled with |cscope| support.
debug Compiled with "DEBUG" defined.
dialog_con Compiled with console dialog support.
@@ -6691,7 +6688,6 @@ digraphs Compiled with support for digraphs.
dnd Compiled with support for the "~ register |quote_~|.
dos16 16 bits DOS version of Vim.
dos32 32 bits DOS (DJGPP) version of Vim.
-ebcdic Compiled on a machine with ebcdic character set.
emacs_tags Compiled with support for Emacs tags.
eval Compiled with expression evaluation support. Always
true, of course!
@@ -6718,7 +6714,6 @@ gui_gtk Compiled with GTK+ GUI (any version).
gui_gtk2 Compiled with GTK+ 2 GUI (gui_gtk is also defined).
gui_mac Compiled with Macintosh GUI.
gui_motif Compiled with Motif GUI.
-gui_photon Compiled with Photon GUI.
gui_running Vim is running in the GUI, or it will start soon.
gui_win32 Compiled with MS Windows Win32 GUI.
gui_win32s idem, and Win32s system being used (Windows 3.1)
diff --git a/runtime/doc/filetype.txt b/runtime/doc/filetype.txt
index 94454fb469..2894814025 100644
--- a/runtime/doc/filetype.txt
+++ b/runtime/doc/filetype.txt
@@ -34,9 +34,8 @@ if you didn't do that already.
Detail: The ":filetype on" command will load one of these files:
Amiga $VIMRUNTIME/filetype.vim
- Mac $VIMRUNTIME:filetype.vim
+ Mac $VIMRUNTIME/filetype.vim
MS-DOS $VIMRUNTIME\filetype.vim
- RiscOS Vim:Filetype
Unix $VIMRUNTIME/filetype.vim
VMS $VIMRUNTIME/filetype.vim
This file is a Vim script that defines autocommands for the
@@ -268,38 +267,6 @@ the 'runtimepath' for a directory to use. If there isn't one, set
'runtimepath' in the |system-vimrc|. Be careful to keep the default
directories!
-
- *autocmd-osfiletypes*
-NOTE: this code is currently disabled, as the RISC OS implementation was
-removed. In the future this will use the 'filetype' option.
-
-On operating systems which support storing a file type with the file, you can
-specify that an autocommand should only be executed if the file is of a
-certain type.
-
-The actual type checking depends on which platform you are running Vim
-on; see your system's documentation for details.
-
-To use osfiletype checking in an autocommand you should put a list of types to
-match in angle brackets in place of a pattern, like this: >
-
- :au BufRead *.html,<&faf;HTML> runtime! syntax/html.vim
-
-This will match:
-
-- Any file whose name ends in ".html"
-- Any file whose type is "&faf" or "HTML", where the meaning of these types
- depends on which version of Vim you are using.
- Unknown types are considered NOT to match.
-
-You can also specify a type and a pattern at the same time (in which case they
-must both match): >
-
- :au BufRead <&fff>diff*
-
-This will match files of type "&fff" whose names start with "diff".
-
-
*plugin-details*
The "plugin" directory can be in any of the directories in the 'runtimepath'
option. All of these directories will be searched for plugins and they are
diff --git a/runtime/doc/gui.txt b/runtime/doc/gui.txt
index bdddec585d..c174914c54 100644
--- a/runtime/doc/gui.txt
+++ b/runtime/doc/gui.txt
@@ -24,9 +24,7 @@ Other GUI documentation:
1. Starting the GUI *gui-start* *E229* *E233*
First you must make sure you actually have a version of Vim with the GUI code
-included. You can check this with the ":version" command, it says "with xxx
-GUI", where "xxx" is X11-Motif, X11-Athena, Photon, GTK, GTK2, etc., or
-"MS-Windows 32 bit GUI version".
+included.
How to start the GUI depends on the system used. Mostly you can run the
GUI version of Vim with:
@@ -690,13 +688,10 @@ because the item will never be selected. Use a single colon to keep it
simple.
*gui-toolbar*
-The toolbar is currently available in the Win32, Athena, Motif, GTK+ (X11),
-and Photon GUI. It should turn up in other GUIs in due course. The
-default toolbar is setup in menu.vim.
-The display of the toolbar is controlled by the 'guioptions' letter 'T'. You
-can thus have menu & toolbar together, or either on its own, or neither.
-The appearance is controlled by the 'toolbar' option. You can choose between
-an image, text or both.
+The default toolbar is setup in menu.vim. The display of the toolbar is
+controlled by the 'guioptions' letter 'T'. You can thus have menu & toolbar
+together, or either on its own, or neither. The appearance is controlled by
+the 'toolbar' option. You can choose between an image, text or both.
*toolbar-icon*
The toolbar is defined as a special menu called ToolBar, which only has one
@@ -779,9 +774,9 @@ from the main menu bar. You must then use the |:popup| or |:tearoff| command
to display it.
*popup-menu*
-In the Win32, GTK+, Motif, Athena and Photon GUI, you can define the
-special menu "PopUp". This is the menu that is displayed when the right mouse
-button is pressed, if 'mousemodel' is set to popup or popup_setpos.
+You can define the special menu "PopUp". This is the menu that is displayed
+when the right mouse button is pressed, if 'mousemodel' is set to popup or
+popup_setpos.
5.3 Showing What Menus Are Mapped To *showing-menus*
diff --git a/runtime/doc/index.txt b/runtime/doc/index.txt
index 6792acd390..01ec37b5a0 100644
--- a/runtime/doc/index.txt
+++ b/runtime/doc/index.txt
@@ -1072,7 +1072,6 @@ tag command action ~
|:@@| :@@ repeat the previous ":@"
|:Next| :N[ext] go to previous file in the argument list
|:Print| :P[rint] print lines
-|:X| :X ask for encryption key
|:append| :a[ppend] append text
|:abbreviate| :ab[breviate] enter abbreviation
|:abclear| :abc[lear] remove all abbreviations
diff --git a/runtime/doc/insert.txt b/runtime/doc/insert.txt
index 60454fa8e1..8126a5b458 100644
--- a/runtime/doc/insert.txt
+++ b/runtime/doc/insert.txt
@@ -1972,7 +1972,6 @@ self explanatory. Using the long or the short version depends on the
possible
[converted] conversion from 'fileencoding' to
'encoding' done
- [crypted] file was decrypted
[READ ERRORS] not all of the file could be read
diff --git a/runtime/doc/manpages/vim.1 b/runtime/doc/manpages/vim.1
index 820caa24f5..59f21e1b9b 100644
--- a/runtime/doc/manpages/vim.1
+++ b/runtime/doc/manpages/vim.1
@@ -395,9 +395,6 @@ If the {scriptout} file exists, characters are appended.
\-W {scriptout}
Like \-w, but an existing file is overwritten.
.TP
-\-x
-Use encryption when writing files. Will prompt for a crypt key.
-.TP
\-X
Don't connect to the X server. Shortens startup time in a terminal, but the
window title and clipboard will not be used.
diff --git a/runtime/doc/mbyte.txt b/runtime/doc/mbyte.txt
index 87ae8777c2..2a5ccc626e 100644
--- a/runtime/doc/mbyte.txt
+++ b/runtime/doc/mbyte.txt
@@ -276,8 +276,7 @@ u Unicode Universal encoding, can replace all others. ISO 10646.
Other encodings cannot be used by Vim internally. But files in other
encodings can be edited by using conversion, see 'fileencoding'.
-Note that all encodings must use ASCII for the characters up to 128 (except
-when compiled for EBCDIC).
+Note that all encodings must use ASCII for the characters up to 128.
Supported 'encoding' values are: *encoding-values*
1 latin1 8-bit characters (ISO 8859-1, also used for cp1252)
diff --git a/runtime/doc/nvim_clipboard.txt b/runtime/doc/nvim_clipboard.txt
index cf38dea3d6..cf63685499 100644
--- a/runtime/doc/nvim_clipboard.txt
+++ b/runtime/doc/nvim_clipboard.txt
@@ -6,25 +6,27 @@
Clipboard integration for Nvim *nvim-clipboard*
-Nvim has no connection to the system clipboard, instead it is accessible
-through the |nvim-provider| infrastructure which transparently uses shell
-commands for communicating with the clipboard.
+Nvim has no direct connection to the system clipboard. Instead, it is
+accessible through the |nvim-provider| infrastructure, which transparently
+uses shell commands for communicating with the clipboard.
-To use clipboard on Nvim, make sure you have one of the following programs
-installed and available on $PATH:
+Clipboard access is implicitly enabled if any of the following clipboard tools
+is found in your `$PATH`.
- xclip
-- xsel(newer alternative to xclip)
-- pbcopy/pbpaste(already available on Mac OS X)
+- xsel (newer alternative to xclip)
+- pbcopy/pbpaste (only for Mac OS X)
-Having any of these programs should enable the '+' and '*' registers. As an
-optional step, set the 'unnamedclip' option to transparently access clipboard
-using the unnamed register. If you use the same |vimrc| for both Vim and Nvim,
-make sure you only set the option when `has('nvim')` is true:
+The presence of a suitable clipboard tool implicitly enables the '+' and '*'
+registers.
+
+If you want to ALWAYS use the clipboard for ALL operations (as opposed
+to interacting with the '+' and/or '*' registers explicitly), set the
+following option:
>
- if has('nvim')
- set unnamedclip
- endif
+ set clipboard+=unnamedplus
<
+See 'clipboard' for details and more options.
+
==============================================================================
vim:tw=78:ts=8:noet:ft=help:norl:
diff --git a/runtime/doc/nvim_intro.txt b/runtime/doc/nvim_intro.txt
index 8a82a09890..d6389a815d 100644
--- a/runtime/doc/nvim_intro.txt
+++ b/runtime/doc/nvim_intro.txt
@@ -17,7 +17,7 @@ differentiate Nvim from Vim:
2. Job control |job-control|
3. Python plugins |nvim-python|
4. Clipboard integration |nvim-clipboard|
-5. Remote plugins |remote-plugin|
+5. Remote plugins |remote-plugin|
6. Provider infrastructure |nvim-provider|
==============================================================================
diff --git a/runtime/doc/nvim_provider.txt b/runtime/doc/nvim_provider.txt
index e67a5c174c..2ab0510a3b 100644
--- a/runtime/doc/nvim_provider.txt
+++ b/runtime/doc/nvim_provider.txt
@@ -25,7 +25,7 @@ examples of integration with external systems that are implemented in Vim and
are now decoupled from Nvim core as providers:
The first example is clipboard integration: On the original Vim source code,
-clipboard functions account for more than 1k lines of C source code(and that
+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
simple shell commands such as xclip or pbcopy/pbpaste.
@@ -57,21 +57,20 @@ What these functions do is simple:
implemented, and is called by the "has" vimscript function to check if
features are available.
-The basic idea is that the provider#(name)#Call function should implement
+The basic idea is that the provider#(name)#Call function should implement
integration with an external system, because calling shell commands and
-|msgpack-rpc| clients(Nvim only) is easier to do in vimscript.
+|msgpack-rpc| clients (Nvim only) is easier to do in vimscript.
-Now, back to the python example. Instead of modifying vimscript to allow the
-definition of lowercase functions and commands(for the |:python|, |:pyfile|
-and |:pydo| commands, and the |pyeval()| function), which would break
-backwards compatibility with Vim, we implemented the
+Now, back to the python example. Instead of modifying vimscript to allow for
+the definition of lowercase functions and commands (for the |:python|,
+|:pyfile|, and |:pydo| commands, and the |pyeval()| function), which would
+break backwards compatibility with Vim, we implemented the
autoload/provider/python.vim script and the provider#python#Call function
that is only defined if an external python host is started successfully.
-That works well with the has('python') expression (normally used by python
+That works well with the `has('python')` expression (normally used by python
plugins) because if the python host isn't installed then the plugin will
-"think" it is running in a Vim compiled without +python feature.
-
+"think" it is running in a Vim compiled without |+python| feature.
==============================================================================
vim:tw=78:ts=8:noet:ft=help:norl:
diff --git a/runtime/doc/nvim_python.txt b/runtime/doc/nvim_python.txt
index e60cc93b19..486c25edd0 100644
--- a/runtime/doc/nvim_python.txt
+++ b/runtime/doc/nvim_python.txt
@@ -13,16 +13,16 @@ Python plugins and scripting in Nvim *nvim-python*
1. Introduction *nvim-python-intro*
Through an external python interpreter connected via |msgpack-rpc|, Nvim
-offers some support for the classic |python-vim| interface. For now only the
+offers some support for the legacy |python-vim| interface. For now only the
old Vim 7.3 API is supported.
==============================================================================
2. Quickstart *nvim-python-quickstart*
-If you just want to start using python plugins with Nvim quickly, here's a
-simple step-by-step:
+If you just want to start using Vim python plugins with Nvim quickly, here's a
+simple tutorial:
-- Make sure python 2.6 or 2.7 is available on your `$PATH`
+- Make sure python 2.6 or 2.7 is available in your `$PATH`
- Install the `neovim` python package:
>
$ pip install neovim
diff --git a/runtime/doc/options.txt b/runtime/doc/options.txt
index 813ed83be4..c646caae4f 100644
--- a/runtime/doc/options.txt
+++ b/runtime/doc/options.txt
@@ -1413,9 +1413,6 @@ A jump table for the options with a short description can be found at |Q_op|.
Note that v:fname_in and v:fname_out will never be the same.
Note that v:charconvert_from and v:charconvert_to may be different
from 'encoding'. Vim internally uses UTF-8 instead of UCS-2 or UCS-4.
- Encryption is not done by Vim when using 'charconvert'. If you want
- to encrypt the file after conversion, 'charconvert' should take care
- of this.
This option cannot be set from a |modeline| or in the |sandbox|, for
security reasons.
@@ -2197,36 +2194,8 @@ A jump table for the options with a short description can be found at |Q_op|.
variables overrule the terminal size values obtained
with system specific functions.
-
*'cryptmethod'* *'cm'*
-'cryptmethod' string (default "zip")
- global or local to buffer |global-local|
- {not in Vi}
- Method used for encryption when the buffer is written to a file:
- *pkzip*
- zip PkZip compatible method. A weak kind of encryption.
- Backwards compatible with Vim 7.2 and older.
- *blowfish*
- blowfish Blowfish method. Strong encryption. Requires Vim 7.3
- or later, files can NOT be read by Vim 7.2 and older.
- This adds a "seed" to the file, every time you write
- the file the encrypted bytes will be different.
-
- When reading an encrypted file 'cryptmethod' will be set automatically
- to the detected method of the file being read. Thus if you write it
- without changing 'cryptmethod' the same method will be used.
- Changing 'cryptmethod' does not mark the file as modified, you have to
- explicitly write it, you don't get a warning unless there are other
- modifications. Also see |:X|.
-
- When setting the global value to an empty string, it will end up with
- the value "zip". When setting the local value to an empty string the
- buffer will use the global value.
-
- When a new encryption method is added in a later version of Vim, and
- the current version does not recognize it, you will get *E821* .
- You need to edit this file with the later version of Vim.
-
+'cryptmethod' Removed. {Nvim}
*'cscopepathcomp'* *'cspc'*
'cscopepathcomp' 'cspc' number (default 0)
@@ -3482,7 +3451,7 @@ A jump table for the options with a short description can be found at |Q_op|.
the case of X). The font names given should be "normal" fonts. Vim
will try to find the related bold and italic fonts.
- For Win32, GTK, Motif, Mac OS and Photon: >
+ For Win32, GTK, Motif, and Mac OS: >
:set guifont=*
< will bring up a font requester, where you can pick the font you want.
@@ -3679,7 +3648,7 @@ A jump table for the options with a short description can be found at |Q_op|.
't' Include tearoff menu items. Currently only works for Win32,
GTK+, and Motif 1.2 GUI.
*'go-T'*
- 'T' Include Toolbar. Currently only in Win32, GTK+, Motif, Photon
+ 'T' Include Toolbar. Currently only in Win32, GTK+, Motif,
and Athena GUIs.
*'go-r'*
'r' Right-hand scrollbar is always present.
@@ -4296,7 +4265,6 @@ A jump table for the options with a short description can be found at |Q_op|.
"@,48-57,/,\,.,-,_,+,,,#,$,%,{,},[,],:,@-@,!,~,="
for AMIGA: "@,48-57,/,.,-,_,+,,,$,:"
for VMS: "@,48-57,/,.,-,_,+,,,#,$,%,<,>,[,],:,;,~"
- for OS/390: "@,240-249,/,.,-,_,+,,,#,$,%,~,="
otherwise: "@,48-57,/,.,-,_,+,,,#,$,%,~,=")
global
{not in Vi}
@@ -4420,23 +4388,8 @@ A jump table for the options with a short description can be found at |Q_op|.
Otherwise only one space is inserted.
NOTE: This option is set when 'compatible' is set.
- *'key'*
-'key' string (default "")
- local to buffer
- {not in Vi}
- {only available when compiled with the |+cryptv|
- feature}
- The key that is used for encrypting and decrypting the current buffer.
- See |encryption| and 'cryptmethod'.
- Careful: Do not set the key value by hand, someone might see the typed
- key. Use the |:X| command. But you can make 'key' empty: >
- :set key=
-< It is not possible to get the value of this option with ":set key" or
- "echo &key". This is to avoid showing it to someone who shouldn't
- know. It also means you cannot see it yourself once you have set it,
- be careful not to make a typing error!
- You can use "&key" in an expression to detect whether encryption is
- enabled. When 'key' is set it returns "*****" (five stars).
+ *'key'*
+'key' Removed. {Nvim}
*'keymap'* *'kmp'* *E544*
'keymap' 'kmp' string (default "")
@@ -5250,14 +5203,6 @@ A jump table for the options with a short description can be found at |Q_op|.
This option cannot be set from a |modeline| or in the |sandbox|, for
security reasons.
-
- *'osfiletype'* *'oft'*
-'osfiletype' 'oft' string (default: "")
- local to buffer
- {not in Vi}
- This option was supported on RISC OS, which has been removed.
-
-
*'paragraphs'* *'para'*
'paragraphs' 'para' string (default "IPLPPPQPP TPHPLIPpLpItpplpipbp")
global
@@ -5742,9 +5687,6 @@ A jump table for the options with a short description can be found at |Q_op|.
Macintosh: "$VIM:vimfiles,
$VIMRUNTIME,
$VIM:vimfiles:after"
- RISC-OS: "Choices:vimfiles,
- $VIMRUNTIME,
- Choices:vimfiles/after"
VMS: "sys$login:vimfiles,
$VIM/vimfiles,
$VIMRUNTIME,
@@ -6255,17 +6197,7 @@ A jump table for the options with a short description can be found at |Q_op|.
set and to the Vim default value when 'compatible' is reset.
*'shortname'* *'sn'* *'noshortname'* *'nosn'*
-'shortname' 'sn' boolean (default off)
- local to buffer
- {not in Vi, not in MS-DOS versions}
- Filenames are assumed to be 8 characters plus one extension of 3
- characters. Multiple dots in file names are not allowed. When this
- option is on, dots in file names are replaced with underscores when
- adding an extension (".~" or ".swp"). This option is not available
- for MS-DOS, because then it would always be on. This option is useful
- when editing files on an MS-DOS compatible filesystem, e.g., messydos
- or crossdos. When running the Win32 GUI version under Win32s, this
- option is always on by default.
+'shortname' 'sn' Removed. {Nvim}
*'showbreak'* *'sbr'* *E595*
'showbreak' 'sbr' string (default "")
@@ -7126,7 +7058,6 @@ A jump table for the options with a short description can be found at |Q_op|.
'term' string (default is $TERM, if that fails:
in the GUI: "builtin_gui"
on Amiga: "amiga"
- on BeOS: "beos-ansi"
on Mac: "mac-ansi"
on MS-DOS: "pcterm"
on Unix: "ansi"
@@ -7390,8 +7321,7 @@ A jump table for the options with a short description can be found at |Q_op|.
*'toolbar'* *'tb'*
'toolbar' 'tb' string (default "icons,tooltips")
global
- {only for |+GUI_GTK|, |+GUI_Athena|, |+GUI_Motif| and
- |+GUI_Photon|}
+ {only for |+GUI_GTK|, |+GUI_Athena|, and |+GUI_Motif|}
The contents of this option controls various toolbar settings. The
possible values are:
icons Toolbar buttons are shown with icons.
@@ -7603,13 +7533,6 @@ A jump table for the options with a short description can be found at |Q_op|.
Note that this causes the whole buffer to be stored in memory. Set
this option to a lower value if you run out of memory.
- {Nvim} *'unnamedclip'* *ucp'*
-'unnamedclip' 'ucp' boolean (default off)
- global
- Use the unnamed register to access the clipboard(when available).
- This option has the same effect of setting 'clipboard' to
- 'unnamed/unnamedplus' in Vim.
-
*'updatecount'* *'uc'*
'updatecount' 'uc' number (default: 200)
global
@@ -7675,8 +7598,7 @@ A jump table for the options with a short description can be found at |Q_op|.
"$VIM/vimfiles/view",
for Unix: "~/.vim/view",
for Macintosh: "$VIM:vimfiles:view"
- for VMS: "sys$login:vimfiles/view"
- for RiscOS: "Choices:vimfiles/view")
+ for VMS: "sys$login:vimfiles/view")
global
{not in Vi}
{not available when compiled without the |+mksession|
@@ -8070,7 +7992,7 @@ A jump table for the options with a short description can be found at |Q_op|.
'winaltkeys' 'wak' string (default "menu")
global
{not in Vi}
- {only used in Win32, Motif, GTK and Photon GUI}
+ {only used in Win32, Motif, and GTK}
Some GUI versions allow the access to menu entries by using the ALT
key in combination with a character that appears underlined in the
menu. This conflicts with the use of the ALT key for mappings and
diff --git a/runtime/doc/os_mac.txt b/runtime/doc/os_mac.txt
index 9ed23b4ae1..67790f1dea 100644
--- a/runtime/doc/os_mac.txt
+++ b/runtime/doc/os_mac.txt
@@ -54,7 +54,7 @@ algorithm is used:
You can use the |$VIM| and |$VIMRUNTIME| variable. >
- :so $VIMRUNTIME:syntax:syntax.vim
+ :so $VIMRUNTIME/syntax/syntax.vim
==============================================================================
2. .vimrc and .vim files *mac-vimfile*
diff --git a/runtime/doc/print.txt b/runtime/doc/print.txt
index 5fcaa6f624..0ffc661c95 100644
--- a/runtime/doc/print.txt
+++ b/runtime/doc/print.txt
@@ -96,8 +96,7 @@ If the option is empty, then vim will use the system default printer for
Windows: cp1252,
Macintosh: mac-roman,
VMS: dec-mcs,
- HPUX: hp-roman8,
- EBCDIC: ebcdic-uk)
+ HPUX: hp-roman8)
global
Sets the character encoding used when printing. This option tells VIM which
print character encoding file from the "print" directory in 'runtimepath' to
@@ -121,10 +120,9 @@ other than latin1 will require VIM to be compiled with the |+iconv| feature.
If no conversion is possible then printing will fail. Any characters that
cannot be converted will be replaced with upside down question marks.
-Four print character encoding files are provided to support default Mac, VMS,
-HPUX, and EBCDIC character encodings and are used by default on these
-platforms. Code page 1252 print character encoding is used by default on
-the Windows platform.
+Three print character encoding files are provided to support default Mac, VMS,
+and HPUX character encodings and are used by default on these platforms. Code
+page 1252 print character encoding is used by default on the Windows platform.
*pexpr-option*
'printexpr' 'pexpr' String (default: see below)
diff --git a/runtime/doc/quickref.txt b/runtime/doc/quickref.txt
index a332b6fcc9..d320e6cd24 100644
--- a/runtime/doc/quickref.txt
+++ b/runtime/doc/quickref.txt
@@ -653,7 +653,6 @@ Short explanation of each option: *option-list*
'confirm' 'cf' ask what to do about unsaved/read-only files
'copyindent' 'ci' make 'autoindent' use existing indent structure
'cpoptions' 'cpo' flags for Vi-compatible behavior
-'cryptmethod' 'cm' type of encryption to use for file writing
'cscopepathcomp' 'cspc' how many components of the path to show
'cscopeprg' 'csprg' command to execute cscope
'cscopequickfix' 'csqf' use quickfix window for cscope results
@@ -756,7 +755,6 @@ Short explanation of each option: *option-list*
'iskeyword' 'isk' characters included in keywords
'isprint' 'isp' printable characters
'joinspaces' 'js' two spaces after a period with a join command
-'key' encryption key
'keymap' 'kmp' name of a keyboard mapping
'keymodel' 'km' enable starting/stopping selection with keys
'keywordprg' 'kp' program to use for the "K" command
@@ -804,7 +802,6 @@ Short explanation of each option: *option-list*
'omnifunc' 'ofu' function for filetype-specific completion
'opendevice' 'odev' allow reading/writing devices on MS-Windows
'operatorfunc' 'opfunc' function to be called for |g@| operator
-'osfiletype' 'oft' no longer supported
'paragraphs' 'para' nroff macros that separate paragraphs
'paste' allow pasting text
'pastetoggle' 'pt' key code that causes 'paste' to toggle
@@ -859,7 +856,6 @@ Short explanation of each option: *option-list*
'shiftround' 'sr' round indent to multiple of shiftwidth
'shiftwidth' 'sw' number of spaces to use for (auto)indent step
'shortmess' 'shm' list of flags, reduce length of messages
-'shortname' 'sn' non-MS-DOS: Filenames assumed to be 8.3 chars
'showbreak' 'sbr' string to use at the start of wrapped lines
'showcmd' 'sc' show (partial) command in status line
'showfulltag' 'sft' show full tag pattern when completing tag
diff --git a/runtime/doc/recover.txt b/runtime/doc/recover.txt
index 75318b00e6..570340cf0c 100644
--- a/runtime/doc/recover.txt
+++ b/runtime/doc/recover.txt
@@ -33,20 +33,13 @@ with the extension ".swp".
- On Unix, a '.' is prepended to swap file names in the same directory as the
edited file. This avoids that the swap file shows up in a directory
listing.
-- On MS-DOS machines and when the 'shortname' option is on, any '.' in the
- original file name is replaced with '_'.
- If this file already exists (e.g., when you are recovering from a crash) a
warning is given and another extension is used, ".swo", ".swn", etc.
- An existing file will never be overwritten.
- The swap file is deleted as soon as Vim stops editing the file.
-Technical: The replacement of '.' with '_' is done to avoid problems with
- MS-DOS compatible filesystems (e.g., crossdos, multidos). If Vim
- is able to detect that the file is on an MS-DOS-like filesystem, a
- flag is set that has the same effect as the 'shortname' option.
- This flag is reset when you start editing another file.
*E326*
- If the ".swp" file name already exists, the last character is
+Technical: If the ".swp" file name already exists, the last character is
decremented until there is no file with that name or ".saa" is
reached. In the last case, no swap file is created.
@@ -196,42 +189,4 @@ will continue to get warning messages that the ".swp" file already exists.
{Vi: recovers in another way and sends mail if there is something to recover}
-ENCRYPTION AND THE SWAP FILE *:recover-crypt*
-
-When the text file is encrypted the swap file is encrypted as well. This
-makes recovery a bit more complicated. When recovering from a swap file and
-encryption has been used, you will be asked to enter one or two crypt keys.
-
-If the text file does not exist you will only be asked to enter the crypt key
-for the swap file.
-
-If the text file does exist, it may be encrypted in a different way than the
-swap file. You will be asked for the crypt key twice:
-
- Need encryption key for "/tmp/tt" ~
- Enter encryption key: ****** ~
- "/tmp/tt" [crypted] 23200L, 522129C ~
- Using swap file "/tmp/.tt.swp" ~
- Original file "/tmp/tt" ~
- Swap file is encrypted: "/tmp/.tt.swp" ~
- If you entered a new crypt key but did not write the text file, ~
- enter the new crypt key. ~
- If you wrote the text file after changing the crypt key press enter ~
- to use the same key for text file and swap file ~
- Enter encryption key: ~
-
-You can be in one of these two situations:
-
-1. The encryption key was not changed, or after changing the key the text file
- was written. You will be prompted for the crypt key twice. The second
- time you can simply press Enter. That means the same key is used for the
- text file and the swap file.
-2. You entered a new encryption key, but did not save the text file. Vim will
- then use the new key for the swap file, and the text file will still be
- encrypted with the old key. At the second prompt enter the new key.
-
-Note that after recovery the key of the swap file will be used for the text
-file. Thus if you write the text file, you need to use that new key.
-
-
vim:tw=78:ts=8:ft=help:norl:
diff --git a/runtime/doc/remote_plugin.txt b/runtime/doc/remote_plugin.txt
index ca7e763d1b..e5d1efcc96 100644
--- a/runtime/doc/remote_plugin.txt
+++ b/runtime/doc/remote_plugin.txt
@@ -14,12 +14,12 @@ Nvim support for remote plugins *remote-plugin*
==============================================================================
1. Introduction *remote-plugin-intro*
-A big Nvim goal is to allow extensibility in arbitrary programming languages
-without requiring direct support from the editor. This is achieved with
-remote plugins, coprocesses that have a direct communication channel(via
+Extensibility is a primary goal of Nvim. Any programming language may be used
+to extend nvim without changes to nvim itself. This is achieved with remote
+plugins, coprocesses that have a direct communication channel (via
|msgpack-rpc|) with the Nvim process.
-Even though these plugins are running in separate processes, they can call, be
+Even though these plugins are running in separate processes they can call, be
called, and receive events just as if the code was being executed in the main
process.
@@ -27,24 +27,24 @@ process.
2. Plugin hosts *remote-plugin-hosts*
While plugins can be implemented as arbitrary programs that communicate
-directly with Nvim API and are called via |rpcrequest()| and |rpcnotify()|,
-that is not the best approach available. Instead, developers should first
-check if a plugin host implementation is available for their favorite
-programming language.
+directly with the high-level Nvim API and are called via |rpcrequest()| and
+|rpcnotify()|, that is not the best approach available. Instead, developers
+should first check if a plugin host implementation is available for their
+chosen programming language.
Plugin hosts are programs that provide a high level environment for plugins,
-and also take care of most boilerplate involved in defining commands, autocmds
-and functions that are implemented over msgpack-rpc connections. They are
-loaded the first time one of its registered plugins are required, keeping
-Nvim startup as fast a possible despite the number of installed plugins/hosts.
+taking care of most boilerplate involved in defining commands, autocmds, and
+functions that are implemented over |msgpack-rpc| connections. Hosts are
+loaded only when one of their registered plugins require it, keeping Nvim's
+startup as fast as possible if many plugins/hosts are installed.
==============================================================================
3. Example *remote-plugin-example*
The best way to learn about remote plugins is with an example, so let's see
-how a very useless python plugin looks like. This plugin exports a command, a
-function and an autocmd. The plugin is called 'Limit', and all it does is
-limit the number of requests made to it. Here's the plugin source code:
+what a python plugin looks like. This plugin exports a command, a function and
+an autocmd. The plugin is called 'Limit', and all it does is limit the number
+of requests made to it. Here's the plugin source code:
>
import neovim
@@ -53,7 +53,7 @@ limit the number of requests made to it. Here's the plugin source code:
def __init__(self, vim):
self.vim = vim
self.calls = 0
-
+
@neovim.command('Cmd', range='', nargs='*', sync=True)
def command_handler(self, args, range):
self._increment_calls()
@@ -61,76 +61,75 @@ limit the number of requests made to it. Here's the plugin source code:
'Command: Called %d times, args: %s, range: %s' % (self.calls,
args,
range))
-
+
@neovim.autocmd('BufEnter', pattern='*.py', eval='expand("<afile>")',
sync=True)
def autocmd_handler(self, filename):
self._increment_calls()
self.vim.current.line = (
'Autocmd: Called %s times, file: %s' % (self.calls, filename))
-
+
@neovim.function('Func')
def function_handler(self, args):
self._increment_calls()
self.vim.current.line = (
'Function: Called %d times, args: %s' % (self.calls, args))
-
+
def _increment_calls(self):
if self.calls == 5:
raise Exception('Too many calls!')
self.calls += 1
<
-As can be seen, the plugin is implemented using pure python idioms(classes,
-methods and decorators), the translation between these language-specific
-idioms to vimscript occurs while the plugin manifest is being generated(see
+As can be seen, the plugin is implemented using pure python idioms (classes,
+methods, and decorators), the translation between these language-specific
+idioms to vimscript occurs while the plugin manifest is being generated (see
below).
Notice that the exported command and autocmd are defined with the "sync" flag,
which affects how Nvim calls the plugin: with "sync" the |rpcrequest()|
function is used, which will block Nvim until the handler function returns a
value. Without the "sync" flag, the call is made using a fire and forget
-approach with |rpcnotify()|(return values or exceptions raised in the handler
-function are ignored)
+approach with |rpcnotify()| (return values or exceptions raised in the handler
+function are ignored).
To test the above plugin, it must be saved in "rplugin/python" in a
-'runtimepath' directory(~/.nvim/rplugin/python/limit.py for example).
-Then, the remote plugin manifest must be generated with
-`:UpdateRemotePlugins`.
+'runtimepath' directory (~/.nvim/rplugin/python/limit.py for example). Then,
+the remote plugin manifest must be generated with `:UpdateRemotePlugins`.
==============================================================================
-4. remote plugin manifest *remote-plugin-manifest*
+4. Remote plugin manifest *remote-plugin-manifest*
-Just installing remote plugins to "rplugin/{host}" isn't enough to
-load them at startup. The `:UpdateRemotePlugins` command must be executed
-every time a remote plugin is installed, updated, or deleted.
+Just installing remote plugins to "rplugin/{host}" isn't enough for them to be
+automatically loaded when required. The `:UpdateRemotePlugins` command must be
+executed every time a remote plugin is installed, updated, or deleted.
`:UpdateRemotePlugins` will generate the remote plugin manifest, a special
vimscript file containing declarations for all vimscript entities
(commands/autocommands/functions) defined by all remote plugins, with each
entity associated with the host and plugin path. The manifest can be seen as a
-generated extension to the user's vimrc(it even has the vimrc filename
+generated extension to the user's vimrc (it even has the vimrc filename
prepended).
The manifest declarations are nothing but calls to the remote#host#RegisterPlugin
function, which will take care of bootstrapping the host as soon as the
-declared command, autocommand or function is used for the first time.
+declared command, autocommand, or function is used for the first time.
-The manifest generation step is necessary to keep editor startup fast in
-situations where a user has remote plugins with different hosts. For
-example, imagine a user that has three plugins, for python, java and .NET
-hosts respectively, if we were to load all three plugins at startup, then
-three language runtimes would also be spawned which could take seconds!
+The manifest generation step is necessary to keep Nvim's startup fast in
+situations where a user has remote plugins with different hosts. For example,
+say a user has three plugins, for python, java and .NET hosts respectively. If
+we were to load all three plugins at startup, then three language runtimes
+would also be spawned which could take seconds!
With the manifest, each host will only be loaded when required. Continuing
-with the example, imagine the java plugin is a semantic completion engine for
-java files, if it defines an BufEnter *.java autocommand then the java host
-will only be spawned when java source files are loaded.
-
-If the explicit call to `:UpdateRemotePlugins` seems incovenient, try
-to see it like this: Its a way to give IDE-like capabilities to nvim while
-still keeping it a fast/lightweight editor for general use. It can also be
-seen as an analogous to the |:helptags| facility.
+with the example, say the java plugin is a semantic completion engine for java
+source files. If it defines the autocommand "BufEnter *.java", then the java
+host will only be spawned when files ending with ".java" are loaded.
+
+If the explicit call to `:UpdateRemotePlugins` seems incovenient, try to see
+it like this: It's a way to give IDE-like capabilities to nvim while still
+keeping it fast and lightweight for general use. It can also be seen as
+analogous to the |:helptags| facility.
==============================================================================
vim:tw=78:ts=8:noet:ft=help:norl:
diff --git a/runtime/doc/spell.txt b/runtime/doc/spell.txt
index 3ffd8932e1..91322def5b 100644
--- a/runtime/doc/spell.txt
+++ b/runtime/doc/spell.txt
@@ -336,8 +336,6 @@ If 'encoding' is "latin1" Vim will look for:
This assumes none of them are found (Polish doesn't make sense when leaving
out the non-ASCII characters).
-Spelling for EBCDIC is currently not supported.
-
A spell file might not be available in the current 'encoding'. See
|spell-mkspell| about how to create a spell file. Converting a spell file
with "iconv" will NOT work!
diff --git a/runtime/doc/starting.txt b/runtime/doc/starting.txt
index d002a3a4ab..bceaea0d83 100644
--- a/runtime/doc/starting.txt
+++ b/runtime/doc/starting.txt
@@ -482,14 +482,6 @@ a slash. Thus "-R" means recovery and "-/R" readonly.
":rv" or ":wv" are used. See also |viminfo-file|.
{not in Vi}
- *-x*
--x Use encryption to read/write files. Will prompt for a key,
- which is then stored in the 'key' option. All writes will
- then use this key to encrypt the text. The '-x' argument is
- not needed when reading a file, because there is a check if
- the file that is being read has been encrypted, and Vim asks
- for a key automatically. |encryption|
-
*-X*
-X Do not try connecting to the X server to get the current
window title and copy/paste using the X clipboard. This
@@ -775,7 +767,7 @@ accordingly. Vim proceeds in this order:
a. If vim was started as |evim| or |eview| or with the |-y| argument, the
script $VIMRUNTIME/evim.vim will be loaded.
*system-vimrc*
- b. For Unix, MS-DOS, MS-Windows, VMS, Macintosh, RISC-OS and Amiga
+ b. For Unix, MS-DOS, MS-Windows, VMS, Macintosh, and Amiga,
the system vimrc file is read for initializations. The path of this
file is shown with the ":version" command. Mostly it's "$VIM/vimrc".
Note that this file is ALWAYS read in 'compatible' mode, since the
@@ -1143,10 +1135,10 @@ 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', 'key', 'lines', 'modified', 'scroll', 'term', 'ttyfast' and
-'ttymouse' 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.
+'fileformat', 'lines', 'modified', 'scroll', 'term', 'ttyfast' and 'ttymouse'
+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.
When special keys are used in mappings, The 'cpoptions' option will be
temporarily set to its Vim default, to avoid the mappings to be
diff --git a/runtime/doc/todo.txt b/runtime/doc/todo.txt
index 1cab028bc2..40f30ff077 100644
--- a/runtime/doc/todo.txt
+++ b/runtime/doc/todo.txt
@@ -232,8 +232,6 @@ Go through more coverity reports.
Patch to add ":undorecover", get as much text out of the undo file as
possible. (Christian Brabandt, 2014 Mar 12)
-Include Haiku port? (Adrien Destugues, Siarzhuk Zharski, 2013 Oct 24)
-
Updated spec ftplugin. (Matěj Cepl, 2013 Oct 16)
Some quickfix messages appear twice. (Gary Johnson, 2014 Feb 16)
@@ -2249,7 +2247,7 @@ GUI:
Need better separation of Vim core and GUI code.
8 When fontset support is enabled, setting 'guifont' to a single font
doesn't work.
-8 Menu priority for sub-menus for: Amiga, BeOS.
+8 Menu priority for sub-menus for: Amiga.
8 When translating menus ignore the part after the Tab, the shortcut. So
that the same menu item with a different shortcut (e.g., for the Mac) are
still translated.
@@ -3373,8 +3371,6 @@ Built-in script language:
Patch by Ilya Sher, 2004 Mar 4.
Return a list instead.
char2hex() convert char string to hex string.
- crypt() encrypt string
- decrypt() decrypt string
base64enc() base 64 encoding
base64dec() base 64 decoding
attributes() return file protection flags "drwxrwxrwx"
@@ -3745,7 +3741,7 @@ Win32 GUI:
GUI:
-8 Make inputdialog() work for Photon, Amiga.
+8 Make inputdialog() work for Amiga.
- <C--> cannot be mapped. Should be possible to recognize this as a
normal "-" with the Ctrl modifier.
7 Implement ":popup" for other systems than Windows.
@@ -3824,8 +3820,6 @@ GUI:
Autocommands:
-9 Rework the code from FEAT_OSFILETYPE for autocmd-osfiletypes to use
- 'filetype'. Only for when the current buffer is known.
- Put autocommand event names in a hashtable for faster lookup?
8 When the SwapExists event is triggered, provide information about the
swap file, e.g., whether the process is running, file was modified, etc.
@@ -4819,8 +4813,7 @@ Digraphs:
Writing files:
- In vim_rename(), should lock "from" file when deleting "to" file for
- systems other than Amiga. Avoids problems with unexpected longname to
- shortname conversion.
+ systems other than Amiga.
8 write mch_isdevice() for Amiga, Mac, VMS, etc.
8 When appending to a file, Vim should also make a backup and a 'patchmode'
file.
diff --git a/runtime/doc/undo.txt b/runtime/doc/undo.txt
index 46469b3533..fba981d4a3 100644
--- a/runtime/doc/undo.txt
+++ b/runtime/doc/undo.txt
@@ -256,9 +256,6 @@ message about that when opening a file.
Undo files are normally saved in the same directory as the file. This can be
changed with the 'undodir' option.
-When the file is encrypted, the text in the undo file is also crypted. The
-same key and method is used. |encryption|
-
You can also save and restore undo histories by using ":wundo" and ":rundo"
respectively:
*:wundo* *:rundo*
@@ -321,13 +318,6 @@ Reading an existing undo file may fail for several reasons:
the undo file cannot be used, it would corrupt the text. This also
happens when 'encoding' differs from when the undo file was written.
*E825* The undo file does not contain valid contents and cannot be used.
-*E826* The undo file is encrypted but decryption failed.
-*E827* The undo file is encrypted but this version of Vim does not support
- encryption. Open the file with another Vim.
-*E832* The undo file is encrypted but 'key' is not set, the text file is not
- encrypted. This would happen if the text file was written by Vim
- encrypted at first, and later overwritten by not encrypted text.
- You probably want to delete this undo file.
"Not reading undo file, owner differs"
The undo file is owned by someone else than the owner of the text
file. For safety the undo file is not used.
diff --git a/runtime/doc/usr_05.txt b/runtime/doc/usr_05.txt
index ac377675ee..a409d7e3ce 100644
--- a/runtime/doc/usr_05.txt
+++ b/runtime/doc/usr_05.txt
@@ -317,7 +317,6 @@ Then copy the file to your plugin directory:
Amiga s:vimfiles/plugin
Macintosh $VIM:vimfiles:plugin
Mac OS X ~/.vim/plugin/
- RISC-OS Choices:vimfiles.plugin
Example for Unix (assuming you didn't have a plugin directory yet): >
diff --git a/runtime/doc/usr_11.txt b/runtime/doc/usr_11.txt
index 9935ded48c..ec404f3301 100644
--- a/runtime/doc/usr_11.txt
+++ b/runtime/doc/usr_11.txt
@@ -283,8 +283,6 @@ machines. Therefore, don't rely on Vim always warning you.
If you really don't want to see this message, you can add the 'A' flag to the
'shortmess' option. But it's very unusual that you need this.
-For remarks about encryption and the swap file, see |:recover-crypt|.
-
==============================================================================
*11.4* Further reading
diff --git a/runtime/doc/usr_23.txt b/runtime/doc/usr_23.txt
index 63cbc612de..0578a63ae5 100644
--- a/runtime/doc/usr_23.txt
+++ b/runtime/doc/usr_23.txt
@@ -6,15 +6,13 @@
This chapter is about editing files that are not ordinary files. With Vim you
-can edit files that are compressed or encrypted. Some files need to be
-accessed over the internet. With some restrictions, binary files can be
-edited as well.
+can edit files that are compressed. Some files need to be accessed over the
+internet. With some restrictions, binary files can be edited as well.
|23.1| DOS, Mac and Unix files
|23.2| Files on the internet
-|23.3| Encryption
-|23.4| Binary files
-|23.5| Compressed files
+|23.3| Binary files
+|23.4| Compressed files
Next chapter: |usr_24.txt| Inserting quickly
Previous chapter: |usr_22.txt| Finding the file to edit
@@ -154,89 +152,7 @@ http://.
For more information, also about passwords, see |netrw|.
==============================================================================
-*23.3* Encryption
-
-Some information you prefer to keep to yourself. For example, when writing
-a test on a computer that students also use. You don't want clever students
-to figure out a way to read the questions before the exam starts. Vim can
-encrypt the file for you, which gives you some protection.
- To start editing a new file with encryption, use the "-x" argument to start
-Vim. Example: >
-
- vim -x exam.txt
-
-Vim prompts you for a key used for encrypting and decrypting the file:
-
- Enter encryption key: ~
-
-Carefully type the secret key now. You cannot see the characters you type,
-they will be replaced by stars. To avoid the situation that a typing mistake
-will cause trouble, Vim asks you to enter the key again:
-
- Enter same key again: ~
-
-You can now edit this file normally and put in all your secrets. When you
-finish editing the file and tell Vim to exit, the file is encrypted and
-written.
- When you edit the file with Vim, it will ask you to enter the same key
-again. You don't need to use the "-x" argument. You can also use the normal
-":edit" command. Vim adds a magic string to the file by which it recognizes
-that the file was encrypted.
- If you try to view this file using another program, all you get is garbage.
-Also, if you edit the file with Vim and enter the wrong key, you get garbage.
-Vim does not have a mechanism to check if the key is the right one (this makes
-it much harder to break the key).
-
-
-SWITCHING ENCRYPTION ON AND OFF
-
-To disable the encryption of a file, set the 'key' option to an empty string:
->
- :set key=
-
-The next time you write the file this will be done without encryption.
- Setting the 'key' option to enable encryption is not a good idea, because
-the password appears in the clear. Anyone shoulder-surfing can read your
-password.
- To avoid this problem, the ":X" command was created. It asks you for an
-encryption key, just like the "-x" argument did: >
-
- :X
- Enter encryption key: ******
- Enter same key again: ******
-
-
-LIMITS ON ENCRYPTION
-
-The encryption algorithm used by Vim is weak. It is good enough to keep out
-the casual prowler, but not good enough to keep out a cryptology expert with
-lots of time on his hands. Also you should be aware that the swap file is not
-encrypted; so while you are editing, people with superuser privileges can read
-the unencrypted text from this file.
- One way to avoid letting people read your swap file is to avoid using one.
-If the -n argument is supplied on the command line, no swap file is used
-(instead, Vim puts everything in memory). For example, to edit the encrypted
-file "file.txt" without a swap file use the following command: >
-
- vim -x -n file.txt
-
-When already editing a file, the swapfile can be disabled with: >
-
- :setlocal noswapfile
-
-Since there is no swapfile, recovery will be impossible. Save the file a bit
-more often to avoid the risk of losing your changes.
-
-While the file is in memory, it is in plain text. Anyone with privilege can
-look in the editor's memory and discover the contents of the file.
- If you use a viminfo file, be aware that the contents of text registers are
-written out in the clear as well.
- If you really want to secure the contents of a file, edit it only on a
-portable computer not connected to a network, use good encryption tools, and
-keep the computer locked up in a big safe when not in use.
-
-==============================================================================
-*23.4* Binary files
+*23.3* Binary files
You can edit binary files with Vim. Vim wasn't really made for this, thus
there are a few restrictions. But you can read a file, change a character and
@@ -322,7 +238,7 @@ the right are ignored.
See the manual page of xxd for more information.
==============================================================================
-*23.5* Compressed files
+*23.4* Compressed files
This is easy: You can edit a compressed file just like any other file. The
"gzip" plugin takes care of decompressing the file when you edit it. And
diff --git a/runtime/doc/usr_toc.txt b/runtime/doc/usr_toc.txt
index d98a999aa4..9e4bf5ca93 100644
--- a/runtime/doc/usr_toc.txt
+++ b/runtime/doc/usr_toc.txt
@@ -198,9 +198,8 @@ Subjects that can be read independently.
|usr_23.txt| Editing other files
|23.1| DOS, Mac and Unix files
|23.2| Files on the internet
- |23.3| Encryption
- |23.4| Binary files
- |23.5| Compressed files
+ |23.3| Binary files
+ |23.4| Compressed files
|usr_24.txt| Inserting quickly
|24.1| Making corrections
diff --git a/runtime/doc/various.txt b/runtime/doc/various.txt
index c3c4ed7cfe..6f639e0fe9 100644
--- a/runtime/doc/various.txt
+++ b/runtime/doc/various.txt
@@ -319,7 +319,6 @@ N *+cmdline_hist* command line history |cmdline-history|
N *+cmdline_info* |'showcmd'| and |'ruler'|
N *+comments* |'comments'| support
B *+conceal* "conceal" support, see |conceal| |:syn-conceal| etc.
-N *+cryptv* encryption support |encryption|
B *+cscope* |cscope| support
m *+cursorbind* |'cursorbind'| support
m *+cursorshape* |termcap-cursor-shape| support
diff --git a/runtime/doc/vi_diff.txt b/runtime/doc/vi_diff.txt
index aa90dc94b0..a3abd2cfd3 100644
--- a/runtime/doc/vi_diff.txt
+++ b/runtime/doc/vi_diff.txt
@@ -137,10 +137,7 @@ Support for different systems.
- In protected mode on Windows 3.1 and MS-DOS (DPMI driver required).
- Windows 95 and Windows NT, with support for long file names.
- VMS
- - BeOS
- Macintosh
- - Risc OS
- - IBM OS/390
Note that on some systems features need to be disabled to reduce
resource usage, esp. on MS-DOS. For some outdated systems you need to
use an older Vim version.
@@ -162,7 +159,7 @@ Graphical User Interface (GUI). |gui|
define your own menus. Better support for CTRL/SHIFT/ALT keys in
combination with special keys and mouse. Supported for various
platforms, such as X11 (with Motif and Athena interfaces), GTK, Win32
- (Windows 95 and later), BeOS, Amiga and Macintosh.
+ (Windows 95 and later), Amiga and Macintosh.
Multiple windows and buffers. |windows.txt|
Vim can split the screen into several windows, each editing a
@@ -751,10 +748,6 @@ switched off by setting the 'updatecount' option to 0 or starting Vim with
the "-n" option. Use the 'directory' option for placing the .swp file
somewhere else.
-Vim is able to work correctly on filesystems with 8.3 file names, also when
-using messydos or crossdos filesystems on the Amiga, or any 8.3 mounted
-filesystem under Unix. See |'shortname'|.
-
Error messages are shown at least one second (Vi overwrites error messages).
If Vim gives the |hit-enter| prompt, you can hit any key. Characters other
@@ -939,8 +932,6 @@ Only Vim is able to accept options in between and after the file names.
-W {name} Vim: Append to script file {name}.
--x Vi, Vim: Ask for encryption key. See |encryption|.
-
-X Vim: Don't connect to the X server.
-y Vim: Start in easy mode, like |evim|.
diff --git a/runtime/menu.vim b/runtime/menu.vim
index e0745585a6..09d3443155 100644
--- a/runtime/menu.vim
+++ b/runtime/menu.vim
@@ -383,7 +383,7 @@ if has("keymap")
endif
unlet s:n
endif
-if has("win32") || has("win16") || has("gui_motif") || has("gui_gtk") || has("gui_kde") || has("gui_photon") || has("gui_mac")
+if has("win32") || has("win16") || has("gui_motif") || has("gui_gtk") || has("gui_kde") || has("gui_mac")
an 20.470 &Edit.Select\ Fo&nt\.\.\. :set guifont=*<CR>
endif
@@ -697,21 +697,13 @@ endfunc
func! s:BMHash(name)
" Make name all upper case, so that chars are between 32 and 96
let nm = substitute(a:name, ".*", '\U\0', "")
- if has("ebcdic")
- " HACK: Replace all non alphabetics with 'Z'
- " Just to make it work for now.
- let nm = substitute(nm, "[^A-Z]", 'Z', "g")
- let sp = char2nr('A') - 1
- else
- let sp = char2nr(' ')
- endif
+ let sp = char2nr(' ')
" convert first six chars into a number for sorting:
return (char2nr(nm[0]) - sp) * 0x800000 + (char2nr(nm[1]) - sp) * 0x20000 + (char2nr(nm[2]) - sp) * 0x1000 + (char2nr(nm[3]) - sp) * 0x80 + (char2nr(nm[4]) - sp) * 0x20 + (char2nr(nm[5]) - sp)
endfunc
func! s:BMHash2(name)
let nm = substitute(a:name, ".", '\L\0', "")
- " Not exactly right for EBCDIC...
if nm[0] < 'a' || nm[0] > 'z'
return '&others.'
elseif nm[0] <= 'd'
diff --git a/runtime/optwin.vim b/runtime/optwin.vim
index 22581ed98b..eab91de3df 100644
--- a/runtime/optwin.vim
+++ b/runtime/optwin.vim
@@ -987,14 +987,6 @@ call append("$", "patchmode\tkeep oldest version of a file; specifies file name
call <SID>OptionG("pm", &pm)
call append("$", "fsync\tforcibly sync the file to disk after writing it")
call <SID>BinOptionG("fs", &fs)
-if !has("msdos")
- call append("$", "shortname\tuse 8.3 file names")
- call append("$", "\t(local to buffer)")
- call <SID>BinOptionL("sn")
-endif
-call append("$", "cryptmethod\tencryption method for file writing: zip or blowfish")
-call append("$", "\t(local to buffer)")
-call <SID>OptionL("cm")
call <SID>Header("the swap file")
@@ -1107,13 +1099,8 @@ if has("quickfix")
endif
-if has("msdos") || has("win16") || has("win32") || has("osfiletype")
+if has("msdos") || has("win16") || has("win32")
call <SID>Header("system specific")
- if has("osfiletype")
- call append("$", "osfiletype\tOS-specific information about the type of file")
- call append("$", "\t(local to buffer)")
- call <SID>OptionL("oft")
- endif
if has("msdos") || has("win16") || has("win32")
call append("$", "shellslash\tuse forward slashes in file names; for Unix-like shells")
call <SID>BinOptionG("ssl", &ssl)
diff --git a/runtime/print/ebcdic-uk.ps b/runtime/print/ebcdic-uk.ps
deleted file mode 100644
index 1070074bff..0000000000
--- a/runtime/print/ebcdic-uk.ps
+++ /dev/null
@@ -1,40 +0,0 @@
-%!PS-Adobe-3.0 Resource-Encoding
-%%Title: VIM-ebcdic-uk
-%%Version: 1.0 0
-%%EndComments
-/VIM-ebcdic-uk[
-/.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef
-/.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef
-/.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef
-/.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef
-/.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef
-/.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef
-/.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef
-/.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef
-/space /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef
-/.notdef /.notdef /dollar /period /less /parenleft /plus /bar
-/ampersand /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef
-/.notdef /.notdef /exclam /sterling /asterisk /parenright /semicolon /logicalnot
-/minus /slash /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef
-/.notdef /.notdef /brokenbar /comma /percent /underscore /greater /question
-/.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef
-/.notdef /quotereversed /colon /numbersign /at /quoteright /equal /quotedbl
-/.notdef /a /b /c /d /e /f /g
-/h /i /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef
-/.notdef /j /k /l /m /n /o /p
-/q /r /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef
-/.notdef /macron /s /t /u /v /w /x
-/y /z /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef
-/.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef
-/.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef
-/braceleft /A /B /C /D /E /F /G
-/H /I /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef
-/braceright /J /K /L /M /N /O /P
-/Q /R /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef
-/backslash /.notdef /S /T /U /V /W /X
-/Y /Z /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef
-/zero /one /two /three /four /five /six /seven
-/eight /nine /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef]
-/Encoding defineresource pop
-% vim:ff=unix:
-%%EOF
diff --git a/runtime/syntax/help.vim b/runtime/syntax/help.vim
index c55d32ef7c..b306e66e59 100644
--- a/runtime/syntax/help.vim
+++ b/runtime/syntax/help.vim
@@ -19,15 +19,9 @@ if has("conceal")
else
syn region helpExample matchgroup=helpIgnore start=" >$" start="^>$" end="^[^ \t]"me=e-1 end="^<"
endif
-if has("ebcdic")
- syn match helpHyperTextJump "\\\@<!|[^"*|]\+|" contains=helpBar
- syn match helpHyperTextEntry "\*[^"*|]\+\*\s"he=e-1 contains=helpStar
- syn match helpHyperTextEntry "\*[^"*|]\+\*$" contains=helpStar
-else
- syn match helpHyperTextJump "\\\@<!|[#-)!+-~]\+|" contains=helpBar
- syn match helpHyperTextEntry "\*[#-)!+-~]\+\*\s"he=e-1 contains=helpStar
- syn match helpHyperTextEntry "\*[#-)!+-~]\+\*$" contains=helpStar
-endif
+syn match helpHyperTextJump "\\\@<!|[#-)!+-~]\+|" contains=helpBar
+syn match helpHyperTextEntry "\*[#-)!+-~]\+\*\s"he=e-1 contains=helpStar
+syn match helpHyperTextEntry "\*[#-)!+-~]\+\*$" contains=helpStar
if has("conceal")
syn match helpBar contained "|" conceal
syn match helpBacktick contained "`" conceal
diff --git a/runtime/syntax/sed.vim b/runtime/syntax/sed.vim
index 42ad6d8e62..f0f80300d6 100644
--- a/runtime/syntax/sed.vim
+++ b/runtime/syntax/sed.vim
@@ -49,12 +49,8 @@ syn match sedReplaceMeta "&\|\\\($\|.\)" contains=sedTab contained
" Metacharacters: $ * . \ ^ [ ~
" @ is used as delimiter and treated on its own below
let __at = char2nr("@")
-let __sed_i = char2nr(" ") " ASCII: 32, EBCDIC: 64
-if has("ebcdic")
- let __sed_last = 255
-else
- let __sed_last = 126
-endif
+let __sed_i = char2nr(" ") " ASCII: 32
+let __sed_last = 126
let __sed_metacharacters = '$*.\^[~'
while __sed_i <= __sed_last
let __sed_delimiter = escape(nr2char(__sed_i), __sed_metacharacters)
@@ -105,7 +101,7 @@ if version >= 508 || !exists("did_sed_syntax_inits")
if exists("highlight_sedtabs")
HiLink sedTab Todo
endif
- let __sed_i = char2nr(" ") " ASCII: 32, EBCDIC: 64
+ let __sed_i = char2nr(" ") " ASCII: 32
while __sed_i <= __sed_last
exe "HiLink sedRegexp".__sed_i "Macro"
exe "HiLink sedReplacement".__sed_i "NONE"
diff --git a/runtime/syntax/vim.vim b/runtime/syntax/vim.vim
index c8aebd4bb2..47d74090d1 100644
--- a/runtime/syntax/vim.vim
+++ b/runtime/syntax/vim.vim
@@ -27,22 +27,22 @@ syn match vimCommand contained "\<z[-+^.=]\="
syn keyword vimStdPlugin contained DiffOrig Man N[ext] P[rint] S TOhtml XMLent XMLns
" vimOptions are caught only when contained in a vimSet {{{2
-syn keyword vimOption contained acd ambiwidth arabicshape autowriteall backupdir bdlay binary breakat bufhidden cd ci cinw co commentstring confirm cpoptions cscoperelative csre cursorcolumn delcombine diffopt ea efm ep et fdc fdo ffs filetype fo foldlevelstart formatexpr ft gfw gtt guipty hh hkmap ic imaf iminsert includeexpr inf isident key langmap lines lmap ma matchtime mco ml modeline mousefocus mousetime nrformats ofu para pdev pi previewwindow printmbfont qe relativenumber rightleftcmd ru sbr scrolloff selection shellcmdflag shellxescape showbreak si smartcase softtabstop spelllang sps sta su swb synmaxcol tagbsearch tbi termencoding thesaurus titlestring tpm ttm ttytype undodir ut vfile vop wcm whichwrap wildignore winaltkeys winminwidth wmnu write
+syn keyword vimOption contained acd ambiwidth arabicshape autowriteall backupdir bdlay binary breakat bufhidden cd ci cinw co commentstring confirm cpoptions cscoperelative csre cursorcolumn delcombine diffopt ea efm ep et fdc fdo ffs filetype fo foldlevelstart formatexpr ft gfw gtt guipty hh hkmap ic imaf iminsert includeexpr inf isident langmap lines lmap ma matchtime mco ml modeline mousefocus mousetime nrformats ofu para pdev pi previewwindow printmbfont qe relativenumber rightleftcmd ru sbr scrolloff selection shellcmdflag shellxescape showbreak si smartcase softtabstop spelllang sps sta su swb synmaxcol tagbsearch tbi termencoding thesaurus titlestring tpm ttm ttytype undodir ut vfile vop wcm whichwrap wildignore winaltkeys winminwidth wmnu write
syn keyword vimOption contained ai ambw ari aw backupext beval brk buflisted cdpath cin cinwords cocu compatible cpt cscopetag cst cursorline dex digraph ead ei equalalways eventignore fde fdt fic fillchars foldclose foldmarker formatlistpat gcr ghr guicursor guitablabel hi hkmapp icon imak ims incsearch infercase isk keymap langmenu linespace loadplugins macatsui maxcombine mef mls modelines mousehide mp nu omnifunc paragraphs penc pm printdevice printoptions quoteescape remap rl ruf sc scrollopt selectmode shellpipe shellxquote showcmd sidescroll smartindent sol spellsuggest sr stal sua swf syntax taglength tbidi terse tildeop tl tr tty tw undofile vb vi wa wd wi wildignorecase window winwidth wmw writeany
syn keyword vimOption contained akm anti arshape awa backupskip bex browsedir buftype cedit cindent clipboard cole complete crb cscopetagorder csto cwh dg dip eadirection ek equalprg ex fdi fen fileencoding fk foldcolumn foldmethod formatoptions gd go guifont guitabtooltip hid hkp iconstring imc imsearch inde insertmode iskeyword keymodel laststatus lisp lpl magic maxfuncdepth menuitems mm modifiable mousem mps number opendevice paste pex pmbcs printencoding prompt rdt report rlc ruler scb scs sessionoptions shellquote shiftround showfulltag sidescrolloff smarttab sp spf srr startofline suffixes switchbuf ta tagrelative tbis textauto timeout tm ts ttybuiltin tx undolevels vbs viewdir wak weirdinvert wic wildmenu winfixheight wiv wop writebackup
-syn keyword vimOption contained al antialias autochdir background balloondelay bexpr bk bs casemap cf cink cmdheight colorcolumn completefunc copyindent cryptmethod cscopeverbose csverb debug dict dir eb enc errorbells expandtab fdl fenc fileencodings fkmap foldenable foldminlines formatprg gdefault gp guifontset helpfile hidden hl ignorecase imcmdline imsf indentexpr is isp keywordprg lazyredraw lispwords ls makeef maxmapdepth mfd mmd modified mousemodel msm numberwidth operatorfunc pastetoggle pexpr pmbfn printexpr pt re restorescreen rnu rulerformat scr sect sft shellredir shiftwidth showmatch siso smc spc spl ss statusline suffixesadd sws tabline tags tbs textmode timeoutlen to tsl ttyfast uc undoreload vdir viewoptions warn wfh wig wildmode winfixwidth wiw wrap writedelay
+syn keyword vimOption contained al antialias autochdir background balloondelay bexpr bk bs casemap cf cink cmdheight colorcolumn completefunc copyindent cscopeverbose csverb debug dict dir eb enc errorbells expandtab fdl fenc fileencodings fkmap foldenable foldminlines formatprg gdefault gp guifontset helpfile hidden hl ignorecase imcmdline imsf indentexpr is isp keywordprg lazyredraw lispwords ls makeef maxmapdepth mfd mmd modified mousemodel msm numberwidth operatorfunc pastetoggle pexpr pmbfn printexpr pt re restorescreen rnu rulerformat scr sect sft shellredir shiftwidth showmatch siso smc spc spl ss statusline suffixesadd sws tabline tags tbs textmode timeoutlen to tsl ttyfast uc undoreload vdir viewoptions warn wfh wig wildmode winfixwidth wiw wrap writedelay
syn keyword vimOption contained aleph ar autoindent backspace ballooneval bg bkc bsdir cb cfu cinkeys cmdwinheight columns completeopt cot cscopepathcomp cspc cuc deco dictionary directory ed encoding errorfile exrc fdls fencs fileformat flp foldexpr foldnestmax fp gfm grepformat guifontwide helpheight highlight hlg im imd imstatusfunc indentkeys isf isprint km lbr list lsp makeprg maxmem mh mmp more mouses mzq nuw opfunc patchexpr pfn popt printfont pumheight readonly revins ro runtimepath scroll sections sh shellslash shm showmode sj smd spell splitbelow ssl stl sw sxe tabpagemax tagstack tenc textwidth title toolbar tsr ttym udf updatecount ve viminfo wb wfw wildchar wildoptions winheight wm wrapmargin ws
-syn keyword vimOption contained allowrevins arab autoread backup balloonexpr bh bl bsk cc ch cino cmp com concealcursor cp cscopeprg csprg cul def diff display edcompatible endofline errorformat fcl fdm fex fileformats fml foldignore foldopen fs gfn grepprg guiheadroom helplang history hls imactivatefunc imdisable inc indk isfname joinspaces kmp lcs listchars lw mat maxmempattern mis mmt mouse mouseshape mzquantum odev osfiletype patchmode ph preserveindent printheader pvh redrawtime ri rs sb scrollbind secure shcf shelltemp shortmess showtabline slm sn spellcapcheck splitright ssop stmp swapfile sxq tabstop tal term tf titlelen toolbariconsize ttimeout ttymouse udir updatetime verbose virtualedit wc wh wildcharm wim winminheight wmh wrapscan ww
-syn keyword vimOption contained altkeymap arabic autowrite backupcopy bdir bin bomb bt ccv charconvert cinoptions cms comments conceallevel cpo cscopequickfix csqf cursorbind define diffexpr dy ef eol esckeys fcs fdn ff fileignorecase fmr foldlevel foldtext fsync gfs gtl guioptions hf hk hlsearch imactivatekey imi include inex isi js kp linebreak lm lz matchpairs maxmemtot mkspellmem mod mousef mouset nf oft pa path pheader previewheight printmbcharset pvw regexpengine rightleft rtp sbo scrolljump sel shell shortname shq sm so spellfile spr st sts swapsync syn tag tb termbidi tgst titleold top ttimeoutlen ttyscroll ul ur unnamedclip unc verbosefile visualbell
+syn keyword vimOption contained allowrevins arab autoread backup balloonexpr bh bl bsk cc ch cino cmp com concealcursor cp cscopeprg csprg cul def diff display edcompatible endofline errorformat fcl fdm fex fileformats fml foldignore foldopen fs gfn grepprg guiheadroom helplang history hls imactivatefunc imdisable inc indk isfname joinspaces kmp lcs listchars lw mat maxmempattern mis mmt mouse mouseshape mzquantum odev patchmode ph preserveindent printheader pvh redrawtime ri rs sb scrollbind secure shcf shelltemp shortmess showtabline slm spellcapcheck splitright ssop stmp swapfile sxq tabstop tal term tf titlelen toolbariconsize ttimeout ttymouse udir updatetime verbose virtualedit wc wh wildcharm wim winminheight wmh wrapscan ww
+syn keyword vimOption contained altkeymap arabic autowrite backupcopy bdir bin bomb bt ccv charconvert cinoptions cms comments conceallevel cpo cscopequickfix csqf cursorbind define diffexpr dy ef eol esckeys fcs fdn ff fileignorecase fmr foldlevel foldtext fsync gfs gtl guioptions hf hk hlsearch imactivatekey imi include inex isi js kp linebreak lm lz matchpairs maxmemtot mkspellmem mod mousef mouset nf pa path pheader previewheight printmbcharset pvw regexpengine rightleft rtp sbo scrolljump sel shell shq sm so spellfile spr st sts swapsync syn tag tb termbidi tgst titleold top ttimeoutlen ttyscroll ul ur unnamedclip unc verbosefile visualbell
" vimOptions: These are the turn-off setting variants {{{2
-syn keyword vimOption contained noacd noallowrevins noantialias noarabic noarshape noautoread noaw noballooneval nobinary nobk nobuflisted nocin noconfirm nocopyindent nocscoperelative nocsre nocuc nocursorcolumn nodelcombine nodigraph noed noendofline noerrorbells noex nofen nofk nogd nohid nohkmap nohkp nohlsearch noicon noim noimcmdline noimdisable noinf noinsertmode nojoinspaces nolazyredraw nolinebreak nolist nolpl noma nomagic noml nomodeline nomodified nomousef nomousehide nonumber noopendevice nopi nopreviewwindow nopvw norelativenumber norestorescreen nori norl noro noru nosb noscb noscs nosft noshelltemp noshortname noshowfulltag noshowmode nosm nosmartindent nosmd nosol nosplitbelow nospr nossl nostartofline noswapfile nota notagrelative notbi notbs noterse notextmode notgst notimeout noto notr nottybuiltin notx noundofile novisualbell nowarn noweirdinvert nowfw nowildignorecase nowinfixheight nowiv nowrap nowrite nowritebackup
-syn keyword vimOption contained noai noaltkeymap noar noarabicshape noautochdir noautowrite noawa nobeval nobl nocf nocindent nocp nocscopetag nocst nocul nocursorline nodg noea noedcompatible noeol noesckeys noexpandtab nofic nofkmap nogdefault nohidden nohkmapp nohls noic noignorecase noimc noimd noincsearch noinfercase nois nojs nolbr nolisp noloadplugins nolz nomacatsui nomh nomod nomodifiable nomore nomousefocus nonu noodev nopaste nopreserveindent noprompt noreadonly noremap norevins norightleft nornu nors noruler nosc noscrollbind nosecure noshellslash noshiftround noshowcmd noshowmatch nosi nosmartcase nosmarttab nosn nospell nosplitright nosr nosta nostmp noswf notagbsearch notagstack notbidi notermbidi notextauto notf notildeop notitle notop nottimeout nottyfast noudf novb nowa nowb nowfh nowic nowildmenu nowinfixwidth nowmnu nowrapscan nowriteany nows
+syn keyword vimOption contained noacd noallowrevins noantialias noarabic noarshape noautoread noaw noballooneval nobinary nobk nobuflisted nocin noconfirm nocopyindent nocscoperelative nocsre nocuc nocursorcolumn nodelcombine nodigraph noed noendofline noerrorbells noex nofen nofk nogd nohid nohkmap nohkp nohlsearch noicon noim noimcmdline noimdisable noinf noinsertmode nojoinspaces nolazyredraw nolinebreak nolist nolpl noma nomagic noml nomodeline nomodified nomousef nomousehide nonumber noopendevice nopi nopreviewwindow nopvw norelativenumber norestorescreen nori norl noro noru nosb noscb noscs nosft noshelltemp noshowfulltag noshowmode nosm nosmartindent nosmd nosol nosplitbelow nospr nossl nostartofline noswapfile nota notagrelative notbi notbs noterse notextmode notgst notimeout noto notr nottybuiltin notx noundofile novisualbell nowarn noweirdinvert nowfw nowildignorecase nowinfixheight nowiv nowrap nowrite nowritebackup
+syn keyword vimOption contained noai noaltkeymap noar noarabicshape noautochdir noautowrite noawa nobeval nobl nocf nocindent nocp nocscopetag nocst nocul nocursorline nodg noea noedcompatible noeol noesckeys noexpandtab nofic nofkmap nogdefault nohidden nohkmapp nohls noic noignorecase noimc noimd noincsearch noinfercase nois nojs nolbr nolisp noloadplugins nolz nomacatsui nomh nomod nomodifiable nomore nomousefocus nonu noodev nopaste nopreserveindent noprompt noreadonly noremap norevins norightleft nornu nors noruler nosc noscrollbind nosecure noshellslash noshiftround noshowcmd noshowmatch nosi nosmartcase nosmarttab nospell nosplitright nosr nosta nostmp noswf notagbsearch notagstack notbidi notermbidi notextauto notf notildeop notitle notop nottimeout nottyfast noudf novb nowa nowb nowfh nowic nowildmenu nowinfixwidth nowmnu nowrapscan nowriteany nows
syn keyword vimOption contained noakm noanti noarab noari noautoindent noautowriteall nobackup nobin nobomb noci nocompatible nocrb nocscopeverbose nocsverb nocursorbind nodeco nodiff noeb noek noequalalways noet noexrc nofileignorecase nofoldenable noguipty nohk
" vimOptions: These are the invertible variants {{{2
-syn keyword vimOption contained invacd invallowrevins invantialias invarabic invarshape invautoread invaw invballooneval invbinary invbk invbuflisted invcin invconfirm invcopyindent invcscoperelative invcsre invcuc invcursorcolumn invdelcombine invdigraph inved invendofline inverrorbells invex invfen invfk invgd invhid invhkmap invhkp invhlsearch invicon invim invimcmdline invimdisable invinf invinsertmode invjoinspaces invlazyredraw invlinebreak invlist invlpl invma invmagic invml invmodeline invmodified invmousef invmousehide invnumber invopendevice invpi invpreviewwindow invpvw invrelativenumber invrestorescreen invri invrl invro invru invsb invscb invscs invsft invshelltemp invshortname invshowfulltag invshowmode invsm invsmartindent invsmd invsol invsplitbelow invspr invssl invstartofline invswapfile invta invtagrelative invtbi invtbs invterse invtextmode invtgst invtimeout invto invtr invttybuiltin invtx invundofile invvisualbell invwarn invweirdinvert invwfw invwildignorecase invwinfixheight invwiv invwrap invwrite invwritebackup
-syn keyword vimOption contained invai invaltkeymap invar invarabicshape invautochdir invautowrite invawa invbeval invbl invcf invcindent invcp invcscopetag invcst invcul invcursorline invdg invea invedcompatible inveol invesckeys invexpandtab invfic invfkmap invgdefault invhidden invhkmapp invhls invic invignorecase invimc invimd invincsearch invinfercase invis invjs invlbr invlisp invloadplugins invlz invmacatsui invmh invmod invmodifiable invmore invmousefocus invnu invodev invpaste invpreserveindent invprompt invreadonly invremap invrevins invrightleft invrnu invrs invruler invsc invscrollbind invsecure invshellslash invshiftround invshowcmd invshowmatch invsi invsmartcase invsmarttab invsn invspell invsplitright invsr invsta invstmp invswf invtagbsearch invtagstack invtbidi invtermbidi invtextauto invtf invtildeop invtitle invtop invttimeout invttyfast invudf invvb invwa invwb invwfh invwic invwildmenu invwinfixwidth invwmnu invwrapscan invwriteany invws
+syn keyword vimOption contained invacd invallowrevins invantialias invarabic invarshape invautoread invaw invballooneval invbinary invbk invbuflisted invcin invconfirm invcopyindent invcscoperelative invcsre invcuc invcursorcolumn invdelcombine invdigraph inved invendofline inverrorbells invex invfen invfk invgd invhid invhkmap invhkp invhlsearch invicon invim invimcmdline invimdisable invinf invinsertmode invjoinspaces invlazyredraw invlinebreak invlist invlpl invma invmagic invml invmodeline invmodified invmousef invmousehide invnumber invopendevice invpi invpreviewwindow invpvw invrelativenumber invrestorescreen invri invrl invro invru invsb invscb invscs invsft invshelltemp invshowfulltag invshowmode invsm invsmartindent invsmd invsol invsplitbelow invspr invssl invstartofline invswapfile invta invtagrelative invtbi invtbs invterse invtextmode invtgst invtimeout invto invtr invttybuiltin invtx invundofile invvisualbell invwarn invweirdinvert invwfw invwildignorecase invwinfixheight invwiv invwrap invwrite invwritebackup
+syn keyword vimOption contained invai invaltkeymap invar invarabicshape invautochdir invautowrite invawa invbeval invbl invcf invcindent invcp invcscopetag invcst invcul invcursorline invdg invea invedcompatible inveol invesckeys invexpandtab invfic invfkmap invgdefault invhidden invhkmapp invhls invic invignorecase invimc invimd invincsearch invinfercase invis invjs invlbr invlisp invloadplugins invlz invmacatsui invmh invmod invmodifiable invmore invmousefocus invnu invodev invpaste invpreserveindent invprompt invreadonly invremap invrevins invrightleft invrnu invrs invruler invsc invscrollbind invsecure invshellslash invshiftround invshowcmd invshowmatch invsi invsmartcase invsmarttab invspell invsplitright invsr invsta invstmp invswf invtagbsearch invtagstack invtbidi invtermbidi invtextauto invtf invtildeop invtitle invtop invttimeout invttyfast invudf invvb invwa invwb invwfh invwic invwildmenu invwinfixwidth invwmnu invwrapscan invwriteany invws
syn keyword vimOption contained invakm invanti invarab invari invautoindent invautowriteall invbackup invbin invbomb invci invcompatible invcrb invcscopeverbose invcsverb invcursorbind invdeco invdiff inveb invek invequalalways invet invexrc invfileignorecase invfoldenable invguipty invhk
" termcap codes (which can also be set) {{{2
diff --git a/scripts/msgpack-gen.lua b/scripts/msgpack-gen.lua
index 9645784f00..d31a062a68 100644
--- a/scripts/msgpack-gen.lua
+++ b/scripts/msgpack-gen.lua
@@ -252,6 +252,11 @@ end
output:write([[
static Map(String, MsgpackRpcRequestHandler) *methods = NULL;
+void msgpack_rpc_add_method_handler(String method, MsgpackRpcRequestHandler handler)
+{
+ map_put(String, MsgpackRpcRequestHandler)(methods, method, handler);
+}
+
void msgpack_rpc_init_method_table(void)
{
methods = map_new(String, MsgpackRpcRequestHandler)();
@@ -263,7 +268,7 @@ void msgpack_rpc_init_method_table(void)
local max_fname_len = 0
for i = 1, #functions do
local fn = functions[i]
- output:write(' map_put(String, MsgpackRpcRequestHandler)(methods, '..
+ output:write(' msgpack_rpc_add_method_handler('..
'(String) {.data = "'..fn.name..'", '..
'.size = sizeof("'..fn.name..'") - 1}, '..
'(MsgpackRpcRequestHandler) {.fn = handle_'.. fn.name..
diff --git a/src/nvim/api/buffer.c b/src/nvim/api/buffer.c
index 982003a31a..0292e82038 100644
--- a/src/nvim/api/buffer.c
+++ b/src/nvim/api/buffer.c
@@ -132,7 +132,12 @@ ArrayOf(String) buffer_get_line_slice(Buffer buffer,
}
const char *bufstr = (char *) ml_get_buf(buf, (linenr_T) lnum, false);
- rv.items[i] = STRING_OBJ(cstr_to_string(bufstr));
+ Object str = STRING_OBJ(cstr_to_string(bufstr));
+
+ // Vim represents NULs as NLs, but this may confuse clients.
+ strchrsub(str.data.string.data, '\n', '\0');
+
+ rv.items[i] = str;
}
end:
@@ -201,7 +206,18 @@ void buffer_set_line_slice(Buffer buffer,
}
String l = replacement.items[i].data.string;
- lines[i] = xmemdupz(l.data, l.size);
+
+ // Fill lines[i] with l's contents. Disallow newlines in the middle of a
+ // line and convert NULs to newlines to avoid truncation.
+ lines[i] = xmallocz(l.size);
+ for (size_t j = 0; j < l.size; j++) {
+ if (l.data[j] == '\n') {
+ api_set_error(err, Exception, _("string cannot contain newlines"));
+ new_len = i + 1;
+ goto end;
+ }
+ lines[i][j] = (char) (l.data[j] == '\0' ? '\n' : l.data[j]);
+ }
}
try_start();
diff --git a/src/nvim/api/vim.c b/src/nvim/api/vim.c
index fe5fa6274b..eab79d970e 100644
--- a/src/nvim/api/vim.c
+++ b/src/nvim/api/vim.c
@@ -21,6 +21,7 @@
#include "nvim/message.h"
#include "nvim/eval.h"
#include "nvim/misc2.h"
+#include "nvim/syntax.h"
#include "nvim/term.h"
#include "nvim/getchar.h"
#include "nvim/os/input.h"
@@ -546,6 +547,11 @@ void vim_unsubscribe(uint64_t channel_id, String event)
channel_unsubscribe(channel_id, e);
}
+Integer vim_name_to_color(String name)
+{
+ return name_to_color((uint8_t *)name.data);
+}
+
Array vim_get_api_info(uint64_t channel_id)
{
Array rv = ARRAY_DICT_INIT;
diff --git a/src/nvim/edit.c b/src/nvim/edit.c
index c7f20783a9..d5ef84ff7b 100644
--- a/src/nvim/edit.c
+++ b/src/nvim/edit.c
@@ -3439,6 +3439,7 @@ static int ins_compl_get_exp(pos_T *ini)
int dict_f = 0;
compl_T *old_match;
int set_match_pos;
+ int l_ctrl_x_mode = ctrl_x_mode;
if (!compl_started) {
FOR_ALL_BUFFERS(buf) {
@@ -3458,10 +3459,12 @@ static int ins_compl_get_exp(pos_T *ini)
found_new_match = FAIL;
set_match_pos = FALSE;
+ assert(l_ctrl_x_mode == ctrl_x_mode);
+
/* For ^N/^P pick a new entry from e_cpt if compl_started is off,
* or if found_all says this entry is done. For ^X^L only use the
* entries from 'complete' that look in loaded buffers. */
- if ((ctrl_x_mode == 0 || ctrl_x_mode == CTRL_X_WHOLE_LINE)
+ if ((l_ctrl_x_mode == 0 || l_ctrl_x_mode == CTRL_X_WHOLE_LINE)
&& (!compl_started || found_all)) {
found_all = FALSE;
while (*e_cpt == ',' || *e_cpt == ' ')
@@ -3470,7 +3473,7 @@ static int ins_compl_get_exp(pos_T *ini)
ins_buf = curbuf;
first_match_pos = *ini;
/* So that ^N can match word immediately after cursor */
- if (ctrl_x_mode == 0)
+ if (l_ctrl_x_mode == 0)
dec(&first_match_pos);
last_match_pos = first_match_pos;
type = 0;
@@ -3506,7 +3509,7 @@ static int ins_compl_get_exp(pos_T *ini)
} else if (*e_cpt == NUL)
break;
else {
- if (ctrl_x_mode == CTRL_X_WHOLE_LINE)
+ if (l_ctrl_x_mode == CTRL_X_WHOLE_LINE)
type = -1;
else if (*e_cpt == 'k' || *e_cpt == 's') {
if (*e_cpt == 'k')
@@ -3576,7 +3579,7 @@ static int ins_compl_get_exp(pos_T *ini)
* of matches is found when compl_pattern is empty */
if (find_tags(compl_pattern, &num_matches, &matches,
TAG_REGEXP | TAG_NAMES | TAG_NOIC |
- TAG_INS_COMP | (ctrl_x_mode ? TAG_VERBOSE : 0),
+ TAG_INS_COMP | (l_ctrl_x_mode ? TAG_VERBOSE : 0),
TAG_MANY, curbuf->b_ffname) == OK && num_matches > 0) {
ins_compl_add_matches(num_matches, matches, p_ic);
}
@@ -3635,9 +3638,9 @@ static int ins_compl_get_exp(pos_T *ini)
++msg_silent; /* Don't want messages for wrapscan. */
- /* ctrl_x_mode == CTRL_X_WHOLE_LINE || word-wise search that
+ /* l_ctrl_x_mode == CTRL_X_WHOLE_LINE || word-wise search that
* has added a word that was at the beginning of the line */
- if ( ctrl_x_mode == CTRL_X_WHOLE_LINE
+ if ( l_ctrl_x_mode == CTRL_X_WHOLE_LINE
|| (compl_cont_status & CONT_SOL))
found_new_match = search_for_exact_line(ins_buf, pos,
compl_direction, compl_pattern);
@@ -3668,7 +3671,7 @@ static int ins_compl_get_exp(pos_T *ini)
&& ini->col == pos->col)
continue;
ptr = ml_get_buf(ins_buf, pos->lnum, FALSE) + pos->col;
- if (ctrl_x_mode == CTRL_X_WHOLE_LINE) {
+ if (l_ctrl_x_mode == CTRL_X_WHOLE_LINE) {
if (compl_cont_status & CONT_ADDING) {
if (pos->lnum >= ins_buf->b_ml.ml_line_count)
continue;
@@ -3751,8 +3754,8 @@ static int ins_compl_get_exp(pos_T *ini)
found_new_match = OK;
/* break the loop for specialized modes (use 'complete' just for the
- * generic ctrl_x_mode == 0) or when we've found a new match */
- if ((ctrl_x_mode != 0 && ctrl_x_mode != CTRL_X_WHOLE_LINE)
+ * generic l_ctrl_x_mode == 0) or when we've found a new match */
+ if ((l_ctrl_x_mode != 0 && l_ctrl_x_mode != CTRL_X_WHOLE_LINE)
|| found_new_match != FAIL) {
if (got_int)
break;
@@ -3760,7 +3763,7 @@ static int ins_compl_get_exp(pos_T *ini)
if (type != -1)
ins_compl_check_keys(0);
- if ((ctrl_x_mode != 0 && ctrl_x_mode != CTRL_X_WHOLE_LINE)
+ if ((l_ctrl_x_mode != 0 && l_ctrl_x_mode != CTRL_X_WHOLE_LINE)
|| compl_interrupted)
break;
compl_started = TRUE;
@@ -3776,13 +3779,13 @@ static int ins_compl_get_exp(pos_T *ini)
}
compl_started = TRUE;
- if ((ctrl_x_mode == 0 || ctrl_x_mode == CTRL_X_WHOLE_LINE)
+ if ((l_ctrl_x_mode == 0 || l_ctrl_x_mode == CTRL_X_WHOLE_LINE)
&& *e_cpt == NUL) /* Got to end of 'complete' */
found_new_match = FAIL;
i = -1; /* total of matches, unknown */
if (found_new_match == FAIL
- || (ctrl_x_mode != 0 && ctrl_x_mode != CTRL_X_WHOLE_LINE))
+ || (l_ctrl_x_mode != 0 && l_ctrl_x_mode != CTRL_X_WHOLE_LINE))
i = ins_compl_make_cyclic();
/* If several matches were added (FORWARD) or the search failed and has
diff --git a/src/nvim/eval.c b/src/nvim/eval.c
index be69bdbe61..45ab901398 100644
--- a/src/nvim/eval.c
+++ b/src/nvim/eval.c
@@ -1835,7 +1835,7 @@ ex_let_one (
p = get_tv_string_chk(tv);
if (p != NULL && op != NULL && *op == '.') {
- s = get_reg_contents(*arg == '@' ? '"' : *arg, TRUE, TRUE);
+ s = get_reg_contents(*arg == '@' ? '"' : *arg, kGRegExprSrc);
if (s != NULL) {
p = ptofree = concat_str(s, p);
free(s);
@@ -4076,7 +4076,7 @@ eval7 (
case '@': ++*arg;
if (evaluate) {
rettv->v_type = VAR_STRING;
- rettv->vval.v_string = get_reg_contents(**arg, TRUE, TRUE);
+ rettv->vval.v_string = get_reg_contents(**arg, kGRegExprSrc);
}
if (**arg != NUL)
++*arg;
@@ -5119,6 +5119,20 @@ void list_append_tv(list_T *l, typval_T *tv)
}
/*
+ * Add a list to a list.
+ */
+void list_append_list(list_T *list, list_T *itemlist)
+{
+ listitem_T *li = listitem_alloc();
+
+ li->li_tv.v_type = VAR_LIST;
+ li->li_tv.v_lock = 0;
+ li->li_tv.vval.v_list = itemlist;
+ list_append(list, li);
+ ++list->lv_refcount;
+}
+
+/*
* Add a dictionary to a list. Used by getqflist().
*/
void list_append_dict(list_T *list, dict_T *dict)
@@ -5406,20 +5420,12 @@ static int list_join(garray_T *gap, list_T *l, char_u *sep, int echo_style, int
{
garray_T join_ga;
int retval;
- join_T *p;
ga_init(&join_ga, (int)sizeof(join_T), l->lv_len);
retval = list_join_inner(gap, l, sep, echo_style, copyID, &join_ga);
- /* Dispose each item in join_ga. */
- if (join_ga.ga_data != NULL) {
- p = (join_T *)join_ga.ga_data;
- for (int i = 0; i < join_ga.ga_len; ++i) {
- free(p->tofree);
- ++p;
- }
- ga_clear(&join_ga);
- }
+# define FREE_JOIN_TOFREE(join) free((join)->tofree)
+ GA_DEEP_CLEAR(&join_ga, join_T, FREE_JOIN_TOFREE);
return retval;
}
@@ -6452,7 +6458,7 @@ static struct fst {
{"getpid", 0, 0, f_getpid},
{"getpos", 1, 1, f_getpos},
{"getqflist", 0, 0, f_getqflist},
- {"getreg", 0, 2, f_getreg},
+ {"getreg", 0, 3, f_getreg},
{"getregtype", 0, 1, f_getregtype},
{"gettabvar", 2, 3, f_gettabvar},
{"gettabwinvar", 3, 4, f_gettabwinvar},
@@ -9512,30 +9518,44 @@ static void f_getqflist(typval_T *argvars, typval_T *rettv)
(void)get_errorlist(wp, rettv->vval.v_list);
}
-/*
- * "getreg()" function
- */
+/// "getreg()" function
static void f_getreg(typval_T *argvars, typval_T *rettv)
{
char_u *strregname;
int regname;
- int arg2 = FALSE;
- int error = FALSE;
+ int arg2 = false;
+ bool return_list = false;
+ int error = false;
if (argvars[0].v_type != VAR_UNKNOWN) {
strregname = get_tv_string_chk(&argvars[0]);
error = strregname == NULL;
- if (argvars[1].v_type != VAR_UNKNOWN)
+ if (argvars[1].v_type != VAR_UNKNOWN) {
arg2 = get_tv_number_chk(&argvars[1], &error);
- } else
+ if (!error && argvars[2].v_type != VAR_UNKNOWN) {
+ return_list = get_tv_number_chk(&argvars[2], &error);
+ }
+ }
+ } else {
strregname = vimvars[VV_REG].vv_str;
+ }
+
+ if (error) {
+ return;
+ }
+
regname = (strregname == NULL ? '"' : *strregname);
if (regname == 0)
regname = '"';
- rettv->v_type = VAR_STRING;
- rettv->vval.v_string = error ? NULL :
- get_reg_contents(regname, TRUE, arg2);
+ if (return_list) {
+ rettv->v_type = VAR_LIST;
+ rettv->vval.v_list =
+ get_reg_contents(regname, (arg2 ? kGRegExprSrc : 0) | kGRegList);
+ } else {
+ rettv->v_type = VAR_STRING;
+ rettv->vval.v_string = get_reg_contents(regname, arg2 ? kGRegExprSrc : 0);
+ }
}
/*
@@ -13300,7 +13320,6 @@ static void f_setreg(typval_T *argvars, typval_T *rettv)
int regname;
char_u *strregname;
char_u *stropt;
- char_u *strval;
int append;
char_u yank_type;
long block_len;
@@ -13317,8 +13336,6 @@ static void f_setreg(typval_T *argvars, typval_T *rettv)
regname = *strregname;
if (regname == 0 || regname == '@')
regname = '"';
- else if (regname == '=')
- return;
if (argvars[2].v_type != VAR_UNKNOWN) {
stropt = get_tv_string_chk(&argvars[2]);
@@ -13346,10 +13363,46 @@ static void f_setreg(typval_T *argvars, typval_T *rettv)
}
}
- strval = get_tv_string_chk(&argvars[1]);
- if (strval != NULL)
- write_reg_contents_ex(regname, strval, -1,
- append, yank_type, block_len);
+ if (argvars[1].v_type == VAR_LIST) {
+ int len = argvars[1].vval.v_list->lv_len;
+ // First half: use for pointers to result lines; second half: use for
+ // pointers to allocated copies.
+ char_u **lstval = xmalloc(sizeof(char_u *) * ((len + 1) * 2));
+ char_u **curval = lstval;
+ char_u **allocval = lstval + len + 2;
+ char_u **curallocval = allocval;
+
+ char_u buf[NUMBUFLEN];
+ for (listitem_T *li = argvars[1].vval.v_list->lv_first;
+ li != NULL;
+ li = li->li_next) {
+ char_u *strval = get_tv_string_buf_chk(&li->li_tv, buf);
+ if (strval == NULL) {
+ goto free_lstval;
+ }
+ if (strval == buf) {
+ // Need to make a copy,
+ // next get_tv_string_buf_chk() will overwrite the string.
+ strval = vim_strsave(buf);
+ *curallocval++ = strval;
+ }
+ *curval++ = strval;
+ }
+ *curval++ = NULL;
+
+ write_reg_contents_lst(regname, lstval, -1, append, yank_type, block_len);
+
+free_lstval:
+ while (curallocval > allocval)
+ free(*--curallocval);
+ free(lstval);
+ } else {
+ char_u *strval = get_tv_string_chk(&argvars[1]);
+ if (strval == NULL) {
+ return;
+ }
+ write_reg_contents_ex(regname, strval, -1, append, yank_type, block_len);
+ }
rettv->vval.v_number = 0;
}
@@ -16273,28 +16326,33 @@ static linenr_T get_tv_lnum_buf(typval_T *argvars, buf_T *buf)
* get_tv_string_chk() and get_tv_string_buf_chk() are similar, but return
* NULL on error.
*/
-static char_u *get_tv_string(typval_T *varp)
+static char_u *get_tv_string(const typval_T *varp)
+ FUNC_ATTR_NONNULL_ALL FUNC_ATTR_NONNULL_RET
{
static char_u mybuf[NUMBUFLEN];
return get_tv_string_buf(varp, mybuf);
}
-static char_u *get_tv_string_buf(typval_T *varp, char_u *buf)
+static char_u *get_tv_string_buf(const typval_T *varp, char_u *buf)
+ FUNC_ATTR_NONNULL_ALL FUNC_ATTR_NONNULL_RET
{
char_u *res = get_tv_string_buf_chk(varp, buf);
return res != NULL ? res : (char_u *)"";
}
-char_u *get_tv_string_chk(typval_T *varp)
+/// Careful: This uses a single, static buffer. YOU CAN ONLY USE IT ONCE!
+char_u *get_tv_string_chk(const typval_T *varp)
+ FUNC_ATTR_NONNULL_ALL
{
static char_u mybuf[NUMBUFLEN];
return get_tv_string_buf_chk(varp, mybuf);
}
-static char_u *get_tv_string_buf_chk(typval_T *varp, char_u *buf)
+static char_u *get_tv_string_buf_chk(const typval_T *varp, char_u *buf)
+ FUNC_ATTR_NONNULL_ALL
{
switch (varp->v_type) {
case VAR_NUMBER:
@@ -19815,16 +19873,12 @@ typval_T eval_call_provider(char *provider, char *method, list_T *arguments)
bool eval_has_provider(char *name)
{
-#define source_provider(name) \
- do_source((uint8_t *)"$VIMRUNTIME/autoload/provider/" name ".vim", \
- false, \
- false)
#define check_provider(name) \
if (has_##name == -1) { \
has_##name = !!find_func((uint8_t *)"provider#" #name "#Call"); \
if (!has_##name) { \
- source_provider(#name); \
+ script_autoload((uint8_t *)"provider#" #name "#Call", false); \
has_##name = !!find_func((uint8_t *)"provider#" #name "#Call"); \
} \
}
diff --git a/src/nvim/ex_cmds.c b/src/nvim/ex_cmds.c
index 5ae03c6be3..701e969393 100644
--- a/src/nvim/ex_cmds.c
+++ b/src/nvim/ex_cmds.c
@@ -5625,9 +5625,7 @@ helptags_one (
if (mix)
got_int = FALSE; /* continue with other languages */
- for (int i = 0; i < ga.ga_len; ++i)
- free(((char_u **)ga.ga_data)[i]);
- ga_clear(&ga);
+ GA_DEEP_CLEAR_PTR(&ga);
fclose(fd_tags); /* there is no check for an error... */
}
diff --git a/src/nvim/ex_cmds2.c b/src/nvim/ex_cmds2.c
index 794e9930b9..fa78047a46 100644
--- a/src/nvim/ex_cmds2.c
+++ b/src/nvim/ex_cmds2.c
@@ -2580,13 +2580,11 @@ char_u *get_scriptname(scid_T id)
}
# if defined(EXITFREE) || defined(PROTO)
-void free_scriptnames(void)
+void free_scriptnames()
{
- for (int i = script_items.ga_len; i > 0; --i)
- free(SCRIPT_ITEM(i).sn_name);
- ga_clear(&script_items);
+# define FREE_SCRIPTNAME(item) free((item)->sn_name)
+ GA_DEEP_CLEAR(&script_items, scriptitem_T, FREE_SCRIPTNAME);
}
-
# endif
diff --git a/src/nvim/ex_docmd.c b/src/nvim/ex_docmd.c
index e180be4421..6bca1ff34d 100644
--- a/src/nvim/ex_docmd.c
+++ b/src/nvim/ex_docmd.c
@@ -97,6 +97,8 @@ typedef struct {
linenr_T lnum; /* sourcing_lnum of the line */
} wcmd_T;
+#define FREE_WCMD(wcmd) free((wcmd)->line)
+
/*
* Structure used to store info for line position in a while or for loop.
* This is required, because do_one_cmd() may invoke ex_function(), which
@@ -708,9 +710,8 @@ int do_cmdline(char_u *cmdline, LineGetter fgetline,
*/
if (cstack.cs_looplevel == 0) {
if (!GA_EMPTY(&lines_ga)) {
- sourcing_lnum =
- ((wcmd_T *)lines_ga.ga_data)[lines_ga.ga_len - 1].lnum;
- free_cmdlines(&lines_ga);
+ sourcing_lnum = ((wcmd_T *)lines_ga.ga_data)[lines_ga.ga_len - 1].lnum;
+ GA_DEEP_CLEAR(&lines_ga, wcmd_T, FREE_WCMD);
}
current_line = 0;
}
@@ -777,8 +778,7 @@ int do_cmdline(char_u *cmdline, LineGetter fgetline,
free(cmdline_copy);
did_emsg_syntax = FALSE;
- free_cmdlines(&lines_ga);
- ga_clear(&lines_ga);
+ GA_DEEP_CLEAR(&lines_ga, wcmd_T, FREE_WCMD);
if (cstack.cs_idx >= 0) {
/*
@@ -1018,17 +1018,6 @@ static void store_loop_line(garray_T *gap, char_u *line)
}
/*
- * Free the lines stored for a ":while" or ":for" loop.
- */
-static void free_cmdlines(garray_T *gap)
-{
- while (!GA_EMPTY(gap)) {
- free(((wcmd_T *)(gap->ga_data))[gap->ga_len - 1].line);
- --gap->ga_len;
- }
-}
-
-/*
* If "fgetline" is get_loop_line(), return TRUE if the getline it uses equals
* "func". * Otherwise return TRUE when "fgetline" equals "func".
*/
@@ -4546,20 +4535,18 @@ void ex_comclear(exarg_T *eap)
uc_clear(&curbuf->b_ucmds);
}
+static void free_ucmd(ucmd_T* cmd) {
+ free(cmd->uc_name);
+ free(cmd->uc_rep);
+ free(cmd->uc_compl_arg);
+}
+
/*
* Clear all user commands for "gap".
*/
void uc_clear(garray_T *gap)
{
- ucmd_T *cmd;
-
- for (int i = 0; i < gap->ga_len; ++i) {
- cmd = USER_CMD_GA(gap, i);
- free(cmd->uc_name);
- free(cmd->uc_rep);
- free(cmd->uc_compl_arg);
- }
- ga_clear(gap);
+ GA_DEEP_CLEAR(gap, ucmd_T, free_ucmd);
}
static void ex_delcommand(exarg_T *eap)
@@ -5488,9 +5475,8 @@ static void ex_goto(exarg_T *eap)
*/
void alist_clear(alist_T *al)
{
- while (--al->al_ga.ga_len >= 0)
- free(AARGLIST(al)[al->al_ga.ga_len].ae_fname);
- ga_clear(&al->al_ga);
+# define FREE_AENTRY_FNAME(arg) free(arg->ae_fname)
+ GA_DEEP_CLEAR(&al->al_ga, aentry_T, FREE_AENTRY_FNAME);
}
/*
diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c
index e56592923d..d3051c5202 100644
--- a/src/nvim/ex_getln.c
+++ b/src/nvim/ex_getln.c
@@ -1984,10 +1984,6 @@ void free_cmdline_buf(void)
*/
static void draw_cmdline(int start, int len)
{
- if (embedded_mode) {
- return;
- }
-
int i;
if (cmdline_star > 0)
diff --git a/src/nvim/fold.c b/src/nvim/fold.c
index e76aacbadc..505ac8da0d 100644
--- a/src/nvim/fold.c
+++ b/src/nvim/fold.c
@@ -1336,9 +1336,8 @@ static void deleteFoldEntry(garray_T *gap, int idx, int recursive)
*/
void deleteFoldRecurse(garray_T *gap)
{
- for (int i = 0; i < gap->ga_len; ++i)
- deleteFoldRecurse(&(((fold_T *)(gap->ga_data))[i].fd_nested));
- ga_clear(gap);
+# define DELETE_FOLD_NESTED(fd) deleteFoldRecurse(&((fd)->fd_nested))
+ GA_DEEP_CLEAR(gap, fold_T, DELETE_FOLD_NESTED);
}
/* foldMarkAdjust() {{{2 */
diff --git a/src/nvim/garray.c b/src/nvim/garray.c
index 08a38493bf..c4f8f66bfe 100644
--- a/src/nvim/garray.c
+++ b/src/nvim/garray.c
@@ -37,10 +37,7 @@ void ga_clear(garray_T *gap)
/// @param gap
void ga_clear_strings(garray_T *gap)
{
- for (int i = 0; i < gap->ga_len; ++i) {
- free(((char_u **)(gap->ga_data))[i]);
- }
- ga_clear(gap);
+ GA_DEEP_CLEAR_PTR(gap);
}
/// Initialize a growing array.
diff --git a/src/nvim/garray.h b/src/nvim/garray.h
index b32bab52f7..b758fce5da 100644
--- a/src/nvim/garray.h
+++ b/src/nvim/garray.h
@@ -43,4 +43,30 @@ static inline void *ga_append_via_ptr(garray_T *gap, size_t item_size)
return ((char *)gap->ga_data) + (item_size * (size_t)gap->ga_len++);
}
+/// Deep free a garray of specific type using a custom free function.
+/// Items in the array as well as the array itself are freed.
+///
+/// @param gap the garray to be freed
+/// @param item_type type of the item in the garray
+/// @param free_item_fn free function that takes (*item_type) as parameter
+#define GA_DEEP_CLEAR(gap, item_type, free_item_fn) \
+ do { \
+ garray_T *_gap = (gap); \
+ if (_gap->ga_data != NULL) { \
+ for (int i = 0; i < _gap->ga_len; i++) { \
+ item_type *_item = &(((item_type *)_gap->ga_data)[i]); \
+ free_item_fn(_item); \
+ } \
+ } \
+ ga_clear(_gap); \
+ } while (false)
+
+#define FREE_PTR_PTR(ptr) free(*(ptr))
+
+/// Call `free` for every pointer stored in the garray and then frees the
+/// garray.
+///
+/// @param gap the garray to be freed
+#define GA_DEEP_CLEAR_PTR(gap) GA_DEEP_CLEAR(gap, void*, FREE_PTR_PTR)
+
#endif // NVIM_GARRAY_H
diff --git a/src/nvim/getchar.c b/src/nvim/getchar.c
index d0bdcde9e8..5dec7e38fd 100644
--- a/src/nvim/getchar.c
+++ b/src/nvim/getchar.c
@@ -2513,6 +2513,13 @@ fix_input_buffer (
int script /* TRUE when reading from a script */
)
{
+ if (abstract_ui) {
+ // Should not escape K_SPECIAL/CSI while in embedded mode because vim key
+ // codes keys are processed in input.c/input_enqueue.
+ buf[len] = NUL;
+ return len;
+ }
+
int i;
char_u *p = buf;
diff --git a/src/nvim/globals.h b/src/nvim/globals.h
index ea91135194..233d326a40 100644
--- a/src/nvim/globals.h
+++ b/src/nvim/globals.h
@@ -465,6 +465,8 @@ EXTERN int highlight_stlnc[9]; /* On top of user */
EXTERN int cterm_normal_fg_color INIT(= 0);
EXTERN int cterm_normal_fg_bold INIT(= 0);
EXTERN int cterm_normal_bg_color INIT(= 0);
+EXTERN RgbValue normal_fg INIT(= -1);
+EXTERN RgbValue normal_bg INIT(= -1);
EXTERN int autocmd_busy INIT(= FALSE); /* Is apply_autocmds() busy? */
EXTERN int autocmd_no_enter INIT(= FALSE); /* *Enter autocmds disabled */
@@ -1251,6 +1253,8 @@ EXTERN int curr_tmode INIT(= TMODE_COOK); /* contains current terminal mode */
// If a msgpack-rpc channel should be started over stdin/stdout
EXTERN bool embedded_mode INIT(= false);
+// Using the "abstract_ui" termcap
+EXTERN bool abstract_ui INIT(= false);
/// Used to track the status of external functions.
/// Currently only used for iconv().
diff --git a/src/nvim/main.c b/src/nvim/main.c
index 8e19cf3686..c806431872 100644
--- a/src/nvim/main.c
+++ b/src/nvim/main.c
@@ -265,13 +265,6 @@ int main(int argc, char **argv)
term_init();
TIME_MSG("shell init");
- event_init();
-
- if (!embedded_mode) {
- // Print a warning if stdout is not a terminal.
- check_tty(&params);
- }
-
/* This message comes before term inits, but after setting "silent_mode"
* when the input is not a tty. */
if (GARGCOUNT > 1 && !silent_mode)
@@ -283,6 +276,7 @@ int main(int argc, char **argv)
// initial screen size of 80x20
full_screen = true;
screen_resize(80, 20, false);
+ termcapinit((uint8_t *)"abstract_ui");
} else {
// set terminal name and get terminal capabilities (will set full_screen)
// Do some initialization of the screen
@@ -292,6 +286,16 @@ int main(int argc, char **argv)
TIME_MSG("Termcap init");
}
+ event_init();
+
+ if (abstract_ui) {
+ t_colors = 256;
+ } else {
+ // Print a warning if stdout is not a terminal TODO(tarruda): Remove this
+ // check once the new terminal UI is implemented
+ check_tty(&params);
+ }
+
/*
* Set the default values for the options that use Rows and Columns.
*/
@@ -424,19 +428,17 @@ int main(int argc, char **argv)
TIME_MSG("waiting for return");
}
- if (!embedded_mode) {
- starttermcap(); // start termcap if not done by wait_return()
- TIME_MSG("start termcap");
- may_req_ambiguous_char_width();
- setmouse(); // may start using the mouse
+ starttermcap(); // start termcap if not done by wait_return()
+ TIME_MSG("start termcap");
+ may_req_ambiguous_char_width();
+ setmouse(); // may start using the mouse
- if (scroll_region) {
- scroll_region_reset(); // In case Rows changed
- }
-
- scroll_start(); // may scroll the screen to the right position
+ if (scroll_region) {
+ scroll_region_reset(); // In case Rows changed
}
+ scroll_start(); // may scroll the screen to the right position
+
/*
* Don't clear the screen when starting in Ex mode, unless using the GUI.
*/
diff --git a/src/nvim/memory.c b/src/nvim/memory.c
index f959ea55e4..c221b13f8b 100644
--- a/src/nvim/memory.c
+++ b/src/nvim/memory.c
@@ -234,6 +234,43 @@ void memchrsub(void *data, char c, char x, size_t len)
}
}
+/// Counts the number of occurrences of `c` in `str`.
+///
+/// @warning Unsafe if `c == NUL`.
+///
+/// @param str Pointer to the string to search.
+/// @param c The byte to search for.
+/// @returns the number of occurrences of `c` in `str`.
+size_t strcnt(const char *str, char c, size_t len)
+ FUNC_ATTR_NONNULL_ALL FUNC_ATTR_PURE
+{
+ assert(c != 0);
+ size_t cnt = 0;
+ while ((str = strchr(str, c))) {
+ cnt++;
+ str++; // Skip the instance of c.
+ }
+ return cnt;
+}
+
+/// Counts the number of occurrences of byte `c` in `data[len]`.
+///
+/// @param data Pointer to the data to search.
+/// @param c The byte to search for.
+/// @param len The length of `data`.
+/// @returns the number of occurrences of `c` in `data[len]`.
+size_t memcnt(const void *data, char c, size_t len)
+ FUNC_ATTR_NONNULL_ALL FUNC_ATTR_PURE
+{
+ size_t cnt = 0;
+ const char *ptr = data, *end = ptr + len;
+ while ((ptr = memchr(ptr, c, (size_t)(end - ptr))) != NULL) {
+ cnt++;
+ ptr++; // Skip the instance of c.
+ }
+ return cnt;
+}
+
/// The xstpcpy() function shall copy the string pointed to by src (including
/// the terminating NUL character) into the array pointed to by dst.
///
diff --git a/src/nvim/menu.c b/src/nvim/menu.c
index 1573aaae84..b31b6c1cec 100644
--- a/src/nvim/menu.c
+++ b/src/nvim/menu.c
@@ -1424,6 +1424,12 @@ typedef struct {
static garray_T menutrans_ga = GA_EMPTY_INIT_VALUE;
+#define FREE_MENUTRANS(mt) \
+ menutrans_T* _mt = (mt); \
+ free(_mt->from); \
+ free(_mt->from_noamp); \
+ free(_mt->to)
+
/*
* ":menutrans".
* This function is also defined without the +multi_lang feature, in which
@@ -1441,13 +1447,8 @@ void ex_menutranslate(exarg_T *eap)
* ":menutrans clear": clear all translations.
*/
if (STRNCMP(arg, "clear", 5) == 0 && ends_excmd(*skipwhite(arg + 5))) {
- menutrans_T *tp = (menutrans_T *)menutrans_ga.ga_data;
- for (int i = 0; i < menutrans_ga.ga_len; ++i) {
- free(tp[i].from);
- free(tp[i].from_noamp);
- free(tp[i].to);
- }
- ga_clear(&menutrans_ga);
+ GA_DEEP_CLEAR(&menutrans_ga, menutrans_T, FREE_MENUTRANS);
+
/* Delete all "menutrans_" global variables. */
del_menutrans_vars();
} else {
diff --git a/src/nvim/message.c b/src/nvim/message.c
index cd0c548fb4..808253d33c 100644
--- a/src/nvim/message.c
+++ b/src/nvim/message.c
@@ -145,7 +145,7 @@ int verb_msg(char_u *s)
return n;
}
-int msg_attr(char_u *s, int attr)
+int msg_attr(char_u *s, int attr) FUNC_ATTR_NONNULL_ARG(1)
{
return msg_attr_keep(s, attr, FALSE);
}
@@ -156,6 +156,7 @@ msg_attr_keep (
int attr,
int keep /* TRUE: set keep_msg if it doesn't scroll */
)
+ FUNC_ATTR_NONNULL_ARG(1)
{
static int entered = 0;
int retval;
@@ -2623,7 +2624,7 @@ int verbose_open(void)
* Give a warning message (for searching).
* Use 'w' highlighting and may repeat the message after redrawing
*/
-void give_warning(char_u *message, bool hl)
+void give_warning(char_u *message, bool hl) FUNC_ATTR_NONNULL_ARG(1)
{
/* Don't do this for ":silent". */
if (msg_silent != 0)
@@ -3623,13 +3624,7 @@ int vim_vsnprintf(char *str, size_t str_m, char *fmt, va_list ap, typval_T *tvs)
remove_trailing_zeroes = TRUE;
}
- if (fmt_spec == 'f' &&
-#ifdef VAX
- abs_f > 1.0e38
-#else
- abs_f > 1.0e307
-#endif
- ) {
+ if (fmt_spec == 'f' && abs_f > 1.0e307) {
/* Avoid a buffer overflow */
strcpy(tmp, "inf");
str_arg_l = 3;
diff --git a/src/nvim/mouse.c b/src/nvim/mouse.c
index 439cdbd5c8..9f67bd1760 100644
--- a/src/nvim/mouse.c
+++ b/src/nvim/mouse.c
@@ -452,7 +452,7 @@ void setmouse(void)
return;
/* don't switch mouse on when not in raw mode (Ex mode) */
- if (cur_tmode != TMODE_RAW) {
+ if (!abstract_ui && cur_tmode != TMODE_RAW) {
mch_setmouse(false);
return;
}
@@ -470,10 +470,11 @@ void setmouse(void)
else
checkfor = MOUSE_NORMAL; /* assume normal mode */
- if (mouse_has(checkfor))
- mch_setmouse(true);
- else
- mch_setmouse(false);
+ if (mouse_has(checkfor)) {
+ ui_mouse_on();
+ } else {
+ ui_mouse_off();
+ }
}
/*
diff --git a/src/nvim/msgpack_rpc/channel.c b/src/nvim/msgpack_rpc/channel.c
index 0c04a7b23e..4c35cce09a 100644
--- a/src/nvim/msgpack_rpc/channel.c
+++ b/src/nvim/msgpack_rpc/channel.c
@@ -10,6 +10,7 @@
#include "nvim/api/private/helpers.h"
#include "nvim/api/vim.h"
#include "nvim/msgpack_rpc/channel.h"
+#include "nvim/msgpack_rpc/remote_ui.h"
#include "nvim/os/event.h"
#include "nvim/os/rstream.h"
#include "nvim/os/rstream_defs.h"
@@ -100,6 +101,17 @@ void channel_init(void)
if (embedded_mode) {
channel_from_stdio();
}
+
+ if (abstract_ui) {
+ // Add handler for "attach_ui"
+ remote_ui_init();
+ String method = cstr_as_string("attach_ui");
+ MsgpackRpcRequestHandler handler = {.fn = remote_ui_attach, .defer = true};
+ msgpack_rpc_add_method_handler(method, handler);
+ method = cstr_as_string("detach_ui");
+ handler.fn = remote_ui_detach;
+ msgpack_rpc_add_method_handler(method, handler);
+ }
}
/// Teardown the module
@@ -241,6 +253,7 @@ Object channel_send_call(uint64_t id,
if (frame.errored) {
api_set_error(err, Exception, "%s", frame.result.data.string.data);
+ api_free_object(frame.result);
return NIL;
}
@@ -347,7 +360,13 @@ static void job_err(RStream *rstream, void *data, bool eof)
static void job_exit(Job *job, void *data)
{
- free_channel((Channel *)data);
+ Channel *channel = data;
+ // ensure the channel is flagged as closed so channel_send_call frees it
+ // later
+ channel->closed = true;
+ if (!kv_size(channel->call_stack)) {
+ free_channel(channel);
+ }
}
static void parse_msgpack(RStream *rstream, void *data, bool eof)
@@ -638,6 +657,10 @@ static void on_stdio_close(Event e)
static void free_channel(Channel *channel)
{
+ if (abstract_ui) {
+ remote_ui_disconnect(channel->id);
+ }
+
pmap_del(uint64_t)(channels, channel->id);
msgpack_unpacker_free(channel->unpacker);
diff --git a/src/nvim/msgpack_rpc/defs.h b/src/nvim/msgpack_rpc/defs.h
index 13067fb7b4..0492a65290 100644
--- a/src/nvim/msgpack_rpc/defs.h
+++ b/src/nvim/msgpack_rpc/defs.h
@@ -19,6 +19,10 @@ typedef struct {
/// Initializes the msgpack-rpc method table
void msgpack_rpc_init_method_table(void);
+// Add a handler to the method table
+void msgpack_rpc_add_method_handler(String method,
+ MsgpackRpcRequestHandler handler);
+
void msgpack_rpc_init_function_metadata(Dictionary *metadata);
/// Dispatches to the actual API function after basic payload validation by
diff --git a/src/nvim/msgpack_rpc/remote_ui.c b/src/nvim/msgpack_rpc/remote_ui.c
new file mode 100644
index 0000000000..f980a77b4c
--- /dev/null
+++ b/src/nvim/msgpack_rpc/remote_ui.c
@@ -0,0 +1,280 @@
+#include <assert.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <stdbool.h>
+
+#include "nvim/vim.h"
+#include "nvim/ui.h"
+#include "nvim/memory.h"
+#include "nvim/map.h"
+#include "nvim/msgpack_rpc/remote_ui.h"
+#include "nvim/msgpack_rpc/channel.h"
+#include "nvim/api/private/defs.h"
+#include "nvim/api/private/helpers.h"
+
+#ifdef INCLUDE_GENERATED_DECLARATIONS
+# include "msgpack_rpc/remote_ui.c.generated.h"
+#endif
+
+typedef struct {
+ uint64_t channel_id;
+ Array buffer;
+} UIData;
+
+static PMap(uint64_t) *connected_uis = NULL;
+
+void remote_ui_init(void)
+{
+ connected_uis = pmap_new(uint64_t)();
+}
+
+Object remote_ui_attach(uint64_t channel_id, uint64_t request_id, Array args,
+ Error *error)
+{
+ if (pmap_has(uint64_t)(connected_uis, channel_id)) {
+ api_set_error(error, Exception, _("UI already attached for channel"));
+ return NIL;
+ }
+
+ if (args.size != 2 || args.items[0].type != kObjectTypeInteger
+ || args.items[1].type != kObjectTypeInteger
+ || args.items[0].data.integer <= 0 || args.items[1].data.integer <= 0) {
+ api_set_error(error, Validation,
+ _("Arguments must be a pair of positive integers "
+ "representing the remote screen width/height"));
+ return NIL;
+ }
+ UIData *data = xmalloc(sizeof(UIData));
+ data->channel_id = channel_id;
+ data->buffer = (Array)ARRAY_DICT_INIT;
+ UI *ui = xcalloc(1, sizeof(UI));
+ ui->width = (int)args.items[0].data.integer;
+ ui->height = (int)args.items[1].data.integer;
+ ui->data = data;
+ ui->resize = remote_ui_resize;
+ ui->clear = remote_ui_clear;
+ ui->eol_clear = remote_ui_eol_clear;
+ ui->cursor_goto = remote_ui_cursor_goto;
+ ui->cursor_on = remote_ui_cursor_on;
+ ui->cursor_off = remote_ui_cursor_off;
+ ui->mouse_on = remote_ui_mouse_on;
+ ui->mouse_off = remote_ui_mouse_off;
+ ui->insert_mode = remote_ui_insert_mode;
+ ui->normal_mode = remote_ui_normal_mode;
+ ui->set_scroll_region = remote_ui_set_scroll_region;
+ ui->scroll = remote_ui_scroll;
+ ui->highlight_set = remote_ui_highlight_set;
+ ui->put = remote_ui_put;
+ ui->bell = remote_ui_bell;
+ ui->visual_bell = remote_ui_visual_bell;
+ ui->flush = remote_ui_flush;
+ ui->suspend = remote_ui_suspend;
+ pmap_put(uint64_t)(connected_uis, channel_id, ui);
+ ui_attach(ui);
+
+ return NIL;
+}
+
+Object remote_ui_detach(uint64_t channel_id, uint64_t request_id, Array args,
+ Error *error)
+{
+ if (!pmap_has(uint64_t)(connected_uis, channel_id)) {
+ api_set_error(error, Exception, _("UI is not attached for channel"));
+ }
+ remote_ui_disconnect(channel_id);
+
+ return NIL;
+}
+
+void remote_ui_disconnect(uint64_t channel_id)
+{
+ UI *ui = pmap_get(uint64_t)(connected_uis, channel_id);
+ if (!ui) {
+ return;
+ }
+ UIData *data = ui->data;
+ // destroy pending screen updates
+ api_free_array(data->buffer);
+ pmap_del(uint64_t)(connected_uis, channel_id);
+ free(ui->data);
+ ui_detach(ui);
+ free(ui);
+}
+
+static void push_call(UI *ui, char *name, Array args)
+{
+ Array call = ARRAY_DICT_INIT;
+ UIData *data = ui->data;
+
+ // To optimize data transfer(especially for "put"), we bundle adjacent
+ // calls to same method together, so only add a new call entry if the last
+ // method call is different from "name"
+ if (kv_size(data->buffer)) {
+ call = kv_A(data->buffer, kv_size(data->buffer) - 1).data.array;
+ }
+
+ if (!kv_size(call) || strcmp(kv_A(call, 0).data.string.data, name)) {
+ call = (Array)ARRAY_DICT_INIT;
+ ADD(data->buffer, ARRAY_OBJ(call));
+ ADD(call, STRING_OBJ(cstr_to_string(name)));
+ }
+
+ ADD(call, ARRAY_OBJ(args));
+ kv_A(data->buffer, kv_size(data->buffer) - 1).data.array = call;
+}
+
+static void remote_ui_resize(UI *ui, int width, int height)
+{
+ Array args = ARRAY_DICT_INIT;
+ ADD(args, INTEGER_OBJ(width));
+ ADD(args, INTEGER_OBJ(height));
+ push_call(ui, "resize", args);
+}
+
+static void remote_ui_clear(UI *ui)
+{
+ Array args = ARRAY_DICT_INIT;
+ push_call(ui, "clear", args);
+}
+
+static void remote_ui_eol_clear(UI *ui)
+{
+ Array args = ARRAY_DICT_INIT;
+ push_call(ui, "eol_clear", args);
+}
+
+static void remote_ui_cursor_goto(UI *ui, int row, int col)
+{
+ Array args = ARRAY_DICT_INIT;
+ ADD(args, INTEGER_OBJ(row));
+ ADD(args, INTEGER_OBJ(col));
+ push_call(ui, "cursor_goto", args);
+}
+
+static void remote_ui_cursor_on(UI *ui)
+{
+ Array args = ARRAY_DICT_INIT;
+ push_call(ui, "cursor_on", args);
+}
+
+static void remote_ui_cursor_off(UI *ui)
+{
+ Array args = ARRAY_DICT_INIT;
+ push_call(ui, "cursor_off", args);
+}
+
+static void remote_ui_mouse_on(UI *ui)
+{
+ Array args = ARRAY_DICT_INIT;
+ push_call(ui, "mouse_on", args);
+}
+
+static void remote_ui_mouse_off(UI *ui)
+{
+ Array args = ARRAY_DICT_INIT;
+ push_call(ui, "mouse_off", args);
+}
+
+static void remote_ui_insert_mode(UI *ui)
+{
+ Array args = ARRAY_DICT_INIT;
+ push_call(ui, "insert_mode", args);
+}
+
+static void remote_ui_normal_mode(UI *ui)
+{
+ Array args = ARRAY_DICT_INIT;
+ push_call(ui, "normal_mode", args);
+}
+
+static void remote_ui_set_scroll_region(UI *ui, int top, int bot, int left,
+ int right)
+{
+ Array args = ARRAY_DICT_INIT;
+ ADD(args, INTEGER_OBJ(top));
+ ADD(args, INTEGER_OBJ(bot));
+ ADD(args, INTEGER_OBJ(left));
+ ADD(args, INTEGER_OBJ(right));
+ push_call(ui, "set_scroll_region", args);
+}
+
+static void remote_ui_scroll(UI *ui, int count)
+{
+ Array args = ARRAY_DICT_INIT;
+ ADD(args, INTEGER_OBJ(count));
+ push_call(ui, "scroll", args);
+}
+
+static void remote_ui_highlight_set(UI *ui, HlAttrs attrs)
+{
+ Array args = ARRAY_DICT_INIT;
+ Dictionary hl = ARRAY_DICT_INIT;
+
+ if (attrs.bold) {
+ PUT(hl, "bold", BOOLEAN_OBJ(true));
+ }
+
+ if (attrs.standout) {
+ PUT(hl, "standout", BOOLEAN_OBJ(true));
+ }
+
+ if (attrs.underline) {
+ PUT(hl, "underline", BOOLEAN_OBJ(true));
+ }
+
+ if (attrs.undercurl) {
+ PUT(hl, "undercurl", BOOLEAN_OBJ(true));
+ }
+
+ if (attrs.italic) {
+ PUT(hl, "italic", BOOLEAN_OBJ(true));
+ }
+
+ if (attrs.reverse) {
+ PUT(hl, "reverse", BOOLEAN_OBJ(true));
+ }
+
+ if (attrs.foreground != -1) {
+ PUT(hl, "foreground", INTEGER_OBJ(attrs.foreground));
+ }
+
+ if (attrs.background != -1) {
+ PUT(hl, "background", INTEGER_OBJ(attrs.background));
+ }
+
+ ADD(args, DICTIONARY_OBJ(hl));
+ push_call(ui, "highlight_set", args);
+}
+
+static void remote_ui_put(UI *ui, uint8_t *data, size_t size)
+{
+ Array args = ARRAY_DICT_INIT;
+ String str = {.data = xmemdupz(data, size), .size = size};
+ ADD(args, STRING_OBJ(str));
+ push_call(ui, "put", args);
+}
+
+static void remote_ui_bell(UI *ui)
+{
+ Array args = ARRAY_DICT_INIT;
+ push_call(ui, "bell", args);
+}
+
+static void remote_ui_visual_bell(UI *ui)
+{
+ Array args = ARRAY_DICT_INIT;
+ push_call(ui, "visual_bell", args);
+}
+
+static void remote_ui_flush(UI *ui)
+{
+ UIData *data = ui->data;
+ channel_send_event(data->channel_id, "redraw", data->buffer);
+ data->buffer = (Array)ARRAY_DICT_INIT;
+}
+
+static void remote_ui_suspend(UI *ui)
+{
+ UIData *data = ui->data;
+ remote_ui_disconnect(data->channel_id);
+}
diff --git a/src/nvim/msgpack_rpc/remote_ui.h b/src/nvim/msgpack_rpc/remote_ui.h
new file mode 100644
index 0000000000..8af86dc1b8
--- /dev/null
+++ b/src/nvim/msgpack_rpc/remote_ui.h
@@ -0,0 +1,9 @@
+#ifndef NVIM_MSGPACK_RPC_REMOTE_UI_H
+#define NVIM_MSGPACK_RPC_REMOTE_UI_H
+
+#include "nvim/ui.h"
+
+#ifdef INCLUDE_GENERATED_DECLARATIONS
+# include "msgpack_rpc/remote_ui.h.generated.h"
+#endif
+#endif // NVIM_MSGPACK_RPC_REMOTE_UI_H
diff --git a/src/nvim/normal.c b/src/nvim/normal.c
index 1b21100933..3b4d4047db 100644
--- a/src/nvim/normal.c
+++ b/src/nvim/normal.c
@@ -915,14 +915,7 @@ getcount:
&& !oap->op_type
&& (idx < 0 || !(nv_cmds[idx].cmd_flags & NV_KEEPREG))) {
clearop(oap);
- {
- int regname = 0;
-
- /* Adjust the register according to 'clipboard', so that when
- * "unnamed" is present it becomes '*' or '+' instead of '"'. */
- adjust_clipboard_register(&regname);
- set_reg_var(regname);
- }
+ set_reg_var(0);
}
/* Get the length of mapped chars again after typing a count, second
@@ -1863,21 +1856,21 @@ do_mouse (
save_cursor = curwin->w_cursor;
- /*
- * When GUI is active, always recognize mouse events, otherwise:
- * - Ignore mouse event in normal mode if 'mouse' doesn't include 'n'.
- * - Ignore mouse event in visual mode if 'mouse' doesn't include 'v'.
- * - For command line and insert mode 'mouse' is checked before calling
- * do_mouse().
- */
- if (do_always)
- do_always = false;
- else {
- if (VIsual_active) {
- if (!mouse_has(MOUSE_VISUAL))
+ // When "abstract_ui" is active, always recognize mouse events, otherwise:
+ // - Ignore mouse event in normal mode if 'mouse' doesn't include 'n'.
+ // - Ignore mouse event in visual mode if 'mouse' doesn't include 'v'.
+ // - For command line and insert mode 'mouse' is checked before calling
+ // do_mouse().
+ if (!abstract_ui) {
+ if (do_always)
+ do_always = false;
+ else {
+ if (VIsual_active) {
+ if (!mouse_has(MOUSE_VISUAL))
+ return false;
+ } else if (State == NORMAL && !mouse_has(MOUSE_NORMAL))
return false;
- } else if (State == NORMAL && !mouse_has(MOUSE_NORMAL))
- return false;
+ }
}
for (;; ) {
@@ -2109,7 +2102,7 @@ do_mouse (
* Windows only shows the popup menu on the button up event.
*/
#if defined(FEAT_GUI_MOTIF) || defined(FEAT_GUI_GTK) \
- || defined(FEAT_GUI_PHOTON) || defined(FEAT_GUI_MAC)
+ || defined(FEAT_GUI_MAC)
if (!is_click)
return false;
#endif
@@ -5105,7 +5098,6 @@ static void nv_brackets(cmdarg_T *cap)
end = equalpos(start, VIsual) ? curwin->w_cursor : VIsual;
curwin->w_cursor = (dir == BACKWARD ? start : end);
}
- adjust_clipboard_register(&regname);
prep_redo_cmd(cap);
do_put(regname, dir, cap->count1, PUT_FIXINDENT);
if (was_visual) {
@@ -7272,10 +7264,8 @@ static void nv_put(cmdarg_T *cap)
*/
was_visual = true;
regname = cap->oap->regname;
- bool adjusted = adjust_clipboard_register(&regname);
if (regname == 0 || regname == '"'
|| VIM_ISDIGIT(regname) || regname == '-'
- || adjusted
) {
/* The delete is going to overwrite the register we want to
* put, save it first. */
diff --git a/src/nvim/ops.c b/src/nvim/ops.c
index 6bf3f6036f..32b37b6458 100644
--- a/src/nvim/ops.c
+++ b/src/nvim/ops.c
@@ -60,6 +60,7 @@
#define DELETION_REGISTER 36
#define CLIP_REGISTER 37
+# define CB_UNNAMEDMASK (CB_UNNAMED | CB_UNNAMEDPLUS)
/*
* Each yank register is an array of pointers to lines.
*/
@@ -74,6 +75,7 @@ static struct yankreg *y_current; /* ptr to current yankreg */
static int y_append; /* TRUE when appending */
static struct yankreg *y_previous = NULL; /* ptr to last written yankreg */
+static bool clipboard_didwarn_unnamed = false;
/*
* structure used by block_prep, op_delete and op_yank for blockwise operators
* also op_change, op_shift, op_insert, op_replace - AKelly
@@ -751,7 +753,8 @@ void get_yank_register(int regname, int writing)
int i;
y_append = FALSE;
- if ((regname == 0 || regname == '"') && !writing && y_previous != NULL) {
+ int unnamedclip = cb_flags & CB_UNNAMEDMASK;
+ if ((regname == 0 || regname == '"') && !unnamedclip && !writing && y_previous != NULL) {
y_current = y_previous;
return;
}
@@ -1302,18 +1305,6 @@ cmdline_paste_reg (
return OK;
}
-bool adjust_clipboard_register(int *rp)
-{
- // If no reg. specified and 'unnamedclip' is set, use the
- // clipboard register.
- if (*rp == 0 && p_unc && eval_has_provider("clipboard")) {
- *rp = '+';
- return true;
- }
-
- return false;
-}
-
/*
* Handle a delete operation.
*
@@ -1328,7 +1319,6 @@ int op_delete(oparg_T *oap)
struct block_def bd;
linenr_T old_lcount = curbuf->b_ml.ml_line_count;
int did_yank = FALSE;
- int orig_regname = oap->regname;
if (curbuf->b_ml.ml_flags & ML_EMPTY) /* nothing to do */
return OK;
@@ -1342,8 +1332,6 @@ int op_delete(oparg_T *oap)
return FAIL;
}
- bool adjusted = adjust_clipboard_register(&oap->regname);
-
if (has_mbyte)
mb_adjust_opend(oap);
@@ -1393,9 +1381,10 @@ int op_delete(oparg_T *oap)
* register. For the black hole register '_' don't yank anything.
*/
if (oap->regname != '_') {
- if (oap->regname != 0) {
+ bool unnamedclip = oap->regname == 0 && (cb_flags & CB_UNNAMEDMASK);
+ if (oap->regname != 0 || unnamedclip) {
/* check for read-only register */
- if (!valid_yank_reg(oap->regname, TRUE)) {
+ if (!( valid_yank_reg(oap->regname, TRUE) || unnamedclip )) {
beep_flush();
return OK;
}
@@ -1407,10 +1396,8 @@ int op_delete(oparg_T *oap)
/*
* Put deleted text into register 1 and shift number registers if the
* delete contains a line break, or when a regname has been specified.
- * Use the register name from before adjust_clip_reg() may have
- * changed it.
*/
- if (orig_regname != 0 || oap->motion_type == MLINE
+ if (oap->regname != 0 || oap->motion_type == MLINE
|| oap->line_count > 1 || oap->use_reg_one) {
y_current = &y_regs[9];
free_yank_all(); /* free register nine */
@@ -1424,9 +1411,7 @@ int op_delete(oparg_T *oap)
/* Yank into small delete register when no named register specified
* and the delete is within one line. */
- if ((
- adjusted ||
- oap->regname == 0) && oap->motion_type != MLINE
+ if (oap->regname == 0 && oap->motion_type != MLINE
&& oap->line_count == 1) {
oap->regname = '-';
get_yank_register(oap->regname, TRUE);
@@ -2623,7 +2608,6 @@ do_put (
int allocated = FALSE;
long cnt;
- adjust_clipboard_register(&regname);
get_clipboard(regname);
if (flags & PUT_FIXINDENT)
@@ -3215,7 +3199,6 @@ void ex_display(exarg_T *eap)
)
continue; /* did not ask for this register */
- adjust_clipboard_register(&name);
get_clipboard(name);
if (i == -1) {
@@ -4671,30 +4654,43 @@ char_u get_reg_type(int regname, long *reglen)
return MAUTO;
}
-/*
- * Return the contents of a register as a single allocated string.
- * Used for "@r" in expressions and for getreg().
- * Returns NULL for error.
- */
-char_u *
-get_reg_contents (
- int regname,
- int allowexpr, /* allow "=" register */
- int expr_src /* get expression for "=" register */
-)
+/// When `flags` has `kGRegList` return a list with text `s`.
+/// Otherwise just return `s`.
+///
+/// Returns a void * for use in get_reg_contents().
+static void *get_reg_wrap_one_line(char_u *s, int flags)
+{
+ if (!(flags & kGRegList)) {
+ return s;
+ }
+ list_T *list = list_alloc();
+ list_append_string(list, NULL, -1);
+ list->lv_first->li_tv.vval.v_string = s;
+ return list;
+}
+
+/// Gets the contents of a register.
+/// @remark Used for `@r` in expressions and for `getreg()`.
+///
+/// @param regname The register.
+/// @param flags see @ref GRegFlags
+///
+/// @returns The contents of the register as an allocated string.
+/// @returns A linked list when `flags` contains @ref kGRegList.
+/// @returns NULL for error.
+void *get_reg_contents(int regname, int flags)
{
long i;
- char_u *retval;
- int allocated;
- /* Don't allow using an expression register inside an expression */
+ // Don't allow using an expression register inside an expression.
if (regname == '=') {
- if (allowexpr) {
- if (expr_src)
- return get_expr_line_src();
- return get_expr_line();
+ if (flags & kGRegNoExpr) {
+ return NULL;
}
- return NULL;
+ if (flags & kGRegExprSrc) {
+ return get_reg_wrap_one_line(get_expr_line_src(), flags);
+ }
+ return get_reg_wrap_one_line(get_expr_line(), flags);
}
if (regname == '@') /* "@@" is used for unnamed register */
@@ -4706,18 +4702,30 @@ get_reg_contents (
get_clipboard(regname);
+ char_u *retval;
+ int allocated;
if (get_spec_reg(regname, &retval, &allocated, FALSE)) {
if (retval == NULL)
return NULL;
- if (!allocated)
- retval = vim_strsave(retval);
- return retval;
+ if (allocated) {
+ return get_reg_wrap_one_line(retval, flags);
+ }
+ return get_reg_wrap_one_line(vim_strsave(retval), flags);
}
get_yank_register(regname, FALSE);
if (y_current->y_array == NULL)
return NULL;
+ if (flags & kGRegList) {
+ list_T *list = list_alloc();
+ for (int i = 0; i < y_current->y_size; ++i) {
+ list_append_string(list, y_current->y_array[i], -1);
+ }
+
+ return list;
+ }
+
/*
* Compute length of resulting string.
*/
@@ -4754,17 +4762,77 @@ get_reg_contents (
return retval;
}
+static bool init_write_reg(int name, struct yankreg **old_y_previous,
+ struct yankreg **old_y_current, int must_append)
+{
+ if (!valid_yank_reg(name, true)) { // check for valid reg name
+ emsg_invreg(name);
+ return false;
+ }
+
+ // Don't want to change the current (unnamed) register.
+ *old_y_previous = y_previous;
+ *old_y_current = y_current;
+
+ get_yank_register(name, true);
+ if (!y_append && !must_append) {
+ free_yank_all();
+ }
+ return true;
+}
+
+static void finish_write_reg(int name, struct yankreg *old_y_previous,
+ struct yankreg *old_y_current)
+{
+ // Send text of clipboard register to the clipboard.
+ set_clipboard(name);
+
+ // ':let @" = "val"' should change the meaning of the "" register
+ if (name != '"') {
+ y_previous = old_y_previous;
+ }
+ y_current = old_y_current;
+}
+
/// write_reg_contents - store `str` in register `name`
///
/// @see write_reg_contents_ex
-void write_reg_contents(int name,
- const char_u *str,
- ssize_t len,
+void write_reg_contents(int name, const char_u *str, ssize_t len,
int must_append)
{
write_reg_contents_ex(name, str, len, must_append, MAUTO, 0L);
}
+void write_reg_contents_lst(int name, char_u **strings, int maxlen,
+ int must_append, int yank_type, long block_len)
+{
+ if (name == '/' || name == '=') {
+ char_u *s = strings[0];
+ if (strings[0] == NULL) {
+ s = (char_u *)"";
+ } else if (strings[1] != NULL) {
+ EMSG(_("E883: search pattern and expression register may not "
+ "contain two or more lines"));
+ return;
+ }
+ write_reg_contents_ex(name, s, -1, must_append, yank_type, block_len);
+ return;
+ }
+
+ // black hole: nothing to do
+ if (name == '_') {
+ return;
+ }
+
+ struct yankreg *old_y_previous, *old_y_current;
+ if (!init_write_reg(name, &old_y_previous, &old_y_current, must_append)) {
+ return;
+ }
+
+ str_to_reg(y_current, yank_type, (char_u *) strings, -1, block_len, true);
+ finish_write_reg(name, old_y_previous, old_y_current);
+}
+
/// write_reg_contents_ex - store `str` in register `name`
///
/// If `str` ends in '\n' or '\r', use linewise, otherwise use
@@ -4791,8 +4859,6 @@ void write_reg_contents_ex(int name,
int yank_type,
long block_len)
{
- struct yankreg *old_y_previous, *old_y_current;
-
if (len < 0) {
len = (ssize_t) STRLEN(str);
}
@@ -4826,28 +4892,16 @@ void write_reg_contents_ex(int name,
return;
}
- if (!valid_yank_reg(name, TRUE)) { /* check for valid reg name */
- emsg_invreg(name);
+ if (name == '_') { // black hole: nothing to do
return;
}
- if (name == '_') /* black hole: nothing to do */
- return;
-
- /* Don't want to change the current (unnamed) register */
- old_y_previous = y_previous;
- old_y_current = y_current;
-
- get_yank_register(name, TRUE);
- if (!y_append && !must_append)
- free_yank_all();
- str_to_reg(y_current, yank_type, str, len, block_len);
-
-
- /* ':let @" = "val"' should change the meaning of the "" register */
- if (name != '"')
- y_previous = old_y_previous;
- y_current = old_y_current;
+ struct yankreg *old_y_previous, *old_y_current;
+ if (!init_write_reg(name, &old_y_previous, &old_y_current, must_append)) {
+ return;
+ }
+ str_to_reg(y_current, yank_type, str, len, block_len, false);
+ finish_write_reg(name, old_y_previous, old_y_current);
}
/// str_to_reg - Put a string into a register.
@@ -4856,100 +4910,100 @@ void write_reg_contents_ex(int name,
///
/// @param y_ptr pointer to yank register
/// @param yank_type MCHAR, MLINE, MBLOCK or MAUTO
-/// @param str string to put in register
-/// @param len length of the string
-/// @param blocklen width of visual block
-static void str_to_reg(struct yankreg *y_ptr,
- int yank_type,
- const char_u *str,
- long len,
- long blocklen)
+/// @param str string or list of strings to put in register
+/// @param len length of the string (Ignored when str_list=true.)
+/// @param blocklen width of visual block, or -1 for "I don't know."
+/// @param str_list True if str is `char_u **`.
+static void str_to_reg(struct yankreg *y_ptr, int yank_type, const char_u *str,
+ size_t len, colnr_T blocklen, bool str_list)
+ FUNC_ATTR_NONNULL_ALL
{
- int type; /* MCHAR, MLINE or MBLOCK */
- int lnum;
- long start;
- long i;
- int extra;
- size_t newlines; /* number of lines added */
- int extraline = 0; /* extra line at the end */
- int append = FALSE; /* append to last line in register */
- char_u *s;
- char_u **pp;
- long maxlen;
-
- if (y_ptr->y_array == NULL) /* NULL means empty register */
+ if (y_ptr->y_array == NULL) { // NULL means empty register
y_ptr->y_size = 0;
+ }
- if (yank_type == MAUTO)
- type = ((len > 0 && (str[len - 1] == NL || str[len - 1] == CAR))
+ int type = yank_type; // MCHAR, MLINE or MBLOCK
+ if (yank_type == MAUTO) {
+ type = ((str_list ||
+ (len > 0 && (str[len - 1] == NL || str[len - 1] == CAR)))
? MLINE : MCHAR);
- else
- type = yank_type;
-
- /*
- * Count the number of lines within the string
- */
- newlines = 0;
- for (i = 0; i < len; i++)
- if (str[i] == '\n')
- ++newlines;
- if (type == MCHAR || len == 0 || str[len - 1] != '\n') {
- extraline = 1;
- ++newlines; /* count extra newline at the end */
}
- if (y_ptr->y_size > 0 && y_ptr->y_type == MCHAR) {
- append = TRUE;
- --newlines; /* uncount newline when appending first line */
+
+ size_t newlines = 0;
+ bool extraline = false; // extra line at the end
+ bool append = false; // append to last line in register
+
+ // Count the number of lines within the string
+ if (str_list) {
+ for (char_u **ss = (char_u **) str; *ss != NULL; ++ss) {
+ newlines++;
+ }
+ } else {
+ newlines = memcnt(str, '\n', len);
+ if (type == MCHAR || len == 0 || str[len - 1] != '\n') {
+ extraline = 1;
+ ++newlines; // count extra newline at the end
+ }
+ if (y_ptr->y_size > 0 && y_ptr->y_type == MCHAR) {
+ append = true;
+ --newlines; // uncount newline when appending first line
+ }
}
- /*
- * Allocate an array to hold the pointers to the new register lines.
- * If the register was not empty, move the existing lines to the new array.
- */
- pp = xcalloc((y_ptr->y_size + newlines), sizeof(char_u *));
- for (lnum = 0; lnum < y_ptr->y_size; ++lnum)
- pp[lnum] = y_ptr->y_array[lnum];
- free(y_ptr->y_array);
+
+ // Grow the register array to hold the pointers to the new lines.
+ char_u **pp = xrealloc(y_ptr->y_array,
+ (y_ptr->y_size + newlines) * sizeof(char_u *));
y_ptr->y_array = pp;
- maxlen = 0;
- /*
- * Find the end of each line and save it into the array.
- */
- for (start = 0; start < len + extraline; start += i + 1) {
- // Let i represent the length of one line.
- const char_u *p = str + start;
- i = (char_u *)xmemscan(p, '\n', len - start) - p;
- if (i > maxlen)
- maxlen = i;
- if (append) {
- --lnum;
- extra = (int)STRLEN(y_ptr->y_array[lnum]);
- } else
- extra = 0;
- s = xmalloc(i + extra + 1);
- if (extra)
- memmove(s, y_ptr->y_array[lnum], (size_t)extra);
- if (append)
- free(y_ptr->y_array[lnum]);
- if (i)
- memmove(s + extra, str + start, (size_t)i);
- extra += i;
- s[extra] = NUL;
- y_ptr->y_array[lnum++] = s;
- while (--extra >= 0) {
- if (*s == NUL)
- *s = '\n'; /* replace NUL with newline */
- ++s;
+ linenr_T lnum = y_ptr->y_size; // The current line number.
+
+ // If called with `blocklen < 0`, we have to update the yank reg's width.
+ size_t maxlen = 0;
+
+ // Find the end of each line and save it into the array.
+ if (str_list) {
+ for (char_u **ss = (char_u **) str; *ss != NULL; ++ss, ++lnum) {
+ size_t ss_len = STRLEN(*ss);
+ pp[lnum] = xmemdupz(*ss, ss_len);
+ if (ss_len > maxlen) {
+ maxlen = ss_len;
+ }
+ }
+ } else {
+ size_t line_len;
+ for (const char_u *start = str, *end = str + len;
+ start < end + extraline;
+ start += line_len + 1, lnum++) {
+ line_len = (const char_u *) xmemscan(start, '\n', end - start) - start;
+ if (line_len > maxlen) {
+ maxlen = line_len;
+ }
+
+ // When appending, copy the previous line and free it after.
+ size_t extra = append ? STRLEN(pp[--lnum]) : 0;
+ char_u *s = xmallocz(line_len + extra);
+ memcpy(s, pp[lnum], extra);
+ memcpy(s + extra, start, line_len);
+ ssize_t s_len = extra + line_len;
+
+ if (append) {
+ free(pp[lnum]);
+ append = false; // only first line is appended
+ }
+ pp[lnum] = s;
+
+ // Convert NULs to '\n' to prevent truncation.
+ memchrsub(pp[lnum], NUL, '\n', s_len);
}
- append = FALSE; /* only first line is appended */
}
y_ptr->y_type = type;
y_ptr->y_size = lnum;
- if (type == MBLOCK)
- y_ptr->y_width = (blocklen < 0 ? maxlen - 1 : blocklen);
- else
+ if (type == MBLOCK) {
+ y_ptr->y_width = (blocklen == -1 ? (colnr_T) maxlen - 1 : blocklen);
+ } else {
y_ptr->y_width = 0;
+ }
}
void clear_oparg(oparg_T *oap)
@@ -5225,33 +5279,82 @@ static void free_register(struct yankreg *reg)
y_current = curr;
}
-static void copy_register(struct yankreg *dest, struct yankreg *src)
-{
- free_register(dest);
- *dest = *src;
- dest->y_array = xcalloc(src->y_size, sizeof(uint8_t *));
- for (int j = 0; j < src->y_size; ++j) {
- dest->y_array[j] = (uint8_t *)xstrdup((char *)src->y_array[j]);
+// return target register
+static int adjust_clipboard_name(int *name) {
+ if (*name == '*' || *name == '+') {
+ if(!eval_has_provider("clipboard")) {
+ EMSG("clipboard: provider is not available");
+ return -1;
+ }
+ return CLIP_REGISTER;
+ } else if (*name == NUL && (cb_flags & (CB_UNNAMED | CB_UNNAMEDPLUS))) {
+ if(!eval_has_provider("clipboard")) {
+ if (!clipboard_didwarn_unnamed) {
+ msg((char_u*)"clipboard: provider not available, ignoring clipboard=unnamed[plus]");
+ clipboard_didwarn_unnamed = true;
+ }
+ return -1;
+ }
+ if (cb_flags & CB_UNNAMEDPLUS) {
+ *name = '+';
+ } else {
+ *name = '*';
+ }
+ return 0; //unnamed
}
+ // don't do anything for other register names
+ return -1;
}
static void get_clipboard(int name)
{
- if (!(name == '*' || name == '+'
- || (p_unc && !name && eval_has_provider("clipboard")))) {
+ int ireg = adjust_clipboard_name(&name);
+ if (ireg < 0) {
return;
}
- struct yankreg *reg = &y_regs[CLIP_REGISTER];
+ struct yankreg *reg = &y_regs[ireg];
free_register(reg);
+
list_T *args = list_alloc();
+ char_u regname = name;
+ list_append_string(args, &regname, 1);
+
typval_T result = eval_call_provider("clipboard", "get", args);
if (result.v_type != VAR_LIST) {
goto err;
}
- list_T *lines = result.vval.v_list;
+ list_T *res = result.vval.v_list, *lines = NULL;
+ if (res->lv_len == 2 && res->lv_first->li_tv.v_type == VAR_LIST) {
+ lines = res->lv_first->li_tv.vval.v_list;
+ if (res->lv_last->li_tv.v_type != VAR_STRING) {
+ goto err;
+ }
+ char_u* regtype = res->lv_last->li_tv.vval.v_string;
+ if (regtype == NULL || strlen((char*)regtype) != 1) {
+ goto err;
+ }
+ switch (regtype[0]) {
+ case 'v': case 'c':
+ reg->y_type = MCHAR;
+ break;
+ case 'V': case 'l':
+ reg->y_type = MLINE;
+ break;
+ case 'b': case Ctrl_V:
+ reg->y_type = MBLOCK;
+ break;
+ default:
+ goto err;
+ }
+ } else {
+ lines = res;
+ // provider did not specify regtype, calculate it below
+ reg->y_type = MAUTO;
+ }
+
reg->y_array = xcalloc(lines->lv_len, sizeof(uint8_t *));
reg->y_size = lines->lv_len;
@@ -5263,9 +5366,23 @@ static void get_clipboard(int name)
reg->y_array[i++] = (uint8_t *)xstrdup((char *)li->li_tv.vval.v_string);
}
- if (!name && p_unc) {
- // copy to the unnamed register
- copy_register(&y_regs[0], reg);
+ if (reg->y_type == MAUTO) {
+ if (reg->y_size > 0 && strlen((char*)reg->y_array[reg->y_size-1]) == 0) {
+ reg->y_type = MLINE;
+ free(reg->y_array[reg->y_size-1]);
+ reg->y_size--;
+ } else {
+ reg->y_type = MCHAR;
+ }
+ } else if (reg->y_type == MBLOCK) {
+ int maxlen = 0;
+ for (int i = 0; i < reg->y_size; i++) {
+ int rowlen = STRLEN(reg->y_array[i]);
+ if (rowlen > maxlen) {
+ maxlen = rowlen;
+ }
+ }
+ reg->y_width = maxlen-1;
}
return;
@@ -5279,22 +5396,17 @@ err:
}
reg->y_array = NULL;
reg->y_size = 0;
- EMSG("Clipboard provider returned invalid data");
+ EMSG("clipboard: provider returned invalid data");
}
static void set_clipboard(int name)
{
- if (!(name == '*' || name == '+'
- || (p_unc && !name && eval_has_provider("clipboard")))) {
+ int ireg = adjust_clipboard_name(&name);
+ if (ireg < 0) {
return;
}
- struct yankreg *reg = &y_regs[CLIP_REGISTER];
-
- if (!name && p_unc) {
- // copy from the unnamed register
- copy_register(reg, &y_regs[0]);
- }
+ struct yankreg *reg = &y_regs[ireg];
list_T *lines = list_alloc();
@@ -5302,5 +5414,26 @@ static void set_clipboard(int name)
list_append_string(lines, reg->y_array[i], -1);
}
- (void)eval_call_provider("clipboard", "set", lines);
+ list_T *args = list_alloc();
+ list_append_list(args, lines);
+
+ char_u regtype;
+ switch (reg->y_type) {
+ case MLINE:
+ regtype = 'V';
+ list_append_string(lines, (char_u*)"", 0);
+ break;
+ case MCHAR:
+ regtype = 'v';
+ break;
+ case MBLOCK:
+ regtype = 'b';
+ break;
+ }
+ list_append_string(args, &regtype, 1);
+
+ char_u regname = name;
+ list_append_string(args, &regname, 1);
+
+ (void)eval_call_provider("clipboard", "set", args);
}
diff --git a/src/nvim/ops.h b/src/nvim/ops.h
index ca70684ab8..3251042c8f 100644
--- a/src/nvim/ops.h
+++ b/src/nvim/ops.h
@@ -47,6 +47,13 @@ typedef int (*Indenter)(void);
#define OP_FORMAT2 26 /* "gw" format operator, keeps cursor pos */
#define OP_FUNCTION 27 /* "g@" call 'operatorfunc' */
+/// Flags for get_reg_contents().
+enum GRegFlags {
+ kGRegNoExpr = 1, ///< Do not allow expression register.
+ kGRegExprSrc = 2, ///< Return expression itself for "=" register.
+ kGRegList = 4 ///< Return list.
+};
+
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "ops.h.generated.h"
#endif
diff --git a/src/nvim/option.c b/src/nvim/option.c
index 2882d7a511..b3a883c79e 100644
--- a/src/nvim/option.c
+++ b/src/nvim/option.c
@@ -527,7 +527,7 @@ static struct vimoption
(char_u *)0L}
SCRIPTID_INIT},
{"clipboard", "cb", P_STRING|P_VI_DEF|P_COMMA|P_NODUP,
- (char_u *)NULL, PV_NONE,
+ (char_u *)&p_cb, PV_NONE,
{(char_u *)"", (char_u *)0L}
SCRIPTID_INIT},
{"cmdheight", "ch", P_NUM|P_VI_DEF|P_RALL,
@@ -1179,9 +1179,6 @@ static struct vimoption
{"optimize", "opt", P_BOOL|P_VI_DEF,
(char_u *)NULL, PV_NONE,
{(char_u *)FALSE, (char_u *)0L} SCRIPTID_INIT},
- {"osfiletype", "oft", P_STRING|P_ALLOCED|P_VI_DEF,
- (char_u *)NULL, PV_NONE,
- {(char_u *)0L, (char_u *)0L} SCRIPTID_INIT},
{"paragraphs", "para", P_STRING|P_VI_DEF,
(char_u *)&p_para, PV_NONE,
{(char_u *)"IPLPPPQPP TPHPLIPpLpItpplpipbp",
@@ -1620,9 +1617,6 @@ static struct vimoption
{"undoreload", "ur", P_NUM|P_VI_DEF,
(char_u *)&p_ur, PV_NONE,
{ (char_u *)10000L, (char_u *)0L} SCRIPTID_INIT},
- {"unnamedclip", "ucp", P_BOOL|P_VI_DEF|P_VIM,
- (char_u *)&p_unc, PV_NONE,
- {(char_u *)FALSE, (char_u *)FALSE} SCRIPTID_INIT},
{"updatecount", "uc", P_NUM|P_VI_DEF,
(char_u *)&p_uc, PV_NONE,
{(char_u *)200L, (char_u *)0L} SCRIPTID_INIT},
@@ -4279,6 +4273,10 @@ did_set_string_option (
if (check_opt_strings(p_ead, p_ead_values, FALSE) != OK)
errmsg = e_invarg;
}
+ else if (varp == &p_cb) {
+ if (opt_strings_flags(p_cb, p_cb_values, &cb_flags, TRUE) != OK)
+ errmsg = e_invarg;
+ }
/* When 'spelllang' or 'spellfile' is set and there is a window for this
* buffer in which 'spell' is set load the wordlists. */
else if (varp == &(curbuf->b_s.b_p_spl) || varp == &(curbuf->b_s.b_p_spf)) {
@@ -4846,7 +4844,6 @@ char_u *check_stl_option(char_u *s)
return NULL;
}
-
/*
* Set curbuf->b_cap_prog to the regexp program for 'spellcapcheck'.
* Return error message when failed, NULL when OK.
diff --git a/src/nvim/option_defs.h b/src/nvim/option_defs.h
index 89264f8982..39dfbe8b88 100644
--- a/src/nvim/option_defs.h
+++ b/src/nvim/option_defs.h
@@ -317,6 +317,13 @@ EXTERN char_u *p_enc; /* 'encoding' */
EXTERN int p_deco; /* 'delcombine' */
EXTERN char_u *p_ccv; /* 'charconvert' */
EXTERN char_u *p_cedit; /* 'cedit' */
+EXTERN char_u *p_cb; /* 'clipboard' */
+EXTERN unsigned cb_flags;
+#ifdef IN_OPTION_C
+static char *(p_cb_values[]) = {"unnamed", "unnamedplus", NULL};
+#endif
+# define CB_UNNAMED 0x001
+# define CB_UNNAMEDPLUS 0x002
EXTERN long p_cwh; /* 'cmdwinheight' */
EXTERN long p_ch; /* 'cmdheight' */
EXTERN int p_confirm; /* 'confirm' */
@@ -582,7 +589,6 @@ static char *(p_ttym_values[]) =
EXTERN char_u *p_udir; /* 'undodir' */
EXTERN long p_ul; /* 'undolevels' */
EXTERN long p_ur; /* 'undoreload' */
-EXTERN int p_unc; /* 'unnamedclip' */
EXTERN long p_uc; /* 'updatecount' */
EXTERN long p_ut; /* 'updatetime' */
EXTERN char_u *p_fcs; /* 'fillchar' */
diff --git a/src/nvim/os/input.c b/src/nvim/os/input.c
index 686fe1f06d..cddc28fac9 100644
--- a/src/nvim/os/input.c
+++ b/src/nvim/os/input.c
@@ -46,7 +46,7 @@ void input_init(void)
{
input_buffer = rbuffer_new(INPUT_BUFFER_SIZE + MAX_KEY_CODE_LEN);
- if (embedded_mode) {
+ if (abstract_ui) {
return;
}
@@ -57,7 +57,7 @@ void input_init(void)
void input_teardown(void)
{
- if (embedded_mode) {
+ if (abstract_ui) {
return;
}
@@ -67,7 +67,7 @@ void input_teardown(void)
// Listen for input
void input_start(void)
{
- if (embedded_mode) {
+ if (abstract_ui) {
return;
}
@@ -77,7 +77,7 @@ void input_start(void)
// Stop listening for input
void input_stop(void)
{
- if (embedded_mode) {
+ if (abstract_ui) {
return;
}
@@ -180,11 +180,110 @@ void input_buffer_restore(String str)
size_t input_enqueue(String keys)
{
- size_t rv = rbuffer_write(input_buffer, keys.data, keys.size);
+ char *ptr = keys.data, *end = ptr + keys.size;
+
+ while (rbuffer_available(input_buffer) >= 6 && ptr < end) {
+ uint8_t buf[6] = {0};
+ int new_size = trans_special((uint8_t **)&ptr, buf, false);
+
+ if (!new_size) {
+ // copy the character unmodified
+ *buf = (uint8_t)*ptr++;
+ new_size = 1;
+ }
+
+ new_size = handle_mouse_event(&ptr, buf, new_size);
+ // TODO(tarruda): Don't produce past unclosed '<' characters, except if
+ // there's a lot of characters after the '<'
+ rbuffer_write(input_buffer, (char *)buf, (size_t)new_size);
+ }
+
+ size_t rv = (size_t)(ptr - keys.data);
process_interrupts();
return rv;
}
+// Mouse event handling code(Extract row/col if available and detect multiple
+// clicks)
+static int handle_mouse_event(char **ptr, uint8_t *buf, int bufsize)
+{
+ int mouse_code = 0;
+
+ if (bufsize == 3) {
+ mouse_code = buf[2];
+ } else if (bufsize == 6) {
+ // prefixed with K_SPECIAL KS_MODIFIER mod
+ mouse_code = buf[5];
+ }
+
+ if (mouse_code < KE_LEFTMOUSE || mouse_code > KE_RIGHTRELEASE) {
+ return bufsize;
+ }
+
+ // a <[COL],[ROW]> sequence can follow and will set the mouse_row/mouse_col
+ // global variables. This is ugly but its how the rest of the code expects to
+ // find mouse coordinates, and it would be too expensive to refactor this
+ // now.
+ int col, row, advance;
+ if (sscanf(*ptr, "<%d,%d>%n", &col, &row, &advance)) {
+ if (col >= 0 && row >= 0) {
+ mouse_row = row;
+ mouse_col = col;
+ }
+ *ptr += advance;
+ }
+
+ static int orig_num_clicks = 0;
+ static int orig_mouse_code = 0;
+ static int orig_mouse_col = 0;
+ static int orig_mouse_row = 0;
+ static uint64_t orig_mouse_time = 0; // time of previous mouse click
+ uint64_t mouse_time = os_hrtime(); // time of current mouse click
+
+ // compute the time elapsed since the previous mouse click and
+ // convert p_mouse from ms to ns
+ uint64_t timediff = mouse_time - orig_mouse_time;
+ uint64_t mouset = (uint64_t)p_mouset * 1000000;
+ if (mouse_code == orig_mouse_code
+ && timediff < mouset
+ && orig_num_clicks != 4
+ && orig_mouse_col == mouse_col
+ && orig_mouse_row == mouse_row) {
+ orig_num_clicks++;
+ } else {
+ orig_num_clicks = 1;
+ }
+ orig_mouse_code = mouse_code;
+ orig_mouse_col = mouse_col;
+ orig_mouse_row = mouse_row;
+ orig_mouse_time = mouse_time;
+
+ int modifiers = 0;
+ if (orig_num_clicks == 2) {
+ modifiers |= MOD_MASK_2CLICK;
+ } else if (orig_num_clicks == 3) {
+ modifiers |= MOD_MASK_3CLICK;
+ } else if (orig_num_clicks == 4) {
+ modifiers |= MOD_MASK_4CLICK;
+ }
+
+ if (modifiers) {
+ if (buf[1] != KS_MODIFIER) {
+ // no modifiers in the buffer yet, shift the bytes 3 positions
+ memcpy(buf + 3, buf, 3);
+ // add the modifier sequence
+ buf[0] = K_SPECIAL;
+ buf[1] = KS_MODIFIER;
+ buf[2] = (uint8_t)modifiers;
+ bufsize += 3;
+ } else {
+ buf[2] |= (uint8_t)modifiers;
+ }
+ }
+
+ return bufsize;
+}
+
static bool input_poll(int ms)
{
if (do_profiling == PROF_YES && ms) {
@@ -255,7 +354,7 @@ static void read_cb(RStream *rstream, void *data, bool at_eof)
static void convert_input(void)
{
- if (embedded_mode || !rbuffer_available(input_buffer)) {
+ if (abstract_ui || !rbuffer_available(input_buffer)) {
// No input buffer space
return;
}
@@ -335,7 +434,7 @@ static bool input_ready(void)
return typebuf_was_filled || // API call filled typeahead
rbuffer_pending(input_buffer) > 0 || // Stdin input
event_has_deferred() || // Events must be processed
- (!embedded_mode && eof); // Stdin closed
+ (!abstract_ui && eof); // Stdin closed
}
// Exit because of an input read error.
diff --git a/src/nvim/os/shell.c b/src/nvim/os/shell.c
index cdd85e4e96..88b7f5c73d 100644
--- a/src/nvim/os/shell.c
+++ b/src/nvim/os/shell.c
@@ -141,7 +141,7 @@ int os_call_shell(char_u *cmd, ShellOpts opts, char_u *extra_arg)
}
if (output) {
- write_output(output, nread);
+ (void)write_output(output, nread, true, true);
free(output);
}
@@ -197,6 +197,9 @@ static int shell(const char *cmd,
// the output buffer
DynamicBuffer buf = DYNAMIC_BUFFER_INIT;
rstream_cb data_cb = system_data_cb;
+ if (nread) {
+ *nread = 0;
+ }
if (forward_output) {
data_cb = out_data_cb;
@@ -296,9 +299,9 @@ static void system_data_cb(RStream *rstream, void *data, bool eof)
static void out_data_cb(RStream *rstream, void *data, bool eof)
{
RBuffer *rbuffer = rstream_buffer(rstream);
- size_t len = rbuffer_pending(rbuffer);
- ui_write((char_u *)rbuffer_read_ptr(rbuffer), (int)len);
- rbuffer_consumed(rbuffer, len);
+ size_t written = write_output(rbuffer_read_ptr(rbuffer),
+ rbuffer_pending(rbuffer), false, eof);
+ rbuffer_consumed(rbuffer, written);
}
/// Parses a command string into a sequence of words, taking quotes into
@@ -407,18 +410,27 @@ static void read_input(DynamicBuffer *buf)
}
}
-static void write_output(char *output, size_t remaining)
+static size_t write_output(char *output, size_t remaining, bool to_buffer,
+ bool eof)
{
if (!output) {
- return;
+ return 0;
}
+ char *start = output;
size_t off = 0;
while (off < remaining) {
if (output[off] == NL) {
// Insert the line
output[off] = NUL;
- ml_append(curwin->w_cursor.lnum++, (char_u *)output, 0, false);
+ if (to_buffer) {
+ ml_append(curwin->w_cursor.lnum++, (char_u *)output, 0, false);
+ } else {
+ // pending data from the output buffer has been flushed to the screen,
+ // safe to call ui_write directly
+ ui_write((char_u *)output, (int)off);
+ ui_write((char_u *)"\r\n", 2);
+ }
size_t skip = off + 1;
output += skip;
remaining -= skip;
@@ -433,14 +445,26 @@ static void write_output(char *output, size_t remaining)
off++;
}
- if (remaining) {
- // append unfinished line
- ml_append(curwin->w_cursor.lnum++, (char_u *)output, 0, false);
- // remember that the NL was missing
- curbuf->b_no_eol_lnum = curwin->w_cursor.lnum;
- } else {
- curbuf->b_no_eol_lnum = 0;
+ if (eof) {
+ if (remaining) {
+ if (to_buffer) {
+ // append unfinished line
+ ml_append(curwin->w_cursor.lnum++, (char_u *)output, 0, false);
+ // remember that the NL was missing
+ curbuf->b_no_eol_lnum = curwin->w_cursor.lnum;
+ } else {
+ ui_write((char_u *)output, (int)remaining);
+ ui_write((char_u *)"\r\n", 2);
+ }
+ output += remaining;
+ } else if (to_buffer) {
+ curbuf->b_no_eol_lnum = 0;
+ }
}
+
+ out_flush();
+
+ return (size_t)(output - start);
}
static void shell_write_cb(WStream *wstream, void *data, int status)
diff --git a/src/nvim/os/signal.c b/src/nvim/os/signal.c
index cf8ba85ed5..ca3ba052d7 100644
--- a/src/nvim/os/signal.c
+++ b/src/nvim/os/signal.c
@@ -45,7 +45,7 @@ void signal_init(void)
uv_signal_start(&shup, signal_cb, SIGHUP);
uv_signal_start(&squit, signal_cb, SIGQUIT);
uv_signal_start(&sterm, signal_cb, SIGTERM);
- if (!embedded_mode) {
+ if (!abstract_ui) {
// TODO(tarruda): There must be an API function for resizing window
uv_signal_start(&swinch, signal_cb, SIGWINCH);
}
diff --git a/src/nvim/os_unix.c b/src/nvim/os_unix.c
index 677976e3e1..a9c1fec0b4 100644
--- a/src/nvim/os_unix.c
+++ b/src/nvim/os_unix.c
@@ -9,7 +9,6 @@
/*
* os_unix.c -- code for all flavors of Unix (BSD, SYSV, SVR4, POSIX, ...)
- * Also for BeOS
*
* A lot of this file was originally written by Juergen Weigert and later
* changed beyond recognition.
diff --git a/src/nvim/screen.c b/src/nvim/screen.c
index 0225eb72c1..c0a909f147 100644
--- a/src/nvim/screen.c
+++ b/src/nvim/screen.c
@@ -5824,9 +5824,12 @@ static void screen_start_highlight(int attr)
attrentry_T *aep = NULL;
screen_attr = attr;
- if (full_screen
- ) {
- {
+ if (full_screen) {
+ if (abstract_ui) {
+ char buf[20];
+ sprintf(buf, "\033|%dh", attr);
+ OUT_STR(buf);
+ } else {
if (attr > HL_ALL) { /* special HL attr. */
if (t_colors > 1)
aep = syn_cterm_attr2entry(attr);
@@ -5877,9 +5880,13 @@ void screen_stop_highlight(void)
{
int do_ME = FALSE; /* output T_ME code */
- if (screen_attr != 0
- ) {
- {
+ if (screen_attr != 0) {
+ if (abstract_ui) {
+ // Handled in ui.c
+ char buf[20];
+ sprintf(buf, "\033|%dH", screen_attr);
+ OUT_STR(buf);
+ } else {
if (screen_attr > HL_ALL) { /* special HL attr. */
attrentry_T *aep;
@@ -6558,11 +6565,14 @@ static void screenclear2(void)
{
int i;
- if (starting == NO_SCREEN || ScreenLines == NULL
- )
+ if (starting == NO_SCREEN || ScreenLines == NULL) {
return;
+ }
+
+ if (!abstract_ui) {
+ screen_attr = -1; /* force setting the Normal colors */
+ }
- screen_attr = -1; /* force setting the Normal colors */
screen_stop_highlight(); /* don't want highlighting here */
@@ -8156,14 +8166,19 @@ void screen_resize(int width, int height, int mustset)
++busy;
-
- if (mustset || (ui_get_shellsize() == FAIL && height != 0)) {
+ // TODO(tarruda): "mustset" is still used in the old tests, which don't use
+ // "abstract_ui" yet. This will change when a new TUI is merged.
+ if (abstract_ui || mustset || (ui_get_shellsize() == FAIL && height != 0)) {
Rows = height;
Columns = width;
- check_shellsize();
+ }
+ check_shellsize();
+
+ if (abstract_ui) {
+ ui_resize(width, height);
+ } else {
mch_set_shellsize();
- } else
- check_shellsize();
+ }
/* The window layout used to be adjusted here, but it now happens in
* screenalloc() (also invoked from screenclear()). That is because the
diff --git a/src/nvim/spell.c b/src/nvim/spell.c
index fa786fdd74..83dcddecd6 100644
--- a/src/nvim/spell.c
+++ b/src/nvim/spell.c
@@ -2379,13 +2379,26 @@ static void slang_free(slang_T *lp)
free(lp);
}
+/// Frees a salitem_T
+static void free_salitem(salitem_T *smp) {
+ free(smp->sm_lead);
+ // Don't free sm_oneof and sm_rules, they point into sm_lead.
+ free(smp->sm_to);
+ free(smp->sm_lead_w);
+ free(smp->sm_oneof_w);
+ free(smp->sm_to_w);
+}
+
+/// Frees a fromto_T
+static void free_fromto(fromto_T *ftp) {
+ free(ftp->ft_from);
+ free(ftp->ft_to);
+}
+
// Clear an slang_T so that the file can be reloaded.
static void slang_clear(slang_T *lp)
{
garray_T *gap;
- fromto_T *ftp;
- salitem_T *smp;
- int round;
free(lp->sl_fbyts);
lp->sl_fbyts = NULL;
@@ -2401,36 +2414,17 @@ static void slang_clear(slang_T *lp)
free(lp->sl_pidxs);
lp->sl_pidxs = NULL;
- for (round = 1; round <= 2; ++round) {
- gap = round == 1 ? &lp->sl_rep : &lp->sl_repsal;
- while (!GA_EMPTY(gap)) {
- ftp = &((fromto_T *)gap->ga_data)[--gap->ga_len];
- free(ftp->ft_from);
- free(ftp->ft_to);
- }
- ga_clear(gap);
- }
+ GA_DEEP_CLEAR(&lp->sl_rep, fromto_T, free_fromto);
+ GA_DEEP_CLEAR(&lp->sl_repsal, fromto_T, free_fromto);
gap = &lp->sl_sal;
if (lp->sl_sofo) {
// "ga_len" is set to 1 without adding an item for latin1
- if (gap->ga_data != NULL)
- // SOFOFROM and SOFOTO items: free lists of wide characters.
- for (int i = 0; i < gap->ga_len; ++i) {
- free(((int **)gap->ga_data)[i]);
- }
- } else
+ GA_DEEP_CLEAR_PTR(gap);
+ } else {
// SAL items: free salitem_T items
- while (!GA_EMPTY(gap)) {
- smp = &((salitem_T *)gap->ga_data)[--gap->ga_len];
- free(smp->sm_lead);
- // Don't free sm_oneof and sm_rules, they point into sm_lead.
- free(smp->sm_to);
- free(smp->sm_lead_w);
- free(smp->sm_oneof_w);
- free(smp->sm_to_w);
- }
- ga_clear(gap);
+ GA_DEEP_CLEAR(gap, salitem_T, free_salitem);
+ }
for (int i = 0; i < lp->sl_prefixcnt; ++i) {
vim_regfree(lp->sl_prefprog[i]);
@@ -9206,15 +9200,10 @@ static void tree_count_words(char_u *byts, idx_T *idxs)
// Free the info put in "*su" by spell_find_suggest().
static void spell_find_cleanup(suginfo_T *su)
{
+# define FREE_SUG_WORD(sug) free(sug->st_word)
// Free the suggestions.
- for (int i = 0; i < su->su_ga.ga_len; ++i) {
- free(SUG(su->su_ga, i).st_word);
- }
- ga_clear(&su->su_ga);
- for (int i = 0; i < su->su_sga.ga_len; ++i) {
- free(SUG(su->su_sga, i).st_word);
- }
- ga_clear(&su->su_sga);
+ GA_DEEP_CLEAR(&su->su_ga, suggest_T, FREE_SUG_WORD);
+ GA_DEEP_CLEAR(&su->su_sga, suggest_T, FREE_SUG_WORD);
// Free the banned words.
hash_clear_all(&su->su_banned, 0);
diff --git a/src/nvim/strings.c b/src/nvim/strings.c
index 20008bca16..1e619b1c6e 100644
--- a/src/nvim/strings.c
+++ b/src/nvim/strings.c
@@ -237,13 +237,9 @@ char_u *vim_strnsave_up(const char_u *string, size_t len)
void vim_strup(char_u *p)
FUNC_ATTR_NONNULL_ALL
{
- char_u *p2;
char_u c;
-
- if (p != NULL) {
- p2 = p;
- while ((c = *p2) != NUL)
- *p2++ = (char_u)((c < 'a' || c > 'z') ? c : c - 0x20);
+ while ((c = *p) != NUL) {
+ *p++ = (char_u)(c < 'a' || c > 'z' ? c : c - 0x20);
}
}
@@ -525,7 +521,7 @@ void sort_strings(char_u **files, int count)
* When "s" is NULL false is returned.
*/
bool has_non_ascii(const char_u *s)
- FUNC_ATTR_NONNULL_ALL FUNC_ATTR_PURE
+ FUNC_ATTR_PURE
{
const char_u *p;
diff --git a/src/nvim/syntax.c b/src/nvim/syntax.c
index 69d6479cf3..896f27f9e4 100644
--- a/src/nvim/syntax.c
+++ b/src/nvim/syntax.c
@@ -11,6 +11,7 @@
*/
#include <assert.h>
+#include <ctype.h>
#include <errno.h>
#include <inttypes.h>
#include <stdbool.h>
@@ -68,9 +69,10 @@ struct hl_group {
int sg_cterm_attr; /* Screen attr for color term mode */
/* Store the sp color name for the GUI or synIDattr() */
int sg_gui; /* "gui=" highlighting attributes */
- char_u *sg_gui_fg_name; /* GUI foreground color name */
- char_u *sg_gui_bg_name; /* GUI background color name */
- char_u *sg_gui_sp_name; /* GUI special color name */
+ RgbValue sg_rgb_fg; // RGB foreground color
+ RgbValue sg_rgb_bg; // RGB background color
+ uint8_t *sg_rgb_fg_name; // RGB foreground color name
+ uint8_t *sg_rgb_bg_name; // RGB background color name
int sg_link; /* link to this highlight group ID */
int sg_set; /* combination of SG_* flags */
scid_T sg_scriptID; /* script in which the group was last set */
@@ -548,14 +550,9 @@ void syntax_start(win_T *wp, linenr_T lnum)
*/
static void clear_syn_state(synstate_T *p)
{
- garray_T *gap;
-
if (p->sst_stacksize > SST_FIX_STATES) {
- gap = &(p->sst_union.sst_ga);
- for (int i = 0; i < gap->ga_len; i++) {
- unref_extmatch(SYN_STATE_P(gap)[i].bs_extmatch);
- }
- ga_clear(gap);
+# define UNREF_BUFSTATE_EXTMATCH(bs) unref_extmatch((bs)->bs_extmatch)
+ GA_DEEP_CLEAR(&(p->sst_union.sst_ga), bufstate_T, UNREF_BUFSTATE_EXTMATCH);
} else {
for (int i = 0; i < p->sst_stacksize; i++) {
unref_extmatch(p->sst_union.sst_stack[i].bs_extmatch);
@@ -568,11 +565,8 @@ static void clear_syn_state(synstate_T *p)
*/
static void clear_current_state(void)
{
- stateitem_T *sip = (stateitem_T *)(current_state.ga_data);
- for (int i = 0; i < current_state.ga_len; i++) {
- unref_extmatch(sip[i].si_extmatch);
- }
- ga_clear(&current_state);
+# define UNREF_STATEITEM_EXTMATCH(si) unref_extmatch((si)->si_extmatch)
+ GA_DEEP_CLEAR(&current_state, stateitem_T, UNREF_STATEITEM_EXTMATCH);
}
/*
@@ -6518,34 +6512,39 @@ do_highlight (
if (!init)
HL_TABLE()[idx].sg_set |= SG_GUI;
- free(HL_TABLE()[idx].sg_gui_fg_name);
- if (STRCMP(arg, "NONE"))
- HL_TABLE()[idx].sg_gui_fg_name = vim_strsave(arg);
- else
- HL_TABLE()[idx].sg_gui_fg_name = NULL;
+ free(HL_TABLE()[idx].sg_rgb_fg_name);
+ if (STRCMP(arg, "NONE")) {
+ HL_TABLE()[idx].sg_rgb_fg_name = (uint8_t *)xstrdup((char *)arg);
+ HL_TABLE()[idx].sg_rgb_fg = name_to_color(arg);
+ } else {
+ HL_TABLE()[idx].sg_rgb_fg_name = NULL;
+ HL_TABLE()[idx].sg_rgb_fg = -1;
+ }
+ }
+
+ if (is_normal_group) {
+ normal_fg = HL_TABLE()[idx].sg_rgb_fg;
}
} else if (STRCMP(key, "GUIBG") == 0) {
if (!init || !(HL_TABLE()[idx].sg_set & SG_GUI)) {
if (!init)
HL_TABLE()[idx].sg_set |= SG_GUI;
- free(HL_TABLE()[idx].sg_gui_bg_name);
- if (STRCMP(arg, "NONE") != 0)
- HL_TABLE()[idx].sg_gui_bg_name = vim_strsave(arg);
- else
- HL_TABLE()[idx].sg_gui_bg_name = NULL;
+ free(HL_TABLE()[idx].sg_rgb_bg_name);
+ if (STRCMP(arg, "NONE") != 0) {
+ HL_TABLE()[idx].sg_rgb_bg_name = (uint8_t *)xstrdup((char *)arg);
+ HL_TABLE()[idx].sg_rgb_bg = name_to_color(arg);
+ } else {
+ HL_TABLE()[idx].sg_rgb_bg_name = NULL;
+ HL_TABLE()[idx].sg_rgb_bg = -1;
+ }
}
- } else if (STRCMP(key, "GUISP") == 0) {
- if (!init || !(HL_TABLE()[idx].sg_set & SG_GUI)) {
- if (!init)
- HL_TABLE()[idx].sg_set |= SG_GUI;
- free(HL_TABLE()[idx].sg_gui_sp_name);
- if (STRCMP(arg, "NONE") != 0)
- HL_TABLE()[idx].sg_gui_sp_name = vim_strsave(arg);
- else
- HL_TABLE()[idx].sg_gui_sp_name = NULL;
+ if (is_normal_group) {
+ normal_bg = HL_TABLE()[idx].sg_rgb_bg;
}
+ } else if (STRCMP(key, "GUISP") == 0) {
+ // Ignored
} else if (STRCMP(key, "START") == 0 || STRCMP(key, "STOP") == 0) {
char_u buf[100];
char_u *tname;
@@ -6670,6 +6669,8 @@ void free_highlight(void)
*/
void restore_cterm_colors(void)
{
+ normal_fg = -1;
+ normal_bg = -1;
cterm_normal_fg_color = 0;
cterm_normal_fg_bold = 0;
cterm_normal_bg_color = 0;
@@ -6705,12 +6706,12 @@ static void highlight_clear(int idx)
HL_TABLE()[idx].sg_cterm_bg = 0;
HL_TABLE()[idx].sg_cterm_attr = 0;
HL_TABLE()[idx].sg_gui = 0;
- free(HL_TABLE()[idx].sg_gui_fg_name);
- HL_TABLE()[idx].sg_gui_fg_name = NULL;
- free(HL_TABLE()[idx].sg_gui_bg_name);
- HL_TABLE()[idx].sg_gui_bg_name = NULL;
- free(HL_TABLE()[idx].sg_gui_sp_name);
- HL_TABLE()[idx].sg_gui_sp_name = NULL;
+ HL_TABLE()[idx].sg_rgb_fg = -1;
+ HL_TABLE()[idx].sg_rgb_bg = -1;
+ free(HL_TABLE()[idx].sg_rgb_fg_name);
+ HL_TABLE()[idx].sg_rgb_fg_name = NULL;
+ free(HL_TABLE()[idx].sg_rgb_bg_name);
+ HL_TABLE()[idx].sg_rgb_bg_name = NULL;
/* Clear the script ID only when there is no link, since that is not
* cleared. */
if (HL_TABLE()[idx].sg_link == 0)
@@ -6771,7 +6772,11 @@ static int get_attr_entry(garray_T *table, attrentry_T *aep)
&& aep->ae_u.cterm.fg_color
== taep->ae_u.cterm.fg_color
&& aep->ae_u.cterm.bg_color
- == taep->ae_u.cterm.bg_color)
+ == taep->ae_u.cterm.bg_color
+ && aep->fg_color
+ == taep->fg_color
+ && aep->bg_color
+ == taep->bg_color)
))
return i + ATTR_OFF;
@@ -6818,6 +6823,8 @@ static int get_attr_entry(garray_T *table, attrentry_T *aep)
} else if (table == &cterm_attr_table) {
taep->ae_u.cterm.fg_color = aep->ae_u.cterm.fg_color;
taep->ae_u.cterm.bg_color = aep->ae_u.cterm.bg_color;
+ taep->fg_color = aep->fg_color;
+ taep->bg_color = aep->bg_color;
}
return table->ga_len - 1 + ATTR_OFF;
@@ -6880,6 +6887,10 @@ int hl_combine_attr(int char_attr, int prim_attr)
new_en.ae_u.cterm.fg_color = spell_aep->ae_u.cterm.fg_color;
if (spell_aep->ae_u.cterm.bg_color > 0)
new_en.ae_u.cterm.bg_color = spell_aep->ae_u.cterm.bg_color;
+ if (spell_aep->fg_color >= 0)
+ new_en.fg_color = spell_aep->fg_color;
+ if (spell_aep->bg_color >= 0)
+ new_en.bg_color = spell_aep->bg_color;
}
}
return get_attr_entry(&cterm_attr_table, &new_en);
@@ -6974,11 +6985,11 @@ static void highlight_list_one(int id)
didh = highlight_list_arg(id, didh, LIST_ATTR,
sgp->sg_gui, NULL, "gui");
didh = highlight_list_arg(id, didh, LIST_STRING,
- 0, sgp->sg_gui_fg_name, "guifg");
+ 0, sgp->sg_rgb_fg_name, "guifg");
didh = highlight_list_arg(id, didh, LIST_STRING,
- 0, sgp->sg_gui_bg_name, "guibg");
+ 0, sgp->sg_rgb_bg_name, "guibg");
didh = highlight_list_arg(id, didh, LIST_STRING,
- 0, sgp->sg_gui_sp_name, "guisp");
+ 0, NULL, "guisp");
if (sgp->sg_link && !got_int) {
(void)syn_list_header(didh, 9999, id);
@@ -7092,10 +7103,10 @@ highlight_color (
return NULL;
if (modec == 'g') {
if (fg)
- return HL_TABLE()[id - 1].sg_gui_fg_name;
+ return HL_TABLE()[id - 1].sg_rgb_fg_name;
if (sp)
- return HL_TABLE()[id - 1].sg_gui_sp_name;
- return HL_TABLE()[id - 1].sg_gui_bg_name;
+ return NULL;
+ return HL_TABLE()[id - 1].sg_rgb_bg_name;
}
if (font || sp)
return NULL;
@@ -7192,9 +7203,14 @@ set_hl_attr (
if (sgp->sg_cterm_fg == 0 && sgp->sg_cterm_bg == 0)
sgp->sg_cterm_attr = sgp->sg_cterm;
else {
- at_en.ae_attr = sgp->sg_cterm;
+ at_en.ae_attr = abstract_ui ? sgp->sg_gui : sgp->sg_cterm;
at_en.ae_u.cterm.fg_color = sgp->sg_cterm_fg;
at_en.ae_u.cterm.bg_color = sgp->sg_cterm_bg;
+ // FIXME(tarruda): The "unset value" for rgb is -1, but since hlgroup is
+ // initialized with 0(by garray functions), check for sg_rgb_{f,b}g_name
+ // before setting attr_entry->{f,g}g_color to a other than -1
+ at_en.fg_color = sgp->sg_rgb_fg_name ? sgp->sg_rgb_fg : -1;
+ at_en.bg_color = sgp->sg_rgb_bg_name ? sgp->sg_rgb_bg : -1;
sgp->sg_cterm_attr = get_attr_entry(&cterm_attr_table, &at_en);
}
}
@@ -7633,6 +7649,200 @@ char_u *get_highlight_name(expand_T *xp, int idx)
}
+RgbValue name_to_color(uint8_t *name)
+{
+#define RGB(r, g, b) ((r << 16) | (g << 8) | b)
+ static struct {
+ char *name;
+ RgbValue color;
+ } color_name_table[] = {
+ // Color names taken from
+ // http://www.rapidtables.com/web/color/RGB_Color.htm
+ {"Maroon", RGB(0x80, 0x00, 0x00)},
+ {"DarkRed", RGB(0x8b, 0x00, 0x00)},
+ {"Brown", RGB(0xa5, 0x2a, 0x2a)},
+ {"Firebrick", RGB(0xb2, 0x22, 0x22)},
+ {"Crimson", RGB(0xdc, 0x14, 0x3c)},
+ {"Red", RGB(0xff, 0x00, 0x00)},
+ {"Tomato", RGB(0xff, 0x63, 0x47)},
+ {"Coral", RGB(0xff, 0x7f, 0x50)},
+ {"IndianRed", RGB(0xcd, 0x5c, 0x5c)},
+ {"LightCoral", RGB(0xf0, 0x80, 0x80)},
+ {"DarkSalmon", RGB(0xe9, 0x96, 0x7a)},
+ {"Salmon", RGB(0xfa, 0x80, 0x72)},
+ {"LightSalmon", RGB(0xff, 0xa0, 0x7a)},
+ {"OrangeRed", RGB(0xff, 0x45, 0x00)},
+ {"DarkOrange", RGB(0xff, 0x8c, 0x00)},
+ {"Orange", RGB(0xff, 0xa5, 0x00)},
+ {"Gold", RGB(0xff, 0xd7, 0x00)},
+ {"DarkGoldenRod", RGB(0xb8, 0x86, 0x0b)},
+ {"GoldenRod", RGB(0xda, 0xa5, 0x20)},
+ {"PaleGoldenRod", RGB(0xee, 0xe8, 0xaa)},
+ {"DarkKhaki", RGB(0xbd, 0xb7, 0x6b)},
+ {"Khaki", RGB(0xf0, 0xe6, 0x8c)},
+ {"Olive", RGB(0x80, 0x80, 0x00)},
+ {"Yellow", RGB(0xff, 0xff, 0x00)},
+ {"YellowGreen", RGB(0x9a, 0xcd, 0x32)},
+ {"DarkOliveGreen", RGB(0x55, 0x6b, 0x2f)},
+ {"OliveDrab", RGB(0x6b, 0x8e, 0x23)},
+ {"LawnGreen", RGB(0x7c, 0xfc, 0x00)},
+ {"ChartReuse", RGB(0x7f, 0xff, 0x00)},
+ {"GreenYellow", RGB(0xad, 0xff, 0x2f)},
+ {"DarkGreen", RGB(0x00, 0x64, 0x00)},
+ {"Green", RGB(0x00, 0x80, 0x00)},
+ {"ForestGreen", RGB(0x22, 0x8b, 0x22)},
+ {"Lime", RGB(0x00, 0xff, 0x00)},
+ {"LimeGreen", RGB(0x32, 0xcd, 0x32)},
+ {"LightGreen", RGB(0x90, 0xee, 0x90)},
+ {"PaleGreen", RGB(0x98, 0xfb, 0x98)},
+ {"DarkSeaGreen", RGB(0x8f, 0xbc, 0x8f)},
+ {"MediumSpringGreen", RGB(0x00, 0xfa, 0x9a)},
+ {"SpringGreen", RGB(0x00, 0xff, 0x7f)},
+ {"SeaGreen", RGB(0x2e, 0x8b, 0x57)},
+ {"MediumAquamarine", RGB(0x66, 0xcd, 0xaa)},
+ {"MediumSeaGreen", RGB(0x3c, 0xb3, 0x71)},
+ {"LightSeaGreen", RGB(0x20, 0xb2, 0xaa)},
+ {"DarkSlateGray", RGB(0x2f, 0x4f, 0x4f)},
+ {"Teal", RGB(0x00, 0x80, 0x80)},
+ {"DarkCyan", RGB(0x00, 0x8b, 0x8b)},
+ {"Aqua", RGB(0x00, 0xff, 0xff)},
+ {"Cyan", RGB(0x00, 0xff, 0xff)},
+ {"LightCyan", RGB(0xe0, 0xff, 0xff)},
+ {"DarkTurquoise", RGB(0x00, 0xce, 0xd1)},
+ {"Turquoise", RGB(0x40, 0xe0, 0xd0)},
+ {"MediumTurquoise", RGB(0x48, 0xd1, 0xcc)},
+ {"PaleTurquoise", RGB(0xaf, 0xee, 0xee)},
+ {"Aquamarine", RGB(0x7f, 0xff, 0xd4)},
+ {"PowderBlue", RGB(0xb0, 0xe0, 0xe6)},
+ {"CadetBlue", RGB(0x5f, 0x9e, 0xa0)},
+ {"SteelBlue", RGB(0x46, 0x82, 0xb4)},
+ {"CornFlowerBlue", RGB(0x64, 0x95, 0xed)},
+ {"DeepSkyBlue", RGB(0x00, 0xbf, 0xff)},
+ {"DodgerBlue", RGB(0x1e, 0x90, 0xff)},
+ {"LightBlue", RGB(0xad, 0xd8, 0xe6)},
+ {"SkyBlue", RGB(0x87, 0xce, 0xeb)},
+ {"LightSkyBlue", RGB(0x87, 0xce, 0xfa)},
+ {"MidnightBlue", RGB(0x19, 0x19, 0x70)},
+ {"Navy", RGB(0x00, 0x00, 0x80)},
+ {"DarkBlue", RGB(0x00, 0x00, 0x8b)},
+ {"MediumBlue", RGB(0x00, 0x00, 0xcd)},
+ {"Blue", RGB(0x00, 0x00, 0xff)},
+ {"RoyalBlue", RGB(0x41, 0x69, 0xe1)},
+ {"BlueViolet", RGB(0x8a, 0x2b, 0xe2)},
+ {"Indigo", RGB(0x4b, 0x00, 0x82)},
+ {"DarkSlateBlue", RGB(0x48, 0x3d, 0x8b)},
+ {"SlateBlue", RGB(0x6a, 0x5a, 0xcd)},
+ {"MediumSlateBlue", RGB(0x7b, 0x68, 0xee)},
+ {"MediumPurple", RGB(0x93, 0x70, 0xdb)},
+ {"DarkMagenta", RGB(0x8b, 0x00, 0x8b)},
+ {"DarkViolet", RGB(0x94, 0x00, 0xd3)},
+ {"DarkOrchid", RGB(0x99, 0x32, 0xcc)},
+ {"MediumOrchid", RGB(0xba, 0x55, 0xd3)},
+ {"Purple", RGB(0x80, 0x00, 0x80)},
+ {"Thistle", RGB(0xd8, 0xbf, 0xd8)},
+ {"Plum", RGB(0xdd, 0xa0, 0xdd)},
+ {"Violet", RGB(0xee, 0x82, 0xee)},
+ {"Magenta", RGB(0xff, 0x00, 0xff)},
+ {"Fuchsia", RGB(0xff, 0x00, 0xff)},
+ {"Orchid", RGB(0xda, 0x70, 0xd6)},
+ {"MediumVioletRed", RGB(0xc7, 0x15, 0x85)},
+ {"PaleVioletRed", RGB(0xdb, 0x70, 0x93)},
+ {"DeepPink", RGB(0xff, 0x14, 0x93)},
+ {"HotPink", RGB(0xff, 0x69, 0xb4)},
+ {"LightPink", RGB(0xff, 0xb6, 0xc1)},
+ {"Pink", RGB(0xff, 0xc0, 0xcb)},
+ {"AntiqueWhite", RGB(0xfa, 0xeb, 0xd7)},
+ {"Beige", RGB(0xf5, 0xf5, 0xdc)},
+ {"Bisque", RGB(0xff, 0xe4, 0xc4)},
+ {"BlanchedAlmond", RGB(0xff, 0xeb, 0xcd)},
+ {"Wheat", RGB(0xf5, 0xde, 0xb3)},
+ {"Cornsilk", RGB(0xff, 0xf8, 0xdc)},
+ {"LemonChiffon", RGB(0xff, 0xfa, 0xcd)},
+ {"LightGoldenRodYellow", RGB(0xfa, 0xfa, 0xd2)},
+ {"LightYellow", RGB(0xff, 0xff, 0xe0)},
+ {"SaddleBrown", RGB(0x8b, 0x45, 0x13)},
+ {"Sienna", RGB(0xa0, 0x52, 0x2d)},
+ {"Chocolate", RGB(0xd2, 0x69, 0x1e)},
+ {"Peru", RGB(0xcd, 0x85, 0x3f)},
+ {"SandyBrown", RGB(0xf4, 0xa4, 0x60)},
+ {"BurlyWood", RGB(0xde, 0xb8, 0x87)},
+ {"Tan", RGB(0xd2, 0xb4, 0x8c)},
+ {"RosyBrown", RGB(0xbc, 0x8f, 0x8f)},
+ {"Moccasin", RGB(0xff, 0xe4, 0xb5)},
+ {"NavajoWhite", RGB(0xff, 0xde, 0xad)},
+ {"PeachPuff", RGB(0xff, 0xda, 0xb9)},
+ {"MistyRose", RGB(0xff, 0xe4, 0xe1)},
+ {"LavenderBlush", RGB(0xff, 0xf0, 0xf5)},
+ {"Linen", RGB(0xfa, 0xf0, 0xe6)},
+ {"Oldlace", RGB(0xfd, 0xf5, 0xe6)},
+ {"PapayaWhip", RGB(0xff, 0xef, 0xd5)},
+ {"SeaShell", RGB(0xff, 0xf5, 0xee)},
+ {"MintCream", RGB(0xf5, 0xff, 0xfa)},
+ {"SlateGray", RGB(0x70, 0x80, 0x90)},
+ {"LightSlateGray", RGB(0x77, 0x88, 0x99)},
+ {"LightSteelBlue", RGB(0xb0, 0xc4, 0xde)},
+ {"Lavender", RGB(0xe6, 0xe6, 0xfa)},
+ {"FloralWhite", RGB(0xff, 0xfa, 0xf0)},
+ {"AliceBlue", RGB(0xf0, 0xf8, 0xff)},
+ {"GhostWhite", RGB(0xf8, 0xf8, 0xff)},
+ {"Honeydew", RGB(0xf0, 0xff, 0xf0)},
+ {"Ivory", RGB(0xff, 0xff, 0xf0)},
+ {"Azure", RGB(0xf0, 0xff, 0xff)},
+ {"Snow", RGB(0xff, 0xfa, 0xfa)},
+ {"Black", RGB(0x00, 0x00, 0x00)},
+ {"DimGray", RGB(0x69, 0x69, 0x69)},
+ {"DimGrey", RGB(0x69, 0x69, 0x69)},
+ {"Gray", RGB(0x80, 0x80, 0x80)},
+ {"Grey", RGB(0x80, 0x80, 0x80)},
+ {"DarkGray", RGB(0xa9, 0xa9, 0xa9)},
+ {"DarkGrey", RGB(0xa9, 0xa9, 0xa9)},
+ {"Silver", RGB(0xc0, 0xc0, 0xc0)},
+ {"LightGray", RGB(0xd3, 0xd3, 0xd3)},
+ {"LightGrey", RGB(0xd3, 0xd3, 0xd3)},
+ {"Gainsboro", RGB(0xdc, 0xdc, 0xdc)},
+ {"WhiteSmoke", RGB(0xf5, 0xf5, 0xf5)},
+ {"White", RGB(0xff, 0xff, 0xff)},
+ // The color names below were taken from gui_x11.c in vim source
+ {"LightRed", RGB(0xff, 0xbb, 0xbb)},
+ {"LightMagenta",RGB(0xff, 0xbb, 0xff)},
+ {"DarkYellow", RGB(0xbb, 0xbb, 0x00)},
+ {"Gray10", RGB(0x1a, 0x1a, 0x1a)},
+ {"Grey10", RGB(0x1a, 0x1a, 0x1a)},
+ {"Gray20", RGB(0x33, 0x33, 0x33)},
+ {"Grey20", RGB(0x33, 0x33, 0x33)},
+ {"Gray30", RGB(0x4d, 0x4d, 0x4d)},
+ {"Grey30", RGB(0x4d, 0x4d, 0x4d)},
+ {"Gray40", RGB(0x66, 0x66, 0x66)},
+ {"Grey40", RGB(0x66, 0x66, 0x66)},
+ {"Gray50", RGB(0x7f, 0x7f, 0x7f)},
+ {"Grey50", RGB(0x7f, 0x7f, 0x7f)},
+ {"Gray60", RGB(0x99, 0x99, 0x99)},
+ {"Grey60", RGB(0x99, 0x99, 0x99)},
+ {"Gray70", RGB(0xb3, 0xb3, 0xb3)},
+ {"Grey70", RGB(0xb3, 0xb3, 0xb3)},
+ {"Gray80", RGB(0xcc, 0xcc, 0xcc)},
+ {"Grey80", RGB(0xcc, 0xcc, 0xcc)},
+ {"Gray90", RGB(0xe5, 0xe5, 0xe5)},
+ {"Grey90", RGB(0xe5, 0xe5, 0xe5)},
+ {NULL, 0},
+ };
+
+ if (name[0] == '#' && isxdigit(name[1]) && isxdigit(name[2])
+ && isxdigit(name[3]) && isxdigit(name[4]) && isxdigit(name[5])
+ && isxdigit(name[6]) && name[7] == NUL) {
+ // rgb hex string
+ return strtol((char *)(name + 1), NULL, 16);
+ }
+
+ for (int i = 0; color_name_table[i].name != NULL; i++) {
+ if (!STRICMP(name, color_name_table[i].name)) {
+ return color_name_table[i].color;
+ }
+ }
+
+ return -1;
+}
+
/**************************************
* End of Highlighting stuff *
**************************************/
diff --git a/src/nvim/syntax.h b/src/nvim/syntax.h
index a03bd1e604..9a284c8a8d 100644
--- a/src/nvim/syntax.h
+++ b/src/nvim/syntax.h
@@ -5,8 +5,6 @@
#include "nvim/buffer_defs.h"
-typedef int guicolor_T;
-
/*
* Terminal highlighting attribute bits.
* Attributes above HL_ALL are used for syntax highlighting.
diff --git a/src/nvim/syntax_defs.h b/src/nvim/syntax_defs.h
index 11e342f870..abf7ea5a7d 100644
--- a/src/nvim/syntax_defs.h
+++ b/src/nvim/syntax_defs.h
@@ -3,6 +3,8 @@
#include "nvim/regexp_defs.h"
+typedef int32_t RgbValue;
+
# define SST_MIN_ENTRIES 150 /* minimal size for state stack array */
# define SST_MAX_ENTRIES 1000 /* maximal size for state stack array */
# define SST_FIX_STATES 7 /* size of sst_stack[]. */
@@ -70,6 +72,7 @@ struct syn_state {
*/
typedef struct attr_entry {
short ae_attr; /* HL_BOLD, etc. */
+ RgbValue fg_color, bg_color;
union {
struct {
char_u *start; /* start escape sequence */
diff --git a/src/nvim/term.c b/src/nvim/term.c
index 54508b1daa..24969bf90f 100644
--- a/src/nvim/term.c
+++ b/src/nvim/term.c
@@ -161,6 +161,33 @@ static bool detected_8bit = false; // detected 8-bit terminal
static struct builtin_term builtin_termcaps[] =
{
+ // abstract UI pseudo termcap, based on vim's "builtin_gui" termcap
+ {(int)KS_NAME, "abstract_ui"},
+ {(int)KS_CE, "\033|$"},
+ {(int)KS_AL, "\033|i"},
+ {(int)KS_CAL, "\033|%p1%dI"},
+ {(int)KS_DL, "\033|d"},
+ {(int)KS_CDL, "\033|%p1%dD"},
+ {(int)KS_CS, "\033|%p1%d;%p2%dR"},
+ {(int)KS_CL, "\033|C"},
+ // attributes switched on with 'h', off with * 'H'
+ {(int)KS_ME, "\033|31H"}, // HL_ALL
+ {(int)KS_MR, "\033|1h"}, // HL_INVERSE
+ {(int)KS_MD, "\033|2h"}, // HL_BOLD
+ {(int)KS_SE, "\033|16H"}, // HL_STANDOUT
+ {(int)KS_SO, "\033|16h"}, // HL_STANDOUT
+ {(int)KS_UE, "\033|8H"}, // HL_UNDERLINE
+ {(int)KS_US, "\033|8h"}, // HL_UNDERLINE
+ {(int)KS_CZR, "\033|4H"}, // HL_ITALIC
+ {(int)KS_CZH, "\033|4h"}, // HL_ITALIC
+ {(int)KS_VB, "\033|f"},
+ {(int)KS_MS, "y"},
+ {(int)KS_UT, "y"},
+ {(int)KS_LE, "\b"}, // cursor-left = BS
+ {(int)KS_ND, "\014"}, // cursor-right = CTRL-L
+ {(int)KS_CM, "\033|%p1%d;%p2%dM"},
+ // there are no key sequences here, for "abstract_ui" vim key codes are
+ // parsed directly in input_enqueue()
#ifndef NO_BUILTIN_TCAPS
@@ -251,69 +278,6 @@ static struct builtin_term builtin_termcaps[] =
{TERMCAP2KEY('*', '7'), "\233\065\065~"}, /* shifted end key */
# endif
-# if defined(__BEOS__) || defined(ALL_BUILTIN_TCAPS)
- /*
- * almost standard ANSI terminal, default for bebox
- */
- {(int)KS_NAME, "beos-ansi"},
- {(int)KS_CE, "\033[K"},
- {(int)KS_CD, "\033[J"},
- {(int)KS_AL, "\033[L"},
-# ifdef TERMINFO
- {(int)KS_CAL, "\033[%p1%dL"},
-# else
- {(int)KS_CAL, "\033[%dL"},
-# endif
- {(int)KS_DL, "\033[M"},
-# ifdef TERMINFO
- {(int)KS_CDL, "\033[%p1%dM"},
-# else
- {(int)KS_CDL, "\033[%dM"},
-# endif
- {(int)KS_CL, "\033[H\033[2J"},
-#ifdef notyet
- {(int)KS_VI, "[VI]"}, /* cursor invisible, VT320: CSI ? 25 l */
- {(int)KS_VE, "[VE]"}, /* cursor visible, VT320: CSI ? 25 h */
-#endif
- {(int)KS_ME, "\033[m"}, /* normal mode */
- {(int)KS_MR, "\033[7m"}, /* reverse */
- {(int)KS_MD, "\033[1m"}, /* bold */
- {(int)KS_SO, "\033[31m"}, /* standout mode: red */
- {(int)KS_SE, "\033[m"}, /* standout end */
- {(int)KS_CZH, "\033[35m"}, /* italic: purple */
- {(int)KS_CZR, "\033[m"}, /* italic end */
- {(int)KS_US, "\033[4m"}, /* underscore mode */
- {(int)KS_UE, "\033[m"}, /* underscore end */
- {(int)KS_CCO, "8"}, /* allow 8 colors */
-# ifdef TERMINFO
- {(int)KS_CAB, "\033[4%p1%dm"}, /* set background color */
- {(int)KS_CAF, "\033[3%p1%dm"}, /* set foreground color */
-# else
- {(int)KS_CAB, "\033[4%dm"}, /* set background color */
- {(int)KS_CAF, "\033[3%dm"}, /* set foreground color */
-# endif
- {(int)KS_OP, "\033[m"}, /* reset colors */
- {(int)KS_MS, "y"}, /* safe to move cur in reverse mode */
- {(int)KS_UT, "y"}, /* guessed */
- {(int)KS_LE, "\b"},
-# ifdef TERMINFO
- {(int)KS_CM, "\033[%i%p1%d;%p2%dH"},
-# else
- {(int)KS_CM, "\033[%i%d;%dH"},
-# endif
- {(int)KS_SR, "\033M"},
-# ifdef TERMINFO
- {(int)KS_CRI, "\033[%p1%dC"},
-# else
- {(int)KS_CRI, "\033[%dC"},
-# endif
-
- {K_UP, "\033[A"},
- {K_DOWN, "\033[B"},
- {K_LEFT, "\033[D"},
- {K_RIGHT, "\033[C"},
-# endif
-
# if defined(UNIX) || defined(ALL_BUILTIN_TCAPS) || defined(SOME_BUILTIN_TCAPS)
/*
* standard ANSI terminal, default for unix
@@ -1162,6 +1126,10 @@ int set_termname(char_u *term)
if (silent_mode)
return OK;
+ if (!STRCMP(term, "abstract_ui")) {
+ abstract_ui = true;
+ }
+
detected_8bit = false; // reset 8-bit detection
if (term_is_builtin(term)) {
@@ -1829,18 +1797,6 @@ void termcapinit(char_u *name)
/// Write s[len] to the screen.
void term_write(char_u *s, size_t len)
{
- if (embedded_mode) {
- // TODO(tarruda): This is a temporary hack to stop Neovim from writing
- // messages to stdout in embedded mode. In the future, embedded mode will
- // be the only possibility(GUIs will always start neovim with a msgpack-rpc
- // over stdio) and this function won't exist.
- //
- // The reason for this is because before Neovim fully migrates to a
- // msgpack-rpc-driven architecture, we must have a fully functional
- // UI working
- return;
- }
-
(void) fwrite(s, len, 1, stdout);
#ifdef UNIX
@@ -2296,7 +2252,7 @@ void shell_resized_check(void)
*/
void settmode(int tmode)
{
- if (embedded_mode) {
+ if (abstract_ui) {
return;
}
@@ -2340,7 +2296,7 @@ void starttermcap(void)
out_flush();
termcap_active = TRUE;
screen_start(); /* don't know where cursor is now */
- {
+ if (!abstract_ui) {
may_req_termresponse();
/* Immediately check for a response. If t_Co changes, we don't
* want to redraw with wrong colors first. */
@@ -2356,7 +2312,7 @@ void stoptermcap(void)
screen_stop_highlight();
reset_cterm_colors();
if (termcap_active) {
- {
+ if (!abstract_ui) {
/* May need to discard T_CRV or T_U7 response. */
if (crv_status == CRV_SENT || u7_status == U7_SENT) {
# ifdef UNIX
@@ -2545,6 +2501,11 @@ static int cursor_is_off = FALSE;
*/
void cursor_on(void)
{
+ if (abstract_ui) {
+ ui_cursor_on();
+ return;
+ }
+
if (cursor_is_off) {
out_str(T_VE);
cursor_is_off = FALSE;
@@ -2556,6 +2517,11 @@ void cursor_on(void)
*/
void cursor_off(void)
{
+ if (abstract_ui) {
+ ui_cursor_off();
+ return;
+ }
+
if (full_screen) {
if (!cursor_is_off)
out_str(T_VI); /* disable cursor */
@@ -2852,6 +2818,11 @@ void set_mouse_topline(win_T *wp)
*/
int check_termcode(int max_offset, char_u *buf, int bufsize, int *buflen)
{
+ if (abstract_ui) {
+ // codes are parsed by input.c/input_enqueue
+ return 0;
+ }
+
char_u *tp;
char_u *p;
int slen = 0; /* init for GCC */
@@ -3883,6 +3854,10 @@ int find_term_bykeys(char_u *src)
*/
static void gather_termleader(void)
{
+ if (abstract_ui) {
+ return;
+ }
+
int len = 0;
if (check_for_codes)
diff --git a/src/nvim/testdir/dotest.in b/src/nvim/testdir/dotest.in
index b2a0e1a68e..b495f674f8 100644
--- a/src/nvim/testdir/dotest.in
+++ b/src/nvim/testdir/dotest.in
@@ -1,3 +1,3 @@
-:set cp
+:set nocp nomore
:map dotest /^STARTTEST j:set ff=unix cpo-=A :.,/ENDTEST/-1w! Xdotest :set ff& cpo+=A nj0:so! Xdotest dotest
dotest
diff --git a/src/nvim/testdir/test14.in b/src/nvim/testdir/test14.in
index fb987ebc88..6ebec99af6 100644
--- a/src/nvim/testdir/test14.in
+++ b/src/nvim/testdir/test14.in
@@ -13,11 +13,7 @@ vaBiBD:?Bug?,/Piece/-2w! test.out
:s/i/~u~/
:s/o/~~~/
:.w >>test.out
-:if has("ebcdic")
-: let tt = "o\<C-V>193\<C-V>xc2\<C-V>o303 \<C-V>90a\<C-V>xfg\<C-V>o578\<Esc>"
-:else
-: let tt = "o\<C-V>65\<C-V>x42\<C-V>o103 \<C-V>33a\<C-V>xfg\<C-V>o78\<Esc>"
-:endif
+:let tt = "o\<C-V>65\<C-V>x42\<C-V>o103 \<C-V>33a\<C-V>xfg\<C-V>o78\<Esc>"
:exe "normal " . tt
:unlet tt
:.w >>test.out
diff --git a/src/nvim/testdir/test17.in b/src/nvim/testdir/test17.in
index bc542c7625..64534ec77c 100644
--- a/src/nvim/testdir/test17.in
+++ b/src/nvim/testdir/test17.in
@@ -4,11 +4,7 @@ Tests for:
STARTTEST
:so small.vim
-:if has("ebcdic")
-: set isfname=@,240-249,/,.,-,_,+,,,$,:,~,{,}
-:else
-: set isfname=@,48-57,/,.,-,_,+,,,$,:,~,{,}
-:endif
+:set isfname=@,48-57,/,.,-,_,+,,,$,:,~,{,}
:function! DeleteDirectory(dir)
: if has("win16") || has("win32") || has("win64") || has("dos16") || has("dos32")
: exec "silent !rmdir /Q /S " . a:dir
diff --git a/src/nvim/testdir/test40.in b/src/nvim/testdir/test40.in
index d92a18f3d0..ced4572fb8 100644
--- a/src/nvim/testdir/test40.in
+++ b/src/nvim/testdir/test40.in
@@ -2,6 +2,7 @@ Test for "*Cmd" autocommands
STARTTEST
:so small.vim
+:set wildchar=^E
:/^start/,$w! Xxx " write lines below to Xxx
:au BufReadCmd XtestA 0r Xxx|$del
:e XtestA " will read text of Xxd instead
diff --git a/src/nvim/testdir/test48.in b/src/nvim/testdir/test48.in
index 48f4abbf75..25ea2fa154 100644
--- a/src/nvim/testdir/test48.in
+++ b/src/nvim/testdir/test48.in
@@ -4,7 +4,7 @@ STARTTEST
:so small.vim
:set noswf
:set ve=all
--dgg
+j-dgg
:"
:" Insert "keyword keyw", ESC, C CTRL-N, shows "keyword ykeyword".
:" Repeating CTRL-N fixes it. (Mary Ellen Foster)
diff --git a/src/nvim/testdir/test60.in b/src/nvim/testdir/test60.in
index 8835df9e0c..f0f1aecedd 100644
--- a/src/nvim/testdir/test60.in
+++ b/src/nvim/testdir/test60.in
@@ -2,6 +2,7 @@ Tests for the exists() and has() functions. vim: set ft=vim ts=8 sw=2 :
STARTTEST
:so small.vim
+:set wildchar=^E
:function! RunTest(str, result)
if exists(a:str) == a:result
echo "OK"
diff --git a/src/nvim/testdir/test68.in b/src/nvim/testdir/test68.in
index ceaf9af1ab..ca54e942b5 100644
--- a/src/nvim/testdir/test68.in
+++ b/src/nvim/testdir/test68.in
@@ -30,7 +30,7 @@ STARTTEST
/^{/+1
:set tw=3 fo=t
gqgqo
-a 
+a 
ENDTEST
{
@@ -99,7 +99,7 @@ ENDTEST
STARTTEST
/^{/+2
:set tw& fo=a
-I^^
+I^^
ENDTEST
{
diff --git a/src/nvim/testdir/test69.in b/src/nvim/testdir/test69.in
index 674dc32812..26f41e8a29 100644
--- a/src/nvim/testdir/test69.in
+++ b/src/nvim/testdir/test69.in
@@ -15,7 +15,7 @@ STARTTEST
:set tw=2 fo=t
gqgqjgqgqo
XYZ
-abc XYZ
+abc XYZ
ENDTEST
{
@@ -31,7 +31,7 @@ gqgqjgqgqjgqgqjgqgqjgqgqo
Xa
X a
XY
-X Y
+X Y
ENDTEST
{
@@ -55,7 +55,7 @@ aX
abX
abcX
abX c
-abXY
+abXY
ENDTEST
{
@@ -110,7 +110,7 @@ gqgqjgqgqjgqgqjgqgqjgqgqjgqgqjgqgqjgqgqjgqgqjgqgqo
X YZ
XX
XXa
-XXY
+XXY
ENDTEST
{
diff --git a/src/nvim/testdir/test90.in b/src/nvim/testdir/test90.in
index 6bac414f31..3c0d8c030c 100644
--- a/src/nvim/testdir/test90.in
+++ b/src/nvim/testdir/test90.in
@@ -2,7 +2,7 @@ Tests for sha256() function. vim: set ft=vim et ts=2 sw=2 :
STARTTEST
:so small.vim
-:if !has('cryptv') || !exists('*sha256')
+:if !exists('*sha256')
e! test.ok
wq! test.out
:endif
diff --git a/src/nvim/testdir/test_breakindent.in b/src/nvim/testdir/test_breakindent.in
index 150c9430db..0b00c95a85 100644
--- a/src/nvim/testdir/test_breakindent.in
+++ b/src/nvim/testdir/test_breakindent.in
@@ -3,6 +3,7 @@ Test for breakindent
STARTTEST
:so small.vim
:if !exists("+breakindent") | e! test.ok | w! test.out | qa! | endif
+:set wildchar=^E
:10new|:vsp|:vert resize 20
:put =\"\tabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOP\"
:set ts=4 sw=4 sts=4 breakindent
diff --git a/src/nvim/testdir/test_breakindent.ok b/src/nvim/testdir/test_breakindent.ok
index d89d424fb3..a530c18fd3 100644
--- a/src/nvim/testdir/test_breakindent.ok
+++ b/src/nvim/testdir/test_breakindent.ok
@@ -33,13 +33,13 @@ Test 4: Simple breakindent + min width: 18
Test 7: breakindent + shift by +1 + nu + sbr=? briopt:sbr
2 ab
-? m
-? x
+ ? m
+ ? x
Test 8: breakindent + shift:1 + nu + sbr=# list briopt:sbr
2 ^Iabcd
-# opq
-# BCD
+ # opq
+ # BCD
Test 9: breakindent + shift by +1 + 'nu' + sbr=# list
2 ^Iabcd
diff --git a/src/nvim/testdir/test_eval.in b/src/nvim/testdir/test_eval.in
index a29fefc3b6..95a59ee42a 100644
--- a/src/nvim/testdir/test_eval.in
+++ b/src/nvim/testdir/test_eval.in
@@ -1,7 +1,154 @@
+Test for various eval features. vim: set ft=vim :
+
+Note: system clipboard support is not tested. I do not think anybody will thank
+me for messing with clipboard.
+
STARTTEST
:so small.vim
:set encoding=latin1
:set noswapfile
+:lang C
+:fun AppendRegContents(reg)
+ call append('$', printf('%s: type %s; value: %s (%s), expr: %s (%s)', 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
+: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 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
diff --git a/src/nvim/testdir/test_eval.ok b/src/nvim/testdir/test_eval.ok
index 63b9156442..061e0cfd2f 100644
--- a/src/nvim/testdir/test_eval.ok
+++ b/src/nvim/testdir/test_eval.ok
Binary files differ
diff --git a/src/nvim/testdir/test_listlbr.in b/src/nvim/testdir/test_listlbr.in
index 75b06b4cc7..36235ea915 100644
--- a/src/nvim/testdir/test_listlbr.in
+++ b/src/nvim/testdir/test_listlbr.in
@@ -3,6 +3,7 @@ Test for linebreak and list option (non-utf8)
STARTTEST
:so small.vim
:if !exists("+linebreak") | e! test.ok | w! test.out | qa! | endif
+:set wildchar=^E
:10new|:vsp|:vert resize 20
:put =\"\tabcdef hijklmn\tpqrstuvwxyz_1060ABCDEFGHIJKLMNOP \"
:norm! zt
diff --git a/src/nvim/testdir/test_listlbr_utf8.in b/src/nvim/testdir/test_listlbr_utf8.in
index ba12adae05..23b3098786 100644
--- a/src/nvim/testdir/test_listlbr_utf8.in
+++ b/src/nvim/testdir/test_listlbr_utf8.in
@@ -3,6 +3,7 @@ Test for linebreak and list option in utf-8 mode
STARTTEST
:so small.vim
:if !exists("+linebreak") | e! test.ok | w! test.out | qa! | endif
+:set wildchar=^E
:so mbyte.vim
:if &enc !=? 'utf-8'|:e! test.ok|:w! test.out|qa!|endif
:10new|:vsp|:vert resize 20
diff --git a/src/nvim/ui.c b/src/nvim/ui.c
index eab6251288..9c58193e8c 100644
--- a/src/nvim/ui.c
+++ b/src/nvim/ui.c
@@ -15,20 +15,24 @@
* 3. Input buffer stuff.
*/
+#include <assert.h>
#include <inttypes.h>
#include <stdbool.h>
#include <string.h>
#include "nvim/vim.h"
#include "nvim/ui.h"
+#include "nvim/charset.h"
#include "nvim/cursor.h"
#include "nvim/diff.h"
#include "nvim/ex_cmds2.h"
#include "nvim/fold.h"
#include "nvim/main.h"
#include "nvim/mbyte.h"
+#include "nvim/ascii.h"
#include "nvim/misc1.h"
#include "nvim/misc2.h"
+#include "nvim/mbyte.h"
#include "nvim/garray.h"
#include "nvim/memory.h"
#include "nvim/move.h"
@@ -39,27 +43,74 @@
#include "nvim/os/input.h"
#include "nvim/os/signal.h"
#include "nvim/screen.h"
+#include "nvim/syntax.h"
#include "nvim/term.h"
#include "nvim/window.h"
-void ui_write(char_u *s, int len)
+#ifdef INCLUDE_GENERATED_DECLARATIONS
+# include "ui.c.generated.h"
+#endif
+
+#define MAX_UI_COUNT 16
+
+static UI *uis[MAX_UI_COUNT];
+static size_t ui_count = 0;
+static int row, col;
+static struct {
+ int top, bot, left, right;
+} sr;
+static int current_highlight_mask = 0;
+static HlAttrs current_attrs = {
+ false, false, false, false, false, false, -1, -1
+};
+static bool cursor_enabled = true;
+static int height = INT_MAX, width = INT_MAX;
+
+// This set of macros allow us to use UI_CALL to invoke any function on
+// registered UI instances. The functions can have 0-5 arguments(configurable
+// by SELECT_NTH)
+//
+// See http://stackoverflow.com/a/11172679 for a better explanation of how it
+// works.
+#define UI_CALL(...) \
+ do { \
+ for (size_t i = 0; i < ui_count; i++) { \
+ UI *ui = uis[i]; \
+ UI_CALL_HELPER(CNT(__VA_ARGS__), __VA_ARGS__); \
+ } \
+ } while (0)
+#define CNT(...) SELECT_NTH(__VA_ARGS__, MORE, MORE, MORE, MORE, ZERO, ignore)
+#define SELECT_NTH(a1, a2, a3, a4, a5, a6, ...) a6
+#define UI_CALL_HELPER(c, ...) UI_CALL_HELPER2(c, __VA_ARGS__)
+#define UI_CALL_HELPER2(c, ...) UI_CALL_##c(__VA_ARGS__)
+#define UI_CALL_MORE(method, ...) ui->method(ui, __VA_ARGS__)
+#define UI_CALL_ZERO(method) ui->method(ui)
+
+void ui_write(uint8_t *s, int len)
{
- /* Don't output anything in silent mode ("ex -s") unless 'verbose' set */
- if (!(silent_mode && p_verbose == 0)) {
- char_u *tofree = NULL;
+ if (silent_mode && !p_verbose) {
+ // Don't output anything in silent mode ("ex -s") unless 'verbose' set
+ return;
+ }
- if (output_conv.vc_type != CONV_NONE) {
- /* Convert characters from 'encoding' to 'termencoding'. */
- tofree = string_convert(&output_conv, s, &len);
- if (tofree != NULL)
- s = tofree;
- }
+ if (abstract_ui) {
+ parse_abstract_ui_codes(s, len);
+ return;
+ }
- term_write(s, len);
+ char_u *tofree = NULL;
- if (output_conv.vc_type != CONV_NONE)
- free(tofree);
+ if (output_conv.vc_type != CONV_NONE) {
+ /* Convert characters from 'encoding' to 'termencoding'. */
+ tofree = string_convert(&output_conv, s, &len);
+ if (tofree != NULL)
+ s = tofree;
}
+
+ term_write(s, len);
+
+ if (output_conv.vc_type != CONV_NONE)
+ free(tofree);
}
/*
@@ -69,7 +120,11 @@ void ui_write(char_u *s, int len)
*/
void ui_suspend(void)
{
- mch_suspend();
+ if (abstract_ui) {
+ UI_CALL(suspend);
+ } else {
+ mch_suspend();
+ }
}
/*
@@ -79,6 +134,10 @@ void ui_suspend(void)
*/
int ui_get_shellsize(void)
{
+ if (abstract_ui) {
+ return FAIL;
+ }
+
int retval;
retval = mch_get_shellsize();
@@ -98,7 +157,363 @@ int ui_get_shellsize(void)
*/
void ui_cursor_shape(void)
{
- term_cursor_shape();
+ if (abstract_ui) {
+ ui_change_mode();
+ } else {
+ term_cursor_shape();
+ conceal_check_cursur_line();
+ }
+}
+
+void ui_resize(int width, int height)
+{
+ sr.top = 0;
+ sr.bot = height - 1;
+ sr.left = 0;
+ sr.right = width - 1;
+ UI_CALL(resize, width, height);
+}
+
+void ui_cursor_on(void)
+{
+ if (!cursor_enabled) {
+ UI_CALL(cursor_on);
+ cursor_enabled = true;
+ }
+}
+
+void ui_cursor_off(void)
+{
+ if (full_screen) {
+ if (cursor_enabled) {
+ UI_CALL(cursor_off);
+ }
+ cursor_enabled = false;
+ }
+}
+
+void ui_mouse_on(void)
+{
+ if (abstract_ui) {
+ UI_CALL(mouse_on);
+ } else {
+ mch_setmouse(true);
+ }
+}
+
+void ui_mouse_off(void)
+{
+ if (abstract_ui) {
+ UI_CALL(mouse_off);
+ } else {
+ mch_setmouse(false);
+ }
+}
+
+// Notify that the current mode has changed. Can be used to change cursor
+// shape, for example.
+void ui_change_mode(void)
+{
+ static int showing_insert_mode = MAYBE;
+
+ if (!full_screen)
+ return;
+
+ if (State & INSERT) {
+ if (showing_insert_mode != TRUE) {
+ UI_CALL(insert_mode);
+ }
+ showing_insert_mode = TRUE;
+ } else {
+ if (showing_insert_mode != FALSE) {
+ UI_CALL(normal_mode);
+ }
+ showing_insert_mode = FALSE;
+ }
conceal_check_cursur_line();
}
+void ui_attach(UI *ui)
+{
+ if (ui_count == MAX_UI_COUNT) {
+ abort();
+ }
+
+ uis[ui_count++] = ui;
+ resized(ui);
+}
+
+void ui_detach(UI *ui)
+{
+ size_t shift_index = MAX_UI_COUNT;
+
+ // Find the index that will be removed
+ for (size_t i = 0; i < ui_count; i++) {
+ if (uis[i] == ui) {
+ shift_index = i;
+ break;
+ }
+ }
+
+ if (shift_index == MAX_UI_COUNT) {
+ abort();
+ }
+
+ // Shift UIs at "shift_index"
+ while (shift_index < ui_count - 1) {
+ uis[shift_index] = uis[shift_index + 1];
+ shift_index++;
+ }
+
+ ui_count--;
+
+ if (ui->width == width || ui->height == height) {
+ // It is possible that the UI being detached had the smallest screen,
+ // so check for the new minimum dimensions
+ width = height = INT_MAX;
+ for (size_t i = 0; i < ui_count; i++) {
+ check_dimensions(uis[i]);
+ }
+ }
+
+ if (ui_count) {
+ screen_resize(width, height, true);
+ }
+}
+
+static void highlight_start(int mask)
+{
+ if (mask > HL_ALL) {
+ // attribute code
+ current_highlight_mask = mask;
+ } else {
+ // attribute mask
+ current_highlight_mask |= mask;
+ }
+
+ if (!ui_count) {
+ return;
+ }
+
+ set_highlight_args(current_highlight_mask, &current_attrs);
+ UI_CALL(highlight_set, current_attrs);
+}
+
+static void highlight_stop(int mask)
+{
+ if (mask > HL_ALL) {
+ // attribute code
+ current_highlight_mask = HL_NORMAL;
+ } else {
+ // attribute mask
+ current_highlight_mask &= ~mask;
+ }
+
+ set_highlight_args(current_highlight_mask, &current_attrs);
+ UI_CALL(highlight_set, current_attrs);
+}
+
+static void set_highlight_args(int mask, HlAttrs *attrs)
+{
+ attrentry_T *aep = NULL;
+
+ if (mask > HL_ALL) {
+ aep = syn_cterm_attr2entry(mask);
+ mask = aep ? aep->ae_attr : 0;
+ }
+
+ attrs->bold = mask & HL_BOLD;
+ attrs->standout = mask & HL_STANDOUT;
+ attrs->underline = mask & HL_UNDERLINE;
+ attrs->undercurl = mask & HL_UNDERCURL;
+ attrs->italic = mask & HL_ITALIC;
+ attrs->reverse = mask & HL_INVERSE;
+ attrs->foreground = aep && aep->fg_color >= 0 ? aep->fg_color : normal_fg;
+ attrs->background = aep && aep->bg_color >= 0 ? aep->bg_color : normal_bg;
+}
+
+static void parse_abstract_ui_codes(uint8_t *ptr, int len)
+{
+ int arg1 = 0, arg2 = 0;
+ uint8_t *end = ptr + len, *p, c;
+ bool update_cursor = false;
+
+ while (ptr < end) {
+ if (ptr < end - 1 && ptr[0] == ESC && ptr[1] == '|') {
+ p = ptr + 2;
+ assert(p != end);
+
+ if (VIM_ISDIGIT(*p)) {
+ arg1 = (int)getdigits(&p);
+ if (p >= end) {
+ break;
+ }
+
+ if (*p == ';') {
+ p++;
+ arg2 = (int)getdigits(&p);
+ if (p >= end)
+ break;
+ }
+ }
+
+ switch (*p) {
+ case 'C':
+ UI_CALL(clear);
+ break;
+ case 'M':
+ ui_cursor_goto(arg1, arg2);
+ break;
+ case 's':
+ update_cursor = true;
+ break;
+ case 'R':
+ if (arg1 < arg2) {
+ sr.top = arg1;
+ sr.bot = arg2;
+ UI_CALL(set_scroll_region, sr.top, sr.bot, sr.left, sr.right);
+ } else {
+ sr.top = arg2;
+ sr.bot = arg1;
+ UI_CALL(set_scroll_region, sr.top, sr.bot, sr.left, sr.right);
+ }
+ break;
+ case 'V':
+ if (arg1 < arg2) {
+ sr.left = arg1;
+ sr.right = arg2;
+ UI_CALL(set_scroll_region, sr.top, sr.bot, sr.left, sr.right);
+ } else {
+ sr.left = arg2;
+ sr.right = arg1;
+ UI_CALL(set_scroll_region, sr.top, sr.bot, sr.left, sr.right);
+ }
+ break;
+ case 'd':
+ UI_CALL(scroll, 1);
+ break;
+ case 'D':
+ UI_CALL(scroll, arg1);
+ break;
+ case 'i':
+ UI_CALL(scroll, -1);
+ break;
+ case 'I':
+ UI_CALL(scroll, -arg1);
+ break;
+ case '$':
+ UI_CALL(eol_clear);
+ break;
+ case 'h':
+ highlight_start(arg1);
+ break;
+ case 'H':
+ highlight_stop(arg1);
+ break;
+ case 'f':
+ UI_CALL(visual_bell);
+ break;
+ default:
+ // Skip the ESC
+ p = ptr + 1;
+ break;
+ }
+ ptr = ++p;
+ } else if ((c = *ptr) < 0x20) {
+ // Ctrl character
+ if (c == '\n') {
+ ui_linefeed();
+ } else if (c == '\r') {
+ ui_carriage_return();
+ } else if (c == '\b') {
+ ui_cursor_left();
+ } else if (c == Ctrl_L) { // cursor right
+ ui_cursor_right();
+ } else if (c == Ctrl_G) {
+ UI_CALL(bell);
+ }
+ ptr++;
+ } else {
+ p = ptr;
+ while (p < end && (*p >= 0x20)) {
+ size_t clen = (size_t)mb_ptr2len(p);
+ UI_CALL(put, p, (size_t)clen);
+ col++;
+ if (mb_ptr2cells(p) > 1) {
+ // double cell character, blank the next cell
+ UI_CALL(put, NULL, 0);
+ col++;
+ }
+ p += clen;
+ }
+ ptr = p;
+ }
+ }
+
+ if (update_cursor) {
+ ui_cursor_shape();
+ }
+
+ UI_CALL(flush);
+}
+
+static void resized(UI *ui)
+{
+ check_dimensions(ui);
+ screen_resize(width, height, true);
+}
+
+static void check_dimensions(UI *ui)
+{
+ // The internal screen dimensions are always the minimum required to fit on
+ // all connected screens
+ if (ui->width < width) {
+ width = ui->width;
+ }
+
+ if (ui->height < height) {
+ height = ui->height;
+ }
+}
+
+static void ui_linefeed(void)
+{
+ int new_col = 0;
+ int new_row = row;
+ if (new_row < sr.bot) {
+ new_row++;
+ } else {
+ UI_CALL(scroll, 1);
+ }
+ ui_cursor_goto(new_row, new_col);
+}
+
+static void ui_carriage_return(void)
+{
+ int new_col = 0;
+ ui_cursor_goto(row, new_col);
+}
+
+static void ui_cursor_left(void)
+{
+ int new_col = col - 1;
+ assert(new_col >= 0);
+ ui_cursor_goto(row, new_col);
+}
+
+static void ui_cursor_right(void)
+{
+ int new_col = col + 1;
+ assert(new_col < width);
+ ui_cursor_goto(row, new_col);
+}
+
+static void ui_cursor_goto(int new_row, int new_col)
+{
+ if (new_row == row && new_col == col) {
+ return;
+ }
+ row = new_row;
+ col = new_col;
+ UI_CALL(cursor_goto, row, col);
+}
diff --git a/src/nvim/ui.h b/src/nvim/ui.h
index b174af9abe..d0933055cc 100644
--- a/src/nvim/ui.h
+++ b/src/nvim/ui.h
@@ -1,7 +1,39 @@
#ifndef NVIM_UI_H
#define NVIM_UI_H
+#include <stddef.h>
#include <stdbool.h>
+#include <stdint.h>
+
+typedef struct {
+ bool bold, standout, underline, undercurl, italic, reverse;
+ int foreground, background;
+} HlAttrs;
+
+typedef struct ui_t UI;
+
+struct ui_t {
+ int width, height;
+ void *data;
+ void (*resize)(UI *ui, int rows, int columns);
+ void (*clear)(UI *ui);
+ void (*eol_clear)(UI *ui);
+ void (*cursor_goto)(UI *ui, int row, int col);
+ void (*cursor_on)(UI *ui);
+ void (*cursor_off)(UI *ui);
+ void (*mouse_on)(UI *ui);
+ void (*mouse_off)(UI *ui);
+ void (*insert_mode)(UI *ui);
+ void (*normal_mode)(UI *ui);
+ void (*set_scroll_region)(UI *ui, int top, int bot, int left, int right);
+ void (*scroll)(UI *ui, int count);
+ void (*highlight_set)(UI *ui, HlAttrs attrs);
+ void (*put)(UI *ui, uint8_t *str, size_t len);
+ void (*bell)(UI *ui);
+ void (*visual_bell)(UI *ui);
+ void (*flush)(UI *ui);
+ void (*suspend)(UI *ui);
+};
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "ui.h.generated.h"
diff --git a/src/nvim/version.c b/src/nvim/version.c
index f73e5c8cae..6f37982f4d 100644
--- a/src/nvim/version.c
+++ b/src/nvim/version.c
@@ -416,14 +416,14 @@ static int included_patches[] = {
//252 NA
251,
//250 NA
- //249,
+ 249,
248,
247,
//246,
245,
//244,
- //243,
- //242,
+ 243,
+ 242,
241,
240,
239,
diff --git a/test/functional/api/buffer_spec.lua b/test/functional/api/buffer_spec.lua
index 169d605b63..b85594f7af 100644
--- a/test/functional/api/buffer_spec.lua
+++ b/test/functional/api/buffer_spec.lua
@@ -34,6 +34,11 @@ describe('buffer_* functions', function()
curbuf('del_line', 0)
eq('', curbuf('get_line', 0))
end)
+
+ it('can handle NULs', function()
+ curbuf('set_line', 0, 'ab\0cd')
+ eq('ab\0cd', curbuf('get_line', 0))
+ end)
end)
diff --git a/test/functional/api/vim_spec.lua b/test/functional/api/vim_spec.lua
index f34df8cefb..2c17a2acd0 100644
--- a/test/functional/api/vim_spec.lua
+++ b/test/functional/api/vim_spec.lua
@@ -36,6 +36,10 @@ describe('vim_* functions', function()
-- 19 * 2 (each japanese character occupies two cells)
eq(44, nvim('strwidth', 'neovimのデザインかなりまともなのになってる。'))
end)
+
+ it('cannot handle NULs', function()
+ eq(0, nvim('strwidth', '\0abc'))
+ end)
end)
describe('{get,set}_current_line', function()
@@ -52,6 +56,11 @@ describe('vim_* functions', function()
eq({1, 2, {['3'] = 1}}, nvim('get_var', 'lua'))
eq({1, 2, {['3'] = 1}}, nvim('eval', 'g:lua'))
end)
+
+ it('truncates values with NULs in them', function()
+ nvim('set_var', 'xxx', 'ab\0cd')
+ eq('ab', nvim('get_var', 'xxx'))
+ end)
end)
describe('{get,set}_option', function()
diff --git a/test/functional/clipboard/autoload/provider/clipboard.vim b/test/functional/clipboard/autoload/provider/clipboard.vim
new file mode 100644
index 0000000000..6c05a19fc3
--- /dev/null
+++ b/test/functional/clipboard/autoload/provider/clipboard.vim
@@ -0,0 +1,16 @@
+let g:test_clip = { '+': [''], '*': [''], }
+
+let s:methods = {}
+
+function! s:methods.get(reg)
+ return g:test_clip[a:reg]
+endfunction
+
+function! s:methods.set(lines, regtype, reg)
+ let g:test_clip[a:reg] = a:lines
+endfunction
+
+
+function! provider#clipboard#Call(method, args)
+ return call(s:methods[a:method],a:args,s:methods)
+endfunction
diff --git a/test/functional/clipboard/clipboard_provider_spec.lua b/test/functional/clipboard/clipboard_provider_spec.lua
new file mode 100644
index 0000000000..ccbb74e487
--- /dev/null
+++ b/test/functional/clipboard/clipboard_provider_spec.lua
@@ -0,0 +1,141 @@
+-- Test clipboard provider support
+
+local helpers = require('test.functional.helpers')
+local clear, feed, insert = helpers.clear, helpers.feed, helpers.insert
+local execute, expect, eq, eval = helpers.execute, helpers.expect, helpers.eq, helpers.eval
+local nvim, run, stop, restart = helpers.nvim, helpers.run, helpers.stop, helpers.restart
+
+local function reset()
+ clear()
+ execute('let &rtp = "test/functional/clipboard,".&rtp')
+end
+
+local function basic_register_test()
+ insert("some words")
+
+ feed('^dwP')
+ expect('some words')
+
+ feed('veyP')
+ expect('some words words')
+
+ feed('^dwywe"-p')
+ expect('wordssome words')
+
+ feed('p')
+ expect('wordssome words words')
+
+ feed('yyp')
+ expect([[
+ wordssome words words
+ wordssome words words]])
+ feed('d-')
+
+ insert([[
+ some text, and some more
+ random text stuff]])
+ feed('ggtav+2ed$p')
+ expect([[
+ some text, stuff and some more
+ random text]])
+ reset()
+end
+
+describe('clipboard usage', function()
+ setup(reset)
+ it("works", function()
+ basic_register_test()
+
+ -- "* and unnamed should function as independent registers
+ insert("some words")
+ feed('^"*dwdw"*P')
+ expect('some ')
+ eq({'some '}, eval("g:test_clip['*']"))
+ reset()
+
+ -- "* and "+ should be independent when the provider supports it
+ insert([[
+ text:
+ first line
+ secound line
+ third line]])
+
+ feed('G"+dd"*dddd"+p"*pp')
+ expect([[
+ text:
+ third line
+ secound line
+ first line]])
+ -- linewise selection should be encoded as an extra newline
+ eq({'third line', ''}, eval("g:test_clip['+']"))
+ eq({'secound line', ''}, eval("g:test_clip['*']"))
+ reset()
+
+ -- handle null bytes
+ insert("some\x16000text\n\x16000very binary\x16000")
+ feed('"*y-+"*p')
+ eq({'some\ntext', '\nvery binary\n',''}, eval("g:test_clip['*']"))
+ expect("some\x00text\n\x00very binary\x00\nsome\x00text\n\x00very binary\x00")
+
+ -- test getreg/getregtype
+ eq('some\ntext\n\nvery binary\n\n', eval("getreg('*', 1)"))
+ eq("V", eval("getregtype('*')"))
+ reset()
+
+ -- blockwise paste
+ insert([[
+ much
+ text]])
+ feed('"*yy') -- force load of provider
+ execute("let g:test_clip['*'] = [['very','block'],'b']")
+ feed('gg"*P')
+ expect([[
+ very much
+ blocktext]])
+ eq("\x165", eval("getregtype('*')"))
+ reset()
+
+ -- test setreg
+ execute('call setreg("*", "setted\\ntext", "c")')
+ execute('call setreg("+", "explicitly\\nlines", "l")')
+ feed('"+P"*p')
+ expect([[
+ esetted
+ textxplicitly
+ lines
+ ]])
+ reset()
+
+ -- test let @+ (issue #1427)
+ execute("let @+ = 'some'")
+ execute("let @* = ' other stuff'")
+ eq({'some'}, eval("g:test_clip['+']"))
+ eq({' other stuff'}, eval("g:test_clip['*']"))
+ feed('"+p"*p')
+ expect('some other stuff')
+ execute("let @+ .= ' more'")
+ feed('dd"+p')
+ expect('some more')
+ reset()
+
+ -- the basic behavior of unnamed register should be the same
+ -- even when handled by clipboard provider
+ execute('set clipboard=unnamed')
+ basic_register_test()
+
+ -- with cb=unnamed, "* and unnamed will be the same register
+ execute('set clipboard=unnamed')
+ insert("some words")
+ feed('^"*dwdw"*P')
+ expect('words')
+ eq({'words'}, eval("g:test_clip['*']"))
+
+ execute("let g:test_clip['*'] = ['linewise stuff','']")
+ feed('p')
+ expect([[
+ words
+ linewise stuff]])
+ reset()
+
+ end)
+end)
diff --git a/test/functional/helpers.lua b/test/functional/helpers.lua
index b758817b41..fc699d22a3 100644
--- a/test/functional/helpers.lua
+++ b/test/functional/helpers.lua
@@ -47,12 +47,6 @@ local function request(method, ...)
error(rv[2])
end
end
- -- Make sure this will only return after all buffered characters have been
- -- processed
- if not loop_stopped then
- -- Except when the loop has been stopped by a notification triggered
- -- by the initial request, for example.
- end
return rv
end
@@ -70,23 +64,30 @@ local function call_and_stop_on_error(...)
return result
end
-local function run(request_cb, notification_cb, setup_cb)
+local function run(request_cb, notification_cb, setup_cb, timeout)
+ local on_request, on_notification, on_setup
- local function on_request(method, args)
- return call_and_stop_on_error(request_cb, method, args)
+ if request_cb then
+ function on_request(method, args)
+ return call_and_stop_on_error(request_cb, method, args)
+ end
end
- local function on_notification(method, args)
- call_and_stop_on_error(notification_cb, method, args)
+ if notification_cb then
+ function on_notification(method, args)
+ call_and_stop_on_error(notification_cb, method, args)
+ end
end
- local function on_setup()
- call_and_stop_on_error(setup_cb)
+ if setup_cb then
+ function on_setup()
+ call_and_stop_on_error(setup_cb)
+ end
end
loop_stopped = false
loop_running = true
- session:run(on_request, on_notification, on_setup)
+ session:run(on_request, on_notification, on_setup, timeout)
loop_running = false
if last_error then
local err = last_error
@@ -115,15 +116,6 @@ local function nvim_feed(input)
end
end
-local function nvim_replace_termcodes(input)
- -- small hack to stop <C-@> from being replaced by the internal
- -- representation(which is different and won't work for vim_input)
- local temp_replacement = 'CCCCCCCCC@@@@@@@@@@'
- input = input:gsub('<[Cc][-]@>', temp_replacement)
- local rv = request('vim_replace_termcodes', input, false, true, true)
- return rv:gsub(temp_replacement, '\000')
-end
-
local function dedent(str)
-- find minimum common indent across lines
local indent = nil
@@ -148,7 +140,7 @@ end
local function feed(...)
for _, v in ipairs({...}) do
- nvim_feed(nvim_replace_termcodes(dedent(v)))
+ nvim_feed(dedent(v))
end
end
@@ -161,7 +153,7 @@ end
local function clear()
if session then
session:request('vim_command', 'qa!')
- session._async_session._msgpack_stream._loop:exit()
+ session:exit()
end
local loop = Loop.new()
local msgpack_stream = MsgpackStream.new(loop)
@@ -172,8 +164,11 @@ end
local function insert(...)
nvim_feed('i')
- rawfeed(...)
- nvim_feed(nvim_replace_termcodes('<ESC>'))
+ for _, v in ipairs({...}) do
+ local escaped = v:gsub('<', '<lt>')
+ rawfeed(escaped)
+ end
+ nvim_feed('<ESC>')
end
local function execute(...)
@@ -182,8 +177,8 @@ local function execute(...)
-- not a search command, prefix with colon
nvim_feed(':')
end
- nvim_feed(v)
- nvim_feed(nvim_replace_termcodes('<CR>'))
+ nvim_feed(v:gsub('<', '<lt>'))
+ nvim_feed('<CR>')
end
end
diff --git a/test/functional/legacy/026_execute_while_if_spec.lua b/test/functional/legacy/026_execute_while_if_spec.lua
index 9acbf76673..ffe37819de 100644
--- a/test/functional/legacy/026_execute_while_if_spec.lua
+++ b/test/functional/legacy/026_execute_while_if_spec.lua
@@ -13,11 +13,7 @@ describe(':execute, :while and :if', function()
let i = 0
while i < 12
let i = i + 1
- if has("ebcdic")
- execute "normal o" . i . "\047"
- else
- execute "normal o" . i . "\033"
- endif
+ execute "normal o" . i . "\033"
if i % 2
normal Ax
if i == 9
@@ -28,21 +24,13 @@ describe(':execute, :while and :if', function()
else
let j = 9
while j > 0
- if has("ebcdic")
- execute "normal" j . "a" . j . "\x27"
- else
- execute "normal" j . "a" . j . "\x1b"
- endif
+ execute "normal" j . "a" . j . "\x1b"
let j = j - 1
endwhile
endif
endif
if i == 9
- if has("ebcdic")
- execute "normal Az\047"
- else
- execute "normal Az\033"
- endif
+ execute "normal Az\033"
endif
endwhile
unlet i j
diff --git a/test/functional/legacy/033_lisp_indent_spec.lua b/test/functional/legacy/033_lisp_indent_spec.lua
index 3ee248815d..0a5577fad3 100644
--- a/test/functional/legacy/033_lisp_indent_spec.lua
+++ b/test/functional/legacy/033_lisp_indent_spec.lua
@@ -22,7 +22,7 @@ describe('lisp indent', function()
:if-exists :supersede)
(let ((,ti ,title))
(as title ,ti)
- (with center
+ (with center
(as h2 (string-upcase ,ti)))
(brs 3)
,@body))))
@@ -35,7 +35,7 @@ describe('lisp indent', function()
,@body
(princ "</a>")))]])
- execute('set lisp expandtab')
+ execute('set lisp')
execute('/^(defun')
feed('=G:/^(defun/,$yank A<cr>')
@@ -52,15 +52,15 @@ describe('lisp indent', function()
(defmacro page (name title &rest body)
(let ((ti (gensym)))
`(with-open-file (*standard-output*
- (html-file ,name)
- :direction :output
- :if-exists :supersede)
+ (html-file ,name)
+ :direction :output
+ :if-exists :supersede)
(let ((,ti ,title))
- (as title ,ti)
- (with center
- (as h2 (string-upcase ,ti)))
- (brs 3)
- ,@body))))
+ (as title ,ti)
+ (with center
+ (as h2 (string-upcase ,ti)))
+ (brs 3)
+ ,@body))))
;;; Utilities for generating links
diff --git a/test/functional/ui/highlight_spec.lua b/test/functional/ui/highlight_spec.lua
new file mode 100644
index 0000000000..3c55c09f95
--- /dev/null
+++ b/test/functional/ui/highlight_spec.lua
@@ -0,0 +1,184 @@
+local helpers = require('test.functional.helpers')
+local Screen = require('test.functional.ui.screen')
+local clear, feed, nvim = helpers.clear, helpers.feed, helpers.nvim
+local execute = helpers.execute
+
+describe('Default highlight groups', function()
+ -- Test the default attributes for highlight groups shown by the :highlight
+ -- command
+ local screen, hlgroup_colors
+
+ setup(function()
+ hlgroup_colors = {
+ NonText = nvim('name_to_color', 'Blue'),
+ Question = nvim('name_to_color', 'SeaGreen')
+ }
+ end)
+
+ before_each(function()
+ clear()
+ screen = Screen.new()
+ screen:attach()
+ end)
+
+ after_each(function()
+ screen:detach()
+ end)
+
+ it('window status bar', function()
+ screen:set_default_attr_ids({
+ [1] = {reverse = true, bold = true}, -- StatusLine
+ [2] = {reverse = true} -- StatusLineNC
+ })
+ execute('sp', 'vsp', 'vsp')
+ screen:expect([[
+ ^ {2:|} {2:|} |
+ ~ {2:|}~ {2:|}~ |
+ ~ {2:|}~ {2:|}~ |
+ ~ {2:|}~ {2:|}~ |
+ ~ {2:|}~ {2:|}~ |
+ ~ {2:|}~ {2:|}~ |
+ {1:[No Name] }{2:[No Name] [No Name] }|
+ |
+ ~ |
+ ~ |
+ ~ |
+ ~ |
+ {2:[No Name] }|
+ |
+ ]])
+ -- navigate to verify that the attributes are properly moved
+ feed('<c-w>j')
+ screen:expect([[
+ {2:|} {2:|} |
+ ~ {2:|}~ {2:|}~ |
+ ~ {2:|}~ {2:|}~ |
+ ~ {2:|}~ {2:|}~ |
+ ~ {2:|}~ {2:|}~ |
+ ~ {2:|}~ {2:|}~ |
+ {2:[No Name] [No Name] [No Name] }|
+ ^ |
+ ~ |
+ ~ |
+ ~ |
+ ~ |
+ {1:[No Name] }|
+ |
+ ]])
+ -- note that when moving to a window with small width nvim will increase
+ -- the width of the new active window at the expense of a inactive window
+ -- (upstream vim has the same behavior)
+ feed('<c-w>k<c-w>l')
+ screen:expect([[
+ {2:|}^ {2:|} |
+ ~ {2:|}~ {2:|}~ |
+ ~ {2:|}~ {2:|}~ |
+ ~ {2:|}~ {2:|}~ |
+ ~ {2:|}~ {2:|}~ |
+ ~ {2:|}~ {2:|}~ |
+ {2:[No Name] }{1:[No Name] }{2:[No Name] }|
+ |
+ ~ |
+ ~ |
+ ~ |
+ ~ |
+ {2:[No Name] }|
+ |
+ ]])
+ feed('<c-w>l')
+ screen:expect([[
+ {2:|} {2:|}^ |
+ ~ {2:|}~ {2:|}~ |
+ ~ {2:|}~ {2:|}~ |
+ ~ {2:|}~ {2:|}~ |
+ ~ {2:|}~ {2:|}~ |
+ ~ {2:|}~ {2:|}~ |
+ {2:[No Name] [No Name] }{1:[No Name] }|
+ |
+ ~ |
+ ~ |
+ ~ |
+ ~ |
+ {2:[No Name] }|
+ |
+ ]])
+ feed('<c-w>h<c-w>h')
+ screen:expect([[
+ ^ {2:|} {2:|} |
+ ~ {2:|}~ {2:|}~ |
+ ~ {2:|}~ {2:|}~ |
+ ~ {2:|}~ {2:|}~ |
+ ~ {2:|}~ {2:|}~ |
+ ~ {2:|}~ {2:|}~ |
+ {1:[No Name] }{2:[No Name] [No Name] }|
+ |
+ ~ |
+ ~ |
+ ~ |
+ ~ |
+ {2:[No Name] }|
+ |
+ ]])
+ end)
+
+ it('insert mode text', function()
+ feed('i')
+ screen:expect([[
+ ^ |
+ ~ |
+ ~ |
+ ~ |
+ ~ |
+ ~ |
+ ~ |
+ ~ |
+ ~ |
+ ~ |
+ ~ |
+ ~ |
+ ~ |
+ {1:-- INSERT --} |
+ ]], {[1] = {bold = true}})
+ end)
+
+ it('end of file markers', function()
+ nvim('command', 'hi Normal guibg=black')
+ screen:expect([[
+ ^ |
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ |
+ ]], {[1] = {bold = true, foreground = hlgroup_colors.NonText}})
+ end)
+
+ it('"wait return" text', function()
+ feed(':ls<cr>')
+ screen:expect([[
+ ~ |
+ ~ |
+ ~ |
+ ~ |
+ ~ |
+ ~ |
+ ~ |
+ ~ |
+ ~ |
+ ~ |
+ ~ |
+ :ls |
+ 1 %a "[No Name]" line 1 |
+ {1:Press ENTER or type command to continue}^ |
+ ]], {[1] = {bold = true, foreground = hlgroup_colors.Question}})
+ feed('<cr>') -- skip the "Press ENTER..." state or tests will hang
+ end)
+end)
diff --git a/test/functional/ui/input_spec.lua b/test/functional/ui/input_spec.lua
new file mode 100644
index 0000000000..60a49c4ed7
--- /dev/null
+++ b/test/functional/ui/input_spec.lua
@@ -0,0 +1,40 @@
+local helpers = require('test.functional.helpers')
+local clear, execute, nvim = helpers.clear, helpers.execute, helpers.nvim
+local feed, next_message, eq = helpers.feed, helpers.next_message, helpers.eq
+
+describe('mappings', function()
+ local cid
+
+ local add_mapping = function(mapping, send)
+ local str = 'mapped '..mapping
+ local cmd = "nnoremap "..mapping.." :call rpcnotify("..cid..", 'mapped', '"
+ ..send:gsub('<', '<lt>').."')<cr>"
+ execute(cmd)
+ end
+
+ local check_mapping = function(mapping, expected)
+ feed(mapping)
+ eq({'notification', 'mapped', {expected}}, next_message())
+ end
+
+ before_each(function()
+ clear()
+ cid = nvim('get_api_info')[1]
+ add_mapping('<s-up>', '<s-up>')
+ add_mapping('<s-up>', '<s-up>')
+ add_mapping('<c-s-up>', '<c-s-up>')
+ add_mapping('<c-s-a-up>', '<c-s-a-up>')
+ end)
+
+ it('ok', function()
+ check_mapping('<s-up>', '<s-up>')
+ check_mapping('<c-s-up>', '<c-s-up>')
+ check_mapping('<s-c-up>', '<c-s-up>')
+ check_mapping('<c-s-a-up>', '<c-s-a-up>')
+ check_mapping('<s-c-a-up>', '<c-s-a-up>')
+ check_mapping('<c-a-s-up>', '<c-s-a-up>')
+ 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>')
+ end)
+end)
diff --git a/test/functional/ui/mouse_spec.lua b/test/functional/ui/mouse_spec.lua
new file mode 100644
index 0000000000..507b5aacae
--- /dev/null
+++ b/test/functional/ui/mouse_spec.lua
@@ -0,0 +1,157 @@
+local helpers = require('test.functional.helpers')
+local Screen = require('test.functional.ui.screen')
+local clear, feed, nvim = helpers.clear, helpers.feed, helpers.nvim
+
+describe('Mouse input', function()
+ local screen, hlgroup_colors
+
+ setup(function()
+ hlgroup_colors = {
+ Visual = nvim('name_to_color', 'LightGrey'),
+ }
+ end)
+
+ before_each(function()
+ clear()
+ nvim('set_option', 'mouse', 'a')
+ -- set mouset to very high value to ensure that even in valgrind/travis,
+ -- nvim will still pick multiple clicks
+ nvim('set_option', 'mouset', 5000)
+ screen = Screen.new(25, 5)
+ screen:attach()
+ screen:set_default_attr_ids({
+ [1] = {background = hlgroup_colors.Visual}
+ })
+ feed('itesting<cr>mouse<cr>support and selection<esc>')
+ screen:expect([[
+ testing |
+ mouse |
+ support and selectio^ |
+ ~ |
+ |
+ ]])
+ end)
+
+ after_each(function()
+ screen:detach()
+ end)
+
+ it('left click moves cursor', function()
+ feed('<LeftMouse><2,1>')
+ screen:expect([[
+ testing |
+ mo^se |
+ support and selection |
+ ~ |
+ |
+ ]])
+ feed('<LeftMouse><0,0>')
+ screen:expect([[
+ ^esting |
+ mouse |
+ support and selection |
+ ~ |
+ |
+ ]])
+ end)
+
+ it('left drag changes visual selection', function()
+ -- drag events must be preceded by a click
+ feed('<LeftMouse><2,1>')
+ screen:expect([[
+ testing |
+ mo^se |
+ support and selection |
+ ~ |
+ |
+ ]])
+ feed('<LeftDrag><4,1>')
+ screen:expect([[
+ testing |
+ mo{1:us}^ |
+ support and selection |
+ ~ |
+ -- VISUAL -- |
+ ]])
+ feed('<LeftDrag><2,2>')
+ screen:expect([[
+ testing |
+ mo{1:use } |
+ {1:su}^port and selection |
+ ~ |
+ -- VISUAL -- |
+ ]])
+ feed('<LeftDrag><0,0>')
+ screen:expect([[
+ ^{1:esting } |
+ {1:mou}se |
+ support and selection |
+ ~ |
+ -- VISUAL -- |
+ ]])
+ end)
+
+ it('two clicks will select the word and enter VISUAL', function()
+ feed('<LeftMouse><2,2><LeftMouse><2,2>')
+ screen:expect([[
+ testing |
+ mouse |
+ {1:suppor}^ and selection |
+ ~ |
+ -- VISUAL -- |
+ ]])
+ end)
+
+ it('three clicks will select the line and enter VISUAL LINE', function()
+ feed('<LeftMouse><2,2><LeftMouse><2,2><LeftMouse><2,2>')
+ screen:expect([[
+ testing |
+ mouse |
+ {1:su}^{1:port and selection } |
+ ~ |
+ -- VISUAL LINE -- |
+ ]])
+ end)
+
+ it('four clicks will enter VISUAL BLOCK', function()
+ feed('<LeftMouse><2,2><LeftMouse><2,2><LeftMouse><2,2><LeftMouse><2,2>')
+ screen:expect([[
+ testing |
+ mouse |
+ su^port and selection |
+ ~ |
+ -- VISUAL BLOCK -- |
+ ]])
+ end)
+
+ it('right click extends visual selection to the clicked location', function()
+ feed('<LeftMouse><0,0>')
+ screen:expect([[
+ ^esting |
+ mouse |
+ support and selection |
+ ~ |
+ |
+ ]])
+ feed('<RightMouse><2,2>')
+ screen:expect([[
+ {1:testing } |
+ {1:mouse } |
+ {1:su}^port and selection |
+ ~ |
+ -- VISUAL -- |
+ ]])
+ end)
+
+ it('ctrl + left click will search for a tag', function()
+ feed('<C-LeftMouse><0,0>')
+ screen:expect([[
+ E433: No tags file |
+ E426: tag not found: test|
+ ing |
+ Press ENTER or type comma|
+ nd to continue^ |
+ ]])
+ feed('<cr>')
+ end)
+end)
diff --git a/test/functional/ui/screen.lua b/test/functional/ui/screen.lua
new file mode 100644
index 0000000000..8e7d1ed798
--- /dev/null
+++ b/test/functional/ui/screen.lua
@@ -0,0 +1,384 @@
+-- This module contains the Screen class, a complete Nvim screen implementation
+-- designed for functional testing. The goal is to provide a simple and
+-- intuitive API for verifying screen state after a set of actions.
+--
+-- The screen class exposes a single assertion method, "Screen:expect". This
+-- method takes a string representing the expected screen state and an optional
+-- set of attribute identifiers for checking highlighted characters(more on
+-- this later).
+--
+-- The string passed to "expect" will be processed according to these rules:
+--
+-- - Each line of the string represents and is matched individually against
+-- a screen row.
+-- - The entire string is stripped of common indentation
+-- - Expected screen rows are stripped of the last character. The last
+-- character should be used to write pipes(|) that make clear where the
+-- screen ends
+-- - The last line is stripped, so the string must have (row count + 1)
+-- lines.
+--
+-- Example usage:
+--
+-- local screen = Screen.new(25, 10)
+-- -- attach the screen to the current Nvim instance
+-- screen:attach()
+-- --enter insert mode and type some text
+-- feed('ihello screen')
+-- -- declare an expectation for the eventual screen state
+-- screen:expect([[
+-- hello screen |
+-- ~ |
+-- ~ |
+-- ~ |
+-- ~ |
+-- ~ |
+-- ~ |
+-- ~ |
+-- ~ |
+-- -- INSERT -- |
+-- ]]) -- <- Last line is stripped
+--
+-- Since screen updates are received asynchronously, "expect" is actually
+-- specifying the eventual screen state. This is how "expect" works: It will
+-- start the event loop with a timeout of 5 seconds. Each time it receives an
+-- update the expected state will be checked against the updated state.
+--
+-- If the expected state matches the current state, the event loop will be
+-- stopped and "expect" will return. If the timeout expires, the last match
+-- error will be reported and the test will fail.
+--
+-- If the second argument is passed to "expect", the screen rows will be
+-- transformed before being matched against the string lines. The
+-- transformation rule is simple: Each substring "S" composed with characters
+-- having the exact same set of attributes will be substituted by "{K:S}",
+-- where K is a key associated the attribute set via the second argument of
+-- "expect".
+--
+-- Too illustrate how this works, let's say that in the above example we wanted
+-- to assert that the "-- INSERT --" string is highlighted with the bold
+-- attribute(which normally is), here's how the call to "expect" should look
+-- like:
+--
+-- screen:expect([[
+-- hello screen \
+-- ~ \
+-- ~ \
+-- ~ \
+-- ~ \
+-- ~ \
+-- ~ \
+-- ~ \
+-- ~ \
+-- {b:-- INSERT --} \
+-- ]], {b = {bold = true}})
+--
+-- In this case "b" is a string associated with the set composed of one
+-- attribute: bold. Note that since the {b:} markup is not a real part of the
+-- screen, the delimiter(|) had to be moved right
+local helpers = require('test.functional.helpers')
+local request, run, stop = helpers.request, helpers.run, helpers.stop
+local eq, dedent = helpers.eq, helpers.dedent
+
+local Screen = {}
+Screen.__index = Screen
+
+function Screen.new(width, height)
+ if not width then
+ width = 53
+ end
+ if not height then
+ height = 14
+ end
+ return setmetatable({
+ _default_attr_ids = nil,
+ _width = width,
+ _height = height,
+ _rows = new_cell_grid(width, height),
+ _mode = 'normal',
+ _mouse_enabled = true,
+ _bell = false,
+ _visual_bell = false,
+ _suspended = true,
+ _attrs = {},
+ _cursor = {
+ enabled = true, row = 1, col = 1
+ },
+ _scroll_region = {
+ top = 1, bot = height, left = 1, right = width
+ }
+ }, Screen)
+end
+
+function Screen:set_default_attr_ids(attr_ids)
+ self._default_attr_ids = attr_ids
+end
+
+function Screen:attach()
+ request('attach_ui', self._width, self._height)
+ self._suspended = false
+end
+
+function Screen:detach()
+ request('detach_ui')
+ self._suspended = true
+end
+
+function Screen:expect(expected, attr_ids)
+ -- remove the last line and dedent
+ expected = dedent(expected:gsub('\n[ ]+$', ''))
+ local expected_rows = {}
+ for row in expected:gmatch('[^\n]+') do
+ -- the last character should be the screen delimiter
+ row = row:sub(1, #row - 1)
+ table.insert(expected_rows, row)
+ end
+ local ids = attr_ids or self._default_attr_ids
+ self:_wait(function()
+ for i = 1, self._height do
+ local expected_row = expected_rows[i]
+ local actual_row = self:_row_repr(self._rows[i], ids)
+ if expected_row ~= actual_row then
+ return 'Row '..tostring(i)..' didnt match.\nExpected: "'..
+ expected_row..'"\nActual: "'..actual_row..'"'
+ end
+ end
+ end)
+end
+
+function Screen:_wait(check, timeout)
+ local err, checked = false
+ local function notification_cb(method, args)
+ assert(method == 'redraw')
+ self:_redraw(args)
+ err = check()
+ checked = true
+ if not err then
+ stop()
+ end
+ return true
+ end
+ run(nil, notification_cb, nil, timeout or 5000)
+ if not checked then
+ err = check()
+ end
+ if err then
+ error(err)
+ end
+end
+
+function Screen:_redraw(updates)
+ for _, update in ipairs(updates) do
+ -- print('--')
+ -- print(require('inspect')(update))
+ local method = update[1]
+ for i = 2, #update do
+ local handler = self['_handle_'..method]
+ handler(self, unpack(update[i]))
+ end
+ -- print(self:_current_screen())
+ end
+end
+
+function Screen:_handle_resize(width, height)
+ self._rows = new_cell_grid(width, height)
+end
+
+function Screen:_handle_clear()
+ self:_clear_block(1, self._height, 1, self._width)
+end
+
+function Screen:_handle_eol_clear()
+ local row, col = self._cursor.row, self._cursor.col
+ self:_clear_block(row, 1, col, self._width - col)
+end
+
+function Screen:_handle_cursor_goto(row, col)
+ self._cursor.row = row + 1
+ self._cursor.col = col + 1
+end
+
+function Screen:_handle_cursor_on()
+ self._cursor.enabled = true
+end
+
+function Screen:_handle_cursor_off()
+ self._cursor.enabled = false
+end
+
+function Screen:_handle_mouse_on()
+ self._mouse_enabled = true
+end
+
+function Screen:_handle_mouse_off()
+ self._mouse_enabled = false
+end
+
+function Screen:_handle_insert_mode()
+ self._mode = 'insert'
+end
+
+function Screen:_handle_normal_mode()
+ self._mode = 'normal'
+end
+
+function Screen:_handle_set_scroll_region(top, bot, left, right)
+ self._scroll_region.top = top + 1
+ self._scroll_region.bot = bot + 1
+ self._scroll_region.left = left + 1
+ self._scroll_region.right = right + 1
+end
+
+function Screen:_handle_scroll(count)
+ local top = self._scroll_region.top
+ local bot = self._scroll_region.bot
+ local left = self._scroll_region.left
+ local right = self._scroll_region.right
+ local start, stop, step
+
+ if count > 0 then
+ start = top
+ stop = bot - count
+ step = 1
+ else
+ start = bot
+ stop = top - count
+ step = -1
+ end
+
+ -- shift scroll region
+ for i = start, stop, step do
+ local target = self._rows[i]
+ local source = self._rows[i + count]
+ self:_copy_row_section(target, source, left, right)
+ end
+
+ -- clear invalid rows
+ for i = stop + 1, stop + count, step do
+ self:_clear_row_section(i, left, right)
+ end
+end
+
+function Screen:_handle_highlight_set(attrs)
+ self._attrs = attrs
+end
+
+function Screen:_handle_put(str)
+ local cell = self._rows[self._cursor.row][self._cursor.col]
+ cell.text = str
+ cell.attrs = self._attrs
+ self._cursor.col = self._cursor.col + 1
+end
+
+function Screen:_handle_bell()
+ self._bell = true
+end
+
+function Screen:_handle_visual_bell()
+ self._visual_bell = true
+end
+
+function Screen:_handle_suspend()
+ self._suspended = true
+end
+
+function Screen:_clear_block(top, lines, left, columns)
+ for i = top, top + lines - 1 do
+ self:_clear_row_section(i, left, left + columns - 1)
+ end
+end
+
+function Screen:_clear_row_section(rownum, startcol, stopcol)
+ local row = self._rows[rownum]
+ for i = startcol, stopcol do
+ row[i].text = ' '
+ row[i].attrs = {}
+ end
+end
+
+function Screen:_copy_row_section(target, source, startcol, stopcol)
+ for i = startcol, stopcol do
+ target[i].text = source[i].text
+ target[i].attrs = source[i].attrs
+ end
+end
+
+function Screen:_row_repr(row, attr_ids)
+ local rv = {}
+ local current_attr_id
+ for i = 1, self._width do
+ local attr_id = get_attr_id(attr_ids, row[i].attrs)
+ if current_attr_id and attr_id ~= current_attr_id then
+ -- close current attribute bracket, add it before any whitespace
+ -- up to the current cell
+ -- table.insert(rv, backward_find_meaningful(rv, i), '}')
+ table.insert(rv, '}')
+ current_attr_id = nil
+ end
+ if not current_attr_id and attr_id then
+ -- open a new attribute bracket
+ table.insert(rv, '{' .. attr_id .. ':')
+ current_attr_id = attr_id
+ end
+ if self._rows[self._cursor.row] == row and self._cursor.col == i then
+ table.insert(rv, '^')
+ else
+ table.insert(rv, row[i].text)
+ end
+ end
+ if current_attr_id then
+ table.insert(rv, '}')
+ end
+ -- return the line representation, but remove empty attribute brackets and
+ -- trailing whitespace
+ return table.concat(rv, '')--:gsub('%s+$', '')
+end
+
+
+function Screen:_current_screen()
+ -- get a string that represents the current screen state(debugging helper)
+ local rv = {}
+ for i = 1, self._height do
+ table.insert(rv, "'"..self:_row_repr(self._rows[i]).."'")
+ end
+ return table.concat(rv, '\n')
+end
+
+function backward_find_meaningful(tbl, from)
+ for i = from or #tbl, 1, -1 do
+ if tbl[i] ~= ' ' then
+ return i + 1
+ end
+ end
+ return from
+end
+
+function new_cell_grid(width, height)
+ local rows = {}
+ for i = 1, height do
+ local cols = {}
+ for j = 1, width do
+ table.insert(cols, {text = ' ', attrs = {}})
+ end
+ table.insert(rows, cols)
+ end
+ return rows
+end
+
+function get_attr_id(attr_ids, attrs)
+ if not attr_ids then
+ return
+ end
+ for id, a in pairs(attr_ids) do
+ if a.bold == attrs.bold and a.standout == attrs.standout and
+ a.underline == attrs.underline and a.undercurl == attrs.undercurl and
+ a.italic == attrs.italic and a.reverse == attrs.reverse and
+ a.foreground == attrs.foreground and
+ a.background == attrs.background then
+ return id
+ end
+ end
+ return nil
+end
+
+return Screen
diff --git a/test/functional/ui/screen_basic_spec.lua b/test/functional/ui/screen_basic_spec.lua
new file mode 100644
index 0000000000..a1110b3231
--- /dev/null
+++ b/test/functional/ui/screen_basic_spec.lua
@@ -0,0 +1,224 @@
+local helpers = require('test.functional.helpers')
+local Screen = require('test.functional.ui.screen')
+local clear, feed, execute = helpers.clear, helpers.feed, helpers.execute
+local insert = helpers.insert
+
+describe('Screen', function()
+ local screen
+
+ before_each(function()
+ clear()
+ screen = Screen.new()
+ screen:attach()
+ end)
+
+ after_each(function()
+ screen:detach()
+ end)
+
+ describe('window', function()
+ describe('split', function()
+ it('horizontal', function()
+ execute('sp')
+ screen:expect([[
+ ^ |
+ ~ |
+ ~ |
+ ~ |
+ ~ |
+ ~ |
+ [No Name] |
+ |
+ ~ |
+ ~ |
+ ~ |
+ ~ |
+ [No Name] |
+ :sp |
+ ]])
+ end)
+
+ it('horizontal and resize', function()
+ execute('sp')
+ execute('resize 8')
+ screen:expect([[
+ ^ |
+ ~ |
+ ~ |
+ ~ |
+ ~ |
+ ~ |
+ ~ |
+ ~ |
+ [No Name] |
+ |
+ ~ |
+ ~ |
+ [No Name] |
+ :resize 8 |
+ ]])
+ end)
+
+ it('horizontal and vertical', function()
+ execute('sp', 'vsp', 'vsp')
+ screen:expect([[
+ ^ | | |
+ ~ |~ |~ |
+ ~ |~ |~ |
+ ~ |~ |~ |
+ ~ |~ |~ |
+ ~ |~ |~ |
+ [No Name] [No Name] [No Name] |
+ |
+ ~ |
+ ~ |
+ ~ |
+ ~ |
+ [No Name] |
+ |
+ ]])
+ insert('hello')
+ screen:expect([[
+ hell^ |hello |hello |
+ ~ |~ |~ |
+ ~ |~ |~ |
+ ~ |~ |~ |
+ ~ |~ |~ |
+ ~ |~ |~ |
+ [No Name] [+] [No Name] [+] [No Name] [+] |
+ hello |
+ ~ |
+ ~ |
+ ~ |
+ ~ |
+ [No Name] [+] |
+ |
+ ]])
+ end)
+ end)
+ end)
+
+ describe('tabnew', function()
+ it('creates a new buffer', function()
+ execute('sp', 'vsp', 'vsp')
+ insert('hello')
+ screen:expect([[
+ hell^ |hello |hello |
+ ~ |~ |~ |
+ ~ |~ |~ |
+ ~ |~ |~ |
+ ~ |~ |~ |
+ ~ |~ |~ |
+ [No Name] [+] [No Name] [+] [No Name] [+] |
+ hello |
+ ~ |
+ ~ |
+ ~ |
+ ~ |
+ [No Name] [+] |
+ |
+ ]])
+ execute('tabnew')
+ insert('hello2')
+ feed('h')
+ screen:expect([[
+ 4+ [No Name] + [No Name] X|
+ hell^2 |
+ ~ |
+ ~ |
+ ~ |
+ ~ |
+ ~ |
+ ~ |
+ ~ |
+ ~ |
+ ~ |
+ ~ |
+ ~ |
+ |
+ ]])
+ execute('tabprevious')
+ screen:expect([[
+ 4+ [No Name] + [No Name] X|
+ hell^ |hello |hello |
+ ~ |~ |~ |
+ ~ |~ |~ |
+ ~ |~ |~ |
+ ~ |~ |~ |
+ ~ |~ |~ |
+ [No Name] [+] [No Name] [+] [No Name] [+] |
+ hello |
+ ~ |
+ ~ |
+ ~ |
+ [No Name] [+] |
+ |
+ ]])
+ end)
+ end)
+
+ describe('insert mode', function()
+ it('move to next line with <cr>', function()
+ feed('iline 1<cr>line 2<cr>')
+ screen:expect([[
+ line 1 |
+ line 2 |
+ ^ |
+ ~ |
+ ~ |
+ ~ |
+ ~ |
+ ~ |
+ ~ |
+ ~ |
+ ~ |
+ ~ |
+ ~ |
+ -- INSERT -- |
+ ]])
+ end)
+ end)
+
+ describe('command mode', function()
+ it('typing commands', function()
+ feed(':ls')
+ screen:expect([[
+ |
+ ~ |
+ ~ |
+ ~ |
+ ~ |
+ ~ |
+ ~ |
+ ~ |
+ ~ |
+ ~ |
+ ~ |
+ ~ |
+ ~ |
+ :ls^ |
+ ]])
+ end)
+
+ it('execute command with multi-line output', function()
+ feed(':ls<cr>')
+ screen:expect([[
+ ~ |
+ ~ |
+ ~ |
+ ~ |
+ ~ |
+ ~ |
+ ~ |
+ ~ |
+ ~ |
+ ~ |
+ ~ |
+ :ls |
+ 1 %a "[No Name]" line 1 |
+ Press ENTER or type command to continue^ |
+ ]])
+ feed('<cr>') -- skip the "Press ENTER..." state or tests will hang
+ end)
+ end)
+end)
diff --git a/third-party/CMakeLists.txt b/third-party/CMakeLists.txt
index 2bb7fc37f2..9f0e3fac9e 100644
--- a/third-party/CMakeLists.txt
+++ b/third-party/CMakeLists.txt
@@ -70,17 +70,17 @@ set(LUAROCKS_URL https://github.com/keplerproject/luarocks/archive/0587afbb5fe8c
set(LUAROCKS_SHA1 61a894fd5d61987bf7e7f9c3e0c5de16ba4b68c4)
set(LUAROCKS_MD5 0f53f42909fbcd2c88be303e8f970516)
-set(LIBUNIBILIUM_URL https://github.com/mauke/unibilium/archive/v1.1.1.tar.gz)
-set(LIBUNIBILIUM_SHA1 582cbac75989d70e70953fa826cb5457cbfacc10)
-set(LIBUNIBILIUM_MD5 c6ff790d31c2fb9e2dbe6c40004d6fc3)
+set(LIBUNIBILIUM_URL https://github.com/neovim/unibilium/archive/neovim.tar.gz)
+set(LIBUNIBILIUM_SHA1 ab22e465150458a4ea91b72de997a35f25df1bcf)
+set(LIBUNIBILIUM_MD5 b0749651429aa4c619baf44eedcd15c6)
set(LIBTERMKEY_URL https://github.com/neovim/libtermkey/archive/neovim.tar.gz)
set(LIBTERMKEY_SHA1 a309038a2297fe4905f03a8807723a9aa07c272a)
set(LIBTERMKEY_MD5 c99e5546da0063fa26dfa7d7f1d5a26f)
set(LIBTICKIT_URL https://github.com/neovim/libtickit/archive/neovim.tar.gz)
-set(LIBTICKIT_SHA1 49e609de29c3bdc3b40d2ade76e69fde6e0d74bc)
-set(LIBTICKIT_MD5 71a5d36d0ef6688d79828aabaf27eb36)
+set(LIBTICKIT_SHA1 08a2aa9ab4bacbeeafefac430691089d829fdb13)
+set(LIBTICKIT_MD5 d2d45eb4f2968b068aa5cc310b7f9abd)
if(USE_BUNDLED_LIBUNIBILIUM)
ExternalProject_Add(libunibilium
@@ -281,7 +281,7 @@ if(USE_BUNDLED_LUAROCKS)
add_custom_command(OUTPUT ${DEPS_LIB_DIR}/luarocks/rocks/nvim-client
COMMAND ${DEPS_BIN_DIR}/luarocks
- ARGS build https://raw.githubusercontent.com/neovim/lua-client/8c40a2fdad5cc407ed5781909965ac87db0aefb0/nvim-client-0.0.1-5.rockspec CC=${DEPS_C_COMPILER} LD=${DEPS_C_COMPILER} LIBUV_DIR=${DEPS_INSTALL_DIR}
+ ARGS build https://raw.githubusercontent.com/neovim/lua-client/a6c232da23dafe085c5606a3d0a666a77dd7d8bd/nvim-client-0.0.1-7.rockspec CC=${DEPS_C_COMPILER} LD=${DEPS_C_COMPILER} LIBUV_DIR=${DEPS_INSTALL_DIR}
DEPENDS lpeg libuv)
add_custom_target(nvim-client
DEPENDS ${DEPS_LIB_DIR}/luarocks/rocks/nvim-client)