Merge branch 'master' into luaviml'/lua
This commit is contained in:
commit
043d8ff9f2
|
@ -39,9 +39,6 @@ tags
|
|||
# generated by luacheck during `make testlint'
|
||||
/test/.luacheckcache
|
||||
|
||||
# luarocks, not added as a subtree because of the large number of blobs
|
||||
/third-party/luarocks
|
||||
|
||||
# local make targets
|
||||
local.mk
|
||||
|
||||
|
@ -49,6 +46,3 @@ local.mk
|
|||
/runtime/doc/*.html
|
||||
/runtime/doc/tags.ref
|
||||
/runtime/doc/errors.log
|
||||
|
||||
# clint errors, generated by `make lint`
|
||||
/errors.json
|
||||
|
|
25
.travis.yml
25
.travis.yml
|
@ -10,7 +10,7 @@ env:
|
|||
# http://docs.travis-ci.com/user/speeding-up-the-build/#Paralellizing-your-build-on-one-VM
|
||||
- MAKE_CMD="make -j2"
|
||||
# Update PATH for pip.
|
||||
- PATH="$(python2.7 -c 'import site; print(site.getuserbase())')/bin:/usr/lib/llvm-symbolizer-3.8/bin:$PATH"
|
||||
- PATH="$(python2.7 -c 'import site; print(site.getuserbase())')/bin:/usr/lib/llvm-symbolizer-3.9/bin:$PATH"
|
||||
# Build directory for Neovim.
|
||||
- BUILD_DIR="$TRAVIS_BUILD_DIR/build"
|
||||
# Build directory for third-party dependencies.
|
||||
|
@ -50,6 +50,7 @@ env:
|
|||
- SUCCESS_MARKER="$BUILD_DIR/.tests_successful"
|
||||
# default target name for functional tests
|
||||
- FUNCTIONALTEST=functionaltest
|
||||
- CI_TARGET=tests
|
||||
|
||||
matrix:
|
||||
include:
|
||||
|
@ -68,12 +69,12 @@ matrix:
|
|||
compiler: gcc-5 -m32
|
||||
env: BUILD_32BIT=ON
|
||||
- os: linux
|
||||
compiler: clang-3.8
|
||||
compiler: clang-3.9
|
||||
env: >
|
||||
CLANG_SANITIZER=ASAN_UBSAN
|
||||
CMAKE_FLAGS="$CMAKE_FLAGS -DPREFER_LUAJIT=false"
|
||||
- os: linux
|
||||
compiler: clang-3.8
|
||||
compiler: clang-3.9
|
||||
env: CLANG_SANITIZER=TSAN
|
||||
- os: osx
|
||||
compiler: clang
|
||||
|
@ -85,24 +86,24 @@ matrix:
|
|||
- env: GCOV=gcov-5 CMAKE_FLAGS="$CMAKE_FLAGS -DUSE_GCOV=ON"
|
||||
fast_finish: true
|
||||
|
||||
before_install: .ci/before_install.sh
|
||||
install: .ci/install.sh
|
||||
before_script: .ci/before_script.sh
|
||||
script: .ci/script.sh
|
||||
before_cache: .ci/before_cache.sh
|
||||
after_success: .ci/after_success.sh
|
||||
before_install: ci/before_install.sh
|
||||
install: ci/install.sh
|
||||
before_script: ci/before_script.sh
|
||||
script: ci/script.sh
|
||||
before_cache: ci/before_cache.sh
|
||||
after_success: ci/after_success.sh
|
||||
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
- llvm-toolchain-precise-3.8
|
||||
- llvm-toolchain-trusty-3.9
|
||||
packages:
|
||||
- autoconf
|
||||
- automake
|
||||
- apport
|
||||
- build-essential
|
||||
- clang-3.8
|
||||
- clang-3.9
|
||||
- cmake
|
||||
- cscope
|
||||
- g++-5-multilib
|
||||
|
@ -112,7 +113,7 @@ addons:
|
|||
- gdb
|
||||
- libc6-dev-i386
|
||||
- libtool
|
||||
- llvm-3.8-dev
|
||||
- llvm-3.9-dev
|
||||
- pkg-config
|
||||
- unzip
|
||||
- valgrind
|
||||
|
|
|
@ -318,6 +318,21 @@ if(NOT PREFER_LUAJIT)
|
|||
find_package(Lua REQUIRED)
|
||||
endif()
|
||||
|
||||
list(APPEND CMAKE_REQUIRED_INCLUDES "${MSGPACK_INCLUDE_DIRS}")
|
||||
check_c_source_compiles("
|
||||
#include <msgpack.h>
|
||||
|
||||
int
|
||||
main(void)
|
||||
{
|
||||
return MSGPACK_OBJECT_FLOAT32;
|
||||
}
|
||||
" MSGPACK_HAS_FLOAT32)
|
||||
|
||||
if(MSGPACK_HAS_FLOAT32)
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DNVIM_MSGPACK_HAS_FLOAT32")
|
||||
endif()
|
||||
|
||||
if(UNIX)
|
||||
option(FEAT_TUI "Enable the Terminal UI" ON)
|
||||
else()
|
||||
|
|
15
Makefile
15
Makefile
|
@ -126,12 +126,15 @@ distclean: clean
|
|||
install: | nvim
|
||||
+$(BUILD_CMD) -C build install
|
||||
|
||||
clint:
|
||||
$(CMAKE_PRG) -DLINT_PRG=./src/clint.py \
|
||||
-DLINT_DIR=src \
|
||||
-DLINT_SUPPRESS_URL="$(DOC_DOWNLOAD_URL_BASE)$(CLINT_ERRORS_FILE_PATH)" \
|
||||
-P cmake/RunLint.cmake
|
||||
clint: build/.ran-cmake
|
||||
+$(BUILD_CMD) -C build clint
|
||||
|
||||
lint: clint testlint
|
||||
clint-full: build/.ran-cmake
|
||||
+$(BUILD_CMD) -C build clint-full
|
||||
|
||||
check-single-includes: build/.ran-cmake
|
||||
+$(BUILD_CMD) -C build check-single-includes
|
||||
|
||||
lint: check-single-includes clint testlint
|
||||
|
||||
.PHONY: test testlint functionaltest unittest lint clint clean distclean nvim libnvim cmake deps install
|
||||
|
|
|
@ -43,7 +43,7 @@ Packages are in [Homebrew], [Debian], [Ubuntu], [Fedora], [Arch Linux], and
|
|||
Project layout
|
||||
--------------
|
||||
|
||||
- `.ci/`: Build server scripts
|
||||
- `ci/`: Build server scripts
|
||||
- `cmake/`: Build scripts
|
||||
- `runtime/`: Application files
|
||||
- [`src/`](src/nvim/README.md): Application source code
|
||||
|
|
|
@ -4,9 +4,9 @@ configuration:
|
|||
- MINGW_32
|
||||
install: []
|
||||
build_script:
|
||||
- call .ci\build.bat
|
||||
- call ci\build.bat
|
||||
cache:
|
||||
- C:\msys64\var\cache\pacman\pkg -> .ci\build.bat
|
||||
- C:\msys64\var\cache\pacman\pkg -> ci\build.bat
|
||||
- .deps -> third-party/CMakeLists.txt
|
||||
artifacts:
|
||||
- path: build/Neovim.zip
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
set -e
|
||||
set -o pipefail
|
||||
|
||||
if [[ -n "${CI_TARGET}" ]]; then
|
||||
if [[ "${CI_TARGET}" == lint ]]; then
|
||||
exit
|
||||
fi
|
||||
|
|
@ -3,7 +3,7 @@
|
|||
set -e
|
||||
set -o pipefail
|
||||
|
||||
if [[ -n "${CI_TARGET}" ]]; then
|
||||
if [[ "${CI_TARGET}" == lint ]]; then
|
||||
exit
|
||||
fi
|
||||
|
|
@ -1,3 +1,11 @@
|
|||
top_make() {
|
||||
${MAKE_CMD} "$@"
|
||||
}
|
||||
|
||||
build_make() {
|
||||
top_make -C "${BUILD_DIR}" "$@"
|
||||
}
|
||||
|
||||
build_deps() {
|
||||
if [[ "${BUILD_32BIT}" == ON ]]; then
|
||||
DEPS_CMAKE_FLAGS="${DEPS_CMAKE_FLAGS} ${CMAKE_FLAGS_32BIT}"
|
||||
|
@ -31,7 +39,7 @@ build_deps() {
|
|||
echo "Configuring with '${DEPS_CMAKE_FLAGS}'."
|
||||
CC= cmake ${DEPS_CMAKE_FLAGS} "${TRAVIS_BUILD_DIR}/third-party/"
|
||||
|
||||
if ! ${MAKE_CMD}; then
|
||||
if ! top_make; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
|
@ -54,18 +62,18 @@ prepare_build() {
|
|||
|
||||
build_nvim() {
|
||||
echo "Building nvim."
|
||||
if ! ${MAKE_CMD} nvim; then
|
||||
if ! top_make nvim; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ "$CLANG_SANITIZER" != "TSAN" ]; then
|
||||
echo "Building libnvim."
|
||||
if ! ${MAKE_CMD} libnvim; then
|
||||
if ! top_make libnvim; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Building nvim-test."
|
||||
if ! ${MAKE_CMD} nvim-test; then
|
||||
if ! top_make nvim-test; then
|
||||
exit 1
|
||||
fi
|
||||
fi
|
|
@ -0,0 +1,121 @@
|
|||
# HACK: get newline for use in strings given that "\n" and $'' do not work.
|
||||
NL="$(printf '\nE')"
|
||||
NL="${NL%E}"
|
||||
|
||||
FAILED=0
|
||||
|
||||
FAIL_SUMMARY=""
|
||||
|
||||
enter_suite() {
|
||||
local suite_name="$1"
|
||||
export NVIM_TEST_CURRENT_SUITE="${NVIM_TEST_CURRENT_SUITE}/$suite_name"
|
||||
}
|
||||
|
||||
exit_suite() {
|
||||
if test $FAILED -ne 0 ; then
|
||||
echo "Suite ${NVIM_TEST_CURRENT_SUITE} failed, summary:"
|
||||
echo "${FAIL_SUMMARY}"
|
||||
fi
|
||||
export NVIM_TEST_CURRENT_SUITE="${NVIM_TEST_CURRENT_SUITE%/*}"
|
||||
if test "x$1" != "x--continue" ; then
|
||||
exit $FAILED
|
||||
fi
|
||||
}
|
||||
|
||||
fail() {
|
||||
local allow_failure=
|
||||
if test "x$1" = "x--allow-failure" ; then
|
||||
shift
|
||||
allow_failure=A
|
||||
fi
|
||||
local test_name="$1"
|
||||
local fail_char="$allow_failure$2"
|
||||
local message="$3"
|
||||
|
||||
: ${fail_char:=F}
|
||||
: ${message:=Test $test_name failed}
|
||||
|
||||
local full_msg="$fail_char $NVIM_TEST_CURRENT_SUITE|$test_name :: $message"
|
||||
FAIL_SUMMARY="${FAIL_SUMMARY}${NL}${full_msg}"
|
||||
echo "Failed: $full_msg"
|
||||
if test "x$allow_failure" = "x" ; then
|
||||
FAILED=1
|
||||
fi
|
||||
}
|
||||
|
||||
run_test() {
|
||||
local cmd="$1"
|
||||
test $# -gt 0 && shift
|
||||
local test_name="$1"
|
||||
: ${test_name:=$cmd}
|
||||
test $# -gt 0 && shift
|
||||
if ! eval "$cmd" ; then
|
||||
fail "${test_name}" "$@"
|
||||
fi
|
||||
}
|
||||
|
||||
run_test_wd() {
|
||||
local timeout="$1"
|
||||
test $# -gt 0 && shift
|
||||
|
||||
local cmd="$1"
|
||||
test $# -gt 0 && shift
|
||||
|
||||
local restart_cmd="$1"
|
||||
: ${restart_cmd:=true}
|
||||
test $# -gt 0 && shift
|
||||
|
||||
local test_name="$1"
|
||||
: ${test_name:=$cmd}
|
||||
test $# -gt 0 && shift
|
||||
|
||||
local output_file="$(mktemp)"
|
||||
local status_file="$(mktemp)"
|
||||
|
||||
local restarts=5
|
||||
local prev_tmpsize=-1
|
||||
while test $restarts -gt 0 ; do
|
||||
: > "${status_file}"
|
||||
(
|
||||
FAILED=0
|
||||
if ! (
|
||||
set -o pipefail
|
||||
eval "$cmd" 2>&1 | tee -a "$output_file"
|
||||
) ; then
|
||||
fail "${test_name}" "$@"
|
||||
fi
|
||||
echo "$FAILED" > "$status_file"
|
||||
) &
|
||||
local pid=$!
|
||||
while test "$(stat -c "%s" "$status_file")" -eq 0 ; do
|
||||
prev_tmpsize=$tmpsize
|
||||
sleep $timeout
|
||||
tmpsize="$(stat -c "%s" "$output_file")"
|
||||
if test $tempsize -eq $prev_temsize ; then
|
||||
# no output, assuming either hang or exit
|
||||
break
|
||||
fi
|
||||
done
|
||||
restarts=$[ restarts - 1 ]
|
||||
if test "$(stat -c "%s" "$status_file")" -eq 0 ; then
|
||||
# status file not updated, assuming hang
|
||||
kill -KILL $pid
|
||||
if test $restarts -eq 0 ; then
|
||||
fail "${test_name}" E "Test hang up"
|
||||
else
|
||||
echo "Test ${test_name} hang up, restarting"
|
||||
eval "$restart_cmd"
|
||||
fi
|
||||
else
|
||||
local new_failed="$(cat "$status_file")"
|
||||
if test "x$new_failed" != "x0" ; then
|
||||
fail "${test_name}" F "Test failed in run_test_wd"
|
||||
fi
|
||||
return 0
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
succeeded() {
|
||||
return $FAILED
|
||||
}
|
|
@ -1,3 +1,5 @@
|
|||
source "${CI_DIR}/common/build.sh"
|
||||
|
||||
print_core() {
|
||||
local app="$1"
|
||||
local core="$2"
|
||||
|
@ -75,7 +77,7 @@ asan_check() {
|
|||
|
||||
run_unittests() {
|
||||
ulimit -c unlimited
|
||||
if ! ${MAKE_CMD} -C "${BUILD_DIR}" unittest ; then
|
||||
if ! build_make unittest ; then
|
||||
check_core_dumps "$(which luajit)"
|
||||
exit 1
|
||||
fi
|
||||
|
@ -84,7 +86,7 @@ run_unittests() {
|
|||
|
||||
run_functionaltests() {
|
||||
ulimit -c unlimited
|
||||
if ! ${MAKE_CMD} -C "${BUILD_DIR}" ${FUNCTIONALTEST}; then
|
||||
if ! build_make ${FUNCTIONALTEST}; then
|
||||
asan_check "${LOG_DIR}"
|
||||
valgrind_check "${LOG_DIR}"
|
||||
check_core_dumps
|
||||
|
@ -110,7 +112,7 @@ run_oldtests() {
|
|||
}
|
||||
|
||||
install_nvim() {
|
||||
${MAKE_CMD} -C "${BUILD_DIR}" install
|
||||
build_make install
|
||||
|
||||
"${INSTALL_PREFIX}/bin/nvim" --version
|
||||
"${INSTALL_PREFIX}/bin/nvim" -u NONE -e -c ':help' -c ':qall' || {
|
|
@ -3,7 +3,7 @@
|
|||
set -e
|
||||
set -o pipefail
|
||||
|
||||
if [[ -n "${CI_TARGET}" ]]; then
|
||||
if [[ "${CI_TARGET}" == lint ]]; then
|
||||
exit
|
||||
fi
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
set -e
|
||||
set -o pipefail
|
||||
|
||||
CI_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
|
||||
source "${CI_DIR}/common/build.sh"
|
||||
source "${CI_DIR}/common/suite.sh"
|
||||
|
||||
enter_suite 'lint'
|
||||
|
||||
set -x
|
||||
|
||||
csi_clean() {
|
||||
find "${BUILD_DIR}/bin" -name 'test-includes-*' -delete
|
||||
find "${BUILD_DIR}" -name '*test-include*.o' -delete
|
||||
}
|
||||
|
||||
run_test 'top_make clint-full' clint
|
||||
run_test 'top_make testlint' testlint
|
||||
CLICOLOR_FORCE=1 run_test_wd \
|
||||
5s \
|
||||
'top_make check-single-includes' \
|
||||
'csi_clean' \
|
||||
single-includes
|
||||
|
||||
exit_suite
|
|
@ -6,6 +6,11 @@ set -o pipefail
|
|||
CI_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
source "${CI_DIR}/common/build.sh"
|
||||
source "${CI_DIR}/common/test.sh"
|
||||
source "${CI_DIR}/common/suite.sh"
|
||||
|
||||
set -x
|
||||
|
||||
enter_suite tests
|
||||
|
||||
check_core_dumps --delete quiet
|
||||
|
||||
|
@ -15,11 +20,15 @@ build_nvim
|
|||
if [ "$CLANG_SANITIZER" != "TSAN" ]; then
|
||||
# Additional threads are only created when the builtin UI starts, which
|
||||
# doesn't happen in the unit/functional tests
|
||||
run_unittests
|
||||
run_functionaltests
|
||||
run_test run_unittests
|
||||
run_test run_functionaltests
|
||||
fi
|
||||
run_oldtests
|
||||
run_test run_oldtests
|
||||
|
||||
install_nvim
|
||||
run_test install_nvim
|
||||
|
||||
touch "${SUCCESS_MARKER}"
|
||||
if succeeded ; then
|
||||
touch "${SUCCESS_MARKER}"
|
||||
fi
|
||||
|
||||
exit_suite
|
|
@ -3,16 +3,11 @@
|
|||
set -e
|
||||
set -o pipefail
|
||||
|
||||
if [[ -n "${CI_TARGET}" ]]; then
|
||||
make "${CI_TARGET}"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# This will pass the environment variables down to a bash process which runs
|
||||
# as $USER, while retaining the environment variables defined and belonging
|
||||
# to secondary groups given above in usermod.
|
||||
if [[ "${TRAVIS_OS_NAME}" == osx ]]; then
|
||||
sudo -E su "${USER}" -c ".ci/run_tests.sh"
|
||||
sudo -E su "${USER}" -c "ci/run_${CI_TARGET}.sh"
|
||||
else
|
||||
.ci/run_tests.sh
|
||||
ci/run_${CI_TARGET}.sh
|
||||
fi
|
|
@ -0,0 +1,18 @@
|
|||
file(
|
||||
DOWNLOAD "${URL}" "${FILE}"
|
||||
STATUS status
|
||||
LOG log
|
||||
)
|
||||
|
||||
list(GET status 0 status_code)
|
||||
list(GET status 1 status_string)
|
||||
|
||||
if(NOT status_code EQUAL 0)
|
||||
if(NOT ALLOW_FAILURE)
|
||||
message(FATAL_ERROR "error: downloading '${URL}' failed
|
||||
status_code: ${status_code}
|
||||
status_string: ${status_string}
|
||||
log: ${log}
|
||||
")
|
||||
endif()
|
||||
endif()
|
|
@ -1,32 +0,0 @@
|
|||
get_filename_component(LINT_DIR ${LINT_DIR} ABSOLUTE)
|
||||
get_filename_component(LINT_PREFIX ${LINT_DIR} PATH)
|
||||
set(LINT_SUPPRESS_FILE "${LINT_PREFIX}/errors.json")
|
||||
|
||||
if(DEFINED ENV{LINT_FILE})
|
||||
file(GLOB_RECURSE LINT_FILES "$ENV{LINT_FILE}")
|
||||
else()
|
||||
file(GLOB_RECURSE LINT_FILES ${LINT_DIR}/*.c ${LINT_DIR}/*.h)
|
||||
endif()
|
||||
|
||||
set(LINT_ARGS)
|
||||
|
||||
if(LINT_SUPPRESS_URL)
|
||||
file(DOWNLOAD ${LINT_SUPPRESS_URL} ${LINT_SUPPRESS_FILE})
|
||||
list(APPEND LINT_ARGS "--suppress-errors=${LINT_SUPPRESS_FILE}")
|
||||
endif()
|
||||
|
||||
foreach(lint_file ${LINT_FILES})
|
||||
file(RELATIVE_PATH lint_file "${LINT_PREFIX}" "${lint_file}")
|
||||
list(APPEND LINT_ARGS "${lint_file}")
|
||||
endforeach()
|
||||
|
||||
execute_process(
|
||||
COMMAND ${LINT_PRG} ${LINT_ARGS}
|
||||
RESULT_VARIABLE res
|
||||
WORKING_DIRECTORY "${LINT_PREFIX}")
|
||||
|
||||
file(REMOVE ${LINT_SUPPRESS_FILE})
|
||||
|
||||
if(NOT res EQUAL 0)
|
||||
message(FATAL_ERROR "Linting failed: ${res}.")
|
||||
endif()
|
|
@ -25,6 +25,8 @@ if(DEFINED ENV{TEST_FILTER})
|
|||
set(TEST_TAG "--filter=$ENV{TEST_FILTER}")
|
||||
endif()
|
||||
|
||||
execute_process(COMMAND ${CMAKE_COMMAND} -E make_directory ${WORKING_DIR}/Xtest-tmpdir)
|
||||
set(ENV{TMPDIR} ${WORKING_DIR}/Xtest-tmpdir)
|
||||
set(ENV{SYSTEM_NAME} ${SYSTEM_NAME})
|
||||
execute_process(
|
||||
COMMAND ${BUSTED_PRG} ${TEST_TAG} ${TEST_FILTER} -v -o ${BUSTED_OUTPUT_TYPE}
|
||||
|
@ -37,6 +39,7 @@ execute_process(
|
|||
|
||||
file(REMOVE ${WORKING_DIR}/Xtest_rplugin_manifest)
|
||||
file(REMOVE_RECURSE ${WORKING_DIR}/Xtest_xdg)
|
||||
file(REMOVE_RECURSE ${WORKING_DIR}/Xtest-tmpdir)
|
||||
|
||||
if(NOT res EQUAL 0)
|
||||
message(STATUS "Output to stderr:\n${err}")
|
||||
|
|
21
man/nvim.1
21
man/nvim.1
|
@ -371,27 +371,6 @@ See
|
|||
Used to set the 'shell' option, which determines the shell used by the
|
||||
.Ic :terminal
|
||||
command.
|
||||
.It Ev NVIM_TUI_ENABLE_CURSOR_SHAPE
|
||||
Set to 0 to prevent Nvim from changing the cursor shape.
|
||||
Set to 1 to enable non-blinking mode-sensitive cursor (this is the default).
|
||||
Set to 2 to enable blinking mode-sensitive cursor.
|
||||
Host terminal must support the DECSCUSR CSI escape sequence.
|
||||
.Pp
|
||||
Depending on the terminal emulator, using this option with
|
||||
.Nm
|
||||
under
|
||||
.Xr tmux 1
|
||||
might require adding the following to
|
||||
.Pa ~/.tmux.conf :
|
||||
.Bd -literal -offset indent
|
||||
set -ga terminal-overrides ',*:Ss=\eE[%p1%d q:Se=\eE[2 q'
|
||||
.Ed
|
||||
.Pp
|
||||
See
|
||||
.Ic terminal-overrides
|
||||
in the
|
||||
.Xr tmux 1
|
||||
manual page for more information.
|
||||
.El
|
||||
.Sh FILES
|
||||
.Bl -tag -width "~/.config/nvim/init.vim"
|
||||
|
|
|
@ -8,6 +8,11 @@ function! s:trim(s) abort
|
|||
return substitute(a:s, '^\_s*\|\_s*$', '', 'g')
|
||||
endfunction
|
||||
|
||||
" Convert '\' to '/'. Collapse '//' and '/./'.
|
||||
function! s:normalize_path(s) abort
|
||||
return substitute(substitute(a:s, '\', '/', 'g'), '/\./\|/\+', '/', 'g')
|
||||
endfunction
|
||||
|
||||
" Simple version comparison.
|
||||
function! s:version_cmp(a, b) abort
|
||||
let a = split(a:a, '\.', 0)
|
||||
|
@ -208,7 +213,7 @@ endfunction
|
|||
|
||||
" Check the Python interpreter's usability.
|
||||
function! s:check_bin(bin) abort
|
||||
if !filereadable(a:bin)
|
||||
if !filereadable(a:bin) && (!has('win32') || !filereadable(a:bin.'.exe'))
|
||||
call health#report_error(printf('"%s" was not found.', a:bin))
|
||||
return 0
|
||||
elseif executable(a:bin) != 1
|
||||
|
@ -287,8 +292,9 @@ function! s:check_python(version) abort
|
|||
|
||||
if exists('$PATH')
|
||||
for path in split($PATH, has('win32') ? ';' : ':')
|
||||
let path_bin = path.'/'.pyname
|
||||
if path_bin != python_bin && index(python_multiple, path_bin) == -1
|
||||
let path_bin = s:normalize_path(path.'/'.pyname)
|
||||
if path_bin != s:normalize_path(python_bin)
|
||||
\ && index(python_multiple, path_bin) == -1
|
||||
\ && executable(path_bin)
|
||||
call add(python_multiple, path_bin)
|
||||
endif
|
||||
|
|
|
@ -601,8 +601,8 @@ all files in it are deleted. When Vim has the setuid bit set this may cause
|
|||
problems, the temp file is owned by the setuid user but the filter command
|
||||
probably runs as the original user.
|
||||
Directory for temporary files is created in the first suitable directory of:
|
||||
For Unix: $TMPDIR, /tmp, current-dir, $HOME.
|
||||
For MS-Windows: $TMP, $TEMP, $USERPROFILE, current-dir.
|
||||
Unix: $TMPDIR, /tmp, current-dir, $HOME.
|
||||
Windows: $TMPDIR, $TMP, $TEMP, $USERPROFILE, current-dir.
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -44,6 +44,7 @@ Functions ~
|
|||
|
||||
Options ~
|
||||
*'fe'* 'fenc'+'enc' before Vim 6.0; no longer used.
|
||||
*'langnoremap'* Deprecated alias to 'nolangremap'.
|
||||
*'vi'*
|
||||
*'viminfo'* Deprecated alias to 'shada' option.
|
||||
|
||||
|
|
|
@ -3999,6 +3999,7 @@ getcompletion({pat}, {type} [, {filtered}]) *getcompletion()*
|
|||
augroup autocmd groups
|
||||
buffer buffer names
|
||||
behave :behave suboptions
|
||||
cmdline |cmdline-completion|
|
||||
color color schemes
|
||||
command Ex command (and arguments)
|
||||
compiler compilers
|
||||
|
@ -4027,7 +4028,7 @@ getcompletion({pat}, {type} [, {filtered}]) *getcompletion()*
|
|||
user user names
|
||||
var user variables
|
||||
|
||||
If {pat} is an empty string, then all the matches are returned.
|
||||
If {pat} is an empty string then all matches are returned.
|
||||
Otherwise only items matching {pat} are returned. See
|
||||
|wildcards| for the use of special characters in {pat}.
|
||||
|
||||
|
@ -7918,6 +7919,12 @@ writefile({list}, {fname} [, {flags}])
|
|||
appended to the file: >
|
||||
:call writefile(["foo"], "event.log", "a")
|
||||
:call writefile(["bar"], "event.log", "a")
|
||||
<
|
||||
When {flags} contains "S" fsync() call is not used, with "s"
|
||||
it is used, 'fsync' option applies by default. No fsync()
|
||||
means that writefile() will finish faster, but writes may be
|
||||
left in OS buffers and not yet written to disk. Such changes
|
||||
will disappear if system crashes before OS does writing.
|
||||
|
||||
All NL characters are replaced with a NUL character.
|
||||
Inserting CR characters needs to be done before passing {list}
|
||||
|
|
|
@ -83,28 +83,6 @@ Recommended place for your personal GUI initializations:
|
|||
The personal initialization files are searched in the order specified above
|
||||
and only the first one that is found is read.
|
||||
|
||||
There are a number of options which only have meaning in the GUI version of
|
||||
Vim. These are 'guicursor', 'guifont', and 'guioptions'. They are
|
||||
documented in |options.txt| with all the other options.
|
||||
|
||||
Another way to set the colors for different occasions is with highlight
|
||||
groups. The "Normal" group is used to set the background and foreground
|
||||
colors. Example (which looks nice): >
|
||||
|
||||
:highlight Normal guibg=grey90
|
||||
|
||||
The "guibg" and "guifg" settings override the normal background and
|
||||
foreground settings. The other settings for the Normal highlight group are
|
||||
not used. Use the 'guifont' option to set the font.
|
||||
|
||||
Also check out the 'guicursor' option, to set the colors for the cursor in
|
||||
various modes.
|
||||
|
||||
Vim tries to make the window fit on the screen when it starts up. This avoids
|
||||
that you can't see part of it. On the X Window System this requires a bit of
|
||||
guesswork. You can change the height that is used for the window title and a
|
||||
task bar with the 'guiheadroom' option.
|
||||
|
||||
*:winp* *:winpos* *E188*
|
||||
:winp[os]
|
||||
Display current position of the top left corner of the GUI vim
|
||||
|
@ -124,21 +102,6 @@ task bar with the 'guiheadroom' option.
|
|||
:win[size] {width} {height}
|
||||
Set the window height to {width} by {height} characters.
|
||||
Obsolete, use ":set lines=11 columns=22".
|
||||
If you get less lines than expected, check the 'guiheadroom'
|
||||
option.
|
||||
|
||||
If you are running the X Window System, you can get information about the
|
||||
window Vim is running in with these commands: >
|
||||
:!xwininfo -id $WINDOWID
|
||||
:!xprop -id $WINDOWID
|
||||
:execute '!xwininfo -id ' . v:windowid
|
||||
:execute '!xprop -id ' . v:windowid
|
||||
<
|
||||
*gui-IME* *iBus*
|
||||
Input methods for international characters in X that rely on the XIM
|
||||
framework, most notably iBus, have been known to produce undesirable results
|
||||
in gVim. These may include an inability to enter spaces, or long delays
|
||||
between typing a character and it being recognized by the application.
|
||||
|
||||
==============================================================================
|
||||
2. Scrollbars *gui-scrollbars*
|
||||
|
|
|
@ -181,11 +181,6 @@ vim.eval(str) *python-eval*
|
|||
# string.atoi() to convert to
|
||||
# a number.
|
||||
|
||||
:py tagList = vim.eval('taglist("eval_expr")')
|
||||
< The latter will return a python list of python dicts, for instance:
|
||||
[{'cmd': '/^eval_expr(arg, nextcmd)$/', 'static': 0, 'name':
|
||||
'eval_expr', 'kind': 'f', 'filename': './src/eval.c'}]
|
||||
|
||||
vim.bindeval(str) *python-bindeval*
|
||||
Like |python-eval|, but returns special objects described in
|
||||
|python-bindeval-objects|. These python objects let you modify (|List|
|
||||
|
|
|
@ -250,23 +250,21 @@ connect to another with different type codes.
|
|||
==============================================================================
|
||||
6. Remote UIs *rpc-remote-ui*
|
||||
|
||||
Nvim allows Graphical user interfaces to be implemented by separate processes
|
||||
communicating with Nvim over the RPC API. Currently the ui model conists of a
|
||||
terminal-like grid with one single, monospace font size, with a few elements
|
||||
that could be drawn separately from the grid (for the momemnt only the popup
|
||||
menu)
|
||||
GUIs can be implemented as external processes communicating with Nvim over the
|
||||
RPC API. Currently the UI model consists of a terminal-like grid with one
|
||||
single, monospace font size. Some elements (UI "widgets") can be drawn
|
||||
separately from the grid.
|
||||
|
||||
After connecting to a nvim instance (typically a spawned, embedded instance)
|
||||
use the |nvim_ui_attach|(width, height, options) API method to tell nvim that your
|
||||
program wants to draw the nvim screen on a grid with "width" times
|
||||
"height" cells. "options" should be a dictionary with the following (all
|
||||
optional) keys:
|
||||
`rgb`: Controls what color format to use.
|
||||
After connecting to Nvim (usually a spawned, embedded instance) use the
|
||||
|nvim_ui_attach| API method to tell Nvim that your program wants to draw the
|
||||
Nvim screen on a grid of width × height cells. `options` must be
|
||||
a dictionary with these (optional) keys:
|
||||
`rgb` Controls what color format to use.
|
||||
Set to true (default) to use 24-bit rgb
|
||||
colors.
|
||||
Set to false to use terminal color codes (at
|
||||
most 256 different colors).
|
||||
`popupmenu_external`: Instead of drawing the completion popupmenu on
|
||||
`popupmenu_external` Instead of drawing the completion popupmenu on
|
||||
the grid, Nvim will send higher-level events to
|
||||
the ui and let it draw the popupmenu.
|
||||
Defaults to false.
|
||||
|
|
|
@ -398,20 +398,6 @@ command, not when assigning a value to an option with ":let".
|
|||
Note the maximum length of an expanded option is limited. How much depends on
|
||||
the system, mostly it is something like 256 or 1024 characters.
|
||||
|
||||
*Linux-backspace*
|
||||
Note about Linux: By default the backspace key
|
||||
produces CTRL-?, which is wrong. You can fix it by
|
||||
putting this line in your rc.local: >
|
||||
echo "keycode 14 = BackSpace" | loadkeys
|
||||
<
|
||||
*NetBSD-backspace*
|
||||
Note about NetBSD: If your backspace doesn't produce
|
||||
the right code, try this: >
|
||||
xmodmap -e "keycode 22 = BackSpace"
|
||||
< If this works, add this in your .Xmodmap file: >
|
||||
keysym 22 = BackSpace
|
||||
< You need to restart for this to take effect.
|
||||
|
||||
==============================================================================
|
||||
2. Automatically setting options *auto-setting*
|
||||
|
||||
|
@ -2754,6 +2740,9 @@ A jump table for the options with a short description can be found at |Q_op|.
|
|||
mode, so it may be undesirable in some situations. Be warned that
|
||||
turning this off increases the chances of data loss after a crash.
|
||||
|
||||
Currently applies only to writing the buffer with e.g. |:w| and
|
||||
|writefile()|.
|
||||
|
||||
*'gdefault'* *'gd'* *'nogdefault'* *'nogd'*
|
||||
'gdefault' 'gd' boolean (default off)
|
||||
global
|
||||
|
@ -2804,21 +2793,17 @@ A jump table for the options with a short description can be found at |Q_op|.
|
|||
i-ci:ver25-Cursor/lCursor,
|
||||
r-cr:hor20-Cursor/lCursor,
|
||||
sm:block-Cursor
|
||||
-blinkwait175-blinkoff150-blinkon175",
|
||||
for Windows console:
|
||||
"n-v-c:block,o:hor50,i-ci:hor15,
|
||||
r-cr:hor30,sm:block")
|
||||
-blinkwait175-blinkoff150-blinkon175")
|
||||
global
|
||||
{only available when compiled with GUI enabled, and
|
||||
for Windows console}
|
||||
This option tells Vim what the cursor should look like in different
|
||||
modes. It fully works in the GUI. In a Windows console, only
|
||||
the height of the cursor can be changed. This can be done by
|
||||
specifying a block cursor, or a percentage for a vertical or
|
||||
horizontal cursor.
|
||||
For a console the 't_SI' and 't_EI' escape sequences are used.
|
||||
|
||||
The option is a comma separated list of parts. Each part consist of a
|
||||
Configures the cursor style for each mode. Works in the GUI and some
|
||||
terminals. Unset to disable: >
|
||||
:set guicursor=
|
||||
<
|
||||
With tmux you might need this in ~/.tmux.conf (see terminal-overrides
|
||||
in the tmux(1) manual page): >
|
||||
set -ga terminal-overrides ',*:Ss=\E[%p1%d q:Se=\E[2 q'
|
||||
<
|
||||
The option is a comma separated list of parts. Each part consists of a
|
||||
mode-list and an argument-list:
|
||||
mode-list:argument-list,mode-list:argument-list,..
|
||||
The mode-list is a dash separated list of these modes:
|
||||
|
@ -2991,18 +2976,6 @@ A jump table for the options with a short description can be found at |Q_op|.
|
|||
|
||||
If set and valid, 'guifontwide' is used for IME instead of 'guifont'.
|
||||
|
||||
*'guiheadroom'* *'ghr'*
|
||||
'guiheadroom' 'ghr' number (default 50)
|
||||
global
|
||||
{only for X11 GUI}
|
||||
The number of pixels subtracted from the screen height when fitting
|
||||
the GUI window on the screen. Set this before the GUI is started,
|
||||
e.g., in your |gvimrc| file. When zero, the whole screen height will
|
||||
be used by the window. When positive, the specified number of pixel
|
||||
lines will be left for window decorations and other items on the
|
||||
screen. Set it to a negative value to allow windows taller than the
|
||||
screen.
|
||||
|
||||
*'guioptions'* *'go'*
|
||||
'guioptions' 'go' string (default "egmrLT" (MS-Windows))
|
||||
global
|
||||
|
@ -3186,29 +3159,17 @@ A jump table for the options with a short description can be found at |Q_op|.
|
|||
Think twice when using ":q!" or ":qa!".
|
||||
|
||||
*'highlight'* *'hl'*
|
||||
'highlight' 'hl' string (default (as a single string):
|
||||
"8:SpecialKey,~:EndOfBuffer,z:TermCursor,
|
||||
Z:TermCursorNC,@:NonText,d:Directory,
|
||||
e:ErrorMsg,i:IncSearch,l:Search,
|
||||
m:MoreMsg,M:ModeMsg,n:LineNr,
|
||||
N:CursorLineNr,r:Question,s:StatusLine,
|
||||
S:StatusLineNC,c:VertSplit,t:Title,
|
||||
v:Visual,w:WarningMsg,W:WildMenu,
|
||||
f:Folded,F:FoldColumn,A:DiffAdd,
|
||||
C:DiffChange,D:DiffDelete,T:DiffText,
|
||||
>:SignColumn,B:SpellBad,P:SpellCap,
|
||||
R:SpellRare,L:SpellLocal,-:Conceal,
|
||||
+:Pmenu,=:PmenuSel,x:PmenuSbar,
|
||||
X:PmenuThumb")
|
||||
'highlight' 'hl' string (default: string of "c:group,..." pairs)
|
||||
global
|
||||
This option can be used to set highlighting mode for various
|
||||
occasions. It is a comma separated list of character pairs. The
|
||||
first character in a pair gives the occasion, the second the mode to
|
||||
use for that occasion. The occasions are:
|
||||
|hl-SpecialKey| 8 Meta and special keys listed with ":map"
|
||||
|hl-EndOfBuffer| ~ lines after the last line in the buffer
|
||||
|hl-Whitespace| 0
|
||||
|hl-EndOfBuffer| ~ lines after the last line in the buffer
|
||||
|hl-TermCursor| z Cursor in a focused terminal
|
||||
|hl-TermCursorNC| Z Cursor in an unfocused terminal
|
||||
|hl-TermCursorNC| Z Cursor in an unfocused terminal
|
||||
|hl-NonText| @ '@' at the end of the window and
|
||||
characters from 'showbreak'
|
||||
|hl-Directory| d directories in CTRL-D listing and other special
|
||||
|
@ -3220,11 +3181,11 @@ A jump table for the options with a short description can be found at |Q_op|.
|
|||
|hl-ModeMsg| M Mode (e.g., "-- INSERT --")
|
||||
|hl-LineNr| n line number for ":number" and ":#" commands, and
|
||||
when 'number' or 'relativenumber' option is set.
|
||||
|hl-CursorLineNr| N like n for when 'cursorline' or 'relativenumber' is
|
||||
|hl-CursorLineNr| N like n for when 'cursorline' or 'relativenumber' is
|
||||
set.
|
||||
|hl-Question| r |hit-enter| prompt and yes/no questions
|
||||
|hl-StatusLine| s status line of current window |status-line|
|
||||
|hl-StatusLineNC| S status lines of not-current windows
|
||||
|hl-StatusLineNC| S status lines of not-current windows
|
||||
|hl-Title| t Titles for output from ":set all", ":autocmd" etc.
|
||||
|hl-VertSplit| c column used to separate vertically split windows
|
||||
|hl-Visual| v Visual mode
|
||||
|
@ -3248,6 +3209,15 @@ A jump table for the options with a short description can be found at |Q_op|.
|
|||
|hl-PmenuSbar| x popup menu scrollbar
|
||||
|hl-PmenuThumb| X popup menu scrollbar thumb
|
||||
|
||||
|hl-TabLine| *
|
||||
|hl-TabLineFill| _
|
||||
|hl-TabLineSel| #
|
||||
|
||||
|hl-ColorColumn| o
|
||||
|hl-CursorColumn| !
|
||||
|hl-CursorLine| .
|
||||
|hl-QuickFixLine| q
|
||||
|
||||
The display modes are:
|
||||
r reverse (termcap entry "mr" and "me")
|
||||
i italic (termcap entry "ZH" and "ZR")
|
||||
|
@ -3776,12 +3746,12 @@ A jump table for the options with a short description can be found at |Q_op|.
|
|||
:source $VIMRUNTIME/menu.vim
|
||||
< Warning: This deletes all menus that you defined yourself!
|
||||
|
||||
*'langnoremap'* *'lnr'*
|
||||
'langnoremap' 'lnr' boolean (default on)
|
||||
*'langremap'* *'lrm'* *'nolangremap'* *'nolrm'*
|
||||
'langremap' 'lrm' boolean (default off)
|
||||
global
|
||||
When on, setting 'langmap' does not apply to characters resulting from
|
||||
When off, setting 'langmap' does not apply to characters resulting from
|
||||
a mapping. If setting 'langmap' disables some of your mappings, make
|
||||
sure this option is set.
|
||||
sure this option is off.
|
||||
|
||||
*'laststatus'* *'ls'*
|
||||
'laststatus' 'ls' number (default 2)
|
||||
|
@ -3830,9 +3800,6 @@ A jump table for the options with a short description can be found at |Q_op|.
|
|||
use this command to get the tallest window possible: >
|
||||
:set lines=999
|
||||
< Minimum value is 2, maximum value is 1000.
|
||||
If you get less lines than expected, check the 'guiheadroom' option.
|
||||
When you set this option and Vim is unable to change the physical
|
||||
number of lines of the display, the display may be messed up.
|
||||
|
||||
*'linespace'* *'lsp'*
|
||||
'linespace' 'lsp' number (default 0, 1 for Win32 GUI)
|
||||
|
@ -3932,9 +3899,8 @@ A jump table for the options with a short description can be found at |Q_op|.
|
|||
:set lcs=tab:>-,trail:-
|
||||
:set lcs=tab:>-,eol:<,nbsp:%
|
||||
:set lcs=extends:>,precedes:<
|
||||
< The "NonText" highlighting will be used for "eol", "extends" and
|
||||
"precedes". "SpecialKey" for "nbsp", "space", "tab" and "trail".
|
||||
|hl-NonText| |hl-SpecialKey|
|
||||
< |hl-NonText| highlighting will be used for "eol", "extends" and
|
||||
"precedes". |hl-Whitespace| for "nbsp", "space", "tab" and "trail".
|
||||
|
||||
*'lpl'* *'nolpl'* *'loadplugins'* *'noloadplugins'*
|
||||
'loadplugins' 'lpl' boolean (default on)
|
||||
|
|
|
@ -715,7 +715,6 @@ Short explanation of each option: *option-list*
|
|||
'guifont' 'gfn' GUI: Name(s) of font(s) to be used
|
||||
'guifontset' 'gfs' GUI: Names of multi-byte fonts to be used
|
||||
'guifontwide' 'gfw' list of font names for double-wide characters
|
||||
'guiheadroom' 'ghr' GUI: pixels room for window decorations
|
||||
'guioptions' 'go' GUI: Which components and options are used
|
||||
'guitablabel' 'gtl' GUI: custom label for a tab page
|
||||
'guitabtooltip' 'gtt' GUI: custom tooltip for a tab page
|
||||
|
|
|
@ -4899,32 +4899,28 @@ PmenuThumb Popup menu: Thumb of the scrollbar.
|
|||
*hl-Question*
|
||||
Question |hit-enter| prompt and yes/no questions
|
||||
*hl-QuickFixLine*
|
||||
QuickFixLine The selected |quickfix| item in the quickfix window.
|
||||
|hl-CursorLine| is combined with this when the cursor is on
|
||||
the currently selected quickfix item.
|
||||
QuickFixLine Current |quickfix| item in the quickfix window. Combined with
|
||||
|hl-CursorLine| when the cursor is there.
|
||||
*hl-Search*
|
||||
Search Last search pattern highlighting (see 'hlsearch').
|
||||
Also used for highlighting the current line in the quickfix
|
||||
window and similar items that need to stand out.
|
||||
Also used for similar items that need to stand out.
|
||||
*hl-SpecialKey*
|
||||
SpecialKey Meta and special keys listed with ":map", also for text used
|
||||
to show unprintable characters in the text, 'listchars'.
|
||||
Generally: text that is displayed differently from what it
|
||||
really is.
|
||||
SpecialKey Unprintable characters: text displayed differently from what
|
||||
it really is. But not 'listchars' whitespace. |hl-Whitespace|
|
||||
*hl-SpellBad*
|
||||
SpellBad Word that is not recognized by the spellchecker. |spell|
|
||||
This will be combined with the highlighting used otherwise.
|
||||
Combined with the highlighting used otherwise.
|
||||
*hl-SpellCap*
|
||||
SpellCap Word that should start with a capital. |spell|
|
||||
This will be combined with the highlighting used otherwise.
|
||||
Combined with the highlighting used otherwise.
|
||||
*hl-SpellLocal*
|
||||
SpellLocal Word that is recognized by the spellchecker as one that is
|
||||
used in another region. |spell|
|
||||
This will be combined with the highlighting used otherwise.
|
||||
Combined with the highlighting used otherwise.
|
||||
*hl-SpellRare*
|
||||
SpellRare Word that is recognized by the spellchecker as one that is
|
||||
hardly ever used. |spell|
|
||||
This will be combined with the highlighting used otherwise.
|
||||
Combined with the highlighting used otherwise.
|
||||
*hl-StatusLine*
|
||||
StatusLine status line of current window
|
||||
*hl-StatusLineNC*
|
||||
|
@ -4943,6 +4939,8 @@ Title titles for output from ":set all", ":autocmd" etc.
|
|||
Visual Visual mode selection
|
||||
*hl-WarningMsg*
|
||||
WarningMsg warning messages
|
||||
*hl-Whitespace*
|
||||
Whitespace "nbsp", "space", "tab" and "trail" in 'listchars'
|
||||
*hl-WildMenu*
|
||||
WildMenu current match in 'wildmenu' completion
|
||||
|
||||
|
|
|
@ -45,7 +45,8 @@ these differences.
|
|||
- 'history' defaults to 10000 (the maximum)
|
||||
- 'hlsearch' is set by default
|
||||
- 'incsearch' is set by default
|
||||
- 'langnoremap' is set by default
|
||||
- 'langnoremap' is enabled by default
|
||||
- 'langremap' is disabled by default
|
||||
- 'laststatus' defaults to 2 (statusline is always shown)
|
||||
- 'listchars' defaults to "tab:> ,trail:-,nbsp:+"
|
||||
- 'nocompatible' is always set
|
||||
|
@ -112,6 +113,7 @@ Some `CTRL-SHIFT-...` key chords are distinguished from `CTRL-...` variants
|
|||
|
||||
Options:
|
||||
'cpoptions' flags: |cpo-_|
|
||||
'guicursor' works in the terminal
|
||||
'inccommand' shows interactive results for |:substitute|-like commands
|
||||
'statusline' supports unlimited alignment sections
|
||||
'tabline' %@Func@foo%X can call any function on mouse-click
|
||||
|
@ -145,6 +147,7 @@ Highlight groups:
|
|||
|hl-Substitute|
|
||||
|hl-TermCursor|
|
||||
|hl-TermCursorNC|
|
||||
|hl-Whitespace| highlights 'listchars' whitespace
|
||||
|
||||
==============================================================================
|
||||
4. Changed features *nvim-features-changed*
|
||||
|
|
|
@ -589,8 +589,6 @@ if has("gui")
|
|||
call append("$", "toolbariconsize\tsize of toolbar icons")
|
||||
call <SID>OptionG("tbis", &tbis)
|
||||
endif
|
||||
call append("$", "guiheadroom\troom (in pixels) left above/below the window")
|
||||
call append("$", " \tset ghr=" . &ghr)
|
||||
endif
|
||||
if has("browse")
|
||||
call append("$", "browsedir\t\"last\", \"buffer\" or \"current\": which directory used for the file browser")
|
||||
|
|
|
@ -17,9 +17,11 @@ function! s:GetManifestPath() abort
|
|||
endif
|
||||
|
||||
let dest = fnamemodify(expand(dest), ':p')
|
||||
if !empty(dest) && !filereadable(dest)
|
||||
if !empty(dest)
|
||||
let dest .= ('/' ==# dest[-1:] ? '' : '/') . 'nvim'
|
||||
call mkdir(dest, 'p', 0700)
|
||||
if !isdirectory(dest)
|
||||
call mkdir(dest, 'p', 0700)
|
||||
endif
|
||||
let manifest_base = dest
|
||||
endif
|
||||
|
||||
|
|
|
@ -0,0 +1,66 @@
|
|||
#!/usr/bin/env python
|
||||
|
||||
import sys
|
||||
import re
|
||||
import os
|
||||
|
||||
from subprocess import Popen, PIPE
|
||||
from argparse import ArgumentParser
|
||||
|
||||
|
||||
GENERATED_INCLUDE_RE = re.compile(
|
||||
r'^\s*#\s*include\s*"([/a-z_0-9.]+\.generated\.h)"(\s+//.*)?$')
|
||||
|
||||
|
||||
def main(argv):
|
||||
argparser = ArgumentParser()
|
||||
argparser.add_argument('--generated-includes-dir', action='append',
|
||||
help='Directory where generated includes are located.')
|
||||
argparser.add_argument('--file', type=open, help='File to check.')
|
||||
argparser.add_argument('iwyu_args', nargs='*',
|
||||
help='IWYU arguments, must go after --.')
|
||||
args = argparser.parse_args(argv)
|
||||
|
||||
with args.file:
|
||||
include_dirs = []
|
||||
|
||||
iwyu = Popen(['include-what-you-use', '-xc'] + args.iwyu_args + ['/dev/stdin'],
|
||||
stdin=PIPE, stdout=PIPE, stderr=PIPE)
|
||||
|
||||
for line in args.file:
|
||||
match = GENERATED_INCLUDE_RE.match(line)
|
||||
if match:
|
||||
for d in args.generated_includes_dir:
|
||||
try:
|
||||
f = open(os.path.join(d, match.group(1)))
|
||||
except IOError:
|
||||
continue
|
||||
else:
|
||||
with f:
|
||||
for generated_line in f:
|
||||
iwyu.stdin.write(generated_line)
|
||||
break
|
||||
else:
|
||||
raise IOError('Failed to find {0}'.format(match.group(1)))
|
||||
else:
|
||||
iwyu.stdin.write(line)
|
||||
|
||||
iwyu.stdin.close()
|
||||
|
||||
out = iwyu.stdout.read()
|
||||
err = iwyu.stderr.read()
|
||||
|
||||
ret = iwyu.wait()
|
||||
|
||||
if ret != 2:
|
||||
print('IWYU failed with exit code {0}:'.format(ret))
|
||||
print('{0} stdout {0}'.format('=' * ((80 - len(' stdout ')) // 2)))
|
||||
print(out)
|
||||
print('{0} stderr {0}'.format('=' * ((80 - len(' stderr ')) // 2)))
|
||||
print(err)
|
||||
return 1
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
raise SystemExit(main(sys.argv[1:]))
|
|
@ -321,7 +321,7 @@ list_vim_patches() {
|
|||
if [[ -n "${vim_tag}" ]]; then
|
||||
local patch_number="${vim_tag:5}" # Remove prefix like "v7.4."
|
||||
# Tagged Vim patch, check version.c:
|
||||
is_missing="$(sed -n '/static int included_patches/,/}/p' "${NVIM_SOURCE_DIR}/src/nvim/version.c" |
|
||||
is_missing="$(sed -n '/static const int included_patches/,/}/p' "${NVIM_SOURCE_DIR}/src/nvim/version.c" |
|
||||
grep -x -e "[[:space:]]*//[[:space:]]${patch_number} NA.*" -e "[[:space:]]*${patch_number}," >/dev/null && echo "false" || echo "true")"
|
||||
vim_commit="${vim_tag#v}"
|
||||
if (cd "${VIM_SOURCE_DIR}" && git --no-pager show --color=never --name-only "v${vim_commit}" 2>/dev/null) | grep -q ^runtime; then
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
# multiqueue.h pointer arithmetic is not accepted by asan
|
||||
fun:multiqueue_node_data
|
||||
fun:dictwatcher_node_data
|
||||
fun:tv_dict_watcher_node_data
|
||||
|
|
10
src/clint.py
10
src/clint.py
|
@ -572,7 +572,8 @@ class _CppLintState(object):
|
|||
for category, count in self.errors_by_category.items():
|
||||
sys.stderr.write('Category \'%s\' errors found: %d\n' %
|
||||
(category, count))
|
||||
sys.stderr.write('Total errors found: %d\n' % self.error_count)
|
||||
if self.error_count:
|
||||
sys.stderr.write('Total errors found: %d\n' % self.error_count)
|
||||
|
||||
def SuppressErrorsFrom(self, fname):
|
||||
"""Open file and read a list of suppressed errors from it"""
|
||||
|
@ -2273,11 +2274,14 @@ def CheckSpacing(filename, clean_lines, linenum, nesting_state, error):
|
|||
# //!< Header comment
|
||||
# or they begin with multiple slashes followed by a space:
|
||||
# //////// Header comment
|
||||
# or they are Vim {{{ fold markers
|
||||
match = (Search(r'[=/-]{4,}\s*$', line[commentend:]) or
|
||||
Search(r'^/$', line[commentend:]) or
|
||||
Search(r'^!< ', line[commentend:]) or
|
||||
Search(r'^/< ', line[commentend:]) or
|
||||
Search(r'^/+ ', line[commentend:]))
|
||||
Search(r'^/+ ', line[commentend:]) or
|
||||
Search(r'^(?:\{{3}|\}{3})\d*(?: |$)',
|
||||
line[commentend:]))
|
||||
if not match:
|
||||
error(filename, linenum, 'whitespace/comments', 4,
|
||||
'Should have a space between // and comment')
|
||||
|
@ -3580,7 +3584,7 @@ def main():
|
|||
if __name__ == '__main__':
|
||||
main()
|
||||
|
||||
# vim: ts=4 sts=4 sw=4
|
||||
# vim: ts=4 sts=4 sw=4 foldmarker=▶,▲
|
||||
|
||||
# Ignore "too complex" warnings when using pymode.
|
||||
# pylama:ignore=C901
|
||||
|
|
|
@ -64,7 +64,7 @@ void *je_realloc(void *ptr, size_t size)
|
|||
// of the memory allocated for item.
|
||||
typedef struct {} dictitem_T;
|
||||
typedef struct {} dict_T;
|
||||
int dict_add(dict_T *d, dictitem_T *item)
|
||||
int tv_dict_add(dict_T *const d, dictitem_T *const item)
|
||||
{
|
||||
__coverity_escape__(item);
|
||||
}
|
||||
|
|
|
@ -10,6 +10,7 @@ if(USE_GCOV)
|
|||
endif()
|
||||
endif()
|
||||
|
||||
set(TOUCHES_DIR ${PROJECT_BINARY_DIR}/touches)
|
||||
set(GENERATED_DIR ${PROJECT_BINARY_DIR}/src/nvim/auto)
|
||||
set(MSGPACK_GENERATOR ${PROJECT_SOURCE_DIR}/scripts/genmsgpack.lua)
|
||||
set(API_METADATA ${PROJECT_BINARY_DIR}/api_metadata.mpack)
|
||||
|
@ -21,7 +22,6 @@ set(GENERATED_API_DISPATCH ${GENERATED_DIR}/api/private/dispatch_wrappers.genera
|
|||
set(GENERATED_FUNCS_METADATA ${GENERATED_DIR}/api/private/funcs_metadata.generated.h)
|
||||
set(GENERATED_EX_CMDS_ENUM ${GENERATED_INCLUDES_DIR}/ex_cmds_enum.generated.h)
|
||||
set(GENERATED_EX_CMDS_DEFS ${GENERATED_DIR}/ex_cmds_defs.generated.h)
|
||||
set(GENERATED_FUNCS_HASH_INPUT ${GENERATED_DIR}/funcs.generated.h.gperf)
|
||||
set(GENERATED_FUNCS ${GENERATED_DIR}/funcs.generated.h)
|
||||
set(GENERATED_EVENTS_ENUM ${GENERATED_INCLUDES_DIR}/auevents_enum.generated.h)
|
||||
set(GENERATED_EVENTS_NAMES_MAP ${GENERATED_DIR}/auevents_name_map.generated.h)
|
||||
|
@ -30,29 +30,34 @@ set(EX_CMDS_GENERATOR ${PROJECT_SOURCE_DIR}/scripts/genex_cmds.lua)
|
|||
set(FUNCS_GENERATOR ${PROJECT_SOURCE_DIR}/scripts/geneval.lua)
|
||||
set(EVENTS_GENERATOR ${PROJECT_SOURCE_DIR}/scripts/gen_events.lua)
|
||||
set(OPTIONS_GENERATOR ${PROJECT_SOURCE_DIR}/scripts/genoptions.lua)
|
||||
set(EVENTS_LIST_FILE ${PROJECT_SOURCE_DIR}/src/nvim/auevents.lua)
|
||||
set(EX_CMDS_DEFS_FILE ${PROJECT_SOURCE_DIR}/src/nvim/ex_cmds.lua)
|
||||
set(EVAL_DEFS_FILE ${PROJECT_SOURCE_DIR}/src/nvim/eval.lua)
|
||||
set(OPTIONS_LIST_FILE ${PROJECT_SOURCE_DIR}/src/nvim/options.lua)
|
||||
set(UNICODE_TABLES_GENERATOR ${PROJECT_SOURCE_DIR}/scripts/genunicodetables.lua)
|
||||
set(UNICODE_DIR ${PROJECT_SOURCE_DIR}/unicode)
|
||||
set(GENERATED_UNICODE_TABLES ${GENERATED_DIR}/unicode_tables.generated.h)
|
||||
set(VIM_MODULE_FILE ${GENERATED_DIR}/viml/executor/vim_module.generated.h)
|
||||
set(VIM_MODULE_SOURCE ${PROJECT_SOURCE_DIR}/src/nvim/viml/executor/vim.lua)
|
||||
set(CHAR_BLOB_GENERATOR ${PROJECT_SOURCE_DIR}/scripts/gencharblob.lua)
|
||||
set(LINT_SUPPRESS_FILE ${PROJECT_BINARY_DIR}/errors.json)
|
||||
set(LINT_SUPPRESS_URL_BASE "https://raw.githubusercontent.com/neovim/doc/gh-pages/reports/clint")
|
||||
set(LINT_SUPPRESS_URL "${LINT_SUPPRESS_URL_BASE}/errors.json")
|
||||
set(LINT_PRG ${PROJECT_SOURCE_DIR}/src/clint.py)
|
||||
set(DOWNLOAD_SCRIPT ${PROJECT_SOURCE_DIR}/cmake/Download.cmake)
|
||||
set(LINT_SUPPRESSES_ROOT ${PROJECT_BINARY_DIR}/errors)
|
||||
set(LINT_SUPPRESSES_URL "https://raw.githubusercontent.com/neovim/doc/gh-pages/reports/clint/errors.tar.gz")
|
||||
|
||||
file(GLOB UNICODE_FILES ${UNICODE_DIR}/*.txt)
|
||||
file(GLOB API_HEADERS api/*.h)
|
||||
file(GLOB MSGPACK_RPC_HEADERS msgpack_rpc/*.h)
|
||||
file(GLOB UNICODE_FILES ${UNICODE_DIR}/*.txt)
|
||||
|
||||
include_directories(${GENERATED_DIR})
|
||||
include_directories(${CACHED_GENERATED_DIR})
|
||||
include_directories(${GENERATED_INCLUDES_DIR})
|
||||
|
||||
file(MAKE_DIRECTORY ${TOUCHES_DIR})
|
||||
file(MAKE_DIRECTORY ${GENERATED_DIR})
|
||||
file(MAKE_DIRECTORY ${GENERATED_INCLUDES_DIR})
|
||||
|
||||
file(GLOB NEOVIM_SOURCES *.c)
|
||||
file(GLOB NVIM_SOURCES *.c)
|
||||
file(GLOB NVIM_HEADERS *.h)
|
||||
|
||||
foreach(subdir
|
||||
os
|
||||
|
@ -72,18 +77,21 @@ foreach(subdir
|
|||
file(MAKE_DIRECTORY ${GENERATED_DIR}/${subdir})
|
||||
file(MAKE_DIRECTORY ${GENERATED_INCLUDES_DIR}/${subdir})
|
||||
file(GLOB sources ${subdir}/*.c)
|
||||
list(APPEND NEOVIM_SOURCES ${sources})
|
||||
file(GLOB headers ${subdir}/*.h)
|
||||
list(APPEND NVIM_SOURCES ${sources})
|
||||
list(APPEND NVIM_HEADERS ${headers})
|
||||
endforeach()
|
||||
|
||||
file(GLOB_RECURSE NEOVIM_HEADERS *.h)
|
||||
file(GLOB UNIT_TEST_FIXTURES ${PROJECT_SOURCE_DIR}/test/unit/fixtures/*.c)
|
||||
|
||||
# Sort file lists to ensure generated files are created in the same order from
|
||||
# build to build.
|
||||
list(SORT NEOVIM_SOURCES)
|
||||
list(SORT NEOVIM_HEADERS)
|
||||
list(SORT NVIM_SOURCES)
|
||||
list(SORT NVIM_HEADERS)
|
||||
|
||||
foreach(sfile ${NEOVIM_SOURCES})
|
||||
list(APPEND LINT_NVIM_SOURCES ${NVIM_SOURCES} ${NVIM_HEADERS})
|
||||
|
||||
foreach(sfile ${NVIM_SOURCES})
|
||||
get_filename_component(f ${sfile} NAME)
|
||||
if(${f} MATCHES "^(regexp_nfa.c)$")
|
||||
list(APPEND to_remove ${sfile})
|
||||
|
@ -93,7 +101,7 @@ foreach(sfile ${NEOVIM_SOURCES})
|
|||
endif()
|
||||
endforeach()
|
||||
|
||||
list(REMOVE_ITEM NEOVIM_SOURCES ${to_remove})
|
||||
list(REMOVE_ITEM NVIM_SOURCES ${to_remove})
|
||||
|
||||
# Legacy files that do not yet pass -Wconversion.
|
||||
set(CONV_SOURCES
|
||||
|
@ -117,7 +125,7 @@ set(CONV_SOURCES
|
|||
window.c)
|
||||
|
||||
foreach(sfile ${CONV_SOURCES})
|
||||
if(NOT EXISTS "${PROJECT_SOURCE_DIR}/src/nvim/${sfile}")
|
||||
if(NOT EXISTS "${CMAKE_CURRENT_LIST_DIR}/${sfile}")
|
||||
message(FATAL_ERROR "${sfile} doesn't exist (it was added to CONV_SOURCES)")
|
||||
endif()
|
||||
endforeach()
|
||||
|
@ -159,12 +167,24 @@ separate_arguments(C_FLAGS_ARRAY UNIX_COMMAND ${CMAKE_C_FLAGS})
|
|||
separate_arguments(C_FLAGS_${build_type}_ARRAY UNIX_COMMAND ${CMAKE_C_FLAGS_${build_type}})
|
||||
set(gen_cflags ${gen_cflags} ${C_FLAGS_${build_type}_ARRAY} ${C_FLAGS_ARRAY})
|
||||
|
||||
foreach(sfile ${NEOVIM_SOURCES}
|
||||
"${PROJECT_SOURCE_DIR}/src/nvim/regexp_nfa.c"
|
||||
function(get_preproc_output varname iname)
|
||||
if(MSVC)
|
||||
set(${varname} /P /Fi${iname} PARENT_SCOPE)
|
||||
else()
|
||||
set(${varname} -E -o ${iname} PARENT_SCOPE)
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
# NVIM_GENERATED_FOR_HEADERS: generated headers to be included in headers
|
||||
# NVIM_GENERATED_FOR_SOURCES: generated headers to be included in sources
|
||||
# NVIM_GENERATED_SOURCES: generated source files
|
||||
# These lists must be mutually exclusive.
|
||||
foreach(sfile ${NVIM_SOURCES}
|
||||
"${CMAKE_CURRENT_LIST_DIR}/regexp_nfa.c"
|
||||
${GENERATED_API_DISPATCH})
|
||||
get_filename_component(full_d ${sfile} PATH)
|
||||
file(RELATIVE_PATH d "${PROJECT_SOURCE_DIR}/src/nvim" "${full_d}")
|
||||
if(${d} MATCHES "^([.][.]|auto/)")
|
||||
file(RELATIVE_PATH d "${CMAKE_CURRENT_LIST_DIR}" "${full_d}")
|
||||
if(${d} MATCHES "^[.][.]|auto/")
|
||||
file(RELATIVE_PATH d "${GENERATED_DIR}" "${full_d}")
|
||||
endif()
|
||||
get_filename_component(f ${sfile} NAME)
|
||||
|
@ -173,26 +193,22 @@ foreach(sfile ${NEOVIM_SOURCES}
|
|||
set(f "${d}/${f}")
|
||||
set(r "${d}/${r}")
|
||||
endif()
|
||||
set(gf1 "${GENERATED_DIR}/${r}.c.generated.h")
|
||||
set(gf2 "${GENERATED_INCLUDES_DIR}/${r}.h.generated.h")
|
||||
set(gf3 "${GENERATED_DIR}/${r}.i")
|
||||
set(gf_c_h "${GENERATED_DIR}/${r}.c.generated.h")
|
||||
set(gf_h_h "${GENERATED_INCLUDES_DIR}/${r}.h.generated.h")
|
||||
set(gf_i "${GENERATED_DIR}/${r}.i")
|
||||
|
||||
if(MSVC)
|
||||
set(PREPROC_OUTPUT /P /Fi${gf3})
|
||||
else()
|
||||
set(PREPROC_OUTPUT -E -o ${gf3})
|
||||
endif()
|
||||
get_preproc_output(PREPROC_OUTPUT ${gf_i})
|
||||
|
||||
add_custom_command(
|
||||
OUTPUT "${gf1}" "${gf2}"
|
||||
OUTPUT "${gf_c_h}" "${gf_h_h}"
|
||||
COMMAND ${CMAKE_C_COMPILER} ${sfile} ${PREPROC_OUTPUT} ${gen_cflags} ${C_FLAGS_ARRAY}
|
||||
COMMAND "${LUA_PRG}" "${HEADER_GENERATOR}" "${sfile}" "${gf1}" "${gf2}" "${gf3}"
|
||||
COMMAND "${LUA_PRG}" "${HEADER_GENERATOR}" "${sfile}" "${gf_c_h}" "${gf_h_h}" "${gf_i}"
|
||||
DEPENDS "${HEADER_GENERATOR}" "${sfile}"
|
||||
)
|
||||
list(APPEND NEOVIM_GENERATED_SOURCES "${gf1}")
|
||||
list(APPEND NEOVIM_GENERATED_SOURCES "${gf2}")
|
||||
list(APPEND NVIM_GENERATED_FOR_SOURCES "${gf_c_h}")
|
||||
list(APPEND NVIM_GENERATED_FOR_HEADERS "${gf_h_h}")
|
||||
if(${d} MATCHES "^api$" AND NOT ${f} MATCHES "^api/helpers.c$")
|
||||
list(APPEND API_HEADERS ${gf2})
|
||||
list(APPEND API_HEADERS ${gf_h_h})
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
|
@ -229,23 +245,32 @@ add_custom_command(
|
|||
${VIM_MODULE_SOURCE}
|
||||
)
|
||||
|
||||
list(APPEND NEOVIM_GENERATED_SOURCES
|
||||
"${PROJECT_BINARY_DIR}/config/auto/pathdef.c"
|
||||
"${GENERATED_API_DISPATCH}"
|
||||
list(APPEND NVIM_GENERATED_SOURCES
|
||||
"${MSGPACK_LUA_C_BINDINGS}"
|
||||
)
|
||||
|
||||
list(APPEND NVIM_GENERATED_FOR_HEADERS
|
||||
"${GENERATED_EX_CMDS_ENUM}"
|
||||
"${GENERATED_EX_CMDS_DEFS}"
|
||||
"${GENERATED_EVENTS_ENUM}"
|
||||
)
|
||||
|
||||
list(APPEND NVIM_GENERATED_FOR_SOURCES
|
||||
"${GENERATED_API_DISPATCH}"
|
||||
"${GENERATED_EX_CMDS_DEFS}"
|
||||
"${GENERATED_EVENTS_NAMES_MAP}"
|
||||
"${GENERATED_OPTIONS}"
|
||||
"${GENERATED_UNICODE_TABLES}"
|
||||
"${MSGPACK_LUA_C_BINDINGS}"
|
||||
"${VIM_MODULE_FILE}"
|
||||
)
|
||||
|
||||
list(APPEND NVIM_GENERATED_SOURCES
|
||||
"${PROJECT_BINARY_DIR}/config/auto/pathdef.c"
|
||||
)
|
||||
|
||||
add_custom_command(OUTPUT ${GENERATED_EX_CMDS_ENUM} ${GENERATED_EX_CMDS_DEFS}
|
||||
COMMAND ${LUA_PRG} ${EX_CMDS_GENERATOR}
|
||||
${PROJECT_SOURCE_DIR}/src/nvim ${GENERATED_INCLUDES_DIR} ${GENERATED_DIR}
|
||||
DEPENDS ${EX_CMDS_GENERATOR} ${EX_CMDS_DEFS_FILE}
|
||||
${CMAKE_CURRENT_LIST_DIR} ${GENERATED_INCLUDES_DIR} ${GENERATED_DIR}
|
||||
DEPENDS ${EX_CMDS_GENERATOR} ${CMAKE_CURRENT_LIST_DIR}/ex_cmds.lua
|
||||
)
|
||||
|
||||
if(NOT GPERF_PRG)
|
||||
|
@ -253,26 +278,34 @@ if(NOT GPERF_PRG)
|
|||
endif()
|
||||
add_custom_command(OUTPUT ${GENERATED_FUNCS} ${FUNCS_DATA}
|
||||
COMMAND ${LUA_PRG} ${FUNCS_GENERATOR}
|
||||
${PROJECT_SOURCE_DIR}/src/nvim ${GENERATED_DIR} ${API_METADATA} ${FUNCS_DATA}
|
||||
${CMAKE_CURRENT_LIST_DIR} ${GENERATED_DIR} ${API_METADATA} ${FUNCS_DATA}
|
||||
COMMAND ${GPERF_PRG}
|
||||
${GENERATED_FUNCS_HASH_INPUT} --output-file=${GENERATED_FUNCS}
|
||||
DEPENDS ${FUNCS_GENERATOR} ${EVAL_DEFS_FILE} ${API_METADATA}
|
||||
${GENERATED_DIR}/funcs.generated.h.gperf --output-file=${GENERATED_FUNCS}
|
||||
DEPENDS ${FUNCS_GENERATOR} ${CMAKE_CURRENT_LIST_DIR}/eval.lua ${API_METADATA}
|
||||
)
|
||||
list(APPEND NEOVIM_GENERATED_SOURCES
|
||||
list(APPEND NVIM_GENERATED_FOR_SOURCES
|
||||
"${GENERATED_FUNCS}")
|
||||
|
||||
add_custom_command(OUTPUT ${GENERATED_EVENTS_ENUM} ${GENERATED_EVENTS_NAMES_MAP}
|
||||
COMMAND ${LUA_PRG} ${EVENTS_GENERATOR}
|
||||
${PROJECT_SOURCE_DIR}/src/nvim ${GENERATED_EVENTS_ENUM} ${GENERATED_EVENTS_NAMES_MAP}
|
||||
DEPENDS ${EVENTS_GENERATOR} ${EVENTS_LIST_FILE}
|
||||
${CMAKE_CURRENT_LIST_DIR} ${GENERATED_EVENTS_ENUM} ${GENERATED_EVENTS_NAMES_MAP}
|
||||
DEPENDS ${EVENTS_GENERATOR} ${CMAKE_CURRENT_LIST_DIR}/auevents.lua
|
||||
)
|
||||
|
||||
add_custom_command(OUTPUT ${GENERATED_OPTIONS}
|
||||
COMMAND ${LUA_PRG} ${OPTIONS_GENERATOR}
|
||||
${PROJECT_SOURCE_DIR}/src/nvim ${GENERATED_OPTIONS}
|
||||
DEPENDS ${OPTIONS_GENERATOR} ${OPTIONS_LIST_FILE}
|
||||
${CMAKE_CURRENT_LIST_DIR} ${GENERATED_OPTIONS}
|
||||
DEPENDS ${OPTIONS_GENERATOR} ${CMAKE_CURRENT_LIST_DIR}/options.lua
|
||||
)
|
||||
|
||||
# NVIM_GENERATED_FOR_SOURCES and NVIM_GENERATED_FOR_HEADERS must be mutually exclusive.
|
||||
foreach(hfile ${NVIM_GENERATED_FOR_HEADERS})
|
||||
list(FIND NVIM_GENERATED_FOR_SOURCES ${hfile} hfile_idx)
|
||||
if(NOT ${hfile_idx} EQUAL -1)
|
||||
message(FATAL_ERROR "File included in both NVIM_GENERATED_FOR_HEADERS and NVIM_GENERATED_FOR_SOURCES")
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
# Our dependencies come first.
|
||||
|
||||
if (LibIntl_FOUND)
|
||||
|
@ -315,8 +348,8 @@ if(JEMALLOC_FOUND)
|
|||
list(APPEND NVIM_EXEC_LINK_LIBRARIES ${JEMALLOC_LIBRARIES})
|
||||
endif()
|
||||
|
||||
add_executable(nvim ${NEOVIM_GENERATED_SOURCES} ${NEOVIM_SOURCES}
|
||||
${NEOVIM_HEADERS})
|
||||
add_executable(nvim ${NVIM_GENERATED_FOR_SOURCES} ${NVIM_GENERATED_FOR_HEADERS}
|
||||
${NVIM_GENERATED_SOURCES} ${NVIM_SOURCES} ${NVIM_HEADERS})
|
||||
target_link_libraries(nvim ${NVIM_EXEC_LINK_LIBRARIES})
|
||||
install_helper(TARGETS nvim)
|
||||
|
||||
|
@ -374,26 +407,49 @@ if(WIN32)
|
|||
add_dependencies(nvim_runtime_deps external_blobs)
|
||||
endif()
|
||||
|
||||
add_library(libnvim STATIC EXCLUDE_FROM_ALL ${NEOVIM_GENERATED_SOURCES}
|
||||
${NEOVIM_SOURCES} ${NEOVIM_HEADERS})
|
||||
add_library(
|
||||
libnvim
|
||||
STATIC
|
||||
EXCLUDE_FROM_ALL
|
||||
${NVIM_SOURCES} ${NVIM_GENERATED_SOURCES}
|
||||
${NVIM_HEADERS} ${NVIM_GENERATED_FOR_SOURCES} ${NVIM_GENERATED_FOR_HEADERS}
|
||||
)
|
||||
set_property(TARGET libnvim APPEND PROPERTY
|
||||
INCLUDE_DIRECTORIES ${LUAJIT_INCLUDE_DIRS})
|
||||
target_link_libraries(libnvim ${NVIM_TEST_LINK_LIBRARIES})
|
||||
set_target_properties(libnvim PROPERTIES
|
||||
POSITION_INDEPENDENT_CODE ON
|
||||
OUTPUT_NAME nvim)
|
||||
set_property(TARGET libnvim
|
||||
APPEND_STRING PROPERTY COMPILE_FLAGS " -DMAKE_LIB ")
|
||||
set_target_properties(
|
||||
libnvim
|
||||
PROPERTIES
|
||||
POSITION_INDEPENDENT_CODE ON
|
||||
OUTPUT_NAME nvim
|
||||
)
|
||||
set_property(
|
||||
TARGET libnvim
|
||||
APPEND_STRING PROPERTY COMPILE_FLAGS " -DMAKE_LIB "
|
||||
)
|
||||
|
||||
add_library(nvim-test MODULE EXCLUDE_FROM_ALL ${NEOVIM_GENERATED_SOURCES}
|
||||
${NEOVIM_SOURCES} ${UNIT_TEST_FIXTURES} ${NEOVIM_HEADERS})
|
||||
add_library(
|
||||
nvim-test
|
||||
MODULE
|
||||
EXCLUDE_FROM_ALL
|
||||
${NVIM_SOURCES} ${NVIM_GENERATED_SOURCES}
|
||||
${NVIM_HEADERS} ${NVIM_GENERATED_FOR_SOURCES} ${NVIM_GENERATED_FOR_HEADERS}
|
||||
${UNIT_TEST_FIXTURES}
|
||||
)
|
||||
target_link_libraries(nvim-test ${NVIM_TEST_LINK_LIBRARIES})
|
||||
set_property(TARGET nvim-test APPEND PROPERTY
|
||||
INCLUDE_DIRECTORIES ${LUAJIT_INCLUDE_DIRS})
|
||||
set_target_properties(nvim-test PROPERTIES
|
||||
POSITION_INDEPENDENT_CODE ON)
|
||||
set_property(TARGET nvim-test
|
||||
APPEND_STRING PROPERTY COMPILE_FLAGS " -DUNIT_TESTING ")
|
||||
set_property(
|
||||
TARGET nvim-test
|
||||
APPEND PROPERTY INCLUDE_DIRECTORIES ${LUAJIT_INCLUDE_DIRS}
|
||||
)
|
||||
set_target_properties(
|
||||
nvim-test
|
||||
PROPERTIES
|
||||
POSITION_INDEPENDENT_CODE ON
|
||||
)
|
||||
set_property(
|
||||
TARGET nvim-test
|
||||
APPEND_STRING PROPERTY COMPILE_FLAGS " -DUNIT_TESTING "
|
||||
)
|
||||
|
||||
if(CLANG_ASAN_UBSAN)
|
||||
message(STATUS "Enabling Clang address sanitizer and undefined behavior sanitizer for nvim.")
|
||||
|
@ -419,4 +475,132 @@ elseif(CLANG_TSAN)
|
|||
set_property(TARGET nvim APPEND_STRING PROPERTY LINK_FLAGS "-fsanitize=thread ")
|
||||
endif()
|
||||
|
||||
function(get_test_target prefix sfile relative_path_var target_var)
|
||||
get_filename_component(full_d "${sfile}" PATH)
|
||||
file(RELATIVE_PATH d "${PROJECT_SOURCE_DIR}/src/nvim" "${full_d}")
|
||||
if(d MATCHES "^[.][.]")
|
||||
file(RELATIVE_PATH d "${GENERATED_DIR}" "${full_d}")
|
||||
endif()
|
||||
get_filename_component(r "${sfile}" NAME)
|
||||
if(NOT d MATCHES "^[.]?$")
|
||||
set(r "${d}/${r}")
|
||||
endif()
|
||||
string(REGEX REPLACE "[/.]" "-" suffix "${r}")
|
||||
set(${relative_path_var} ${r} PARENT_SCOPE)
|
||||
if(prefix STREQUAL "")
|
||||
set(${target_var} "${suffix}" PARENT_SCOPE)
|
||||
else()
|
||||
set(${target_var} "${prefix}-${suffix}" PARENT_SCOPE)
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
set(NO_SINGLE_CHECK_HEADERS
|
||||
cursor_shape.h
|
||||
digraph.h
|
||||
ex_cmds.h
|
||||
ex_getln.h
|
||||
file_search.h
|
||||
fold.h
|
||||
getchar.h
|
||||
hardcopy.h
|
||||
if_cscope.h
|
||||
if_cscope_defs.h
|
||||
mark.h
|
||||
mbyte.h
|
||||
memfile_defs.h
|
||||
memline.h
|
||||
memline_defs.h
|
||||
menu.h
|
||||
misc2.h
|
||||
move.h
|
||||
msgpack_rpc/server.h
|
||||
ops.h
|
||||
option.h
|
||||
os/shell.h
|
||||
os_unix.h
|
||||
os/win_defs.h
|
||||
popupmnu.h
|
||||
quickfix.h
|
||||
regexp.h
|
||||
regexp_defs.h
|
||||
screen.h
|
||||
search.h
|
||||
sha256.h
|
||||
sign_defs.h
|
||||
spell.h
|
||||
spellfile.h
|
||||
syntax.h
|
||||
syntax_defs.h
|
||||
tag.h
|
||||
terminal.h
|
||||
tui/tui.h
|
||||
ugrid.h
|
||||
ui.h
|
||||
ui_bridge.h
|
||||
undo.h
|
||||
undo_defs.h
|
||||
version.h
|
||||
window.h
|
||||
)
|
||||
foreach(hfile ${NVIM_HEADERS})
|
||||
get_test_target(test-includes "${hfile}" relative_path texe)
|
||||
|
||||
if(NOT ${hfile} MATCHES "[.]c[.]h$")
|
||||
set(tsource "${GENERATED_DIR}/${relative_path}.test-include.c")
|
||||
write_file("${tsource}" "#include \"${hfile}\"\nint main(int argc, char **argv) { return 0; }")
|
||||
add_executable(
|
||||
${texe}
|
||||
EXCLUDE_FROM_ALL
|
||||
${tsource} ${NVIM_HEADERS} ${NVIM_GENERATED_FOR_HEADERS})
|
||||
|
||||
list(FIND NO_SINGLE_CHECK_HEADERS "${relative_path}" hfile_exclude_idx)
|
||||
if(${hfile_exclude_idx} EQUAL -1)
|
||||
list(APPEND HEADER_CHECK_TARGETS ${texe})
|
||||
endif()
|
||||
endif()
|
||||
endforeach()
|
||||
add_custom_target(check-single-includes DEPENDS ${HEADER_CHECK_TARGETS})
|
||||
|
||||
function(add_download output url allow_failure)
|
||||
add_custom_command(
|
||||
OUTPUT "${output}"
|
||||
COMMAND
|
||||
${CMAKE_COMMAND}
|
||||
-DURL=${url} -DFILE=${output}
|
||||
-DALLOW_FAILURE=${allow_failure}
|
||||
-P ${DOWNLOAD_SCRIPT}
|
||||
DEPENDS ${DOWNLOAD_SCRIPT}
|
||||
)
|
||||
endfunction()
|
||||
|
||||
add_download(${LINT_SUPPRESS_FILE} ${LINT_SUPPRESS_URL} off)
|
||||
|
||||
set(LINT_NVIM_REL_SOURCES)
|
||||
foreach(sfile ${LINT_NVIM_SOURCES})
|
||||
get_test_target("" "${sfile}" r suffix)
|
||||
set(suppress_file ${LINT_SUPPRESSES_ROOT}/${suffix}.json)
|
||||
set(suppress_url "${LINT_SUPPRESS_URL_BASE}/${suffix}.json")
|
||||
set(rsfile src/nvim/${r})
|
||||
add_download(${suppress_file} ${suppress_url} on)
|
||||
set(touch_file "${TOUCHES_DIR}/ran-clint-${suffix}")
|
||||
add_custom_command(
|
||||
OUTPUT ${touch_file}
|
||||
COMMAND ${LINT_PRG} --suppress-errors=${suppress_file} ${rsfile}
|
||||
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
|
||||
COMMAND ${CMAKE_COMMAND} -E touch ${touch_file}
|
||||
DEPENDS ${LINT_PRG} ${sfile} ${suppress_file}
|
||||
)
|
||||
list(APPEND LINT_TARGETS ${touch_file})
|
||||
list(APPEND LINT_NVIM_REL_SOURCES ${rsfile})
|
||||
endforeach()
|
||||
add_custom_target(clint DEPENDS ${LINT_TARGETS})
|
||||
|
||||
add_custom_target(
|
||||
clint-full
|
||||
COMMAND
|
||||
${LINT_PRG} --suppress-errors=${LINT_SUPPRESS_FILE} ${LINT_NVIM_REL_SOURCES}
|
||||
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
|
||||
DEPENDS ${LINT_PRG} ${LINT_NVIM_SOURCES} ${LINT_SUPPRESS_FILE}
|
||||
)
|
||||
|
||||
add_subdirectory(po)
|
||||
|
|
|
@ -296,7 +296,7 @@ void nvim_buf_set_lines(uint64_t channel_id,
|
|||
tabpage_T *save_curtab = NULL;
|
||||
size_t new_len = replacement.size;
|
||||
size_t old_len = (size_t)(end - start);
|
||||
ssize_t extra = 0; // lines added to text, can be negative
|
||||
ptrdiff_t extra = 0; // lines added to text, can be negative
|
||||
char **lines = (new_len != 0) ? xcalloc(new_len, sizeof(char *)) : NULL;
|
||||
|
||||
for (size_t i = 0; i < new_len; i++) {
|
||||
|
@ -342,8 +342,8 @@ void nvim_buf_set_lines(uint64_t channel_id,
|
|||
}
|
||||
}
|
||||
|
||||
if ((ssize_t)to_delete > 0) {
|
||||
extra -= (ssize_t)to_delete;
|
||||
if (to_delete > 0) {
|
||||
extra -= (ptrdiff_t)to_delete;
|
||||
}
|
||||
|
||||
// For as long as possible, replace the existing old_len with the
|
||||
|
@ -395,10 +395,10 @@ void nvim_buf_set_lines(uint64_t channel_id,
|
|||
mark_adjust((linenr_T)start, (linenr_T)(end - 1), MAXLNUM, extra);
|
||||
}
|
||||
|
||||
changed_lines((linenr_T)start, 0, (linenr_T)end, extra);
|
||||
changed_lines((linenr_T)start, 0, (linenr_T)end, (long)extra);
|
||||
|
||||
if (save_curbuf.br_buf == NULL) {
|
||||
fix_cursor((linenr_T)start, (linenr_T)end, extra);
|
||||
fix_cursor((linenr_T)start, (linenr_T)end, (linenr_T)extra);
|
||||
}
|
||||
|
||||
end:
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
#include "nvim/window.h"
|
||||
#include "nvim/memory.h"
|
||||
#include "nvim/eval.h"
|
||||
#include "nvim/eval/typval.h"
|
||||
#include "nvim/map_defs.h"
|
||||
#include "nvim/map.h"
|
||||
#include "nvim/option.h"
|
||||
|
@ -87,14 +88,13 @@ bool try_end(Error *err)
|
|||
/// @param[out] err Details of an error that may have occurred
|
||||
Object dict_get_value(dict_T *dict, String key, Error *err)
|
||||
{
|
||||
hashitem_T *hi = hash_find(&dict->dv_hashtab, (uint8_t *) key.data);
|
||||
dictitem_T *const di = tv_dict_find(dict, key.data, (ptrdiff_t)key.size);
|
||||
|
||||
if (HASHITEM_EMPTY(hi)) {
|
||||
if (di == NULL) {
|
||||
api_set_error(err, Validation, _("Key not found"));
|
||||
return (Object) OBJECT_INIT;
|
||||
}
|
||||
|
||||
dictitem_T *di = dict_lookup(hi);
|
||||
return vim_to_object(&di->di_tv);
|
||||
}
|
||||
|
||||
|
@ -129,7 +129,7 @@ Object dict_set_var(dict_T *dict, String key, Object value, bool del,
|
|||
return rv;
|
||||
}
|
||||
|
||||
dictitem_T *di = dict_find(dict, (char_u *)key.data, (int)key.size);
|
||||
dictitem_T *di = tv_dict_find(dict, key.data, (ptrdiff_t)key.size);
|
||||
|
||||
if (di != NULL) {
|
||||
if (di->di_flags & DI_FLAGS_RO) {
|
||||
|
@ -155,9 +155,7 @@ Object dict_set_var(dict_T *dict, String key, Object value, bool del,
|
|||
rv = vim_to_object(&di->di_tv);
|
||||
}
|
||||
// Delete the entry
|
||||
hashitem_T *hi = hash_find(&dict->dv_hashtab, di->di_key);
|
||||
hash_remove(&dict->dv_hashtab, hi);
|
||||
dictitem_free(di);
|
||||
tv_dict_item_remove(dict, di);
|
||||
}
|
||||
} else {
|
||||
// Update the key
|
||||
|
@ -170,20 +168,20 @@ Object dict_set_var(dict_T *dict, String key, Object value, bool del,
|
|||
|
||||
if (di == NULL) {
|
||||
// Need to create an entry
|
||||
di = dictitem_alloc((uint8_t *) key.data);
|
||||
dict_add(dict, di);
|
||||
di = tv_dict_item_alloc_len(key.data, key.size);
|
||||
tv_dict_add(dict, di);
|
||||
} else {
|
||||
// Return the old value
|
||||
if (retval) {
|
||||
rv = vim_to_object(&di->di_tv);
|
||||
}
|
||||
clear_tv(&di->di_tv);
|
||||
tv_clear(&di->di_tv);
|
||||
}
|
||||
|
||||
// Update the value
|
||||
copy_tv(&tv, &di->di_tv);
|
||||
tv_copy(&tv, &di->di_tv);
|
||||
// Clear the temporary variable
|
||||
clear_tv(&tv);
|
||||
tv_clear(&tv);
|
||||
}
|
||||
|
||||
return rv;
|
||||
|
@ -291,7 +289,7 @@ void set_option_to(void *to, int type, String name, Object value, Error *err)
|
|||
}
|
||||
}
|
||||
|
||||
int opt_flags = (type ? OPT_LOCAL : OPT_GLOBAL);
|
||||
int opt_flags = (type == SREQ_GLOBAL) ? OPT_GLOBAL : OPT_LOCAL;
|
||||
|
||||
if (flags & SOPT_BOOL) {
|
||||
if (value.type != kObjectTypeBoolean) {
|
||||
|
@ -627,7 +625,7 @@ String cstr_as_string(char *str) FUNC_ATTR_PURE
|
|||
if (str == NULL) {
|
||||
return (String) STRING_INIT;
|
||||
}
|
||||
return (String) {.data = str, .size = strlen(str)};
|
||||
return (String) { .data = str, .size = strlen(str) };
|
||||
}
|
||||
|
||||
/// Converts from type Object to a VimL value.
|
||||
|
@ -682,20 +680,20 @@ bool object_to_vim(Object obj, typval_T *tv, Error *err)
|
|||
break;
|
||||
|
||||
case kObjectTypeArray: {
|
||||
list_T *list = list_alloc();
|
||||
list_T *const list = tv_list_alloc();
|
||||
|
||||
for (uint32_t i = 0; i < obj.data.array.size; i++) {
|
||||
Object item = obj.data.array.items[i];
|
||||
listitem_T *li = listitem_alloc();
|
||||
listitem_T *li = tv_list_item_alloc();
|
||||
|
||||
if (!object_to_vim(item, &li->li_tv, err)) {
|
||||
// cleanup
|
||||
listitem_free(li);
|
||||
list_free(list);
|
||||
tv_list_item_free(li);
|
||||
tv_list_free(list);
|
||||
return false;
|
||||
}
|
||||
|
||||
list_append(list, li);
|
||||
tv_list_append(list, li);
|
||||
}
|
||||
list->lv_refcount++;
|
||||
|
||||
|
@ -705,7 +703,7 @@ bool object_to_vim(Object obj, typval_T *tv, Error *err)
|
|||
}
|
||||
|
||||
case kObjectTypeDictionary: {
|
||||
dict_T *dict = dict_alloc();
|
||||
dict_T *const dict = tv_dict_alloc();
|
||||
|
||||
for (uint32_t i = 0; i < obj.data.dictionary.size; i++) {
|
||||
KeyValuePair item = obj.data.dictionary.items[i];
|
||||
|
@ -715,20 +713,20 @@ bool object_to_vim(Object obj, typval_T *tv, Error *err)
|
|||
api_set_error(err, Validation,
|
||||
_("Empty dictionary keys aren't allowed"));
|
||||
// cleanup
|
||||
dict_free(dict);
|
||||
tv_dict_free(dict);
|
||||
return false;
|
||||
}
|
||||
|
||||
dictitem_T *di = dictitem_alloc((uint8_t *)key.data);
|
||||
dictitem_T *const di = tv_dict_item_alloc(key.data);
|
||||
|
||||
if (!object_to_vim(item.value, &di->di_tv, err)) {
|
||||
// cleanup
|
||||
dictitem_free(di);
|
||||
dict_free(dict);
|
||||
tv_dict_item_free(di);
|
||||
tv_dict_free(dict);
|
||||
return false;
|
||||
}
|
||||
|
||||
dict_add(dict, di);
|
||||
tv_dict_add(dict, di);
|
||||
}
|
||||
dict->dv_refcount++;
|
||||
|
||||
|
@ -962,11 +960,7 @@ static void set_option_value_err(char *key,
|
|||
{
|
||||
char *errmsg;
|
||||
|
||||
if ((errmsg = (char *)set_option_value((uint8_t *)key,
|
||||
numval,
|
||||
(uint8_t *)stringval,
|
||||
opt_flags)))
|
||||
{
|
||||
if ((errmsg = set_option_value(key, numval, stringval, opt_flags))) {
|
||||
if (try_end(err)) {
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
#include "nvim/api/private/defs.h"
|
||||
#include "nvim/api/private/helpers.h"
|
||||
#include "nvim/popupmnu.h"
|
||||
#include "nvim/cursor_shape.h"
|
||||
|
||||
#ifdef INCLUDE_GENERATED_DECLARATIONS
|
||||
# include "api/ui.c.generated.h"
|
||||
|
@ -69,6 +70,7 @@ void nvim_ui_attach(uint64_t channel_id, Integer width, Integer height,
|
|||
ui->clear = remote_ui_clear;
|
||||
ui->eol_clear = remote_ui_eol_clear;
|
||||
ui->cursor_goto = remote_ui_cursor_goto;
|
||||
ui->cursor_style_set = remote_ui_cursor_style_set;
|
||||
ui->update_menu = remote_ui_update_menu;
|
||||
ui->busy_start = remote_ui_busy_start;
|
||||
ui->busy_stop = remote_ui_busy_stop;
|
||||
|
@ -298,6 +300,14 @@ static void remote_ui_scroll(UI *ui, int count)
|
|||
push_call(ui, "scroll", args);
|
||||
}
|
||||
|
||||
static void remote_ui_cursor_style_set(UI *ui, bool enabled, Dictionary data)
|
||||
{
|
||||
Array args = ARRAY_DICT_INIT;
|
||||
ADD(args, BOOLEAN_OBJ(enabled));
|
||||
ADD(args, copy_object(DICTIONARY_OBJ(data)));
|
||||
push_call(ui, "cursor_style_set", args);
|
||||
}
|
||||
|
||||
static void remote_ui_highlight_set(UI *ui, HlAttrs attrs)
|
||||
{
|
||||
Array args = ARRAY_DICT_INIT;
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
#include "nvim/memory.h"
|
||||
#include "nvim/message.h"
|
||||
#include "nvim/eval.h"
|
||||
#include "nvim/eval/typval.h"
|
||||
#include "nvim/option.h"
|
||||
#include "nvim/syntax.h"
|
||||
#include "nvim/getchar.h"
|
||||
|
@ -181,19 +182,20 @@ Object nvim_eval(String expr, Error *err)
|
|||
Object rv = OBJECT_INIT;
|
||||
// Evaluate the expression
|
||||
try_start();
|
||||
typval_T *expr_result = eval_expr((char_u *)expr.data, NULL);
|
||||
|
||||
if (!expr_result) {
|
||||
api_set_error(err, Exception, _("Failed to evaluate expression"));
|
||||
typval_T rettv;
|
||||
if (eval0((char_u *)expr.data, &rettv, NULL, true) == FAIL) {
|
||||
api_set_error(err, Exception, "Failed to evaluate expression");
|
||||
}
|
||||
|
||||
if (!try_end(err)) {
|
||||
// No errors, convert the result
|
||||
rv = vim_to_object(expr_result);
|
||||
rv = vim_to_object(&rettv);
|
||||
}
|
||||
|
||||
// Free the vim object
|
||||
free_tv(expr_result);
|
||||
// Free the Vim object
|
||||
tv_clear(&rettv);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
@ -238,11 +240,11 @@ Object nvim_call_function(String fname, Array args, Error *err)
|
|||
if (!try_end(err)) {
|
||||
rv = vim_to_object(&rettv);
|
||||
}
|
||||
clear_tv(&rettv);
|
||||
tv_clear(&rettv);
|
||||
|
||||
free_vim_args:
|
||||
while (i > 0) {
|
||||
clear_tv(&vim_args[--i]);
|
||||
tv_clear(&vim_args[--i]);
|
||||
}
|
||||
|
||||
return rv;
|
||||
|
@ -439,7 +441,7 @@ Object nvim_get_vvar(String name, Error *err)
|
|||
///
|
||||
/// @param name Option name
|
||||
/// @param[out] err Error details, if any
|
||||
/// @return Option value
|
||||
/// @return Option value (global)
|
||||
Object nvim_get_option(String name, Error *err)
|
||||
FUNC_API_SINCE(1)
|
||||
{
|
||||
|
|
|
@ -8,9 +8,11 @@
|
|||
|
||||
// Definitions of various common control characters.
|
||||
|
||||
#define CharOrd(x) ((x) < 'a' ? (x) - 'A' : (x) - 'a')
|
||||
#define CharOrdLow(x) ((x) - 'a')
|
||||
#define CharOrdUp(x) ((x) - 'A')
|
||||
#define CharOrd(x) ((uint8_t)(x) < 'a' \
|
||||
? (uint8_t)(x) - 'A'\
|
||||
: (uint8_t)(x) - 'a')
|
||||
#define CharOrdLow(x) ((uint8_t)(x) - 'a')
|
||||
#define CharOrdUp(x) ((uint8_t)(x) - 'A')
|
||||
#define ROT13(c, a) (((((c) - (a)) + 13) % 26) + (a))
|
||||
|
||||
#define NUL '\000'
|
||||
|
@ -18,15 +20,14 @@
|
|||
#define BS '\010'
|
||||
#define TAB '\011'
|
||||
#define NL '\012'
|
||||
#define NL_STR (char_u *)"\012"
|
||||
#define NL_STR "\012"
|
||||
#define FF '\014'
|
||||
#define CAR '\015' /* CR is used by Mac OS X */
|
||||
#define ESC '\033'
|
||||
#define ESC_STR (char_u *)"\033"
|
||||
#define ESC_STR_nc "\033"
|
||||
#define ESC_STR "\033"
|
||||
#define DEL 0x7f
|
||||
#define DEL_STR (char_u *)"\177"
|
||||
#define CSI 0x9b /* Control Sequence Introducer */
|
||||
#define DEL_STR "\177"
|
||||
#define CSI 0x9b // Control Sequence Introducer
|
||||
#define CSI_STR "\233"
|
||||
#define DCS 0x90 /* Device Control String */
|
||||
#define STERM 0x9c /* String Terminator */
|
||||
|
|
|
@ -627,10 +627,11 @@ void buf_freeall(buf_T *buf, int flags)
|
|||
*/
|
||||
if (buf == curbuf && !is_curbuf)
|
||||
return;
|
||||
diff_buf_delete(buf); /* Can't use 'diff' for unloaded buffer. */
|
||||
/* Remove any ownsyntax, unless exiting. */
|
||||
if (firstwin != NULL && curwin->w_buffer == buf)
|
||||
diff_buf_delete(buf); // Can't use 'diff' for unloaded buffer.
|
||||
// Remove any ownsyntax, unless exiting.
|
||||
if (curwin != NULL && curwin->w_buffer == buf) {
|
||||
reset_synblock(curwin);
|
||||
}
|
||||
|
||||
/* No folds in an empty buffer. */
|
||||
FOR_ALL_TAB_WINDOWS(tp, win) {
|
||||
|
@ -660,7 +661,7 @@ static void free_buffer(buf_T *buf)
|
|||
free_buffer_stuff(buf, true);
|
||||
unref_var_dict(buf->b_vars);
|
||||
aubuflocal_remove(buf);
|
||||
dict_unref(buf->additional_data);
|
||||
tv_dict_unref(buf->additional_data);
|
||||
clear_fmark(&buf->b_last_cursor);
|
||||
clear_fmark(&buf->b_last_insert);
|
||||
clear_fmark(&buf->b_last_change);
|
||||
|
@ -1471,7 +1472,7 @@ static inline void buf_init_changedtick(buf_T *const buf)
|
|||
{
|
||||
STATIC_ASSERT(sizeof("changedtick") <= sizeof(buf->changedtick_di.di_key),
|
||||
"buf->changedtick_di cannot hold large enough keys");
|
||||
buf->changedtick_di = (dictitem16_T) {
|
||||
buf->changedtick_di = (ChangedtickDictItem) {
|
||||
.di_flags = DI_FLAGS_RO|DI_FLAGS_FIX, // Must not include DI_FLAGS_ALLOC.
|
||||
.di_tv = (typval_T) {
|
||||
.v_type = VAR_NUMBER,
|
||||
|
@ -1480,7 +1481,7 @@ static inline void buf_init_changedtick(buf_T *const buf)
|
|||
},
|
||||
.di_key = "changedtick",
|
||||
};
|
||||
dict_add(buf->b_vars, (dictitem_T *)&buf->changedtick_di);
|
||||
tv_dict_add(buf->b_vars, (dictitem_T *)&buf->changedtick_di);
|
||||
}
|
||||
|
||||
/// Add a file name to the buffer list.
|
||||
|
@ -1572,7 +1573,7 @@ buf_T * buflist_new(char_u *ffname, char_u *sfname, linenr_T lnum, int flags)
|
|||
if (buf != curbuf || curbuf == NULL) {
|
||||
buf = xcalloc(1, sizeof(buf_T));
|
||||
// init b: variables
|
||||
buf->b_vars = dict_alloc();
|
||||
buf->b_vars = tv_dict_alloc();
|
||||
init_var_dict(buf->b_vars, &buf->b_bufvar, VAR_SCOPE);
|
||||
buf_init_changedtick(buf);
|
||||
}
|
||||
|
@ -2723,7 +2724,7 @@ fileinfo (
|
|||
else
|
||||
name = curbuf->b_ffname;
|
||||
home_replace(shorthelp ? curbuf : NULL, name, p,
|
||||
(int)(IOSIZE - (p - buffer)), TRUE);
|
||||
(size_t)(IOSIZE - (p - buffer)), true);
|
||||
}
|
||||
|
||||
vim_snprintf_add((char *)buffer, IOSIZE, "\"%s%s%s%s%s%s",
|
||||
|
@ -2888,7 +2889,7 @@ void maketitle(void)
|
|||
buf[off++] = ' ';
|
||||
buf[off++] = '(';
|
||||
home_replace(curbuf, curbuf->b_ffname,
|
||||
buf + off, SPACE_FOR_DIR - off, TRUE);
|
||||
buf + off, (size_t)(SPACE_FOR_DIR - off), true);
|
||||
#ifdef BACKSLASH_IN_FILENAME
|
||||
/* avoid "c:/name" to be reduced to "c" */
|
||||
if (isalpha(buf[off]) && buf[off + 1] == ':')
|
||||
|
@ -3503,7 +3504,7 @@ int build_stl_str_hl(
|
|||
curbuf = o_curbuf;
|
||||
|
||||
// Remove the variable we just stored
|
||||
do_unlet((char_u *)"g:actual_curbuf", true);
|
||||
do_unlet(S_LEN("g:actual_curbuf"), true);
|
||||
|
||||
// }
|
||||
|
||||
|
@ -4206,11 +4207,11 @@ void fname_expand(buf_T *buf, char_u **ffname, char_u **sfname)
|
|||
#ifdef WIN32
|
||||
if (!buf->b_p_bin) {
|
||||
// If the file name is a shortcut file, use the file it links to.
|
||||
char_u *rfname = (char_u *)os_resolve_shortcut(*ffname);
|
||||
char *rfname = os_resolve_shortcut((const char *)(*ffname));
|
||||
if (rfname != NULL) {
|
||||
xfree(*ffname);
|
||||
*ffname = rfname;
|
||||
*sfname = rfname;
|
||||
*ffname = (char_u *)rfname;
|
||||
*sfname = (char_u *)rfname;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
@ -5442,8 +5443,8 @@ void buf_open_scratch(handle_T bufnr, char *bufname)
|
|||
{
|
||||
(void)do_ecmd((int)bufnr, NULL, NULL, NULL, ECMD_ONE, ECMD_HIDE, NULL);
|
||||
(void)setfname(curbuf, (char_u *)bufname, NULL, true);
|
||||
set_option_value((char_u *)"bh", 0L, (char_u *)"hide", OPT_LOCAL);
|
||||
set_option_value((char_u *)"bt", 0L, (char_u *)"nofile", OPT_LOCAL);
|
||||
set_option_value((char_u *)"swf", 0L, NULL, OPT_LOCAL);
|
||||
set_option_value("bh", 0L, "hide", OPT_LOCAL);
|
||||
set_option_value("bt", 0L, "nofile", OPT_LOCAL);
|
||||
set_option_value("swf", 0L, NULL, OPT_LOCAL);
|
||||
RESET_BINDING(curwin);
|
||||
}
|
||||
|
|
|
@ -1,12 +1,14 @@
|
|||
#ifndef NVIM_BUFFER_H
|
||||
#define NVIM_BUFFER_H
|
||||
|
||||
#include "nvim/vim.h"
|
||||
#include "nvim/window.h"
|
||||
#include "nvim/pos.h" // for linenr_T
|
||||
#include "nvim/ex_cmds_defs.h" // for exarg_T
|
||||
#include "nvim/screen.h" // for StlClickRecord
|
||||
#include "nvim/func_attr.h"
|
||||
#include "nvim/eval.h"
|
||||
#include "nvim/macros.h"
|
||||
|
||||
// Values for buflist_getfile()
|
||||
enum getf_values {
|
||||
|
@ -91,8 +93,8 @@ static inline void buf_set_changedtick(buf_T *const buf, const int changedtick)
|
|||
static inline void buf_set_changedtick(buf_T *const buf, const int changedtick)
|
||||
{
|
||||
#ifndef NDEBUG
|
||||
dictitem_T *const changedtick_di = dict_find(
|
||||
buf->b_vars, (char_u *)"changedtick", sizeof("changedtick") - 1);
|
||||
dictitem_T *const changedtick_di = tv_dict_find(
|
||||
buf->b_vars, S_LEN("changedtick"));
|
||||
assert(changedtick_di != NULL);
|
||||
assert(changedtick_di->di_tv.v_type == VAR_NUMBER);
|
||||
assert(changedtick_di->di_tv.v_lock == VAR_FIXED);
|
||||
|
|
|
@ -21,8 +21,6 @@ typedef struct {
|
|||
#include "nvim/pos.h"
|
||||
// for the number window-local and buffer-local options
|
||||
#include "nvim/option_defs.h"
|
||||
// for optional iconv support
|
||||
#include "nvim/iconv.h"
|
||||
// for jump list and tag stack sizes in a buffer and mark types
|
||||
#include "nvim/mark_defs.h"
|
||||
// for u_header_T; needs buf_T.
|
||||
|
@ -30,7 +28,9 @@ typedef struct {
|
|||
// for hashtab_T
|
||||
#include "nvim/hashtab.h"
|
||||
// for dict_T
|
||||
#include "nvim/eval_defs.h"
|
||||
#include "nvim/eval/typval.h"
|
||||
// for proftime_T
|
||||
#include "nvim/profile.h"
|
||||
// for String
|
||||
#include "nvim/api/private/defs.h"
|
||||
// for Map(K, V)
|
||||
|
@ -318,25 +318,6 @@ typedef struct {
|
|||
String save_inputbuf;
|
||||
} tasave_T;
|
||||
|
||||
/*
|
||||
* Used for conversion of terminal I/O and script files.
|
||||
*/
|
||||
typedef struct {
|
||||
int vc_type; /* zero or one of the CONV_ values */
|
||||
int vc_factor; /* max. expansion factor */
|
||||
# ifdef USE_ICONV
|
||||
iconv_t vc_fd; /* for CONV_ICONV */
|
||||
# endif
|
||||
bool vc_fail; /* fail for invalid char, don't use '?' */
|
||||
} vimconv_T;
|
||||
|
||||
#define CONV_NONE 0
|
||||
#define CONV_TO_UTF8 1
|
||||
#define CONV_9_TO_UTF8 2
|
||||
#define CONV_TO_LATIN1 3
|
||||
#define CONV_TO_LATIN9 4
|
||||
#define CONV_ICONV 5
|
||||
|
||||
/*
|
||||
* Structure used for mappings and abbreviations.
|
||||
*/
|
||||
|
@ -447,6 +428,10 @@ typedef struct {
|
|||
char_u *b_syn_isk; // iskeyword option
|
||||
} synblock_T;
|
||||
|
||||
/// Type used for changedtick_di member in buf_T
|
||||
///
|
||||
/// Primary exists so that literals of relevant type can be made.
|
||||
typedef TV_DICTITEM_STRUCT(sizeof("changedtick")) ChangedtickDictItem;
|
||||
|
||||
#define BUF_HAS_QF_ENTRY 1
|
||||
#define BUF_HAS_LL_ENTRY 2
|
||||
|
@ -491,7 +476,7 @@ struct file_buffer {
|
|||
// file has been changed and not written out.
|
||||
/// Change identifier incremented for each change, including undo
|
||||
#define b_changedtick changedtick_di.di_tv.vval.v_number
|
||||
dictitem16_T changedtick_di; // b:changedtick dictionary item.
|
||||
ChangedtickDictItem changedtick_di; // b:changedtick dictionary item.
|
||||
|
||||
bool b_saving; /* Set to true if we are in the middle of
|
||||
saving the buffer. */
|
||||
|
@ -735,8 +720,8 @@ struct file_buffer {
|
|||
int b_bad_char; /* "++bad=" argument when edit started or 0 */
|
||||
int b_start_bomb; /* 'bomb' when it was read */
|
||||
|
||||
dictitem_T b_bufvar; /* variable for "b:" Dictionary */
|
||||
dict_T *b_vars; /* internal variables, local to buffer */
|
||||
ScopeDictDictItem b_bufvar; ///< Variable for "b:" Dictionary.
|
||||
dict_T *b_vars; ///< b: scope dictionary.
|
||||
|
||||
/* When a buffer is created, it starts without a swap file. b_may_swap is
|
||||
* then set to indicate that a swap file may be opened later. It is reset
|
||||
|
@ -824,9 +809,9 @@ struct tabpage_S {
|
|||
buf_T *(tp_diffbuf[DB_COUNT]);
|
||||
int tp_diff_invalid; ///< list of diffs is outdated
|
||||
frame_T *(tp_snapshot[SNAP_COUNT]); ///< window layout snapshots
|
||||
dictitem_T tp_winvar; ///< variable for "t:" Dictionary
|
||||
dict_T *tp_vars; ///< internal variables, local to tab page
|
||||
char_u *tp_localdir; ///< Absolute path of local CWD or NULL
|
||||
ScopeDictDictItem tp_winvar; ///< Variable for "t:" Dictionary.
|
||||
dict_T *tp_vars; ///< Internal variables, local to tab page.
|
||||
char_u *tp_localdir; ///< Absolute path of local cwd or NULL.
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -1118,8 +1103,8 @@ struct window_S {
|
|||
|
||||
long w_scbind_pos;
|
||||
|
||||
dictitem_T w_winvar; /* variable for "w:" Dictionary */
|
||||
dict_T *w_vars; /* internal variables, local to window */
|
||||
ScopeDictDictItem w_winvar; ///< Variable for "w:" dictionary.
|
||||
dict_T *w_vars; ///< Dictionary with w: variables.
|
||||
|
||||
int w_farsi; /* for the window dependent Farsi functions */
|
||||
|
||||
|
|
|
@ -41,8 +41,10 @@ static bool chartab_initialized = false;
|
|||
(buf)->b_chartab[(unsigned)(c) >> 6] |= (1ull << ((c) & 0x3f))
|
||||
#define RESET_CHARTAB(buf, c) \
|
||||
(buf)->b_chartab[(unsigned)(c) >> 6] &= ~(1ull << ((c) & 0x3f))
|
||||
#define GET_CHARTAB_TAB(chartab, c) \
|
||||
((chartab)[(unsigned)(c) >> 6] & (1ull << ((c) & 0x3f)))
|
||||
#define GET_CHARTAB(buf, c) \
|
||||
((buf)->b_chartab[(unsigned)(c) >> 6] & (1ull << ((c) & 0x3f)))
|
||||
GET_CHARTAB_TAB((buf)->b_chartab, c)
|
||||
|
||||
// Table used below, see init_chartab() for an explanation
|
||||
static char_u g_chartab[256];
|
||||
|
@ -88,7 +90,6 @@ int buf_init_chartab(buf_T *buf, int global)
|
|||
{
|
||||
int c;
|
||||
int c2;
|
||||
char_u *p;
|
||||
int i;
|
||||
bool tilde;
|
||||
bool do_isalpha;
|
||||
|
@ -142,7 +143,8 @@ int buf_init_chartab(buf_T *buf, int global)
|
|||
// Walk through the 'isident', 'iskeyword', 'isfname' and 'isprint'
|
||||
// options Each option is a list of characters, character numbers or
|
||||
// ranges, separated by commas, e.g.: "200-210,x,#-178,-"
|
||||
for (i = global ? 0 : 3; i <= 3; ++i) {
|
||||
for (i = global ? 0 : 3; i <= 3; i++) {
|
||||
const char_u *p;
|
||||
if (i == 0) {
|
||||
// first round: 'isident'
|
||||
p = p_isi;
|
||||
|
@ -167,7 +169,7 @@ int buf_init_chartab(buf_T *buf, int global)
|
|||
}
|
||||
|
||||
if (ascii_isdigit(*p)) {
|
||||
c = getdigits_int(&p);
|
||||
c = getdigits_int((char_u **)&p);
|
||||
} else {
|
||||
c = mb_ptr2char_adv(&p);
|
||||
}
|
||||
|
@ -177,7 +179,7 @@ int buf_init_chartab(buf_T *buf, int global)
|
|||
++p;
|
||||
|
||||
if (ascii_isdigit(*p)) {
|
||||
c2 = getdigits_int(&p);
|
||||
c2 = getdigits_int((char_u **)&p);
|
||||
} else {
|
||||
c2 = mb_ptr2char_adv(&p);
|
||||
}
|
||||
|
@ -634,7 +636,7 @@ int char2cells(int c)
|
|||
/// @param p
|
||||
///
|
||||
/// @return number of display cells.
|
||||
int ptr2cells(char_u *p)
|
||||
int ptr2cells(const char_u *p)
|
||||
{
|
||||
// For UTF-8 we need to look at more bytes if the first byte is >= 0x80.
|
||||
if (*p >= 0x80) {
|
||||
|
@ -776,6 +778,20 @@ bool vim_iswordc(int c)
|
|||
return vim_iswordc_buf(c, curbuf);
|
||||
}
|
||||
|
||||
/// Check that "c" is a keyword character
|
||||
/// Letters and characters from 'iskeyword' option for given buffer.
|
||||
/// For multi-byte characters mb_get_class() is used (builtin rules).
|
||||
///
|
||||
/// @param[in] c Character to check.
|
||||
/// @param[in] chartab Buffer chartab.
|
||||
bool vim_iswordc_tab(const int c, const uint64_t *const chartab)
|
||||
FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ALL
|
||||
{
|
||||
return (c >= 0x100
|
||||
? (utf_class(c) >= 2)
|
||||
: (c > 0 && GET_CHARTAB_TAB(chartab, c) != 0));
|
||||
}
|
||||
|
||||
/// Check that "c" is a keyword character:
|
||||
/// Letters and characters from 'iskeyword' option for given buffer.
|
||||
/// For multi-byte characters mb_get_class() is used (builtin rules).
|
||||
|
@ -785,10 +801,7 @@ bool vim_iswordc(int c)
|
|||
bool vim_iswordc_buf(int c, buf_T *buf)
|
||||
FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ARG(2)
|
||||
{
|
||||
if (c >= 0x100) {
|
||||
return utf_class(c) >= 2;
|
||||
}
|
||||
return c > 0 && c < 0x100 && GET_CHARTAB(buf, c) != 0;
|
||||
return vim_iswordc_tab(c, buf->b_chartab);
|
||||
}
|
||||
|
||||
/// Just like vim_iswordc() but uses a pointer to the (multi-byte) character.
|
||||
|
@ -1384,7 +1397,8 @@ void getvcols(win_T *wp, pos_T *pos1, pos_T *pos2, colnr_T *left,
|
|||
///
|
||||
/// @return Pointer to character after the skipped whitespace.
|
||||
char_u *skipwhite(const char_u *q)
|
||||
FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT
|
||||
FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ALL
|
||||
FUNC_ATTR_NONNULL_RET
|
||||
{
|
||||
const char_u *p = q;
|
||||
while (ascii_iswhite(*p)) {
|
||||
|
@ -1393,19 +1407,21 @@ char_u *skipwhite(const char_u *q)
|
|||
return (char_u *)p;
|
||||
}
|
||||
|
||||
/// skip over digits
|
||||
/// Skip over digits
|
||||
///
|
||||
/// @param q
|
||||
/// @param[in] q String to skip digits in.
|
||||
///
|
||||
/// @return Pointer to the character after the skipped digits.
|
||||
char_u* skipdigits(char_u *q)
|
||||
char_u *skipdigits(const char_u *q)
|
||||
FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ALL
|
||||
FUNC_ATTR_NONNULL_RET
|
||||
{
|
||||
char_u *p = q;
|
||||
const char_u *p = q;
|
||||
while (ascii_isdigit(*p)) {
|
||||
// skip to next non-digit
|
||||
p++;
|
||||
}
|
||||
return p;
|
||||
return (char_u *)p;
|
||||
}
|
||||
|
||||
/// skip over binary digits
|
||||
|
@ -1551,17 +1567,17 @@ int vim_tolower(int c)
|
|||
return TOLOWER_LOC(c);
|
||||
}
|
||||
|
||||
/// skiptowhite: skip over text until ' ' or '\t' or NUL.
|
||||
/// Skip over text until ' ' or '\t' or NUL
|
||||
///
|
||||
/// @param p
|
||||
/// @param[in] p Text to skip over.
|
||||
///
|
||||
/// @return Pointer to the next whitespace or NUL character.
|
||||
char_u* skiptowhite(char_u *p)
|
||||
char_u *skiptowhite(const char_u *p)
|
||||
{
|
||||
while (*p != ' ' && *p != '\t' && *p != NUL) {
|
||||
p++;
|
||||
}
|
||||
return p;
|
||||
return (char_u *)p;
|
||||
}
|
||||
|
||||
/// skiptowhite_esc: Like skiptowhite(), but also skip escaped chars
|
||||
|
|
|
@ -1,6 +1,20 @@
|
|||
#ifndef NVIM_CHARSET_H
|
||||
#define NVIM_CHARSET_H
|
||||
|
||||
#include "nvim/types.h"
|
||||
#include "nvim/pos.h"
|
||||
#include "nvim/buffer_defs.h"
|
||||
|
||||
/// Return the folded-case equivalent of the given character
|
||||
///
|
||||
/// @param[in] c Character to transform.
|
||||
///
|
||||
/// @return Folded variant.
|
||||
#define CH_FOLD(c) \
|
||||
utf_fold((sizeof(c) == sizeof(char)) \
|
||||
?((int)(uint8_t)(c)) \
|
||||
:((int)(c)))
|
||||
|
||||
#ifdef INCLUDE_GENERATED_DECLARATIONS
|
||||
# include "charset.h.generated.h"
|
||||
#endif
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
#include "nvim/state.h"
|
||||
#include "nvim/vim.h"
|
||||
#include "nvim/ascii.h"
|
||||
#include "nvim/mark.h"
|
||||
|
||||
#ifdef INCLUDE_GENERATED_DECLARATIONS
|
||||
# include "cursor.c.generated.h"
|
||||
|
@ -227,9 +228,10 @@ static int coladvance2(
|
|||
}
|
||||
}
|
||||
|
||||
/* prevent from moving onto a trail byte */
|
||||
if (has_mbyte)
|
||||
mb_adjustpos(curbuf, pos);
|
||||
// Prevent from moving onto a trail byte.
|
||||
if (has_mbyte) {
|
||||
mark_mb_adjustpos(curbuf, pos);
|
||||
}
|
||||
|
||||
if (col < wcol)
|
||||
return FAIL;
|
||||
|
@ -361,9 +363,10 @@ void check_cursor_col_win(win_T *win)
|
|||
win->w_cursor.col = len;
|
||||
} else {
|
||||
win->w_cursor.col = len - 1;
|
||||
/* Move the cursor to the head byte. */
|
||||
if (has_mbyte)
|
||||
mb_adjustpos(win->w_buffer, &win->w_cursor);
|
||||
// Move the cursor to the head byte.
|
||||
if (has_mbyte) {
|
||||
mark_mb_adjustpos(win->w_buffer, &win->w_cursor);
|
||||
}
|
||||
}
|
||||
} else if (win->w_cursor.col < 0) {
|
||||
win->w_cursor.col = 0;
|
||||
|
|
|
@ -7,40 +7,74 @@
|
|||
#include "nvim/charset.h"
|
||||
#include "nvim/strings.h"
|
||||
#include "nvim/syntax.h"
|
||||
#include "nvim/api/private/helpers.h"
|
||||
#include "nvim/ui.h"
|
||||
|
||||
/*
|
||||
* Handling of cursor and mouse pointer shapes in various modes.
|
||||
*/
|
||||
|
||||
/// Handling of cursor and mouse pointer shapes in various modes.
|
||||
static cursorentry_T shape_table[SHAPE_IDX_COUNT] =
|
||||
{
|
||||
/* The values will be filled in from the 'guicursor' and 'mouseshape'
|
||||
* defaults when Vim starts.
|
||||
* Adjust the SHAPE_IDX_ defines when making changes! */
|
||||
{0, 0, 0, 700L, 400L, 250L, 0, 0, "n", SHAPE_CURSOR+SHAPE_MOUSE},
|
||||
{0, 0, 0, 700L, 400L, 250L, 0, 0, "v", SHAPE_CURSOR+SHAPE_MOUSE},
|
||||
{0, 0, 0, 700L, 400L, 250L, 0, 0, "i", SHAPE_CURSOR+SHAPE_MOUSE},
|
||||
{0, 0, 0, 700L, 400L, 250L, 0, 0, "r", SHAPE_CURSOR+SHAPE_MOUSE},
|
||||
{0, 0, 0, 700L, 400L, 250L, 0, 0, "c", SHAPE_CURSOR+SHAPE_MOUSE},
|
||||
{0, 0, 0, 700L, 400L, 250L, 0, 0, "ci", SHAPE_CURSOR+SHAPE_MOUSE},
|
||||
{0, 0, 0, 700L, 400L, 250L, 0, 0, "cr", SHAPE_CURSOR+SHAPE_MOUSE},
|
||||
{0, 0, 0, 700L, 400L, 250L, 0, 0, "o", SHAPE_CURSOR+SHAPE_MOUSE},
|
||||
{0, 0, 0, 700L, 400L, 250L, 0, 0, "ve", SHAPE_CURSOR+SHAPE_MOUSE},
|
||||
{0, 0, 0, 0L, 0L, 0L, 0, 0, "e", SHAPE_MOUSE},
|
||||
{0, 0, 0, 0L, 0L, 0L, 0, 0, "s", SHAPE_MOUSE},
|
||||
{0, 0, 0, 0L, 0L, 0L, 0, 0, "sd", SHAPE_MOUSE},
|
||||
{0, 0, 0, 0L, 0L, 0L, 0, 0, "vs", SHAPE_MOUSE},
|
||||
{0, 0, 0, 0L, 0L, 0L, 0, 0, "vd", SHAPE_MOUSE},
|
||||
{0, 0, 0, 0L, 0L, 0L, 0, 0, "m", SHAPE_MOUSE},
|
||||
{0, 0, 0, 0L, 0L, 0L, 0, 0, "ml", SHAPE_MOUSE},
|
||||
{0, 0, 0, 100L, 100L, 100L, 0, 0, "sm", SHAPE_CURSOR},
|
||||
// Values are set by 'guicursor' and 'mouseshape'.
|
||||
// Adjust the SHAPE_IDX_ defines when changing this!
|
||||
{ "normal", 0, 0, 0, 700L, 400L, 250L, 0, 0, "n", SHAPE_CURSOR+SHAPE_MOUSE },
|
||||
{ "visual", 0, 0, 0, 700L, 400L, 250L, 0, 0, "v", SHAPE_CURSOR+SHAPE_MOUSE },
|
||||
{ "insert", 0, 0, 0, 700L, 400L, 250L, 0, 0, "i", SHAPE_CURSOR+SHAPE_MOUSE },
|
||||
{ "replace", 0, 0, 0, 700L, 400L, 250L, 0, 0, "r", SHAPE_CURSOR+SHAPE_MOUSE },
|
||||
{ "cmdline_normal", 0, 0, 0, 700L, 400L, 250L, 0, 0, "c", SHAPE_CURSOR+SHAPE_MOUSE },
|
||||
{ "cmdline_insert", 0, 0, 0, 700L, 400L, 250L, 0, 0, "ci", SHAPE_CURSOR+SHAPE_MOUSE },
|
||||
{ "cmdline_replace", 0, 0, 0, 700L, 400L, 250L, 0, 0, "cr", SHAPE_CURSOR+SHAPE_MOUSE },
|
||||
{ "operator", 0, 0, 0, 700L, 400L, 250L, 0, 0, "o", SHAPE_CURSOR+SHAPE_MOUSE },
|
||||
{ "visual_select", 0, 0, 0, 700L, 400L, 250L, 0, 0, "ve", SHAPE_CURSOR+SHAPE_MOUSE },
|
||||
{ "cmdline_hover", 0, 0, 0, 0L, 0L, 0L, 0, 0, "e", SHAPE_MOUSE },
|
||||
{ "statusline_hover", 0, 0, 0, 0L, 0L, 0L, 0, 0, "s", SHAPE_MOUSE },
|
||||
{ "statusline_drag", 0, 0, 0, 0L, 0L, 0L, 0, 0, "sd", SHAPE_MOUSE },
|
||||
{ "vsep_hover", 0, 0, 0, 0L, 0L, 0L, 0, 0, "vs", SHAPE_MOUSE },
|
||||
{ "vsep_drag", 0, 0, 0, 0L, 0L, 0L, 0, 0, "vd", SHAPE_MOUSE },
|
||||
{ "more", 0, 0, 0, 0L, 0L, 0L, 0, 0, "m", SHAPE_MOUSE },
|
||||
{ "more_lastline", 0, 0, 0, 0L, 0L, 0L, 0, 0, "ml", SHAPE_MOUSE },
|
||||
{ "showmatch", 0, 0, 0, 100L, 100L, 100L, 0, 0, "sm", SHAPE_CURSOR },
|
||||
};
|
||||
|
||||
/*
|
||||
* Parse the 'guicursor' option ("what" is SHAPE_CURSOR) or 'mouseshape'
|
||||
* ("what" is SHAPE_MOUSE).
|
||||
* Returns error message for an illegal option, NULL otherwise.
|
||||
*/
|
||||
/// Converts cursor_shapes into a Dictionary of dictionaries
|
||||
/// @return dictionary of the form {"normal" : { "cursor_shape": ... }, ...}
|
||||
Dictionary cursor_shape_dict(void)
|
||||
{
|
||||
Dictionary all = ARRAY_DICT_INIT;
|
||||
|
||||
for (int i = 0; i < SHAPE_IDX_COUNT; i++) {
|
||||
Dictionary dic = ARRAY_DICT_INIT;
|
||||
cursorentry_T *cur = &shape_table[i];
|
||||
if (cur->used_for & SHAPE_MOUSE) {
|
||||
PUT(dic, "mouse_shape", INTEGER_OBJ(cur->mshape));
|
||||
}
|
||||
if (cur->used_for & SHAPE_CURSOR) {
|
||||
String shape_str;
|
||||
switch (cur->shape) {
|
||||
case SHAPE_BLOCK: shape_str = cstr_to_string("block"); break;
|
||||
case SHAPE_VER: shape_str = cstr_to_string("vertical"); break;
|
||||
case SHAPE_HOR: shape_str = cstr_to_string("horizontal"); break;
|
||||
default: shape_str = cstr_to_string("unknown");
|
||||
}
|
||||
PUT(dic, "cursor_shape", STRING_OBJ(shape_str));
|
||||
PUT(dic, "cell_percentage", INTEGER_OBJ(cur->percentage));
|
||||
PUT(dic, "blinkwait", INTEGER_OBJ(cur->blinkwait));
|
||||
PUT(dic, "blinkon", INTEGER_OBJ(cur->blinkon));
|
||||
PUT(dic, "blinkoff", INTEGER_OBJ(cur->blinkoff));
|
||||
PUT(dic, "hl_id", INTEGER_OBJ(cur->id));
|
||||
PUT(dic, "id_lm", INTEGER_OBJ(cur->id_lm));
|
||||
}
|
||||
PUT(dic, "short_name", STRING_OBJ(cstr_to_string(cur->name)));
|
||||
|
||||
PUT(all, cur->full_name, DICTIONARY_OBJ(dic));
|
||||
}
|
||||
|
||||
return all;
|
||||
}
|
||||
|
||||
/// Parse the 'guicursor' option
|
||||
///
|
||||
/// @param what SHAPE_CURSOR or SHAPE_MOUSE ('mouseshape')
|
||||
///
|
||||
/// @returns error message for an illegal option, NULL otherwise.
|
||||
char_u *parse_shape_opt(int what)
|
||||
{
|
||||
char_u *modep;
|
||||
|
@ -55,14 +89,13 @@ char_u *parse_shape_opt(int what)
|
|||
int found_ve = false; /* found "ve" flag */
|
||||
int round;
|
||||
|
||||
/*
|
||||
* First round: check for errors; second round: do it for real.
|
||||
*/
|
||||
for (round = 1; round <= 2; ++round) {
|
||||
/*
|
||||
* Repeat for all comma separated parts.
|
||||
*/
|
||||
// First round: check for errors; second round: do it for real.
|
||||
for (round = 1; round <= 2; round++) {
|
||||
// Repeat for all comma separated parts.
|
||||
modep = p_guicursor;
|
||||
if (*p_guicursor == NUL) {
|
||||
modep = (char_u *)"a:block-blinkon0";
|
||||
}
|
||||
while (*modep != NUL) {
|
||||
colonp = vim_strchr(modep, ':');
|
||||
if (colonp == NULL)
|
||||
|
@ -71,19 +104,18 @@ char_u *parse_shape_opt(int what)
|
|||
return (char_u *)N_("E546: Illegal mode");
|
||||
commap = vim_strchr(modep, ',');
|
||||
|
||||
/*
|
||||
* Repeat for all mode's before the colon.
|
||||
* For the 'a' mode, we loop to handle all the modes.
|
||||
*/
|
||||
// Repeat for all modes before the colon.
|
||||
// For the 'a' mode, we loop to handle all the modes.
|
||||
all_idx = -1;
|
||||
assert(modep < colonp);
|
||||
while (modep < colonp || all_idx >= 0) {
|
||||
if (all_idx < 0) {
|
||||
/* Find the mode. */
|
||||
if (modep[1] == '-' || modep[1] == ':')
|
||||
// Find the mode
|
||||
if (modep[1] == '-' || modep[1] == ':') {
|
||||
len = 1;
|
||||
else
|
||||
} else {
|
||||
len = 2;
|
||||
}
|
||||
|
||||
if (len == 1 && TOLOWER_ASC(modep[0]) == 'a') {
|
||||
all_idx = SHAPE_IDX_COUNT - 1;
|
||||
|
@ -100,11 +132,11 @@ char_u *parse_shape_opt(int what)
|
|||
modep += len + 1;
|
||||
}
|
||||
|
||||
if (all_idx >= 0)
|
||||
if (all_idx >= 0) {
|
||||
idx = all_idx--;
|
||||
else if (round == 2) {
|
||||
} else if (round == 2) {
|
||||
{
|
||||
/* Set the defaults, for the missing parts */
|
||||
// Set the defaults, for the missing parts
|
||||
shape_table[idx].shape = SHAPE_BLOCK;
|
||||
shape_table[idx].blinkwait = 700L;
|
||||
shape_table[idx].blinkon = 400L;
|
||||
|
@ -208,6 +240,23 @@ char_u *parse_shape_opt(int what)
|
|||
shape_table[SHAPE_IDX_VE].id_lm = shape_table[SHAPE_IDX_V].id_lm;
|
||||
}
|
||||
}
|
||||
|
||||
ui_cursor_style_set();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/// Map cursor mode from string to integer
|
||||
///
|
||||
/// @param mode Fullname of the mode whose id we are looking for
|
||||
/// @return -1 in case of failure, else the matching SHAPE_ID* integer
|
||||
int cursor_mode_str2int(const char *mode)
|
||||
{
|
||||
for (int current_mode = 0; current_mode < SHAPE_IDX_COUNT; current_mode++) {
|
||||
if (strcmp(shape_table[current_mode].full_name, mode) == 0) {
|
||||
return current_mode;
|
||||
}
|
||||
}
|
||||
ELOG("Unknown mode %s", mode);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,32 +1,34 @@
|
|||
#ifndef NVIM_CURSOR_SHAPE_H
|
||||
#define NVIM_CURSOR_SHAPE_H
|
||||
|
||||
/*
|
||||
* struct to store values from 'guicursor' and 'mouseshape'
|
||||
*/
|
||||
/* Indexes in shape_table[] */
|
||||
#define SHAPE_IDX_N 0 /* Normal mode */
|
||||
#define SHAPE_IDX_V 1 /* Visual mode */
|
||||
#define SHAPE_IDX_I 2 /* Insert mode */
|
||||
#define SHAPE_IDX_R 3 /* Replace mode */
|
||||
#define SHAPE_IDX_C 4 /* Command line Normal mode */
|
||||
#define SHAPE_IDX_CI 5 /* Command line Insert mode */
|
||||
#define SHAPE_IDX_CR 6 /* Command line Replace mode */
|
||||
#define SHAPE_IDX_O 7 /* Operator-pending mode */
|
||||
#define SHAPE_IDX_VE 8 /* Visual mode with 'selection' exclusive */
|
||||
#define SHAPE_IDX_CLINE 9 /* On command line */
|
||||
#define SHAPE_IDX_STATUS 10 /* A status line */
|
||||
#define SHAPE_IDX_SDRAG 11 /* dragging a status line */
|
||||
#define SHAPE_IDX_VSEP 12 /* A vertical separator line */
|
||||
#define SHAPE_IDX_VDRAG 13 /* dragging a vertical separator line */
|
||||
#define SHAPE_IDX_MORE 14 /* Hit-return or More */
|
||||
#define SHAPE_IDX_MOREL 15 /* Hit-return or More in last line */
|
||||
#define SHAPE_IDX_SM 16 /* showing matching paren */
|
||||
#define SHAPE_IDX_COUNT 17
|
||||
/// struct to store values from 'guicursor' and 'mouseshape'
|
||||
/// Indexes in shape_table[]
|
||||
typedef enum {
|
||||
SHAPE_IDX_N = 0, ///< Normal mode
|
||||
SHAPE_IDX_V = 1, ///< Visual mode
|
||||
SHAPE_IDX_I = 2, ///< Insert mode
|
||||
SHAPE_IDX_R = 3, ///< Replace mode
|
||||
SHAPE_IDX_C = 4, ///< Command line Normal mode
|
||||
SHAPE_IDX_CI = 5, ///< Command line Insert mode
|
||||
SHAPE_IDX_CR = 6, ///< Command line Replace mode
|
||||
SHAPE_IDX_O = 7, ///< Operator-pending mode
|
||||
SHAPE_IDX_VE = 8, ///< Visual mode with 'selection' exclusive
|
||||
SHAPE_IDX_CLINE = 9, ///< On command line
|
||||
SHAPE_IDX_STATUS = 10, ///< On status line
|
||||
SHAPE_IDX_SDRAG = 11, ///< dragging a status line
|
||||
SHAPE_IDX_VSEP = 12, ///< On vertical separator line
|
||||
SHAPE_IDX_VDRAG = 13, ///< dragging a vertical separator line
|
||||
SHAPE_IDX_MORE = 14, ///< Hit-return or More
|
||||
SHAPE_IDX_MOREL = 15, ///< Hit-return or More in last line
|
||||
SHAPE_IDX_SM = 16, ///< showing matching paren
|
||||
SHAPE_IDX_COUNT = 17
|
||||
} MouseMode;
|
||||
|
||||
#define SHAPE_BLOCK 0 /* block cursor */
|
||||
#define SHAPE_HOR 1 /* horizontal bar cursor */
|
||||
#define SHAPE_VER 2 /* vertical bar cursor */
|
||||
typedef enum {
|
||||
SHAPE_BLOCK = 0, ///< block cursor
|
||||
SHAPE_HOR = 1, ///< horizontal bar cursor
|
||||
SHAPE_VER = 2 ///< vertical bar cursor
|
||||
} CursorShape;
|
||||
|
||||
#define MSHAPE_NUMBERED 1000 /* offset for shapes identified by number */
|
||||
#define MSHAPE_HIDE 1 /* hide mouse pointer */
|
||||
|
@ -35,16 +37,17 @@
|
|||
#define SHAPE_CURSOR 2 /* used for text cursor shape */
|
||||
|
||||
typedef struct cursor_entry {
|
||||
int shape; /* one of the SHAPE_ defines */
|
||||
int mshape; /* one of the MSHAPE defines */
|
||||
int percentage; /* percentage of cell for bar */
|
||||
long blinkwait; /* blinking, wait time before blinking starts */
|
||||
long blinkon; /* blinking, on time */
|
||||
long blinkoff; /* blinking, off time */
|
||||
int id; /* highlight group ID */
|
||||
int id_lm; /* highlight group ID for :lmap mode */
|
||||
char *name; /* mode name (fixed) */
|
||||
char used_for; /* SHAPE_MOUSE and/or SHAPE_CURSOR */
|
||||
char *full_name; ///< mode description
|
||||
CursorShape shape; ///< cursor shape: one of the SHAPE_ defines
|
||||
int mshape; ///< mouse shape: one of the MSHAPE defines
|
||||
int percentage; ///< percentage of cell for bar
|
||||
long blinkwait; ///< blinking, wait time before blinking starts
|
||||
long blinkon; ///< blinking, on time
|
||||
long blinkoff; ///< blinking, off time
|
||||
int id; ///< highlight group ID
|
||||
int id_lm; ///< highlight group ID for :lmap mode
|
||||
char *name; ///< mode short name
|
||||
char used_for; ///< SHAPE_MOUSE and/or SHAPE_CURSOR
|
||||
} cursorentry_T;
|
||||
|
||||
|
||||
|
|
|
@ -1586,7 +1586,7 @@ static int diff_cmp(char_u *s1, char_u *s2)
|
|||
}
|
||||
|
||||
if ((diff_flags & DIFF_ICASE) && !(diff_flags & DIFF_IWHITE)) {
|
||||
return mb_stricmp(s1, s2);
|
||||
return mb_stricmp((const char *)s1, (const char *)s2);
|
||||
}
|
||||
|
||||
// Ignore white space changes and possibly ignore case.
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
#ifndef NVIM_DIFF_H
|
||||
#define NVIM_DIFF_H
|
||||
|
||||
#include "nvim/pos.h"
|
||||
#include "nvim/ex_cmds_defs.h"
|
||||
|
||||
#ifdef INCLUDE_GENERATED_DECLARATIONS
|
||||
# include "diff.h.generated.h"
|
||||
#endif
|
||||
|
|
435
src/nvim/edit.c
435
src/nvim/edit.c
|
@ -15,6 +15,7 @@
|
|||
#include "nvim/cursor.h"
|
||||
#include "nvim/digraph.h"
|
||||
#include "nvim/eval.h"
|
||||
#include "nvim/eval/typval.h"
|
||||
#include "nvim/ex_docmd.h"
|
||||
#include "nvim/ex_getln.h"
|
||||
#include "nvim/farsi.h"
|
||||
|
@ -1422,7 +1423,7 @@ static void ins_ctrl_v(void)
|
|||
edit_putchar('^', TRUE);
|
||||
did_putchar = TRUE;
|
||||
}
|
||||
AppendToRedobuff((char_u *)CTRL_V_STR); /* CTRL-V */
|
||||
AppendToRedobuff(CTRL_V_STR);
|
||||
|
||||
add_to_showcmd_c(Ctrl_V);
|
||||
|
||||
|
@ -1976,7 +1977,6 @@ static bool ins_compl_accept_char(int c)
|
|||
*/
|
||||
int ins_compl_add_infercase(char_u *str, int len, int icase, char_u *fname, int dir, int flags)
|
||||
{
|
||||
char_u *p;
|
||||
int i, c;
|
||||
int actual_len; /* Take multi-byte characters */
|
||||
int actual_compl_length; /* into account. */
|
||||
|
@ -1986,11 +1986,11 @@ int ins_compl_add_infercase(char_u *str, int len, int icase, char_u *fname, int
|
|||
int was_letter = FALSE;
|
||||
|
||||
if (p_ic && curbuf->b_p_inf && len > 0) {
|
||||
/* Infer case of completed part. */
|
||||
// Infer case of completed part.
|
||||
|
||||
/* Find actual length of completion. */
|
||||
// Find actual length of completion.
|
||||
if (has_mbyte) {
|
||||
p = str;
|
||||
const char_u *p = str;
|
||||
actual_len = 0;
|
||||
while (*p != NUL) {
|
||||
mb_ptr_adv(p);
|
||||
|
@ -2001,7 +2001,7 @@ int ins_compl_add_infercase(char_u *str, int len, int icase, char_u *fname, int
|
|||
|
||||
/* Find actual length of original text. */
|
||||
if (has_mbyte) {
|
||||
p = compl_orig_text;
|
||||
const char_u *p = compl_orig_text;
|
||||
actual_compl_length = 0;
|
||||
while (*p != NUL) {
|
||||
mb_ptr_adv(p);
|
||||
|
@ -2017,27 +2017,35 @@ int ins_compl_add_infercase(char_u *str, int len, int icase, char_u *fname, int
|
|||
|
||||
/* Allocate wide character array for the completion and fill it. */
|
||||
wca = xmalloc(actual_len * sizeof(*wca));
|
||||
p = str;
|
||||
for (i = 0; i < actual_len; ++i)
|
||||
if (has_mbyte)
|
||||
wca[i] = mb_ptr2char_adv(&p);
|
||||
else
|
||||
wca[i] = *(p++);
|
||||
{
|
||||
const char_u *p = str;
|
||||
for (i = 0; i < actual_len; i++) {
|
||||
if (has_mbyte) {
|
||||
wca[i] = mb_ptr2char_adv(&p);
|
||||
} else {
|
||||
wca[i] = *(p++);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Rule 1: Were any chars converted to lower? */
|
||||
p = compl_orig_text;
|
||||
for (i = 0; i < min_len; ++i) {
|
||||
if (has_mbyte)
|
||||
c = mb_ptr2char_adv(&p);
|
||||
else
|
||||
c = *(p++);
|
||||
if (vim_islower(c)) {
|
||||
has_lower = TRUE;
|
||||
if (vim_isupper(wca[i])) {
|
||||
/* Rule 1 is satisfied. */
|
||||
for (i = actual_compl_length; i < actual_len; ++i)
|
||||
wca[i] = vim_tolower(wca[i]);
|
||||
break;
|
||||
// Rule 1: Were any chars converted to lower?
|
||||
{
|
||||
const char_u *p = compl_orig_text;
|
||||
for (i = 0; i < min_len; i++) {
|
||||
if (has_mbyte) {
|
||||
c = mb_ptr2char_adv(&p);
|
||||
} else {
|
||||
c = *(p++);
|
||||
}
|
||||
if (vim_islower(c)) {
|
||||
has_lower = true;
|
||||
if (vim_isupper(wca[i])) {
|
||||
// Rule 1 is satisfied.
|
||||
for (i = actual_compl_length; i < actual_len; i++) {
|
||||
wca[i] = vim_tolower(wca[i]);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2047,84 +2055,110 @@ int ins_compl_add_infercase(char_u *str, int len, int icase, char_u *fname, int
|
|||
* upper case.
|
||||
*/
|
||||
if (!has_lower) {
|
||||
p = compl_orig_text;
|
||||
for (i = 0; i < min_len; ++i) {
|
||||
if (has_mbyte)
|
||||
const char_u *p = compl_orig_text;
|
||||
for (i = 0; i < min_len; i++) {
|
||||
if (has_mbyte) {
|
||||
c = mb_ptr2char_adv(&p);
|
||||
else
|
||||
} else {
|
||||
c = *(p++);
|
||||
}
|
||||
if (was_letter && vim_isupper(c) && vim_islower(wca[i])) {
|
||||
/* Rule 2 is satisfied. */
|
||||
for (i = actual_compl_length; i < actual_len; ++i)
|
||||
// Rule 2 is satisfied.
|
||||
for (i = actual_compl_length; i < actual_len; i++) {
|
||||
wca[i] = vim_toupper(wca[i]);
|
||||
}
|
||||
break;
|
||||
}
|
||||
was_letter = vim_islower(c) || vim_isupper(c);
|
||||
}
|
||||
}
|
||||
|
||||
/* Copy the original case of the part we typed. */
|
||||
p = compl_orig_text;
|
||||
for (i = 0; i < min_len; ++i) {
|
||||
if (has_mbyte)
|
||||
c = mb_ptr2char_adv(&p);
|
||||
else
|
||||
c = *(p++);
|
||||
if (vim_islower(c))
|
||||
wca[i] = vim_tolower(wca[i]);
|
||||
else if (vim_isupper(c))
|
||||
wca[i] = vim_toupper(wca[i]);
|
||||
// Copy the original case of the part we typed.
|
||||
{
|
||||
const char_u *p = compl_orig_text;
|
||||
for (i = 0; i < min_len; i++) {
|
||||
if (has_mbyte) {
|
||||
c = mb_ptr2char_adv(&p);
|
||||
} else {
|
||||
c = *(p++);
|
||||
}
|
||||
if (vim_islower(c)) {
|
||||
wca[i] = vim_tolower(wca[i]);
|
||||
} else if (vim_isupper(c)) {
|
||||
wca[i] = vim_toupper(wca[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Generate encoding specific output from wide character array.
|
||||
* Multi-byte characters can occupy up to five bytes more than
|
||||
* ASCII characters, and we also need one byte for NUL, so stay
|
||||
* six bytes away from the edge of IObuff.
|
||||
*/
|
||||
p = IObuff;
|
||||
i = 0;
|
||||
while (i < actual_len && (p - IObuff + 6) < IOSIZE)
|
||||
if (has_mbyte)
|
||||
p += (*mb_char2bytes)(wca[i++], p);
|
||||
else
|
||||
*(p++) = wca[i++];
|
||||
*p = NUL;
|
||||
// Generate encoding specific output from wide character array.
|
||||
// Multi-byte characters can occupy up to five bytes more than
|
||||
// ASCII characters, and we also need one byte for NUL, so stay
|
||||
// six bytes away from the edge of IObuff.
|
||||
{
|
||||
char_u *p = IObuff;
|
||||
i = 0;
|
||||
while (i < actual_len && (p - IObuff + 6) < IOSIZE) {
|
||||
if (has_mbyte) {
|
||||
p += (*mb_char2bytes)(wca[i++], p);
|
||||
} else {
|
||||
*(p++) = wca[i++];
|
||||
}
|
||||
}
|
||||
*p = NUL;
|
||||
}
|
||||
|
||||
xfree(wca);
|
||||
|
||||
return ins_compl_add(IObuff, len, icase, fname, NULL, dir,
|
||||
flags, FALSE);
|
||||
return ins_compl_add(IObuff, len, icase, fname, NULL, false, dir, flags,
|
||||
false);
|
||||
}
|
||||
return ins_compl_add(str, len, icase, fname, NULL, dir, flags, FALSE);
|
||||
return ins_compl_add(str, len, icase, fname, NULL, false, dir, flags, false);
|
||||
}
|
||||
|
||||
/*
|
||||
* Add a match to the list of matches.
|
||||
* If the given string is already in the list of completions, then return
|
||||
* NOTDONE, otherwise add it to the list and return OK. If there is an error
|
||||
* then FAIL is returned.
|
||||
*/
|
||||
static int
|
||||
ins_compl_add (
|
||||
char_u *str,
|
||||
int len,
|
||||
int icase,
|
||||
char_u *fname,
|
||||
char_u **cptext, /* extra text for popup menu or NULL */
|
||||
int cdir,
|
||||
int flags,
|
||||
int adup /* accept duplicate match */
|
||||
)
|
||||
/// Add a match to the list of matches
|
||||
///
|
||||
/// @param[in] str Match to add.
|
||||
/// @param[in] len Match length, -1 to use #STRLEN.
|
||||
/// @param[in] icase Whether case is to be ignored.
|
||||
/// @param[in] fname File name match comes from. May be NULL.
|
||||
/// @param[in] cptext Extra text for popup menu. May be NULL. If not NULL,
|
||||
/// must have exactly #CPT_COUNT items.
|
||||
/// @param[in] cptext_allocated If true, will not copy cptext strings.
|
||||
///
|
||||
/// @note Will free strings in case of error.
|
||||
/// cptext itself will not be freed.
|
||||
/// @param[in] cdir Completion direction.
|
||||
/// @param[in] adup True if duplicate matches are to be accepted.
|
||||
///
|
||||
/// @return NOTDONE if the given string is already in the list of completions,
|
||||
/// otherwise it is added to the list and OK is returned. FAIL will be
|
||||
/// returned in case of error.
|
||||
static int ins_compl_add(char_u *const str, int len,
|
||||
const bool icase, char_u *const fname,
|
||||
char_u *const *const cptext,
|
||||
const bool cptext_allocated,
|
||||
const Direction cdir, int flags, const bool adup)
|
||||
FUNC_ATTR_NONNULL_ARG(1)
|
||||
{
|
||||
compl_T *match;
|
||||
int dir = (cdir == 0 ? compl_direction : cdir);
|
||||
int dir = (cdir == kDirectionNotSet ? compl_direction : cdir);
|
||||
|
||||
os_breakcheck();
|
||||
if (got_int)
|
||||
#define FREE_CPTEXT(cptext, cptext_allocated) \
|
||||
do { \
|
||||
if (cptext != NULL && cptext_allocated) { \
|
||||
for (size_t i = 0; i < CPT_COUNT; i++) { \
|
||||
xfree(cptext[i]); \
|
||||
} \
|
||||
} \
|
||||
} while (0)
|
||||
if (got_int) {
|
||||
FREE_CPTEXT(cptext, cptext_allocated);
|
||||
return FAIL;
|
||||
if (len < 0)
|
||||
}
|
||||
if (len < 0) {
|
||||
len = (int)STRLEN(str);
|
||||
}
|
||||
|
||||
/*
|
||||
* If the same match is already present, don't add it.
|
||||
|
@ -2132,10 +2166,12 @@ ins_compl_add (
|
|||
if (compl_first_match != NULL && !adup) {
|
||||
match = compl_first_match;
|
||||
do {
|
||||
if ( !(match->cp_flags & ORIGINAL_TEXT)
|
||||
&& STRNCMP(match->cp_str, str, len) == 0
|
||||
&& match->cp_str[len] == NUL)
|
||||
if (!(match->cp_flags & ORIGINAL_TEXT)
|
||||
&& STRNCMP(match->cp_str, str, len) == 0
|
||||
&& match->cp_str[len] == NUL) {
|
||||
FREE_CPTEXT(cptext, cptext_allocated);
|
||||
return NOTDONE;
|
||||
}
|
||||
match = match->cp_next;
|
||||
} while (match != NULL && match != compl_first_match);
|
||||
}
|
||||
|
@ -2166,16 +2202,26 @@ ins_compl_add (
|
|||
else if (fname != NULL) {
|
||||
match->cp_fname = vim_strsave(fname);
|
||||
flags |= FREE_FNAME;
|
||||
} else
|
||||
} else {
|
||||
match->cp_fname = NULL;
|
||||
}
|
||||
match->cp_flags = flags;
|
||||
|
||||
if (cptext != NULL) {
|
||||
int i;
|
||||
|
||||
for (i = 0; i < CPT_COUNT; ++i)
|
||||
if (cptext[i] != NULL && *cptext[i] != NUL)
|
||||
match->cp_text[i] = vim_strsave(cptext[i]);
|
||||
for (i = 0; i < CPT_COUNT; i++) {
|
||||
if (cptext[i] == NULL) {
|
||||
continue;
|
||||
}
|
||||
if (*cptext[i] != NUL) {
|
||||
match->cp_text[i] = (cptext_allocated
|
||||
? cptext[i]
|
||||
: (char_u *)xstrdup((char *)cptext[i]));
|
||||
} else if (cptext_allocated) {
|
||||
xfree(cptext[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -2298,9 +2344,10 @@ static void ins_compl_add_matches(int num_matches, char_u **matches, int icase)
|
|||
|
||||
for (i = 0; i < num_matches && add_r != FAIL; i++)
|
||||
if ((add_r = ins_compl_add(matches[i], -1, icase,
|
||||
NULL, NULL, dir, 0, FALSE)) == OK)
|
||||
/* if dir was BACKWARD then honor it just once */
|
||||
NULL, NULL, false, dir, 0, false)) == OK) {
|
||||
// If dir was BACKWARD then honor it just once.
|
||||
dir = FORWARD;
|
||||
}
|
||||
FreeWild(num_matches, matches);
|
||||
}
|
||||
|
||||
|
@ -2364,8 +2411,8 @@ void set_completion(colnr_T startcol, list_T *list)
|
|||
/* compl_pattern doesn't need to be set */
|
||||
compl_orig_text = vim_strnsave(get_cursor_line_ptr() + compl_col,
|
||||
compl_length);
|
||||
if (ins_compl_add(compl_orig_text, -1, p_ic, NULL, NULL, 0,
|
||||
ORIGINAL_TEXT, FALSE) != OK) {
|
||||
if (ins_compl_add(compl_orig_text, -1, p_ic, NULL, NULL, false, 0,
|
||||
ORIGINAL_TEXT, false) != OK) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -2887,7 +2934,7 @@ static void ins_compl_clear(void)
|
|||
compl_orig_text = NULL;
|
||||
compl_enter_selects = FALSE;
|
||||
// clear v:completed_item
|
||||
set_vim_var_dict(VV_COMPLETED_ITEM, dict_alloc());
|
||||
set_vim_var_dict(VV_COMPLETED_ITEM, tv_dict_alloc());
|
||||
}
|
||||
|
||||
/// Check that Insert completion is active.
|
||||
|
@ -3432,7 +3479,6 @@ expand_by_function (
|
|||
{
|
||||
list_T *matchlist = NULL;
|
||||
dict_T *matchdict = NULL;
|
||||
char_u *args[2];
|
||||
char_u *funcname;
|
||||
pos_T pos;
|
||||
win_T *curwin_save;
|
||||
|
@ -3443,9 +3489,8 @@ expand_by_function (
|
|||
if (*funcname == NUL)
|
||||
return;
|
||||
|
||||
/* Call 'completefunc' to obtain the list of matches. */
|
||||
args[0] = (char_u *)"0";
|
||||
args[1] = base;
|
||||
// Call 'completefunc' to obtain the list of matches.
|
||||
const char_u *const args[2] = { (char_u *)"0", base };
|
||||
|
||||
pos = curwin->w_cursor;
|
||||
curwin_save = curwin;
|
||||
|
@ -3461,8 +3506,8 @@ expand_by_function (
|
|||
matchdict = rettv.vval.v_dict;
|
||||
break;
|
||||
default:
|
||||
/* TODO: Give error message? */
|
||||
clear_tv(&rettv);
|
||||
// TODO(brammool): Give error message?
|
||||
tv_clear(&rettv);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -3484,10 +3529,12 @@ expand_by_function (
|
|||
ins_compl_add_dict(matchdict);
|
||||
|
||||
theend:
|
||||
if (matchdict != NULL)
|
||||
dict_unref(matchdict);
|
||||
if (matchlist != NULL)
|
||||
list_unref(matchlist);
|
||||
if (matchdict != NULL) {
|
||||
tv_dict_unref(matchdict);
|
||||
}
|
||||
if (matchlist != NULL) {
|
||||
tv_list_unref(matchlist);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -3516,53 +3563,60 @@ static void ins_compl_add_dict(dict_T *dict)
|
|||
dictitem_T *di_refresh;
|
||||
dictitem_T *di_words;
|
||||
|
||||
/* Check for optional "refresh" item. */
|
||||
compl_opt_refresh_always = FALSE;
|
||||
di_refresh = dict_find(dict, (char_u *)"refresh", 7);
|
||||
// Check for optional "refresh" item.
|
||||
compl_opt_refresh_always = false;
|
||||
di_refresh = tv_dict_find(dict, S_LEN("refresh"));
|
||||
if (di_refresh != NULL && di_refresh->di_tv.v_type == VAR_STRING) {
|
||||
char_u *v = di_refresh->di_tv.vval.v_string;
|
||||
const char *v = (const char *)di_refresh->di_tv.vval.v_string;
|
||||
|
||||
if (v != NULL && STRCMP(v, (char_u *)"always") == 0)
|
||||
compl_opt_refresh_always = TRUE;
|
||||
if (v != NULL && strcmp(v, "always") == 0) {
|
||||
compl_opt_refresh_always = true;
|
||||
}
|
||||
}
|
||||
|
||||
/* Add completions from a "words" list. */
|
||||
di_words = dict_find(dict, (char_u *)"words", 5);
|
||||
if (di_words != NULL && di_words->di_tv.v_type == VAR_LIST)
|
||||
// Add completions from a "words" list.
|
||||
di_words = tv_dict_find(dict, S_LEN("words"));
|
||||
if (di_words != NULL && di_words->di_tv.v_type == VAR_LIST) {
|
||||
ins_compl_add_list(di_words->di_tv.vval.v_list);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Add a match to the list of matches from a typeval_T.
|
||||
* If the given string is already in the list of completions, then return
|
||||
* NOTDONE, otherwise add it to the list and return OK. If there is an error
|
||||
* then FAIL is returned.
|
||||
*/
|
||||
int ins_compl_add_tv(typval_T *tv, int dir)
|
||||
/// Add a match to the list of matches from VimL object
|
||||
///
|
||||
/// @param[in] tv Object to get matches from.
|
||||
/// @param[in] dir Completion direction.
|
||||
///
|
||||
/// @return NOTDONE if the given string is already in the list of completions,
|
||||
/// otherwise it is added to the list and OK is returned. FAIL will be
|
||||
/// returned in case of error.
|
||||
int ins_compl_add_tv(typval_T *const tv, const Direction dir)
|
||||
FUNC_ATTR_NONNULL_ALL
|
||||
{
|
||||
char_u *word;
|
||||
int icase = FALSE;
|
||||
int adup = FALSE;
|
||||
int aempty = FALSE;
|
||||
char_u *(cptext[CPT_COUNT]);
|
||||
const char *word;
|
||||
bool icase = false;
|
||||
bool adup = false;
|
||||
bool aempty = false;
|
||||
char *(cptext[CPT_COUNT]);
|
||||
|
||||
if (tv->v_type == VAR_DICT && tv->vval.v_dict != NULL) {
|
||||
word = get_dict_string(tv->vval.v_dict, "word", false);
|
||||
cptext[CPT_ABBR] = get_dict_string(tv->vval.v_dict, "abbr", false);
|
||||
cptext[CPT_MENU] = get_dict_string(tv->vval.v_dict, "menu", false);
|
||||
cptext[CPT_KIND] = get_dict_string(tv->vval.v_dict, "kind", false);
|
||||
cptext[CPT_INFO] = get_dict_string(tv->vval.v_dict, "info", false);
|
||||
word = tv_dict_get_string(tv->vval.v_dict, "word", false);
|
||||
cptext[CPT_ABBR] = tv_dict_get_string(tv->vval.v_dict, "abbr", true);
|
||||
cptext[CPT_MENU] = tv_dict_get_string(tv->vval.v_dict, "menu", true);
|
||||
cptext[CPT_KIND] = tv_dict_get_string(tv->vval.v_dict, "kind", true);
|
||||
cptext[CPT_INFO] = tv_dict_get_string(tv->vval.v_dict, "info", true);
|
||||
|
||||
icase = get_dict_number(tv->vval.v_dict, "icase");
|
||||
adup = get_dict_number(tv->vval.v_dict, "dup");
|
||||
aempty = get_dict_number(tv->vval.v_dict, "empty");
|
||||
icase = (bool)tv_dict_get_number(tv->vval.v_dict, "icase");
|
||||
adup = (bool)tv_dict_get_number(tv->vval.v_dict, "dup");
|
||||
aempty = (bool)tv_dict_get_number(tv->vval.v_dict, "empty");
|
||||
} else {
|
||||
word = get_tv_string_chk(tv);
|
||||
word = (const char *)tv_get_string_chk(tv);
|
||||
memset(cptext, 0, sizeof(cptext));
|
||||
}
|
||||
if (word == NULL || (!aempty && *word == NUL))
|
||||
if (word == NULL || (!aempty && *word == NUL)) {
|
||||
return FAIL;
|
||||
return ins_compl_add(word, -1, icase, NULL, cptext, dir, 0, adup);
|
||||
}
|
||||
return ins_compl_add((char_u *)word, -1, icase, NULL,
|
||||
(char_u **)cptext, true, dir, 0, adup);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -3977,7 +4031,7 @@ static void ins_compl_delete(void)
|
|||
// causes flicker, thus we can't do that.
|
||||
changed_cline_bef_curs();
|
||||
// clear v:completed_item
|
||||
set_vim_var_dict(VV_COMPLETED_ITEM, dict_alloc());
|
||||
set_vim_var_dict(VV_COMPLETED_ITEM, tv_dict_alloc());
|
||||
}
|
||||
|
||||
// Insert the new text being completed.
|
||||
|
@ -3992,17 +4046,21 @@ static void ins_compl_insert(int in_compl_func)
|
|||
|
||||
// Set completed item.
|
||||
// { word, abbr, menu, kind, info }
|
||||
dict_T *dict = dict_alloc();
|
||||
dict_add_nr_str(dict, "word", 0L,
|
||||
EMPTY_IF_NULL(compl_shown_match->cp_str));
|
||||
dict_add_nr_str(dict, "abbr", 0L,
|
||||
EMPTY_IF_NULL(compl_shown_match->cp_text[CPT_ABBR]));
|
||||
dict_add_nr_str(dict, "menu", 0L,
|
||||
EMPTY_IF_NULL(compl_shown_match->cp_text[CPT_MENU]));
|
||||
dict_add_nr_str(dict, "kind", 0L,
|
||||
EMPTY_IF_NULL(compl_shown_match->cp_text[CPT_KIND]));
|
||||
dict_add_nr_str(dict, "info", 0L,
|
||||
EMPTY_IF_NULL(compl_shown_match->cp_text[CPT_INFO]));
|
||||
dict_T *dict = tv_dict_alloc();
|
||||
tv_dict_add_str(dict, S_LEN("word"),
|
||||
(const char *)EMPTY_IF_NULL(compl_shown_match->cp_str));
|
||||
tv_dict_add_str(
|
||||
dict, S_LEN("abbr"),
|
||||
(const char *)EMPTY_IF_NULL(compl_shown_match->cp_text[CPT_ABBR]));
|
||||
tv_dict_add_str(
|
||||
dict, S_LEN("menu"),
|
||||
(const char *)EMPTY_IF_NULL(compl_shown_match->cp_text[CPT_MENU]));
|
||||
tv_dict_add_str(
|
||||
dict, S_LEN("kind"),
|
||||
(const char *)EMPTY_IF_NULL(compl_shown_match->cp_text[CPT_KIND]));
|
||||
tv_dict_add_str(
|
||||
dict, S_LEN("info"),
|
||||
(const char *)EMPTY_IF_NULL(compl_shown_match->cp_text[CPT_INFO]));
|
||||
set_vim_var_dict(VV_COMPLETED_ITEM, dict);
|
||||
if (!in_compl_func) {
|
||||
compl_curr_match = compl_shown_match;
|
||||
|
@ -4544,7 +4602,6 @@ static int ins_complete(int c, bool enable_pum)
|
|||
* Call user defined function 'completefunc' with "a:findstart"
|
||||
* set to 1 to obtain the length of text to use for completion.
|
||||
*/
|
||||
char_u *args[2];
|
||||
int col;
|
||||
char_u *funcname;
|
||||
pos_T pos;
|
||||
|
@ -4563,8 +4620,7 @@ static int ins_complete(int c, bool enable_pum)
|
|||
return FAIL;
|
||||
}
|
||||
|
||||
args[0] = (char_u *)"1";
|
||||
args[1] = NULL;
|
||||
const char_u *const args[2] = { (char_u *)"1", NULL };
|
||||
pos = curwin->w_cursor;
|
||||
curwin_save = curwin;
|
||||
curbuf_save = curbuf;
|
||||
|
@ -4664,8 +4720,8 @@ static int ins_complete(int c, bool enable_pum)
|
|||
/* Always add completion for the original text. */
|
||||
xfree(compl_orig_text);
|
||||
compl_orig_text = vim_strnsave(line + compl_col, compl_length);
|
||||
if (ins_compl_add(compl_orig_text, -1, p_ic, NULL, NULL, 0,
|
||||
ORIGINAL_TEXT, FALSE) != OK) {
|
||||
if (ins_compl_add(compl_orig_text, -1, p_ic, NULL, NULL, false, 0,
|
||||
ORIGINAL_TEXT, false) != OK) {
|
||||
xfree(compl_pattern);
|
||||
compl_pattern = NULL;
|
||||
xfree(compl_orig_text);
|
||||
|
@ -5744,15 +5800,16 @@ comp_textwidth (
|
|||
*/
|
||||
static void redo_literal(int c)
|
||||
{
|
||||
char_u buf[10];
|
||||
char buf[10];
|
||||
|
||||
/* Only digits need special treatment. Translate them into a string of
|
||||
* three digits. */
|
||||
// Only digits need special treatment. Translate them into a string of
|
||||
// three digits.
|
||||
if (ascii_isdigit(c)) {
|
||||
vim_snprintf((char *)buf, sizeof(buf), "%03d", c);
|
||||
vim_snprintf(buf, sizeof(buf), "%03d", c);
|
||||
AppendToRedobuff(buf);
|
||||
} else
|
||||
} else {
|
||||
AppendCharToRedobuff(c);
|
||||
}
|
||||
}
|
||||
|
||||
// start_arrow() is called when an arrow key is used in insert mode.
|
||||
|
@ -5781,8 +5838,8 @@ static void start_arrow_common(pos_T *end_insert_pos, bool end_change)
|
|||
{
|
||||
if (!arrow_used && end_change) { // something has been inserted
|
||||
AppendToRedobuff(ESC_STR);
|
||||
stop_insert(end_insert_pos, FALSE, FALSE);
|
||||
arrow_used = TRUE; /* this means we stopped the current insert */
|
||||
stop_insert(end_insert_pos, false, false);
|
||||
arrow_used = true; // This means we stopped the current insert.
|
||||
}
|
||||
check_spell_redraw();
|
||||
}
|
||||
|
@ -5839,7 +5896,7 @@ int stop_arrow(void)
|
|||
vr_lines_changed = 1;
|
||||
}
|
||||
ResetRedobuff();
|
||||
AppendToRedobuff((char_u *)"1i"); /* pretend we start an insertion */
|
||||
AppendToRedobuff("1i"); // Pretend we start an insertion.
|
||||
new_insert_skip = 2;
|
||||
} else if (ins_need_undo) {
|
||||
if (u_save_cursor() == OK)
|
||||
|
@ -6304,12 +6361,13 @@ stuff_inserted (
|
|||
}
|
||||
|
||||
do {
|
||||
stuffReadbuff(ptr);
|
||||
/* a trailing "0" is inserted as "<C-V>048", "^" as "<C-V>^" */
|
||||
if (last)
|
||||
stuffReadbuff((char_u *)(last == '0'
|
||||
? "\026\060\064\070"
|
||||
: "\026^"));
|
||||
stuffReadbuff((const char *)ptr);
|
||||
// A trailing "0" is inserted as "<C-V>048", "^" as "<C-V>^".
|
||||
if (last) {
|
||||
stuffReadbuff((last == '0'
|
||||
? "\026\060\064\070"
|
||||
: "\026^"));
|
||||
}
|
||||
} while (--count > 0);
|
||||
|
||||
if (last)
|
||||
|
@ -7066,8 +7124,8 @@ static void ins_ctrl_g(void)
|
|||
*/
|
||||
static void ins_ctrl_hat(void)
|
||||
{
|
||||
if (map_to_exists_mode((char_u *)"", LANGMAP, FALSE)) {
|
||||
/* ":lmap" mappings exists, Toggle use of ":lmap" mappings. */
|
||||
if (map_to_exists_mode("", LANGMAP, false)) {
|
||||
// ":lmap" mappings exists, Toggle use of ":lmap" mappings.
|
||||
if (State & LANGMAP) {
|
||||
curbuf->b_p_iminsert = B_IMODE_NONE;
|
||||
State &= ~LANGMAP;
|
||||
|
@ -7102,13 +7160,12 @@ static bool ins_esc(long *count, int cmdchar, bool nomove)
|
|||
disabled_redraw = false;
|
||||
}
|
||||
if (!arrow_used) {
|
||||
/*
|
||||
* Don't append the ESC for "r<CR>" and "grx".
|
||||
* When 'insertmode' is set only CTRL-L stops Insert mode. Needed for
|
||||
* when "count" is non-zero.
|
||||
*/
|
||||
if (cmdchar != 'r' && cmdchar != 'v')
|
||||
AppendToRedobuff(p_im ? (char_u *)"\014" : ESC_STR);
|
||||
// Don't append the ESC for "r<CR>" and "grx".
|
||||
// When 'insertmode' is set only CTRL-L stops Insert mode. Needed for
|
||||
// when "count" is non-zero.
|
||||
if (cmdchar != 'r' && cmdchar != 'v') {
|
||||
AppendToRedobuff(p_im ? "\014" : ESC_STR);
|
||||
}
|
||||
|
||||
/*
|
||||
* Repeating insert may take a long time. Check for
|
||||
|
@ -7262,7 +7319,8 @@ static bool ins_start_select(int c)
|
|||
// Execute the key in (insert) Select mode.
|
||||
stuffcharReadbuff(Ctrl_O);
|
||||
if (mod_mask) {
|
||||
char_u buf[4] = { K_SPECIAL, KS_MODIFIER, mod_mask, NUL };
|
||||
const char buf[] = { (char)K_SPECIAL, (char)KS_MODIFIER,
|
||||
(char)(uint8_t)mod_mask, NUL };
|
||||
stuffReadbuff(buf);
|
||||
}
|
||||
stuffcharReadbuff(c);
|
||||
|
@ -8070,11 +8128,11 @@ static bool ins_tab(void)
|
|||
return true;
|
||||
}
|
||||
|
||||
did_ai = FALSE;
|
||||
did_si = FALSE;
|
||||
can_si = FALSE;
|
||||
can_si_back = FALSE;
|
||||
AppendToRedobuff((char_u *)"\t");
|
||||
did_ai = false;
|
||||
did_si = false;
|
||||
can_si = false;
|
||||
can_si_back = false;
|
||||
AppendToRedobuff("\t");
|
||||
|
||||
if (p_sta && ind) { // insert tab in indent, use "shiftwidth"
|
||||
temp = get_sw_value(curbuf);
|
||||
|
@ -8339,8 +8397,8 @@ static int ins_digraph(void)
|
|||
edit_unputchar();
|
||||
}
|
||||
if (cc != ESC) {
|
||||
AppendToRedobuff((char_u *)CTRL_V_STR);
|
||||
c = getdigraph(c, cc, TRUE);
|
||||
AppendToRedobuff(CTRL_V_STR);
|
||||
c = getdigraph(c, cc, true);
|
||||
clear_showcmd();
|
||||
return c;
|
||||
}
|
||||
|
@ -8402,12 +8460,13 @@ static int ins_ctrl_ey(int tc)
|
|||
if (c != NUL) {
|
||||
long tw_save;
|
||||
|
||||
/* The character must be taken literally, insert like it
|
||||
* was typed after a CTRL-V, and pretend 'textwidth'
|
||||
* wasn't set. Digits, 'o' and 'x' are special after a
|
||||
* CTRL-V, don't use it for these. */
|
||||
if (c < 256 && !isalnum(c))
|
||||
AppendToRedobuff((char_u *)CTRL_V_STR); /* CTRL-V */
|
||||
// The character must be taken literally, insert like it
|
||||
// was typed after a CTRL-V, and pretend 'textwidth'
|
||||
// wasn't set. Digits, 'o' and 'x' are special after a
|
||||
// CTRL-V, don't use it for these.
|
||||
if (c < 256 && !isalnum(c)) {
|
||||
AppendToRedobuff(CTRL_V_STR);
|
||||
}
|
||||
tw_save = curbuf->b_p_tw;
|
||||
curbuf->b_p_tw = -1;
|
||||
insert_special(c, TRUE, FALSE);
|
||||
|
|
9387
src/nvim/eval.c
9387
src/nvim/eval.c
File diff suppressed because it is too large
Load Diff
|
@ -1,21 +1,23 @@
|
|||
#ifndef NVIM_EVAL_H
|
||||
#define NVIM_EVAL_H
|
||||
|
||||
#include "nvim/profile.h"
|
||||
#include "nvim/hashtab.h" // For hashtab_T
|
||||
#include "nvim/garray.h" // For garray_T
|
||||
#include "nvim/buffer_defs.h" // For scid_T
|
||||
#include "nvim/buffer_defs.h"
|
||||
#include "nvim/ex_cmds_defs.h" // For exarg_T
|
||||
#include "nvim/eval/typval.h"
|
||||
#include "nvim/profile.h"
|
||||
#include "nvim/garray.h"
|
||||
|
||||
#define COPYID_INC 2
|
||||
#define COPYID_MASK (~0x1)
|
||||
|
||||
// All user-defined functions are found in this hashtable.
|
||||
extern hashtab_T func_hashtab;
|
||||
|
||||
// From user function to hashitem and back.
|
||||
EXTERN ufunc_T dumuf;
|
||||
#define UF2HIKEY(fp) ((fp)->uf_name)
|
||||
#define HIKEY2UF(p) ((ufunc_T *)(p - (dumuf.uf_name - (char_u *)&dumuf)))
|
||||
#define HIKEY2UF(p) ((ufunc_T *)(p - offsetof(ufunc_T, uf_name)))
|
||||
#define HI2UF(hi) HIKEY2UF((hi)->hi_key)
|
||||
|
||||
/// Defines for Vim variables
|
||||
|
|
|
@ -2,10 +2,11 @@
|
|||
|
||||
#include <msgpack.h>
|
||||
|
||||
#include "nvim/eval_defs.h"
|
||||
#include "nvim/eval/typval.h"
|
||||
#include "nvim/eval.h"
|
||||
#include "nvim/eval/encode.h"
|
||||
#include "nvim/ascii.h"
|
||||
#include "nvim/macros.h"
|
||||
#include "nvim/message.h"
|
||||
#include "nvim/globals.h"
|
||||
#include "nvim/charset.h" // vim_str2nr
|
||||
|
@ -52,16 +53,16 @@ static inline void create_special_dict(typval_T *const rettv,
|
|||
typval_T val)
|
||||
FUNC_ATTR_NONNULL_ALL
|
||||
{
|
||||
dict_T *const dict = dict_alloc();
|
||||
dictitem_T *const type_di = dictitem_alloc((char_u *) "_TYPE");
|
||||
dict_T *const dict = tv_dict_alloc();
|
||||
dictitem_T *const type_di = tv_dict_item_alloc_len(S_LEN("_TYPE"));
|
||||
type_di->di_tv.v_type = VAR_LIST;
|
||||
type_di->di_tv.v_lock = VAR_UNLOCKED;
|
||||
type_di->di_tv.vval.v_list = (list_T *) eval_msgpack_type_lists[type];
|
||||
type_di->di_tv.vval.v_list->lv_refcount++;
|
||||
dict_add(dict, type_di);
|
||||
dictitem_T *const val_di = dictitem_alloc((char_u *) "_VAL");
|
||||
tv_dict_add(dict, type_di);
|
||||
dictitem_T *const val_di = tv_dict_item_alloc_len(S_LEN("_VAL"));
|
||||
val_di->di_tv = val;
|
||||
dict_add(dict, val_di);
|
||||
tv_dict_add(dict, val_di);
|
||||
dict->dv_refcount++;
|
||||
*rettv = (typval_T) {
|
||||
.v_type = VAR_DICT,
|
||||
|
@ -119,18 +120,18 @@ static inline int json_decoder_pop(ValuesStackItem obj,
|
|||
if (last_container.container.vval.v_list->lv_len != 0
|
||||
&& !obj.didcomma) {
|
||||
EMSG2(_("E474: Expected comma before list item: %s"), val_location);
|
||||
clear_tv(&obj.val);
|
||||
tv_clear(&obj.val);
|
||||
return FAIL;
|
||||
}
|
||||
assert(last_container.special_val == NULL);
|
||||
listitem_T *obj_li = listitem_alloc();
|
||||
listitem_T *obj_li = tv_list_item_alloc();
|
||||
obj_li->li_tv = obj.val;
|
||||
list_append(last_container.container.vval.v_list, obj_li);
|
||||
tv_list_append(last_container.container.vval.v_list, obj_li);
|
||||
} else if (last_container.stack_index == kv_size(*stack) - 2) {
|
||||
if (!obj.didcolon) {
|
||||
EMSG2(_("E474: Expected colon before dictionary value: %s"),
|
||||
val_location);
|
||||
clear_tv(&obj.val);
|
||||
tv_clear(&obj.val);
|
||||
return FAIL;
|
||||
}
|
||||
ValuesStackItem key = kv_pop(*stack);
|
||||
|
@ -139,34 +140,35 @@ static inline int json_decoder_pop(ValuesStackItem obj,
|
|||
assert(!(key.is_special_string
|
||||
|| key.val.vval.v_string == NULL
|
||||
|| *key.val.vval.v_string == NUL));
|
||||
dictitem_T *obj_di = dictitem_alloc(key.val.vval.v_string);
|
||||
clear_tv(&key.val);
|
||||
if (dict_add(last_container.container.vval.v_dict, obj_di)
|
||||
dictitem_T *const obj_di = tv_dict_item_alloc(
|
||||
(const char *)key.val.vval.v_string);
|
||||
tv_clear(&key.val);
|
||||
if (tv_dict_add(last_container.container.vval.v_dict, obj_di)
|
||||
== FAIL) {
|
||||
assert(false);
|
||||
}
|
||||
obj_di->di_tv = obj.val;
|
||||
} else {
|
||||
list_T *const kv_pair = list_alloc();
|
||||
list_append_list(last_container.special_val, kv_pair);
|
||||
listitem_T *const key_li = listitem_alloc();
|
||||
list_T *const kv_pair = tv_list_alloc();
|
||||
tv_list_append_list(last_container.special_val, kv_pair);
|
||||
listitem_T *const key_li = tv_list_item_alloc();
|
||||
key_li->li_tv = key.val;
|
||||
list_append(kv_pair, key_li);
|
||||
listitem_T *const val_li = listitem_alloc();
|
||||
tv_list_append(kv_pair, key_li);
|
||||
listitem_T *const val_li = tv_list_item_alloc();
|
||||
val_li->li_tv = obj.val;
|
||||
list_append(kv_pair, val_li);
|
||||
tv_list_append(kv_pair, val_li);
|
||||
}
|
||||
} else {
|
||||
// Object with key only
|
||||
if (!obj.is_special_string && obj.val.v_type != VAR_STRING) {
|
||||
EMSG2(_("E474: Expected string key: %s"), *pp);
|
||||
clear_tv(&obj.val);
|
||||
tv_clear(&obj.val);
|
||||
return FAIL;
|
||||
} else if (!obj.didcomma
|
||||
&& (last_container.special_val == NULL
|
||||
&& (DICT_LEN(last_container.container.vval.v_dict) != 0))) {
|
||||
EMSG2(_("E474: Expected comma before dictionary key: %s"), val_location);
|
||||
clear_tv(&obj.val);
|
||||
tv_clear(&obj.val);
|
||||
return FAIL;
|
||||
}
|
||||
// Handle empty key and key represented as special dictionary
|
||||
|
@ -174,16 +176,16 @@ static inline int json_decoder_pop(ValuesStackItem obj,
|
|||
&& (obj.is_special_string
|
||||
|| obj.val.vval.v_string == NULL
|
||||
|| *obj.val.vval.v_string == NUL
|
||||
|| dict_find(last_container.container.vval.v_dict,
|
||||
obj.val.vval.v_string, -1))) {
|
||||
clear_tv(&obj.val);
|
||||
|| tv_dict_find(last_container.container.vval.v_dict,
|
||||
(const char *)obj.val.vval.v_string, -1))) {
|
||||
tv_clear(&obj.val);
|
||||
|
||||
// Restart
|
||||
(void) kv_pop(*container_stack);
|
||||
ValuesStackItem last_container_val =
|
||||
kv_A(*stack, last_container.stack_index);
|
||||
while (kv_size(*stack) > last_container.stack_index) {
|
||||
clear_tv(&(kv_pop(*stack).val));
|
||||
tv_clear(&(kv_pop(*stack).val));
|
||||
}
|
||||
*pp = last_container.s;
|
||||
*didcomma = last_container_val.didcomma;
|
||||
|
@ -228,7 +230,7 @@ static inline int json_decoder_pop(ValuesStackItem obj,
|
|||
list_T *decode_create_map_special_dict(typval_T *const ret_tv)
|
||||
FUNC_ATTR_NONNULL_ALL
|
||||
{
|
||||
list_T *const list = list_alloc();
|
||||
list_T *const list = tv_list_alloc();
|
||||
list->lv_refcount++;
|
||||
create_special_dict(ret_tv, kMPMap, ((typval_T) {
|
||||
.v_type = VAR_LIST,
|
||||
|
@ -264,7 +266,7 @@ typval_T decode_string(const char *const s, const size_t len,
|
|||
? memchr(s, NUL, len) != NULL
|
||||
: (bool)hasnul);
|
||||
if (really_hasnul) {
|
||||
list_T *const list = list_alloc();
|
||||
list_T *const list = tv_list_alloc();
|
||||
list->lv_refcount++;
|
||||
typval_T tv;
|
||||
create_special_dict(&tv, binary ? kMPBinary : kMPString, ((typval_T) {
|
||||
|
@ -277,7 +279,7 @@ typval_T decode_string(const char *const s, const size_t len,
|
|||
xfree((void *)s);
|
||||
}
|
||||
if (elw_ret == -1) {
|
||||
clear_tv(&tv);
|
||||
tv_clear(&tv);
|
||||
return (typval_T) { .v_type = VAR_UNKNOWN, .v_lock = VAR_UNLOCKED };
|
||||
}
|
||||
return tv;
|
||||
|
@ -502,9 +504,8 @@ static inline int parse_json_string(vimconv_T *const conv,
|
|||
str_end = new_str + str_len;
|
||||
}
|
||||
*str_end = NUL;
|
||||
typval_T obj;
|
||||
obj = decode_string(str, (size_t)(str_end - str), hasnul ? kTrue : kFalse,
|
||||
false, true);
|
||||
typval_T obj = decode_string(
|
||||
str, (size_t)(str_end - str), hasnul ? kTrue : kFalse, false, true);
|
||||
if (obj.v_type == VAR_UNKNOWN) {
|
||||
goto parse_json_string_fail;
|
||||
}
|
||||
|
@ -864,7 +865,7 @@ json_decode_string_cycle_start:
|
|||
break;
|
||||
}
|
||||
case '[': {
|
||||
list_T *list = list_alloc();
|
||||
list_T *list = tv_list_alloc();
|
||||
list->lv_refcount++;
|
||||
typval_T tv = {
|
||||
.v_type = VAR_LIST,
|
||||
|
@ -887,7 +888,7 @@ json_decode_string_cycle_start:
|
|||
next_map_special = false;
|
||||
val_list = decode_create_map_special_dict(&tv);
|
||||
} else {
|
||||
dict_T *dict = dict_alloc();
|
||||
dict_T *dict = tv_dict_alloc();
|
||||
dict->dv_refcount++;
|
||||
tv = (typval_T) {
|
||||
.v_type = VAR_DICT,
|
||||
|
@ -939,7 +940,7 @@ json_decode_string_after_cycle:
|
|||
json_decode_string_fail:
|
||||
ret = FAIL;
|
||||
while (kv_size(stack)) {
|
||||
clear_tv(&(kv_pop(stack).val));
|
||||
tv_clear(&(kv_pop(stack).val));
|
||||
}
|
||||
json_decode_string_ret:
|
||||
kv_destroy(stack);
|
||||
|
@ -985,7 +986,7 @@ int msgpack_to_vim(const msgpack_object mobj, typval_T *const rettv)
|
|||
.vval = { .v_number = (varnumber_T) mobj.via.u64 },
|
||||
};
|
||||
} else {
|
||||
list_T *const list = list_alloc();
|
||||
list_T *const list = tv_list_alloc();
|
||||
list->lv_refcount++;
|
||||
create_special_dict(rettv, kMPInteger, ((typval_T) {
|
||||
.v_type = VAR_LIST,
|
||||
|
@ -993,10 +994,10 @@ int msgpack_to_vim(const msgpack_object mobj, typval_T *const rettv)
|
|||
.vval = { .v_list = list },
|
||||
}));
|
||||
uint64_t n = mobj.via.u64;
|
||||
list_append_number(list, 1);
|
||||
list_append_number(list, (varnumber_T) ((n >> 62) & 0x3));
|
||||
list_append_number(list, (varnumber_T) ((n >> 31) & 0x7FFFFFFF));
|
||||
list_append_number(list, (varnumber_T) (n & 0x7FFFFFFF));
|
||||
tv_list_append_number(list, 1);
|
||||
tv_list_append_number(list, (varnumber_T)((n >> 62) & 0x3));
|
||||
tv_list_append_number(list, (varnumber_T)((n >> 31) & 0x7FFFFFFF));
|
||||
tv_list_append_number(list, (varnumber_T)(n & 0x7FFFFFFF));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -1008,22 +1009,28 @@ int msgpack_to_vim(const msgpack_object mobj, typval_T *const rettv)
|
|||
.vval = { .v_number = (varnumber_T) mobj.via.i64 },
|
||||
};
|
||||
} else {
|
||||
list_T *const list = list_alloc();
|
||||
list_T *const list = tv_list_alloc();
|
||||
list->lv_refcount++;
|
||||
create_special_dict(rettv, kMPInteger, ((typval_T) {
|
||||
.v_type = VAR_LIST,
|
||||
.v_lock = VAR_UNLOCKED,
|
||||
.vval = { .v_list = list },
|
||||
}));
|
||||
uint64_t n = -((uint64_t) mobj.via.i64);
|
||||
list_append_number(list, -1);
|
||||
list_append_number(list, (varnumber_T) ((n >> 62) & 0x3));
|
||||
list_append_number(list, (varnumber_T) ((n >> 31) & 0x7FFFFFFF));
|
||||
list_append_number(list, (varnumber_T) (n & 0x7FFFFFFF));
|
||||
uint64_t n = -((uint64_t)mobj.via.i64);
|
||||
tv_list_append_number(list, -1);
|
||||
tv_list_append_number(list, (varnumber_T)((n >> 62) & 0x3));
|
||||
tv_list_append_number(list, (varnumber_T)((n >> 31) & 0x7FFFFFFF));
|
||||
tv_list_append_number(list, (varnumber_T)(n & 0x7FFFFFFF));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case MSGPACK_OBJECT_FLOAT: {
|
||||
#ifdef NVIM_MSGPACK_HAS_FLOAT32
|
||||
case MSGPACK_OBJECT_FLOAT32:
|
||||
case MSGPACK_OBJECT_FLOAT64:
|
||||
#else
|
||||
case MSGPACK_OBJECT_FLOAT:
|
||||
#endif
|
||||
{
|
||||
*rettv = (typval_T) {
|
||||
.v_type = VAR_FLOAT,
|
||||
.v_lock = VAR_UNLOCKED,
|
||||
|
@ -1048,7 +1055,7 @@ int msgpack_to_vim(const msgpack_object mobj, typval_T *const rettv)
|
|||
break;
|
||||
}
|
||||
case MSGPACK_OBJECT_ARRAY: {
|
||||
list_T *const list = list_alloc();
|
||||
list_T *const list = tv_list_alloc();
|
||||
list->lv_refcount++;
|
||||
*rettv = (typval_T) {
|
||||
.v_type = VAR_LIST,
|
||||
|
@ -1056,9 +1063,9 @@ int msgpack_to_vim(const msgpack_object mobj, typval_T *const rettv)
|
|||
.vval = { .v_list = list },
|
||||
};
|
||||
for (size_t i = 0; i < mobj.via.array.size; i++) {
|
||||
listitem_T *const li = listitem_alloc();
|
||||
listitem_T *const li = tv_list_item_alloc();
|
||||
li->li_tv.v_type = VAR_UNKNOWN;
|
||||
list_append(list, li);
|
||||
tv_list_append(list, li);
|
||||
if (msgpack_to_vim(mobj.via.array.ptr[i], &li->li_tv) == FAIL) {
|
||||
return FAIL;
|
||||
}
|
||||
|
@ -1074,7 +1081,7 @@ int msgpack_to_vim(const msgpack_object mobj, typval_T *const rettv)
|
|||
goto msgpack_to_vim_generic_map;
|
||||
}
|
||||
}
|
||||
dict_T *const dict = dict_alloc();
|
||||
dict_T *const dict = tv_dict_alloc();
|
||||
dict->dv_refcount++;
|
||||
*rettv = (typval_T) {
|
||||
.v_type = VAR_DICT,
|
||||
|
@ -1087,9 +1094,9 @@ int msgpack_to_vim(const msgpack_object mobj, typval_T *const rettv)
|
|||
memcpy(&di->di_key[0], mobj.via.map.ptr[i].key.via.str.ptr,
|
||||
mobj.via.map.ptr[i].key.via.str.size);
|
||||
di->di_tv.v_type = VAR_UNKNOWN;
|
||||
if (dict_add(dict, di) == FAIL) {
|
||||
if (tv_dict_add(dict, di) == FAIL) {
|
||||
// Duplicate key: fallback to generic map
|
||||
clear_tv(rettv);
|
||||
tv_clear(rettv);
|
||||
xfree(di);
|
||||
goto msgpack_to_vim_generic_map;
|
||||
}
|
||||
|
@ -1101,14 +1108,14 @@ int msgpack_to_vim(const msgpack_object mobj, typval_T *const rettv)
|
|||
msgpack_to_vim_generic_map: {}
|
||||
list_T *const list = decode_create_map_special_dict(rettv);
|
||||
for (size_t i = 0; i < mobj.via.map.size; i++) {
|
||||
list_T *const kv_pair = list_alloc();
|
||||
list_append_list(list, kv_pair);
|
||||
listitem_T *const key_li = listitem_alloc();
|
||||
list_T *const kv_pair = tv_list_alloc();
|
||||
tv_list_append_list(list, kv_pair);
|
||||
listitem_T *const key_li = tv_list_item_alloc();
|
||||
key_li->li_tv.v_type = VAR_UNKNOWN;
|
||||
list_append(kv_pair, key_li);
|
||||
listitem_T *const val_li = listitem_alloc();
|
||||
tv_list_append(kv_pair, key_li);
|
||||
listitem_T *const val_li = tv_list_item_alloc();
|
||||
val_li->li_tv.v_type = VAR_UNKNOWN;
|
||||
list_append(kv_pair, val_li);
|
||||
tv_list_append(kv_pair, val_li);
|
||||
if (msgpack_to_vim(mobj.via.map.ptr[i].key, &key_li->li_tv) == FAIL) {
|
||||
return FAIL;
|
||||
}
|
||||
|
@ -1119,11 +1126,11 @@ msgpack_to_vim_generic_map: {}
|
|||
break;
|
||||
}
|
||||
case MSGPACK_OBJECT_EXT: {
|
||||
list_T *const list = list_alloc();
|
||||
list_T *const list = tv_list_alloc();
|
||||
list->lv_refcount++;
|
||||
list_append_number(list, mobj.via.ext.type);
|
||||
list_T *const ext_val_list = list_alloc();
|
||||
list_append_list(list, ext_val_list);
|
||||
tv_list_append_number(list, mobj.via.ext.type);
|
||||
list_T *const ext_val_list = tv_list_alloc();
|
||||
tv_list_append_list(list, ext_val_list);
|
||||
create_special_dict(rettv, kMPExt, ((typval_T) {
|
||||
.v_type = VAR_LIST,
|
||||
.v_lock = VAR_UNLOCKED,
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
|
||||
#include <msgpack.h>
|
||||
|
||||
#include "nvim/eval_defs.h"
|
||||
#include "nvim/eval/typval.h"
|
||||
|
||||
#ifdef INCLUDE_GENERATED_DECLARATIONS
|
||||
# include "eval/decode.h.generated.h"
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
#include "nvim/eval/encode.h"
|
||||
#include "nvim/buffer_defs.h" // vimconv_T
|
||||
#include "nvim/eval.h"
|
||||
#include "nvim/eval_defs.h"
|
||||
#include "nvim/eval/typval.h"
|
||||
#include "nvim/garray.h"
|
||||
#include "nvim/mbyte.h"
|
||||
#include "nvim/message.h"
|
||||
|
@ -45,7 +45,8 @@ const char *const encode_special_var_names[] = {
|
|||
#endif
|
||||
|
||||
/// Msgpack callback for writing to readfile()-style list
|
||||
int encode_list_write(void *data, const char *buf, size_t len)
|
||||
int encode_list_write(void *const data, const char *const buf, const size_t len)
|
||||
FUNC_ATTR_NONNULL_ARG(1)
|
||||
{
|
||||
if (len == 0) {
|
||||
return 0;
|
||||
|
@ -80,11 +81,11 @@ int encode_list_write(void *data, const char *buf, size_t len)
|
|||
str = xmemdupz(line_start, line_length);
|
||||
memchrsub(str, NUL, NL, line_length);
|
||||
}
|
||||
list_append_allocated_string(list, str);
|
||||
tv_list_append_allocated_string(list, str);
|
||||
line_end++;
|
||||
}
|
||||
if (line_end == end) {
|
||||
list_append_allocated_string(list, NULL);
|
||||
tv_list_append_allocated_string(list, NULL);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -743,11 +744,11 @@ bool encode_check_json_key(const typval_T *const tv)
|
|||
}
|
||||
const dictitem_T *type_di;
|
||||
const dictitem_T *val_di;
|
||||
if ((type_di = dict_find((dict_T *) spdict, (char_u *) "_TYPE", -1)) == NULL
|
||||
if ((type_di = tv_dict_find(spdict, S_LEN("_TYPE"))) == NULL
|
||||
|| type_di->di_tv.v_type != VAR_LIST
|
||||
|| (type_di->di_tv.vval.v_list != eval_msgpack_type_lists[kMPString]
|
||||
&& type_di->di_tv.vval.v_list != eval_msgpack_type_lists[kMPBinary])
|
||||
|| (val_di = dict_find((dict_T *) spdict, (char_u *) "_VAL", -1)) == NULL
|
||||
|| (val_di = tv_dict_find(spdict, S_LEN("_VAL"))) == NULL
|
||||
|| val_di->di_tv.v_type != VAR_LIST) {
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,115 @@
|
|||
#include "nvim/eval/typval.h"
|
||||
#include "nvim/eval/executor.h"
|
||||
#include "nvim/eval.h"
|
||||
#include "nvim/message.h"
|
||||
#include "nvim/vim.h"
|
||||
#include "nvim/globals.h"
|
||||
|
||||
#ifdef INCLUDE_GENERATED_DECLARATIONS
|
||||
# include "eval/executor.c.generated.h"
|
||||
#endif
|
||||
|
||||
static char *e_letwrong = N_("E734: Wrong variable type for %s=");
|
||||
|
||||
char *e_listidx = N_("E684: list index out of range: %" PRId64);
|
||||
|
||||
/// Hanle tv1 += tv2, -=, .=
|
||||
///
|
||||
/// @param[in,out] tv1 First operand, modified typval.
|
||||
/// @param[in] tv2 Second operand.
|
||||
/// @param[in] op Used operator.
|
||||
///
|
||||
/// @return OK or FAIL.
|
||||
int eexe_mod_op(typval_T *const tv1, const typval_T *const tv2,
|
||||
const char *const op)
|
||||
FUNC_ATTR_NONNULL_ALL
|
||||
{
|
||||
// Can't do anything with a Funcref, a Dict or special value on the right.
|
||||
if (tv2->v_type != VAR_FUNC && tv2->v_type != VAR_DICT) {
|
||||
switch (tv1->v_type) {
|
||||
case VAR_DICT:
|
||||
case VAR_FUNC:
|
||||
case VAR_PARTIAL:
|
||||
case VAR_SPECIAL: {
|
||||
break;
|
||||
}
|
||||
case VAR_LIST: {
|
||||
if (*op != '+' || tv2->v_type != VAR_LIST) {
|
||||
break;
|
||||
}
|
||||
// List += List
|
||||
if (tv1->vval.v_list != NULL && tv2->vval.v_list != NULL) {
|
||||
tv_list_extend(tv1->vval.v_list, tv2->vval.v_list, NULL);
|
||||
}
|
||||
return OK;
|
||||
}
|
||||
case VAR_NUMBER:
|
||||
case VAR_STRING: {
|
||||
if (tv2->v_type == VAR_LIST) {
|
||||
break;
|
||||
}
|
||||
if (*op == '+' || *op == '-') {
|
||||
// nr += nr or nr -= nr
|
||||
varnumber_T n = tv_get_number(tv1);
|
||||
if (tv2->v_type == VAR_FLOAT) {
|
||||
float_T f = n;
|
||||
|
||||
if (*op == '+') {
|
||||
f += tv2->vval.v_float;
|
||||
} else {
|
||||
f -= tv2->vval.v_float;
|
||||
}
|
||||
tv_clear(tv1);
|
||||
tv1->v_type = VAR_FLOAT;
|
||||
tv1->vval.v_float = f;
|
||||
} else {
|
||||
if (*op == '+') {
|
||||
n += tv_get_number(tv2);
|
||||
} else {
|
||||
n -= tv_get_number(tv2);
|
||||
}
|
||||
tv_clear(tv1);
|
||||
tv1->v_type = VAR_NUMBER;
|
||||
tv1->vval.v_number = n;
|
||||
}
|
||||
} else {
|
||||
// str .= str
|
||||
if (tv2->v_type == VAR_FLOAT) {
|
||||
break;
|
||||
}
|
||||
const char *tvs = tv_get_string(tv1);
|
||||
char numbuf[NUMBUFLEN];
|
||||
char *const s = (char *)concat_str(
|
||||
(const char_u *)tvs, (const char_u *)tv_get_string_buf(tv2,
|
||||
numbuf));
|
||||
tv_clear(tv1);
|
||||
tv1->v_type = VAR_STRING;
|
||||
tv1->vval.v_string = (char_u *)s;
|
||||
}
|
||||
return OK;
|
||||
}
|
||||
case VAR_FLOAT: {
|
||||
if (*op == '.' || (tv2->v_type != VAR_FLOAT
|
||||
&& tv2->v_type != VAR_NUMBER
|
||||
&& tv2->v_type != VAR_STRING)) {
|
||||
break;
|
||||
}
|
||||
const float_T f = (tv2->v_type == VAR_FLOAT
|
||||
? tv2->vval.v_float
|
||||
: tv_get_number(tv2));
|
||||
if (*op == '+') {
|
||||
tv1->vval.v_float += f;
|
||||
} else {
|
||||
tv1->vval.v_float -= f;
|
||||
}
|
||||
return OK;
|
||||
}
|
||||
case VAR_UNKNOWN: {
|
||||
assert(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
EMSG2(_(e_letwrong), op);
|
||||
return FAIL;
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
#ifndef NVIM_EVAL_EXECUTOR_H
|
||||
#define NVIM_EVAL_EXECUTOR_H
|
||||
|
||||
#include "nvim/eval/typval.h"
|
||||
|
||||
extern char *e_listidx;
|
||||
|
||||
#ifdef INCLUDE_GENERATED_DECLARATIONS
|
||||
# include "eval/executor.h.generated.h"
|
||||
#endif
|
||||
#endif // NVIM_EVAL_EXECUTOR_H
|
|
@ -0,0 +1,11 @@
|
|||
#include "nvim/eval/typval.h"
|
||||
#include "nvim/eval/gc.h"
|
||||
|
||||
#ifdef INCLUDE_GENERATED_DECLARATIONS
|
||||
# include "eval/gc.c.generated.h"
|
||||
#endif
|
||||
|
||||
/// Head of list of all dictionaries
|
||||
dict_T *gc_first_dict = NULL;
|
||||
/// Head of list of all lists
|
||||
list_T *gc_first_list = NULL;
|
|
@ -0,0 +1,12 @@
|
|||
#ifndef NVIM_EVAL_GC_H
|
||||
#define NVIM_EVAL_GC_H
|
||||
|
||||
#include "nvim/eval/typval.h"
|
||||
|
||||
extern dict_T *gc_first_dict;
|
||||
extern list_T *gc_first_list;
|
||||
|
||||
#ifdef INCLUDE_GENERATED_DECLARATIONS
|
||||
# include "eval/gc.h.generated.h"
|
||||
#endif
|
||||
#endif // NVIM_EVAL_GC_H
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,429 @@
|
|||
#ifndef NVIM_EVAL_TYPVAL_H
|
||||
#define NVIM_EVAL_TYPVAL_H
|
||||
|
||||
#include <limits.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "nvim/types.h"
|
||||
#include "nvim/hashtab.h"
|
||||
#include "nvim/garray.h"
|
||||
#include "nvim/mbyte.h"
|
||||
#include "nvim/func_attr.h"
|
||||
#include "nvim/lib/queue.h"
|
||||
#include "nvim/profile.h" // for proftime_T
|
||||
#include "nvim/pos.h" // for linenr_T
|
||||
#include "nvim/gettext.h"
|
||||
#include "nvim/message.h"
|
||||
|
||||
/// Type used for VimL VAR_NUMBER values
|
||||
typedef int varnumber_T;
|
||||
|
||||
/// Type used for VimL VAR_FLOAT values
|
||||
typedef double float_T;
|
||||
|
||||
/// Maximal possible value of varnumber_T variable
|
||||
#define VARNUMBER_MAX INT_MAX
|
||||
|
||||
/// Mimimal possible value of varnumber_T variable
|
||||
#define VARNUMBER_MIN INT_MIN
|
||||
#define PRIdVARNUMBER "d"
|
||||
|
||||
/// %d printf format specifier for varnumber_T
|
||||
#define PRIdVARNUMBER "d"
|
||||
|
||||
typedef struct listvar_S list_T;
|
||||
typedef struct dictvar_S dict_T;
|
||||
typedef struct partial_S partial_T;
|
||||
|
||||
typedef struct ufunc ufunc_T;
|
||||
|
||||
typedef enum {
|
||||
kCallbackNone,
|
||||
kCallbackFuncref,
|
||||
kCallbackPartial,
|
||||
} CallbackType;
|
||||
|
||||
typedef struct {
|
||||
union {
|
||||
char_u *funcref;
|
||||
partial_T *partial;
|
||||
} data;
|
||||
CallbackType type;
|
||||
} Callback;
|
||||
#define CALLBACK_NONE ((Callback){ .type = kCallbackNone })
|
||||
|
||||
/// Structure holding dictionary watcher
|
||||
typedef struct dict_watcher {
|
||||
Callback callback;
|
||||
char *key_pattern;
|
||||
size_t key_pattern_len;
|
||||
QUEUE node;
|
||||
bool busy; // prevent recursion if the dict is changed in the callback
|
||||
} DictWatcher;
|
||||
|
||||
/// Special variable values
|
||||
typedef enum {
|
||||
kSpecialVarFalse, ///< v:false
|
||||
kSpecialVarTrue, ///< v:true
|
||||
kSpecialVarNull, ///< v:null
|
||||
} SpecialVarValue;
|
||||
|
||||
/// Variable lock status for typval_T.v_lock
|
||||
typedef enum {
|
||||
VAR_UNLOCKED = 0, ///< Not locked.
|
||||
VAR_LOCKED = 1, ///< User lock, can be unlocked.
|
||||
VAR_FIXED = 2, ///< Locked forever.
|
||||
} VarLockStatus;
|
||||
|
||||
/// VimL variable types, for use in typval_T.v_type
|
||||
typedef enum {
|
||||
VAR_UNKNOWN = 0, ///< Unknown (unspecified) value.
|
||||
VAR_NUMBER, ///< Number, .v_number is used.
|
||||
VAR_STRING, ///< String, .v_string is used.
|
||||
VAR_FUNC, ///< Function reference, .v_string is used as function name.
|
||||
VAR_LIST, ///< List, .v_list is used.
|
||||
VAR_DICT, ///< Dictionary, .v_dict is used.
|
||||
VAR_FLOAT, ///< Floating-point value, .v_float is used.
|
||||
VAR_SPECIAL, ///< Special value (true, false, null), .v_special
|
||||
///< is used.
|
||||
VAR_PARTIAL, ///< Partial, .v_partial is used.
|
||||
} VarType;
|
||||
|
||||
/// Structure that holds an internal variable value
|
||||
typedef struct {
|
||||
VarType v_type; ///< Variable type.
|
||||
VarLockStatus v_lock; ///< Variable lock status.
|
||||
union typval_vval_union {
|
||||
varnumber_T v_number; ///< Number, for VAR_NUMBER.
|
||||
SpecialVarValue v_special; ///< Special value, for VAR_SPECIAL.
|
||||
float_T v_float; ///< Floating-point number, for VAR_FLOAT.
|
||||
char_u *v_string; ///< String, for VAR_STRING and VAR_FUNC, can be NULL.
|
||||
list_T *v_list; ///< List for VAR_LIST, can be NULL.
|
||||
dict_T *v_dict; ///< Dictionary for VAR_DICT, can be NULL.
|
||||
partial_T *v_partial; ///< Closure: function with args.
|
||||
} vval; ///< Actual value.
|
||||
} typval_T;
|
||||
|
||||
/// Values for (struct dictvar_S).dv_scope
|
||||
typedef enum {
|
||||
VAR_NO_SCOPE = 0, ///< Not a scope dictionary.
|
||||
VAR_SCOPE = 1, ///< Scope dictionary which requires prefix (a:, v:, …).
|
||||
VAR_DEF_SCOPE = 2, ///< Scope dictionary which may be accessed without prefix
|
||||
///< (l:, g:).
|
||||
} ScopeType;
|
||||
|
||||
/// Structure to hold an item of a list
|
||||
typedef struct listitem_S listitem_T;
|
||||
|
||||
struct listitem_S {
|
||||
listitem_T *li_next; ///< Next item in list.
|
||||
listitem_T *li_prev; ///< Previous item in list.
|
||||
typval_T li_tv; ///< Item value.
|
||||
};
|
||||
|
||||
/// Structure used by those that are using an item in a list
|
||||
typedef struct listwatch_S listwatch_T;
|
||||
|
||||
struct listwatch_S {
|
||||
listitem_T *lw_item; ///< Item being watched.
|
||||
listwatch_T *lw_next; ///< Next watcher.
|
||||
};
|
||||
|
||||
/// Structure to hold info about a list
|
||||
struct listvar_S {
|
||||
listitem_T *lv_first; ///< First item, NULL if none.
|
||||
listitem_T *lv_last; ///< Last item, NULL if none.
|
||||
int lv_refcount; ///< Reference count.
|
||||
int lv_len; ///< Number of items.
|
||||
listwatch_T *lv_watch; ///< First watcher, NULL if none.
|
||||
int lv_idx; ///< Index of a cached item, used for optimising repeated l[idx].
|
||||
listitem_T *lv_idx_item; ///< When not NULL item at index "lv_idx".
|
||||
int lv_copyID; ///< ID used by deepcopy().
|
||||
list_T *lv_copylist; ///< Copied list used by deepcopy().
|
||||
VarLockStatus lv_lock; ///< Zero, VAR_LOCKED, VAR_FIXED.
|
||||
list_T *lv_used_next; ///< next list in used lists list.
|
||||
list_T *lv_used_prev; ///< Previous list in used lists list.
|
||||
};
|
||||
|
||||
// Static list with 10 items. Use init_static_list() to initialize.
|
||||
typedef struct {
|
||||
list_T sl_list; // must be first
|
||||
listitem_T sl_items[10];
|
||||
} staticList10_T;
|
||||
|
||||
// Structure to hold an item of a Dictionary.
|
||||
// Also used for a variable.
|
||||
// The key is copied into "di_key" to avoid an extra alloc/free for it.
|
||||
struct dictitem_S {
|
||||
typval_T di_tv; ///< type and value of the variable
|
||||
char_u di_flags; ///< flags (only used for variable)
|
||||
char_u di_key[1]; ///< key (actually longer!)
|
||||
};
|
||||
|
||||
#define TV_DICTITEM_STRUCT(KEY_LEN) \
|
||||
struct { \
|
||||
typval_T di_tv; /* Structure that holds scope dictionary itself. */ \
|
||||
uint8_t di_flags; /* Flags. */ \
|
||||
char_u di_key[KEY_LEN]; /* Key value. */ \
|
||||
}
|
||||
|
||||
/// Structure to hold a scope dictionary
|
||||
///
|
||||
/// @warning Must be compatible with dictitem_T.
|
||||
///
|
||||
/// For use in find_var_in_ht to pretend that it found dictionary item when it
|
||||
/// finds scope dictionary.
|
||||
typedef TV_DICTITEM_STRUCT(1) ScopeDictDictItem;
|
||||
|
||||
/// Structure to hold an item of a Dictionary
|
||||
///
|
||||
/// @warning Must be compatible with ScopeDictDictItem.
|
||||
///
|
||||
/// Also used for a variable.
|
||||
typedef TV_DICTITEM_STRUCT() dictitem_T;
|
||||
|
||||
/// Flags for dictitem_T.di_flags
|
||||
typedef enum {
|
||||
DI_FLAGS_RO = 1, ///< Read-only value
|
||||
DI_FLAGS_RO_SBX = 2, ///< Value, read-only in the sandbox
|
||||
DI_FLAGS_FIX = 4, ///< Fixed value: cannot be :unlet or remove()d.
|
||||
DI_FLAGS_LOCK = 8, ///< Locked value.
|
||||
DI_FLAGS_ALLOC = 16, ///< Separately allocated.
|
||||
} DictItemFlags;
|
||||
|
||||
/// Structure representing a Dictionary
|
||||
struct dictvar_S {
|
||||
VarLockStatus dv_lock; ///< Whole dictionary lock status.
|
||||
ScopeType dv_scope; ///< Non-zero (#VAR_SCOPE, #VAR_DEF_SCOPE) if
|
||||
///< dictionary represents a scope (i.e. g:, l: …).
|
||||
int dv_refcount; ///< Reference count.
|
||||
int dv_copyID; ///< ID used when recursivery traversing a value.
|
||||
hashtab_T dv_hashtab; ///< Hashtab containing all items.
|
||||
dict_T *dv_copydict; ///< Copied dict used by deepcopy().
|
||||
dict_T *dv_used_next; ///< Next dictionary in used dictionaries list.
|
||||
dict_T *dv_used_prev; ///< Previous dictionary in used dictionaries list.
|
||||
QUEUE watchers; ///< Dictionary key watchers set by user code.
|
||||
};
|
||||
|
||||
/// Type used for script ID
|
||||
typedef int scid_T;
|
||||
/// Format argument for scid_T
|
||||
#define PRIdSCID "d"
|
||||
|
||||
// Structure to hold info for a function that is currently being executed.
|
||||
typedef struct funccall_S funccall_T;
|
||||
|
||||
/// Structure to hold info for a user function.
|
||||
struct ufunc {
|
||||
int uf_varargs; ///< variable nr of arguments
|
||||
int uf_flags;
|
||||
int uf_calls; ///< nr of active calls
|
||||
bool uf_cleared; ///< func_clear() was already called
|
||||
garray_T uf_args; ///< arguments
|
||||
garray_T uf_lines; ///< function lines
|
||||
int uf_profiling; ///< true when func is being profiled
|
||||
// Profiling the function as a whole.
|
||||
int uf_tm_count; ///< nr of calls
|
||||
proftime_T uf_tm_total; ///< time spent in function + children
|
||||
proftime_T uf_tm_self; ///< time spent in function itself
|
||||
proftime_T uf_tm_children; ///< time spent in children this call
|
||||
// Profiling the function per line.
|
||||
int *uf_tml_count; ///< nr of times line was executed
|
||||
proftime_T *uf_tml_total; ///< time spent in a line + children
|
||||
proftime_T *uf_tml_self; ///< time spent in a line itself
|
||||
proftime_T uf_tml_start; ///< start time for current line
|
||||
proftime_T uf_tml_children; ///< time spent in children for this line
|
||||
proftime_T uf_tml_wait; ///< start wait time for current line
|
||||
int uf_tml_idx; ///< index of line being timed; -1 if none
|
||||
int uf_tml_execed; ///< line being timed was executed
|
||||
scid_T uf_script_ID; ///< ID of script where function was defined,
|
||||
///< used for s: variables
|
||||
int uf_refcount; ///< reference count, see func_name_refcount()
|
||||
funccall_T *uf_scoped; ///< l: local variables for closure
|
||||
char_u uf_name[1]; ///< name of function (actually longer); can
|
||||
///< start with <SNR>123_ (<SNR> is K_SPECIAL
|
||||
///< KS_EXTRA KE_SNR)
|
||||
};
|
||||
|
||||
/// Maximum number of function arguments
|
||||
#define MAX_FUNC_ARGS 20
|
||||
|
||||
struct partial_S {
|
||||
int pt_refcount; ///< Reference count.
|
||||
char_u *pt_name; ///< Function name; when NULL use pt_func->name.
|
||||
ufunc_T *pt_func; ///< Function pointer; when NULL lookup function with
|
||||
///< pt_name.
|
||||
bool pt_auto; ///< When true the partial was created by using dict.member
|
||||
///< in handle_subscript().
|
||||
int pt_argc; ///< Number of arguments.
|
||||
typval_T *pt_argv; ///< Arguments in allocated array.
|
||||
dict_T *pt_dict; ///< Dict for "self".
|
||||
};
|
||||
|
||||
/// Structure used for explicit stack while garbage collecting hash tables
|
||||
typedef struct ht_stack_S {
|
||||
hashtab_T *ht;
|
||||
struct ht_stack_S *prev;
|
||||
} ht_stack_T;
|
||||
|
||||
/// Structure used for explicit stack while garbage collecting lists
|
||||
typedef struct list_stack_S {
|
||||
list_T *list;
|
||||
struct list_stack_S *prev;
|
||||
} list_stack_T;
|
||||
|
||||
// In a hashtab item "hi_key" points to "di_key" in a dictitem.
|
||||
// This avoids adding a pointer to the hashtab item.
|
||||
|
||||
/// Convert a hashitem pointer to a dictitem pointer
|
||||
#define TV_DICT_HI2DI(hi) \
|
||||
((dictitem_T *)((hi)->hi_key - offsetof(dictitem_T, di_key)))
|
||||
|
||||
static inline long tv_list_len(const list_T *const l)
|
||||
REAL_FATTR_PURE REAL_FATTR_WARN_UNUSED_RESULT;
|
||||
|
||||
/// Get the number of items in a list
|
||||
///
|
||||
/// @param[in] l List to check.
|
||||
static inline long tv_list_len(const list_T *const l)
|
||||
{
|
||||
if (l == NULL) {
|
||||
return 0;
|
||||
}
|
||||
return l->lv_len;
|
||||
}
|
||||
|
||||
static inline long tv_dict_len(const dict_T *const d)
|
||||
REAL_FATTR_PURE REAL_FATTR_WARN_UNUSED_RESULT;
|
||||
|
||||
/// Get the number of items in a Dictionary
|
||||
///
|
||||
/// @param[in] d Dictionary to check.
|
||||
static inline long tv_dict_len(const dict_T *const d)
|
||||
{
|
||||
if (d == NULL) {
|
||||
return 0L;
|
||||
}
|
||||
return (long)d->dv_hashtab.ht_used;
|
||||
}
|
||||
|
||||
static inline bool tv_dict_is_watched(const dict_T *const d)
|
||||
REAL_FATTR_PURE REAL_FATTR_WARN_UNUSED_RESULT;
|
||||
|
||||
/// Check if dictionary is watched
|
||||
///
|
||||
/// @param[in] d Dictionary to check.
|
||||
///
|
||||
/// @return true if there is at least one watcher.
|
||||
static inline bool tv_dict_is_watched(const dict_T *const d)
|
||||
{
|
||||
return d && !QUEUE_EMPTY(&d->watchers);
|
||||
}
|
||||
|
||||
/// Initialize VimL object
|
||||
///
|
||||
/// Initializes to unlocked VAR_UNKNOWN object.
|
||||
///
|
||||
/// @param[out] tv Object to initialize.
|
||||
static inline void tv_init(typval_T *const tv)
|
||||
{
|
||||
if (tv != NULL) {
|
||||
memset(tv, 0, sizeof(*tv));
|
||||
}
|
||||
}
|
||||
|
||||
#define TV_INITIAL_VALUE \
|
||||
((typval_T) { \
|
||||
.v_type = VAR_UNKNOWN, \
|
||||
.v_lock = VAR_UNLOCKED, \
|
||||
})
|
||||
|
||||
/// Empty string
|
||||
///
|
||||
/// Needed for hack which allows not allocating empty string and still not
|
||||
/// crashing when freeing it.
|
||||
extern const char *const tv_empty_string;
|
||||
|
||||
/// Specifies that free_unref_items() function has (not) been entered
|
||||
extern bool tv_in_free_unref_items;
|
||||
|
||||
/// Iterate over a dictionary
|
||||
///
|
||||
/// @param[in] d Dictionary to iterate over.
|
||||
/// @param di Name of the variable with current dictitem_T entry.
|
||||
/// @param code Cycle body.
|
||||
#define TV_DICT_ITER(d, di, code) \
|
||||
HASHTAB_ITER(&(d)->dv_hashtab, di##hi_, { \
|
||||
{ \
|
||||
dictitem_T *const di = TV_DICT_HI2DI(di##hi_); \
|
||||
{ \
|
||||
code \
|
||||
} \
|
||||
} \
|
||||
})
|
||||
|
||||
static inline bool tv_get_float_chk(const typval_T *const tv,
|
||||
float_T *const ret_f)
|
||||
REAL_FATTR_NONNULL_ALL REAL_FATTR_WARN_UNUSED_RESULT;
|
||||
|
||||
// FIXME circular dependency, cannot import message.h.
|
||||
bool emsgf(const char *const fmt, ...);
|
||||
|
||||
/// Get the float value
|
||||
///
|
||||
/// Raises an error if object is not number or floating-point.
|
||||
///
|
||||
/// @param[in] tv VimL object to get value from.
|
||||
/// @param[out] ret_f Location where resulting float is stored.
|
||||
///
|
||||
/// @return true in case of success, false if tv is not a number or float.
|
||||
static inline bool tv_get_float_chk(const typval_T *const tv,
|
||||
float_T *const ret_f)
|
||||
{
|
||||
if (tv->v_type == VAR_FLOAT) {
|
||||
*ret_f = tv->vval.v_float;
|
||||
return true;
|
||||
}
|
||||
if (tv->v_type == VAR_NUMBER) {
|
||||
*ret_f = (float_T)tv->vval.v_number;
|
||||
return true;
|
||||
}
|
||||
emsgf(_("E808: Number or Float required"));
|
||||
return false;
|
||||
}
|
||||
|
||||
static inline DictWatcher *tv_dict_watcher_node_data(QUEUE *q)
|
||||
REAL_FATTR_NONNULL_ALL REAL_FATTR_NONNULL_RET REAL_FATTR_PURE
|
||||
REAL_FATTR_WARN_UNUSED_RESULT REAL_FATTR_ALWAYS_INLINE;
|
||||
|
||||
/// Compute the `DictWatcher` address from a QUEUE node.
|
||||
///
|
||||
/// This only exists for .asan-blacklist (ASAN doesn't handle QUEUE_DATA pointer
|
||||
/// arithmetic).
|
||||
static inline DictWatcher *tv_dict_watcher_node_data(QUEUE *q)
|
||||
{
|
||||
return QUEUE_DATA(q, DictWatcher, node);
|
||||
}
|
||||
|
||||
static inline bool tv_is_func(const typval_T tv)
|
||||
FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_ALWAYS_INLINE FUNC_ATTR_CONST;
|
||||
|
||||
/// Check whether given typval_T contains a function
|
||||
///
|
||||
/// That is, whether it contains VAR_FUNC or VAR_PARTIAL.
|
||||
///
|
||||
/// @param[in] tv Typval to check.
|
||||
///
|
||||
/// @return True if it is a function or a partial, false otherwise.
|
||||
static inline bool tv_is_func(const typval_T tv)
|
||||
{
|
||||
return tv.v_type == VAR_FUNC || tv.v_type == VAR_PARTIAL;
|
||||
}
|
||||
|
||||
#ifdef INCLUDE_GENERATED_DECLARATIONS
|
||||
# include "eval/typval.h.generated.h"
|
||||
#endif
|
||||
#endif // NVIM_EVAL_TYPVAL_H
|
|
@ -238,7 +238,7 @@
|
|||
#include <assert.h>
|
||||
|
||||
#include "nvim/lib/kvec.h"
|
||||
#include "nvim/eval_defs.h"
|
||||
#include "nvim/eval/typval.h"
|
||||
#include "nvim/eval/encode.h"
|
||||
#include "nvim/func_attr.h"
|
||||
#include "nvim/eval/typval_encode.h"
|
||||
|
@ -402,11 +402,11 @@ static int _TYPVAL_ENCODE_CONVERT_ONE_VALUE(
|
|||
const dictitem_T *val_di;
|
||||
if (TYPVAL_ENCODE_ALLOW_SPECIALS
|
||||
&& tv->vval.v_dict->dv_hashtab.ht_used == 2
|
||||
&& (type_di = dict_find((dict_T *)tv->vval.v_dict,
|
||||
(char_u *)"_TYPE", -1)) != NULL
|
||||
&& (type_di = tv_dict_find((dict_T *)tv->vval.v_dict,
|
||||
S_LEN("_TYPE"))) != NULL
|
||||
&& type_di->di_tv.v_type == VAR_LIST
|
||||
&& (val_di = dict_find((dict_T *)tv->vval.v_dict,
|
||||
(char_u *)"_VAL", -1)) != NULL) {
|
||||
&& (val_di = tv_dict_find((dict_T *)tv->vval.v_dict,
|
||||
S_LEN("_VAL"))) != NULL) {
|
||||
size_t i;
|
||||
for (i = 0; i < ARRAY_SIZE(eval_msgpack_type_lists); i++) {
|
||||
if (type_di->di_tv.vval.v_list == eval_msgpack_type_lists[i]) {
|
||||
|
@ -658,7 +658,7 @@ typval_encode_stop_converting_one_item:
|
|||
while (HASHITEM_EMPTY(cur_mpsv->data.d.hi)) {
|
||||
cur_mpsv->data.d.hi++;
|
||||
}
|
||||
dictitem_T *const di = HI2DI(cur_mpsv->data.d.hi);
|
||||
dictitem_T *const di = TV_DICT_HI2DI(cur_mpsv->data.d.hi);
|
||||
cur_mpsv->data.d.todo--;
|
||||
cur_mpsv->data.d.hi++;
|
||||
TYPVAL_ENCODE_CONV_STR_STRING(NULL, &di->di_key[0],
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
#include <assert.h>
|
||||
|
||||
#include "nvim/lib/kvec.h"
|
||||
#include "nvim/eval_defs.h"
|
||||
#include "nvim/eval/typval.h"
|
||||
#include "nvim/func_attr.h"
|
||||
|
||||
/// Type of the stack entry
|
||||
|
|
|
@ -1,285 +0,0 @@
|
|||
#ifndef NVIM_EVAL_DEFS_H
|
||||
#define NVIM_EVAL_DEFS_H
|
||||
|
||||
#include <limits.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#include "nvim/hashtab.h"
|
||||
#include "nvim/lib/queue.h"
|
||||
#include "nvim/garray.h" // for garray_T
|
||||
#include "nvim/profile.h" // for proftime_T
|
||||
#include "nvim/pos.h" // for linenr_T
|
||||
|
||||
typedef int varnumber_T;
|
||||
typedef double float_T;
|
||||
|
||||
#define VARNUMBER_MAX INT_MAX
|
||||
#define VARNUMBER_MIN INT_MIN
|
||||
|
||||
typedef struct listvar_S list_T;
|
||||
typedef struct dictvar_S dict_T;
|
||||
typedef struct partial_S partial_T;
|
||||
|
||||
/// Special variable values
|
||||
typedef enum {
|
||||
kSpecialVarFalse, ///< v:false
|
||||
kSpecialVarTrue, ///< v:true
|
||||
kSpecialVarNull, ///< v:null
|
||||
} SpecialVarValue;
|
||||
|
||||
/// Variable lock status for typval_T.v_lock
|
||||
typedef enum {
|
||||
VAR_UNLOCKED = 0, ///< Not locked.
|
||||
VAR_LOCKED = 1, ///< User lock, can be unlocked.
|
||||
VAR_FIXED = 2, ///< Locked forever.
|
||||
} VarLockStatus;
|
||||
|
||||
/// VimL variable types, for use in typval_T.v_type
|
||||
typedef enum {
|
||||
VAR_UNKNOWN = 0, ///< Unknown (unspecified) value.
|
||||
VAR_NUMBER, ///< Number, .v_number is used.
|
||||
VAR_STRING, ///< String, .v_string is used.
|
||||
VAR_FUNC, ///< Function reference, .v_string is used as function name.
|
||||
VAR_LIST, ///< List, .v_list is used.
|
||||
VAR_DICT, ///< Dictionary, .v_dict is used.
|
||||
VAR_FLOAT, ///< Floating-point value, .v_float is used.
|
||||
VAR_SPECIAL, ///< Special value (true, false, null), .v_special
|
||||
///< is used.
|
||||
VAR_PARTIAL, ///< Partial, .v_partial is used.
|
||||
} VarType;
|
||||
|
||||
/// Structure that holds an internal variable value
|
||||
typedef struct {
|
||||
VarType v_type; ///< Variable type.
|
||||
VarLockStatus v_lock; ///< Variable lock status.
|
||||
union typval_vval_union {
|
||||
varnumber_T v_number; ///< Number, for VAR_NUMBER.
|
||||
SpecialVarValue v_special; ///< Special value, for VAR_SPECIAL.
|
||||
float_T v_float; ///< Floating-point number, for VAR_FLOAT.
|
||||
char_u *v_string; ///< String, for VAR_STRING and VAR_FUNC, can be NULL.
|
||||
list_T *v_list; ///< List for VAR_LIST, can be NULL.
|
||||
dict_T *v_dict; ///< Dictionary for VAR_DICT, can be NULL.
|
||||
partial_T *v_partial; ///< Closure: function with args.
|
||||
} vval; ///< Actual value.
|
||||
} typval_T;
|
||||
|
||||
/* Values for "dv_scope". */
|
||||
#define VAR_SCOPE 1 /* a:, v:, s:, etc. scope dictionaries */
|
||||
#define VAR_DEF_SCOPE 2 /* l:, g: scope dictionaries: here funcrefs are not
|
||||
allowed to mask existing functions */
|
||||
|
||||
/*
|
||||
* Structure to hold an item of a list: an internal variable without a name.
|
||||
*/
|
||||
typedef struct listitem_S listitem_T;
|
||||
|
||||
struct listitem_S {
|
||||
listitem_T *li_next; /* next item in list */
|
||||
listitem_T *li_prev; /* previous item in list */
|
||||
typval_T li_tv; /* type and value of the variable */
|
||||
};
|
||||
|
||||
/*
|
||||
* Struct used by those that are using an item in a list.
|
||||
*/
|
||||
typedef struct listwatch_S listwatch_T;
|
||||
|
||||
struct listwatch_S {
|
||||
listitem_T *lw_item; /* item being watched */
|
||||
listwatch_T *lw_next; /* next watcher */
|
||||
};
|
||||
|
||||
/*
|
||||
* Structure to hold info about a list.
|
||||
*/
|
||||
struct listvar_S {
|
||||
listitem_T *lv_first; ///< First item, NULL if none.
|
||||
listitem_T *lv_last; ///< Last item, NULL if none.
|
||||
int lv_refcount; ///< Reference count.
|
||||
int lv_len; ///< Number of items.
|
||||
listwatch_T *lv_watch; ///< First watcher, NULL if none.
|
||||
int lv_idx; ///< Index of a cached item, used for optimising repeated l[idx].
|
||||
listitem_T *lv_idx_item; ///< When not NULL item at index "lv_idx".
|
||||
int lv_copyID; ///< ID used by deepcopy().
|
||||
list_T *lv_copylist; ///< Copied list used by deepcopy().
|
||||
VarLockStatus lv_lock; ///< Zero, VAR_LOCKED, VAR_FIXED.
|
||||
list_T *lv_used_next; ///< next list in used lists list.
|
||||
list_T *lv_used_prev; ///< Previous list in used lists list.
|
||||
};
|
||||
|
||||
// Static list with 10 items. Use init_static_list() to initialize.
|
||||
typedef struct {
|
||||
list_T sl_list; // must be first
|
||||
listitem_T sl_items[10];
|
||||
} staticList10_T;
|
||||
|
||||
// Structure to hold an item of a Dictionary.
|
||||
// Also used for a variable.
|
||||
// The key is copied into "di_key" to avoid an extra alloc/free for it.
|
||||
struct dictitem_S {
|
||||
typval_T di_tv; ///< type and value of the variable
|
||||
char_u di_flags; ///< flags (only used for variable)
|
||||
char_u di_key[1]; ///< key (actually longer!)
|
||||
};
|
||||
|
||||
typedef struct dictitem_S dictitem_T;
|
||||
|
||||
/// A dictitem with a 16 character key (plus NUL)
|
||||
struct dictitem16_S {
|
||||
typval_T di_tv; ///< type and value of the variable
|
||||
char_u di_flags; ///< flags (only used for variable)
|
||||
char_u di_key[17]; ///< key
|
||||
};
|
||||
|
||||
typedef struct dictitem16_S dictitem16_T;
|
||||
|
||||
|
||||
#define DI_FLAGS_RO 1 // "di_flags" value: read-only variable
|
||||
#define DI_FLAGS_RO_SBX 2 // "di_flags" value: read-only in the sandbox
|
||||
#define DI_FLAGS_FIX 4 // "di_flags" value: fixed: no :unlet or remove()
|
||||
#define DI_FLAGS_LOCK 8 // "di_flags" value: locked variable
|
||||
#define DI_FLAGS_ALLOC 16 // "di_flags" value: separately allocated
|
||||
|
||||
/// Structure representing a Dictionary
|
||||
struct dictvar_S {
|
||||
VarLockStatus dv_lock; ///< Whole dictionary lock status.
|
||||
char dv_scope; ///< Non-zero (#VAR_SCOPE, #VAR_DEF_SCOPE) if
|
||||
///< dictionary represents a scope (i.e. g:, l: …).
|
||||
int dv_refcount; ///< Reference count.
|
||||
int dv_copyID; ///< ID used when recursivery traversing a value.
|
||||
hashtab_T dv_hashtab; ///< Hashtab containing all items.
|
||||
dict_T *dv_copydict; ///< Copied dict used by deepcopy().
|
||||
dict_T *dv_used_next; ///< Next dictionary in used dictionaries list.
|
||||
dict_T *dv_used_prev; ///< Previous dictionary in used dictionaries list.
|
||||
QUEUE watchers; ///< Dictionary key watchers set by user code.
|
||||
};
|
||||
|
||||
typedef int scid_T; // script ID
|
||||
typedef struct funccall_S funccall_T;
|
||||
|
||||
// Structure to hold info for a user function.
|
||||
typedef struct ufunc ufunc_T;
|
||||
|
||||
struct ufunc {
|
||||
int uf_varargs; ///< variable nr of arguments
|
||||
int uf_flags;
|
||||
int uf_calls; ///< nr of active calls
|
||||
bool uf_cleared; ///< func_clear() was already called
|
||||
garray_T uf_args; ///< arguments
|
||||
garray_T uf_lines; ///< function lines
|
||||
int uf_profiling; ///< true when func is being profiled
|
||||
// Profiling the function as a whole.
|
||||
int uf_tm_count; ///< nr of calls
|
||||
proftime_T uf_tm_total; ///< time spent in function + children
|
||||
proftime_T uf_tm_self; ///< time spent in function itself
|
||||
proftime_T uf_tm_children; ///< time spent in children this call
|
||||
// Profiling the function per line.
|
||||
int *uf_tml_count; ///< nr of times line was executed
|
||||
proftime_T *uf_tml_total; ///< time spent in a line + children
|
||||
proftime_T *uf_tml_self; ///< time spent in a line itself
|
||||
proftime_T uf_tml_start; ///< start time for current line
|
||||
proftime_T uf_tml_children; ///< time spent in children for this line
|
||||
proftime_T uf_tml_wait; ///< start wait time for current line
|
||||
int uf_tml_idx; ///< index of line being timed; -1 if none
|
||||
int uf_tml_execed; ///< line being timed was executed
|
||||
scid_T uf_script_ID; ///< ID of script where function was defined,
|
||||
// used for s: variables
|
||||
int uf_refcount; ///< reference count, see func_name_refcount()
|
||||
funccall_T *uf_scoped; ///< l: local variables for closure
|
||||
char_u uf_name[1]; ///< name of function (actually longer); can
|
||||
// start with <SNR>123_ (<SNR> is K_SPECIAL
|
||||
// KS_EXTRA KE_SNR)
|
||||
};
|
||||
|
||||
/// Maximum number of function arguments
|
||||
#define MAX_FUNC_ARGS 20
|
||||
#define VAR_SHORT_LEN 20 // short variable name length
|
||||
#define FIXVAR_CNT 12 // number of fixed variables
|
||||
|
||||
// structure to hold info for a function that is currently being executed.
|
||||
struct funccall_S {
|
||||
ufunc_T *func; ///< function being called
|
||||
int linenr; ///< next line to be executed
|
||||
int returned; ///< ":return" used
|
||||
struct { ///< fixed variables for arguments
|
||||
dictitem_T var; ///< variable (without room for name)
|
||||
char_u room[VAR_SHORT_LEN]; ///< room for the name
|
||||
} fixvar[FIXVAR_CNT];
|
||||
dict_T l_vars; ///< l: local function variables
|
||||
dictitem_T l_vars_var; ///< variable for l: scope
|
||||
dict_T l_avars; ///< a: argument variables
|
||||
dictitem_T l_avars_var; ///< variable for a: scope
|
||||
list_T l_varlist; ///< list for a:000
|
||||
listitem_T l_listitems[MAX_FUNC_ARGS]; ///< listitems for a:000
|
||||
typval_T *rettv; ///< return value
|
||||
linenr_T breakpoint; ///< next line with breakpoint or zero
|
||||
int dbg_tick; ///< debug_tick when breakpoint was set
|
||||
int level; ///< top nesting level of executed function
|
||||
proftime_T prof_child; ///< time spent in a child
|
||||
funccall_T *caller; ///< calling function or NULL
|
||||
int fc_refcount; ///< number of user functions that reference
|
||||
// this funccal
|
||||
int fc_copyID; ///< for garbage collection
|
||||
garray_T fc_funcs; ///< list of ufunc_T* which keep a reference
|
||||
// to "func"
|
||||
};
|
||||
|
||||
// structure used by trans_function_name()
|
||||
typedef struct {
|
||||
dict_T *fd_dict; ///< Dictionary used.
|
||||
char_u *fd_newkey; ///< New key in "dict" in allocated memory.
|
||||
dictitem_T *fd_di; ///< Dictionary item used.
|
||||
} funcdict_T;
|
||||
|
||||
struct partial_S {
|
||||
int pt_refcount; ///< Reference count.
|
||||
char_u *pt_name; ///< Function name; when NULL use pt_func->name.
|
||||
ufunc_T *pt_func; ///< Function pointer; when NULL lookup function
|
||||
///< with pt_name.
|
||||
bool pt_auto; ///< when true the partial was created for using
|
||||
///< dict.member in handle_subscript().
|
||||
int pt_argc; ///< Number of arguments.
|
||||
typval_T *pt_argv; ///< Arguments in allocated array.
|
||||
dict_T *pt_dict; ///< Dict for "self".
|
||||
};
|
||||
|
||||
// structure used for explicit stack while garbage collecting hash tables
|
||||
typedef struct ht_stack_S {
|
||||
hashtab_T *ht;
|
||||
struct ht_stack_S *prev;
|
||||
} ht_stack_T;
|
||||
|
||||
// structure used for explicit stack while garbage collecting lists
|
||||
typedef struct list_stack_S {
|
||||
list_T *list;
|
||||
struct list_stack_S *prev;
|
||||
} list_stack_T;
|
||||
|
||||
// In a hashtab item "hi_key" points to "di_key" in a dictitem.
|
||||
// This avoids adding a pointer to the hashtab item.
|
||||
|
||||
/// Convert a dictitem pointer to a hashitem key pointer
|
||||
#define DI2HIKEY(di) ((di)->di_key)
|
||||
|
||||
/// Convert a hashitem key pointer to a dictitem pointer
|
||||
#define HIKEY2DI(p) ((dictitem_T *)(p - offsetof(dictitem_T, di_key)))
|
||||
|
||||
/// Convert a hashitem value pointer to a dictitem pointer
|
||||
#define HIVAL2DI(p) \
|
||||
((dictitem_T *)(((char *)p) - offsetof(dictitem_T, di_tv)))
|
||||
|
||||
/// Convert a hashitem pointer to a dictitem pointer
|
||||
#define HI2DI(hi) HIKEY2DI((hi)->hi_key)
|
||||
|
||||
/// Type of assert_* check being performed
|
||||
typedef enum
|
||||
{
|
||||
ASSERT_EQUAL,
|
||||
ASSERT_NOTEQUAL,
|
||||
ASSERT_MATCH,
|
||||
ASSERT_NOTMATCH,
|
||||
ASSERT_INRANGE,
|
||||
ASSERT_OTHER,
|
||||
} assert_type_T;
|
||||
|
||||
#endif // NVIM_EVAL_DEFS_H
|
|
@ -21,7 +21,7 @@ struct process {
|
|||
int pid, status, refcount;
|
||||
// set to the hrtime of when process_stop was called for the process.
|
||||
uint64_t stopped_time;
|
||||
char *cwd;
|
||||
const char *cwd;
|
||||
char **argv;
|
||||
Stream *in, *out, *err;
|
||||
process_exit_cb cb;
|
||||
|
|
|
@ -89,7 +89,10 @@ static void on_rbuffer_nonfull(RBuffer *buf, void *data)
|
|||
static void alloc_cb(uv_handle_t *handle, size_t suggested, uv_buf_t *buf)
|
||||
{
|
||||
Stream *stream = handle->data;
|
||||
buf->base = rbuffer_write_ptr(stream->buffer, &buf->len);
|
||||
// `uv_buf_t.len` happens to have different size on Windows.
|
||||
size_t write_count;
|
||||
buf->base = rbuffer_write_ptr(stream->buffer, &write_count);
|
||||
buf->len = write_count;
|
||||
}
|
||||
|
||||
// Callback invoked by libuv after it copies the data into the buffer provided
|
||||
|
@ -136,7 +139,10 @@ static void fread_idle_cb(uv_idle_t *handle)
|
|||
uv_fs_t req;
|
||||
Stream *stream = handle->data;
|
||||
|
||||
stream->uvbuf.base = rbuffer_write_ptr(stream->buffer, &stream->uvbuf.len);
|
||||
// `uv_buf_t.len` happens to have different size on Windows.
|
||||
size_t write_count;
|
||||
stream->uvbuf.base = rbuffer_write_ptr(stream->buffer, &write_count);
|
||||
stream->uvbuf.len = write_count;
|
||||
|
||||
// the offset argument to uv_fs_read is int64_t, could someone really try
|
||||
// to read more than 9 quintillion (9e18) bytes?
|
||||
|
|
|
@ -1008,8 +1008,8 @@ void do_bang(int addr_count, exarg_T *eap, int forceit, int do_in, int do_out)
|
|||
|
||||
AppendToRedobuffLit(cmd, -1);
|
||||
xfree(cmd);
|
||||
AppendToRedobuff((char_u *)"\n");
|
||||
bangredo = FALSE;
|
||||
AppendToRedobuff("\n");
|
||||
bangredo = false;
|
||||
}
|
||||
/*
|
||||
* Add quotes around the command, for shells that need them.
|
||||
|
@ -2958,7 +2958,7 @@ void sub_set_replacement(SubReplacementString sub)
|
|||
{
|
||||
xfree(old_sub.sub);
|
||||
if (sub.additional_elements != old_sub.additional_elements) {
|
||||
list_unref(old_sub.additional_elements);
|
||||
tv_list_unref(old_sub.additional_elements);
|
||||
}
|
||||
old_sub = sub;
|
||||
}
|
||||
|
@ -4764,8 +4764,8 @@ void fix_help_buffer(void)
|
|||
char_u *p;
|
||||
char_u *rt;
|
||||
|
||||
/* set filetype to "help". */
|
||||
set_option_value((char_u *)"ft", 0L, (char_u *)"help", OPT_LOCAL);
|
||||
// Set filetype to "help".
|
||||
set_option_value("ft", 0L, "help", OPT_LOCAL);
|
||||
|
||||
if (!syntax_present(curwin)) {
|
||||
for (lnum = 1; lnum <= curbuf->b_ml.ml_line_count; ++lnum) {
|
||||
|
|
|
@ -4,8 +4,8 @@
|
|||
#include <stdbool.h>
|
||||
|
||||
#include "nvim/os/time.h"
|
||||
#include "nvim/eval_defs.h"
|
||||
#include "nvim/pos.h"
|
||||
#include "nvim/eval/typval.h"
|
||||
|
||||
// flags for do_ecmd()
|
||||
#define ECMD_HIDE 0x01 // don't free the current buffer
|
||||
|
|
|
@ -957,23 +957,21 @@ char_u *get_profile_name(expand_T *xp, int idx)
|
|||
}
|
||||
|
||||
/// Handle command line completion for :profile command.
|
||||
void set_context_in_profile_cmd(expand_T *xp, char_u *arg)
|
||||
void set_context_in_profile_cmd(expand_T *xp, const char *arg)
|
||||
{
|
||||
char_u *end_subcmd;
|
||||
|
||||
// Default: expand subcommands.
|
||||
xp->xp_context = EXPAND_PROFILE;
|
||||
pexpand_what = PEXP_SUBCMD;
|
||||
xp->xp_pattern = arg;
|
||||
xp->xp_pattern = (char_u *)arg;
|
||||
|
||||
end_subcmd = skiptowhite(arg);
|
||||
char_u *const end_subcmd = skiptowhite((const char_u *)arg);
|
||||
if (*end_subcmd == NUL) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (end_subcmd - arg == 5 && STRNCMP(arg, "start", 5) == 0) {
|
||||
if ((const char *)end_subcmd - arg == 5 && strncmp(arg, "start", 5) == 0) {
|
||||
xp->xp_context = EXPAND_FILES;
|
||||
xp->xp_pattern = skipwhite(end_subcmd);
|
||||
xp->xp_pattern = skipwhite((const char_u *)end_subcmd);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -2073,9 +2071,9 @@ void ex_listdo(exarg_T *eap)
|
|||
// Clear 'shm' to avoid that the file message overwrites
|
||||
// any output from the command.
|
||||
p_shm_save = vim_strsave(p_shm);
|
||||
set_option_value((char_u *)"shm", 0L, (char_u *)"", 0);
|
||||
set_option_value("shm", 0L, "", 0);
|
||||
do_argfile(eap, i);
|
||||
set_option_value((char_u *)"shm", 0L, p_shm_save, 0);
|
||||
set_option_value("shm", 0L, (char *)p_shm_save, 0);
|
||||
xfree(p_shm_save);
|
||||
}
|
||||
if (curwin->w_arg_idx != i) {
|
||||
|
@ -2138,9 +2136,9 @@ void ex_listdo(exarg_T *eap)
|
|||
// Go to the next buffer. Clear 'shm' to avoid that the file
|
||||
// message overwrites any output from the command.
|
||||
p_shm_save = vim_strsave(p_shm);
|
||||
set_option_value((char_u *)"shm", 0L, (char_u *)"", 0);
|
||||
set_option_value("shm", 0L, "", 0);
|
||||
goto_buffer(eap, DOBUF_FIRST, FORWARD, next_fnum);
|
||||
set_option_value((char_u *)"shm", 0L, p_shm_save, 0);
|
||||
set_option_value("shm", 0L, (char *)p_shm_save, 0);
|
||||
xfree(p_shm_save);
|
||||
|
||||
// If autocommands took us elsewhere, quit here.
|
||||
|
@ -2256,8 +2254,8 @@ void ex_compiler(exarg_T *eap)
|
|||
}
|
||||
do_cmdline_cmd("command -nargs=* CompilerSet setlocal <args>");
|
||||
}
|
||||
do_unlet((char_u *)"g:current_compiler", true);
|
||||
do_unlet((char_u *)"b:current_compiler", true);
|
||||
do_unlet(S_LEN("g:current_compiler"), true);
|
||||
do_unlet(S_LEN("b:current_compiler"), true);
|
||||
|
||||
snprintf((char *)buf, bufsize, "compiler/%s.vim", eap->arg);
|
||||
if (source_runtime(buf, DIP_ALL) == FAIL) {
|
||||
|
@ -2280,7 +2278,7 @@ void ex_compiler(exarg_T *eap)
|
|||
old_cur_comp);
|
||||
xfree(old_cur_comp);
|
||||
} else {
|
||||
do_unlet((char_u *)"g:current_compiler", true);
|
||||
do_unlet(S_LEN("g:current_compiler"), true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2496,16 +2494,16 @@ static int APP_BOTH;
|
|||
static void add_pack_plugin(char_u *fname, void *cookie)
|
||||
{
|
||||
char_u *p4, *p3, *p2, *p1, *p;
|
||||
char_u *new_rtp;
|
||||
char_u *ffname = (char_u *)fix_fname((char *)fname);
|
||||
|
||||
char *const ffname = fix_fname((char *)fname);
|
||||
|
||||
if (ffname == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (cookie != &APP_LOAD && strstr((char *)p_rtp, (char *)ffname) == NULL) {
|
||||
if (cookie != &APP_LOAD && strstr((char *)p_rtp, ffname) == NULL) {
|
||||
// directory is not yet in 'runtimepath', add it
|
||||
p4 = p3 = p2 = p1 = get_past_head(ffname);
|
||||
p4 = p3 = p2 = p1 = get_past_head((char_u *)ffname);
|
||||
for (p = p1; *p; mb_ptr_adv(p)) {
|
||||
if (vim_ispathsep_nocolon(*p)) {
|
||||
p4 = p3; p3 = p2; p2 = p1; p1 = p;
|
||||
|
@ -2521,13 +2519,13 @@ static void add_pack_plugin(char_u *fname, void *cookie)
|
|||
*p4 = NUL;
|
||||
|
||||
// Find "ffname" in "p_rtp", ignoring '/' vs '\' differences
|
||||
size_t fname_len = STRLEN(ffname);
|
||||
char_u *insp = p_rtp;
|
||||
size_t fname_len = strlen(ffname);
|
||||
const char *insp = (const char *)p_rtp;
|
||||
for (;;) {
|
||||
if (vim_fnamencmp(insp, ffname, fname_len) == 0) {
|
||||
if (path_fnamencmp(insp, ffname, fname_len) == 0) {
|
||||
break;
|
||||
}
|
||||
insp = vim_strchr(insp, ',');
|
||||
insp = strchr(insp, ',');
|
||||
if (insp == NULL) {
|
||||
break;
|
||||
}
|
||||
|
@ -2536,10 +2534,10 @@ static void add_pack_plugin(char_u *fname, void *cookie)
|
|||
|
||||
if (insp == NULL) {
|
||||
// not found, append at the end
|
||||
insp = p_rtp + STRLEN(p_rtp);
|
||||
insp = (const char *)p_rtp + STRLEN(p_rtp);
|
||||
} else {
|
||||
// append after the matching directory.
|
||||
insp += STRLEN(ffname);
|
||||
insp += strlen(ffname);
|
||||
while (*insp != NUL && *insp != ',') {
|
||||
insp++;
|
||||
}
|
||||
|
@ -2547,31 +2545,40 @@ static void add_pack_plugin(char_u *fname, void *cookie)
|
|||
*p4 = c;
|
||||
|
||||
// check if rtp/pack/name/start/name/after exists
|
||||
char *afterdir = concat_fnames((char *)ffname, "after", true);
|
||||
char *afterdir = concat_fnames(ffname, "after", true);
|
||||
size_t afterlen = 0;
|
||||
if (os_isdir((char_u *)afterdir)) {
|
||||
afterlen = STRLEN(afterdir) + 1; // add one for comma
|
||||
afterlen = strlen(afterdir) + 1; // add one for comma
|
||||
}
|
||||
|
||||
size_t oldlen = STRLEN(p_rtp);
|
||||
size_t addlen = STRLEN(ffname) + 1; // add one for comma
|
||||
new_rtp = try_malloc(oldlen + addlen + afterlen + 1); // add one for NUL
|
||||
const size_t oldlen = STRLEN(p_rtp);
|
||||
const size_t addlen = strlen(ffname) + 1; // add one for comma
|
||||
const size_t new_rtp_len = oldlen + addlen + afterlen + 1;
|
||||
// add one for NUL -------------------------------------^
|
||||
char *const new_rtp = try_malloc(new_rtp_len);
|
||||
if (new_rtp == NULL) {
|
||||
goto theend;
|
||||
}
|
||||
uintptr_t keep = (uintptr_t)(insp - p_rtp);
|
||||
const size_t keep = (size_t)(insp - (const char *)p_rtp);
|
||||
size_t new_rtp_fill = 0;
|
||||
memmove(new_rtp, p_rtp, keep);
|
||||
new_rtp[keep] = ',';
|
||||
memmove(new_rtp + keep + 1, ffname, addlen);
|
||||
new_rtp_fill += keep;
|
||||
new_rtp[new_rtp_fill++] = ',';
|
||||
memmove(new_rtp + new_rtp_fill, ffname, addlen);
|
||||
new_rtp_fill += addlen - 1;
|
||||
assert(new_rtp[new_rtp_fill] == NUL || new_rtp[new_rtp_fill] == ',');
|
||||
if (p_rtp[keep] != NUL) {
|
||||
memmove(new_rtp + keep + addlen, p_rtp + keep,
|
||||
oldlen - keep + 1);
|
||||
memmove(new_rtp + new_rtp_fill, p_rtp + keep, oldlen - keep + 1);
|
||||
new_rtp_fill += oldlen - keep;
|
||||
}
|
||||
if (afterlen > 0) {
|
||||
STRCAT(new_rtp, ",");
|
||||
STRCAT(new_rtp, afterdir);
|
||||
assert(new_rtp[new_rtp_fill] == NUL);
|
||||
new_rtp[new_rtp_fill++] = ',';
|
||||
memmove(new_rtp + new_rtp_fill, afterdir, afterlen - 1);
|
||||
new_rtp_fill += afterlen - 1;
|
||||
}
|
||||
set_option_value((char_u *)"rtp", 0L, new_rtp, 0);
|
||||
new_rtp[new_rtp_fill] = NUL;
|
||||
set_option_value("rtp", 0L, new_rtp, 0);
|
||||
xfree(new_rtp);
|
||||
xfree(afterdir);
|
||||
}
|
||||
|
@ -2580,7 +2587,7 @@ static void add_pack_plugin(char_u *fname, void *cookie)
|
|||
static const char *plugpat = "%s/plugin/**/*.vim"; // NOLINT
|
||||
static const char *ftpat = "%s/ftdetect/*.vim"; // NOLINT
|
||||
|
||||
size_t len = STRLEN(ffname) + STRLEN(ftpat);
|
||||
size_t len = strlen(ffname) + STRLEN(ftpat);
|
||||
char_u *pat = try_malloc(len + 1);
|
||||
if (pat == NULL) {
|
||||
goto theend;
|
||||
|
@ -3699,12 +3706,12 @@ static void script_host_execute(char *name, exarg_T *eap)
|
|||
char *const script = script_get(eap, &len);
|
||||
|
||||
if (script != NULL) {
|
||||
list_T *const args = list_alloc();
|
||||
list_T *const args = tv_list_alloc();
|
||||
// script
|
||||
list_append_allocated_string(args, script);
|
||||
tv_list_append_allocated_string(args, script);
|
||||
// current range
|
||||
list_append_number(args, (int)eap->line1);
|
||||
list_append_number(args, (int)eap->line2);
|
||||
tv_list_append_number(args, (int)eap->line1);
|
||||
tv_list_append_number(args, (int)eap->line2);
|
||||
(void)eval_call_provider(name, "execute", args);
|
||||
}
|
||||
}
|
||||
|
@ -3714,21 +3721,21 @@ static void script_host_execute_file(char *name, exarg_T *eap)
|
|||
uint8_t buffer[MAXPATHL];
|
||||
vim_FullName((char *)eap->arg, (char *)buffer, sizeof(buffer), false);
|
||||
|
||||
list_T *args = list_alloc();
|
||||
list_T *args = tv_list_alloc();
|
||||
// filename
|
||||
list_append_string(args, buffer, -1);
|
||||
tv_list_append_string(args, (const char *)buffer, -1);
|
||||
// current range
|
||||
list_append_number(args, (int)eap->line1);
|
||||
list_append_number(args, (int)eap->line2);
|
||||
tv_list_append_number(args, (int)eap->line1);
|
||||
tv_list_append_number(args, (int)eap->line2);
|
||||
(void)eval_call_provider(name, "execute_file", args);
|
||||
}
|
||||
|
||||
static void script_host_do_range(char *name, exarg_T *eap)
|
||||
{
|
||||
list_T *args = list_alloc();
|
||||
list_append_number(args, (int)eap->line1);
|
||||
list_append_number(args, (int)eap->line2);
|
||||
list_append_string(args, eap->arg, -1);
|
||||
list_T *args = tv_list_alloc();
|
||||
tv_list_append_number(args, (int)eap->line1);
|
||||
tv_list_append_number(args, (int)eap->line2);
|
||||
tv_list_append_string(args, (const char *)eap->arg, -1);
|
||||
(void)eval_call_provider(name, "do_range", args);
|
||||
}
|
||||
|
||||
|
|
|
@ -68,6 +68,7 @@
|
|||
#include "nvim/event/wstream.h"
|
||||
#include "nvim/shada.h"
|
||||
#include "nvim/viml/executor/executor.h"
|
||||
#include "nvim/globals.h"
|
||||
|
||||
static int quitmore = 0;
|
||||
static int ex_pressedreturn = FALSE;
|
||||
|
@ -270,7 +271,7 @@ do_exmode (
|
|||
/*
|
||||
* Execute a simple command line. Used for translated commands like "*".
|
||||
*/
|
||||
int do_cmdline_cmd(char *cmd)
|
||||
int do_cmdline_cmd(const char *cmd)
|
||||
{
|
||||
return do_cmdline((char_u *)cmd, NULL, NULL,
|
||||
DOCMD_NOWAIT|DOCMD_KEYTYPED);
|
||||
|
@ -2633,32 +2634,27 @@ int cmd_exists(const char *const name)
|
|||
* perfectly compatible with each other, but then the command line syntax
|
||||
* probably won't change that much -- webb.
|
||||
*/
|
||||
char_u *
|
||||
set_one_cmd_context (
|
||||
const char * set_one_cmd_context(
|
||||
expand_T *xp,
|
||||
char_u *buff /* buffer for command string */
|
||||
const char *buff // buffer for command string
|
||||
)
|
||||
{
|
||||
char_u *p;
|
||||
char_u *cmd, *arg;
|
||||
int len = 0;
|
||||
size_t len = 0;
|
||||
exarg_T ea;
|
||||
int compl = EXPAND_NOTHING;
|
||||
int delim;
|
||||
int forceit = FALSE;
|
||||
int usefilter = FALSE; /* filter instead of file name */
|
||||
int context = EXPAND_NOTHING;
|
||||
int forceit = false;
|
||||
int usefilter = false; // Filter instead of file name.
|
||||
|
||||
ExpandInit(xp);
|
||||
xp->xp_pattern = buff;
|
||||
xp->xp_context = EXPAND_COMMANDS; /* Default until we get past command */
|
||||
xp->xp_pattern = (char_u *)buff;
|
||||
xp->xp_context = EXPAND_COMMANDS; // Default until we get past command
|
||||
ea.argt = 0;
|
||||
|
||||
/*
|
||||
* 2. skip comment lines and leading space, colons or bars
|
||||
*/
|
||||
for (cmd = buff; vim_strchr((char_u *)" \t:|", *cmd) != NULL; cmd++)
|
||||
;
|
||||
xp->xp_pattern = cmd;
|
||||
// 2. skip comment lines and leading space, colons or bars
|
||||
const char *cmd;
|
||||
for (cmd = buff; strchr(" \t:|", *cmd) != NULL; cmd++) {
|
||||
}
|
||||
xp->xp_pattern = (char_u *)cmd;
|
||||
|
||||
if (*cmd == NUL)
|
||||
return NULL;
|
||||
|
@ -2670,14 +2666,15 @@ set_one_cmd_context (
|
|||
/*
|
||||
* 3. parse a range specifier of the form: addr [,addr] [;addr] ..
|
||||
*/
|
||||
cmd = skip_range(cmd, &xp->xp_context);
|
||||
cmd = (const char *)skip_range((const char_u *)cmd, &xp->xp_context);
|
||||
|
||||
/*
|
||||
* 4. parse command
|
||||
*/
|
||||
xp->xp_pattern = cmd;
|
||||
if (*cmd == NUL)
|
||||
xp->xp_pattern = (char_u *)cmd;
|
||||
if (*cmd == NUL) {
|
||||
return NULL;
|
||||
}
|
||||
if (*cmd == '"') {
|
||||
xp->xp_context = EXPAND_NOTHING;
|
||||
return NULL;
|
||||
|
@ -2693,6 +2690,7 @@ set_one_cmd_context (
|
|||
* do accept "keepmarks", "keepalt" and "keepjumps".
|
||||
* - the 's' command can be followed directly by 'c', 'g', 'i', 'I' or 'r'
|
||||
*/
|
||||
const char *p;
|
||||
if (*cmd == 'k' && cmd[1] != 'e') {
|
||||
ea.cmdidx = CMD_k;
|
||||
p = cmd + 1;
|
||||
|
@ -2715,20 +2713,21 @@ set_one_cmd_context (
|
|||
}
|
||||
}
|
||||
// check for non-alpha command
|
||||
if (p == cmd && vim_strchr((char_u *)"@*!=><&~#", *p) != NULL) {
|
||||
if (p == cmd && strchr("@*!=><&~#", *p) != NULL) {
|
||||
p++;
|
||||
}
|
||||
len = (int)(p - cmd);
|
||||
len = (size_t)(p - cmd);
|
||||
|
||||
if (len == 0) {
|
||||
xp->xp_context = EXPAND_UNSUCCESSFUL;
|
||||
return NULL;
|
||||
}
|
||||
for (ea.cmdidx = (cmdidx_T)0; (int)ea.cmdidx < (int)CMD_SIZE;
|
||||
ea.cmdidx = (cmdidx_T)((int)ea.cmdidx + 1))
|
||||
if (STRNCMP(cmdnames[(int)ea.cmdidx].cmd_name, cmd,
|
||||
(size_t)len) == 0)
|
||||
ea.cmdidx = (cmdidx_T)((int)ea.cmdidx + 1)) {
|
||||
if (STRNCMP(cmdnames[(int)ea.cmdidx].cmd_name, cmd, len) == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (cmd[0] >= 'A' && cmd[0] <= 'Z') {
|
||||
while (ASCII_ISALNUM(*p) || *p == '*') { // Allow * wild card
|
||||
|
@ -2745,16 +2744,15 @@ set_one_cmd_context (
|
|||
return NULL;
|
||||
|
||||
if (ea.cmdidx == CMD_SIZE) {
|
||||
if (*cmd == 's' && vim_strchr((char_u *)"cgriI", cmd[1]) != NULL) {
|
||||
if (*cmd == 's' && strchr("cgriI", cmd[1]) != NULL) {
|
||||
ea.cmdidx = CMD_substitute;
|
||||
p = cmd + 1;
|
||||
} else if (cmd[0] >= 'A' && cmd[0] <= 'Z') {
|
||||
ea.cmd = cmd;
|
||||
p = find_ucmd(&ea, p, NULL, xp,
|
||||
&compl
|
||||
);
|
||||
if (p == NULL)
|
||||
ea.cmdidx = CMD_SIZE; /* ambiguous user command */
|
||||
ea.cmd = (char_u *)cmd;
|
||||
p = (const char *)find_ucmd(&ea, (char_u *)p, NULL, xp, &context);
|
||||
if (p == NULL) {
|
||||
ea.cmdidx = CMD_SIZE; // Ambiguous user command.
|
||||
}
|
||||
}
|
||||
}
|
||||
if (ea.cmdidx == CMD_SIZE) {
|
||||
|
@ -2777,16 +2775,17 @@ set_one_cmd_context (
|
|||
ea.argt = cmdnames[(int)ea.cmdidx].cmd_argt;
|
||||
}
|
||||
|
||||
arg = skipwhite(p);
|
||||
const char *arg = (const char *)skipwhite((const char_u *)p);
|
||||
|
||||
if (ea.cmdidx == CMD_write || ea.cmdidx == CMD_update) {
|
||||
if (*arg == '>') { /* append */
|
||||
if (*++arg == '>')
|
||||
++arg;
|
||||
arg = skipwhite(arg);
|
||||
} else if (*arg == '!' && ea.cmdidx == CMD_write) { /* :w !filter */
|
||||
++arg;
|
||||
usefilter = TRUE;
|
||||
if (*arg == '>') { // Append.
|
||||
if (*++arg == '>') {
|
||||
arg++;
|
||||
}
|
||||
arg = (const char *)skipwhite((const char_u *)arg);
|
||||
} else if (*arg == '!' && ea.cmdidx == CMD_write) { // :w !filter
|
||||
arg++;
|
||||
usefilter = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2799,23 +2798,24 @@ set_one_cmd_context (
|
|||
}
|
||||
|
||||
if (ea.cmdidx == CMD_lshift || ea.cmdidx == CMD_rshift) {
|
||||
while (*arg == *cmd) /* allow any number of '>' or '<' */
|
||||
++arg;
|
||||
arg = skipwhite(arg);
|
||||
while (*arg == *cmd) { // allow any number of '>' or '<'
|
||||
arg++;
|
||||
}
|
||||
arg = (const char *)skipwhite((const char_u *)arg);
|
||||
}
|
||||
|
||||
/* Does command allow "+command"? */
|
||||
if ((ea.argt & EDITCMD) && !usefilter && *arg == '+') {
|
||||
/* Check if we're in the +command */
|
||||
p = arg + 1;
|
||||
arg = skip_cmd_arg(arg, FALSE);
|
||||
arg = (const char *)skip_cmd_arg((char_u *)arg, false);
|
||||
|
||||
/* Still touching the command after '+'? */
|
||||
if (*arg == NUL)
|
||||
return p;
|
||||
|
||||
/* Skip space(s) after +command to get to the real argument */
|
||||
arg = skipwhite(arg);
|
||||
// Skip space(s) after +command to get to the real argument.
|
||||
arg = (const char *)skipwhite((const char_u *)arg);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -2844,19 +2844,18 @@ set_one_cmd_context (
|
|||
}
|
||||
|
||||
// no arguments allowed
|
||||
if (!(ea.argt & EXTRA) && *arg != NUL
|
||||
&& vim_strchr((char_u *)"|\"", *arg) == NULL) {
|
||||
if (!(ea.argt & EXTRA) && *arg != NUL && strchr("|\"", *arg) == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Find start of last argument (argument just before cursor): */
|
||||
p = buff;
|
||||
xp->xp_pattern = p;
|
||||
len = (int)STRLEN(buff);
|
||||
xp->xp_pattern = (char_u *)p;
|
||||
len = strlen(buff);
|
||||
while (*p && p < buff + len) {
|
||||
if (*p == ' ' || *p == TAB) {
|
||||
/* argument starts after a space */
|
||||
xp->xp_pattern = ++p;
|
||||
// Argument starts after a space.
|
||||
xp->xp_pattern = (char_u *)++p;
|
||||
} else {
|
||||
if (*p == '\\' && *(p + 1) != NUL)
|
||||
++p; /* skip over escaped character */
|
||||
|
@ -2866,25 +2865,26 @@ set_one_cmd_context (
|
|||
|
||||
if (ea.argt & XFILE) {
|
||||
int c;
|
||||
int in_quote = FALSE;
|
||||
char_u *bow = NULL; /* Beginning of word */
|
||||
int in_quote = false;
|
||||
const char *bow = NULL; // Beginning of word.
|
||||
|
||||
/*
|
||||
* Allow spaces within back-quotes to count as part of the argument
|
||||
* being expanded.
|
||||
*/
|
||||
xp->xp_pattern = skipwhite(arg);
|
||||
p = xp->xp_pattern;
|
||||
xp->xp_pattern = skipwhite((const char_u *)arg);
|
||||
p = (const char *)xp->xp_pattern;
|
||||
while (*p != NUL) {
|
||||
if (has_mbyte)
|
||||
c = mb_ptr2char(p);
|
||||
else
|
||||
c = *p;
|
||||
if (c == '\\' && p[1] != NUL)
|
||||
++p;
|
||||
else if (c == '`') {
|
||||
if (has_mbyte) {
|
||||
c = mb_ptr2char((const char_u *)p);
|
||||
} else {
|
||||
c = (uint8_t)(*p);
|
||||
}
|
||||
if (c == '\\' && p[1] != NUL) {
|
||||
p++;
|
||||
} else if (c == '`') {
|
||||
if (!in_quote) {
|
||||
xp->xp_pattern = p;
|
||||
xp->xp_pattern = (char_u *)p;
|
||||
bow = p + 1;
|
||||
}
|
||||
in_quote = !in_quote;
|
||||
|
@ -2897,22 +2897,26 @@ set_one_cmd_context (
|
|||
|| ascii_iswhite(c)) {
|
||||
len = 0; /* avoid getting stuck when space is in 'isfname' */
|
||||
while (*p != NUL) {
|
||||
if (has_mbyte)
|
||||
c = mb_ptr2char(p);
|
||||
else
|
||||
if (has_mbyte) {
|
||||
c = mb_ptr2char((const char_u *)p);
|
||||
} else {
|
||||
c = *p;
|
||||
if (c == '`' || vim_isfilec_or_wc(c))
|
||||
}
|
||||
if (c == '`' || vim_isfilec_or_wc(c)) {
|
||||
break;
|
||||
if (has_mbyte)
|
||||
len = (*mb_ptr2len)(p);
|
||||
else
|
||||
}
|
||||
if (has_mbyte) {
|
||||
len = (size_t)(*mb_ptr2len)((const char_u *)p);
|
||||
} else {
|
||||
len = 1;
|
||||
}
|
||||
mb_ptr_adv(p);
|
||||
}
|
||||
if (in_quote)
|
||||
if (in_quote) {
|
||||
bow = p;
|
||||
else
|
||||
xp->xp_pattern = p;
|
||||
} else {
|
||||
xp->xp_pattern = (char_u *)p;
|
||||
}
|
||||
p -= len;
|
||||
}
|
||||
mb_ptr_adv(p);
|
||||
|
@ -2922,8 +2926,9 @@ set_one_cmd_context (
|
|||
* If we are still inside the quotes, and we passed a space, just
|
||||
* expand from there.
|
||||
*/
|
||||
if (bow != NULL && in_quote)
|
||||
xp->xp_pattern = bow;
|
||||
if (bow != NULL && in_quote) {
|
||||
xp->xp_pattern = (char_u *)bow;
|
||||
}
|
||||
xp->xp_context = EXPAND_FILES;
|
||||
|
||||
/* For a shell command more chars need to be escaped. */
|
||||
|
@ -2931,33 +2936,36 @@ set_one_cmd_context (
|
|||
#ifndef BACKSLASH_IN_FILENAME
|
||||
xp->xp_shell = TRUE;
|
||||
#endif
|
||||
/* When still after the command name expand executables. */
|
||||
if (xp->xp_pattern == skipwhite(arg))
|
||||
// When still after the command name expand executables.
|
||||
if (xp->xp_pattern == skipwhite((const char_u *)arg)) {
|
||||
xp->xp_context = EXPAND_SHELLCMD;
|
||||
}
|
||||
}
|
||||
|
||||
/* Check for environment variable */
|
||||
if (*xp->xp_pattern == '$'
|
||||
) {
|
||||
for (p = xp->xp_pattern + 1; *p != NUL; ++p)
|
||||
if (!vim_isIDc(*p))
|
||||
// Check for environment variable.
|
||||
if (*xp->xp_pattern == '$') {
|
||||
for (p = (const char *)xp->xp_pattern + 1; *p != NUL; p++) {
|
||||
if (!vim_isIDc((uint8_t)(*p))) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (*p == NUL) {
|
||||
xp->xp_context = EXPAND_ENV_VARS;
|
||||
++xp->xp_pattern;
|
||||
/* Avoid that the assignment uses EXPAND_FILES again. */
|
||||
if (compl != EXPAND_USER_DEFINED && compl != EXPAND_USER_LIST)
|
||||
compl = EXPAND_ENV_VARS;
|
||||
xp->xp_pattern++;
|
||||
// Avoid that the assignment uses EXPAND_FILES again.
|
||||
if (context != EXPAND_USER_DEFINED && context != EXPAND_USER_LIST) {
|
||||
context = EXPAND_ENV_VARS;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Check for user names */
|
||||
if (*xp->xp_pattern == '~') {
|
||||
for (p = xp->xp_pattern + 1; *p != NUL && *p != '/'; ++p)
|
||||
;
|
||||
/* Complete ~user only if it partially matches a user name.
|
||||
* A full match ~user<Tab> will be replaced by user's home
|
||||
* directory i.e. something like ~user<Tab> -> /home/user/ */
|
||||
if (*p == NUL && p > xp->xp_pattern + 1
|
||||
for (p = (const char *)xp->xp_pattern + 1; *p != NUL && *p != '/'; p++) {
|
||||
}
|
||||
// Complete ~user only if it partially matches a user name.
|
||||
// A full match ~user<Tab> will be replaced by user's home
|
||||
// directory i.e. something like ~user<Tab> -> /home/user/
|
||||
if (*p == NUL && p > (const char *)xp->xp_pattern + 1
|
||||
&& match_user(xp->xp_pattern + 1) == 1) {
|
||||
xp->xp_context = EXPAND_USER;
|
||||
++xp->xp_pattern;
|
||||
|
@ -2987,7 +2995,7 @@ set_one_cmd_context (
|
|||
break;
|
||||
case CMD_help:
|
||||
xp->xp_context = EXPAND_HELP;
|
||||
xp->xp_pattern = arg;
|
||||
xp->xp_pattern = (char_u *)arg;
|
||||
break;
|
||||
|
||||
/* Command modifiers: return the argument.
|
||||
|
@ -3030,13 +3038,14 @@ set_one_cmd_context (
|
|||
if (*arg == NUL || !ends_excmd(*arg)) {
|
||||
/* also complete "None" */
|
||||
set_context_in_echohl_cmd(xp, arg);
|
||||
arg = skipwhite(skiptowhite(arg));
|
||||
arg = (const char *)skipwhite(skiptowhite((const char_u *)arg));
|
||||
if (*arg != NUL) {
|
||||
xp->xp_context = EXPAND_NOTHING;
|
||||
arg = skip_regexp(arg + 1, *arg, p_magic, NULL);
|
||||
arg = (const char *)skip_regexp((char_u *)arg + 1, (uint8_t)(*arg),
|
||||
p_magic, NULL);
|
||||
}
|
||||
}
|
||||
return find_nextcmd(arg);
|
||||
return (const char *)find_nextcmd((char_u *)arg);
|
||||
|
||||
/*
|
||||
* All completion for the +cmdline_compl feature goes here.
|
||||
|
@ -3045,15 +3054,15 @@ set_one_cmd_context (
|
|||
case CMD_command:
|
||||
/* Check for attributes */
|
||||
while (*arg == '-') {
|
||||
arg++; /* Skip "-" */
|
||||
p = skiptowhite(arg);
|
||||
arg++; // Skip "-".
|
||||
p = (const char *)skiptowhite((const char_u *)arg);
|
||||
if (*p == NUL) {
|
||||
/* Cursor is still in the attribute */
|
||||
p = vim_strchr(arg, '=');
|
||||
// Cursor is still in the attribute.
|
||||
p = strchr(arg, '=');
|
||||
if (p == NULL) {
|
||||
/* No "=", so complete attribute names */
|
||||
// No "=", so complete attribute names.
|
||||
xp->xp_context = EXPAND_USER_CMD_FLAGS;
|
||||
xp->xp_pattern = arg;
|
||||
xp->xp_pattern = (char_u *)arg;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -3061,73 +3070,81 @@ set_one_cmd_context (
|
|||
// their arguments as well.
|
||||
if (STRNICMP(arg, "complete", p - arg) == 0) {
|
||||
xp->xp_context = EXPAND_USER_COMPLETE;
|
||||
xp->xp_pattern = p + 1;
|
||||
xp->xp_pattern = (char_u *)p + 1;
|
||||
return NULL;
|
||||
} else if (STRNICMP(arg, "nargs", p - arg) == 0) {
|
||||
xp->xp_context = EXPAND_USER_NARGS;
|
||||
xp->xp_pattern = p + 1;
|
||||
xp->xp_pattern = (char_u *)p + 1;
|
||||
return NULL;
|
||||
} else if (STRNICMP(arg, "addr", p - arg) == 0) {
|
||||
xp->xp_context = EXPAND_USER_ADDR_TYPE;
|
||||
xp->xp_pattern = p + 1;
|
||||
xp->xp_pattern = (char_u *)p + 1;
|
||||
return NULL;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
arg = skipwhite(p);
|
||||
arg = (const char *)skipwhite((char_u *)p);
|
||||
}
|
||||
|
||||
/* After the attributes comes the new command name */
|
||||
p = skiptowhite(arg);
|
||||
// After the attributes comes the new command name.
|
||||
p = (const char *)skiptowhite((const char_u *)arg);
|
||||
if (*p == NUL) {
|
||||
xp->xp_context = EXPAND_USER_COMMANDS;
|
||||
xp->xp_pattern = arg;
|
||||
xp->xp_pattern = (char_u *)arg;
|
||||
break;
|
||||
}
|
||||
|
||||
/* And finally comes a normal command */
|
||||
return skipwhite(p);
|
||||
// And finally comes a normal command.
|
||||
return (const char *)skipwhite((const char_u *)p);
|
||||
|
||||
case CMD_delcommand:
|
||||
xp->xp_context = EXPAND_USER_COMMANDS;
|
||||
xp->xp_pattern = arg;
|
||||
xp->xp_pattern = (char_u *)arg;
|
||||
break;
|
||||
|
||||
case CMD_global:
|
||||
case CMD_vglobal:
|
||||
delim = *arg; /* get the delimiter */
|
||||
if (delim)
|
||||
++arg; /* skip delimiter if there is one */
|
||||
case CMD_vglobal: {
|
||||
const int delim = (uint8_t)(*arg); // Get the delimiter.
|
||||
if (delim) {
|
||||
arg++; // Skip delimiter if there is one.
|
||||
}
|
||||
|
||||
while (arg[0] != NUL && arg[0] != delim) {
|
||||
if (arg[0] == '\\' && arg[1] != NUL)
|
||||
++arg;
|
||||
++arg;
|
||||
while (arg[0] != NUL && (uint8_t)arg[0] != delim) {
|
||||
if (arg[0] == '\\' && arg[1] != NUL) {
|
||||
arg++;
|
||||
}
|
||||
arg++;
|
||||
}
|
||||
if (arg[0] != NUL)
|
||||
return arg + 1;
|
||||
break;
|
||||
}
|
||||
case CMD_and:
|
||||
case CMD_substitute:
|
||||
delim = *arg;
|
||||
case CMD_substitute: {
|
||||
const int delim = (uint8_t)(*arg);
|
||||
if (delim) {
|
||||
/* skip "from" part */
|
||||
++arg;
|
||||
arg = skip_regexp(arg, delim, p_magic, NULL);
|
||||
// Skip "from" part.
|
||||
arg++;
|
||||
arg = (const char *)skip_regexp((char_u *)arg, delim, p_magic, NULL);
|
||||
}
|
||||
/* skip "to" part */
|
||||
while (arg[0] != NUL && arg[0] != delim) {
|
||||
if (arg[0] == '\\' && arg[1] != NUL)
|
||||
++arg;
|
||||
++arg;
|
||||
// Skip "to" part.
|
||||
while (arg[0] != NUL && (uint8_t)arg[0] != delim) {
|
||||
if (arg[0] == '\\' && arg[1] != NUL) {
|
||||
arg++;
|
||||
}
|
||||
arg++;
|
||||
}
|
||||
if (arg[0] != NUL) /* skip delimiter */
|
||||
++arg;
|
||||
while (arg[0] && vim_strchr((char_u *)"|\"#", arg[0]) == NULL)
|
||||
++arg;
|
||||
if (arg[0] != NUL)
|
||||
if (arg[0] != NUL) { // Skip delimiter.
|
||||
arg++;
|
||||
}
|
||||
while (arg[0] && strchr("|\"#", arg[0]) == NULL) {
|
||||
arg++;
|
||||
}
|
||||
if (arg[0] != NUL) {
|
||||
return arg;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case CMD_isearch:
|
||||
case CMD_dsearch:
|
||||
case CMD_ilist:
|
||||
|
@ -3137,36 +3154,40 @@ set_one_cmd_context (
|
|||
case CMD_djump:
|
||||
case CMD_isplit:
|
||||
case CMD_dsplit:
|
||||
arg = skipwhite(skipdigits(arg)); /* skip count */
|
||||
if (*arg == '/') { /* Match regexp, not just whole words */
|
||||
for (++arg; *arg && *arg != '/'; arg++)
|
||||
if (*arg == '\\' && arg[1] != NUL)
|
||||
// Skip count.
|
||||
arg = (const char *)skipwhite(skipdigits((const char_u *)arg));
|
||||
if (*arg == '/') { // Match regexp, not just whole words.
|
||||
for (++arg; *arg && *arg != '/'; arg++) {
|
||||
if (*arg == '\\' && arg[1] != NUL) {
|
||||
arg++;
|
||||
}
|
||||
}
|
||||
if (*arg) {
|
||||
arg = skipwhite(arg + 1);
|
||||
arg = (const char *)skipwhite((const char_u *)arg + 1);
|
||||
|
||||
/* Check for trailing illegal characters */
|
||||
if (*arg && vim_strchr((char_u *)"|\"\n", *arg) == NULL)
|
||||
// Check for trailing illegal characters.
|
||||
if (*arg && strchr("|\"\n", *arg) == NULL) {
|
||||
xp->xp_context = EXPAND_NOTHING;
|
||||
else
|
||||
} else {
|
||||
return arg;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case CMD_autocmd:
|
||||
return set_context_in_autocmd(xp, arg, FALSE);
|
||||
return (const char *)set_context_in_autocmd(xp, (char_u *)arg, false);
|
||||
|
||||
case CMD_doautocmd:
|
||||
case CMD_doautoall:
|
||||
return set_context_in_autocmd(xp, arg, TRUE);
|
||||
return (const char *)set_context_in_autocmd(xp, (char_u *)arg, true);
|
||||
case CMD_set:
|
||||
set_context_in_set_cmd(xp, arg, 0);
|
||||
set_context_in_set_cmd(xp, (char_u *)arg, 0);
|
||||
break;
|
||||
case CMD_setglobal:
|
||||
set_context_in_set_cmd(xp, arg, OPT_GLOBAL);
|
||||
set_context_in_set_cmd(xp, (char_u *)arg, OPT_GLOBAL);
|
||||
break;
|
||||
case CMD_setlocal:
|
||||
set_context_in_set_cmd(xp, arg, OPT_LOCAL);
|
||||
set_context_in_set_cmd(xp, (char_u *)arg, OPT_LOCAL);
|
||||
break;
|
||||
case CMD_tag:
|
||||
case CMD_stag:
|
||||
|
@ -3178,15 +3199,16 @@ set_one_cmd_context (
|
|||
case CMD_tjump:
|
||||
case CMD_stjump:
|
||||
case CMD_ptjump:
|
||||
if (*p_wop != NUL)
|
||||
if (*p_wop != NUL) {
|
||||
xp->xp_context = EXPAND_TAGS_LISTFILES;
|
||||
else
|
||||
} else {
|
||||
xp->xp_context = EXPAND_TAGS;
|
||||
xp->xp_pattern = arg;
|
||||
}
|
||||
xp->xp_pattern = (char_u *)arg;
|
||||
break;
|
||||
case CMD_augroup:
|
||||
xp->xp_context = EXPAND_AUGROUP;
|
||||
xp->xp_pattern = arg;
|
||||
xp->xp_pattern = (char_u *)arg;
|
||||
break;
|
||||
case CMD_syntax:
|
||||
set_context_in_syntax_cmd(xp, arg);
|
||||
|
@ -3203,20 +3225,21 @@ set_one_cmd_context (
|
|||
case CMD_echoerr:
|
||||
case CMD_call:
|
||||
case CMD_return:
|
||||
set_context_for_expression(xp, arg, ea.cmdidx);
|
||||
set_context_for_expression(xp, (char_u *)arg, ea.cmdidx);
|
||||
break;
|
||||
|
||||
case CMD_unlet:
|
||||
while ((xp->xp_pattern = vim_strchr(arg, ' ')) != NULL)
|
||||
arg = xp->xp_pattern + 1;
|
||||
while ((xp->xp_pattern = (char_u *)strchr(arg, ' ')) != NULL) {
|
||||
arg = (const char *)xp->xp_pattern + 1;
|
||||
}
|
||||
xp->xp_context = EXPAND_USER_VARS;
|
||||
xp->xp_pattern = arg;
|
||||
xp->xp_pattern = (char_u *)arg;
|
||||
break;
|
||||
|
||||
case CMD_function:
|
||||
case CMD_delfunction:
|
||||
xp->xp_context = EXPAND_USER_FUNC;
|
||||
xp->xp_pattern = arg;
|
||||
xp->xp_pattern = (char_u *)arg;
|
||||
break;
|
||||
|
||||
case CMD_echohl:
|
||||
|
@ -3231,33 +3254,37 @@ set_one_cmd_context (
|
|||
set_context_in_cscope_cmd(xp, arg, ea.cmdidx);
|
||||
break;
|
||||
case CMD_sign:
|
||||
set_context_in_sign_cmd(xp, arg);
|
||||
set_context_in_sign_cmd(xp, (char_u *)arg);
|
||||
break;
|
||||
case CMD_bdelete:
|
||||
case CMD_bwipeout:
|
||||
case CMD_bunload:
|
||||
while ((xp->xp_pattern = vim_strchr(arg, ' ')) != NULL)
|
||||
arg = xp->xp_pattern + 1;
|
||||
/*FALLTHROUGH*/
|
||||
while ((xp->xp_pattern = (char_u *)strchr(arg, ' ')) != NULL) {
|
||||
arg = (const char *)xp->xp_pattern + 1;
|
||||
}
|
||||
// FALLTHROUGH
|
||||
case CMD_buffer:
|
||||
case CMD_sbuffer:
|
||||
case CMD_checktime:
|
||||
xp->xp_context = EXPAND_BUFFERS;
|
||||
xp->xp_pattern = arg;
|
||||
xp->xp_pattern = (char_u *)arg;
|
||||
break;
|
||||
case CMD_USER:
|
||||
case CMD_USER_BUF:
|
||||
if (compl != EXPAND_NOTHING) {
|
||||
/* XFILE: file names are handled above */
|
||||
if (context != EXPAND_NOTHING) {
|
||||
// XFILE: file names are handled above.
|
||||
if (!(ea.argt & XFILE)) {
|
||||
if (compl == EXPAND_MENUS)
|
||||
return set_context_in_menu_cmd(xp, cmd, arg, forceit);
|
||||
if (compl == EXPAND_COMMANDS)
|
||||
if (context == EXPAND_MENUS) {
|
||||
return (const char *)set_context_in_menu_cmd(xp, (char_u *)cmd,
|
||||
(char_u *)arg, forceit);
|
||||
} else if (context == EXPAND_COMMANDS) {
|
||||
return arg;
|
||||
if (compl == EXPAND_MAPPINGS)
|
||||
return set_context_in_map_cmd(xp, (char_u *)"map",
|
||||
arg, forceit, FALSE, FALSE, CMD_map);
|
||||
/* Find start of last argument. */
|
||||
} else if (context == EXPAND_MAPPINGS) {
|
||||
return (const char *)set_context_in_map_cmd(
|
||||
xp, (char_u *)"map", (char_u *)arg, forceit, false, false,
|
||||
CMD_map);
|
||||
}
|
||||
// Find start of last argument.
|
||||
p = arg;
|
||||
while (*p) {
|
||||
if (*p == ' ')
|
||||
|
@ -3267,9 +3294,9 @@ set_one_cmd_context (
|
|||
++p; /* skip over escaped character */
|
||||
mb_ptr_adv(p);
|
||||
}
|
||||
xp->xp_pattern = arg;
|
||||
xp->xp_pattern = (char_u *)arg;
|
||||
}
|
||||
xp->xp_context = compl;
|
||||
xp->xp_context = context;
|
||||
}
|
||||
break;
|
||||
case CMD_map: case CMD_noremap:
|
||||
|
@ -3281,8 +3308,8 @@ set_one_cmd_context (
|
|||
case CMD_lmap: case CMD_lnoremap:
|
||||
case CMD_smap: case CMD_snoremap:
|
||||
case CMD_xmap: case CMD_xnoremap:
|
||||
return set_context_in_map_cmd(xp, cmd, arg, forceit,
|
||||
FALSE, FALSE, ea.cmdidx);
|
||||
return (const char *)set_context_in_map_cmd(
|
||||
xp, (char_u *)cmd, (char_u *)arg, forceit, false, false, ea.cmdidx);
|
||||
case CMD_unmap:
|
||||
case CMD_nunmap:
|
||||
case CMD_vunmap:
|
||||
|
@ -3292,18 +3319,18 @@ set_one_cmd_context (
|
|||
case CMD_lunmap:
|
||||
case CMD_sunmap:
|
||||
case CMD_xunmap:
|
||||
return set_context_in_map_cmd(xp, cmd, arg, forceit,
|
||||
FALSE, TRUE, ea.cmdidx);
|
||||
return (const char *)set_context_in_map_cmd(
|
||||
xp, (char_u *)cmd, (char_u *)arg, forceit, false, true, ea.cmdidx);
|
||||
case CMD_abbreviate: case CMD_noreabbrev:
|
||||
case CMD_cabbrev: case CMD_cnoreabbrev:
|
||||
case CMD_iabbrev: case CMD_inoreabbrev:
|
||||
return set_context_in_map_cmd(xp, cmd, arg, forceit,
|
||||
TRUE, FALSE, ea.cmdidx);
|
||||
return (const char *)set_context_in_map_cmd(
|
||||
xp, (char_u *)cmd, (char_u *)arg, forceit, true, false, ea.cmdidx);
|
||||
case CMD_unabbreviate:
|
||||
case CMD_cunabbrev:
|
||||
case CMD_iunabbrev:
|
||||
return set_context_in_map_cmd(xp, cmd, arg, forceit,
|
||||
TRUE, TRUE, ea.cmdidx);
|
||||
return (const char *)set_context_in_map_cmd(
|
||||
xp, (char_u *)cmd, (char_u *)arg, forceit, true, true, ea.cmdidx);
|
||||
case CMD_menu: case CMD_noremenu: case CMD_unmenu:
|
||||
case CMD_amenu: case CMD_anoremenu: case CMD_aunmenu:
|
||||
case CMD_nmenu: case CMD_nnoremenu: case CMD_nunmenu:
|
||||
|
@ -3313,47 +3340,49 @@ set_one_cmd_context (
|
|||
case CMD_cmenu: case CMD_cnoremenu: case CMD_cunmenu:
|
||||
case CMD_tmenu: case CMD_tunmenu:
|
||||
case CMD_popup: case CMD_emenu:
|
||||
return set_context_in_menu_cmd(xp, cmd, arg, forceit);
|
||||
return (const char *)set_context_in_menu_cmd(
|
||||
xp, (char_u *)cmd, (char_u *)arg, forceit);
|
||||
|
||||
case CMD_colorscheme:
|
||||
xp->xp_context = EXPAND_COLORS;
|
||||
xp->xp_pattern = arg;
|
||||
xp->xp_pattern = (char_u *)arg;
|
||||
break;
|
||||
|
||||
case CMD_compiler:
|
||||
xp->xp_context = EXPAND_COMPILER;
|
||||
xp->xp_pattern = arg;
|
||||
xp->xp_pattern = (char_u *)arg;
|
||||
break;
|
||||
|
||||
case CMD_ownsyntax:
|
||||
xp->xp_context = EXPAND_OWNSYNTAX;
|
||||
xp->xp_pattern = arg;
|
||||
xp->xp_pattern = (char_u *)arg;
|
||||
break;
|
||||
|
||||
case CMD_setfiletype:
|
||||
xp->xp_context = EXPAND_FILETYPE;
|
||||
xp->xp_pattern = arg;
|
||||
xp->xp_pattern = (char_u *)arg;
|
||||
break;
|
||||
|
||||
case CMD_packadd:
|
||||
xp->xp_context = EXPAND_PACKADD;
|
||||
xp->xp_pattern = arg;
|
||||
xp->xp_pattern = (char_u *)arg;
|
||||
break;
|
||||
|
||||
#ifdef HAVE_WORKING_LIBINTL
|
||||
case CMD_language:
|
||||
p = skiptowhite(arg);
|
||||
p = (const char *)skiptowhite((const char_u *)arg);
|
||||
if (*p == NUL) {
|
||||
xp->xp_context = EXPAND_LANGUAGE;
|
||||
xp->xp_pattern = arg;
|
||||
xp->xp_pattern = (char_u *)arg;
|
||||
} else {
|
||||
if ( STRNCMP(arg, "messages", p - arg) == 0
|
||||
|| STRNCMP(arg, "ctype", p - arg) == 0
|
||||
|| STRNCMP(arg, "time", p - arg) == 0) {
|
||||
if (strncmp(arg, "messages", p - arg) == 0
|
||||
|| strncmp(arg, "ctype", p - arg) == 0
|
||||
|| strncmp(arg, "time", p - arg) == 0) {
|
||||
xp->xp_context = EXPAND_LOCALES;
|
||||
xp->xp_pattern = skipwhite(p);
|
||||
} else
|
||||
xp->xp_pattern = skipwhite((const char_u *)p);
|
||||
} else {
|
||||
xp->xp_context = EXPAND_NOTHING;
|
||||
}
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
|
@ -3362,16 +3391,16 @@ set_one_cmd_context (
|
|||
break;
|
||||
case CMD_behave:
|
||||
xp->xp_context = EXPAND_BEHAVE;
|
||||
xp->xp_pattern = arg;
|
||||
xp->xp_pattern = (char_u *)arg;
|
||||
break;
|
||||
|
||||
case CMD_history:
|
||||
xp->xp_context = EXPAND_HISTORY;
|
||||
xp->xp_pattern = arg;
|
||||
xp->xp_pattern = (char_u *)arg;
|
||||
break;
|
||||
case CMD_syntime:
|
||||
xp->xp_context = EXPAND_SYNTIME;
|
||||
xp->xp_pattern = arg;
|
||||
xp->xp_pattern = (char_u *)arg;
|
||||
break;
|
||||
|
||||
|
||||
|
@ -3390,10 +3419,9 @@ set_one_cmd_context (
|
|||
* Also skip white space and ":" characters.
|
||||
* Returns the "cmd" pointer advanced to beyond the range.
|
||||
*/
|
||||
char_u *
|
||||
skip_range (
|
||||
char_u *cmd,
|
||||
int *ctx /* pointer to xp_context or NULL */
|
||||
char_u *skip_range(
|
||||
const char_u *cmd,
|
||||
int *ctx // pointer to xp_context or NULL
|
||||
)
|
||||
{
|
||||
unsigned delim;
|
||||
|
@ -3418,7 +3446,7 @@ skip_range (
|
|||
while (*cmd == ':')
|
||||
cmd = skipwhite(cmd + 1);
|
||||
|
||||
return cmd;
|
||||
return (char_u *)cmd;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -4587,14 +4615,15 @@ int ends_excmd(int c) FUNC_ATTR_CONST
|
|||
* Return the next command, after the first '|' or '\n'.
|
||||
* Return NULL if not found.
|
||||
*/
|
||||
char_u *find_nextcmd(char_u *p)
|
||||
char_u *find_nextcmd(const char_u *p)
|
||||
{
|
||||
while (*p != '|' && *p != '\n') {
|
||||
if (*p == NUL)
|
||||
if (*p == NUL) {
|
||||
return NULL;
|
||||
++p;
|
||||
}
|
||||
p++;
|
||||
}
|
||||
return p + 1;
|
||||
return (char_u *)p + 1;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -6796,7 +6825,7 @@ do_exedit (
|
|||
int ms = msg_scroll;
|
||||
|
||||
if (eap->nextcmd != NULL) {
|
||||
stuffReadbuff(eap->nextcmd);
|
||||
stuffReadbuff((const char *)eap->nextcmd);
|
||||
eap->nextcmd = NULL;
|
||||
}
|
||||
|
||||
|
@ -7726,7 +7755,7 @@ static void ex_mkrc(exarg_T *eap)
|
|||
|
||||
/* When using 'viewdir' may have to create the directory. */
|
||||
if (using_vdir && !os_isdir(p_vdir)) {
|
||||
vim_mkdir_emsg(p_vdir, 0755);
|
||||
vim_mkdir_emsg((const char *)p_vdir, 0755);
|
||||
}
|
||||
|
||||
fd = open_exfile((char_u *) fname, eap->forceit, WRITEBIN);
|
||||
|
@ -7838,10 +7867,17 @@ static void ex_mkrc(exarg_T *eap)
|
|||
xfree(viewFile);
|
||||
}
|
||||
|
||||
int vim_mkdir_emsg(char_u *name, int prot)
|
||||
/// Try creating a directory, give error message on failure
|
||||
///
|
||||
/// @param[in] name Directory to create.
|
||||
/// @param[in] prot Directory permissions.
|
||||
///
|
||||
/// @return OK in case of success, FAIL otherwise.
|
||||
int vim_mkdir_emsg(const char *const name, const int prot)
|
||||
FUNC_ATTR_NONNULL_ALL
|
||||
{
|
||||
int ret;
|
||||
if ((ret = os_mkdir((char *)name, prot)) != 0) {
|
||||
if ((ret = os_mkdir(name, prot)) != 0) {
|
||||
EMSG3(_(e_mkdir), name, os_strerror(ret));
|
||||
return FAIL;
|
||||
}
|
||||
|
@ -8418,8 +8454,8 @@ eval_vars (
|
|||
*usedlen = 1;
|
||||
return NULL;
|
||||
}
|
||||
result = list_find_str(get_vim_var_list(VV_OLDFILES),
|
||||
(long)i);
|
||||
result = (char_u *)tv_list_find_str(get_vim_var_list(VV_OLDFILES),
|
||||
i - 1);
|
||||
if (result == NULL) {
|
||||
*errormsg = (char_u *)"";
|
||||
return NULL;
|
||||
|
@ -9349,8 +9385,8 @@ static int ses_put_fname(FILE *fd, char_u *name, unsigned *flagp)
|
|||
*p = '/';
|
||||
}
|
||||
|
||||
/* escape special characters */
|
||||
p = vim_strsave_fnameescape(sname, FALSE);
|
||||
// Escape special characters.
|
||||
p = (char_u *)vim_strsave_fnameescape((const char *)sname, false);
|
||||
xfree(sname);
|
||||
|
||||
/* write the result */
|
||||
|
@ -9485,18 +9521,18 @@ void dialog_msg(char_u *buff, char *format, char_u *fname)
|
|||
static void ex_behave(exarg_T *eap)
|
||||
{
|
||||
if (STRCMP(eap->arg, "mswin") == 0) {
|
||||
set_option_value((char_u *)"selection", 0L, (char_u *)"exclusive", 0);
|
||||
set_option_value((char_u *)"selectmode", 0L, (char_u *)"mouse,key", 0);
|
||||
set_option_value((char_u *)"mousemodel", 0L, (char_u *)"popup", 0);
|
||||
set_option_value((char_u *)"keymodel", 0L,
|
||||
(char_u *)"startsel,stopsel", 0);
|
||||
set_option_value("selection", 0L, "exclusive", 0);
|
||||
set_option_value("selectmode", 0L, "mouse,key", 0);
|
||||
set_option_value("mousemodel", 0L, "popup", 0);
|
||||
set_option_value("keymodel", 0L, "startsel,stopsel", 0);
|
||||
} else if (STRCMP(eap->arg, "xterm") == 0) {
|
||||
set_option_value((char_u *)"selection", 0L, (char_u *)"inclusive", 0);
|
||||
set_option_value((char_u *)"selectmode", 0L, (char_u *)"", 0);
|
||||
set_option_value((char_u *)"mousemodel", 0L, (char_u *)"extend", 0);
|
||||
set_option_value((char_u *)"keymodel", 0L, (char_u *)"", 0);
|
||||
} else
|
||||
set_option_value("selection", 0L, "inclusive", 0);
|
||||
set_option_value("selectmode", 0L, "", 0);
|
||||
set_option_value("mousemodel", 0L, "extend", 0);
|
||||
set_option_value("keymodel", 0L, "", 0);
|
||||
} else {
|
||||
EMSG2(_(e_invarg2), eap->arg);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -9610,8 +9646,9 @@ void filetype_maybe_enable(void)
|
|||
*/
|
||||
static void ex_setfiletype(exarg_T *eap)
|
||||
{
|
||||
if (!did_filetype)
|
||||
set_option_value((char_u *)"filetype", 0L, eap->arg, OPT_LOCAL);
|
||||
if (!did_filetype) {
|
||||
set_option_value("filetype", 0L, (char *)eap->arg, OPT_LOCAL);
|
||||
}
|
||||
}
|
||||
|
||||
static void ex_digraphs(exarg_T *eap)
|
||||
|
@ -9697,7 +9734,8 @@ static void ex_match(exarg_T *eap)
|
|||
|
||||
c = *end;
|
||||
*end = NUL;
|
||||
match_add(curwin, g, p + 1, 10, id, NULL, NULL);
|
||||
match_add(curwin, (const char *)g, (const char *)p + 1, 10, id,
|
||||
NULL, NULL);
|
||||
xfree(g);
|
||||
*end = c;
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
#define NVIM_EX_DOCMD_H
|
||||
|
||||
#include "nvim/ex_cmds_defs.h"
|
||||
#include "nvim/globals.h"
|
||||
|
||||
// flags for do_cmdline()
|
||||
#define DOCMD_VERBOSE 0x01 // included command in error message
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
/*
|
||||
* ex_eval.c: functions for Ex command line for the +eval feature.
|
||||
*/
|
||||
// TODO(ZyX-I): move to eval/executor
|
||||
|
||||
/// @file ex_eval.c
|
||||
///
|
||||
/// Functions for Ex command line for the +eval feature.
|
||||
#include <assert.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
@ -12,6 +14,7 @@
|
|||
#include "nvim/ex_eval.h"
|
||||
#include "nvim/charset.h"
|
||||
#include "nvim/eval.h"
|
||||
#include "nvim/eval/typval.h"
|
||||
#include "nvim/ex_cmds2.h"
|
||||
#include "nvim/ex_docmd.h"
|
||||
#include "nvim/message.h"
|
||||
|
@ -19,8 +22,6 @@
|
|||
#include "nvim/regexp.h"
|
||||
#include "nvim/strings.h"
|
||||
|
||||
|
||||
|
||||
#ifdef INCLUDE_GENERATED_DECLARATIONS
|
||||
# include "ex_eval.c.generated.h"
|
||||
#endif
|
||||
|
@ -57,12 +58,14 @@
|
|||
* is an error exception.) - The macros can be defined as expressions checking
|
||||
* for a variable that is allowed to be changed during execution of a script.
|
||||
*/
|
||||
/* Values used for the Vim release. */
|
||||
# define THROW_ON_ERROR TRUE
|
||||
# define THROW_ON_ERROR_TRUE
|
||||
# define THROW_ON_INTERRUPT TRUE
|
||||
# define THROW_ON_INTERRUPT_TRUE
|
||||
|
||||
// Values used for the Vim release.
|
||||
#define THROW_ON_ERROR true
|
||||
#define THROW_ON_ERROR_TRUE
|
||||
#define THROW_ON_INTERRUPT true
|
||||
#define THROW_ON_INTERRUPT_TRUE
|
||||
|
||||
#define discard_pending_return(p) tv_free((typval_T *)(p))
|
||||
|
||||
/*
|
||||
* When several errors appear in a row, setting "force_abort" is delayed until
|
||||
|
@ -779,7 +782,6 @@ void report_discard_pending(int pending, void *value)
|
|||
*/
|
||||
void ex_if(exarg_T *eap)
|
||||
{
|
||||
int error;
|
||||
int skip;
|
||||
int result;
|
||||
struct condstack *cstack = eap->cstack;
|
||||
|
@ -800,6 +802,7 @@ void ex_if(exarg_T *eap)
|
|||
1] &
|
||||
CSF_ACTIVE));
|
||||
|
||||
bool error;
|
||||
result = eval_to_bool(eap->arg, &error, &eap->nextcmd, skip);
|
||||
|
||||
if (!skip && !error) {
|
||||
|
@ -844,7 +847,6 @@ void ex_endif(exarg_T *eap)
|
|||
*/
|
||||
void ex_else(exarg_T *eap)
|
||||
{
|
||||
int error;
|
||||
int skip;
|
||||
int result;
|
||||
struct condstack *cstack = eap->cstack;
|
||||
|
@ -901,6 +903,7 @@ void ex_else(exarg_T *eap)
|
|||
}
|
||||
|
||||
if (eap->cmdidx == CMD_elseif) {
|
||||
bool error;
|
||||
result = eval_to_bool(eap->arg, &error, &eap->nextcmd, skip);
|
||||
/* When throwing error exceptions, we want to throw always the first
|
||||
* of several errors in a row. This is what actually happens when
|
||||
|
@ -925,7 +928,7 @@ void ex_else(exarg_T *eap)
|
|||
*/
|
||||
void ex_while(exarg_T *eap)
|
||||
{
|
||||
int error;
|
||||
bool error;
|
||||
int skip;
|
||||
int result;
|
||||
struct condstack *cstack = eap->cstack;
|
||||
|
@ -1147,23 +1150,25 @@ void ex_endwhile(exarg_T *eap)
|
|||
*/
|
||||
void ex_throw(exarg_T *eap)
|
||||
{
|
||||
char_u *arg = eap->arg;
|
||||
char_u *value;
|
||||
const char *arg = (const char *)eap->arg;
|
||||
char *value;
|
||||
|
||||
if (*arg != NUL && *arg != '|' && *arg != '\n')
|
||||
value = eval_to_string_skip(arg, &eap->nextcmd, eap->skip);
|
||||
else {
|
||||
if (*arg != NUL && *arg != '|' && *arg != '\n') {
|
||||
value = eval_to_string_skip(arg, (const char **)&eap->nextcmd,
|
||||
(bool)eap->skip);
|
||||
} else {
|
||||
EMSG(_(e_argreq));
|
||||
value = NULL;
|
||||
}
|
||||
|
||||
/* On error or when an exception is thrown during argument evaluation, do
|
||||
* not throw. */
|
||||
// On error or when an exception is thrown during argument evaluation, do
|
||||
// not throw.
|
||||
if (!eap->skip && value != NULL) {
|
||||
if (throw_exception(value, ET_USER, NULL) == FAIL)
|
||||
if (throw_exception((char_u *)value, ET_USER, NULL) == FAIL) {
|
||||
xfree(value);
|
||||
else
|
||||
} else {
|
||||
do_throw(eap->cstack);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
#include <stdlib.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
#include "nvim/assert.h"
|
||||
#include "nvim/vim.h"
|
||||
#include "nvim/ascii.h"
|
||||
#include "nvim/arabic.h"
|
||||
|
@ -578,7 +579,7 @@ static int command_line_execute(VimState *state, int key)
|
|||
}
|
||||
if (vim_ispathsep(ccline.cmdbuff[s->j])
|
||||
#ifdef BACKSLASH_IN_FILENAME
|
||||
&& vim_strchr(" *?[{`$%#", ccline.cmdbuff[s->j + 1])
|
||||
&& strchr(" *?[{`$%#", ccline.cmdbuff[s->j + 1])
|
||||
== NULL
|
||||
#endif
|
||||
) {
|
||||
|
@ -960,7 +961,7 @@ static int command_line_handle_key(CommandLineState *s)
|
|||
return command_line_not_changed(s);
|
||||
|
||||
case Ctrl_HAT:
|
||||
if (map_to_exists_mode((char_u *)"", LANGMAP, false)) {
|
||||
if (map_to_exists_mode("", LANGMAP, false)) {
|
||||
// ":lmap" mappings exists, toggle use of mappings.
|
||||
State ^= LANGMAP;
|
||||
if (s->b_im_ptr != NULL) {
|
||||
|
@ -2553,19 +2554,22 @@ void cmdline_paste_str(char_u *s, int literally)
|
|||
else
|
||||
while (*s != NUL) {
|
||||
cv = *s;
|
||||
if (cv == Ctrl_V && s[1])
|
||||
++s;
|
||||
if (has_mbyte)
|
||||
c = mb_cptr2char_adv(&s);
|
||||
else
|
||||
if (cv == Ctrl_V && s[1]) {
|
||||
s++;
|
||||
}
|
||||
if (has_mbyte) {
|
||||
c = mb_cptr2char_adv((const char_u **)&s);
|
||||
} else {
|
||||
c = *s++;
|
||||
}
|
||||
if (cv == Ctrl_V || c == ESC || c == Ctrl_C
|
||||
|| c == CAR || c == NL || c == Ctrl_L
|
||||
#ifdef UNIX
|
||||
|| c == intr_char
|
||||
#endif
|
||||
|| (c == Ctrl_BSL && *s == Ctrl_N))
|
||||
|| (c == Ctrl_BSL && *s == Ctrl_N)) {
|
||||
stuffcharReadbuff(Ctrl_V);
|
||||
}
|
||||
stuffcharReadbuff(c);
|
||||
}
|
||||
}
|
||||
|
@ -3120,9 +3124,10 @@ void ExpandEscape(expand_T *xp, char_u *str, int numfiles, char_u **files, int o
|
|||
#endif
|
||||
}
|
||||
#ifdef BACKSLASH_IN_FILENAME
|
||||
p = vim_strsave_fnameescape(files[i], FALSE);
|
||||
p = (char_u *)vim_strsave_fnameescape((const char *)files[i], false);
|
||||
#else
|
||||
p = vim_strsave_fnameescape(files[i], xp->xp_shell);
|
||||
p = (char_u *)vim_strsave_fnameescape((const char *)files[i],
|
||||
xp->xp_shell);
|
||||
#endif
|
||||
xfree(files[i]);
|
||||
files[i] = p;
|
||||
|
@ -3152,42 +3157,49 @@ void ExpandEscape(expand_T *xp, char_u *str, int numfiles, char_u **files, int o
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Escape special characters in "fname" for when used as a file name argument
|
||||
* after a Vim command, or, when "shell" is non-zero, a shell command.
|
||||
* Returns the result in allocated memory.
|
||||
*/
|
||||
char_u *vim_strsave_fnameescape(char_u *fname, int shell) FUNC_ATTR_NONNULL_RET
|
||||
/// Escape special characters in a file name for use as a command argument
|
||||
///
|
||||
/// @param[in] fname File name to escape.
|
||||
/// @param[in] shell What to escape for: if false, escapes for VimL command,
|
||||
/// if true then it escapes for a shell command.
|
||||
///
|
||||
/// @return [allocated] escaped file name.
|
||||
char *vim_strsave_fnameescape(const char *const fname, const bool shell)
|
||||
FUNC_ATTR_NONNULL_RET FUNC_ATTR_MALLOC FUNC_ATTR_NONNULL_ALL
|
||||
{
|
||||
char_u *p;
|
||||
#ifdef BACKSLASH_IN_FILENAME
|
||||
#define PATH_ESC_CHARS ((char_u *)" \t\n*?[{`%#'\"|!<")
|
||||
char_u buf[20];
|
||||
#define PATH_ESC_CHARS " \t\n*?[{`%#'\"|!<"
|
||||
char_u buf[sizeof(PATH_ESC_CHARS)];
|
||||
int j = 0;
|
||||
|
||||
/* Don't escape '[', '{' and '!' if they are in 'isfname'. */
|
||||
for (p = PATH_ESC_CHARS; *p != NUL; ++p)
|
||||
if ((*p != '[' && *p != '{' && *p != '!') || !vim_isfilec(*p))
|
||||
buf[j++] = *p;
|
||||
// Don't escape '[', '{' and '!' if they are in 'isfname'.
|
||||
for (const char *s = PATH_ESC_CHARS; *s != NUL; s++) {
|
||||
if ((*s != '[' && *s != '{' && *s != '!') || !vim_isfilec(*s)) {
|
||||
buf[j++] = *s;
|
||||
}
|
||||
}
|
||||
buf[j] = NUL;
|
||||
p = vim_strsave_escaped(fname, buf);
|
||||
char *p = (char *)vim_strsave_escaped((const char_u *)fname,
|
||||
(const char_u *)buf);
|
||||
#else
|
||||
#define PATH_ESC_CHARS ((char_u *)" \t\n*?[{`$\\%#'\"|!<")
|
||||
#define SHELL_ESC_CHARS ((char_u *)" \t\n*?[{`$\\%#'\"|!<>();&")
|
||||
p = vim_strsave_escaped(fname, shell ? SHELL_ESC_CHARS : PATH_ESC_CHARS);
|
||||
char *p = (char *)vim_strsave_escaped(
|
||||
(const char_u *)fname, (shell ? SHELL_ESC_CHARS : PATH_ESC_CHARS));
|
||||
if (shell && csh_like_shell()) {
|
||||
/* For csh and similar shells need to put two backslashes before '!'.
|
||||
* One is taken by Vim, one by the shell. */
|
||||
char_u *s = vim_strsave_escaped(p, (char_u *)"!");
|
||||
// For csh and similar shells need to put two backslashes before '!'.
|
||||
// One is taken by Vim, one by the shell.
|
||||
char *s = (char *)vim_strsave_escaped((const char_u *)p,
|
||||
(const char_u *)"!");
|
||||
xfree(p);
|
||||
p = s;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* '>' and '+' are special at the start of some commands, e.g. ":edit" and
|
||||
* ":write". "cd -" has a special meaning. */
|
||||
// '>' and '+' are special at the start of some commands, e.g. ":edit" and
|
||||
// ":write". "cd -" has a special meaning.
|
||||
if (*p == '>' || *p == '+' || (*p == '-' && p[1] == NUL)) {
|
||||
escape_fname(&p);
|
||||
escape_fname((char_u **)&p);
|
||||
}
|
||||
|
||||
return p;
|
||||
|
@ -3624,7 +3636,6 @@ set_cmd_context (
|
|||
)
|
||||
{
|
||||
int old_char = NUL;
|
||||
char_u *nextcomm;
|
||||
|
||||
/*
|
||||
* Avoid a UMR warning from Purify, only save the character if it has been
|
||||
|
@ -3633,7 +3644,7 @@ set_cmd_context (
|
|||
if (col < len)
|
||||
old_char = str[col];
|
||||
str[col] = NUL;
|
||||
nextcomm = str;
|
||||
const char *nextcomm = (const char *)str;
|
||||
|
||||
if (use_ccline && ccline.cmdfirstc == '=') {
|
||||
// pass CMD_SIZE because there is no real command
|
||||
|
@ -3642,9 +3653,11 @@ set_cmd_context (
|
|||
xp->xp_context = ccline.xp_context;
|
||||
xp->xp_pattern = ccline.cmdbuff;
|
||||
xp->xp_arg = ccline.xp_arg;
|
||||
} else
|
||||
while (nextcomm != NULL)
|
||||
} else {
|
||||
while (nextcomm != NULL) {
|
||||
nextcomm = set_one_cmd_context(xp, nextcomm);
|
||||
}
|
||||
}
|
||||
|
||||
/* Store the string here so that call_user_expand_func() can get to them
|
||||
* easily. */
|
||||
|
@ -4197,9 +4210,11 @@ static int ExpandUserDefined(expand_T *xp, regmatch_T *regmatch, int *num_file,
|
|||
char_u keep;
|
||||
garray_T ga;
|
||||
|
||||
retstr = call_user_expand_func(call_func_retstr, xp, num_file, file);
|
||||
if (retstr == NULL)
|
||||
retstr = call_user_expand_func((user_expand_func_T)call_func_retstr, xp,
|
||||
num_file, file);
|
||||
if (retstr == NULL) {
|
||||
return FAIL;
|
||||
}
|
||||
|
||||
ga_init(&ga, (int)sizeof(char *), 3);
|
||||
for (s = retstr; *s != NUL; s = e) {
|
||||
|
@ -4237,9 +4252,11 @@ static int ExpandUserList(expand_T *xp, int *num_file, char_u ***file)
|
|||
listitem_T *li;
|
||||
garray_T ga;
|
||||
|
||||
retlist = call_user_expand_func(call_func_retlist, xp, num_file, file);
|
||||
if (retlist == NULL)
|
||||
retlist = call_user_expand_func((user_expand_func_T)call_func_retlist, xp,
|
||||
num_file, file);
|
||||
if (retlist == NULL) {
|
||||
return FAIL;
|
||||
}
|
||||
|
||||
ga_init(&ga, (int)sizeof(char *), 3);
|
||||
/* Loop over the items in the list. */
|
||||
|
@ -4249,7 +4266,7 @@ static int ExpandUserList(expand_T *xp, int *num_file, char_u ***file)
|
|||
|
||||
GA_APPEND(char_u *, &ga, vim_strsave(li->li_tv.vval.v_string));
|
||||
}
|
||||
list_unref(retlist);
|
||||
tv_list_unref(retlist);
|
||||
|
||||
*file = ga.ga_data;
|
||||
*num_file = ga.ga_len;
|
||||
|
@ -4545,7 +4562,7 @@ static inline void hist_free_entry(histentry_T *hisptr)
|
|||
FUNC_ATTR_NONNULL_ALL
|
||||
{
|
||||
xfree(hisptr->hisstr);
|
||||
list_unref(hisptr->additional_elements);
|
||||
tv_list_unref(hisptr->additional_elements);
|
||||
clear_hist_entry(hisptr);
|
||||
}
|
||||
|
||||
|
@ -4601,7 +4618,7 @@ in_history (
|
|||
history[type][last_i] = history[type][i];
|
||||
last_i = i;
|
||||
}
|
||||
list_unref(list);
|
||||
tv_list_unref(list);
|
||||
history[type][i].hisnum = ++hisnum[type];
|
||||
history[type][i].hisstr = str;
|
||||
history[type][i].timestamp = os_time();
|
||||
|
@ -4623,7 +4640,7 @@ in_history (
|
|||
///
|
||||
/// @return Any value from HistoryType enum, including HIST_INVALID. May not
|
||||
/// return HIST_DEFAULT unless return_default is true.
|
||||
HistoryType get_histtype(const char_u *const name, const size_t len,
|
||||
HistoryType get_histtype(const char *const name, const size_t len,
|
||||
const bool return_default)
|
||||
FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT
|
||||
{
|
||||
|
@ -4677,8 +4694,8 @@ add_to_history (
|
|||
* down, only lines that were added.
|
||||
*/
|
||||
if (histype == HIST_SEARCH && in_map) {
|
||||
if (maptick == last_maptick) {
|
||||
/* Current line is from the same mapping, remove it */
|
||||
if (maptick == last_maptick && hisidx[HIST_SEARCH] >= 0) {
|
||||
// Current line is from the same mapping, remove it
|
||||
hisptr = &history[HIST_SEARCH][hisidx[HIST_SEARCH]];
|
||||
hist_free_entry(hisptr);
|
||||
--hisnum[histype];
|
||||
|
@ -5016,7 +5033,7 @@ void ex_history(exarg_T *eap)
|
|||
while (ASCII_ISALPHA(*end)
|
||||
|| vim_strchr((char_u *)":=@>/?", *end) != NULL)
|
||||
end++;
|
||||
histype1 = get_histtype(arg, end - arg, false);
|
||||
histype1 = get_histtype((const char *)arg, end - arg, false);
|
||||
if (histype1 == HIST_INVALID) {
|
||||
if (STRNICMP(arg, "all", end - arg) == 0) {
|
||||
histype1 = 0;
|
||||
|
@ -5173,7 +5190,7 @@ static int ex_window(void)
|
|||
// Create empty command-line buffer.
|
||||
buf_open_scratch(0, "[Command Line]");
|
||||
// Command-line buffer has bufhidden=wipe, unlike a true "scratch" buffer.
|
||||
set_option_value((char_u *)"bh", 0L, (char_u *)"wipe", OPT_LOCAL);
|
||||
set_option_value("bh", 0L, "wipe", OPT_LOCAL);
|
||||
curwin->w_p_rl = cmdmsg_rl;
|
||||
cmdmsg_rl = false;
|
||||
curbuf->b_p_ma = true;
|
||||
|
@ -5191,7 +5208,7 @@ static int ex_window(void)
|
|||
add_map((char_u *)"<buffer> <Tab> <C-X><C-V>", INSERT);
|
||||
add_map((char_u *)"<buffer> <Tab> a<C-X><C-V>", NORMAL);
|
||||
}
|
||||
set_option_value((char_u *)"ft", 0L, (char_u *)"vim", OPT_LOCAL);
|
||||
set_option_value("ft", 0L, "vim", OPT_LOCAL);
|
||||
}
|
||||
|
||||
/* Reset 'textwidth' after setting 'filetype' (the Vim filetype plugin
|
||||
|
@ -5275,18 +5292,18 @@ static int ex_window(void)
|
|||
cmdwin_result = Ctrl_C;
|
||||
/* Set the new command line from the cmdline buffer. */
|
||||
xfree(ccline.cmdbuff);
|
||||
if (cmdwin_result == K_XF1 || cmdwin_result == K_XF2) { /* :qa[!] typed */
|
||||
char *p = (cmdwin_result == K_XF2) ? "qa" : "qa!";
|
||||
if (cmdwin_result == K_XF1 || cmdwin_result == K_XF2) { // :qa[!] typed
|
||||
const char *p = (cmdwin_result == K_XF2) ? "qa" : "qa!";
|
||||
|
||||
if (histtype == HIST_CMD) {
|
||||
/* Execute the command directly. */
|
||||
ccline.cmdbuff = vim_strsave((char_u *)p);
|
||||
// Execute the command directly.
|
||||
ccline.cmdbuff = (char_u *)xstrdup(p);
|
||||
cmdwin_result = CAR;
|
||||
} else {
|
||||
/* First need to cancel what we were doing. */
|
||||
// First need to cancel what we were doing.
|
||||
ccline.cmdbuff = NULL;
|
||||
stuffcharReadbuff(':');
|
||||
stuffReadbuff((char_u *)p);
|
||||
stuffReadbuff(p);
|
||||
stuffcharReadbuff(CAR);
|
||||
}
|
||||
} else if (cmdwin_result == K_XF2) { /* :qa typed */
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
#ifndef NVIM_EX_GETLN_H
|
||||
#define NVIM_EX_GETLN_H
|
||||
|
||||
#include "nvim/eval_defs.h"
|
||||
#include "nvim/eval/typval.h"
|
||||
#include "nvim/ex_cmds.h"
|
||||
|
||||
/* Values for nextwild() and ExpandOne(). See ExpandOne() for meaning. */
|
||||
|
|
|
@ -322,8 +322,11 @@ vim_findfile_init (
|
|||
drive[0] = path[0];
|
||||
drive[1] = ':';
|
||||
drive[2] = NUL;
|
||||
if (vim_FullName(drive, ff_expand_buffer, MAXPATHL, TRUE) == FAIL)
|
||||
if (vim_FullName((const char *)drive, (char *)ff_expand_buffer, MAXPATHL,
|
||||
true)
|
||||
== FAIL) {
|
||||
goto error_return;
|
||||
}
|
||||
path += 2;
|
||||
} else
|
||||
#endif
|
||||
|
@ -1549,14 +1552,14 @@ void do_autocmd_dirchanged(char *new_dir, CdScope scope)
|
|||
assert(false);
|
||||
}
|
||||
|
||||
dict_add_nr_str(dict, "scope", 0L, (char_u *)buf);
|
||||
dict_add_nr_str(dict, "cwd", 0L, (char_u *)new_dir);
|
||||
dict_set_keys_readonly(dict);
|
||||
tv_dict_add_str(dict, S_LEN("scope"), buf);
|
||||
tv_dict_add_str(dict, S_LEN("cwd"), new_dir);
|
||||
tv_dict_set_keys_readonly(dict);
|
||||
|
||||
apply_autocmds(EVENT_DIRCHANGED, (char_u *)buf, (char_u *)new_dir, false,
|
||||
NULL);
|
||||
|
||||
dict_clear(dict);
|
||||
tv_dict_clear(dict);
|
||||
|
||||
recursive = false;
|
||||
}
|
||||
|
|
|
@ -200,18 +200,14 @@ void filemess(buf_T *buf, char_u *name, char_u *s, int attr)
|
|||
{
|
||||
int msg_scroll_save;
|
||||
|
||||
if (msg_silent != 0)
|
||||
if (msg_silent != 0) {
|
||||
return;
|
||||
msg_add_fname(buf, name); /* put file name in IObuff with quotes */
|
||||
/* If it's extremely long, truncate it. */
|
||||
if (STRLEN(IObuff) > IOSIZE - 80)
|
||||
IObuff[IOSIZE - 80] = NUL;
|
||||
STRCAT(IObuff, s);
|
||||
/*
|
||||
* For the first message may have to start a new line.
|
||||
* For further ones overwrite the previous one, reset msg_scroll before
|
||||
* calling filemess().
|
||||
*/
|
||||
}
|
||||
add_quoted_fname((char *)IObuff, IOSIZE - 80, buf, (const char *)name);
|
||||
xstrlcat((char *)IObuff, (const char *)s, IOSIZE);
|
||||
// For the first message may have to start a new line.
|
||||
// For further ones overwrite the previous one, reset msg_scroll before
|
||||
// calling filemess().
|
||||
msg_scroll_save = msg_scroll;
|
||||
if (shortmess(SHM_OVERALL) && !exiting && p_verbose == 0)
|
||||
msg_scroll = FALSE;
|
||||
|
@ -428,7 +424,7 @@ readfile (
|
|||
}
|
||||
|
||||
if (!read_buffer && !read_stdin) {
|
||||
perm = os_getperm(fname);
|
||||
perm = os_getperm((const char *)fname);
|
||||
#ifdef UNIX
|
||||
// On Unix it is possible to read a directory, so we have to
|
||||
// check for it before os_open().
|
||||
|
@ -614,10 +610,12 @@ readfile (
|
|||
return FAIL;
|
||||
}
|
||||
#ifdef UNIX
|
||||
/* Set swap file protection bits after creating it. */
|
||||
// Set swap file protection bits after creating it.
|
||||
if (swap_mode > 0 && curbuf->b_ml.ml_mfp != NULL
|
||||
&& curbuf->b_ml.ml_mfp->mf_fname != NULL)
|
||||
(void)os_setperm(curbuf->b_ml.ml_mfp->mf_fname, (long)swap_mode);
|
||||
&& curbuf->b_ml.ml_mfp->mf_fname != NULL) {
|
||||
(void)os_setperm((const char *)curbuf->b_ml.ml_mfp->mf_fname,
|
||||
(long)swap_mode);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -1798,8 +1796,8 @@ failed:
|
|||
}
|
||||
|
||||
if (!filtering && !(flags & READ_DUMMY)) {
|
||||
msg_add_fname(curbuf, sfname); /* fname in IObuff with quotes */
|
||||
c = FALSE;
|
||||
add_quoted_fname((char *)IObuff, IOSIZE, curbuf, (const char *)sfname);
|
||||
c = false;
|
||||
|
||||
#ifdef UNIX
|
||||
# ifdef S_ISFIFO
|
||||
|
@ -2256,9 +2254,16 @@ buf_write (
|
|||
int len;
|
||||
linenr_T lnum;
|
||||
long nchars;
|
||||
char_u *errmsg = NULL;
|
||||
int errmsg_allocated = FALSE;
|
||||
char_u *errnum = NULL;
|
||||
#define SET_ERRMSG_NUM(num, msg) \
|
||||
errnum = num, errmsg = msg, errmsgarg = 0
|
||||
#define SET_ERRMSG_ARG(msg, error) \
|
||||
errnum = NULL, errmsg = msg, errmsgarg = error
|
||||
#define SET_ERRMSG(msg) \
|
||||
errnum = NULL, errmsg = msg, errmsgarg = 0
|
||||
const char *errnum = NULL;
|
||||
char *errmsg = NULL;
|
||||
int errmsgarg = 0;
|
||||
bool errmsg_allocated = false;
|
||||
char_u *buffer;
|
||||
char_u smallbuf[SMBUFSIZE];
|
||||
char_u *backup_ext;
|
||||
|
@ -2280,7 +2285,6 @@ buf_write (
|
|||
/* writing everything */
|
||||
int whole = (start == 1 && end == buf->b_ml.ml_line_count);
|
||||
linenr_T old_line_count = buf->b_ml.ml_line_count;
|
||||
int attr;
|
||||
int fileformat;
|
||||
int write_bin;
|
||||
struct bw_info write_info; /* info for buf_write_bytes() */
|
||||
|
@ -2575,13 +2579,11 @@ buf_write (
|
|||
perm = file_info_old.stat.st_mode;
|
||||
if (!S_ISREG(file_info_old.stat.st_mode)) { /* not a file */
|
||||
if (S_ISDIR(file_info_old.stat.st_mode)) {
|
||||
errnum = (char_u *)"E502: ";
|
||||
errmsg = (char_u *)_("is a directory");
|
||||
SET_ERRMSG_NUM("E502", _("is a directory"));
|
||||
goto fail;
|
||||
}
|
||||
if (os_nodetype((char *)fname) != NODE_WRITABLE) {
|
||||
errnum = (char_u *)"E503: ";
|
||||
errmsg = (char_u *)_("is not a file or writable device");
|
||||
SET_ERRMSG_NUM("E503", _("is not a file or writable device"));
|
||||
goto fail;
|
||||
}
|
||||
/* It's a device of some kind (or a fifo) which we can write to
|
||||
|
@ -2597,8 +2599,7 @@ buf_write (
|
|||
*/
|
||||
c = os_nodetype((char *)fname);
|
||||
if (c == NODE_OTHER) {
|
||||
errnum = (char_u *)"E503: ";
|
||||
errmsg = (char_u *)_("is not a file or writable device");
|
||||
SET_ERRMSG_NUM("E503", _("is not a file or writable device"));
|
||||
goto fail;
|
||||
}
|
||||
if (c == NODE_WRITABLE) {
|
||||
|
@ -2606,12 +2607,11 @@ buf_write (
|
|||
newfile = TRUE;
|
||||
perm = -1;
|
||||
} else {
|
||||
perm = os_getperm(fname);
|
||||
if (perm < 0)
|
||||
newfile = TRUE;
|
||||
else if (os_isdir(fname)) {
|
||||
errnum = (char_u *)"E502: ";
|
||||
errmsg = (char_u *)_("is a directory");
|
||||
perm = os_getperm((const char *)fname);
|
||||
if (perm < 0) {
|
||||
newfile = true;
|
||||
} else if (os_isdir(fname)) {
|
||||
SET_ERRMSG_NUM("E502", _("is a directory"));
|
||||
goto fail;
|
||||
}
|
||||
if (overwriting) {
|
||||
|
@ -2630,11 +2630,9 @@ buf_write (
|
|||
|
||||
if (!forceit && file_readonly) {
|
||||
if (vim_strchr(p_cpo, CPO_FWRITE) != NULL) {
|
||||
errnum = (char_u *)"E504: ";
|
||||
errmsg = (char_u *)_(err_readonly);
|
||||
SET_ERRMSG_NUM("E504", _(err_readonly));
|
||||
} else {
|
||||
errnum = (char_u *)"E505: ";
|
||||
errmsg = (char_u *)_("is read-only (add ! to override)");
|
||||
SET_ERRMSG_NUM("E505", _("is read-only (add ! to override)"));
|
||||
}
|
||||
goto fail;
|
||||
}
|
||||
|
@ -2870,9 +2868,9 @@ buf_write (
|
|||
xfree(backup);
|
||||
backup = NULL;
|
||||
} else {
|
||||
/* set file protection same as original file, but
|
||||
* strip s-bit */
|
||||
(void)os_setperm(backup, perm & 0777);
|
||||
// set file protection same as original file, but
|
||||
// strip s-bit.
|
||||
(void)os_setperm((const char *)backup, perm & 0777);
|
||||
|
||||
#ifdef UNIX
|
||||
/*
|
||||
|
@ -2883,7 +2881,8 @@ buf_write (
|
|||
*/
|
||||
if (file_info_new.stat.st_gid != file_info_old.stat.st_gid
|
||||
&& os_fchown(bfd, -1, file_info_old.stat.st_gid) != 0) {
|
||||
os_setperm(backup, (perm & 0707) | ((perm & 07) << 3));
|
||||
os_setperm((const char *)backup,
|
||||
(perm & 0707) | ((perm & 07) << 3));
|
||||
}
|
||||
# ifdef HAVE_SELINUX
|
||||
mch_copy_sec(fname, backup);
|
||||
|
@ -2901,23 +2900,27 @@ buf_write (
|
|||
while ((write_info.bw_len = read_eintr(fd, copybuf,
|
||||
BUFSIZE)) > 0) {
|
||||
if (buf_write_bytes(&write_info) == FAIL) {
|
||||
errmsg = (char_u *)_(
|
||||
"E506: Can't write to backup file (add ! to override)");
|
||||
SET_ERRMSG(_(
|
||||
"E506: Can't write to backup file (add ! to override)"));
|
||||
break;
|
||||
}
|
||||
os_breakcheck();
|
||||
if (got_int) {
|
||||
errmsg = (char_u *)_(e_interr);
|
||||
SET_ERRMSG(_(e_interr));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (close(bfd) < 0 && errmsg == NULL)
|
||||
errmsg = (char_u *)_(
|
||||
"E507: Close error for backup file (add ! to override)");
|
||||
if (write_info.bw_len < 0)
|
||||
errmsg = (char_u *)_(
|
||||
"E508: Can't read file for backup (add ! to override)");
|
||||
int error;
|
||||
if ((error = os_close(bfd)) != 0 && errmsg == NULL) {
|
||||
SET_ERRMSG_ARG(_("E507: Close error for backup file "
|
||||
"(add ! to override): %s"),
|
||||
error);
|
||||
}
|
||||
if (write_info.bw_len < 0) {
|
||||
SET_ERRMSG(_(
|
||||
"E508: Can't read file for backup (add ! to override)"));
|
||||
}
|
||||
#ifdef UNIX
|
||||
set_file_time(backup,
|
||||
file_info_old.stat.st_atim.tv_sec,
|
||||
|
@ -2934,18 +2937,19 @@ buf_write (
|
|||
}
|
||||
}
|
||||
nobackup:
|
||||
close(fd); /* ignore errors for closing read file */
|
||||
os_close(fd); // Ignore errors for closing read file.
|
||||
xfree(copybuf);
|
||||
|
||||
if (backup == NULL && errmsg == NULL)
|
||||
errmsg = (char_u *)_(
|
||||
"E509: Cannot create backup file (add ! to override)");
|
||||
/* ignore errors when forceit is TRUE */
|
||||
if (backup == NULL && errmsg == NULL) {
|
||||
SET_ERRMSG(_(
|
||||
"E509: Cannot create backup file (add ! to override)"));
|
||||
}
|
||||
// Ignore errors when forceit is TRUE.
|
||||
if ((some_error || errmsg != NULL) && !forceit) {
|
||||
retval = FAIL;
|
||||
goto fail;
|
||||
}
|
||||
errmsg = NULL;
|
||||
SET_ERRMSG(NULL);
|
||||
} else {
|
||||
char_u *dirp;
|
||||
char_u *p;
|
||||
|
@ -2960,8 +2964,7 @@ nobackup:
|
|||
* anyway, thus we need an extra check here.
|
||||
*/
|
||||
if (file_readonly && vim_strchr(p_cpo, CPO_FWRITE) != NULL) {
|
||||
errnum = (char_u *)"E504: ";
|
||||
errmsg = (char_u *)_(err_readonly);
|
||||
SET_ERRMSG_NUM("E504", _(err_readonly));
|
||||
goto fail;
|
||||
}
|
||||
|
||||
|
@ -3025,7 +3028,7 @@ nobackup:
|
|||
}
|
||||
}
|
||||
if (backup == NULL && !forceit) {
|
||||
errmsg = (char_u *)_("E510: Can't make backup file (add ! to override)");
|
||||
SET_ERRMSG(_("E510: Can't make backup file (add ! to override)"));
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
@ -3037,8 +3040,8 @@ nobackup:
|
|||
&& file_info_old.stat.st_uid == getuid()
|
||||
&& vim_strchr(p_cpo, CPO_FWRITE) == NULL) {
|
||||
perm |= 0200;
|
||||
(void)os_setperm(fname, perm);
|
||||
made_writable = TRUE;
|
||||
(void)os_setperm((const char *)fname, perm);
|
||||
made_writable = true;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -3066,7 +3069,7 @@ nobackup:
|
|||
&& !(exiting && backup != NULL)) {
|
||||
ml_preserve(buf, FALSE);
|
||||
if (got_int) {
|
||||
errmsg = (char_u *)_(e_interr);
|
||||
SET_ERRMSG(_(e_interr));
|
||||
goto restore_backup;
|
||||
}
|
||||
}
|
||||
|
@ -3137,8 +3140,8 @@ nobackup:
|
|||
*/
|
||||
if (*p_ccv != NUL) {
|
||||
wfname = vim_tempname();
|
||||
if (wfname == NULL) { /* Can't write without a tempfile! */
|
||||
errmsg = (char_u *)_("E214: Can't find temp file for writing");
|
||||
if (wfname == NULL) { // Can't write without a tempfile!
|
||||
SET_ERRMSG(_("E214: Can't find temp file for writing"));
|
||||
goto restore_backup;
|
||||
}
|
||||
}
|
||||
|
@ -3150,8 +3153,8 @@ nobackup:
|
|||
&& wfname == fname
|
||||
) {
|
||||
if (!forceit) {
|
||||
errmsg = (char_u *)_(
|
||||
"E213: Cannot convert (add ! to write without conversion)");
|
||||
SET_ERRMSG(_(
|
||||
"E213: Cannot convert (add ! to write without conversion)"));
|
||||
goto restore_backup;
|
||||
}
|
||||
notconverted = TRUE;
|
||||
|
@ -3186,11 +3189,10 @@ nobackup:
|
|||
if ((!newfile && os_fileinfo_hardlinks(&file_info) > 1)
|
||||
|| (os_fileinfo_link((char *)fname, &file_info)
|
||||
&& !os_fileinfo_id_equal(&file_info, &file_info_old))) {
|
||||
errmsg = (char_u *)_("E166: Can't open linked file for writing");
|
||||
} else
|
||||
SET_ERRMSG(_("E166: Can't open linked file for writing"));
|
||||
} else {
|
||||
#endif
|
||||
{
|
||||
errmsg = (char_u *)_("E212: Can't open file for writing");
|
||||
SET_ERRMSG_ARG(_("E212: Can't open file for writing: %s"), fd);
|
||||
if (forceit && vim_strchr(p_cpo, CPO_FWRITE) == NULL
|
||||
&& perm >= 0) {
|
||||
#ifdef UNIX
|
||||
|
@ -3208,7 +3210,9 @@ nobackup:
|
|||
os_remove((char *)wfname);
|
||||
continue;
|
||||
}
|
||||
#ifdef UNIX
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
restore_backup:
|
||||
|
@ -3250,7 +3254,7 @@ restore_backup:
|
|||
xfree(wfname);
|
||||
goto fail;
|
||||
}
|
||||
errmsg = NULL;
|
||||
SET_ERRMSG(NULL);
|
||||
|
||||
|
||||
write_info.bw_fd = fd;
|
||||
|
@ -3370,7 +3374,6 @@ restore_backup:
|
|||
nchars += len;
|
||||
}
|
||||
|
||||
#if defined(UNIX)
|
||||
// On many journalling file systems there is a bug that causes both the
|
||||
// original and the backup file to be lost when halting the system right
|
||||
// after writing the file. That's because only the meta-data is
|
||||
|
@ -3379,11 +3382,11 @@ restore_backup:
|
|||
// For a device do try the fsync() but don't complain if it does not work
|
||||
// (could be a pipe).
|
||||
// If the 'fsync' option is FALSE, don't fsync(). Useful for laptops.
|
||||
if (p_fs && os_fsync(fd) != 0 && !device) {
|
||||
errmsg = (char_u *)_("E667: Fsync failed");
|
||||
int error;
|
||||
if (p_fs && (error = os_fsync(fd)) != 0 && !device) {
|
||||
SET_ERRMSG_ARG(_("E667: Fsync failed: %s"), error);
|
||||
end = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_SELINUX
|
||||
/* Probably need to set the security context. */
|
||||
|
@ -3402,8 +3405,9 @@ restore_backup:
|
|||
|| file_info.stat.st_uid != file_info_old.stat.st_uid
|
||||
|| file_info.stat.st_gid != file_info_old.stat.st_gid) {
|
||||
os_fchown(fd, file_info_old.stat.st_uid, file_info_old.stat.st_gid);
|
||||
if (perm >= 0) /* set permission again, may have changed */
|
||||
(void)os_setperm(wfname, perm);
|
||||
if (perm >= 0) { // Set permission again, may have changed.
|
||||
(void)os_setperm((const char *)wfname, perm);
|
||||
}
|
||||
}
|
||||
buf_set_file_id(buf);
|
||||
} else if (!buf->file_id_valid) {
|
||||
|
@ -3412,8 +3416,8 @@ restore_backup:
|
|||
}
|
||||
#endif
|
||||
|
||||
if (close(fd) != 0) {
|
||||
errmsg = (char_u *)_("E512: Close failed");
|
||||
if ((error = os_close(fd)) != 0) {
|
||||
SET_ERRMSG_ARG(_("E512: Close failed: %s"), error);
|
||||
end = 0;
|
||||
}
|
||||
|
||||
|
@ -3421,8 +3425,9 @@ restore_backup:
|
|||
if (made_writable)
|
||||
perm &= ~0200; /* reset 'w' bit for security reasons */
|
||||
#endif
|
||||
if (perm >= 0) /* set perm. of new file same as old file */
|
||||
(void)os_setperm(wfname, perm);
|
||||
if (perm >= 0) { // Set perm. of new file same as old file.
|
||||
(void)os_setperm((const char *)wfname, perm);
|
||||
}
|
||||
#ifdef HAVE_ACL
|
||||
/* Probably need to set the ACL before changing the user (can't set the
|
||||
* ACL on a file the user doesn't own). */
|
||||
|
@ -3449,21 +3454,24 @@ restore_backup:
|
|||
if (end == 0) {
|
||||
if (errmsg == NULL) {
|
||||
if (write_info.bw_conv_error) {
|
||||
if (write_info.bw_conv_error_lnum == 0)
|
||||
errmsg = (char_u *)_(
|
||||
"E513: write error, conversion failed (make 'fenc' empty to override)");
|
||||
else {
|
||||
errmsg_allocated = TRUE;
|
||||
errmsg = xmalloc(300);
|
||||
vim_snprintf((char *)errmsg, 300,
|
||||
_("E513: write error, conversion failed in line %" PRId64
|
||||
if (write_info.bw_conv_error_lnum == 0) {
|
||||
SET_ERRMSG(_(
|
||||
"E513: write error, conversion failed "
|
||||
"(make 'fenc' empty to override)"));
|
||||
} else {
|
||||
errmsg_allocated = true;
|
||||
SET_ERRMSG(xmalloc(300));
|
||||
vim_snprintf(
|
||||
errmsg, 300,
|
||||
_("E513: write error, conversion failed in line %" PRIdLINENR
|
||||
" (make 'fenc' empty to override)"),
|
||||
(int64_t)write_info.bw_conv_error_lnum);
|
||||
write_info.bw_conv_error_lnum);
|
||||
}
|
||||
} else if (got_int)
|
||||
errmsg = (char_u *)_(e_interr);
|
||||
else
|
||||
errmsg = (char_u *)_("E514: write error (file system full?)");
|
||||
} else if (got_int) {
|
||||
SET_ERRMSG(_(e_interr));
|
||||
} else {
|
||||
SET_ERRMSG(_("E514: write error (file system full?)"));
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -3518,8 +3526,8 @@ restore_backup:
|
|||
fname = sfname; /* use shortname now, for the messages */
|
||||
#endif
|
||||
if (!filtering) {
|
||||
msg_add_fname(buf, fname); /* put fname in IObuff with quotes */
|
||||
c = FALSE;
|
||||
add_quoted_fname((char *)IObuff, IOSIZE, buf, (const char *)fname);
|
||||
c = false;
|
||||
if (write_info.bw_conv_error) {
|
||||
STRCAT(IObuff, _(" CONVERSION ERROR"));
|
||||
c = TRUE;
|
||||
|
@ -3628,7 +3636,7 @@ restore_backup:
|
|||
close(empty_fd);
|
||||
}
|
||||
if (org != NULL) {
|
||||
os_setperm((char_u *)org, os_getperm(fname) & 0777);
|
||||
os_setperm(org, os_getperm((const char *)fname) & 0777);
|
||||
xfree(org);
|
||||
}
|
||||
}
|
||||
|
@ -3668,33 +3676,32 @@ nofail:
|
|||
#endif
|
||||
|
||||
if (errmsg != NULL) {
|
||||
int numlen = errnum != NULL ? (int)STRLEN(errnum) : 0;
|
||||
|
||||
attr = hl_attr(HLF_E); /* set highlight for error messages */
|
||||
msg_add_fname(buf,
|
||||
// - 100 to save some space for further error message
|
||||
#ifndef UNIX
|
||||
sfname
|
||||
add_quoted_fname((char *)IObuff, IOSIZE - 100, buf, (const char *)sfname);
|
||||
#else
|
||||
fname
|
||||
add_quoted_fname((char *)IObuff, IOSIZE - 100, buf, (const char *)fname);
|
||||
#endif
|
||||
); /* put file name in IObuff with quotes */
|
||||
if (STRLEN(IObuff) + STRLEN(errmsg) + numlen >= IOSIZE)
|
||||
IObuff[IOSIZE - STRLEN(errmsg) - numlen - 1] = NUL;
|
||||
/* If the error message has the form "is ...", put the error number in
|
||||
* front of the file name. */
|
||||
if (errnum != NULL) {
|
||||
STRMOVE(IObuff + numlen, IObuff);
|
||||
memmove(IObuff, errnum, (size_t)numlen);
|
||||
if (errmsgarg != 0) {
|
||||
emsgf("%s: %s%s: %s", errnum, IObuff, errmsg, os_strerror(errmsgarg));
|
||||
} else {
|
||||
emsgf("%s: %s%s", errnum, IObuff, errmsg);
|
||||
}
|
||||
} else if (errmsgarg != 0) {
|
||||
emsgf(errmsg, os_strerror(errmsgarg));
|
||||
} else {
|
||||
emsgf(errmsg);
|
||||
}
|
||||
STRCAT(IObuff, errmsg);
|
||||
emsg(IObuff);
|
||||
if (errmsg_allocated)
|
||||
if (errmsg_allocated) {
|
||||
xfree(errmsg);
|
||||
}
|
||||
|
||||
retval = FAIL;
|
||||
if (end == 0) {
|
||||
const int attr = hl_attr(HLF_E); // Set highlight for error messages.
|
||||
MSG_PUTS_ATTR(_("\nWARNING: Original file may be lost or damaged\n"),
|
||||
attr | MSG_HIST);
|
||||
attr | MSG_HIST);
|
||||
MSG_PUTS_ATTR(_(
|
||||
"don't quit the editor until the file is successfully written!"),
|
||||
attr | MSG_HIST);
|
||||
|
@ -3754,6 +3761,9 @@ nofail:
|
|||
got_int |= prev_got_int;
|
||||
|
||||
return retval;
|
||||
#undef SET_ERRMSG
|
||||
#undef SET_ERRMSG_ARG
|
||||
#undef SET_ERRMSG_NUM
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -3797,16 +3807,25 @@ static int set_rw_fname(char_u *fname, char_u *sfname)
|
|||
return OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* Put file name into IObuff with quotes.
|
||||
*/
|
||||
void msg_add_fname(buf_T *buf, char_u *fname)
|
||||
/// Put file name into the specified buffer with quotes
|
||||
///
|
||||
/// Replaces home directory at the start with `~`.
|
||||
///
|
||||
/// @param[out] ret_buf Buffer to save results to.
|
||||
/// @param[in] buf_len ret_buf length.
|
||||
/// @param[in] buf buf_T file name is coming from.
|
||||
/// @param[in] fname File name to write.
|
||||
static void add_quoted_fname(char *const ret_buf, const size_t buf_len,
|
||||
const buf_T *const buf, const char *fname)
|
||||
FUNC_ATTR_NONNULL_ARG(1)
|
||||
{
|
||||
if (fname == NULL)
|
||||
fname = (char_u *)"-stdin-";
|
||||
home_replace(buf, fname, IObuff + 1, IOSIZE - 4, TRUE);
|
||||
IObuff[0] = '"';
|
||||
STRCAT(IObuff, "\" ");
|
||||
if (fname == NULL) {
|
||||
fname = "-stdin-";
|
||||
}
|
||||
ret_buf[0] = '"';
|
||||
home_replace(buf, (const char_u *)fname, (char_u *)ret_buf + 1,
|
||||
(int)buf_len - 4, true);
|
||||
xstrlcat(ret_buf, "\" ", buf_len);
|
||||
}
|
||||
|
||||
/// Append message for text mode to IObuff.
|
||||
|
@ -4548,9 +4567,9 @@ int put_time(FILE *fd, time_t time_)
|
|||
|
||||
/// os_rename() only works if both files are on the same file system, this
|
||||
/// function will (attempts to?) copy the file across if rename fails -- webb
|
||||
//
|
||||
///
|
||||
/// @return -1 for failure, 0 for success
|
||||
int vim_rename(char_u *from, char_u *to)
|
||||
int vim_rename(const char_u *from, const char_u *to)
|
||||
{
|
||||
int fd_in;
|
||||
int fd_out;
|
||||
|
@ -4569,10 +4588,12 @@ int vim_rename(char_u *from, char_u *to)
|
|||
* the file name differs we need to go through a temp file.
|
||||
*/
|
||||
if (fnamecmp(from, to) == 0) {
|
||||
if (p_fic && STRCMP(path_tail(from), path_tail(to)) != 0)
|
||||
if (p_fic && (STRCMP(path_tail((char_u *)from), path_tail((char_u *)to))
|
||||
!= 0)) {
|
||||
use_tmp_file = true;
|
||||
else
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Fail if the "from" file doesn't exist. Avoids that "to" is deleted.
|
||||
|
@ -4638,9 +4659,9 @@ int vim_rename(char_u *from, char_u *to)
|
|||
/*
|
||||
* Rename() failed, try copying the file.
|
||||
*/
|
||||
perm = os_getperm(from);
|
||||
perm = os_getperm((const char *)from);
|
||||
#ifdef HAVE_ACL
|
||||
/* For systems that support ACL: get the ACL from the original file. */
|
||||
// For systems that support ACL: get the ACL from the original file.
|
||||
acl = mch_get_acl(from);
|
||||
#endif
|
||||
fd_in = os_open((char *)from, O_RDONLY, 0);
|
||||
|
@ -4688,8 +4709,8 @@ int vim_rename(char_u *from, char_u *to)
|
|||
errmsg = _("E210: Error reading \"%s\"");
|
||||
to = from;
|
||||
}
|
||||
#ifndef UNIX /* for Unix os_open() already set the permission */
|
||||
os_setperm(to, perm);
|
||||
#ifndef UNIX // For Unix os_open() already set the permission.
|
||||
os_setperm((const char *)to, perm);
|
||||
#endif
|
||||
#ifdef HAVE_ACL
|
||||
mch_set_acl(to, acl);
|
||||
|
@ -5200,7 +5221,7 @@ void forward_slash(char_u *fname)
|
|||
{
|
||||
char_u *p;
|
||||
|
||||
if (path_with_url(fname)) {
|
||||
if (path_with_url((const char *)fname)) {
|
||||
return;
|
||||
}
|
||||
for (p = fname; *p != NUL; p++) {
|
||||
|
@ -5261,7 +5282,7 @@ static void vim_maketempdir(void)
|
|||
/// Delete "name" and everything in it, recursively.
|
||||
/// @param name The path which should be deleted.
|
||||
/// @return 0 for success, -1 if some file was not deleted.
|
||||
int delete_recursive(char_u *name)
|
||||
int delete_recursive(const char *name)
|
||||
{
|
||||
int result = 0;
|
||||
|
||||
|
@ -5275,7 +5296,7 @@ int delete_recursive(char_u *name)
|
|||
EW_DIR | EW_FILE | EW_SILENT | EW_ALLLINKS
|
||||
| EW_DODOT | EW_EMPTYOK) == OK) {
|
||||
for (int i = 0; i < file_count; i++) {
|
||||
if (delete_recursive(files[i]) != 0) {
|
||||
if (delete_recursive((const char *)files[i]) != 0) {
|
||||
result = -1;
|
||||
}
|
||||
}
|
||||
|
@ -5285,9 +5306,9 @@ int delete_recursive(char_u *name)
|
|||
}
|
||||
|
||||
xfree(exp);
|
||||
os_rmdir((char *)name);
|
||||
os_rmdir(name);
|
||||
} else {
|
||||
result = os_remove((char *)name) == 0 ? 0 : -1;
|
||||
result = os_remove(name) == 0 ? 0 : -1;
|
||||
}
|
||||
|
||||
return result;
|
||||
|
@ -5299,7 +5320,7 @@ void vim_deltempdir(void)
|
|||
if (vim_tempdir != NULL) {
|
||||
// remove the trailing path separator
|
||||
path_tail(vim_tempdir)[-1] = NUL;
|
||||
delete_recursive(vim_tempdir);
|
||||
delete_recursive((const char *)vim_tempdir);
|
||||
xfree(vim_tempdir);
|
||||
vim_tempdir = NULL;
|
||||
}
|
||||
|
|
|
@ -2232,32 +2232,51 @@ static linenr_T foldUpdateIEMSRecurse(garray_T *gap, int level,
|
|||
* before where we started looking, extend it. If it
|
||||
* starts at another line, update nested folds to keep
|
||||
* their position, compensating for the new fd_top. */
|
||||
if (fp->fd_top >= startlnum && fp->fd_top != firstlnum) {
|
||||
if (fp->fd_top > firstlnum)
|
||||
/* like lines are inserted */
|
||||
if (fp->fd_top == firstlnum) {
|
||||
// We have found a fold beginning exactly where we want one.
|
||||
} else if (fp->fd_top >= startlnum) {
|
||||
if (fp->fd_top > firstlnum) {
|
||||
// We will move the start of this fold up, hence we move all
|
||||
// nested folds (with relative line numbers) down.
|
||||
foldMarkAdjustRecurse(&fp->fd_nested,
|
||||
(linenr_T)0, (linenr_T)MAXLNUM,
|
||||
(long)(fp->fd_top - firstlnum), 0L);
|
||||
else
|
||||
/* like lines are deleted */
|
||||
(linenr_T)0, (linenr_T)MAXLNUM,
|
||||
(long)(fp->fd_top - firstlnum), 0L);
|
||||
} else {
|
||||
// Will move fold down, move nested folds relatively up.
|
||||
foldMarkAdjustRecurse(&fp->fd_nested,
|
||||
(linenr_T)0,
|
||||
(long)(firstlnum - fp->fd_top - 1),
|
||||
(linenr_T)MAXLNUM,
|
||||
(long)(fp->fd_top - firstlnum));
|
||||
(linenr_T)0,
|
||||
(long)(firstlnum - fp->fd_top - 1),
|
||||
(linenr_T)MAXLNUM,
|
||||
(long)(fp->fd_top - firstlnum));
|
||||
}
|
||||
fp->fd_len += fp->fd_top - firstlnum;
|
||||
fp->fd_top = firstlnum;
|
||||
fold_changed = TRUE;
|
||||
} else if (flp->start != 0 && lvl == level
|
||||
&& fp->fd_top != firstlnum) {
|
||||
/* Existing fold that includes startlnum must stop
|
||||
* if we find the start of a new fold at the same
|
||||
* level. Split it. Delete contained folds at
|
||||
* this point to split them too. */
|
||||
foldRemove(&fp->fd_nested, flp->lnum - fp->fd_top,
|
||||
flp->lnum - fp->fd_top);
|
||||
fold_changed = true;
|
||||
} else if ((flp->start != 0 && lvl == level)
|
||||
|| (firstlnum != startlnum)) {
|
||||
// Before there was a fold spanning from above startlnum to below
|
||||
// firstlnum. This fold is valid above startlnum (because we are
|
||||
// not updating that range), but there is now a break in it.
|
||||
// If the break is because we are now forced to start a new fold
|
||||
// at the level "level" at line fline->lnum, then we need to
|
||||
// split the fold at fline->lnum.
|
||||
// If the break is because the range [startlnum, firstlnum) is
|
||||
// now at a lower indent than "level", we need to split the fold
|
||||
// in this range.
|
||||
// Any splits have to be done recursively.
|
||||
linenr_T breakstart;
|
||||
linenr_T breakend;
|
||||
if (firstlnum != startlnum) {
|
||||
breakstart = startlnum;
|
||||
breakend = firstlnum;
|
||||
} else {
|
||||
breakstart = flp->lnum;
|
||||
breakend = flp->lnum;
|
||||
}
|
||||
foldRemove(&fp->fd_nested, breakstart - fp->fd_top,
|
||||
breakend - fp->fd_top);
|
||||
i = (int)(fp - (fold_T *)gap->ga_data);
|
||||
foldSplit(gap, i, flp->lnum, flp->lnum - 1);
|
||||
foldSplit(gap, i, breakstart, breakend - 1);
|
||||
fp = (fold_T *)gap->ga_data + i + 1;
|
||||
/* If using the "marker" or "syntax" method, we
|
||||
* need to continue until the end of the fold is
|
||||
|
@ -2267,6 +2286,16 @@ static linenr_T foldUpdateIEMSRecurse(garray_T *gap, int level,
|
|||
|| getlevel == foldlevelSyntax)
|
||||
finish = TRUE;
|
||||
}
|
||||
if (fp->fd_top == startlnum && concat) {
|
||||
i = (int)(fp - (fold_T *)gap->ga_data);
|
||||
if (i != 0) {
|
||||
fp2 = fp - 1;
|
||||
if (fp2->fd_top + fp2->fd_len == fp->fd_top) {
|
||||
foldMerge(fp2, gap, fp);
|
||||
fp = fp2;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (fp->fd_top >= startlnum) {
|
||||
|
|
|
@ -235,19 +235,18 @@ char_u *get_inserted(void)
|
|||
return get_buffcont(&redobuff, FALSE);
|
||||
}
|
||||
|
||||
/*
|
||||
* Add string "s" after the current block of buffer "buf".
|
||||
* K_SPECIAL and CSI should have been escaped already.
|
||||
*/
|
||||
static void
|
||||
add_buff (
|
||||
buffheader_T *buf,
|
||||
char_u *s,
|
||||
ssize_t slen // length of "s" or -1
|
||||
)
|
||||
/// Add string after the current block of the given buffer
|
||||
///
|
||||
/// K_SPECIAL and CSI should have been escaped already.
|
||||
///
|
||||
/// @param[out] buf Buffer to add to.
|
||||
/// @param[in] s String to add.
|
||||
/// @param[in] slen String length or -1 for NUL-terminated string.
|
||||
static void add_buff(buffheader_T *const buf, const char *const s,
|
||||
ptrdiff_t slen)
|
||||
{
|
||||
if (slen < 0) {
|
||||
slen = (ssize_t)STRLEN(s);
|
||||
slen = (ptrdiff_t)strlen(s);
|
||||
}
|
||||
if (slen == 0) { // don't add empty strings
|
||||
return;
|
||||
|
@ -292,9 +291,8 @@ add_buff (
|
|||
*/
|
||||
static void add_num_buff(buffheader_T *buf, long n)
|
||||
{
|
||||
char_u number[32];
|
||||
|
||||
sprintf((char *)number, "%" PRId64, (int64_t)n);
|
||||
char number[32];
|
||||
snprintf(number, sizeof(number), "%ld", n);
|
||||
add_buff(buf, number, -1L);
|
||||
}
|
||||
|
||||
|
@ -304,27 +302,29 @@ static void add_num_buff(buffheader_T *buf, long n)
|
|||
*/
|
||||
static void add_char_buff(buffheader_T *buf, int c)
|
||||
{
|
||||
char_u bytes[MB_MAXBYTES + 1];
|
||||
char bytes[MB_MAXBYTES + 1];
|
||||
|
||||
int len;
|
||||
int i;
|
||||
char_u temp[4];
|
||||
|
||||
if (IS_SPECIAL(c))
|
||||
if (IS_SPECIAL(c)) {
|
||||
len = 1;
|
||||
else
|
||||
len = (*mb_char2bytes)(c, bytes);
|
||||
for (i = 0; i < len; ++i) {
|
||||
if (!IS_SPECIAL(c))
|
||||
c = bytes[i];
|
||||
} else {
|
||||
len = (*mb_char2bytes)(c, (char_u *)bytes);
|
||||
}
|
||||
|
||||
for (int i = 0; i < len; i++) {
|
||||
if (!IS_SPECIAL(c)) {
|
||||
c = bytes[i];
|
||||
}
|
||||
|
||||
char temp[4];
|
||||
if (IS_SPECIAL(c) || c == K_SPECIAL || c == NUL) {
|
||||
/* translate special key code into three byte sequence */
|
||||
temp[0] = K_SPECIAL;
|
||||
temp[1] = (char_u)K_SECOND(c);
|
||||
temp[2] = (char_u)K_THIRD(c);
|
||||
// Translate special key code into three byte sequence.
|
||||
temp[0] = (char)K_SPECIAL;
|
||||
temp[1] = (char)K_SECOND(c);
|
||||
temp[2] = (char)K_THIRD(c);
|
||||
temp[3] = NUL;
|
||||
} else {
|
||||
temp[0] = (char_u)c;
|
||||
temp[0] = (char)c;
|
||||
temp[1] = NUL;
|
||||
}
|
||||
add_buff(buf, temp, -1L);
|
||||
|
@ -479,16 +479,14 @@ static int save_level = 0;
|
|||
|
||||
void saveRedobuff(void)
|
||||
{
|
||||
char_u *s;
|
||||
|
||||
if (save_level++ == 0) {
|
||||
save_redobuff = redobuff;
|
||||
redobuff.bh_first.b_next = NULL;
|
||||
save_old_redobuff = old_redobuff;
|
||||
old_redobuff.bh_first.b_next = NULL;
|
||||
|
||||
/* Make a copy, so that ":normal ." in a function works. */
|
||||
s = get_buffcont(&save_redobuff, FALSE);
|
||||
// Make a copy, so that ":normal ." in a function works.
|
||||
char *const s = (char *)get_buffcont(&save_redobuff, false);
|
||||
if (s != NULL) {
|
||||
add_buff(&redobuff, s, -1L);
|
||||
xfree(s);
|
||||
|
@ -514,10 +512,11 @@ void restoreRedobuff(void)
|
|||
* Append "s" to the redo buffer.
|
||||
* K_SPECIAL and CSI should already have been escaped.
|
||||
*/
|
||||
void AppendToRedobuff(char_u *s)
|
||||
void AppendToRedobuff(const char *s)
|
||||
{
|
||||
if (!block_redo)
|
||||
add_buff(&redobuff, s, -1L);
|
||||
if (!block_redo) {
|
||||
add_buff(&redobuff, (const char *)s, -1L);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -530,44 +529,47 @@ AppendToRedobuffLit (
|
|||
int len /* length of "str" or -1 for up to the NUL */
|
||||
)
|
||||
{
|
||||
char_u *s = str;
|
||||
int c;
|
||||
char_u *start;
|
||||
|
||||
if (block_redo)
|
||||
if (block_redo) {
|
||||
return;
|
||||
}
|
||||
|
||||
while (len < 0 ? *s != NUL : s - str < len) {
|
||||
/* Put a string of normal characters in the redo buffer (that's
|
||||
* faster). */
|
||||
start = s;
|
||||
while (*s >= ' ' && *s < DEL && (len < 0 || s - str < len))
|
||||
++s;
|
||||
const char *s = (const char *)str;
|
||||
while (len < 0 ? *s != NUL : s - (const char *)str < len) {
|
||||
// Put a string of normal characters in the redo buffer (that's
|
||||
// faster).
|
||||
const char *start = s;
|
||||
while (*s >= ' ' && *s < DEL && (len < 0 || s - (const char *)str < len)) {
|
||||
s++;
|
||||
}
|
||||
|
||||
/* Don't put '0' or '^' as last character, just in case a CTRL-D is
|
||||
* typed next. */
|
||||
if (*s == NUL && (s[-1] == '0' || s[-1] == '^'))
|
||||
--s;
|
||||
if (s > start)
|
||||
// Don't put '0' or '^' as last character, just in case a CTRL-D is
|
||||
// typed next.
|
||||
if (*s == NUL && (s[-1] == '0' || s[-1] == '^')) {
|
||||
s--;
|
||||
}
|
||||
if (s > start) {
|
||||
add_buff(&redobuff, start, (long)(s - start));
|
||||
}
|
||||
|
||||
if (*s == NUL || (len >= 0 && s - str >= len))
|
||||
if (*s == NUL || (len >= 0 && s - (const char *)str >= len)) {
|
||||
break;
|
||||
}
|
||||
|
||||
/* Handle a special or multibyte character. */
|
||||
if (has_mbyte)
|
||||
/* Handle composing chars separately. */
|
||||
c = mb_cptr2char_adv(&s);
|
||||
else
|
||||
c = *s++;
|
||||
if (c < ' ' || c == DEL || (*s == NUL && (c == '0' || c == '^')))
|
||||
// Handle a special or multibyte character.
|
||||
// Composing chars separately are handled separately.
|
||||
const int c = (has_mbyte
|
||||
? mb_cptr2char_adv((const char_u **)&s)
|
||||
: (uint8_t)(*s++));
|
||||
if (c < ' ' || c == DEL || (*s == NUL && (c == '0' || c == '^'))) {
|
||||
add_char_buff(&redobuff, Ctrl_V);
|
||||
}
|
||||
|
||||
/* CTRL-V '0' must be inserted as CTRL-V 048 */
|
||||
if (*s == NUL && c == '0')
|
||||
add_buff(&redobuff, (char_u *)"048", 3L);
|
||||
else
|
||||
// CTRL-V '0' must be inserted as CTRL-V 048.
|
||||
if (*s == NUL && c == '0') {
|
||||
add_buff(&redobuff, "048", 3L);
|
||||
} else {
|
||||
add_char_buff(&redobuff, c);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -594,19 +596,19 @@ void AppendNumberToRedobuff(long n)
|
|||
* Append string "s" to the stuff buffer.
|
||||
* CSI and K_SPECIAL must already have been escaped.
|
||||
*/
|
||||
void stuffReadbuff(char_u *s)
|
||||
void stuffReadbuff(const char *s)
|
||||
{
|
||||
add_buff(&readbuf1, s, -1L);
|
||||
}
|
||||
|
||||
/// Append string "s" to the redo stuff buffer.
|
||||
/// @remark CSI and K_SPECIAL must already have been escaped.
|
||||
void stuffRedoReadbuff(char_u *s)
|
||||
void stuffRedoReadbuff(const char *s)
|
||||
{
|
||||
add_buff(&readbuf2, s, -1L);
|
||||
}
|
||||
|
||||
void stuffReadbuffLen(char_u *s, long len)
|
||||
void stuffReadbuffLen(const char *s, long len)
|
||||
{
|
||||
add_buff(&readbuf1, s, len);
|
||||
}
|
||||
|
@ -616,19 +618,18 @@ void stuffReadbuffLen(char_u *s, long len)
|
|||
* escaping other K_SPECIAL and CSI bytes.
|
||||
* Change CR, LF and ESC into a space.
|
||||
*/
|
||||
void stuffReadbuffSpec(char_u *s)
|
||||
void stuffReadbuffSpec(const char *s)
|
||||
{
|
||||
int c;
|
||||
|
||||
while (*s != NUL) {
|
||||
if (*s == K_SPECIAL && s[1] != NUL && s[2] != NUL) {
|
||||
/* Insert special key literally. */
|
||||
stuffReadbuffLen(s, 3L);
|
||||
if ((uint8_t)(*s) == K_SPECIAL && s[1] != NUL && s[2] != NUL) {
|
||||
// Insert special key literally.
|
||||
stuffReadbuffLen(s, 3);
|
||||
s += 3;
|
||||
} else {
|
||||
c = mb_ptr2char_adv(&s);
|
||||
if (c == CAR || c == NL || c == ESC)
|
||||
int c = mb_ptr2char_adv((const char_u **)&s);
|
||||
if (c == CAR || c == NL || c == ESC) {
|
||||
c = ' ';
|
||||
}
|
||||
stuffcharReadbuff(c);
|
||||
}
|
||||
}
|
||||
|
@ -747,8 +748,8 @@ int start_redo(long count, int old_redo)
|
|||
|
||||
/* copy the buffer name, if present */
|
||||
if (c == '"') {
|
||||
add_buff(&readbuf2, (char_u *)"\"", 1L);
|
||||
c = read_redo(FALSE, old_redo);
|
||||
add_buff(&readbuf2, "\"", 1L);
|
||||
c = read_redo(false, old_redo);
|
||||
|
||||
/* if a numbered buffer is used, increment the number */
|
||||
if (c >= '1' && c < '9')
|
||||
|
@ -1091,21 +1092,19 @@ static void gotchars(char_u *chars, size_t len)
|
|||
{
|
||||
char_u *s = chars;
|
||||
int c;
|
||||
char_u buf[2];
|
||||
|
||||
// remember how many chars were last recorded
|
||||
if (Recording) {
|
||||
last_recorded_len += len;
|
||||
}
|
||||
|
||||
buf[1] = NUL;
|
||||
while (len--) {
|
||||
// Handle one byte at a time; no translation to be done.
|
||||
c = *s++;
|
||||
updatescript(c);
|
||||
|
||||
if (Recording) {
|
||||
buf[0] = (char_u)c;
|
||||
char buf[2] = { (char)c, NUL };
|
||||
add_buff(&recordbuff, buf, 1L);
|
||||
}
|
||||
}
|
||||
|
@ -1881,9 +1880,8 @@ static int vgetorpeek(int advance)
|
|||
(size_t)(mlen - typebuf.tb_maplen));
|
||||
}
|
||||
|
||||
del_typebuf(mlen, 0); /* remove the chars */
|
||||
set_option_value((char_u *)"paste",
|
||||
(long)!p_paste, NULL, 0);
|
||||
del_typebuf(mlen, 0); // Remove the chars.
|
||||
set_option_value("paste", !p_paste, NULL, 0);
|
||||
if (!(State & INSERT)) {
|
||||
msg_col = 0;
|
||||
msg_row = (int)Rows - 1;
|
||||
|
@ -1905,7 +1903,7 @@ static int vgetorpeek(int advance)
|
|||
}
|
||||
|
||||
if ((mp == NULL || max_mlen >= mp_match_len)
|
||||
&& keylen != KEYLEN_PART_MAP) {
|
||||
&& keylen != KEYLEN_PART_MAP && keylen != KEYLEN_PART_KEY) {
|
||||
// No matching mapping found or found a non-matching mapping that
|
||||
// matches at least what the matching mapping matched
|
||||
keylen = 0;
|
||||
|
@ -3219,82 +3217,99 @@ showmap (
|
|||
ui_flush(); /* show one line at a time */
|
||||
}
|
||||
|
||||
/*
|
||||
* Return TRUE if a map exists that has "str" in the rhs for mode "modechars".
|
||||
* Recognize termcap codes in "str".
|
||||
* Also checks mappings local to the current buffer.
|
||||
*/
|
||||
int map_to_exists(char_u *str, char_u *modechars, int abbr)
|
||||
/// Check if a map exists that has given string in the rhs
|
||||
///
|
||||
/// Also checks mappings local to the current buffer.
|
||||
///
|
||||
/// @param[in] str String which mapping must have in the rhs. Termcap codes
|
||||
/// are recognized in this argument.
|
||||
/// @param[in] modechars Mode(s) in which mappings are checked.
|
||||
/// @param[in] abbr true if checking abbreviations in place of mappings.
|
||||
///
|
||||
/// @return true if there is at least one mapping with given parameters.
|
||||
bool map_to_exists(const char *const str, const char *const modechars,
|
||||
const bool abbr)
|
||||
FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_PURE
|
||||
{
|
||||
int mode = 0;
|
||||
char_u *rhs;
|
||||
char_u *buf;
|
||||
int retval;
|
||||
|
||||
rhs = replace_termcodes(str, STRLEN(str), &buf, false, true, false,
|
||||
CPO_TO_CPO_FLAGS);
|
||||
char_u *buf;
|
||||
char_u *const rhs = replace_termcodes((const char_u *)str, strlen(str), &buf,
|
||||
false, true, false,
|
||||
CPO_TO_CPO_FLAGS);
|
||||
|
||||
if (vim_strchr(modechars, 'n') != NULL)
|
||||
mode |= NORMAL;
|
||||
if (vim_strchr(modechars, 'v') != NULL)
|
||||
mode |= VISUAL + SELECTMODE;
|
||||
if (vim_strchr(modechars, 'x') != NULL)
|
||||
mode |= VISUAL;
|
||||
if (vim_strchr(modechars, 's') != NULL)
|
||||
mode |= SELECTMODE;
|
||||
if (vim_strchr(modechars, 'o') != NULL)
|
||||
mode |= OP_PENDING;
|
||||
if (vim_strchr(modechars, 'i') != NULL)
|
||||
mode |= INSERT;
|
||||
if (vim_strchr(modechars, 'l') != NULL)
|
||||
mode |= LANGMAP;
|
||||
if (vim_strchr(modechars, 'c') != NULL)
|
||||
mode |= CMDLINE;
|
||||
#define MAPMODE(mode, modechars, chr, modeflags) \
|
||||
do { \
|
||||
if (strchr(modechars, chr) != NULL) { \
|
||||
mode |= modeflags; \
|
||||
} \
|
||||
} while (0)
|
||||
MAPMODE(mode, modechars, 'n', NORMAL);
|
||||
MAPMODE(mode, modechars, 'v', VISUAL|SELECTMODE);
|
||||
MAPMODE(mode, modechars, 'x', VISUAL);
|
||||
MAPMODE(mode, modechars, 's', SELECTMODE);
|
||||
MAPMODE(mode, modechars, 'o', OP_PENDING);
|
||||
MAPMODE(mode, modechars, 'i', INSERT);
|
||||
MAPMODE(mode, modechars, 'l', LANGMAP);
|
||||
MAPMODE(mode, modechars, 'c', CMDLINE);
|
||||
#undef MAPMODE
|
||||
|
||||
retval = map_to_exists_mode(rhs, mode, abbr);
|
||||
retval = map_to_exists_mode((const char *)rhs, mode, abbr);
|
||||
xfree(buf);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return TRUE if a map exists that has "str" in the rhs for mode "mode".
|
||||
* Also checks mappings local to the current buffer.
|
||||
*/
|
||||
int map_to_exists_mode(char_u *rhs, int mode, int abbr)
|
||||
/// Check if a map exists that has given string in the rhs
|
||||
///
|
||||
/// Also checks mappings local to the current buffer.
|
||||
///
|
||||
/// @param[in] rhs String which mapping must have in the rhs. Termcap codes
|
||||
/// are recognized in this argument.
|
||||
/// @param[in] mode Mode(s) in which mappings are checked.
|
||||
/// @param[in] abbr true if checking abbreviations in place of mappings.
|
||||
///
|
||||
/// @return true if there is at least one mapping with given parameters.
|
||||
int map_to_exists_mode(const char *const rhs, const int mode, const bool abbr)
|
||||
{
|
||||
mapblock_T *mp;
|
||||
int hash;
|
||||
int expand_buffer = FALSE;
|
||||
bool expand_buffer = false;
|
||||
|
||||
validate_maphash();
|
||||
|
||||
/* Do it twice: once for global maps and once for local maps. */
|
||||
for (;; ) {
|
||||
for (hash = 0; hash < 256; ++hash) {
|
||||
// Do it twice: once for global maps and once for local maps.
|
||||
for (;;) {
|
||||
for (hash = 0; hash < 256; hash++) {
|
||||
if (abbr) {
|
||||
if (hash > 0) /* there is only one abbr list */
|
||||
if (hash > 0) { // There is only one abbr list.
|
||||
break;
|
||||
if (expand_buffer)
|
||||
}
|
||||
if (expand_buffer) {
|
||||
mp = curbuf->b_first_abbr;
|
||||
else
|
||||
} else {
|
||||
mp = first_abbr;
|
||||
} else if (expand_buffer)
|
||||
}
|
||||
} else if (expand_buffer) {
|
||||
mp = curbuf->b_maphash[hash];
|
||||
else
|
||||
} else {
|
||||
mp = maphash[hash];
|
||||
}
|
||||
for (; mp; mp = mp->m_next) {
|
||||
if ((mp->m_mode & mode)
|
||||
&& strstr((char *)mp->m_str, (char *)rhs) != NULL)
|
||||
return TRUE;
|
||||
&& strstr((char *)mp->m_str, rhs) != NULL) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (expand_buffer)
|
||||
if (expand_buffer) {
|
||||
break;
|
||||
expand_buffer = TRUE;
|
||||
}
|
||||
expand_buffer = true;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
#ifndef NVIM_GETTEXT_H
|
||||
#define NVIM_GETTEXT_H
|
||||
|
||||
#ifdef HAVE_WORKING_LIBINTL
|
||||
# include <libintl.h>
|
||||
# define _(x) gettext((char *)(x))
|
||||
// XXX do we actually need this?
|
||||
# ifdef gettext_noop
|
||||
# define N_(x) gettext_noop(x)
|
||||
# else
|
||||
# define N_(x) x
|
||||
# endif
|
||||
#else
|
||||
# define _(x) ((char *)(x))
|
||||
# define N_(x) x
|
||||
# define bindtextdomain(x, y) // empty
|
||||
# define bind_textdomain_codeset(x, y) // empty
|
||||
# define textdomain(x) // empty
|
||||
#endif
|
||||
|
||||
#endif // NVIM_GETTEXT_H
|
|
@ -12,6 +12,7 @@
|
|||
#include "nvim/syntax_defs.h"
|
||||
#include "nvim/types.h"
|
||||
#include "nvim/event/loop.h"
|
||||
#include "nvim/os/os_defs.h"
|
||||
|
||||
#define IOSIZE (1024+1) // file I/O and sprintf buffer size
|
||||
|
||||
|
@ -21,16 +22,6 @@
|
|||
# define MSG_BUF_CLEN (MSG_BUF_LEN / 6) // cell length (worst case: utf-8
|
||||
// takes 6 bytes for one cell)
|
||||
|
||||
// Maximum length of a file path. Make it a bit long, to stay
|
||||
// on the safe side. But not too long to put on the stack.
|
||||
#ifndef MAXPATHL
|
||||
# ifdef MAXPATHLEN
|
||||
# define MAXPATHL MAXPATHLEN
|
||||
# else
|
||||
# define MAXPATHL 256
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifdef WIN32
|
||||
# define _PATHSEPSTR "\\"
|
||||
#else
|
||||
|
@ -473,6 +464,7 @@ typedef enum {
|
|||
, HLF_CUL // 'cursurline'
|
||||
, HLF_MC // 'colorcolumn'
|
||||
, HLF_QFL // selected quickfix line
|
||||
, HLF_0 // Whitespace
|
||||
, HLF_COUNT // MUST be the last one
|
||||
} hlf_T;
|
||||
|
||||
|
@ -481,7 +473,7 @@ typedef enum {
|
|||
#define HL_FLAGS { '8', '~', 'z', 'Z', '@', 'd', 'e', 'i', 'l', 'm', 'M', 'n', \
|
||||
'N', 'r', 's', 'S', 'c', 't', 'v', 'V', 'w', 'W', 'f', 'F', \
|
||||
'A', 'C', 'D', 'T', '-', '>', 'B', 'P', 'R', 'L', '+', '=', \
|
||||
'x', 'X', '*', '#', '_', '!', '.', 'o', 'q' }
|
||||
'x', 'X', '*', '#', '_', '!', '.', 'o', 'q', '0' }
|
||||
|
||||
EXTERN int highlight_attr[HLF_COUNT]; /* Highl. attr for each context. */
|
||||
EXTERN int highlight_user[9]; /* User[1-9] attributes */
|
||||
|
@ -1208,6 +1200,7 @@ EXTERN char_u e_dirnotf[] INIT(= N_(
|
|||
"E919: Directory not found in '%s': \"%s\""));
|
||||
EXTERN char_u e_unsupportedoption[] INIT(= N_("E519: Option not supported"));
|
||||
EXTERN char_u e_fnametoolong[] INIT(= N_("E856: Filename too long"));
|
||||
EXTERN char_u e_float_as_string[] INIT(= N_("E806: using Float as a String"));
|
||||
|
||||
|
||||
EXTERN char top_bot_msg[] INIT(= N_("search hit TOP, continuing at BOTTOM"));
|
||||
|
@ -1226,11 +1219,6 @@ EXTERN FILE *time_fd INIT(= NULL); /* where to write startup timing */
|
|||
EXTERN int ignored;
|
||||
EXTERN char *ignoredp;
|
||||
|
||||
EXTERN bool in_free_unref_items INIT(= false);
|
||||
|
||||
// Used for checking if local variables or arguments used in a lambda.
|
||||
EXTERN int *eval_lavars_used INIT(= NULL);
|
||||
|
||||
// If a msgpack-rpc channel should be started over stdin/stdout
|
||||
EXTERN bool embedded_mode INIT(= false);
|
||||
|
||||
|
@ -1255,7 +1243,7 @@ typedef enum {
|
|||
kCdScopeInvalid = -1,
|
||||
kCdScopeWindow, ///< Affects one window.
|
||||
kCdScopeTab, ///< Affects one tab page.
|
||||
kCdScopeGlobal, ///< Affects the entire instance of Neovim.
|
||||
kCdScopeGlobal, ///< Affects the entire Nvim instance.
|
||||
} CdScope;
|
||||
|
||||
#define MIN_CD_SCOPE kCdScopeWindow
|
||||
|
|
|
@ -369,7 +369,6 @@ static void prt_get_attr(int hl_id, prt_text_attr_T *pattr, int modec)
|
|||
{
|
||||
int colorindex;
|
||||
uint32_t fg_color;
|
||||
char *color;
|
||||
|
||||
pattr->bold = (highlight_has_attr(hl_id, HL_BOLD, modec) != NULL);
|
||||
pattr->italic = (highlight_has_attr(hl_id, HL_ITALIC, modec) != NULL);
|
||||
|
@ -377,11 +376,12 @@ static void prt_get_attr(int hl_id, prt_text_attr_T *pattr, int modec)
|
|||
pattr->undercurl = (highlight_has_attr(hl_id, HL_UNDERCURL, modec) != NULL);
|
||||
|
||||
{
|
||||
color = (char *)highlight_color(hl_id, (char_u *)"fg", modec);
|
||||
if (color == NULL)
|
||||
const char *color = highlight_color(hl_id, "fg", modec);
|
||||
if (color == NULL) {
|
||||
colorindex = 0;
|
||||
else
|
||||
} else {
|
||||
colorindex = atoi(color);
|
||||
}
|
||||
|
||||
if (colorindex >= 0 && colorindex < t_colors)
|
||||
fg_color = prt_get_term_color(colorindex);
|
||||
|
|
|
@ -82,7 +82,7 @@ void hash_clear_all(hashtab_T *ht, unsigned int off)
|
|||
/// used for that key.
|
||||
/// WARNING: Returned pointer becomes invalid as soon as the hash table
|
||||
/// is changed in any way.
|
||||
hashitem_T *hash_find(hashtab_T *ht, const char_u *key)
|
||||
hashitem_T *hash_find(const hashtab_T *const ht, const char_u *const key)
|
||||
{
|
||||
return hash_lookup(ht, (const char *)key, STRLEN(key), hash_hash(key));
|
||||
}
|
||||
|
@ -99,7 +99,8 @@ hashitem_T *hash_find(hashtab_T *ht, const char_u *key)
|
|||
///
|
||||
/// @warning Returned pointer becomes invalid as soon as the hash table
|
||||
/// is changed in any way.
|
||||
hashitem_T *hash_find_len(hashtab_T *ht, const char *key, const size_t len)
|
||||
hashitem_T *hash_find_len(const hashtab_T *const ht, const char *const key,
|
||||
const size_t len)
|
||||
{
|
||||
return hash_lookup(ht, key, len, hash_hash_len(key, len));
|
||||
}
|
||||
|
@ -115,7 +116,7 @@ hashitem_T *hash_find_len(hashtab_T *ht, const char *key, const size_t len)
|
|||
/// used for that key.
|
||||
/// WARNING: Returned pointer becomes invalid as soon as the hash table
|
||||
/// is changed in any way.
|
||||
hashitem_T *hash_lookup(hashtab_T *const ht,
|
||||
hashitem_T *hash_lookup(const hashtab_T *const ht,
|
||||
const char *const key, const size_t key_len,
|
||||
const hash_T hash)
|
||||
{
|
||||
|
|
|
@ -70,6 +70,25 @@ typedef struct hashtable_S {
|
|||
hashitem_T ht_smallarray[HT_INIT_SIZE]; /// initial array
|
||||
} hashtab_T;
|
||||
|
||||
/// Iterate over a hashtab
|
||||
///
|
||||
/// @param[in] ht Hashtab to iterate over.
|
||||
/// @param hi Name of the variable with current hashtab entry.
|
||||
/// @param code Cycle body.
|
||||
#define HASHTAB_ITER(ht, hi, code) \
|
||||
do { \
|
||||
hashtab_T *const hi##ht_ = (ht); \
|
||||
size_t hi##todo_ = hi##ht_->ht_used; \
|
||||
for (hashitem_T *hi = hi##ht_->ht_array; hi##todo_; hi++) { \
|
||||
if (!HASHITEM_EMPTY(hi)) { \
|
||||
{ \
|
||||
code \
|
||||
} \
|
||||
hi##todo_--; \
|
||||
} \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#ifdef INCLUDE_GENERATED_DECLARATIONS
|
||||
# include "hashtab.h.generated.h"
|
||||
#endif
|
||||
|
|
|
@ -140,31 +140,30 @@ char_u *get_cscope_name(expand_T *xp, int idx)
|
|||
/*
|
||||
* Handle command line completion for :cscope command.
|
||||
*/
|
||||
void set_context_in_cscope_cmd(expand_T *xp, char_u *arg, cmdidx_T cmdidx)
|
||||
void set_context_in_cscope_cmd(expand_T *xp, const char *arg, cmdidx_T cmdidx)
|
||||
{
|
||||
char_u *p;
|
||||
|
||||
/* Default: expand subcommands */
|
||||
// Default: expand subcommands.
|
||||
xp->xp_context = EXPAND_CSCOPE;
|
||||
xp->xp_pattern = arg;
|
||||
expand_what = (cmdidx == CMD_scscope)
|
||||
? EXP_SCSCOPE_SUBCMD : EXP_CSCOPE_SUBCMD;
|
||||
xp->xp_pattern = (char_u *)arg;
|
||||
expand_what = ((cmdidx == CMD_scscope)
|
||||
? EXP_SCSCOPE_SUBCMD : EXP_CSCOPE_SUBCMD);
|
||||
|
||||
/* (part of) subcommand already typed */
|
||||
if (*arg != NUL) {
|
||||
p = skiptowhite(arg);
|
||||
if (*p != NUL) { /* past first word */
|
||||
xp->xp_pattern = skipwhite(p);
|
||||
if (*skiptowhite(xp->xp_pattern) != NUL)
|
||||
const char *p = (const char *)skiptowhite((const char_u *)arg);
|
||||
if (*p != NUL) { // Past first word.
|
||||
xp->xp_pattern = skipwhite((const char_u *)p);
|
||||
if (*skiptowhite(xp->xp_pattern) != NUL) {
|
||||
xp->xp_context = EXPAND_NOTHING;
|
||||
else if (STRNICMP(arg, "add", p - arg) == 0)
|
||||
} else if (STRNICMP(arg, "add", p - arg) == 0) {
|
||||
xp->xp_context = EXPAND_FILES;
|
||||
else if (STRNICMP(arg, "kill", p - arg) == 0)
|
||||
} else if (STRNICMP(arg, "kill", p - arg) == 0) {
|
||||
expand_what = EXP_CSCOPE_KILL;
|
||||
else if (STRNICMP(arg, "find", p - arg) == 0)
|
||||
} else if (STRNICMP(arg, "find", p - arg) == 0) {
|
||||
expand_what = EXP_CSCOPE_FIND;
|
||||
else
|
||||
} else {
|
||||
xp->xp_context = EXPAND_NOTHING;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -174,7 +174,7 @@ static char_u *skip_string(char_u *p)
|
|||
char_u *paren = vim_strchr(delim, '(');
|
||||
|
||||
if (paren != NULL) {
|
||||
ptrdiff_t delim_len = paren - delim;
|
||||
const ptrdiff_t delim_len = paren - delim;
|
||||
|
||||
for (p += 3; *p; ++p)
|
||||
if (p[0] == ')' && STRNCMP(p + 1, delim, delim_len) == 0
|
||||
|
|
|
@ -94,7 +94,7 @@
|
|||
do { \
|
||||
if (*p_langmap \
|
||||
&& (condition) \
|
||||
&& (!p_lnr || (p_lnr && typebuf_maplen() == 0)) \
|
||||
&& (p_lrm || (!p_lrm && KeyTyped)) \
|
||||
&& !KeyStuffed \
|
||||
&& (c) >= 0) \
|
||||
{ \
|
||||
|
|
|
@ -283,7 +283,7 @@ int main(int argc, char **argv)
|
|||
cmdline_row = (int)(Rows - p_ch);
|
||||
msg_row = cmdline_row;
|
||||
screenalloc(false); /* allocate screen buffers */
|
||||
set_init_2();
|
||||
set_init_2(params.headless);
|
||||
TIME_MSG("inits 2");
|
||||
|
||||
msg_scroll = TRUE;
|
||||
|
@ -391,9 +391,10 @@ int main(int argc, char **argv)
|
|||
shada_read_everything(NULL, false, true);
|
||||
TIME_MSG("reading ShaDa");
|
||||
}
|
||||
/* It's better to make v:oldfiles an empty list than NULL. */
|
||||
if (get_vim_var_list(VV_OLDFILES) == NULL)
|
||||
set_vim_var_list(VV_OLDFILES, list_alloc());
|
||||
// It's better to make v:oldfiles an empty list than NULL.
|
||||
if (get_vim_var_list(VV_OLDFILES) == NULL) {
|
||||
set_vim_var_list(VV_OLDFILES, tv_list_alloc());
|
||||
}
|
||||
|
||||
/*
|
||||
* "-q errorfile": Load the error file now.
|
||||
|
@ -802,17 +803,18 @@ static void command_line_scan(mparm_T *parmp)
|
|||
argv_idx = -1; /* skip to next argument */
|
||||
break;
|
||||
|
||||
case 'A': /* "-A" start in Arabic mode */
|
||||
set_option_value((char_u *)"arabic", 1L, NULL, 0);
|
||||
case 'A': { // "-A" start in Arabic mode.
|
||||
set_option_value("arabic", 1L, NULL, 0);
|
||||
break;
|
||||
|
||||
case 'b': /* "-b" binary mode */
|
||||
/* Needs to be effective before expanding file names, because
|
||||
* for Win32 this makes us edit a shortcut file itself,
|
||||
* instead of the file it links to. */
|
||||
}
|
||||
case 'b': { // "-b" binary mode.
|
||||
// Needs to be effective before expanding file names, because
|
||||
// for Win32 this makes us edit a shortcut file itself,
|
||||
// instead of the file it links to.
|
||||
set_options_bin(curbuf->b_p_bin, 1, 0);
|
||||
curbuf->b_p_bin = 1; /* binary file I/O */
|
||||
curbuf->b_p_bin = 1; // Binary file I/O.
|
||||
break;
|
||||
}
|
||||
|
||||
case 'e': /* "-e" Ex mode */
|
||||
exmode_active = EXMODE_NORMAL;
|
||||
|
@ -829,24 +831,27 @@ static void command_line_scan(mparm_T *parmp)
|
|||
main_start_gui();
|
||||
break;
|
||||
|
||||
case 'F': /* "-F" start in Farsi mode: rl + fkmap set */
|
||||
p_fkmap = TRUE;
|
||||
set_option_value((char_u *)"rl", 1L, NULL, 0);
|
||||
case 'F': { // "-F" start in Farsi mode: rl + fkmap set.
|
||||
p_fkmap = true;
|
||||
set_option_value("rl", 1L, NULL, 0);
|
||||
break;
|
||||
}
|
||||
|
||||
case 'h': /* "-h" give help message */
|
||||
usage();
|
||||
mch_exit(0);
|
||||
|
||||
case 'H': /* "-H" start in Hebrew mode: rl + hkmap set */
|
||||
p_hkmap = TRUE;
|
||||
set_option_value((char_u *)"rl", 1L, NULL, 0);
|
||||
case 'H': { // "-H" start in Hebrew mode: rl + hkmap set.
|
||||
p_hkmap = true;
|
||||
set_option_value("rl", 1L, NULL, 0);
|
||||
break;
|
||||
}
|
||||
|
||||
case 'l': /* "-l" lisp mode, 'lisp' and 'showmatch' on */
|
||||
set_option_value((char_u *)"lisp", 1L, NULL, 0);
|
||||
p_sm = TRUE;
|
||||
case 'l': { // "-l" lisp mode, 'lisp' and 'showmatch' on.
|
||||
set_option_value("lisp", 1L, NULL, 0);
|
||||
p_sm = true;
|
||||
break;
|
||||
}
|
||||
|
||||
case 'M': /* "-M" no changes or writing of files */
|
||||
reset_modifiable();
|
||||
|
@ -945,8 +950,7 @@ static void command_line_scan(mparm_T *parmp)
|
|||
/* default is 10: a little bit verbose */
|
||||
p_verbose = get_number_arg(argv[0], &argv_idx, 10);
|
||||
if (argv[0][argv_idx] != NUL) {
|
||||
set_option_value((char_u *)"verbosefile", 0L,
|
||||
(char_u *)argv[0] + argv_idx, 0);
|
||||
set_option_value("verbosefile", 0L, argv[0] + argv_idx, 0);
|
||||
argv_idx = (int)STRLEN(argv[0]);
|
||||
}
|
||||
break;
|
||||
|
@ -955,7 +959,7 @@ static void command_line_scan(mparm_T *parmp)
|
|||
/* "-w {scriptout}" write to script */
|
||||
if (ascii_isdigit(((char_u *)argv[0])[argv_idx])) {
|
||||
n = get_number_arg(argv[0], &argv_idx, 10);
|
||||
set_option_value((char_u *)"window", n, NULL, 0);
|
||||
set_option_value("window", n, NULL, 0);
|
||||
break;
|
||||
}
|
||||
want_argument = TRUE;
|
||||
|
@ -1087,7 +1091,7 @@ scripterror:
|
|||
if (ascii_isdigit(*((char_u *)argv[0]))) {
|
||||
argv_idx = 0;
|
||||
n = get_number_arg(argv[0], &argv_idx, 10);
|
||||
set_option_value((char_u *)"window", n, NULL, 0);
|
||||
set_option_value("window", n, NULL, 0);
|
||||
argv_idx = -1;
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -62,7 +62,7 @@ int setmark(int c)
|
|||
/// Free fmark_T item
|
||||
void free_fmark(fmark_T fm)
|
||||
{
|
||||
dict_unref(fm.additional_data);
|
||||
tv_dict_unref(fm.additional_data);
|
||||
}
|
||||
|
||||
/// Free xfmark_T item
|
||||
|
@ -1431,3 +1431,26 @@ void free_all_marks(void)
|
|||
memset(&namedfm[0], 0, sizeof(namedfm));
|
||||
}
|
||||
#endif
|
||||
|
||||
/// Adjust position to point to the first byte of a multi-byte character
|
||||
///
|
||||
/// If it points to a tail byte it is move backwards to the head byte.
|
||||
///
|
||||
/// @param[in] buf Buffer to adjust position in.
|
||||
/// @param[out] lp Position to adjust.
|
||||
void mark_mb_adjustpos(buf_T *buf, pos_T *lp)
|
||||
FUNC_ATTR_NONNULL_ALL
|
||||
{
|
||||
if (lp->col > 0 || lp->coladd > 1) {
|
||||
const char_u *const p = ml_get_buf(buf, lp->lnum, false);
|
||||
lp->col -= (*mb_head_off)(p, p + lp->col);
|
||||
// Reset "coladd" when the cursor would be on the right half of a
|
||||
// double-wide character.
|
||||
if (lp->coladd == 1
|
||||
&& p[lp->col] != TAB
|
||||
&& vim_isprintc((*mb_ptr2char)(p + lp->col))
|
||||
&& ptr2cells(p + lp->col) > 1) {
|
||||
lp->coladd = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,7 +29,7 @@
|
|||
|
||||
/// Clear given fmark
|
||||
#define CLEAR_FMARK(fmarkp_) \
|
||||
RESET_FMARK(fmarkp_, ((pos_T) {0, 0, 0}), 0)
|
||||
RESET_FMARK(fmarkp_, ((pos_T) { 0, 0, 0 }), 0)
|
||||
|
||||
/// Set given extended mark (regular mark + file name)
|
||||
#define SET_XFMARK(xfmarkp_, mark_, fnum_, fname_) \
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
#include "nvim/pos.h"
|
||||
#include "nvim/os/time.h"
|
||||
#include "nvim/eval_defs.h"
|
||||
#include "nvim/eval/typval.h"
|
||||
|
||||
/*
|
||||
* marks: positions in a file
|
||||
|
|
130
src/nvim/mbyte.c
130
src/nvim/mbyte.c
|
@ -50,6 +50,7 @@
|
|||
#include "nvim/strings.h"
|
||||
#include "nvim/os/os.h"
|
||||
#include "nvim/arabic.h"
|
||||
#include "nvim/mark.h"
|
||||
|
||||
typedef struct {
|
||||
int rangeStart;
|
||||
|
@ -375,16 +376,18 @@ void remove_bom(char_u *s)
|
|||
*/
|
||||
int mb_get_class(const char_u *p)
|
||||
{
|
||||
return mb_get_class_buf(p, curbuf);
|
||||
return mb_get_class_tab(p, curbuf->b_chartab);
|
||||
}
|
||||
|
||||
int mb_get_class_buf(const char_u *p, buf_T *buf)
|
||||
int mb_get_class_tab(const char_u *p, const uint64_t *const chartab)
|
||||
{
|
||||
if (MB_BYTE2LEN(p[0]) == 1) {
|
||||
if (p[0] == NUL || ascii_iswhite(p[0]))
|
||||
if (p[0] == NUL || ascii_iswhite(p[0])) {
|
||||
return 0;
|
||||
if (vim_iswordc_buf(p[0], buf))
|
||||
}
|
||||
if (vim_iswordc_tab(p[0], chartab)) {
|
||||
return 2;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
return utf_class(utf_ptr2char(p));
|
||||
|
@ -580,7 +583,7 @@ int utf_ptr2char(const char_u *p)
|
|||
* If byte sequence is illegal or incomplete, returns -1 and does not advance
|
||||
* "s".
|
||||
*/
|
||||
static int utf_safe_read_char_adv(char_u **s, size_t *n)
|
||||
static int utf_safe_read_char_adv(const char_u **s, size_t *n)
|
||||
{
|
||||
int c;
|
||||
|
||||
|
@ -622,7 +625,7 @@ static int utf_safe_read_char_adv(char_u **s, size_t *n)
|
|||
* Get character at **pp and advance *pp to the next character.
|
||||
* Note: composing characters are skipped!
|
||||
*/
|
||||
int mb_ptr2char_adv(char_u **pp)
|
||||
int mb_ptr2char_adv(const char_u **const pp)
|
||||
{
|
||||
int c;
|
||||
|
||||
|
@ -635,7 +638,7 @@ int mb_ptr2char_adv(char_u **pp)
|
|||
* Get character at **pp and advance *pp to the next character.
|
||||
* Note: composing characters are returned as separate characters.
|
||||
*/
|
||||
int mb_cptr2char_adv(char_u **pp)
|
||||
int mb_cptr2char_adv(const char_u **pp)
|
||||
{
|
||||
int c;
|
||||
|
||||
|
@ -1230,7 +1233,8 @@ bool utf_isupper(int a)
|
|||
return utf_tolower(a) != a;
|
||||
}
|
||||
|
||||
static int utf_strnicmp(char_u *s1, char_u *s2, size_t n1, size_t n2)
|
||||
static int utf_strnicmp(const char_u *s1, const char_u *s2, size_t n1,
|
||||
size_t n2)
|
||||
{
|
||||
int c1, c2, cdiff;
|
||||
char_u buffer[6];
|
||||
|
@ -1300,6 +1304,7 @@ static int utf_strnicmp(char_u *s1, char_u *s2, size_t n1, size_t n2)
|
|||
# define CP_UTF8 65001 /* magic number from winnls.h */
|
||||
#endif
|
||||
|
||||
/// Reassigns `strw` to a new, allocated pointer to a UTF16 string.
|
||||
int utf8_to_utf16(const char *str, WCHAR **strw)
|
||||
FUNC_ATTR_NONNULL_ALL
|
||||
{
|
||||
|
@ -1341,40 +1346,40 @@ int utf8_to_utf16(const char *str, WCHAR **strw)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/// Reassigns `str` to a new, allocated pointer to a UTF8 string.
|
||||
int utf16_to_utf8(const WCHAR *strw, char **str)
|
||||
FUNC_ATTR_NONNULL_ALL
|
||||
{
|
||||
// Compute the space required to store the string as UTF-8.
|
||||
ssize_t utf8_len = WideCharToMultiByte(CP_UTF8,
|
||||
0,
|
||||
strw,
|
||||
-1,
|
||||
NULL,
|
||||
0,
|
||||
NULL,
|
||||
NULL);
|
||||
DWORD utf8_len = WideCharToMultiByte(CP_UTF8,
|
||||
0,
|
||||
strw,
|
||||
-1,
|
||||
NULL,
|
||||
0,
|
||||
NULL,
|
||||
NULL);
|
||||
if (utf8_len == 0) {
|
||||
return GetLastError();
|
||||
}
|
||||
|
||||
ssize_t buf_sz = utf8_len * sizeof(char);
|
||||
char *buf = xmalloc(buf_sz);
|
||||
char *pos = buf;
|
||||
*str = xmalloc(utf8_len);
|
||||
|
||||
// Convert string to UTF-8.
|
||||
int r = WideCharToMultiByte(CP_UTF8,
|
||||
0,
|
||||
strw,
|
||||
-1,
|
||||
pos,
|
||||
utf8_len,
|
||||
NULL,
|
||||
NULL);
|
||||
assert(r == utf8_len);
|
||||
if (r != utf8_len) {
|
||||
EMSG2("WideCharToMultiByte failed: %d", r);
|
||||
// Convert to UTF-8.
|
||||
utf8_len = WideCharToMultiByte(CP_UTF8,
|
||||
0,
|
||||
strw,
|
||||
-1,
|
||||
*str,
|
||||
utf8_len,
|
||||
NULL,
|
||||
NULL);
|
||||
if (utf8_len == 0) {
|
||||
free(*str);
|
||||
*str = NULL;
|
||||
return GetLastError();
|
||||
}
|
||||
*str = pos;
|
||||
(*str)[utf8_len] = '\0';
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -1389,19 +1394,26 @@ int utf16_to_utf8(const WCHAR *strw, char **str)
|
|||
* Returns zero if s1 and s2 are equal (ignoring case), the difference between
|
||||
* two characters otherwise.
|
||||
*/
|
||||
int mb_strnicmp(char_u *s1, char_u *s2, size_t nn)
|
||||
int mb_strnicmp(const char_u *s1, const char_u *s2, const size_t nn)
|
||||
{
|
||||
return utf_strnicmp(s1, s2, nn, nn);
|
||||
}
|
||||
|
||||
/* We need to call mb_stricmp() even when we aren't dealing with a multi-byte
|
||||
* encoding because mb_stricmp() takes care of all ascii and non-ascii
|
||||
* encodings, including characters with umlauts in latin1, etc., while
|
||||
* STRICMP() only handles the system locale version, which often does not
|
||||
* handle non-ascii properly. */
|
||||
int mb_stricmp(char_u *s1, char_u *s2)
|
||||
/// Compare strings case-insensitively
|
||||
///
|
||||
/// @note We need to call mb_stricmp() even when we aren't dealing with
|
||||
/// a multi-byte encoding because mb_stricmp() takes care of all ASCII and
|
||||
/// non-ascii encodings, including characters with umlauts in latin1,
|
||||
/// etc., while STRICMP() only handles the system locale version, which
|
||||
/// often does not handle non-ascii properly.
|
||||
///
|
||||
/// @param[in] s1 First string to compare, not more then #MAXCOL characters.
|
||||
/// @param[in] s2 Second string to compare, not more then #MAXCOL characters.
|
||||
///
|
||||
/// @return 0 if strings are equal, <0 if s1 < s2, >0 if s1 > s2.
|
||||
int mb_stricmp(const char *s1, const char *s2)
|
||||
{
|
||||
return mb_strnicmp(s1, s2, MAXCOL);
|
||||
return mb_strnicmp((const char_u *)s1, (const char_u *)s2, MAXCOL);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1639,38 +1651,16 @@ theend:
|
|||
*/
|
||||
void mb_adjust_cursor(void)
|
||||
{
|
||||
mb_adjustpos(curbuf, &curwin->w_cursor);
|
||||
}
|
||||
|
||||
/*
|
||||
* Adjust position "*lp" to point to the first byte of a multi-byte character.
|
||||
* If it points to a tail byte it's moved backwards to the head byte.
|
||||
*/
|
||||
void mb_adjustpos(buf_T *buf, pos_T *lp)
|
||||
{
|
||||
char_u *p;
|
||||
|
||||
if (lp->col > 0
|
||||
|| lp->coladd > 1
|
||||
) {
|
||||
p = ml_get_buf(buf, lp->lnum, FALSE);
|
||||
lp->col -= (*mb_head_off)(p, p + lp->col);
|
||||
/* Reset "coladd" when the cursor would be on the right half of a
|
||||
* double-wide character. */
|
||||
if (lp->coladd == 1
|
||||
&& p[lp->col] != TAB
|
||||
&& vim_isprintc((*mb_ptr2char)(p + lp->col))
|
||||
&& ptr2cells(p + lp->col) > 1)
|
||||
lp->coladd = 0;
|
||||
}
|
||||
mark_mb_adjustpos(curbuf, &curwin->w_cursor);
|
||||
}
|
||||
|
||||
/// Checks and adjusts cursor column. Not mode-dependent.
|
||||
/// @see check_cursor_col_win
|
||||
///
|
||||
/// @param win Places cursor on a valid column for this window.
|
||||
void mb_check_adjust_col(win_T *win)
|
||||
/// @param win_ Places cursor on a valid column for this window.
|
||||
void mb_check_adjust_col(void *win_)
|
||||
{
|
||||
win_T *win = (win_T *)win_;
|
||||
colnr_T oldcol = win->w_cursor.col;
|
||||
|
||||
// Column 0 is always valid.
|
||||
|
@ -2039,8 +2029,8 @@ void * my_iconv_open(char_u *to, char_u *from)
|
|||
* Returns the converted string in allocated memory. NULL for an error.
|
||||
* If resultlenp is not NULL, sets it to the result length in bytes.
|
||||
*/
|
||||
static char_u * iconv_string(vimconv_T *vcp, char_u *str, size_t slen,
|
||||
size_t *unconvlenp, size_t *resultlenp)
|
||||
static char_u *iconv_string(const vimconv_T *const vcp, char_u *str,
|
||||
size_t slen, size_t *unconvlenp, size_t *resultlenp)
|
||||
{
|
||||
const char *from;
|
||||
size_t fromlen;
|
||||
|
@ -2325,7 +2315,7 @@ int convert_setup_ext(vimconv_T *vcp, char_u *from, bool from_unicode_is_utf8,
|
|||
* Illegal chars are often changed to "?", unless vcp->vc_fail is set.
|
||||
* When something goes wrong, NULL is returned and "*lenp" is unchanged.
|
||||
*/
|
||||
char_u * string_convert(vimconv_T *vcp, char_u *ptr, size_t *lenp)
|
||||
char_u *string_convert(const vimconv_T *const vcp, char_u *ptr, size_t *lenp)
|
||||
{
|
||||
return string_convert_ext(vcp, ptr, lenp, NULL);
|
||||
}
|
||||
|
@ -2335,7 +2325,7 @@ char_u * string_convert(vimconv_T *vcp, char_u *ptr, size_t *lenp)
|
|||
* an incomplete sequence at the end it is not converted and "*unconvlenp" is
|
||||
* set to the number of remaining bytes.
|
||||
*/
|
||||
char_u * string_convert_ext(vimconv_T *vcp, char_u *ptr,
|
||||
char_u * string_convert_ext(const vimconv_T *const vcp, char_u *ptr,
|
||||
size_t *lenp, size_t *unconvlenp)
|
||||
{
|
||||
char_u *retval = NULL;
|
||||
|
|
|
@ -2,6 +2,11 @@
|
|||
#define NVIM_MBYTE_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "nvim/iconv.h"
|
||||
#include "nvim/func_attr.h"
|
||||
#include "nvim/os/os_defs.h" // For WCHAR, indirect
|
||||
|
||||
/*
|
||||
* Return byte length of character that starts with byte "b".
|
||||
|
@ -40,7 +45,41 @@
|
|||
#define mb_ptr2char utf_ptr2char
|
||||
#define mb_head_off utf_head_off
|
||||
|
||||
/// Flags for vimconv_T
|
||||
typedef enum {
|
||||
CONV_NONE = 0,
|
||||
CONV_TO_UTF8 = 1,
|
||||
CONV_9_TO_UTF8 = 2,
|
||||
CONV_TO_LATIN1 = 3,
|
||||
CONV_TO_LATIN9 = 4,
|
||||
CONV_ICONV = 5,
|
||||
} ConvFlags;
|
||||
|
||||
/// Structure used for string conversions
|
||||
typedef struct {
|
||||
int vc_type; ///< Zero or more ConvFlags.
|
||||
int vc_factor; ///< Maximal expansion factor.
|
||||
# ifdef USE_ICONV
|
||||
iconv_t vc_fd; ///< Value for CONV_ICONV.
|
||||
# endif
|
||||
bool vc_fail; ///< What to do with invalid characters: if true, fail,
|
||||
///< otherwise use '?'.
|
||||
} vimconv_T;
|
||||
|
||||
#ifdef INCLUDE_GENERATED_DECLARATIONS
|
||||
# include "mbyte.h.generated.h"
|
||||
#endif
|
||||
|
||||
static inline int mb_strcmp_ic(bool ic, const char *s1, const char *s2)
|
||||
REAL_FATTR_NONNULL_ALL REAL_FATTR_PURE REAL_FATTR_WARN_UNUSED_RESULT;
|
||||
|
||||
/// Compare strings
|
||||
///
|
||||
/// @param[in] ic True if case is to be ignored.
|
||||
///
|
||||
/// @return 0 if s1 == s2, <0 if s1 < s2, >0 if s1 > s2.
|
||||
static inline int mb_strcmp_ic(bool ic, const char *s1, const char *s2)
|
||||
{
|
||||
return (ic ? mb_stricmp(s1, s2) : strcmp(s1, s2));
|
||||
}
|
||||
#endif // NVIM_MBYTE_H
|
||||
|
|
|
@ -992,7 +992,7 @@ void ml_recover(void)
|
|||
if (b0_ff != 0)
|
||||
set_fileformat(b0_ff - 1, OPT_LOCAL);
|
||||
if (b0_fenc != NULL) {
|
||||
set_option_value((char_u *)"fenc", 0L, b0_fenc, OPT_LOCAL);
|
||||
set_option_value("fenc", 0L, (char *)b0_fenc, OPT_LOCAL);
|
||||
xfree(b0_fenc);
|
||||
}
|
||||
unchanged(curbuf, TRUE);
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue