mirror of
https://github.com/neovim/neovim.git
synced 2025-02-25 18:55:25 -06:00
Merge branch 'master' into s-dash-stdin
This commit is contained in:
commit
ad999eaa77
13
.gitignore
vendored
13
.gitignore
vendored
@ -1,3 +1,6 @@
|
||||
# Tools
|
||||
.ropeproject/
|
||||
|
||||
# Build/deps dir
|
||||
/build/
|
||||
/cmake-build-debug/
|
||||
@ -17,13 +20,13 @@ tags
|
||||
/src/nvim/po/vim.pot
|
||||
/src/nvim/po/*.ck
|
||||
|
||||
# generated by tests with $NVIM_LOG_FILE set.
|
||||
# Generated by tests with $NVIM_LOG_FILE set.
|
||||
/.nvimlog
|
||||
|
||||
# Files generated by scripts/vim-patch.sh
|
||||
# Generated by scripts/vim-patch.sh
|
||||
/.vim-src/
|
||||
|
||||
# Files generated by the tests
|
||||
# Generated by old (Vim) tests.
|
||||
/src/nvim/testdir/del
|
||||
/src/nvim/testdir/test*.out
|
||||
/src/nvim/testdir/test*.res
|
||||
@ -36,10 +39,10 @@ tags
|
||||
/src/nvim/testdir/valgrind.*
|
||||
/src/nvim/testdir/.gdbinit
|
||||
|
||||
# Folder generated by the unit tests
|
||||
# Generated by unit tests.
|
||||
/test/includes/post/
|
||||
|
||||
# generated by luacheck during `make testlint'
|
||||
# Generated by luacheck during `make testlint'
|
||||
/test/.luacheckcache
|
||||
|
||||
# local make targets
|
||||
|
58
.travis.yml
58
.travis.yml
@ -4,13 +4,8 @@ language: c
|
||||
|
||||
env:
|
||||
global:
|
||||
# To force rebuilding of third-party dependencies, set this to 'true'.
|
||||
- BUILD_NVIM_DEPS=false
|
||||
# Travis has 1.5 virtual cores according to
|
||||
# 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-4.0/bin:$PATH"
|
||||
# Set "false" to force rebuild of third-party dependencies.
|
||||
- CACHE_ENABLE=true
|
||||
# Build directory for Neovim.
|
||||
- BUILD_DIR="$TRAVIS_BUILD_DIR/build"
|
||||
# Build directory for third-party dependencies.
|
||||
@ -41,9 +36,7 @@ env:
|
||||
- UBSAN_OPTIONS="print_stacktrace=1 log_path=$LOG_DIR/ubsan"
|
||||
# Environment variables for Valgrind.
|
||||
- VALGRIND_LOG="$LOG_DIR/valgrind-%p.log"
|
||||
# Cache marker for third-party dependencies cache.
|
||||
# If this file exists, we know that the cache contains compiled
|
||||
# dependencies and we can use it.
|
||||
# If this file exists, the cache is valid (compile was successful).
|
||||
- CACHE_MARKER="$HOME/.cache/nvim-deps/.travis_cache_marker"
|
||||
# default target name for functional tests
|
||||
- FUNCTIONALTEST=functionaltest
|
||||
@ -51,40 +44,41 @@ env:
|
||||
|
||||
jobs:
|
||||
include:
|
||||
- stage: sanitizers
|
||||
- stage: normal builds
|
||||
os: linux
|
||||
compiler: clang-4.0
|
||||
compiler: clang
|
||||
env: >
|
||||
CLANG_SANITIZER=ASAN_UBSAN
|
||||
CMAKE_FLAGS="$CMAKE_FLAGS -DPREFER_LUA=ON"
|
||||
- stage: normal builds
|
||||
os: linux
|
||||
compiler: gcc-5
|
||||
env: FUNCTIONALTEST=functionaltest-lua
|
||||
sudo: true
|
||||
- os: linux
|
||||
# Travis creates a cache per compiler.
|
||||
# Set a different value here to store 32-bit
|
||||
# dependencies in a separate cache.
|
||||
compiler: gcc-5 -m32
|
||||
compiler: gcc
|
||||
env: >
|
||||
FUNCTIONALTEST=functionaltest-lua
|
||||
CMAKE_FLAGS="$CMAKE_FLAGS -DPREFER_LUA=ON"
|
||||
DEPS_CMAKE_FLAGS="$DEPS_CMAKE_FLAGS -DUSE_BUNDLED_LUAJIT=OFF"
|
||||
- os: linux
|
||||
# Travis creates a cache per compiler. Set a different value here to
|
||||
# store 32-bit dependencies in a separate cache.
|
||||
compiler: gcc -m32
|
||||
env: BUILD_32BIT=ON
|
||||
- os: osx
|
||||
compiler: clang
|
||||
osx_image: xcode7.3 # macOS 10.11
|
||||
- os: osx
|
||||
compiler: gcc-4.9
|
||||
compiler: gcc
|
||||
osx_image: xcode7.3 # macOS 10.11
|
||||
- stage: lint
|
||||
os: linux
|
||||
- os: linux
|
||||
env: CI_TARGET=lint
|
||||
- stage: Flaky builds
|
||||
os: linux
|
||||
compiler: gcc-5
|
||||
env: GCOV=gcov-5 CMAKE_FLAGS="$CMAKE_FLAGS -DUSE_GCOV=ON"
|
||||
compiler: gcc
|
||||
env: GCOV=gcov CMAKE_FLAGS="$CMAKE_FLAGS -DUSE_GCOV=ON"
|
||||
- os: linux
|
||||
compiler: clang-4.0
|
||||
compiler: clang
|
||||
env: CLANG_SANITIZER=TSAN
|
||||
allow_failures:
|
||||
- env: GCOV=gcov-5 CMAKE_FLAGS="$CMAKE_FLAGS -DUSE_GCOV=ON"
|
||||
- env: GCOV=gcov CMAKE_FLAGS="$CMAKE_FLAGS -DUSE_GCOV=ON"
|
||||
- env: CLANG_SANITIZER=TSAN
|
||||
fast_finish: true
|
||||
|
||||
@ -97,27 +91,22 @@ after_success: ci/after_success.sh
|
||||
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
- llvm-toolchain-trusty-4.0
|
||||
packages:
|
||||
- autoconf
|
||||
- automake
|
||||
- apport
|
||||
- build-essential
|
||||
- clang-4.0
|
||||
- clang
|
||||
- cmake
|
||||
- cscope
|
||||
- g++-5-multilib
|
||||
- g++-multilib
|
||||
- gcc-5-multilib
|
||||
- gcc-multilib
|
||||
- gdb
|
||||
- language-pack-tr
|
||||
- libc6-dev-i386
|
||||
- libtool
|
||||
- llvm-4.0-dev
|
||||
- locales
|
||||
- ninja-build
|
||||
- pkg-config
|
||||
- unzip
|
||||
- valgrind
|
||||
@ -132,6 +121,7 @@ cache:
|
||||
directories:
|
||||
- "$HOME/.cache/pip"
|
||||
- "$HOME/.cache/nvim-deps"
|
||||
- "$HOME/.cache/nvim-deps-downloads"
|
||||
|
||||
notifications:
|
||||
webhooks:
|
||||
|
@ -12,7 +12,11 @@ list(APPEND CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake")
|
||||
include(PreventInTreeBuilds)
|
||||
|
||||
# Prefer our bundled versions of dependencies.
|
||||
if(DEFINED ENV{DEPS_BUILD_DIR})
|
||||
set(DEPS_PREFIX "$ENV{DEPS_BUILD_DIR}/usr" CACHE PATH "Path prefix for finding dependencies")
|
||||
else()
|
||||
set(DEPS_PREFIX "${CMAKE_CURRENT_SOURCE_DIR}/.deps/usr" CACHE PATH "Path prefix for finding dependencies")
|
||||
endif()
|
||||
if(CMAKE_CROSSCOMPILING AND NOT UNIX)
|
||||
list(INSERT CMAKE_FIND_ROOT_PATH 0 ${DEPS_PREFIX})
|
||||
list(INSERT CMAKE_PREFIX_PATH 0 ${DEPS_PREFIX}/../host/bin)
|
||||
@ -63,14 +67,14 @@ set_property(CACHE CMAKE_BUILD_TYPE PROPERTY
|
||||
# If not in a git repo (e.g., a tarball) these tokens define the complete
|
||||
# version string, else they are combined with the result of `git describe`.
|
||||
set(NVIM_VERSION_MAJOR 0)
|
||||
set(NVIM_VERSION_MINOR 2)
|
||||
set(NVIM_VERSION_PATCH 3)
|
||||
set(NVIM_VERSION_MINOR 3)
|
||||
set(NVIM_VERSION_PATCH 0)
|
||||
set(NVIM_VERSION_PRERELEASE "-dev") # for package maintainers
|
||||
|
||||
# API level
|
||||
set(NVIM_API_LEVEL 3) # Bump this after any API change.
|
||||
set(NVIM_API_LEVEL 4) # Bump this after any API change.
|
||||
set(NVIM_API_LEVEL_COMPAT 0) # Adjust this after a _breaking_ API change.
|
||||
set(NVIM_API_PRERELEASE false)
|
||||
set(NVIM_API_PRERELEASE true)
|
||||
|
||||
file(TO_CMAKE_PATH ${CMAKE_CURRENT_LIST_DIR}/.git FORCED_GIT_DIR)
|
||||
include(GetGitRevisionDescription)
|
||||
@ -204,6 +208,7 @@ int main(void)
|
||||
if(MSVC)
|
||||
# XXX: /W4 gives too many warnings. #3241
|
||||
add_definitions(/W3 -D_CRT_SECURE_NO_WARNINGS -D_CRT_NONSTDC_NO_DEPRECATE)
|
||||
add_definitions(-DWIN32)
|
||||
else()
|
||||
add_definitions(-Wall -Wextra -pedantic -Wno-unused-parameter
|
||||
-Wstrict-prototypes -std=gnu99)
|
||||
@ -223,6 +228,9 @@ endif()
|
||||
if(MINGW)
|
||||
# Use POSIX compatible stdio in Mingw
|
||||
add_definitions(-D__USE_MINGW_ANSI_STDIO)
|
||||
endif()
|
||||
if(WIN32)
|
||||
# Windows Vista is the minimum supported version
|
||||
add_definitions(-D_WIN32_WINNT=0x0600)
|
||||
endif()
|
||||
|
||||
@ -250,13 +258,14 @@ if(HAS_DIAG_COLOR_FLAG)
|
||||
endif()
|
||||
|
||||
if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
|
||||
if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS "4.8.5")
|
||||
# Array-bounds testing is broken in some GCC versions before 4.8.5.
|
||||
# https://gcc.gnu.org/bugzilla/show_bug.cgi?id=56273
|
||||
check_c_compiler_flag(-Wno-array-bounds HAS_NO_ARRAY_BOUNDS_FLAG)
|
||||
if(HAS_NO_ARRAY_BOUNDS_FLAG)
|
||||
add_definitions(-Wno-array-bounds)
|
||||
endif()
|
||||
# 1. Array-bounds testing is broken in some GCC versions before 4.8.5.
|
||||
# https://gcc.gnu.org/bugzilla/show_bug.cgi?id=56273
|
||||
# 2. But _Pragma("...ignored") is broken (unresolved) in GCC 5+:
|
||||
# https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66099
|
||||
# So we must disable -Warray-bounds globally for GCC (for kbtree.h, #7083).
|
||||
check_c_compiler_flag(-Wno-array-bounds HAS_NO_ARRAY_BOUNDS_FLAG)
|
||||
if(HAS_NO_ARRAY_BOUNDS_FLAG)
|
||||
add_definitions(-Wno-array-bounds)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
@ -277,6 +286,8 @@ else()
|
||||
set(DEBUG 0)
|
||||
endif()
|
||||
|
||||
option(LOG_LIST_ACTIONS "Add list actions logging" OFF)
|
||||
|
||||
add_definitions(-DINCLUDE_GENERATED_DECLARATIONS)
|
||||
|
||||
if(CMAKE_COMPILER_IS_GNUCXX AND CMAKE_SYSTEM_NAME STREQUAL "Linux")
|
||||
@ -505,17 +516,6 @@ if(BUSTED_PRG)
|
||||
get_property(TEST_INCLUDE_DIRS DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
|
||||
PROPERTY INCLUDE_DIRECTORIES)
|
||||
|
||||
# Set policy CMP0026 to OLD so we avoid CMake warnings on newer
|
||||
# versions of cmake.
|
||||
if(POLICY CMP0026)
|
||||
cmake_policy(SET CMP0026 OLD)
|
||||
endif()
|
||||
if(CMAKE_GENERATOR MATCHES "Visual Studio")
|
||||
set(TEST_LIBNVIM_PATH ${CMAKE_BINARY_DIR}/lib/nvim-test.dll)
|
||||
else()
|
||||
get_target_property(TEST_LIBNVIM_PATH nvim-test LOCATION)
|
||||
endif()
|
||||
|
||||
# When running tests from 'ninja' we need to use the
|
||||
# console pool: to do so we need to use the USES_TERMINAL
|
||||
# option, but this is only available in CMake 3.2
|
||||
@ -524,10 +524,6 @@ if(BUSTED_PRG)
|
||||
list(APPEND TEST_TARGET_ARGS "USES_TERMINAL")
|
||||
endif()
|
||||
|
||||
configure_file(
|
||||
test/config/paths.lua.in
|
||||
${CMAKE_BINARY_DIR}/test/config/paths.lua)
|
||||
|
||||
set(UNITTEST_PREREQS nvim-test unittest-headers)
|
||||
set(FUNCTIONALTEST_PREREQS nvim printargs-test shell-test)
|
||||
if(NOT WIN32)
|
||||
@ -564,6 +560,32 @@ if(BUSTED_PRG)
|
||||
message(WARNING "disabling unit tests: no Luajit FFI in ${LUA_PRG}")
|
||||
endif()
|
||||
|
||||
if(${CMAKE_VERSION} VERSION_LESS 2.8.12)
|
||||
if(CMAKE_GENERATOR MATCHES "Visual Studio")
|
||||
set(TEST_LIBNVIM_PATH ${CMAKE_BINARY_DIR}/lib/nvim-test.dll)
|
||||
else()
|
||||
get_target_property(TEST_LIBNVIM_PATH nvim-test LOCATION)
|
||||
endif()
|
||||
configure_file(
|
||||
${CMAKE_SOURCE_DIR}/test/config/paths.lua.in
|
||||
${CMAKE_BINARY_DIR}/test/config/paths.lua)
|
||||
else()
|
||||
# To avoid duplicating paths.lua.in while we still support CMake < 2.8.12,
|
||||
# use configure_file() to add the generator expression and then generate
|
||||
# the final file
|
||||
if(LUA_HAS_FFI)
|
||||
set(TEST_LIBNVIM_PATH $<TARGET_FILE:nvim-test>)
|
||||
else()
|
||||
set(TEST_LIBNVIM_PATH "")
|
||||
endif()
|
||||
configure_file(
|
||||
${CMAKE_SOURCE_DIR}/test/config/paths.lua.in
|
||||
${CMAKE_BINARY_DIR}/test/config/paths.lua.gen)
|
||||
file(GENERATE
|
||||
OUTPUT ${CMAKE_BINARY_DIR}/test/config/paths.lua
|
||||
INPUT ${CMAKE_BINARY_DIR}/test/config/paths.lua.gen)
|
||||
endif()
|
||||
|
||||
add_custom_target(functionaltest
|
||||
COMMAND ${CMAKE_COMMAND}
|
||||
-DBUSTED_PRG=${BUSTED_PRG}
|
||||
|
@ -14,7 +14,7 @@ low-risk/isolated tasks:
|
||||
Developer guidelines
|
||||
--------------------
|
||||
|
||||
- Nvim developers should read `:help dev-help`.
|
||||
- Nvim developers should read `:help dev`.
|
||||
- External UI developers should read `:help dev-ui`.
|
||||
|
||||
Reporting problems
|
||||
@ -24,7 +24,7 @@ Reporting problems
|
||||
- Search [existing issues][github-issues] (including closed!)
|
||||
- Update Neovim to the latest version to see if your problem persists.
|
||||
- Disable plugins incrementally, to narrow down the cause of the issue.
|
||||
- When reporting a crash, include a stacktrace.
|
||||
- When reporting a crash, [include a stacktrace](https://github.com/neovim/neovim/wiki/Development-tips#backtrace-linux).
|
||||
- [Bisect][git-bisect] to the cause of a regression, if you are able. This is _extremely_ helpful.
|
||||
- Check `$NVIM_LOG_FILE`, if it exists.
|
||||
- Include `cmake --system-information` for **build** issues.
|
||||
@ -92,7 +92,7 @@ and [AppVeyor].
|
||||
- CI builds are compiled with [`-Werror`][gcc-warnings], so compiler warnings
|
||||
will fail the build.
|
||||
- If any tests fail, the build will fail.
|
||||
See [Building Neovim#running-tests][wiki-run-tests] to run tests locally.
|
||||
See [test/README.md#running-tests][run-tests] to run tests locally.
|
||||
Passing locally doesn't guarantee passing the CI build, because of the
|
||||
different compilers and platforms tested against.
|
||||
- CI runs [ASan] and other analyzers.
|
||||
@ -168,7 +168,7 @@ as context, use the `-W` argument as well.
|
||||
[hygiene]: http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html
|
||||
[style-guide]: http://neovim.io/develop/style-guide.xml
|
||||
[ASan]: http://clang.llvm.org/docs/AddressSanitizer.html
|
||||
[wiki-run-tests]: https://github.com/neovim/neovim/wiki/Building-Neovim#running-tests
|
||||
[run-tests]: https://github.com/neovim/neovim/blob/master/test/README.md#running-tests
|
||||
[wiki-faq]: https://github.com/neovim/neovim/wiki/FAQ
|
||||
[review-checklist]: https://github.com/neovim/neovim/wiki/Code-review-checklist
|
||||
[3174]: https://github.com/neovim/neovim/issues/3174
|
||||
|
27
Makefile
27
Makefile
@ -1,3 +1,4 @@
|
||||
THIS_DIR = $(shell pwd)
|
||||
filter-false = $(strip $(filter-out 0 off OFF false FALSE,$1))
|
||||
filter-true = $(strip $(filter-out 1 on ON true TRUE,$1))
|
||||
|
||||
@ -8,11 +9,14 @@ CMAKE_PRG ?= $(shell (command -v cmake3 || echo cmake))
|
||||
CMAKE_BUILD_TYPE ?= Debug
|
||||
|
||||
CMAKE_FLAGS := -DCMAKE_BUILD_TYPE=$(CMAKE_BUILD_TYPE)
|
||||
DOC_DOWNLOAD_URL_BASE := https://raw.githubusercontent.com/neovim/doc/gh-pages
|
||||
CLINT_ERRORS_FILE_PATH := /reports/clint/errors.json
|
||||
|
||||
BUILD_TYPE ?= $(shell (type ninja > /dev/null 2>&1 && echo "Ninja") || \
|
||||
echo "Unix Makefiles")
|
||||
DEPS_BUILD_DIR ?= .deps
|
||||
|
||||
ifneq (1,$(words [$(DEPS_BUILD_DIR)]))
|
||||
$(error DEPS_BUILD_DIR must not contain whitespace)
|
||||
endif
|
||||
|
||||
ifeq (,$(BUILD_TOOL))
|
||||
ifeq (Ninja,$(BUILD_TYPE))
|
||||
@ -48,7 +52,7 @@ endif
|
||||
|
||||
ifneq (,$(findstring functionaltest-lua,$(MAKECMDGOALS)))
|
||||
BUNDLED_LUA_CMAKE_FLAG := -DUSE_BUNDLED_LUA=ON
|
||||
$(shell [ -x .deps/usr/bin/lua ] || rm build/.ran-*)
|
||||
$(shell [ -x $(DEPS_BUILD_DIR)/usr/bin/lua ] || rm build/.ran-*)
|
||||
endif
|
||||
|
||||
# For use where we want to make sure only a single job is run. This does issue
|
||||
@ -68,20 +72,20 @@ cmake:
|
||||
$(MAKE) build/.ran-cmake
|
||||
|
||||
build/.ran-cmake: | deps
|
||||
cd build && $(CMAKE_PRG) -G '$(BUILD_TYPE)' $(CMAKE_FLAGS) $(CMAKE_EXTRA_FLAGS) ..
|
||||
cd build && $(CMAKE_PRG) -G '$(BUILD_TYPE)' $(CMAKE_FLAGS) $(CMAKE_EXTRA_FLAGS) $(THIS_DIR)
|
||||
touch $@
|
||||
|
||||
deps: | build/.ran-third-party-cmake
|
||||
ifeq ($(call filter-true,$(USE_BUNDLED_DEPS)),)
|
||||
+$(BUILD_CMD) -C .deps
|
||||
+$(BUILD_CMD) -C $(DEPS_BUILD_DIR)
|
||||
endif
|
||||
|
||||
build/.ran-third-party-cmake:
|
||||
ifeq ($(call filter-true,$(USE_BUNDLED_DEPS)),)
|
||||
mkdir -p .deps
|
||||
cd .deps && \
|
||||
mkdir -p $(DEPS_BUILD_DIR)
|
||||
cd $(DEPS_BUILD_DIR) && \
|
||||
$(CMAKE_PRG) -G '$(BUILD_TYPE)' $(BUNDLED_CMAKE_FLAG) $(BUNDLED_LUA_CMAKE_FLAG) \
|
||||
$(DEPS_CMAKE_FLAGS) ../third-party
|
||||
$(DEPS_CMAKE_FLAGS) $(THIS_DIR)/third-party
|
||||
endif
|
||||
mkdir -p build
|
||||
touch $@
|
||||
@ -124,7 +128,7 @@ clean:
|
||||
$(MAKE) -C runtime/doc clean
|
||||
|
||||
distclean: clean
|
||||
rm -rf .deps build
|
||||
rm -rf $(DEPS_BUILD_DIR) build
|
||||
|
||||
install: | nvim
|
||||
+$(BUILD_CMD) -C build install
|
||||
@ -141,6 +145,11 @@ check-single-includes: build/.ran-cmake
|
||||
appimage:
|
||||
bash scripts/genappimage.sh
|
||||
|
||||
# Build an appimage with embedded update information appimage-nightly for
|
||||
# nightly builds or appimage-latest for a release
|
||||
appimage-%:
|
||||
bash scripts/genappimage.sh $*
|
||||
|
||||
lint: check-single-includes clint testlint lualint
|
||||
|
||||
.PHONY: test testlint lualint functionaltest unittest lint clint clean distclean nvim libnvim cmake deps install appimage
|
||||
|
@ -14,7 +14,7 @@
|
||||
[](https://neovim.io/doc/reports/pvs)
|
||||
|
||||
[](https://buildd.debian.org/neovim)
|
||||
[](https://github.com/neovim/neovim/releases/)
|
||||
[](https://github.com/neovim/neovim/releases/)
|
||||
|
||||
Neovim is a project that seeks to aggressively refactor Vim in order to:
|
||||
|
||||
@ -34,11 +34,15 @@ Install from source
|
||||
make CMAKE_BUILD_TYPE=RelWithDebInfo
|
||||
sudo make install
|
||||
|
||||
To install to a non-default location, specify `CMAKE_INSTALL_PREFIX`:
|
||||
To install to a non-default location, set `CMAKE_INSTALL_PREFIX`:
|
||||
|
||||
make CMAKE_EXTRA_FLAGS="-DCMAKE_INSTALL_PREFIX=/full/path/"
|
||||
make install
|
||||
|
||||
To list all targets:
|
||||
|
||||
cmake --build build --target help
|
||||
|
||||
See [the wiki](https://github.com/neovim/neovim/wiki/Building-Neovim) for details.
|
||||
|
||||
Install from package
|
||||
|
@ -1,7 +1,10 @@
|
||||
version: '{build}'
|
||||
environment:
|
||||
APPVEYOR_CACHE_ENTRY_ZIP_ARGS: "-t7z -m0=lzma -mx=9"
|
||||
image: Visual Studio 2017
|
||||
configuration:
|
||||
- MSVC_64
|
||||
- MSVC_32
|
||||
- MINGW_64
|
||||
- MINGW_32
|
||||
- MINGW_64-gcov
|
||||
@ -9,10 +12,12 @@ matrix:
|
||||
allow_failures:
|
||||
- configuration: MINGW_64-gcov
|
||||
install: []
|
||||
before_build:
|
||||
- ps: Install-Product node 8
|
||||
build_script:
|
||||
- call ci\build.bat
|
||||
- powershell ci\build.ps1
|
||||
cache:
|
||||
- C:\msys64\var\cache\pacman\pkg -> ci\build.bat
|
||||
- C:\msys64\var\cache\pacman\pkg -> ci\build.ps1
|
||||
- .deps -> third-party\**
|
||||
artifacts:
|
||||
- path: build/Neovim.zip
|
||||
|
@ -1,9 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -e
|
||||
set -o pipefail
|
||||
|
||||
if [[ -n "${GCOV}" ]]; then
|
||||
coveralls --gcov "$(which "${GCOV}")" --encoding iso-8859-1 || echo 'coveralls upload failed.'
|
||||
bash <(curl -s https://codecov.io/bash) || echo 'codecov upload failed.'
|
||||
fi
|
@ -4,16 +4,24 @@ 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"
|
||||
|
||||
# Don't cache pip's log and selfcheck.
|
||||
rm -rf "${HOME}/.cache/pip/log"
|
||||
rm -f "${HOME}/.cache/pip/selfcheck.json"
|
||||
|
||||
echo "before_cache.sh: cache size"
|
||||
du -d 2 "${HOME}/.cache" | sort -n
|
||||
|
||||
# Update the third-party dependency cache only if the build was successful.
|
||||
if ended_successfully; then
|
||||
rm -rf "${HOME}/.cache/nvim-deps"
|
||||
mv "${DEPS_BUILD_DIR}" "${HOME}/.cache/nvim-deps"
|
||||
|
||||
rm -rf "${HOME}/.cache/nvim-deps-downloads"
|
||||
mv "${DEPS_DOWNLOAD_DIR}" "${HOME}/.cache/nvim-deps-downloads"
|
||||
|
||||
touch "${CACHE_MARKER}"
|
||||
echo "Updated third-party dependencies (timestamp: $(stat -c '%y' "${CACHE_MARKER}"))."
|
||||
echo "Updated third-party dependencies (timestamp: $(_stat "${CACHE_MARKER}"))."
|
||||
fi
|
||||
|
@ -23,17 +23,26 @@ echo 'python info:'
|
||||
2>&1 pyenv versions || true
|
||||
) | sed 's/^/ /'
|
||||
|
||||
echo "Upgrade Python 2 pip."
|
||||
pip2.7 -q install --user --upgrade pip
|
||||
|
||||
if [[ "${TRAVIS_OS_NAME}" == osx ]]; then
|
||||
echo "Install Python 3."
|
||||
brew install python3
|
||||
echo "Upgrade Python 3."
|
||||
brew upgrade python
|
||||
echo "Upgrade Python 3 pip."
|
||||
pip3 -q install --user --upgrade pip
|
||||
else
|
||||
echo "Upgrade Python 2 pip."
|
||||
pip2.7 -q install --user --upgrade pip
|
||||
echo "Upgrade Python 3 pip."
|
||||
# Allow failure. pyenv pip3 on travis is broken:
|
||||
# https://github.com/travis-ci/travis-ci/issues/8363
|
||||
pip3 -q install --user --upgrade pip || true
|
||||
fi
|
||||
|
||||
echo "Install node (LTS)"
|
||||
|
||||
if [[ "${TRAVIS_OS_NAME}" == osx ]] || [ ! -f ~/.nvm/nvm.sh ]; then
|
||||
curl -o ~/.nvm/nvm.sh https://raw.githubusercontent.com/creationix/nvm/master/nvm.sh
|
||||
fi
|
||||
|
||||
source ~/.nvm/nvm.sh
|
||||
nvm install --lts
|
||||
nvm use --lts
|
||||
|
62
ci/build.bat
62
ci/build.bat
@ -1,62 +0,0 @@
|
||||
:: These are native MinGW builds, but they use the toolchain inside
|
||||
:: MSYS2, this allows using all the dependencies and tools available
|
||||
:: in MSYS2, but we cannot build inside the MSYS2 shell.
|
||||
echo on
|
||||
if "%CONFIGURATION%" == "MINGW_32" (
|
||||
set ARCH=i686
|
||||
set BITS=32
|
||||
) else (
|
||||
set ARCH=x86_64
|
||||
set BITS=64
|
||||
)
|
||||
if "%CONFIGURATION%" == "MINGW_64-gcov" (
|
||||
set USE_GCOV="-DUSE_GCOV=ON"
|
||||
)
|
||||
|
||||
:: We cannot have sh.exe in the PATH (MinGW)
|
||||
set PATH=%PATH:C:\Program Files\Git\usr\bin;=%
|
||||
set PATH=C:\msys64\mingw%BITS%\bin;C:\Windows\System32;C:\Windows;%PATH%
|
||||
:: The default cpack in the PATH is not CMake
|
||||
set PATH=C:\Program Files (x86)\CMake\bin\cpack.exe;%PATH%
|
||||
|
||||
:: Build third-party dependencies
|
||||
C:\msys64\usr\bin\bash -lc "pacman --verbose --noconfirm -Su" || goto :error
|
||||
C:\msys64\usr\bin\bash -lc "pacman --verbose --noconfirm --needed -S mingw-w64-%ARCH%-cmake mingw-w64-%ARCH%-perl mingw-w64-%ARCH%-diffutils mingw-w64-%ARCH%-unibilium gperf" || goto :error
|
||||
|
||||
:: Setup python (use AppVeyor system python)
|
||||
C:\Python27\python.exe -m pip install neovim || goto :error
|
||||
C:\Python35\python.exe -m pip install neovim || goto :error
|
||||
:: Disambiguate python3
|
||||
move c:\Python35\python.exe c:\Python35\python3.exe
|
||||
set PATH=C:\Python35;C:\Python27;%PATH%
|
||||
:: Sanity check
|
||||
python -c "import neovim; print(str(neovim))" || goto :error
|
||||
python3 -c "import neovim; print(str(neovim))" || goto :error
|
||||
|
||||
mkdir .deps
|
||||
cd .deps
|
||||
cmake -G "MinGW Makefiles" -DCMAKE_BUILD_TYPE=RelWithDebInfo ..\third-party\ || goto :error
|
||||
mingw32-make VERBOSE=1 || goto :error
|
||||
cd ..
|
||||
|
||||
:: Build Neovim
|
||||
mkdir build
|
||||
cd build
|
||||
cmake -G "MinGW Makefiles" -DCMAKE_BUILD_TYPE=RelWithDebInfo -DBUSTED_OUTPUT_TYPE=nvim %USE_GCOV% -DGPERF_PRG="C:\msys64\usr\bin\gperf.exe" .. || goto :error
|
||||
mingw32-make VERBOSE=1 || goto :error
|
||||
bin\nvim --version || goto :error
|
||||
|
||||
:: Functional tests
|
||||
mingw32-make functionaltest VERBOSE=1 || goto :error
|
||||
|
||||
if defined USE_GCOV (
|
||||
C:\msys64\usr\bin\bash -lc "cd /c/projects/neovim; bash <(curl -s https://codecov.io/bash) || echo 'codecov upload failed.'"
|
||||
)
|
||||
|
||||
:: Build artifacts
|
||||
cpack -G ZIP -C RelWithDebInfo
|
||||
if defined APPVEYOR_REPO_TAG_NAME cpack -G NSIS -C RelWithDebInfo
|
||||
|
||||
goto :EOF
|
||||
:error
|
||||
exit /b %errorlevel%
|
128
ci/build.ps1
Normal file
128
ci/build.ps1
Normal file
@ -0,0 +1,128 @@
|
||||
Set-PSDebug -Trace 1
|
||||
|
||||
$env:CONFIGURATION -match '^(?<compiler>\w+)_(?<bits>32|64)(?:-(?<option>\w+))?$'
|
||||
$compiler = $Matches.compiler
|
||||
$compileOption = $Matches.option
|
||||
$bits = $Matches.bits
|
||||
$cmakeBuildType = 'RelWithDebInfo'
|
||||
$depsCmakeVars = @{
|
||||
CMAKE_BUILD_TYPE = $cmakeBuildType;
|
||||
}
|
||||
$nvimCmakeVars = @{
|
||||
CMAKE_BUILD_TYPE = $cmakeBuildType;
|
||||
BUSTED_OUTPUT_TYPE = 'nvim';
|
||||
}
|
||||
|
||||
# For pull requests, skip some build configurations to save time.
|
||||
if ($env:APPVEYOR_PULL_REQUEST_HEAD_COMMIT -and $env:CONFIGURATION -match '^(MSVC_64|MINGW_32)$') {
|
||||
exit 0
|
||||
}
|
||||
|
||||
function exitIfFailed() {
|
||||
if ($LastExitCode -ne 0) {
|
||||
exit $LastExitCode
|
||||
}
|
||||
}
|
||||
|
||||
if ($compiler -eq 'MINGW') {
|
||||
if ($bits -eq 32) {
|
||||
$arch = 'i686'
|
||||
}
|
||||
elseif ($bits -eq 64) {
|
||||
$arch = 'x86_64'
|
||||
}
|
||||
if ($compileOption -eq 'gcov') {
|
||||
$nvimCmakeVars['USE_GCOV'] = 'ON'
|
||||
$uploadToCodecov = $true
|
||||
}
|
||||
# These are native MinGW builds, but they use the toolchain inside
|
||||
# MSYS2, this allows using all the dependencies and tools available
|
||||
# in MSYS2, but we cannot build inside the MSYS2 shell.
|
||||
$cmakeGenerator = 'MinGW Makefiles'
|
||||
$cmakeGeneratorArgs = 'VERBOSE=1'
|
||||
|
||||
# Add MinGW to the PATH
|
||||
$env:PATH = "C:\msys64\mingw$bits\bin;$env:PATH"
|
||||
|
||||
# Build third-party dependencies
|
||||
C:\msys64\usr\bin\bash -lc "pacman --verbose --noconfirm -Su" ; exitIfFailed
|
||||
C:\msys64\usr\bin\bash -lc "pacman --verbose --noconfirm --needed -S mingw-w64-$arch-cmake mingw-w64-$arch-perl mingw-w64-$arch-diffutils mingw-w64-$arch-unibilium" ; exitIfFailed
|
||||
}
|
||||
elseif ($compiler -eq 'MSVC') {
|
||||
$cmakeGeneratorArgs = '/verbosity:normal'
|
||||
if ($bits -eq 32) {
|
||||
$cmakeGenerator = 'Visual Studio 15 2017'
|
||||
}
|
||||
elseif ($bits -eq 64) {
|
||||
$cmakeGenerator = 'Visual Studio 15 2017 Win64'
|
||||
}
|
||||
}
|
||||
|
||||
# Remove Git Unix utilities from the PATH
|
||||
$env:PATH = $env:PATH.Replace('C:\Program Files\Git\usr\bin', '')
|
||||
|
||||
# Setup python (use AppVeyor system python)
|
||||
C:\Python27\python.exe -m pip install neovim ; exitIfFailed
|
||||
C:\Python35\python.exe -m pip install neovim ; exitIfFailed
|
||||
# Disambiguate python3
|
||||
move c:\Python35\python.exe c:\Python35\python3.exe
|
||||
$env:PATH = "C:\Python35;C:\Python27;$env:PATH"
|
||||
# Sanity check
|
||||
python -c "import neovim; print(str(neovim))" ; exitIfFailed
|
||||
python3 -c "import neovim; print(str(neovim))" ; exitIfFailed
|
||||
|
||||
$env:PATH = "C:\Ruby24\bin;$env:PATH"
|
||||
cmd /c gem.cmd install neovim ; exitIfFailed
|
||||
where.exe neovim-ruby-host.bat ; exitIfFailed
|
||||
|
||||
cmd /c npm.cmd install -g neovim ; exitIfFailed
|
||||
where.exe neovim-node-host.cmd ; exitIfFailed
|
||||
|
||||
function convertToCmakeArgs($vars) {
|
||||
return $vars.GetEnumerator() | foreach { "-D$($_.Key)=$($_.Value)" }
|
||||
}
|
||||
|
||||
mkdir .deps
|
||||
cd .deps
|
||||
cmake -G $cmakeGenerator $(convertToCmakeArgs($depsCmakeVars)) ..\third-party\ ; exitIfFailed
|
||||
cmake --build . --config $cmakeBuildType -- $cmakeGeneratorArgs ; exitIfFailed
|
||||
cd ..
|
||||
|
||||
# Build Neovim
|
||||
mkdir build
|
||||
cd build
|
||||
cmake -G $cmakeGenerator $(convertToCmakeArgs($nvimCmakeVars)) .. ; exitIfFailed
|
||||
cmake --build . --config $cmakeBuildType -- $cmakeGeneratorArgs ; exitIfFailed
|
||||
bin\nvim --version ; exitIfFailed
|
||||
|
||||
# Functional tests
|
||||
# The $LastExitCode from MSBuild can't be trusted
|
||||
$failed = $false
|
||||
# Temporarily turn off tracing to reduce log file output
|
||||
Set-PSDebug -Off
|
||||
cmake --build . --config $cmakeBuildType --target functionaltest -- $cmakeGeneratorArgs |
|
||||
foreach { $failed = $failed -or
|
||||
$_ -match 'Running functional tests failed with error'; $_ }
|
||||
Set-PSDebug -Trace 1
|
||||
if ($failed) {
|
||||
exit $LastExitCode
|
||||
}
|
||||
|
||||
|
||||
if ($uploadToCodecov) {
|
||||
C:\msys64\usr\bin\bash -lc "cd /c/projects/neovim; bash <(curl -s https://codecov.io/bash) -c -F functionaltest || echo 'codecov upload failed.'"
|
||||
}
|
||||
|
||||
# Old tests
|
||||
$env:PATH += ';C:\msys64\usr\bin'
|
||||
& "C:\msys64\mingw$bits\bin\mingw32-make.exe" -C $(Convert-Path ..\src\nvim\testdir) VERBOSE=1
|
||||
|
||||
if ($uploadToCodecov) {
|
||||
C:\msys64\usr\bin\bash -lc "cd /c/projects/neovim; bash <(curl -s https://codecov.io/bash) -c -F oldtest || echo 'codecov upload failed.'"
|
||||
}
|
||||
|
||||
# Build artifacts
|
||||
cpack -G ZIP -C RelWithDebInfo
|
||||
if ($env:APPVEYOR_REPO_TAG_NAME -ne $null) {
|
||||
cpack -G NSIS -C RelWithDebInfo
|
||||
}
|
@ -1,5 +1,16 @@
|
||||
_stat() {
|
||||
if test "${TRAVIS_OS_NAME}" = osx ; then
|
||||
stat -f %Sm "${@}"
|
||||
else
|
||||
stat -c %y "${@}"
|
||||
fi
|
||||
}
|
||||
|
||||
top_make() {
|
||||
${MAKE_CMD} "$@"
|
||||
echo '================================================================================'
|
||||
# Travis has 1.5 virtual cores according to:
|
||||
# http://docs.travis-ci.com/user/speeding-up-the-build/#Paralellizing-your-build-on-one-VM
|
||||
ninja "$@"
|
||||
}
|
||||
|
||||
build_make() {
|
||||
@ -15,28 +26,21 @@ build_deps() {
|
||||
DEPS_CMAKE_FLAGS="${DEPS_CMAKE_FLAGS} -DUSE_BUNDLED_LUA=ON"
|
||||
fi
|
||||
|
||||
rm -rf "${DEPS_BUILD_DIR}"
|
||||
mkdir -p "${DEPS_BUILD_DIR}"
|
||||
mkdir -p "${DEPS_DOWNLOAD_DIR}"
|
||||
|
||||
# If there is a valid cache and we're not forced to recompile,
|
||||
# use cached third-party dependencies.
|
||||
if test -f "${CACHE_MARKER}" && test "${BUILD_NVIM_DEPS}" != "true" ; then
|
||||
local statcmd="stat -c '%y'"
|
||||
if test "${TRAVIS_OS_NAME}" = osx ; then
|
||||
statcmd="stat -f '%Sm'"
|
||||
fi
|
||||
echo "Using third-party dependencies from Travis's cache (last updated: $(${statcmd} "${CACHE_MARKER}"))."
|
||||
|
||||
mkdir -p "$(dirname "${DEPS_BUILD_DIR}")"
|
||||
mv "${HOME}/.cache/nvim-deps" "${DEPS_BUILD_DIR}"
|
||||
else
|
||||
mkdir -p "${DEPS_BUILD_DIR}"
|
||||
# Use cached dependencies if $CACHE_MARKER exists.
|
||||
if test -f "${CACHE_MARKER}" && ! test "${CACHE_ENABLE}" = "false" ; then
|
||||
echo "Using third-party dependencies from Travis cache (last update: $(_stat "${CACHE_MARKER}"))."
|
||||
cp -r "${HOME}/.cache/nvim-deps" "${DEPS_BUILD_DIR}"
|
||||
cp -r "${HOME}/.cache/nvim-deps-downloads" "${DEPS_DOWNLOAD_DIR}"
|
||||
fi
|
||||
|
||||
# Even if we're using cached dependencies, run CMake and make to
|
||||
# update CMake configuration and update to newer deps versions.
|
||||
cd "${DEPS_BUILD_DIR}"
|
||||
echo "Configuring with '${DEPS_CMAKE_FLAGS}'."
|
||||
CC= cmake ${DEPS_CMAKE_FLAGS} "${TRAVIS_BUILD_DIR}/third-party/"
|
||||
CC= cmake -G Ninja ${DEPS_CMAKE_FLAGS} "${TRAVIS_BUILD_DIR}/third-party/"
|
||||
|
||||
if ! top_make; then
|
||||
exit 1
|
||||
@ -56,7 +60,7 @@ prepare_build() {
|
||||
mkdir -p "${BUILD_DIR}"
|
||||
cd "${BUILD_DIR}"
|
||||
echo "Configuring with '${CMAKE_FLAGS} $@'."
|
||||
cmake ${CMAKE_FLAGS} "$@" "${TRAVIS_BUILD_DIR}"
|
||||
cmake -G Ninja ${CMAKE_FLAGS} "$@" "${TRAVIS_BUILD_DIR}"
|
||||
}
|
||||
|
||||
build_nvim() {
|
||||
@ -71,9 +75,11 @@ build_nvim() {
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Building nvim-test."
|
||||
if ! top_make nvim-test ; then
|
||||
exit 1
|
||||
if test "${FUNCTIONALTEST}" != "functionaltest-lua"; then
|
||||
echo "Building nvim-test."
|
||||
if ! top_make nvim-test ; then
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
@ -87,3 +93,12 @@ build_nvim() {
|
||||
|
||||
cd "${TRAVIS_BUILD_DIR}"
|
||||
}
|
||||
|
||||
macos_rvm_dance() {
|
||||
# neovim-ruby gem requires a ruby newer than the macOS default.
|
||||
source ~/.rvm/scripts/rvm
|
||||
rvm get stable --auto-dotfiles
|
||||
rvm reload
|
||||
rvm use 2.2.5
|
||||
rvm use
|
||||
}
|
||||
|
@ -1,6 +1,15 @@
|
||||
. "${CI_DIR}/common/build.sh"
|
||||
. "${CI_DIR}/common/suite.sh"
|
||||
|
||||
submit_coverage() {
|
||||
if [ -n "${GCOV}" ]; then
|
||||
if curl --fail --output codecov.bash --silent https://codecov.io/bash; then
|
||||
bash codecov.bash -c -F "$1" || echo "codecov upload failed."
|
||||
rm -f codecov.bash
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
print_core() {
|
||||
local app="$1"
|
||||
local core="$2"
|
||||
@ -71,7 +80,9 @@ valgrind_check() {
|
||||
}
|
||||
|
||||
asan_check() {
|
||||
check_logs "${1}" "*san.*"
|
||||
if test "${CLANG_SANITIZER}" = "ASAN_UBSAN" ; then
|
||||
check_logs "${1}" "*san.*" | asan_symbolize
|
||||
fi
|
||||
}
|
||||
|
||||
run_unittests() {(
|
||||
@ -80,6 +91,7 @@ run_unittests() {(
|
||||
if ! build_make unittest ; then
|
||||
fail 'unittests' F 'Unit tests failed'
|
||||
fi
|
||||
submit_coverage unittest
|
||||
check_core_dumps "$(which luajit)"
|
||||
exit_suite
|
||||
)}
|
||||
@ -90,6 +102,7 @@ run_functionaltests() {(
|
||||
if ! build_make ${FUNCTIONALTEST}; then
|
||||
fail 'functionaltests' F 'Functional tests failed'
|
||||
fi
|
||||
submit_coverage functionaltest
|
||||
asan_check "${LOG_DIR}"
|
||||
valgrind_check "${LOG_DIR}"
|
||||
check_core_dumps
|
||||
@ -103,6 +116,7 @@ run_oldtests() {(
|
||||
reset
|
||||
fail 'oldtests' F 'Legacy tests failed'
|
||||
fi
|
||||
submit_coverage oldtest
|
||||
asan_check "${LOG_DIR}"
|
||||
valgrind_check "${LOG_DIR}"
|
||||
check_core_dumps
|
||||
|
@ -8,18 +8,26 @@ if [[ "${CI_TARGET}" == lint ]]; then
|
||||
fi
|
||||
|
||||
if [[ "${TRAVIS_OS_NAME}" == osx ]]; then
|
||||
brew install ninja
|
||||
brew install gettext
|
||||
brew reinstall -s libtool
|
||||
fi
|
||||
|
||||
# Use default CC to avoid compilation problems when installing Python modules.
|
||||
echo "Install neovim module and coveralls for Python 2."
|
||||
CC=cc pip2.7 -q install --user --upgrade neovim cpp-coveralls
|
||||
|
||||
echo "Install neovim module for Python 3."
|
||||
# Allow failure. pyenv pip3 on travis is broken:
|
||||
# https://github.com/travis-ci/travis-ci/issues/8363
|
||||
CC=cc pip3 -q install --user --upgrade neovim || true
|
||||
|
||||
echo "Install neovim RubyGem."
|
||||
gem install --no-document --version ">= 0.2.0" neovim
|
||||
if ! [ "${TRAVIS_OS_NAME}" = osx ] ; then
|
||||
# Update PATH for pip.
|
||||
export PATH="$(python2.7 -c 'import site; print(site.getuserbase())')/bin:$PATH"
|
||||
# Use default CC to avoid compilation problems when installing Python modules.
|
||||
echo "Install neovim module for Python 2."
|
||||
CC=cc pip2.7 -q install --user --upgrade neovim
|
||||
|
||||
echo "Install neovim RubyGem."
|
||||
gem install --no-document --version ">= 0.2.0" neovim
|
||||
fi
|
||||
|
||||
echo "Install neovim npm package"
|
||||
npm install -g neovim
|
||||
|
@ -10,19 +10,19 @@ source "${CI_DIR}/common/suite.sh"
|
||||
|
||||
enter_suite 'clint'
|
||||
|
||||
run_test 'top_make clint-full' clint
|
||||
run_test 'make clint-full' clint
|
||||
|
||||
exit_suite --continue
|
||||
|
||||
enter_suite 'testlint'
|
||||
|
||||
run_test 'top_make testlint' testlint
|
||||
run_test 'make testlint' testlint
|
||||
|
||||
exit_suite --continue
|
||||
|
||||
enter_suite 'lualint'
|
||||
|
||||
run_test 'top_make lualint' lualint
|
||||
run_test 'make lualint' lualint
|
||||
|
||||
exit_suite --continue
|
||||
|
||||
@ -31,7 +31,7 @@ enter_suite single-includes
|
||||
CLICOLOR_FORCE=1 run_test_wd \
|
||||
--allow-hang \
|
||||
10s \
|
||||
'top_make check-single-includes' \
|
||||
'make check-single-includes' \
|
||||
'csi_clean' \
|
||||
single-includes
|
||||
|
||||
|
@ -22,7 +22,9 @@ enter_suite tests
|
||||
if test "$CLANG_SANITIZER" != "TSAN" ; then
|
||||
# Additional threads are only created when the builtin UI starts, which
|
||||
# doesn't happen in the unit/functional tests
|
||||
run_test run_unittests
|
||||
if test "${FUNCTIONALTEST}" != "functionaltest-lua"; then
|
||||
run_test run_unittests
|
||||
fi
|
||||
run_test run_functionaltests
|
||||
fi
|
||||
run_test run_oldtests
|
||||
|
@ -27,7 +27,7 @@ find_path(LibIntl_INCLUDE_DIR
|
||||
)
|
||||
|
||||
find_library(LibIntl_LIBRARY
|
||||
NAMES intl libintl.a
|
||||
NAMES intl libintl
|
||||
)
|
||||
|
||||
if (LibIntl_INCLUDE_DIR)
|
||||
|
@ -44,7 +44,7 @@ endif()
|
||||
|
||||
if(MSVC)
|
||||
# The import library for the msgpack DLL has a different name
|
||||
list(APPEND MSGPACK_NAMES msgpack_import)
|
||||
list(APPEND MSGPACK_NAMES msgpackc_import)
|
||||
else()
|
||||
list(APPEND MSGPACK_NAMES msgpackc msgpack)
|
||||
endif()
|
||||
|
@ -38,6 +38,7 @@ function(get_compile_flags _compile_flags)
|
||||
get_directory_property(include_directories_list
|
||||
DIRECTORY "src/nvim"
|
||||
INCLUDE_DIRECTORIES)
|
||||
list(REMOVE_DUPLICATES include_directories_list)
|
||||
foreach(include_directory ${include_directories_list})
|
||||
set(include_directories "${include_directories} -I${include_directory}")
|
||||
endforeach()
|
||||
|
@ -4,9 +4,8 @@
|
||||
|
||||
# Check if a module is available in Lua
|
||||
function(check_lua_module LUA_PRG_PATH MODULE RESULT_VAR)
|
||||
execute_process(COMMAND ${LUA_PRG_PATH} -e "require('${MODULE}')"
|
||||
RESULT_VARIABLE module_missing
|
||||
ERROR_QUIET)
|
||||
execute_process(COMMAND ${LUA_PRG_PATH} -l "${MODULE}" -e ""
|
||||
RESULT_VARIABLE module_missing)
|
||||
if(module_missing)
|
||||
set(${RESULT_VAR} False PARENT_SCOPE)
|
||||
else()
|
||||
|
@ -38,7 +38,7 @@ set(ENV{SYSTEM_NAME} ${SYSTEM_NAME})
|
||||
execute_process(
|
||||
COMMAND ${BUSTED_PRG} ${TEST_TAG} ${TEST_FILTER} -v -o ${BUSTED_OUTPUT_TYPE}
|
||||
--lua=${LUA_PRG} --lazy --helper=${TEST_DIR}/${TEST_TYPE}/preload.lua
|
||||
--lpath=${BUILD_DIR}/?.lua ${TEST_PATH}
|
||||
--lpath=${BUILD_DIR}/?.lua --lpath=?.lua ${TEST_PATH}
|
||||
WORKING_DIRECTORY ${WORKING_DIR}
|
||||
ERROR_VARIABLE err
|
||||
RESULT_VARIABLE res
|
||||
|
@ -1,6 +1,6 @@
|
||||
codecov:
|
||||
notify:
|
||||
require_ci_to_pass: yes
|
||||
require_ci_to_pass: no
|
||||
ci:
|
||||
- appveyor
|
||||
- travis
|
||||
|
@ -12,6 +12,11 @@ check_type_size("size_t" SIZEOF_SIZE_T)
|
||||
check_type_size("long long" SIZEOF_LONG_LONG)
|
||||
check_type_size("void *" SIZEOF_VOID_PTR)
|
||||
|
||||
if (CMAKE_HOST_SYSTEM_VERSION MATCHES ".*-Microsoft")
|
||||
# Windows Subsystem for Linux
|
||||
set(HAVE_WSL 1)
|
||||
endif()
|
||||
|
||||
check_symbol_exists(_NSGetEnviron crt_externs.h HAVE__NSGETENVIRON)
|
||||
|
||||
# Headers
|
||||
|
@ -48,6 +48,7 @@
|
||||
#cmakedefine HAVE_UTIME_H
|
||||
#cmakedefine HAVE_UTIMES
|
||||
#cmakedefine HAVE_WORKING_LIBINTL
|
||||
#cmakedefine HAVE_WSL
|
||||
#cmakedefine UNIX
|
||||
#cmakedefine USE_FNAME_CASE
|
||||
#cmakedefine HAVE_SYS_UIO_H
|
||||
@ -62,6 +63,7 @@
|
||||
|
||||
#ifndef UNIT_TESTING
|
||||
#cmakedefine HAVE_JEMALLOC
|
||||
#cmakedefine LOG_LIST_ACTIONS
|
||||
#endif
|
||||
|
||||
#cmakedefine HAVE_BE64TOH
|
||||
|
39
man/nvim.1
39
man/nvim.1
@ -25,7 +25,7 @@ To enter commands in
|
||||
type a colon
|
||||
.Pq Sq \&:
|
||||
which is also used in this manual to denote commands.
|
||||
For more information, consult the on-line help system with the
|
||||
For more information, consult the online help system with the
|
||||
.Ic :help
|
||||
command.
|
||||
.Bl -tag -width Fl
|
||||
@ -329,6 +329,8 @@ Implies
|
||||
.Fl -headless .
|
||||
.It Fl -headless
|
||||
Do not start a user interface.
|
||||
.It Fl -listen Ar address
|
||||
Start RPC server on this pipe or TCP socket.
|
||||
.It Fl h , -help
|
||||
Print usage information and exit.
|
||||
.It Fl v , -version
|
||||
@ -337,12 +339,12 @@ Print version information and exit.
|
||||
.Sh ENVIRONMENT
|
||||
.Bl -tag -width Fl
|
||||
.It Ev VIM
|
||||
Used to locate various user files, such as the user's init.vim.
|
||||
Used to locate various user files, such as init.vim.
|
||||
.It Ev VIMRUNTIME
|
||||
Used to locate run time files, such as on-line documentation and
|
||||
Used to locate runtime files, such as online documentation and
|
||||
syntax highlighting definitions.
|
||||
.It Ev XDG_CONFIG_HOME
|
||||
Path to use for the user-local configuration directory, see
|
||||
Path to the user-local configuration directory, see
|
||||
.Sx FILES .
|
||||
Defaults to
|
||||
.Pa ~/.config
|
||||
@ -356,7 +358,7 @@ Defaults to
|
||||
.Pa ~/.local/share
|
||||
if not set.
|
||||
.It Ev VIMINIT
|
||||
A string of Ex commands to be executed at startup.
|
||||
Ex commands to be executed at startup.
|
||||
For example, the command to quit is
|
||||
.Ic :q ,
|
||||
so to have
|
||||
@ -375,41 +377,32 @@ command.
|
||||
.Sh FILES
|
||||
.Bl -tag -width "~/.config/nvim/init.vim"
|
||||
.It Pa ~/.config/nvim/init.vim
|
||||
The user-local
|
||||
User-local
|
||||
.Nm
|
||||
configuration file.
|
||||
See
|
||||
.Ev XDG_CONFIG_HOME
|
||||
above.
|
||||
.It Pa ~/.config/nvim
|
||||
The user-local
|
||||
User-local
|
||||
.Nm
|
||||
configuration directory.
|
||||
See
|
||||
.Ev XDG_CONFIG_HOME
|
||||
above.
|
||||
See also
|
||||
.Ev XDG_CONFIG_HOME .
|
||||
.It Pa $VIM/sysinit.vim
|
||||
The system-global
|
||||
System-global
|
||||
.Nm
|
||||
configuration file.
|
||||
.It Pa /usr/local/share/nvim
|
||||
The system-global
|
||||
System-global
|
||||
.Nm
|
||||
runtime directory.
|
||||
.El
|
||||
.Sh AUTHORS
|
||||
.Nm
|
||||
was started by
|
||||
.An Thiago de Arruda ,
|
||||
with a lot of help from others.
|
||||
.Pp
|
||||
Nvim was started by
|
||||
.An Thiago de Arruda .
|
||||
Most of Vim was written by
|
||||
.An -nosplit
|
||||
.An Bram Moolenaar ,
|
||||
with a lot of help from others.
|
||||
.An Bram Moolenaar .
|
||||
See
|
||||
.Ic :help credits .
|
||||
.Pp
|
||||
Vim is based on Stevie, worked on by
|
||||
.An Tim Thompson ,
|
||||
.An Tony Andrews ,
|
||||
|
@ -42,6 +42,7 @@ foreach(PACKAGE ${PACKAGES})
|
||||
nvim
|
||||
WORKING_DIRECTORY "${GENERATED_PACKAGE_DIR}/${PACKNAME}"
|
||||
)
|
||||
add_dependencies(${PACKNAME}-tags nvim_runtime_deps)
|
||||
|
||||
add_custom_command(OUTPUT "${GENERATED_PACKAGE_DIR}/${PACKNAME}/doc/tags"
|
||||
DEPENDS
|
||||
@ -71,7 +72,7 @@ foreach(DF ${DOCFILES})
|
||||
endforeach()
|
||||
|
||||
add_custom_target(helptags
|
||||
COMMAND ${CMAKE_COMMAND} -E remove_directory ${GENERATED_RUNTIME_DIR}/doc
|
||||
COMMAND ${CMAKE_COMMAND} -E remove ${GENERATED_RUNTIME_DIR}/doc/*
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_directory
|
||||
${PROJECT_SOURCE_DIR}/runtime/doc ${GENERATED_RUNTIME_DIR}/doc
|
||||
COMMAND "${PROJECT_BINARY_DIR}/bin/nvim"
|
||||
@ -80,6 +81,7 @@ add_custom_target(helptags
|
||||
nvim
|
||||
WORKING_DIRECTORY "${GENERATED_RUNTIME_DIR}"
|
||||
)
|
||||
add_dependencies(helptags nvim_runtime_deps)
|
||||
|
||||
add_custom_command(OUTPUT ${GENERATED_HELP_TAGS}
|
||||
DEPENDS
|
||||
@ -138,7 +140,7 @@ endforeach()
|
||||
file(GLOB_RECURSE RUNTIME_FILES
|
||||
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
|
||||
rgb.txt
|
||||
*.vim *.dict *.py *.rb *.ps *.tutor)
|
||||
*.vim *.lua *.dict *.py *.rb *.ps *.spl *.tutor *.tutor.json)
|
||||
|
||||
foreach(F ${RUNTIME_FILES})
|
||||
get_filename_component(BASEDIR ${F} PATH)
|
||||
|
741
runtime/autoload/dist/ft.vim
vendored
Normal file
741
runtime/autoload/dist/ft.vim
vendored
Normal file
@ -0,0 +1,741 @@
|
||||
" Vim functions for file type detection
|
||||
"
|
||||
" Maintainer: Bram Moolenaar <Bram@vim.org>
|
||||
" Last Change: 2017 Nov 11
|
||||
|
||||
" These functions are moved here from runtime/filetype.vim to make startup
|
||||
" faster.
|
||||
|
||||
" Line continuation is used here, remove 'C' from 'cpoptions'
|
||||
let s:cpo_save = &cpo
|
||||
set cpo&vim
|
||||
|
||||
func dist#ft#Check_inp()
|
||||
if getline(1) =~ '^\*'
|
||||
setf abaqus
|
||||
else
|
||||
let n = 1
|
||||
if line("$") > 500
|
||||
let nmax = 500
|
||||
else
|
||||
let nmax = line("$")
|
||||
endif
|
||||
while n <= nmax
|
||||
if getline(n) =~? "^header surface data"
|
||||
setf trasys
|
||||
break
|
||||
endif
|
||||
let n = n + 1
|
||||
endwhile
|
||||
endif
|
||||
endfunc
|
||||
|
||||
" This function checks for the kind of assembly that is wanted by the user, or
|
||||
" can be detected from the first five lines of the file.
|
||||
func dist#ft#FTasm()
|
||||
" make sure b:asmsyntax exists
|
||||
if !exists("b:asmsyntax")
|
||||
let b:asmsyntax = ""
|
||||
endif
|
||||
|
||||
if b:asmsyntax == ""
|
||||
call dist#ft#FTasmsyntax()
|
||||
endif
|
||||
|
||||
" if b:asmsyntax still isn't set, default to asmsyntax or GNU
|
||||
if b:asmsyntax == ""
|
||||
if exists("g:asmsyntax")
|
||||
let b:asmsyntax = g:asmsyntax
|
||||
else
|
||||
let b:asmsyntax = "asm"
|
||||
endif
|
||||
endif
|
||||
|
||||
exe "setf " . fnameescape(b:asmsyntax)
|
||||
endfunc
|
||||
|
||||
func dist#ft#FTasmsyntax()
|
||||
" see if file contains any asmsyntax=foo overrides. If so, change
|
||||
" b:asmsyntax appropriately
|
||||
let head = " ".getline(1)." ".getline(2)." ".getline(3)." ".getline(4).
|
||||
\" ".getline(5)." "
|
||||
let match = matchstr(head, '\sasmsyntax=\zs[a-zA-Z0-9]\+\ze\s')
|
||||
if match != ''
|
||||
let b:asmsyntax = match
|
||||
elseif ((head =~? '\.title') || (head =~? '\.ident') || (head =~? '\.macro') || (head =~? '\.subtitle') || (head =~? '\.library'))
|
||||
let b:asmsyntax = "vmasm"
|
||||
endif
|
||||
endfunc
|
||||
|
||||
" Check if one of the first five lines contains "VB_Name". In that case it is
|
||||
" probably a Visual Basic file. Otherwise it's assumed to be "alt" filetype.
|
||||
func dist#ft#FTVB(alt)
|
||||
if getline(1).getline(2).getline(3).getline(4).getline(5) =~? 'VB_Name\|Begin VB\.\(Form\|MDIForm\|UserControl\)'
|
||||
setf vb
|
||||
else
|
||||
exe "setf " . a:alt
|
||||
endif
|
||||
endfunc
|
||||
|
||||
func dist#ft#FTbtm()
|
||||
if exists("g:dosbatch_syntax_for_btm") && g:dosbatch_syntax_for_btm
|
||||
setf dosbatch
|
||||
else
|
||||
setf btm
|
||||
endif
|
||||
endfunc
|
||||
|
||||
func dist#ft#BindzoneCheck(default)
|
||||
if getline(1).getline(2).getline(3).getline(4) =~ '^; <<>> DiG [0-9.]\+.* <<>>\|$ORIGIN\|$TTL\|IN\s\+SOA'
|
||||
setf bindzone
|
||||
elseif a:default != ''
|
||||
exe 'setf ' . a:default
|
||||
endif
|
||||
endfunc
|
||||
|
||||
func dist#ft#FTlpc()
|
||||
if exists("g:lpc_syntax_for_c")
|
||||
let lnum = 1
|
||||
while lnum <= 12
|
||||
if getline(lnum) =~# '^\(//\|inherit\|private\|protected\|nosave\|string\|object\|mapping\|mixed\)'
|
||||
setf lpc
|
||||
return
|
||||
endif
|
||||
let lnum = lnum + 1
|
||||
endwhile
|
||||
endif
|
||||
setf c
|
||||
endfunc
|
||||
|
||||
func dist#ft#FTheader()
|
||||
if match(getline(1, min([line("$"), 200])), '^@\(interface\|end\|class\)') > -1
|
||||
if exists("g:c_syntax_for_h")
|
||||
setf objc
|
||||
else
|
||||
setf objcpp
|
||||
endif
|
||||
elseif exists("g:c_syntax_for_h")
|
||||
setf c
|
||||
elseif exists("g:ch_syntax_for_h")
|
||||
setf ch
|
||||
else
|
||||
setf cpp
|
||||
endif
|
||||
endfunc
|
||||
|
||||
" This function checks if one of the first ten lines start with a '@'. In
|
||||
" that case it is probably a change file.
|
||||
" If the first line starts with # or ! it's probably a ch file.
|
||||
" If a line has "main", "include", "//" ir "/*" it's probably ch.
|
||||
" Otherwise CHILL is assumed.
|
||||
func dist#ft#FTchange()
|
||||
let lnum = 1
|
||||
while lnum <= 10
|
||||
if getline(lnum)[0] == '@'
|
||||
setf change
|
||||
return
|
||||
endif
|
||||
if lnum == 1 && (getline(1)[0] == '#' || getline(1)[0] == '!')
|
||||
setf ch
|
||||
return
|
||||
endif
|
||||
if getline(lnum) =~ "MODULE"
|
||||
setf chill
|
||||
return
|
||||
endif
|
||||
if getline(lnum) =~ 'main\s*(\|#\s*include\|//'
|
||||
setf ch
|
||||
return
|
||||
endif
|
||||
let lnum = lnum + 1
|
||||
endwhile
|
||||
setf chill
|
||||
endfunc
|
||||
|
||||
func dist#ft#FTent()
|
||||
" This function checks for valid cl syntax in the first five lines.
|
||||
" Look for either an opening comment, '#', or a block start, '{".
|
||||
" If not found, assume SGML.
|
||||
let lnum = 1
|
||||
while lnum < 6
|
||||
let line = getline(lnum)
|
||||
if line =~ '^\s*[#{]'
|
||||
setf cl
|
||||
return
|
||||
elseif line !~ '^\s*$'
|
||||
" Not a blank line, not a comment, and not a block start,
|
||||
" so doesn't look like valid cl code.
|
||||
break
|
||||
endif
|
||||
let lnum = lnum + 1
|
||||
endw
|
||||
setf dtd
|
||||
endfunc
|
||||
|
||||
func dist#ft#EuphoriaCheck()
|
||||
if exists('g:filetype_euphoria')
|
||||
exe 'setf ' . g:filetype_euphoria
|
||||
else
|
||||
setf euphoria3
|
||||
endif
|
||||
endfunc
|
||||
|
||||
func dist#ft#DtraceCheck()
|
||||
let lines = getline(1, min([line("$"), 100]))
|
||||
if match(lines, '^module\>\|^import\>') > -1
|
||||
" D files often start with a module and/or import statement.
|
||||
setf d
|
||||
elseif match(lines, '^#!\S\+dtrace\|#pragma\s\+D\s\+option\|:\S\{-}:\S\{-}:') > -1
|
||||
setf dtrace
|
||||
else
|
||||
setf d
|
||||
endif
|
||||
endfunc
|
||||
|
||||
func dist#ft#FTe()
|
||||
if exists('g:filetype_euphoria')
|
||||
exe 'setf ' . g:filetype_euphoria
|
||||
else
|
||||
let n = 1
|
||||
while n < 100 && n < line("$")
|
||||
if getline(n) =~ "^\\s*\\(<'\\|'>\\)\\s*$"
|
||||
setf specman
|
||||
return
|
||||
endif
|
||||
let n = n + 1
|
||||
endwhile
|
||||
setf eiffel
|
||||
endif
|
||||
endfunc
|
||||
|
||||
" Distinguish between HTML, XHTML and Django
|
||||
func dist#ft#FThtml()
|
||||
let n = 1
|
||||
while n < 10 && n < line("$")
|
||||
if getline(n) =~ '\<DTD\s\+XHTML\s'
|
||||
setf xhtml
|
||||
return
|
||||
endif
|
||||
if getline(n) =~ '{%\s*\(extends\|block\|load\)\>\|{#\s\+'
|
||||
setf htmldjango
|
||||
return
|
||||
endif
|
||||
let n = n + 1
|
||||
endwhile
|
||||
setf html
|
||||
endfunc
|
||||
|
||||
" Distinguish between standard IDL and MS-IDL
|
||||
func dist#ft#FTidl()
|
||||
let n = 1
|
||||
while n < 50 && n < line("$")
|
||||
if getline(n) =~ '^\s*import\s\+"\(unknwn\|objidl\)\.idl"'
|
||||
setf msidl
|
||||
return
|
||||
endif
|
||||
let n = n + 1
|
||||
endwhile
|
||||
setf idl
|
||||
endfunc
|
||||
|
||||
" Distinguish between "default" and Cproto prototype file. */
|
||||
func dist#ft#ProtoCheck(default)
|
||||
" Cproto files have a comment in the first line and a function prototype in
|
||||
" the second line, it always ends in ";". Indent files may also have
|
||||
" comments, thus we can't match comments to see the difference.
|
||||
" IDL files can have a single ';' in the second line, require at least one
|
||||
" chacter before the ';'.
|
||||
if getline(2) =~ '.;$'
|
||||
setf cpp
|
||||
else
|
||||
exe 'setf ' . a:default
|
||||
endif
|
||||
endfunc
|
||||
|
||||
func dist#ft#FTm()
|
||||
let n = 1
|
||||
let saw_comment = 0 " Whether we've seen a multiline comment leader.
|
||||
while n < 100
|
||||
let line = getline(n)
|
||||
if line =~ '^\s*/\*'
|
||||
" /* ... */ is a comment in Objective C and Murphi, so we can't conclude
|
||||
" it's either of them yet, but track this as a hint in case we don't see
|
||||
" anything more definitive.
|
||||
let saw_comment = 1
|
||||
endif
|
||||
if line =~ '^\s*\(#\s*\(include\|import\)\>\|@import\>\|//\)'
|
||||
setf objc
|
||||
return
|
||||
endif
|
||||
if line =~ '^\s*%'
|
||||
setf matlab
|
||||
return
|
||||
endif
|
||||
if line =~ '^\s*(\*'
|
||||
setf mma
|
||||
return
|
||||
endif
|
||||
if line =~ '^\c\s*\(\(type\|var\)\>\|--\)'
|
||||
setf murphi
|
||||
return
|
||||
endif
|
||||
let n = n + 1
|
||||
endwhile
|
||||
|
||||
if saw_comment
|
||||
" We didn't see anything definitive, but this looks like either Objective C
|
||||
" or Murphi based on the comment leader. Assume the former as it is more
|
||||
" common.
|
||||
setf objc
|
||||
elseif exists("g:filetype_m")
|
||||
" Use user specified default filetype for .m
|
||||
exe "setf " . g:filetype_m
|
||||
else
|
||||
" Default is matlab
|
||||
setf matlab
|
||||
endif
|
||||
endfunc
|
||||
|
||||
func dist#ft#FTmms()
|
||||
let n = 1
|
||||
while n < 10
|
||||
let line = getline(n)
|
||||
if line =~ '^\s*\(%\|//\)' || line =~ '^\*'
|
||||
setf mmix
|
||||
return
|
||||
endif
|
||||
if line =~ '^\s*#'
|
||||
setf make
|
||||
return
|
||||
endif
|
||||
let n = n + 1
|
||||
endwhile
|
||||
setf mmix
|
||||
endfunc
|
||||
|
||||
" This function checks if one of the first five lines start with a dot. In
|
||||
" that case it is probably an nroff file: 'filetype' is set and 1 is returned.
|
||||
func dist#ft#FTnroff()
|
||||
if getline(1)[0] . getline(2)[0] . getline(3)[0] . getline(4)[0] . getline(5)[0] =~ '\.'
|
||||
setf nroff
|
||||
return 1
|
||||
endif
|
||||
return 0
|
||||
endfunc
|
||||
|
||||
func dist#ft#FTmm()
|
||||
let n = 1
|
||||
while n < 10
|
||||
let line = getline(n)
|
||||
if line =~ '^\s*\(#\s*\(include\|import\)\>\|@import\>\|/\*\)'
|
||||
setf objcpp
|
||||
return
|
||||
endif
|
||||
let n = n + 1
|
||||
endwhile
|
||||
setf nroff
|
||||
endfunc
|
||||
|
||||
func dist#ft#FTpl()
|
||||
if exists("g:filetype_pl")
|
||||
exe "setf " . g:filetype_pl
|
||||
else
|
||||
" recognize Prolog by specific text in the first non-empty line
|
||||
" require a blank after the '%' because Perl uses "%list" and "%translate"
|
||||
let l = getline(nextnonblank(1))
|
||||
if l =~ '\<prolog\>' || l =~ '^\s*\(%\+\(\s\|$\)\|/\*\)' || l =~ ':-'
|
||||
setf prolog
|
||||
else
|
||||
setf perl
|
||||
endif
|
||||
endif
|
||||
endfunc
|
||||
|
||||
func dist#ft#FTinc()
|
||||
if exists("g:filetype_inc")
|
||||
exe "setf " . g:filetype_inc
|
||||
else
|
||||
let lines = getline(1).getline(2).getline(3)
|
||||
if lines =~? "perlscript"
|
||||
setf aspperl
|
||||
elseif lines =~ "<%"
|
||||
setf aspvbs
|
||||
elseif lines =~ "<?"
|
||||
setf php
|
||||
else
|
||||
call dist#ft#FTasmsyntax()
|
||||
if exists("b:asmsyntax")
|
||||
exe "setf " . fnameescape(b:asmsyntax)
|
||||
else
|
||||
setf pov
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
endfunc
|
||||
|
||||
func dist#ft#FTprogress_cweb()
|
||||
if exists("g:filetype_w")
|
||||
exe "setf " . g:filetype_w
|
||||
return
|
||||
endif
|
||||
if getline(1) =~ '&ANALYZE' || getline(3) =~ '&GLOBAL-DEFINE'
|
||||
setf progress
|
||||
else
|
||||
setf cweb
|
||||
endif
|
||||
endfunc
|
||||
|
||||
func dist#ft#FTprogress_asm()
|
||||
if exists("g:filetype_i")
|
||||
exe "setf " . g:filetype_i
|
||||
return
|
||||
endif
|
||||
" This function checks for an assembly comment the first ten lines.
|
||||
" If not found, assume Progress.
|
||||
let lnum = 1
|
||||
while lnum <= 10 && lnum < line('$')
|
||||
let line = getline(lnum)
|
||||
if line =~ '^\s*;' || line =~ '^\*'
|
||||
call dist#ft#FTasm()
|
||||
return
|
||||
elseif line !~ '^\s*$' || line =~ '^/\*'
|
||||
" Not an empty line: Doesn't look like valid assembly code.
|
||||
" Or it looks like a Progress /* comment
|
||||
break
|
||||
endif
|
||||
let lnum = lnum + 1
|
||||
endw
|
||||
setf progress
|
||||
endfunc
|
||||
|
||||
func dist#ft#FTprogress_pascal()
|
||||
if exists("g:filetype_p")
|
||||
exe "setf " . g:filetype_p
|
||||
return
|
||||
endif
|
||||
" This function checks for valid Pascal syntax in the first ten lines.
|
||||
" Look for either an opening comment or a program start.
|
||||
" If not found, assume Progress.
|
||||
let lnum = 1
|
||||
while lnum <= 10 && lnum < line('$')
|
||||
let line = getline(lnum)
|
||||
if line =~ '^\s*\(program\|unit\|procedure\|function\|const\|type\|var\)\>'
|
||||
\ || line =~ '^\s*{' || line =~ '^\s*(\*'
|
||||
setf pascal
|
||||
return
|
||||
elseif line !~ '^\s*$' || line =~ '^/\*'
|
||||
" Not an empty line: Doesn't look like valid Pascal code.
|
||||
" Or it looks like a Progress /* comment
|
||||
break
|
||||
endif
|
||||
let lnum = lnum + 1
|
||||
endw
|
||||
setf progress
|
||||
endfunc
|
||||
|
||||
func dist#ft#FTr()
|
||||
let max = line("$") > 50 ? 50 : line("$")
|
||||
|
||||
for n in range(1, max)
|
||||
" Rebol is easy to recognize, check for that first
|
||||
if getline(n) =~? '\<REBOL\>'
|
||||
setf rebol
|
||||
return
|
||||
endif
|
||||
endfor
|
||||
|
||||
for n in range(1, max)
|
||||
" R has # comments
|
||||
if getline(n) =~ '^\s*#'
|
||||
setf r
|
||||
return
|
||||
endif
|
||||
" Rexx has /* comments */
|
||||
if getline(n) =~ '^\s*/\*'
|
||||
setf rexx
|
||||
return
|
||||
endif
|
||||
endfor
|
||||
|
||||
" Nothing recognized, use user default or assume Rexx
|
||||
if exists("g:filetype_r")
|
||||
exe "setf " . g:filetype_r
|
||||
else
|
||||
" Rexx used to be the default, but R appears to be much more popular.
|
||||
setf r
|
||||
endif
|
||||
endfunc
|
||||
|
||||
func dist#ft#McSetf()
|
||||
" Rely on the file to start with a comment.
|
||||
" MS message text files use ';', Sendmail files use '#' or 'dnl'
|
||||
for lnum in range(1, min([line("$"), 20]))
|
||||
let line = getline(lnum)
|
||||
if line =~ '^\s*\(#\|dnl\)'
|
||||
setf m4 " Sendmail .mc file
|
||||
return
|
||||
elseif line =~ '^\s*;'
|
||||
setf msmessages " MS Message text file
|
||||
return
|
||||
endif
|
||||
endfor
|
||||
setf m4 " Default: Sendmail .mc file
|
||||
endfunc
|
||||
|
||||
" Called from filetype.vim and scripts.vim.
|
||||
func dist#ft#SetFileTypeSH(name)
|
||||
if expand("<amatch>") =~ g:ft_ignore_pat
|
||||
return
|
||||
endif
|
||||
if a:name =~ '\<csh\>'
|
||||
" Some .sh scripts contain #!/bin/csh.
|
||||
call dist#ft#SetFileTypeShell("csh")
|
||||
return
|
||||
elseif a:name =~ '\<tcsh\>'
|
||||
" Some .sh scripts contain #!/bin/tcsh.
|
||||
call dist#ft#SetFileTypeShell("tcsh")
|
||||
return
|
||||
elseif a:name =~ '\<zsh\>'
|
||||
" Some .sh scripts contain #!/bin/zsh.
|
||||
call dist#ft#SetFileTypeShell("zsh")
|
||||
return
|
||||
elseif a:name =~ '\<ksh\>'
|
||||
let b:is_kornshell = 1
|
||||
if exists("b:is_bash")
|
||||
unlet b:is_bash
|
||||
endif
|
||||
if exists("b:is_sh")
|
||||
unlet b:is_sh
|
||||
endif
|
||||
elseif exists("g:bash_is_sh") || a:name =~ '\<bash\>' || a:name =~ '\<bash2\>'
|
||||
let b:is_bash = 1
|
||||
if exists("b:is_kornshell")
|
||||
unlet b:is_kornshell
|
||||
endif
|
||||
if exists("b:is_sh")
|
||||
unlet b:is_sh
|
||||
endif
|
||||
elseif a:name =~ '\<sh\>'
|
||||
let b:is_sh = 1
|
||||
if exists("b:is_kornshell")
|
||||
unlet b:is_kornshell
|
||||
endif
|
||||
if exists("b:is_bash")
|
||||
unlet b:is_bash
|
||||
endif
|
||||
endif
|
||||
call dist#ft#SetFileTypeShell("sh")
|
||||
endfunc
|
||||
|
||||
" For shell-like file types, check for an "exec" command hidden in a comment,
|
||||
" as used for Tcl.
|
||||
" Also called from scripts.vim, thus can't be local to this script.
|
||||
func dist#ft#SetFileTypeShell(name)
|
||||
if expand("<amatch>") =~ g:ft_ignore_pat
|
||||
return
|
||||
endif
|
||||
let l = 2
|
||||
while l < 20 && l < line("$") && getline(l) =~ '^\s*\(#\|$\)'
|
||||
" Skip empty and comment lines.
|
||||
let l = l + 1
|
||||
endwhile
|
||||
if l < line("$") && getline(l) =~ '\s*exec\s' && getline(l - 1) =~ '^\s*#.*\\$'
|
||||
" Found an "exec" line after a comment with continuation
|
||||
let n = substitute(getline(l),'\s*exec\s\+\([^ ]*/\)\=', '', '')
|
||||
if n =~ '\<tclsh\|\<wish'
|
||||
setf tcl
|
||||
return
|
||||
endif
|
||||
endif
|
||||
exe "setf " . a:name
|
||||
endfunc
|
||||
|
||||
func dist#ft#CSH()
|
||||
if exists("g:filetype_csh")
|
||||
call dist#ft#SetFileTypeShell(g:filetype_csh)
|
||||
elseif &shell =~ "tcsh"
|
||||
call dist#ft#SetFileTypeShell("tcsh")
|
||||
else
|
||||
call dist#ft#SetFileTypeShell("csh")
|
||||
endif
|
||||
endfunc
|
||||
|
||||
let s:ft_rules_udev_rules_pattern = '^\s*\cudev_rules\s*=\s*"\([^"]\{-1,}\)/*".*'
|
||||
func dist#ft#FTRules()
|
||||
let path = expand('<amatch>:p')
|
||||
if path =~ '^/\(etc/udev/\%(rules\.d/\)\=.*\.rules\|lib/udev/\%(rules\.d/\)\=.*\.rules\)$'
|
||||
setf udevrules
|
||||
return
|
||||
endif
|
||||
if path =~ '^/etc/ufw/'
|
||||
setf conf " Better than hog
|
||||
return
|
||||
endif
|
||||
if path =~ '^/\(etc\|usr/share\)/polkit-1/rules\.d'
|
||||
setf javascript
|
||||
return
|
||||
endif
|
||||
try
|
||||
let config_lines = readfile('/etc/udev/udev.conf')
|
||||
catch /^Vim\%((\a\+)\)\=:E484/
|
||||
setf hog
|
||||
return
|
||||
endtry
|
||||
let dir = expand('<amatch>:p:h')
|
||||
for line in config_lines
|
||||
if line =~ s:ft_rules_udev_rules_pattern
|
||||
let udev_rules = substitute(line, s:ft_rules_udev_rules_pattern, '\1', "")
|
||||
if dir == udev_rules
|
||||
setf udevrules
|
||||
endif
|
||||
break
|
||||
endif
|
||||
endfor
|
||||
setf hog
|
||||
endfunc
|
||||
|
||||
func dist#ft#SQL()
|
||||
if exists("g:filetype_sql")
|
||||
exe "setf " . g:filetype_sql
|
||||
else
|
||||
setf sql
|
||||
endif
|
||||
endfunc
|
||||
|
||||
" If the file has an extension of 't' and is in a directory 't' or 'xt' then
|
||||
" it is almost certainly a Perl test file.
|
||||
" If the first line starts with '#' and contains 'perl' it's probably a Perl
|
||||
" file.
|
||||
" (Slow test) If a file contains a 'use' statement then it is almost certainly
|
||||
" a Perl file.
|
||||
func dist#ft#FTperl()
|
||||
let dirname = expand("%:p:h:t")
|
||||
if expand("%:e") == 't' && (dirname == 't' || dirname == 'xt')
|
||||
setf perl
|
||||
return 1
|
||||
endif
|
||||
if getline(1)[0] == '#' && getline(1) =~ 'perl'
|
||||
setf perl
|
||||
return 1
|
||||
endif
|
||||
if search('^use\s\s*\k', 'nc', 30)
|
||||
setf perl
|
||||
return 1
|
||||
endif
|
||||
return 0
|
||||
endfunc
|
||||
|
||||
" Choose context, plaintex, or tex (LaTeX) based on these rules:
|
||||
" 1. Check the first line of the file for "%&<format>".
|
||||
" 2. Check the first 1000 non-comment lines for LaTeX or ConTeXt keywords.
|
||||
" 3. Default to "latex" or to g:tex_flavor, can be set in user's vimrc.
|
||||
func dist#ft#FTtex()
|
||||
let firstline = getline(1)
|
||||
if firstline =~ '^%&\s*\a\+'
|
||||
let format = tolower(matchstr(firstline, '\a\+'))
|
||||
let format = substitute(format, 'pdf', '', '')
|
||||
if format == 'tex'
|
||||
let format = 'latex'
|
||||
elseif format == 'plaintex'
|
||||
let format = 'plain'
|
||||
endif
|
||||
elseif expand('%') =~ 'tex/context/.*/.*.tex'
|
||||
let format = 'context'
|
||||
else
|
||||
" Default value, may be changed later:
|
||||
let format = exists("g:tex_flavor") ? g:tex_flavor : 'plain'
|
||||
" Save position, go to the top of the file, find first non-comment line.
|
||||
let save_cursor = getpos('.')
|
||||
call cursor(1,1)
|
||||
let firstNC = search('^\s*[^[:space:]%]', 'c', 1000)
|
||||
if firstNC " Check the next thousand lines for a LaTeX or ConTeXt keyword.
|
||||
let lpat = 'documentclass\>\|usepackage\>\|begin{\|newcommand\>\|renewcommand\>'
|
||||
let cpat = 'start\a\+\|setup\a\+\|usemodule\|enablemode\|enableregime\|setvariables\|useencoding\|usesymbols\|stelle\a\+\|verwende\a\+\|stel\a\+\|gebruik\a\+\|usa\a\+\|imposta\a\+\|regle\a\+\|utilisemodule\>'
|
||||
let kwline = search('^\s*\\\%(' . lpat . '\)\|^\s*\\\(' . cpat . '\)',
|
||||
\ 'cnp', firstNC + 1000)
|
||||
if kwline == 1 " lpat matched
|
||||
let format = 'latex'
|
||||
elseif kwline == 2 " cpat matched
|
||||
let format = 'context'
|
||||
endif " If neither matched, keep default set above.
|
||||
" let lline = search('^\s*\\\%(' . lpat . '\)', 'cn', firstNC + 1000)
|
||||
" let cline = search('^\s*\\\%(' . cpat . '\)', 'cn', firstNC + 1000)
|
||||
" if cline > 0
|
||||
" let format = 'context'
|
||||
" endif
|
||||
" if lline > 0 && (cline == 0 || cline > lline)
|
||||
" let format = 'tex'
|
||||
" endif
|
||||
endif " firstNC
|
||||
call setpos('.', save_cursor)
|
||||
endif " firstline =~ '^%&\s*\a\+'
|
||||
|
||||
" Translation from formats to file types. TODO: add AMSTeX, RevTex, others?
|
||||
if format == 'plain'
|
||||
setf plaintex
|
||||
elseif format == 'context'
|
||||
setf context
|
||||
else " probably LaTeX
|
||||
setf tex
|
||||
endif
|
||||
return
|
||||
endfunc
|
||||
|
||||
func dist#ft#FTxml()
|
||||
let n = 1
|
||||
while n < 100 && n < line("$")
|
||||
let line = getline(n)
|
||||
" DocBook 4 or DocBook 5.
|
||||
let is_docbook4 = line =~ '<!DOCTYPE.*DocBook'
|
||||
let is_docbook5 = line =~ ' xmlns="http://docbook.org/ns/docbook"'
|
||||
if is_docbook4 || is_docbook5
|
||||
let b:docbk_type = "xml"
|
||||
if is_docbook5
|
||||
let b:docbk_ver = 5
|
||||
else
|
||||
let b:docbk_ver = 4
|
||||
endif
|
||||
setf docbk
|
||||
return
|
||||
endif
|
||||
if line =~ 'xmlns:xbl="http://www.mozilla.org/xbl"'
|
||||
setf xbl
|
||||
return
|
||||
endif
|
||||
let n += 1
|
||||
endwhile
|
||||
setf xml
|
||||
endfunc
|
||||
|
||||
func dist#ft#FTy()
|
||||
let n = 1
|
||||
while n < 100 && n < line("$")
|
||||
let line = getline(n)
|
||||
if line =~ '^\s*%'
|
||||
setf yacc
|
||||
return
|
||||
endif
|
||||
if getline(n) =~ '^\s*\(#\|class\>\)' && getline(n) !~ '^\s*#\s*include'
|
||||
setf racc
|
||||
return
|
||||
endif
|
||||
let n = n + 1
|
||||
endwhile
|
||||
setf yacc
|
||||
endfunc
|
||||
|
||||
func dist#ft#Redif()
|
||||
let lnum = 1
|
||||
while lnum <= 5 && lnum < line('$')
|
||||
if getline(lnum) =~ "^\ctemplate-type:"
|
||||
setf redif
|
||||
return
|
||||
endif
|
||||
let lnum = lnum + 1
|
||||
endwhile
|
||||
endfunc
|
||||
|
||||
|
||||
" Restore 'cpoptions'
|
||||
let &cpo = s:cpo_save
|
||||
unlet s:cpo_save
|
@ -93,27 +93,27 @@ function! s:help_to_link(s) abort
|
||||
return substitute(a:s, '\v:h%[elp] ([^|][^"\r\n ]+)', ':help |\1|', 'g')
|
||||
endfunction
|
||||
|
||||
" Format a message for a specific report item
|
||||
" Format a message for a specific report item.
|
||||
" a:1: Optional advice (string or list)
|
||||
function! s:format_report_message(status, msg, ...) abort " {{{
|
||||
let output = ' - ' . a:status . ': ' . s:indent_after_line1(a:msg, 4)
|
||||
let advice = []
|
||||
|
||||
" Optional parameters
|
||||
if a:0 > 0
|
||||
let advice = type(a:1) == type("") ? [a:1] : a:1
|
||||
let advice = type(a:1) == type('') ? [a:1] : a:1
|
||||
if type(advice) != type([])
|
||||
throw "Expected String or List"
|
||||
throw 'a:1: expected String or List'
|
||||
endif
|
||||
|
||||
" Report each suggestion
|
||||
if !empty(advice)
|
||||
let output .= "\n - ADVICE:"
|
||||
for suggestion in advice
|
||||
let output .= "\n - " . s:indent_after_line1(suggestion, 10)
|
||||
endfor
|
||||
endif
|
||||
endif
|
||||
|
||||
" Report each suggestion
|
||||
if len(advice) > 0
|
||||
let output .= "\n - ADVICE:"
|
||||
endif
|
||||
for suggestion in advice
|
||||
let output .= "\n - " . s:indent_after_line1(suggestion, 10)
|
||||
endfor
|
||||
|
||||
return s:help_to_link(output)
|
||||
endfunction " }}}
|
||||
|
||||
@ -128,6 +128,7 @@ function! health#report_ok(msg) abort " {{{
|
||||
endfunction " }}}
|
||||
|
||||
" Reports a health warning.
|
||||
" a:1: Optional advice (string or list)
|
||||
function! health#report_warn(msg, ...) abort " {{{
|
||||
if a:0 > 0
|
||||
echo s:format_report_message('WARNING', a:msg, a:1)
|
||||
@ -137,6 +138,7 @@ function! health#report_warn(msg, ...) abort " {{{
|
||||
endfunction " }}}
|
||||
|
||||
" Reports a failed healthcheck.
|
||||
" a:1: Optional advice (string or list)
|
||||
function! health#report_error(msg, ...) abort " {{{
|
||||
if a:0 > 0
|
||||
echo s:format_report_message('ERROR', a:msg, a:1)
|
||||
|
@ -7,12 +7,12 @@ function! s:check_config() abort
|
||||
" If $VIM is empty we don't care. Else make sure it is valid.
|
||||
if !empty($VIM) && !filereadable($VIM.'/runtime/doc/nvim.txt')
|
||||
let ok = v:false
|
||||
call health#report_error("$VIM is invalid: ".$VIM)
|
||||
call health#report_error('$VIM is invalid: '.$VIM)
|
||||
endif
|
||||
|
||||
if exists('$NVIM_TUI_ENABLE_CURSOR_SHAPE')
|
||||
let ok = v:false
|
||||
call health#report_warn("$NVIM_TUI_ENABLE_CURSOR_SHAPE is ignored in Nvim 0.2+",
|
||||
call health#report_warn('$NVIM_TUI_ENABLE_CURSOR_SHAPE is ignored in Nvim 0.2+',
|
||||
\ [ "Use the 'guicursor' option to configure cursor shape. :help 'guicursor'",
|
||||
\ 'https://github.com/neovim/neovim/wiki/Following-HEAD#20170402' ])
|
||||
endif
|
||||
@ -100,8 +100,8 @@ function! s:check_performance() abort
|
||||
else
|
||||
call health#report_info(buildtype)
|
||||
call health#report_warn(
|
||||
\ "Non-optimized build-type. Nvim will be slower.",
|
||||
\ ["Install a different Nvim package, or rebuild with `CMAKE_BUILD_TYPE=RelWithDebInfo`.",
|
||||
\ 'Non-optimized build-type. Nvim will be slower.',
|
||||
\ ['Install a different Nvim package, or rebuild with `CMAKE_BUILD_TYPE=RelWithDebInfo`.',
|
||||
\ s:suggest_faq])
|
||||
endif
|
||||
endfunction
|
||||
@ -174,7 +174,7 @@ function! s:check_terminal() abort
|
||||
\ .(empty(kbs_entry) ? '? (not found)' : kdch1_entry))
|
||||
endif
|
||||
for env_var in ['XTERM_VERSION', 'VTE_VERSION', 'TERM_PROGRAM', 'COLORTERM', 'SSH_TTY']
|
||||
if !exists('$'.env_var)
|
||||
if exists('$'.env_var)
|
||||
call health#report_info(printf("$%s='%s'", env_var, eval('$'.env_var)))
|
||||
endif
|
||||
endfor
|
||||
|
@ -13,6 +13,12 @@ function! s:normalize_path(s) abort
|
||||
return substitute(substitute(a:s, '\', '/', 'g'), '/\./\|/\+', '/', 'g')
|
||||
endfunction
|
||||
|
||||
" Returns TRUE if `cmd` exits with success, else FALSE.
|
||||
function! s:cmd_ok(cmd) abort
|
||||
call system(a:cmd)
|
||||
return v:shell_error == 0
|
||||
endfunction
|
||||
|
||||
" Simple version comparison.
|
||||
function! s:version_cmp(a, b) abort
|
||||
let a = split(a:a, '\.', 0)
|
||||
@ -120,6 +126,13 @@ endfunction
|
||||
function! s:check_clipboard() abort
|
||||
call health#report_start('Clipboard (optional)')
|
||||
|
||||
if !empty($TMUX) && executable('tmux') && executable('pbpaste') && !s:cmd_ok('pbpaste')
|
||||
let tmux_version = matchstr(system('tmux -V'), '\d\+\.\d\+')
|
||||
call health#report_error('pbcopy does not work with tmux version: '.tmux_version,
|
||||
\ ['Install tmux 2.6+. https://superuser.com/q/231130',
|
||||
\ 'or use tmux with reattach-to-user-namespace. https://superuser.com/a/413233'])
|
||||
endif
|
||||
|
||||
let clipboard_tool = provider#clipboard#Executable()
|
||||
if exists('g:clipboard') && empty(clipboard_tool)
|
||||
call health#report_error(
|
||||
@ -247,20 +260,23 @@ function! s:check_python(version) abort
|
||||
let python_multiple = []
|
||||
|
||||
if exists(loaded_var) && !exists('*provider#'.pyname.'#Call')
|
||||
call health#report_info('Disabled. '.loaded_var.'='.eval(loaded_var))
|
||||
return
|
||||
call health#report_info('Disabled ('.loaded_var.'='.eval(loaded_var).'). This might be due to some previous error.')
|
||||
endif
|
||||
|
||||
if !empty(pyenv)
|
||||
if empty(pyenv_root)
|
||||
call health#report_warn(
|
||||
\ 'pyenv was found, but $PYENV_ROOT is not set.',
|
||||
\ ['Did you follow the final install instructions?',
|
||||
\ 'If you use a shell "framework" like Prezto or Oh My Zsh, try without.',
|
||||
\ 'Try a different shell (bash).']
|
||||
call health#report_info(
|
||||
\ 'pyenv was found, but $PYENV_ROOT is not set. `pyenv root` will be used.'
|
||||
\ .' If you run into problems, try setting $PYENV_ROOT explicitly.'
|
||||
\ )
|
||||
let pyenv_root = s:trim(s:system([pyenv, 'root']))
|
||||
endif
|
||||
|
||||
if !isdirectory(pyenv_root)
|
||||
call health#report_error('Invalid pyenv root: '.pyenv_root)
|
||||
else
|
||||
call health#report_ok(printf('pyenv found: "%s"', pyenv))
|
||||
call health#report_info(printf('pyenv: %s', pyenv))
|
||||
call health#report_info(printf('pyenv root: %s', pyenv_root))
|
||||
endif
|
||||
endif
|
||||
|
||||
@ -272,9 +288,6 @@ function! s:check_python(version) abort
|
||||
if empty(pyname)
|
||||
call health#report_warn('No Python interpreter was found with the neovim '
|
||||
\ . 'module. Using the first available for diagnostics.')
|
||||
if !empty(pythonx_errs)
|
||||
call health#report_warn(pythonx_errs)
|
||||
endif
|
||||
endif
|
||||
|
||||
if !empty(pyname)
|
||||
@ -332,8 +345,8 @@ function! s:check_python(version) abort
|
||||
endif
|
||||
endif
|
||||
|
||||
if !empty(python_bin)
|
||||
if empty(venv) && !empty(pyenv) && !exists('g:'.host_prog_var)
|
||||
if !empty(python_bin) && !exists('g:'.host_prog_var)
|
||||
if empty(venv) && !empty(pyenv)
|
||||
\ && !empty(pyenv_root) && resolve(python_bin) !~# '^'.pyenv_root.'/'
|
||||
call health#report_warn('pyenv is not set up optimally.', [
|
||||
\ printf('Create a virtualenv specifically '
|
||||
@ -341,7 +354,7 @@ function! s:check_python(version) abort
|
||||
\ . 'the need to install the Neovim Python module in each '
|
||||
\ . 'version/virtualenv.', host_prog_var)
|
||||
\ ])
|
||||
elseif !empty(venv) && exists('g:'.host_prog_var)
|
||||
elseif !empty(venv)
|
||||
if !empty(pyenv_root)
|
||||
let venv_root = pyenv_root
|
||||
else
|
||||
@ -366,27 +379,16 @@ function! s:check_python(version) abort
|
||||
let python_bin = ''
|
||||
endif
|
||||
|
||||
" Check if $VIRTUAL_ENV is active
|
||||
let virtualenv_inactive = 0
|
||||
|
||||
" Check if $VIRTUAL_ENV is valid.
|
||||
if exists('$VIRTUAL_ENV')
|
||||
if !empty(pyenv)
|
||||
let pyenv_prefix = resolve(s:trim(s:system([pyenv, 'prefix'])))
|
||||
if $VIRTUAL_ENV != pyenv_prefix
|
||||
let virtualenv_inactive = 1
|
||||
endif
|
||||
elseif !empty(pyname) && exepath(pyname) !~# '^'.$VIRTUAL_ENV.'/'
|
||||
let virtualenv_inactive = 1
|
||||
if !empty(pyname) && $VIRTUAL_ENV !=# matchstr(exepath(pyname), '^\V'.$VIRTUAL_ENV)
|
||||
call health#report_warn(
|
||||
\ '$VIRTUAL_ENV exists but appears to be inactive. '
|
||||
\ . 'This could lead to unexpected results.',
|
||||
\ [ 'If you are using Zsh, see: http://vi.stackexchange.com/a/7654' ])
|
||||
endif
|
||||
endif
|
||||
|
||||
if virtualenv_inactive
|
||||
call health#report_warn(
|
||||
\ '$VIRTUAL_ENV exists but appears to be inactive. '
|
||||
\ . 'This could lead to unexpected results.',
|
||||
\ [ 'If you are using Zsh, see: http://vi.stackexchange.com/a/7654/5229' ])
|
||||
endif
|
||||
|
||||
" Diagnostic output
|
||||
call health#report_info('Executable: ' . (empty(python_bin) ? 'Not found' : python_bin))
|
||||
if len(python_multiple)
|
||||
@ -451,10 +453,11 @@ function! s:check_ruby() abort
|
||||
|
||||
let host = provider#ruby#Detect()
|
||||
if empty(host)
|
||||
call health#report_warn('Missing "neovim" gem.',
|
||||
\ ['Run in shell: gem install neovim',
|
||||
\ 'Is the gem bin directory in $PATH? Check `gem environment`.',
|
||||
\ 'If you are using rvm/rbenv/chruby, try "rehashing".'])
|
||||
call health#report_warn('`neovim-ruby-host` not found.',
|
||||
\ ['Run `gem install neovim` to ensure the neovim RubyGem is installed.',
|
||||
\ 'Run `gem environment` to ensure the gem bin directory is in $PATH.',
|
||||
\ 'If you are using rvm/rbenv/chruby, try "rehashing".',
|
||||
\ 'See :help g:ruby_host_prog for non-standard gem installations.'])
|
||||
return
|
||||
endif
|
||||
call health#report_info('Host: '. host)
|
||||
@ -488,7 +491,7 @@ function! s:check_ruby() abort
|
||||
endfunction
|
||||
|
||||
function! s:check_node() abort
|
||||
call health#report_start('Node provider (optional)')
|
||||
call health#report_start('Node.js provider (optional)')
|
||||
|
||||
let loaded_var = 'g:loaded_node_provider'
|
||||
if exists(loaded_var) && !exists('*provider#node#Call')
|
||||
@ -502,7 +505,16 @@ function! s:check_node() abort
|
||||
\ ['Install Node.js and verify that `node` and `npm` commands work.'])
|
||||
return
|
||||
endif
|
||||
call health#report_info('Node: '. s:system('node -v'))
|
||||
let node_v = get(split(s:system('node -v'), "\n"), 0, '')
|
||||
call health#report_info('Node.js: '. node_v)
|
||||
if !s:shell_error && s:version_cmp(node_v[1:], '6.0.0') < 0
|
||||
call health#report_warn('Neovim node.js host does not support '.node_v)
|
||||
" Skip further checks, they are nonsense if nodejs is too old.
|
||||
return
|
||||
endif
|
||||
if !provider#node#can_inspect()
|
||||
call health#report_warn('node.js on this system does not support --inspect-brk so $NVIM_NODE_HOST_DEBUG is ignored.')
|
||||
endif
|
||||
|
||||
let host = provider#node#Detect()
|
||||
if empty(host)
|
||||
@ -511,7 +523,7 @@ function! s:check_node() abort
|
||||
\ 'Is the npm bin directory in $PATH?'])
|
||||
return
|
||||
endif
|
||||
call health#report_info('Host: '. host)
|
||||
call health#report_info('Neovim node.js host: '. host)
|
||||
|
||||
let latest_npm_cmd = has('win32') ? 'cmd /c npm info neovim --json' : 'npm info neovim --json'
|
||||
let latest_npm = s:system(split(latest_npm_cmd))
|
||||
@ -530,11 +542,11 @@ function! s:check_node() abort
|
||||
let latest_npm = get(get(pkg_data, 'dist-tags', {}), 'latest', 'unable to parse')
|
||||
endif
|
||||
|
||||
let current_npm_cmd = host .' --version'
|
||||
let current_npm_cmd = ['node', host, '--version']
|
||||
let current_npm = s:system(current_npm_cmd)
|
||||
if s:shell_error
|
||||
call health#report_error('Failed to run: '. current_npm_cmd,
|
||||
\ ['Report this issue with the output of: ', current_npm_cmd])
|
||||
call health#report_error('Failed to run: '. string(current_npm_cmd),
|
||||
\ ['Report this issue with the output of: ', string(current_npm_cmd)])
|
||||
return
|
||||
endif
|
||||
|
||||
@ -544,7 +556,7 @@ function! s:check_node() abort
|
||||
\ current_npm, latest_npm),
|
||||
\ ['Run in shell: npm update neovim'])
|
||||
else
|
||||
call health#report_ok('Latest "neovim" npm is installed: '. current_npm)
|
||||
call health#report_ok('Latest "neovim" npm package is installed: '. current_npm)
|
||||
endif
|
||||
endfunction
|
||||
|
||||
|
@ -65,9 +65,9 @@ function! man#open_page(count, count1, mods, ...) abort
|
||||
try
|
||||
set eventignore+=BufReadCmd
|
||||
if a:mods !~# 'tab' && s:find_man()
|
||||
execute 'silent edit' fnameescape(bufname)
|
||||
execute 'silent keepalt edit' fnameescape(bufname)
|
||||
else
|
||||
execute 'silent' a:mods 'split' fnameescape(bufname)
|
||||
execute 'silent keepalt' a:mods 'split' fnameescape(bufname)
|
||||
endif
|
||||
finally
|
||||
set eventignore-=BufReadCmd
|
||||
@ -148,7 +148,8 @@ function! s:get_page(path) abort
|
||||
let manwidth = empty($MANWIDTH) ? winwidth(0) : $MANWIDTH
|
||||
" Force MANPAGER=cat to ensure Vim is not recursively invoked (by man-db).
|
||||
" http://comments.gmane.org/gmane.editors.vim.devel/29085
|
||||
let cmd = ['env', 'MANPAGER=cat', 'MANWIDTH='.manwidth, 'man']
|
||||
" Set MAN_KEEP_FORMATTING so Debian man doesn't discard backspaces.
|
||||
let cmd = ['env', 'MANPAGER=cat', 'MANWIDTH='.manwidth, 'MAN_KEEP_FORMATTING=1', 'man']
|
||||
return s:system(cmd + (s:localfile_arg ? ['-l', a:path] : [a:path]))
|
||||
endfunction
|
||||
|
||||
@ -157,11 +158,10 @@ function! s:put_page(page) abort
|
||||
setlocal noreadonly
|
||||
silent keepjumps %delete _
|
||||
silent put =a:page
|
||||
" Remove all backspaced/escape characters.
|
||||
execute 'silent keeppatterns keepjumps %substitute,.\b\|\e\[\d\+m,,e'.(&gdefault?'':'g')
|
||||
while getline(1) =~# '^\s*$'
|
||||
silent keepjumps 1delete _
|
||||
endwhile
|
||||
lua require("man").highlight_man_page()
|
||||
setlocal filetype=man
|
||||
endfunction
|
||||
|
||||
@ -299,6 +299,12 @@ endfunction
|
||||
" see man#extract_sect_and_name_ref on why tolower(sect)
|
||||
function! man#complete(arg_lead, cmd_line, cursor_pos) abort
|
||||
let args = split(a:cmd_line)
|
||||
let cmd_offset = index(args, 'Man')
|
||||
if cmd_offset > 0
|
||||
" Prune all arguments up to :Man itself. Otherwise modifier commands like
|
||||
" :tab, :vertical, etc. would lead to a wrong length.
|
||||
let args = args[cmd_offset:]
|
||||
endif
|
||||
let l = len(args)
|
||||
if l > 3
|
||||
return
|
||||
@ -370,13 +376,12 @@ function! s:format_candidate(path, psect) abort
|
||||
endfunction
|
||||
|
||||
function! man#init_pager() abort
|
||||
" Remove all backspaced/escape characters.
|
||||
execute 'silent keeppatterns keepjumps %substitute,.\b\|\e\[\d\+m,,e'.(&gdefault?'':'g')
|
||||
if getline(1) =~# '^\s*$'
|
||||
silent keepjumps 1delete _
|
||||
else
|
||||
keepjumps 1
|
||||
endif
|
||||
lua require("man").highlight_man_page()
|
||||
" This is not perfect. See `man glDrawArraysInstanced`. Since the title is
|
||||
" all caps it is impossible to tell what the original capitilization was.
|
||||
let ref = substitute(matchstr(getline(1), '^[^)]\+)'), ' ', '_', 'g')
|
||||
|
@ -1,20 +1,21 @@
|
||||
" Common functionality for providers
|
||||
" Common functions for providers
|
||||
|
||||
let s:stderr = {}
|
||||
|
||||
function! provider#stderr_collector(chan_id, data, event)
|
||||
let stderr = get(s:stderr, a:chan_id, [''])
|
||||
let stderr[-1] .= a:data[0]
|
||||
call extend(stderr, a:data[1:])
|
||||
let s:stderr[a:chan_id] = stderr
|
||||
endfunction
|
||||
|
||||
function! provider#clear_stderr(chan_id)
|
||||
if has_key(s:stderr, a:chan_id)
|
||||
call remove(s:stderr, a:chan_id)
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! provider#get_stderr(chan_id)
|
||||
return get(s:stderr, a:chan_id, [])
|
||||
" Start the provider and perform a 'poll' request
|
||||
"
|
||||
" Returns a valid channel on success
|
||||
function! provider#Poll(argv, orig_name, log_env) abort
|
||||
let job = {'rpc': v:true, 'stderr_buffered': v:true}
|
||||
try
|
||||
let channel_id = jobstart(a:argv, job)
|
||||
if channel_id > 0 && rpcrequest(channel_id, 'poll') ==# 'ok'
|
||||
return channel_id
|
||||
endif
|
||||
catch
|
||||
echomsg v:throwpoint
|
||||
echomsg v:exception
|
||||
for row in get(job, 'stderr', [])
|
||||
echomsg row
|
||||
endfor
|
||||
endtry
|
||||
throw remote#host#LoadErrorForHost(a:orig_name, a:log_env)
|
||||
endfunction
|
||||
|
@ -7,7 +7,7 @@ let s:clipboard = {}
|
||||
|
||||
" When caching is enabled, store the jobid of the xclip/xsel process keeping
|
||||
" ownership of the selection, so we know how long the cache is valid.
|
||||
let s:selection = { 'owner': 0, 'data': [], 'on_stderr': function('provider#stderr_collector') }
|
||||
let s:selection = { 'owner': 0, 'data': [], 'stderr_buffered': v:true }
|
||||
|
||||
function! s:selection.on_exit(jobid, data, event) abort
|
||||
" At this point this nvim instance might already have launched
|
||||
@ -16,19 +16,17 @@ function! s:selection.on_exit(jobid, data, event) abort
|
||||
let self.owner = 0
|
||||
endif
|
||||
if a:data != 0
|
||||
let stderr = provider#get_stderr(a:jobid)
|
||||
echohl WarningMsg
|
||||
echomsg 'clipboard: error invoking '.get(self.argv, 0, '?').': '.join(stderr)
|
||||
echomsg 'clipboard: error invoking '.get(self.argv, 0, '?').': '.join(self.stderr)
|
||||
echohl None
|
||||
endif
|
||||
call provider#clear_stderr(a:jobid)
|
||||
endfunction
|
||||
|
||||
let s:selections = { '*': s:selection, '+': copy(s:selection) }
|
||||
|
||||
function! s:try_cmd(cmd, ...) abort
|
||||
let argv = split(a:cmd, " ")
|
||||
let out = a:0 ? systemlist(argv, a:1, 1) : systemlist(argv, [''], 1)
|
||||
let out = systemlist(argv, (a:0 ? a:1 : ['']), 1)
|
||||
if v:shell_error
|
||||
if !exists('s:did_error_try_cmd')
|
||||
echohl WarningMsg
|
||||
@ -66,7 +64,7 @@ function! provider#clipboard#Executable() abort
|
||||
let s:paste = get(g:clipboard, 'paste', { '+': v:null, '*': v:null })
|
||||
let s:cache_enabled = get(g:clipboard, 'cache_enabled', 0)
|
||||
return get(g:clipboard, 'name', 'g:clipboard')
|
||||
elseif has('mac') && executable('pbcopy')
|
||||
elseif has('mac') && executable('pbpaste') && s:cmd_ok('pbpaste')
|
||||
let s:copy['+'] = 'pbcopy'
|
||||
let s:paste['+'] = 'pbpaste'
|
||||
let s:copy['*'] = s:copy['+']
|
||||
@ -142,12 +140,13 @@ function! s:clipboard.set(lines, regtype, reg) abort
|
||||
return 0
|
||||
end
|
||||
|
||||
let selection = s:selections[a:reg]
|
||||
if selection.owner > 0
|
||||
if s:selections[a:reg].owner > 0
|
||||
" The previous provider instance should exit when the new one takes
|
||||
" ownership, but kill it to be sure we don't fill up the job table.
|
||||
call jobstop(selection.owner)
|
||||
call jobstop(s:selections[a:reg].owner)
|
||||
end
|
||||
let s:selections[a:reg] = copy(s:selection)
|
||||
let selection = s:selections[a:reg]
|
||||
let selection.data = [a:lines, a:regtype]
|
||||
let argv = split(s:copy[a:reg], " ")
|
||||
let selection.argv = argv
|
||||
|
@ -3,13 +3,59 @@ if exists('g:loaded_node_provider')
|
||||
endif
|
||||
let g:loaded_node_provider = 1
|
||||
|
||||
let s:job_opts = {'rpc': v:true, 'on_stderr': function('provider#stderr_collector')}
|
||||
|
||||
function! provider#node#Detect() abort
|
||||
return has('win32') ? exepath('neovim-node-host.cmd') : exepath('neovim-node-host')
|
||||
function! s:is_minimum_version(version, min_major, min_minor) abort
|
||||
if empty(a:version)
|
||||
let nodejs_version = get(split(system(['node', '-v']), "\n"), 0, '')
|
||||
if v:shell_error || nodejs_version[0] !=# 'v'
|
||||
return 0
|
||||
endif
|
||||
else
|
||||
let nodejs_version = a:version
|
||||
endif
|
||||
" Remove surrounding junk. Example: 'v4.12.0' => '4.12.0'
|
||||
let nodejs_version = matchstr(nodejs_version, '\(\d\.\?\)\+')
|
||||
" [major, minor, patch]
|
||||
let v_list = split(nodejs_version, '\.')
|
||||
return len(v_list) == 3
|
||||
\ && ((str2nr(v_list[0]) > str2nr(a:min_major))
|
||||
\ || (str2nr(v_list[0]) == str2nr(a:min_major)
|
||||
\ && str2nr(v_list[1]) >= str2nr(a:min_minor)))
|
||||
endfunction
|
||||
|
||||
function! provider#node#Prog()
|
||||
" Support for --inspect-brk requires node 6.12+ or 7.6+ or 8+
|
||||
" Return 1 if it is supported
|
||||
" Return 0 otherwise
|
||||
function! provider#node#can_inspect() abort
|
||||
if !executable('node')
|
||||
return 0
|
||||
endif
|
||||
let ver = get(split(system(['node', '-v']), "\n"), 0, '')
|
||||
if v:shell_error || ver[0] !=# 'v'
|
||||
return 0
|
||||
endif
|
||||
return (ver[1] ==# '6' && s:is_minimum_version(ver, 6, 12))
|
||||
\ || s:is_minimum_version(ver, 7, 6)
|
||||
endfunction
|
||||
|
||||
function! provider#node#Detect() abort
|
||||
if exists('g:node_host_prog')
|
||||
return g:node_host_prog
|
||||
endif
|
||||
let global_modules = get(split(system('npm root -g'), "\n"), 0, '')
|
||||
if v:shell_error || !isdirectory(global_modules)
|
||||
return ''
|
||||
endif
|
||||
if !s:is_minimum_version(v:null, 6, 0)
|
||||
return ''
|
||||
endif
|
||||
let entry_point = glob(global_modules . '/neovim/bin/cli.js')
|
||||
if !filereadable(entry_point)
|
||||
return ''
|
||||
endif
|
||||
return entry_point
|
||||
endfunction
|
||||
|
||||
function! provider#node#Prog() abort
|
||||
return s:prog
|
||||
endfunction
|
||||
|
||||
@ -19,37 +65,18 @@ function! provider#node#Require(host) abort
|
||||
return
|
||||
endif
|
||||
|
||||
if has('win32')
|
||||
let args = provider#node#Prog()
|
||||
else
|
||||
let args = ['node']
|
||||
let args = ['node']
|
||||
|
||||
if !empty($NVIM_NODE_HOST_DEBUG)
|
||||
call add(args, '--inspect-brk')
|
||||
endif
|
||||
|
||||
call add(args , provider#node#Prog())
|
||||
if !empty($NVIM_NODE_HOST_DEBUG) && provider#node#can_inspect()
|
||||
call add(args, '--inspect-brk')
|
||||
endif
|
||||
|
||||
try
|
||||
let channel_id = jobstart(args, s:job_opts)
|
||||
if rpcrequest(channel_id, 'poll') ==# 'ok'
|
||||
return channel_id
|
||||
endif
|
||||
catch
|
||||
echomsg v:throwpoint
|
||||
echomsg v:exception
|
||||
for row in provider#get_stderr(channel_id)
|
||||
echomsg row
|
||||
endfor
|
||||
endtry
|
||||
finally
|
||||
call provider#clear_stderr(channel_id)
|
||||
endtry
|
||||
throw remote#host#LoadErrorForHost(a:host.orig_name, '$NVIM_NODE_LOG_FILE')
|
||||
call add(args, provider#node#Prog())
|
||||
|
||||
return provider#Poll(args, a:host.orig_name, '$NVIM_NODE_LOG_FILE')
|
||||
endfunction
|
||||
|
||||
function! provider#node#Call(method, args)
|
||||
function! provider#node#Call(method, args) abort
|
||||
if s:err != ''
|
||||
echoerr s:err
|
||||
return
|
||||
@ -74,7 +101,7 @@ let s:err = ''
|
||||
let s:prog = provider#node#Detect()
|
||||
|
||||
if empty(s:prog)
|
||||
let s:err = 'Cannot find the "neovim" node package. Try :CheckHealth'
|
||||
let s:err = 'Cannot find the "neovim" node package. Try :checkhealth'
|
||||
endif
|
||||
|
||||
call remote#host#RegisterPlugin('node-provider', 'node', [])
|
||||
|
@ -11,11 +11,11 @@ let g:loaded_python_provider = 1
|
||||
|
||||
let [s:prog, s:err] = provider#pythonx#Detect(2)
|
||||
|
||||
function! provider#python#Prog()
|
||||
function! provider#python#Prog() abort
|
||||
return s:prog
|
||||
endfunction
|
||||
|
||||
function! provider#python#Error()
|
||||
function! provider#python#Error() abort
|
||||
return s:err
|
||||
endfunction
|
||||
|
||||
@ -29,7 +29,7 @@ endif
|
||||
call remote#host#RegisterClone('legacy-python-provider', 'python')
|
||||
call remote#host#RegisterPlugin('legacy-python-provider', 'script_host.py', [])
|
||||
|
||||
function! provider#python#Call(method, args)
|
||||
function! provider#python#Call(method, args) abort
|
||||
if s:err != ''
|
||||
return
|
||||
endif
|
||||
|
@ -11,11 +11,11 @@ let g:loaded_python3_provider = 1
|
||||
|
||||
let [s:prog, s:err] = provider#pythonx#Detect(3)
|
||||
|
||||
function! provider#python3#Prog()
|
||||
function! provider#python3#Prog() abort
|
||||
return s:prog
|
||||
endfunction
|
||||
|
||||
function! provider#python3#Error()
|
||||
function! provider#python3#Error() abort
|
||||
return s:err
|
||||
endfunction
|
||||
|
||||
@ -29,7 +29,7 @@ endif
|
||||
call remote#host#RegisterClone('legacy-python3-provider', 'python3')
|
||||
call remote#host#RegisterPlugin('legacy-python3-provider', 'script_host.py', [])
|
||||
|
||||
function! provider#python3#Call(method, args)
|
||||
function! provider#python3#Call(method, args) abort
|
||||
if s:err != ''
|
||||
return
|
||||
endif
|
||||
|
@ -5,8 +5,6 @@ endif
|
||||
|
||||
let s:loaded_pythonx_provider = 1
|
||||
|
||||
let s:job_opts = {'rpc': v:true, 'on_stderr': function('provider#stderr_collector')}
|
||||
|
||||
function! provider#pythonx#Require(host) abort
|
||||
let ver = (a:host.orig_name ==# 'python') ? 2 : 3
|
||||
|
||||
@ -20,22 +18,7 @@ function! provider#pythonx#Require(host) abort
|
||||
call add(args, plugin.path)
|
||||
endfor
|
||||
|
||||
try
|
||||
let channel_id = jobstart(args, s:job_opts)
|
||||
if rpcrequest(channel_id, 'poll') ==# 'ok'
|
||||
return channel_id
|
||||
endif
|
||||
catch
|
||||
echomsg v:throwpoint
|
||||
echomsg v:exception
|
||||
for row in provider#get_stderr(channel_id)
|
||||
echomsg row
|
||||
endfor
|
||||
finally
|
||||
call provider#clear_stderr(channel_id)
|
||||
endtry
|
||||
throw remote#host#LoadErrorForHost(a:host.orig_name,
|
||||
\ '$NVIM_PYTHON_LOG_FILE')
|
||||
return provider#Poll(args, a:host.orig_name, '$NVIM_PYTHON_LOG_FILE')
|
||||
endfunction
|
||||
|
||||
function! provider#pythonx#Detect(major_ver) abort
|
||||
|
@ -4,17 +4,6 @@ if exists('g:loaded_ruby_provider')
|
||||
endif
|
||||
let g:loaded_ruby_provider = 1
|
||||
|
||||
let s:stderr = {}
|
||||
let s:job_opts = {'rpc': v:true}
|
||||
|
||||
function! s:job_opts.on_stderr(chan_id, data, event)
|
||||
let stderr = get(s:stderr, a:chan_id, [''])
|
||||
let last = remove(stderr, -1)
|
||||
let a:data[0] = last.a:data[0]
|
||||
call extend(stderr, a:data)
|
||||
let s:stderr[a:chan_id] = stderr
|
||||
endfunction
|
||||
|
||||
function! provider#ruby#Detect() abort
|
||||
if exists("g:ruby_host_prog")
|
||||
return g:ruby_host_prog
|
||||
@ -23,7 +12,7 @@ function! provider#ruby#Detect() abort
|
||||
end
|
||||
endfunction
|
||||
|
||||
function! provider#ruby#Prog()
|
||||
function! provider#ruby#Prog() abort
|
||||
return s:prog
|
||||
endfunction
|
||||
|
||||
@ -35,22 +24,10 @@ function! provider#ruby#Require(host) abort
|
||||
let prog .= " " . shellescape(plugin.path)
|
||||
endfor
|
||||
|
||||
try
|
||||
let channel_id = jobstart(prog, s:job_opts)
|
||||
if rpcrequest(channel_id, 'poll') ==# 'ok'
|
||||
return channel_id
|
||||
endif
|
||||
catch
|
||||
echomsg v:throwpoint
|
||||
echomsg v:exception
|
||||
for row in get(s:stderr, channel_id, [])
|
||||
echomsg row
|
||||
endfor
|
||||
endtry
|
||||
throw remote#host#LoadErrorForHost(a:host.orig_name, '$NVIM_RUBY_LOG_FILE')
|
||||
return provider#Poll(prog, a:host.orig_name, '$NVIM_RUBY_LOG_FILE')
|
||||
endfunction
|
||||
|
||||
function! provider#ruby#Call(method, args)
|
||||
function! provider#ruby#Call(method, args) abort
|
||||
if s:err != ''
|
||||
echoerr s:err
|
||||
return
|
||||
|
@ -2,9 +2,6 @@
|
||||
|
||||
" Setup: {{{1
|
||||
function! tutor#SetupVim()
|
||||
if &columns < 90
|
||||
set columns=90
|
||||
endif
|
||||
if !exists('g:did_load_ftplugin') || g:did_load_ftplugin != 1
|
||||
filetype plugin on
|
||||
endif
|
||||
|
@ -49,6 +49,7 @@ version.api_prerelease Declares the current API level as unstable >
|
||||
(version.api_prerelease && fn.since == version.api_level)
|
||||
functions API function signatures
|
||||
ui_events UI event signatures |ui|
|
||||
ui_options Supported |ui-options|
|
||||
{fn}.since API level where function {fn} was introduced
|
||||
{fn}.deprecated_since API level where function {fn} was deprecated
|
||||
types Custom handle types defined by Nvim
|
||||
@ -60,8 +61,7 @@ External programs ("clients") can use the metadata to discover the |rpc-api|.
|
||||
API contract *api-contract*
|
||||
|
||||
The API is made of functions and events. Clients call functions like those
|
||||
described at |api-global|, and may "attach" in order to receive rich events,
|
||||
described at |rpc-remote-ui|.
|
||||
described at |api-global|, and may "attach" to receive rich |ui-events|.
|
||||
|
||||
As Nvim develops, its API may change only according the following "contract":
|
||||
|
||||
@ -446,7 +446,11 @@ nvim_get_keymap({mode}) *nvim_get_keymap()*
|
||||
Array of maparg()-like dictionaries describing mappings
|
||||
|
||||
nvim_get_api_info() *nvim_get_api_info()*
|
||||
TODO: Documentation
|
||||
Returns a 2-tuple (Array), where item 0 is the current channel
|
||||
id and item 1 is the |api-metadata| map (Dictionary).
|
||||
|
||||
Return:~
|
||||
2-tuple [{channel-id}, {api-metadata}]
|
||||
|
||||
Attributes:~
|
||||
{async}
|
||||
@ -477,6 +481,84 @@ nvim_call_atomic({calls}) *nvim_call_atomic()*
|
||||
error ocurred, the values from all preceding calls will
|
||||
still be returned.
|
||||
|
||||
*nvim_parse_expression()*
|
||||
nvim_parse_expression({expr}, {flags}, {highlight})
|
||||
Parse a VimL expression
|
||||
|
||||
Attributes:~
|
||||
{async}
|
||||
|
||||
Parameters:~
|
||||
{expr} Expression to parse. Is always treated as a
|
||||
single line.
|
||||
{flags} Flags: - "m" if multiple expressions in a
|
||||
row are allowed (only the first one will be
|
||||
parsed), - "E" if EOC tokens are not allowed
|
||||
(determines whether they will stop parsing
|
||||
process or be recognized as an
|
||||
operator/space, though also yielding an
|
||||
error). - "l" when needing to start parsing
|
||||
with lvalues for ":let" or ":for". Common
|
||||
flag sets: - "m" to parse like for ":echo". -
|
||||
"E" to parse like for "<C-r>=". - empty
|
||||
string for ":call". - "lm" to parse for
|
||||
":let".
|
||||
{highlight} If true, return value will also include
|
||||
"highlight" key containing array of 4-tuples
|
||||
(arrays) (Integer, Integer, Integer, String),
|
||||
where first three numbers define the
|
||||
highlighted region and represent line,
|
||||
starting column and ending column (latter
|
||||
exclusive: one should highlight region
|
||||
[start_col, end_col)).
|
||||
|
||||
Return:~
|
||||
AST: top-level dictionary with these keys: "error":
|
||||
Dictionary with error, present only if parser saw some
|
||||
error. Contains the following keys: "message": String,
|
||||
error message in printf format, translated. Must contain
|
||||
exactly one "%.*s". "arg": String, error message argument.
|
||||
"len": Amount of bytes successfully parsed. With flags
|
||||
equal to "" that should be equal to the length of expr
|
||||
string. @note: “Sucessfully parsed” here means
|
||||
“participated in AST creation”, not “till the first
|
||||
error”. "ast": AST, either nil or a dictionary with these
|
||||
keys: "type": node type, one of the value names from
|
||||
ExprASTNodeType stringified without "kExprNode" prefix.
|
||||
"start": a pair [line, column] describing where node is
|
||||
“started” where "line" is always 0 (will not be 0 if you
|
||||
will be using nvim_parse_viml() on e.g. ":let", but that
|
||||
is not present yet). Both elements are Integers. "len":
|
||||
“length” of the node. This and "start" are there for
|
||||
debugging purposes primary (debugging parser and providing
|
||||
debug information). "children": a list of nodes described
|
||||
in top/"ast". There always is zero, one or two children,
|
||||
key will not be present if node has no children. Maximum
|
||||
number of children may be found in node_maxchildren array.
|
||||
Local values (present only for certain nodes): "scope": a
|
||||
single Integer, specifies scope for "Option" and
|
||||
"PlainIdentifier" nodes. For "Option" it is one of
|
||||
ExprOptScope values, for "PlainIdentifier" it is one of
|
||||
ExprVarScope values. "ident": identifier (without scope,
|
||||
if any), present for "Option", "PlainIdentifier",
|
||||
"PlainKey" and "Environment" nodes. "name": Integer,
|
||||
register name (one character) or -1. Only present for
|
||||
"Register" nodes. "cmp_type": String, comparison type, one
|
||||
of the value names from ExprComparisonType, stringified
|
||||
without "kExprCmp" prefix. Only present for "Comparison"
|
||||
nodes. "ccs_strategy": String, case comparison strategy,
|
||||
one of the value names from ExprCaseCompareStrategy,
|
||||
stringified without "kCCStrategy" prefix. Only present for
|
||||
"Comparison" nodes. "augmentation": String, augmentation
|
||||
type for "Assignment" nodes. Is either an empty string,
|
||||
"Add", "Subtract" or "Concat" for "=", "+=", "-=" or ".="
|
||||
respectively. "invert": Boolean, true if result of
|
||||
comparison needs to be inverted. Only present for
|
||||
"Comparison" nodes. "ivalue": Integer, integer value for
|
||||
"Integer" nodes. "fvalue": Float, floating-point value for
|
||||
"Float" nodes. "svalue": String, value for
|
||||
"SingleQuotedString" and "DoubleQuotedString" nodes.
|
||||
|
||||
nvim__id({obj}) *nvim__id()*
|
||||
Returns object given as argument
|
||||
|
||||
@ -717,9 +799,10 @@ nvim_buf_add_highlight({buffer}, {src_id}, {hl_group}, {line},
|
||||
or -1 for ungrouped highlight
|
||||
{hl_group} Name of the highlight group to use
|
||||
{line} Line to highlight (zero-indexed)
|
||||
{col_start} Start of range of columns to highlight
|
||||
{col_end} End of range of columns to highlight, or -1
|
||||
to highlight to end of line
|
||||
{col_start} Start of (byte-indexed) column range to
|
||||
highlight
|
||||
{col_end} End of (byte-indexed) column range to
|
||||
highlight, or -1 to highlight to end of line
|
||||
|
||||
Return:~
|
||||
The src_id that was used
|
||||
@ -953,9 +1036,6 @@ nvim_tabpage_is_valid({tabpage}) *nvim_tabpage_is_valid()*
|
||||
==============================================================================
|
||||
UI Functions *api-ui*
|
||||
|
||||
remote_ui_disconnect() *remote_ui_disconnect()*
|
||||
TODO: Documentation
|
||||
|
||||
nvim_ui_attach({width}, {height}, {options}) *nvim_ui_attach()*
|
||||
TODO: Documentation
|
||||
|
||||
@ -968,4 +1048,4 @@ nvim_ui_try_resize({width}, {height}) *nvim_ui_try_resize()*
|
||||
nvim_ui_set_option({name}, {value}) *nvim_ui_set_option()*
|
||||
TODO: Documentation
|
||||
|
||||
vim:tw=78:ts=8:ft=help:norl:
|
||||
vim:tw=78:ts=8:ft=help:norl:
|
||||
|
@ -259,13 +259,12 @@ Name triggered by ~
|
||||
|BufNew| just after creating a new buffer
|
||||
|
||||
|SwapExists| detected an existing swap file
|
||||
|TermOpen| when a terminal buffer is starting
|
||||
|TermClose| when a terminal buffer ends
|
||||
|TermOpen| when a terminal job starts
|
||||
|TermClose| when a terminal job ends
|
||||
|
||||
Options
|
||||
|FileType| when the 'filetype' option has been set
|
||||
|Syntax| when the 'syntax' option has been set
|
||||
|TermChanged| after the value of 'term' has changed
|
||||
|OptionSet| after setting any option
|
||||
|
||||
Startup and exit
|
||||
@ -933,26 +932,20 @@ TabEnter Just after entering a tab page. |tab-page|
|
||||
TabLeave Just before leaving a tab page. |tab-page|
|
||||
A WinLeave event will have been triggered
|
||||
first.
|
||||
{Nvim} *TabNew*
|
||||
*TabNew*
|
||||
TabNew When creating a new tab page. |tab-page|
|
||||
After WinEnter and before TabEnter.
|
||||
{Nvim} *TabNewEntered*
|
||||
*TabNewEntered*
|
||||
TabNewEntered After entering a new tab page. |tab-page|
|
||||
After BufEnter.
|
||||
{Nvim} *TabClosed*
|
||||
*TabClosed*
|
||||
TabClosed After closing a tab page. <afile> can be used
|
||||
for the tab page number.
|
||||
*TermChanged*
|
||||
TermChanged After the value of 'term' has changed. Useful
|
||||
for re-loading the syntax file to update the
|
||||
colors, fonts and other terminal-dependent
|
||||
settings. Executed for all loaded buffers.
|
||||
{Nvim} *TermClose*
|
||||
TermClose When a terminal buffer ends.
|
||||
{Nvim} *TermOpen*
|
||||
TermOpen When a terminal buffer is starting. This can
|
||||
be used to configure the terminal emulator by
|
||||
setting buffer variables. |terminal|
|
||||
*TermClose*
|
||||
TermClose When a |terminal| job ends.
|
||||
*TermOpen*
|
||||
TermOpen When a |terminal| job is starting. Can be
|
||||
used to configure the terminal buffer.
|
||||
*TermResponse*
|
||||
TermResponse After the response to |t_RV| is received from
|
||||
the terminal. The value of |v:termresponse|
|
||||
|
@ -4,9 +4,9 @@
|
||||
NVIM REFERENCE MANUAL by Thiago de Arruda
|
||||
|
||||
|
||||
Nvim's facilities for async io *channel*
|
||||
Nvim asynchronous IO *channel*
|
||||
|
||||
Type <M-]> to see the table of contents.
|
||||
Type |gO| to see the table of contents.
|
||||
|
||||
==============================================================================
|
||||
1. Introduction *channel-intro*
|
||||
@ -43,7 +43,7 @@ bytes. Additionally, for a job channel using rpc, bytes can still be
|
||||
read over its stderr. Similarily, only bytes can be written to nvim's own stderr.
|
||||
|
||||
*channel-callback* *buffered*
|
||||
*on_stdout* *on_stderr* *on_stdin* *on_data*
|
||||
*E5210* *on_stdout* *on_stderr* *on_stdin* *on_data*
|
||||
A callback function `on_{stream}` will be invoked with data read from the
|
||||
channel. By default, the callback will be invoked immediately when data is
|
||||
available, to facilitate interactive communication. The same callback will
|
||||
@ -52,7 +52,11 @@ Alternatively the `{stream}_buffered` option can be set to invoke the callback
|
||||
only when the underlying stream reaches EOF, and will then be passed in
|
||||
complete output. This is helpful when only the complete output is useful, and
|
||||
not partial data. Futhermore if `{stream}_buffered` is set but not a callback,
|
||||
the data is saved in the options dict, with the stream name as key.
|
||||
the data is saved in the options dict, with the stream name as key. For this
|
||||
to work a new options dict must be used for each opened channel. If a script
|
||||
uses a global `s:job_opts` dict, it can be copied with |copy()| before supplying
|
||||
it to |jobstart()|. If a dict is reused, so that the dict key already is
|
||||
occupied, error `E5210` will be raised.
|
||||
|
||||
- The arguments passed to the callback function are:
|
||||
|
||||
|
@ -22,6 +22,10 @@ Commands ~
|
||||
*:wv*
|
||||
*:wviminfo* Deprecated alias to |:wshada| command.
|
||||
|
||||
Environment Variables ~
|
||||
*$NVIM_LISTEN_ADDRESS* Deprecated in favor of |--listen|. If both are given,
|
||||
$NVIM_LISTEN_ADDRESS is ignored.
|
||||
|
||||
Events ~
|
||||
*EncodingChanged* Never fired; 'encoding' is always "utf-8".
|
||||
*FileEncoding* Never fired; equivalent to |EncodingChanged|.
|
||||
@ -37,8 +41,8 @@ Functions ~
|
||||
*file_readable()* Obsolete name for |filereadable()|.
|
||||
*highlight_exists()* Obsolete name for |hlexists()|.
|
||||
*highlightID()* Obsolete name for |hlID()|.
|
||||
*jobclose()* Obsolete name for |chanclose()|
|
||||
*jobsend()* Obsolete name for |chansend()|
|
||||
*jobclose()* Obsolete name for |chanclose()|
|
||||
*jobsend()* Obsolete name for |chansend()|
|
||||
*last_buffer_nr()* Obsolete name for bufnr("$").
|
||||
|
||||
Modifiers ~
|
||||
@ -48,8 +52,11 @@ Modifiers ~
|
||||
*:map-special* <> notation is always enabled. |cpo-<|
|
||||
|
||||
Options ~
|
||||
*'cscopeverbose'* Enabled by default. Use |:silent| instead.
|
||||
'gd'
|
||||
'gdefault' Enables the |:substitute| flag 'g' by default.
|
||||
*'fe'* 'fenc'+'enc' before Vim 6.0; no longer used.
|
||||
*'highlight'* *'hl'* Names of builtin |highlight-groups| cannot be changed.
|
||||
*'highlight'* *'hl'* Names of builtin |highlight-groups| cannot be changed.
|
||||
*'langnoremap'* Deprecated alias to 'nolangremap'.
|
||||
*'vi'*
|
||||
*'viminfo'* Deprecated alias to 'shada' option.
|
||||
|
@ -270,9 +270,9 @@ External UIs are expected to implement these common features:
|
||||
- Send the "super" key (Windows key, Apple key) as a |<D-| chord.
|
||||
|
||||
Implementation ~
|
||||
- Options can be monitored for changes by the |OptionSet| autocmd. E.g. if the
|
||||
user sets the 'guifont' option, this autocmd notifies channel 42: >
|
||||
autocmd OptionSet guifont call rpcnotify(42, 'option-changed', 'guifont', &guifont)
|
||||
- UI-related options ('guifont', 'ambiwidth', …) are published in the
|
||||
"option_set" |ui-global| event. The event is triggered when the UI first
|
||||
connects to Nvim and whenever an option is changed by the user or a plugin.
|
||||
|
||||
|
||||
vim:tw=78:ts=8:ft=help:norl:
|
||||
|
@ -562,16 +562,16 @@ list of the current window.
|
||||
buffer.
|
||||
Also see |++opt| and |+cmd|.
|
||||
|
||||
:[count]arge[dit][!] [++opt] [+cmd] {name} *:arge* *:argedit*
|
||||
Add {name} to the argument list and edit it.
|
||||
:[count]arge[dit][!] [++opt] [+cmd] {name} .. *:arge* *:argedit*
|
||||
Add {name}s to the argument list and edit it.
|
||||
When {name} already exists in the argument list, this
|
||||
entry is edited.
|
||||
This is like using |:argadd| and then |:edit|.
|
||||
Note that only one file name is allowed, and spaces
|
||||
inside the file name are allowed, like with |:edit|.
|
||||
Spaces in filenames have to be escaped with "\".
|
||||
[count] is used like with |:argadd|.
|
||||
[!] is required if the current file cannot be
|
||||
|abandon|ed.
|
||||
If the current file cannot be |abandon|ed {name}s will
|
||||
still be added to the argument list, but won't be
|
||||
edited. No check for duplicates is done.
|
||||
Also see |++opt| and |+cmd|.
|
||||
|
||||
:[count]arga[dd] {name} .. *:arga* *:argadd* *E479*
|
||||
|
@ -1559,10 +1559,10 @@ v:exception The value of the exception most recently caught and not
|
||||
< Output: "caught oops".
|
||||
|
||||
*v:false* *false-variable*
|
||||
v:false Special value used to put "false" in JSON and msgpack. See
|
||||
|json_encode()|. This value is converted to "v:false" when used
|
||||
as a String (e.g. in |expr5| with string concatenation
|
||||
operator) and to zero when used as a Number (e.g. in |expr5|
|
||||
v:false Special value used to put "false" in JSON and msgpack. See
|
||||
|json_encode()|. This value is converted to "v:false" when used
|
||||
as a String (e.g. in |expr5| with string concatenation
|
||||
operator) and to zero when used as a Number (e.g. in |expr5|
|
||||
or |expr7| when used with numeric operators). Read-only.
|
||||
|
||||
*v:fcs_reason* *fcs_reason-variable*
|
||||
@ -1703,16 +1703,16 @@ v:mouse_col Column number for a mouse click obtained with |getchar()|.
|
||||
value is zero when there was no mouse button click.
|
||||
|
||||
*v:msgpack_types* *msgpack_types-variable*
|
||||
v:msgpack_types Dictionary containing msgpack types used by |msgpackparse()|
|
||||
and |msgpackdump()|. All types inside dictionary are fixed
|
||||
(not editable) empty lists. To check whether some list is one
|
||||
v:msgpack_types Dictionary containing msgpack types used by |msgpackparse()|
|
||||
and |msgpackdump()|. All types inside dictionary are fixed
|
||||
(not editable) empty lists. To check whether some list is one
|
||||
of msgpack types, use |is| operator.
|
||||
|
||||
*v:null* *null-variable*
|
||||
v:null Special value used to put "null" in JSON and NIL in msgpack.
|
||||
See |json_encode()|. This value is converted to "v:null" when
|
||||
used as a String (e.g. in |expr5| with string concatenation
|
||||
operator) and to zero when used as a Number (e.g. in |expr5|
|
||||
v:null Special value used to put "null" in JSON and NIL in msgpack.
|
||||
See |json_encode()|. This value is converted to "v:null" when
|
||||
used as a String (e.g. in |expr5| with string concatenation
|
||||
operator) and to zero when used as a Number (e.g. in |expr5|
|
||||
or |expr7| when used with numeric operators). Read-only.
|
||||
|
||||
*v:oldfiles* *oldfiles-variable*
|
||||
@ -1788,9 +1788,9 @@ v:scrollstart String describing the script or function that caused the
|
||||
hit-enter prompt.
|
||||
|
||||
*v:servername* *servername-variable*
|
||||
*$NVIM_LISTEN_ADDRESS*
|
||||
v:servername Default Nvim server address. Equivalent to
|
||||
|$NVIM_LISTEN_ADDRESS| on startup. |serverstop()|
|
||||
v:servername Primary listen-address of the current Nvim instance, the first
|
||||
item returned by |serverlist()|. Can be set by |--listen| or
|
||||
|$NVIM_LISTEN_ADDRESS| at startup. |serverstart()| |serverstop()|
|
||||
Read-only.
|
||||
|
||||
|
||||
@ -1903,10 +1903,10 @@ v:throwpoint The point where the exception most recently caught and not
|
||||
< Output: "Exception from test.vim, line 2"
|
||||
|
||||
*v:true* *true-variable*
|
||||
v:true Special value used to put "true" in JSON and msgpack. See
|
||||
|json_encode()|. This value is converted to "v:true" when used
|
||||
as a String (e.g. in |expr5| with string concatenation
|
||||
operator) and to one when used as a Number (e.g. in |expr5| or
|
||||
v:true Special value used to put "true" in JSON and msgpack. See
|
||||
|json_encode()|. This value is converted to "v:true" when used
|
||||
as a String (e.g. in |expr5| with string concatenation
|
||||
operator) and to one when used as a Number (e.g. in |expr5| or
|
||||
|expr7| when used with numeric operators). Read-only.
|
||||
|
||||
*v:val* *val-variable*
|
||||
@ -2492,7 +2492,7 @@ assert_fails({cmd} [, {error}]) *assert_fails()*
|
||||
assert_false({actual} [, {msg}]) *assert_false()*
|
||||
When {actual} is not false an error message is added to
|
||||
|v:errors|, like with |assert_equal()|.
|
||||
A value is false when it is zero or |v:false|. When "{actual}"
|
||||
A value is false when it is zero or |v:false|. When "{actual}"
|
||||
is not a number or |v:false| the assert fails.
|
||||
When {msg} is omitted an error in the form
|
||||
"Expected False but got {actual}" is produced.
|
||||
@ -3182,7 +3182,7 @@ diff_hlID({lnum}, {col}) *diff_hlID()*
|
||||
empty({expr}) *empty()*
|
||||
Return the Number 1 if {expr} is empty, zero otherwise.
|
||||
A |List| or |Dictionary| is empty when it does not have any
|
||||
items. A Number is empty when its value is zero. Special
|
||||
items. A Number is empty when its value is zero. Special
|
||||
variable is empty when it is |v:false| or |v:null|.
|
||||
|
||||
escape({string}, {chars}) *escape()*
|
||||
@ -4327,17 +4327,25 @@ getqflist([{what}]) *getqflist()*
|
||||
If the optional {what} dictionary argument is supplied, then
|
||||
returns only the items listed in {what} as a dictionary. The
|
||||
following string items are supported in {what}:
|
||||
context get the context stored with |setqflist()|
|
||||
items quickfix list entries
|
||||
nr get information for this quickfix list; zero
|
||||
means the current quickfix list
|
||||
means the current quickfix list and '$' means
|
||||
the last quickfix list
|
||||
title get the list title
|
||||
winid get the |window-ID| (if opened)
|
||||
all all of the above quickfix properties
|
||||
Non-string items in {what} are ignored.
|
||||
If "nr" is not present then the current quickfix list is used.
|
||||
To get the number of lists in the quickfix stack, set 'nr' to
|
||||
'$' in {what}. The 'nr' value in the returned dictionary
|
||||
contains the quickfix stack size.
|
||||
In case of error processing {what}, an empty dictionary is
|
||||
returned.
|
||||
|
||||
The returned dictionary contains the following entries:
|
||||
context context information stored with |setqflist()|
|
||||
items quickfix list entries
|
||||
nr quickfix list number
|
||||
title quickfix list title text
|
||||
winid quickfix |window-ID| (if opened)
|
||||
@ -4749,7 +4757,7 @@ input({opts})
|
||||
string, or a blank string (for no prompt). A '\n' can be used
|
||||
in the prompt to start a new line.
|
||||
|
||||
In the second form it accepts a single dictionary with the
|
||||
In the second form it accepts a single dictionary with the
|
||||
following keys, any of which may be omitted:
|
||||
|
||||
Key Default Description ~
|
||||
@ -4757,7 +4765,7 @@ input({opts})
|
||||
default "" Same as {text} in the first form.
|
||||
completion nothing Same as {completion} in the first form.
|
||||
cancelreturn "" Same as {cancelreturn} from
|
||||
|inputdialog()|. Also works with
|
||||
|inputdialog()|. Also works with
|
||||
input().
|
||||
highlight nothing Highlight handler: |Funcref|.
|
||||
|
||||
@ -4833,8 +4841,8 @@ input({opts})
|
||||
modifier. If the function causes any errors, it will be
|
||||
skipped for the duration of the current input() call.
|
||||
|
||||
Currently coloring is disabled when command-line contains
|
||||
arabic characters.
|
||||
Highlighting is disabled if command-line contains arabic
|
||||
characters.
|
||||
|
||||
NOTE: This function must not be used in a startup file, for
|
||||
the versions that only run in GUI mode (e.g., the Win32 GUI).
|
||||
@ -4948,19 +4956,19 @@ islocked({expr}) *islocked()* *E786*
|
||||
message. Use |exists()| to check for existence.
|
||||
|
||||
id({expr}) *id()*
|
||||
Returns a |String| which is a unique identifier of the
|
||||
container type (|List|, |Dict| and |Partial|). It is
|
||||
guaranteed that for the mentioned types `id(v1) ==# id(v2)`
|
||||
returns true iff `type(v1) == type(v2) && v1 is v2` (note:
|
||||
|v:_null_list| and |v:_null_dict| have the same `id()` with
|
||||
different types because they are internally represented as
|
||||
a NULL pointers). Currently `id()` returns a hexadecimal
|
||||
representanion of the pointers to the containers (i.e. like
|
||||
`0x994a40`), same as `printf("%p", {expr})`, but it is advised
|
||||
Returns a |String| which is a unique identifier of the
|
||||
container type (|List|, |Dict| and |Partial|). It is
|
||||
guaranteed that for the mentioned types `id(v1) ==# id(v2)`
|
||||
returns true iff `type(v1) == type(v2) && v1 is v2` (note:
|
||||
|v:_null_list| and |v:_null_dict| have the same `id()` with
|
||||
different types because they are internally represented as
|
||||
a NULL pointers). Currently `id()` returns a hexadecimal
|
||||
representanion of the pointers to the containers (i.e. like
|
||||
`0x994a40`), same as `printf("%p", {expr})`, but it is advised
|
||||
against counting on exact format of return value.
|
||||
|
||||
It is not guaranteed that `id(no_longer_existing_container)`
|
||||
will not be equal to some other `id()`: new containers may
|
||||
It is not guaranteed that `id(no_longer_existing_container)`
|
||||
will not be equal to some other `id()`: new containers may
|
||||
reuse identifiers of the garbage-collected ones.
|
||||
|
||||
items({dict}) *items()*
|
||||
@ -5071,14 +5079,14 @@ join({list} [, {sep}]) *join()*
|
||||
The opposite function is |split()|.
|
||||
|
||||
json_decode({expr}) *json_decode()*
|
||||
Convert {expr} from JSON object. Accepts |readfile()|-style
|
||||
list as the input, as well as regular string. May output any
|
||||
Convert {expr} from JSON object. Accepts |readfile()|-style
|
||||
list as the input, as well as regular string. May output any
|
||||
Vim value. In the following cases it will output
|
||||
|msgpack-special-dict|:
|
||||
1. Dictionary contains duplicate key.
|
||||
2. Dictionary contains empty key.
|
||||
3. String contains NUL byte. Two special dictionaries: for
|
||||
dictionary and for string will be emitted in case string
|
||||
3. String contains NUL byte. Two special dictionaries: for
|
||||
dictionary and for string will be emitted in case string
|
||||
with NUL byte was a dictionary key.
|
||||
|
||||
Note: function treats its input as UTF-8 always. The JSON
|
||||
@ -5087,14 +5095,14 @@ json_decode({expr}) *json_decode()*
|
||||
Non-UTF-8 characters are an error.
|
||||
|
||||
json_encode({expr}) *json_encode()*
|
||||
Convert {expr} into a JSON string. Accepts
|
||||
|msgpack-special-dict| as the input. Will not convert
|
||||
|Funcref|s, mappings with non-string keys (can be created as
|
||||
|msgpack-special-dict|), values with self-referencing
|
||||
containers, strings which contain non-UTF-8 characters,
|
||||
pseudo-UTF-8 strings which contain codepoints reserved for
|
||||
surrogate pairs (such strings are not valid UTF-8 strings).
|
||||
Non-printable characters are converted into "\u1234" escapes
|
||||
Convert {expr} into a JSON string. Accepts
|
||||
|msgpack-special-dict| as the input. Will not convert
|
||||
|Funcref|s, mappings with non-string keys (can be created as
|
||||
|msgpack-special-dict|), values with self-referencing
|
||||
containers, strings which contain non-UTF-8 characters,
|
||||
pseudo-UTF-8 strings which contain codepoints reserved for
|
||||
surrogate pairs (such strings are not valid UTF-8 strings).
|
||||
Non-printable characters are converted into "\u1234" escapes
|
||||
or special escapes like "\t", other are dumped as-is.
|
||||
|
||||
keys({dict}) *keys()*
|
||||
@ -5193,7 +5201,7 @@ line({expr}) The result is a Number, which is the line number of the file
|
||||
This autocommand jumps to the last known position in a file
|
||||
just after opening it, if the '" mark is set: >
|
||||
:au BufReadPost *
|
||||
\ if line("'\"") > 1 && line("'\"") <= line("$") && &ft !~# 'commit'
|
||||
\ if line("'\"") > 1 && line("'\"") <= line("$") && &ft !~# 'commit'
|
||||
\ | exe "normal! g`\""
|
||||
\ | endif
|
||||
|
||||
@ -5244,7 +5252,7 @@ log10({expr}) *log10()*
|
||||
< -2.0
|
||||
|
||||
luaeval({expr}[, {expr}])
|
||||
Evaluate Lua expression {expr} and return its result converted
|
||||
Evaluate Lua expression {expr} and return its result converted
|
||||
to Vim data structures. See |lua-luaeval| for more details.
|
||||
|
||||
map({expr1}, {expr2}) *map()*
|
||||
@ -5493,7 +5501,7 @@ matchaddpos({group}, {pos} [, {priority} [, {id} [, {dict}]]])
|
||||
sets buffer line boundaries to redraw screen. It is supposed
|
||||
to be used when fast match additions and deletions are
|
||||
required, for example to highlight matching parentheses.
|
||||
|
||||
*E5030* *E5031*
|
||||
The list {pos} can contain one of these items:
|
||||
- A number. This whole line will be highlighted. The first
|
||||
line has number 1.
|
||||
@ -5507,6 +5515,10 @@ matchaddpos({group}, {pos} [, {priority} [, {id} [, {dict}]]])
|
||||
- A list with three numbers, e.g., [23, 11, 3]. As above, but
|
||||
the third number gives the length of the highlight in bytes.
|
||||
|
||||
Entries with zero and negative line numbers are silently
|
||||
ignored, as well as entries with negative column numbers and
|
||||
lengths.
|
||||
|
||||
The maximum number of positions is 8.
|
||||
|
||||
Example: >
|
||||
@ -5675,7 +5687,7 @@ mkdir({name} [, {path} [, {prot}]])
|
||||
:call mkdir($HOME . "/tmp/foo/bar", "p", 0700)
|
||||
< This function is not available in the |sandbox|.
|
||||
|
||||
If you try to create an existing directory with {path} set to
|
||||
If you try to create an existing directory with {path} set to
|
||||
"p" mkdir() will silently exit.
|
||||
|
||||
*mode()*
|
||||
@ -5728,78 +5740,76 @@ msgpackdump({list}) {Nvim} *msgpackdump()*
|
||||
5. Points 3. and 4. do not apply to |msgpack-special-dict|s.
|
||||
|
||||
msgpackparse({list}) {Nvim} *msgpackparse()*
|
||||
Convert a |readfile()|-style list to a list of VimL objects.
|
||||
Convert a |readfile()|-style list to a list of VimL objects.
|
||||
Example: >
|
||||
let fname = expand('~/.config/nvim/shada/main.shada')
|
||||
let mpack = readfile(fname, 'b')
|
||||
let shada_objects = msgpackparse(mpack)
|
||||
< This will read ~/.config/nvim/shada/main.shada file to
|
||||
< This will read ~/.config/nvim/shada/main.shada file to
|
||||
`shada_objects` list.
|
||||
|
||||
Limitations:
|
||||
1. Mapping ordering is not preserved unless messagepack
|
||||
mapping is dumped using generic mapping
|
||||
1. Mapping ordering is not preserved unless messagepack
|
||||
mapping is dumped using generic mapping
|
||||
(|msgpack-special-map|).
|
||||
2. Since the parser aims to preserve all data untouched
|
||||
(except for 1.) some strings are parsed to
|
||||
|msgpack-special-dict| format which is not convenient to
|
||||
2. Since the parser aims to preserve all data untouched
|
||||
(except for 1.) some strings are parsed to
|
||||
|msgpack-special-dict| format which is not convenient to
|
||||
use.
|
||||
*msgpack-special-dict*
|
||||
Some messagepack strings may be parsed to special
|
||||
Some messagepack strings may be parsed to special
|
||||
dictionaries. Special dictionaries are dictionaries which
|
||||
|
||||
1. Contain exactly two keys: `_TYPE` and `_VAL`.
|
||||
2. `_TYPE` key is one of the types found in |v:msgpack_types|
|
||||
2. `_TYPE` key is one of the types found in |v:msgpack_types|
|
||||
variable.
|
||||
3. Value for `_VAL` has the following format (Key column
|
||||
3. Value for `_VAL` has the following format (Key column
|
||||
contains name of the key from |v:msgpack_types|):
|
||||
|
||||
Key Value ~
|
||||
nil Zero, ignored when dumping. This value cannot
|
||||
possibly appear in |msgpackparse()| output in Neovim
|
||||
versions which have |v:null|.
|
||||
boolean One or zero. When dumping it is only checked that
|
||||
value is a |Number|. This value cannot possibly
|
||||
appear in |msgpackparse()| output in Neovim versions
|
||||
which have |v:true| and |v:false|.
|
||||
integer |List| with four numbers: sign (-1 or 1), highest two
|
||||
bits, number with bits from 62nd to 31st, lowest 31
|
||||
bits. I.e. to get actual number one will need to use
|
||||
nil Zero, ignored when dumping. Not returned by
|
||||
|msgpackparse()| since |v:null| was introduced.
|
||||
boolean One or zero. When dumping it is only checked that
|
||||
value is a |Number|. Not returned by |msgpackparse()|
|
||||
since |v:true| and |v:false| were introduced.
|
||||
integer |List| with four numbers: sign (-1 or 1), highest two
|
||||
bits, number with bits from 62nd to 31st, lowest 31
|
||||
bits. I.e. to get actual number one will need to use
|
||||
code like >
|
||||
_VAL[0] * ((_VAL[1] << 62)
|
||||
& (_VAL[2] << 31)
|
||||
& _VAL[3])
|
||||
< Special dictionary with this type will appear in
|
||||
|msgpackparse()| output under one of the following
|
||||
< Special dictionary with this type will appear in
|
||||
|msgpackparse()| output under one of the following
|
||||
circumstances:
|
||||
1. |Number| is 32-bit and value is either above
|
||||
1. |Number| is 32-bit and value is either above
|
||||
INT32_MAX or below INT32_MIN.
|
||||
2. |Number| is 64-bit and value is above INT64_MAX. It
|
||||
cannot possibly be below INT64_MIN because msgpack
|
||||
2. |Number| is 64-bit and value is above INT64_MAX. It
|
||||
cannot possibly be below INT64_MIN because msgpack
|
||||
C parser does not support such values.
|
||||
float |Float|. This value cannot possibly appear in
|
||||
float |Float|. This value cannot possibly appear in
|
||||
|msgpackparse()| output.
|
||||
string |readfile()|-style list of strings. This value will
|
||||
appear in |msgpackparse()| output if string contains
|
||||
zero byte or if string is a mapping key and mapping is
|
||||
being represented as special dictionary for other
|
||||
string |readfile()|-style list of strings. This value will
|
||||
appear in |msgpackparse()| output if string contains
|
||||
zero byte or if string is a mapping key and mapping is
|
||||
being represented as special dictionary for other
|
||||
reasons.
|
||||
binary |readfile()|-style list of strings. This value will
|
||||
appear in |msgpackparse()| output if binary string
|
||||
binary |readfile()|-style list of strings. This value will
|
||||
appear in |msgpackparse()| output if binary string
|
||||
contains zero byte.
|
||||
array |List|. This value cannot appear in |msgpackparse()|
|
||||
array |List|. This value cannot appear in |msgpackparse()|
|
||||
output.
|
||||
*msgpack-special-map*
|
||||
map |List| of |List|s with two items (key and value) each.
|
||||
This value will appear in |msgpackparse()| output if
|
||||
map |List| of |List|s with two items (key and value) each.
|
||||
This value will appear in |msgpackparse()| output if
|
||||
parsed mapping contains one of the following keys:
|
||||
1. Any key that is not a string (including keys which
|
||||
1. Any key that is not a string (including keys which
|
||||
are binary strings).
|
||||
2. String with NUL byte inside.
|
||||
3. Duplicate key.
|
||||
4. Empty key.
|
||||
ext |List| with two values: first is a signed integer
|
||||
representing extension type. Second is
|
||||
ext |List| with two values: first is a signed integer
|
||||
representing extension type. Second is
|
||||
|readfile()|-style list of strings.
|
||||
|
||||
nextnonblank({lnum}) *nextnonblank()*
|
||||
@ -6073,11 +6083,11 @@ pumvisible() *pumvisible()*
|
||||
py3eval({expr}) *py3eval()*
|
||||
Evaluate Python expression {expr} and return its result
|
||||
converted to Vim data structures.
|
||||
Numbers and strings are returned as they are (strings are
|
||||
copied though, Unicode strings are additionally converted to
|
||||
Numbers and strings are returned as they are (strings are
|
||||
copied though, Unicode strings are additionally converted to
|
||||
UTF-8).
|
||||
Lists are represented as Vim |List| type.
|
||||
Dictionaries are represented as Vim |Dictionary| type with
|
||||
Dictionaries are represented as Vim |Dictionary| type with
|
||||
keys converted to strings.
|
||||
{only available when compiled with the |+python3| feature}
|
||||
|
||||
@ -6145,7 +6155,7 @@ readfile({fname} [, {binary} [, {max}]])
|
||||
reltime([{start} [, {end}]]) *reltime()*
|
||||
Return an item that represents a time value. The format of
|
||||
the item depends on the system. It can be passed to
|
||||
|reltimestr()| to convert it to a string or |reltimefloat()|
|
||||
|reltimestr()| to convert it to a string or |reltimefloat()|
|
||||
to convert to a float.
|
||||
|
||||
Without an argument it returns the current "relative time", an
|
||||
@ -6628,15 +6638,11 @@ server2client({clientid}, {string}) *server2client()*
|
||||
:echo server2client(expand("<client>"), "HELLO")
|
||||
<
|
||||
serverlist() *serverlist()*
|
||||
Returns a list of available server names in a list.
|
||||
When there are no servers an empty string is returned.
|
||||
Returns a list of server addresses, or empty if all servers
|
||||
were stopped. |serverstart()| |serverstop()|
|
||||
Example: >
|
||||
:echo serverlist()
|
||||
< {Nvim} *--serverlist*
|
||||
The Vim command-line option `--serverlist` was removed from
|
||||
Nvim, but it can be imitated: >
|
||||
nvim --cmd "echo serverlist()" --cmd "q"
|
||||
<
|
||||
|
||||
serverstart([{address}]) *serverstart()*
|
||||
Opens a socket or named pipe at {address} and listens for
|
||||
|RPC| messages. Clients can send |API| commands to the address
|
||||
@ -6664,13 +6670,9 @@ serverstart([{address}]) *serverstart()*
|
||||
|
||||
< |$NVIM_LISTEN_ADDRESS| is set to {address} if not already set.
|
||||
|
||||
*--servername*
|
||||
The Vim command-line option `--servername` can be imitated: >
|
||||
nvim --cmd "let g:server_addr = serverstart('foo')"
|
||||
<
|
||||
serverstop({address}) *serverstop()*
|
||||
Closes the pipe or socket at {address}. Does nothing if
|
||||
{address} is empty or invalid.
|
||||
Closes the pipe or socket at {address}.
|
||||
Returns TRUE if {address} is valid, else FALSE.
|
||||
If |$NVIM_LISTEN_ADDRESS| is stopped it is unset.
|
||||
If |v:servername| is stopped it is set to the next available
|
||||
address returned by |serverlist()|.
|
||||
@ -6843,6 +6845,7 @@ setqflist({list} [, {action}[, {what}]]) *setqflist()*
|
||||
nr error number
|
||||
text description of the error
|
||||
type single-character error type, 'E', 'W', etc.
|
||||
valid recognized error message
|
||||
|
||||
The "col", "vcol", "nr", "type" and "text" entries are
|
||||
optional. Either "lnum" or "pattern" entry can be used to
|
||||
@ -6852,21 +6855,26 @@ setqflist({list} [, {action}[, {what}]]) *setqflist()*
|
||||
item will not be handled as an error line.
|
||||
If both "pattern" and "lnum" are present then "pattern" will
|
||||
be used.
|
||||
If the "valid" entry is not supplied, then the valid flag is
|
||||
set when "bufnr" is a valid buffer or "filename" exists.
|
||||
If you supply an empty {list}, the quickfix list will be
|
||||
cleared.
|
||||
Note that the list is not exactly the same as what
|
||||
|getqflist()| returns.
|
||||
|
||||
*E927*
|
||||
If {action} is set to 'a', then the items from {list} are
|
||||
added to the existing quickfix list. If there is no existing
|
||||
list, then a new list is created.
|
||||
{action} values: *E927*
|
||||
'a' The items from {list} are added to the existing
|
||||
quickfix list. If there is no existing list, then a
|
||||
new list is created.
|
||||
|
||||
If {action} is set to 'r', then the items from the current
|
||||
quickfix list are replaced with the items from {list}. This
|
||||
can also be used to clear the list: >
|
||||
:call setqflist([], 'r')
|
||||
'r' The items from the current quickfix list are replaced
|
||||
with the items from {list}. This can also be used to
|
||||
clear the list: >
|
||||
:call setqflist([], 'r')
|
||||
<
|
||||
'f' All the quickfix lists in the quickfix stack are
|
||||
freed.
|
||||
|
||||
If {action} is not present or is set to ' ', then a new list
|
||||
is created.
|
||||
|
||||
@ -6877,7 +6885,12 @@ setqflist({list} [, {action}[, {what}]]) *setqflist()*
|
||||
only the items listed in {what} are set. The first {list}
|
||||
argument is ignored. The following items can be specified in
|
||||
{what}:
|
||||
nr list number in the quickfix stack
|
||||
context any Vim type can be stored as a context
|
||||
items list of quickfix entries. Same as the {list}
|
||||
argument.
|
||||
nr list number in the quickfix stack; zero
|
||||
means the current quickfix list and '$' means
|
||||
the last quickfix list
|
||||
title quickfix list title text
|
||||
Unsupported keys in {what} are ignored.
|
||||
If the "nr" item is not present, then the current quickfix list
|
||||
@ -6929,9 +6942,9 @@ setreg({regname}, {value} [, {options}])
|
||||
:call setreg('a', "1\n2\n3", 'b5')
|
||||
|
||||
< This example shows using the functions to save and restore a
|
||||
register (note: you may not reliably restore register value
|
||||
without using the third argument to |getreg()| as without it
|
||||
newlines are represented as newlines AND Nul bytes are
|
||||
register (note: you may not reliably restore register value
|
||||
without using the third argument to |getreg()| as without it
|
||||
newlines are represented as newlines AND Nul bytes are
|
||||
represented as newlines as well, see |NL-used-for-Nul|). >
|
||||
:let var_a = getreg('a', 1, 1)
|
||||
:let var_amode = getregtype('a')
|
||||
@ -6982,18 +6995,22 @@ shellescape({string} [, {special}]) *shellescape()*
|
||||
quotes within {string}.
|
||||
Otherwise, it will enclose {string} in single quotes and
|
||||
replace all "'" with "'\''".
|
||||
|
||||
When the {special} argument is present and it's a non-zero
|
||||
Number or a non-empty String (|non-zero-arg|), then special
|
||||
items such as "!", "%", "#" and "<cword>" will be preceded by
|
||||
a backslash. This backslash will be removed again by the |:!|
|
||||
command.
|
||||
|
||||
The "!" character will be escaped (again with a |non-zero-arg|
|
||||
{special}) when 'shell' contains "csh" in the tail. That is
|
||||
because for csh and tcsh "!" is used for history replacement
|
||||
even when inside single quotes.
|
||||
The <NL> character is also escaped. With a |non-zero-arg|
|
||||
{special} and 'shell' containing "csh" in the tail it's
|
||||
|
||||
With a |non-zero-arg| {special} the <NL> character is also
|
||||
escaped. When 'shell' containing "csh" in the tail it's
|
||||
escaped a second time.
|
||||
|
||||
Example of use with a |:!| command: >
|
||||
:exe '!dir ' . shellescape(expand('<cfile>'), 1)
|
||||
< This results in a directory listing for the file under the
|
||||
@ -7369,20 +7386,20 @@ string({expr}) Return {expr} converted to a String. If {expr} is a Number,
|
||||
{expr} type result ~
|
||||
String 'string'
|
||||
Number 123
|
||||
Float 123.123456 or 1.123456e8 or
|
||||
Float 123.123456 or 1.123456e8 or
|
||||
`str2float('inf')`
|
||||
Funcref `function('name')`
|
||||
List [item, item]
|
||||
Dictionary {key: value, key: value}
|
||||
Note that in String values the ' character is doubled.
|
||||
Also see |strtrans()|.
|
||||
Note 2: Output format is mostly compatible with YAML, except
|
||||
for infinite and NaN floating-point values representations
|
||||
which use |str2float()|. Strings are also dumped literally,
|
||||
only single quote is escaped, which does not allow using YAML
|
||||
for parsing back binary strings. |eval()| should always work for
|
||||
strings and floats though and this is the only official
|
||||
method, use |msgpackdump()| or |json_encode()| if you need to
|
||||
Note 2: Output format is mostly compatible with YAML, except
|
||||
for infinite and NaN floating-point values representations
|
||||
which use |str2float()|. Strings are also dumped literally,
|
||||
only single quote is escaped, which does not allow using YAML
|
||||
for parsing back binary strings. |eval()| should always work for
|
||||
strings and floats though and this is the only official
|
||||
method, use |msgpackdump()| or |json_encode()| if you need to
|
||||
share data with other application.
|
||||
|
||||
*strlen()*
|
||||
@ -7577,17 +7594,29 @@ synIDtrans({synID}) *synIDtrans()*
|
||||
":highlight link" are followed.
|
||||
|
||||
synconcealed({lnum}, {col}) *synconcealed()*
|
||||
The result is a List. The first item in the list is 0 if the
|
||||
character at the position {lnum} and {col} is not part of a
|
||||
concealable region, 1 if it is. The second item in the list is
|
||||
a string. If the first item is 1, the second item contains the
|
||||
text which will be displayed in place of the concealed text,
|
||||
depending on the current setting of 'conceallevel'. The third
|
||||
and final item in the list is a unique number representing the
|
||||
specific syntax region matched. This allows detection of the
|
||||
beginning of a new concealable region if there are two
|
||||
consecutive regions with the same replacement character.
|
||||
For an example use see $VIMRUNTIME/syntax/2html.vim .
|
||||
The result is a List with currently three items:
|
||||
1. The first item in the list is 0 if the character at the
|
||||
position {lnum} and {col} is not part of a concealable
|
||||
region, 1 if it is.
|
||||
2. The second item in the list is a string. If the first item
|
||||
is 1, the second item contains the text which will be
|
||||
displayed in place of the concealed text, depending on the
|
||||
current setting of 'conceallevel' and 'listchars'.
|
||||
3. The third and final item in the list is a number
|
||||
representing the specific syntax region matched in the
|
||||
line. When the character is not concealed the value is
|
||||
zero. This allows detection of the beginning of a new
|
||||
concealable region if there are two consecutive regions
|
||||
with the same replacement character. For an example, if
|
||||
the text is "123456" and both "23" and "45" are concealed
|
||||
and replace by the character "X", then:
|
||||
call returns ~
|
||||
synconcealed(lnum, 1) [0, '', 0]
|
||||
synconcealed(lnum, 2) [1, 'X', 1]
|
||||
synconcealed(lnum, 3) [1, 'X', 1]
|
||||
synconcealed(lnum, 4) [1, 'X', 2]
|
||||
synconcealed(lnum, 5) [1, 'X', 2]
|
||||
synconcealed(lnum, 6) [0, '', 0]
|
||||
|
||||
|
||||
synstack({lnum}, {col}) *synstack()*
|
||||
@ -7620,6 +7649,9 @@ system({cmd} [, {input}]) *system()* *E677*
|
||||
|writefile()| does with {binary} set to "b" (i.e. with
|
||||
a newline between each list item, and newlines inside list
|
||||
items converted to NULs).
|
||||
When {input} is given and is a valid buffer id, the content of
|
||||
the buffer is written to the file line by line, each line
|
||||
terminated by a NL (and NUL where the text has NL).
|
||||
*E5677*
|
||||
Note: system() cannot write to or read from backgrounded ("&")
|
||||
shell commands, e.g.: >
|
||||
@ -7630,10 +7662,10 @@ system({cmd} [, {input}]) *system()* *E677*
|
||||
redirection syntax) before input can reach it. Use
|
||||
|jobstart()| instead.
|
||||
|
||||
Note: Use |shellescape()| or |::S| with |expand()| or
|
||||
|fnamemodify()| to escape special characters in a command
|
||||
argument. Newlines in {cmd} may cause the command to fail.
|
||||
The characters in 'shellquote' and 'shellxquote' may also
|
||||
Note: Use |shellescape()| or |::S| with |expand()| or
|
||||
|fnamemodify()| to escape special characters in a command
|
||||
argument. Newlines in {cmd} may cause the command to fail.
|
||||
The characters in 'shellquote' and 'shellxquote' may also
|
||||
cause trouble.
|
||||
|
||||
The result is a String. Example: >
|
||||
@ -7660,9 +7692,9 @@ system({cmd} [, {input}]) *system()* *E677*
|
||||
|
||||
|
||||
systemlist({cmd} [, {input} [, {keepempty}]]) *systemlist()*
|
||||
Same as |system()|, but returns a |List| with lines (parts of
|
||||
output separated by NL) with NULs transformed into NLs. Output
|
||||
is the same as |readfile()| will output with {binary} argument
|
||||
Same as |system()|, but returns a |List| with lines (parts of
|
||||
output separated by NL) with NULs transformed into NLs. Output
|
||||
is the same as |readfile()| will output with {binary} argument
|
||||
set to "b", except that a final newline is not preserved,
|
||||
unless {keepempty} is non-zero.
|
||||
Note that on MS-Windows you may get trailing CR characters.
|
||||
@ -7926,7 +7958,7 @@ type({expr}) *type()*
|
||||
:if type(myvar) == type({})
|
||||
:if type(myvar) == type(0.0)
|
||||
:if type(myvar) == type(v:true)
|
||||
< In place of checking for |v:null| type it is better to check
|
||||
< In place of checking for |v:null| type it is better to check
|
||||
for |v:null| directly as it is the only value of this type: >
|
||||
:if myvar is v:null
|
||||
< To check if the v:t_ variables exist use this: >
|
||||
@ -8243,10 +8275,10 @@ writefile({list}, {fname} [, {flags}])
|
||||
: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
|
||||
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.
|
||||
@ -8414,6 +8446,7 @@ win32 Windows version of Vim (32 or 64 bit).
|
||||
winaltkeys Compiled with 'winaltkeys' option.
|
||||
windows Compiled with support for more than one window.
|
||||
writebackup Compiled with 'writebackup' default on.
|
||||
wsl WSL (Windows Subsystem for Linux) version of Vim.
|
||||
|
||||
*string-match*
|
||||
Matching a pattern in a String
|
||||
@ -8728,7 +8761,7 @@ like this: >
|
||||
|
||||
When such a function is called, and it is not defined yet, Vim will search the
|
||||
"autoload" directories in 'runtimepath' for a script file called
|
||||
"filename.vim". For example "~/.config/nvim/autoload/filename.vim". That
|
||||
"filename.vim". For example "~/.config/nvim/autoload/filename.vim". That
|
||||
file should then define the function like this: >
|
||||
|
||||
function filename#funcname()
|
||||
@ -8889,11 +8922,6 @@ This does NOT work: >
|
||||
value and the global value are changed.
|
||||
Example: >
|
||||
:let &path = &path . ',/usr/local/include'
|
||||
< This also works for terminal codes in the form t_xx.
|
||||
But only for alphanumerical names. Example: >
|
||||
:let &t_k1 = "\<Esc>[234;"
|
||||
< When the code does not exist yet it will be created as
|
||||
a terminal key code, there is no error.
|
||||
|
||||
:let &{option-name} .= {expr1}
|
||||
For a string option: Append {expr1} to the value.
|
||||
@ -9004,8 +9032,8 @@ This does NOT work: >
|
||||
< *E741* *E940*
|
||||
If you try to change a locked variable you get an
|
||||
error message: "E741: Value is locked: {name}".
|
||||
If you try to lock or unlock a built-in variable you
|
||||
will get an error message "E940: Cannot lock or unlock
|
||||
If you try to lock or unlock a built-in variable you
|
||||
will get an error message "E940: Cannot lock or unlock
|
||||
variable {name}".
|
||||
|
||||
[depth] is relevant when locking a |List| or
|
||||
@ -9264,17 +9292,17 @@ This does NOT work: >
|
||||
with the |:redraw| command. Example: >
|
||||
:new | redraw | echo "there is a new window"
|
||||
< *:echo-self-refer*
|
||||
When printing nested containers echo prints second
|
||||
occurrence of the self-referencing container using
|
||||
"[...@level]" (self-referencing |List|) or
|
||||
When printing nested containers echo prints second
|
||||
occurrence of the self-referencing container using
|
||||
"[...@level]" (self-referencing |List|) or
|
||||
"{...@level}" (self-referencing |Dict|): >
|
||||
:let l = []
|
||||
:call add(l, l)
|
||||
:let l2 = []
|
||||
:call add(l2, [l2])
|
||||
:echo l l2
|
||||
< echoes "[[...@0]] [[[...@0]]]". Echoing "[l]" will
|
||||
echo "[[[...@1]]]" because l first occurs at second
|
||||
< echoes "[[...@0]] [[[...@0]]]". Echoing "[l]" will
|
||||
echo "[[[...@1]]]" because l first occurs at second
|
||||
level.
|
||||
|
||||
*:echon*
|
||||
@ -10505,18 +10533,19 @@ missing: >
|
||||
|
||||
To execute a command only when the |+eval| feature is disabled requires a trick,
|
||||
as this example shows: >
|
||||
if 1
|
||||
nnoremap : :"
|
||||
endif
|
||||
normal :set history=111<CR>
|
||||
if 1
|
||||
nunmap :
|
||||
endif
|
||||
|
||||
silent! while 0
|
||||
set history=111
|
||||
silent! endwhile
|
||||
|
||||
When the |+eval| feature is available the command is skipped because of the
|
||||
"while 0". Without the |+eval| feature the "while 0" is an error, which is
|
||||
silently ignored, and the command is executed.
|
||||
|
||||
The "<CR>" here is a real CR character, type CTRL-V Enter to get it.
|
||||
|
||||
When the |+eval| feature is available the ":" is remapped to add a double
|
||||
quote, which has the effect of commenting-out the command. without the
|
||||
quote, which has the effect of commenting-out the command. Without the
|
||||
|+eval| feature the nnoremap command is skipped and the command is executed.
|
||||
|
||||
==============================================================================
|
||||
@ -10563,7 +10592,7 @@ option will still be marked as it was set in the sandbox.
|
||||
In a few situations it is not allowed to change the text in the buffer, jump
|
||||
to another window and some other things that might confuse or break what Vim
|
||||
is currently doing. This mostly applies to things that happen when Vim is
|
||||
actually doing something else. For example, evaluating the 'balloonexpr' may
|
||||
actually doing something else. For example, evaluating the 'balloonexpr' may
|
||||
happen any moment the mouse cursor is resting at some position.
|
||||
|
||||
This is not allowed when the textlock is active:
|
||||
@ -10573,5 +10602,123 @@ This is not allowed when the textlock is active:
|
||||
- closing a window or quitting Vim
|
||||
- etc.
|
||||
|
||||
==============================================================================
|
||||
13. Command-line expressions highlighting *expr-highlight*
|
||||
|
||||
Expressions entered by the user in |i_CTRL-R_=|, |c_CTRL-\_e|, |quote=| are
|
||||
highlighted by the built-in expressions parser. It uses highlight groups
|
||||
described in the table below, which may be overriden by colorschemes.
|
||||
*hl-NvimInvalid*
|
||||
Besides the "Nvim"-prefixed highlight groups described below, there are
|
||||
"NvimInvalid"-prefixed highlight groups which have the same meaning but
|
||||
indicate that the token contains an error or that an error occurred just
|
||||
before it. They have mostly the same hierarchy, except that (by default) in
|
||||
place of any non-Nvim-prefixed group NvimInvalid linking to `Error` is used
|
||||
and some other intermediate groups are present.
|
||||
|
||||
Group Default link Colored expression ~
|
||||
*hl-NvimInternalError* None, red/red Parser bug
|
||||
|
||||
*hl-NvimAssignment* Operator Generic assignment
|
||||
*hl-NvimPlainAssignment* NvimAssignment `=` in |:let|
|
||||
*hl-NvimAugmentedAssignment* NvimAssignment Generic, `+=`/`-=`/`.=`
|
||||
*hl-NvimAssignmentWithAddition* NvimAugmentedAssignment `+=` in |:let+=|
|
||||
*hl-NvimAssignmentWithSubtraction* NvimAugmentedAssignment `-=` in |:let-=|
|
||||
*hl-NvimAssignmentWithConcatenation* NvimAugmentedAssignment `.=` in |:let.=|
|
||||
|
||||
*hl-NvimOperator* Operator Generic operator
|
||||
|
||||
*hl-NvimUnaryOperator* NvimOperator Generic unary op
|
||||
*hl-NvimUnaryPlus* NvimUnaryOperator |expr-unary-+|
|
||||
*hl-NvimUnaryMinus* NvimUnaryOperator |expr-unary--|
|
||||
*hl-NvimNot* NvimUnaryOperator |expr-!|
|
||||
|
||||
*hl-NvimBinaryOperator* NvimOperator Generic binary op
|
||||
*hl-NvimComparison* NvimBinaryOperator Any |expr4| operator
|
||||
*hl-NvimComparisonModifier* NvimComparison `#`/`?` near |expr4| op
|
||||
*hl-NvimBinaryPlus* NvimBinaryOperator |expr-+|
|
||||
*hl-NvimBinaryMinus* NvimBinaryOperator |expr--|
|
||||
*hl-NvimConcat* NvimBinaryOperator |expr-.|
|
||||
*hl-NvimConcatOrSubscript* NvimConcat |expr-.| or |expr-entry|
|
||||
*hl-NvimOr* NvimBinaryOperator |expr-barbar|
|
||||
*hl-NvimAnd* NvimBinaryOperator |expr-&&|
|
||||
*hl-NvimMultiplication* NvimBinaryOperator |expr-star|
|
||||
*hl-NvimDivision* NvimBinaryOperator |expr-/|
|
||||
*hl-NvimMod* NvimBinaryOperator |expr-%|
|
||||
|
||||
*hl-NvimTernary* NvimOperator `?` in |expr1|
|
||||
*hl-NvimTernaryColon* NvimTernary `:` in |expr1|
|
||||
|
||||
*hl-NvimParenthesis* Delimiter Generic bracket
|
||||
*hl-NvimLambda* NvimParenthesis `{`/`}` in |lambda|
|
||||
*hl-NvimNestingParenthesis* NvimParenthesis `(`/`)` in |expr-nesting|
|
||||
*hl-NvimCallingParenthesis* NvimParenthesis `(`/`)` in |expr-function|
|
||||
|
||||
*hl-NvimSubscript* NvimParenthesis Generic subscript
|
||||
*hl-NvimSubscriptBracket* NvimSubscript `[`/`]` in |expr-[]|
|
||||
*hl-NvimSubscriptColon* NvimSubscript `:` in |expr-[:]|
|
||||
*hl-NvimCurly* NvimSubscript `{`/`}` in
|
||||
|curly-braces-names|
|
||||
|
||||
*hl-NvimContainer* NvimParenthesis Generic container
|
||||
*hl-NvimDict* NvimContainer `{`/`}` in |dict| literal
|
||||
*hl-NvimList* NvimContainer `[`/`]` in |list| literal
|
||||
|
||||
*hl-NvimIdentifier* Identifier Generic identifier
|
||||
*hl-NvimIdentifierScope* NvimIdentifier Namespace: letter
|
||||
before `:` in
|
||||
|internal-variables|
|
||||
*hl-NvimIdentifierScopeDelimiter* NvimIdentifier `:` after namespace
|
||||
letter
|
||||
*hl-NvimIdentifierName* NvimIdentifier Rest of the ident
|
||||
*hl-NvimIdentifierKey* NvimIdentifier Identifier after
|
||||
|expr-entry|
|
||||
|
||||
*hl-NvimColon* Delimiter `:` in |dict| literal
|
||||
*hl-NvimComma* Delimiter `,` in |dict|/|list|
|
||||
literal or
|
||||
|expr-function|
|
||||
*hl-NvimArrow* Delimiter `->` in |lambda|
|
||||
|
||||
*hl-NvimRegister* SpecialChar |expr-register|
|
||||
*hl-NvimNumber* Number Non-prefix digits
|
||||
in integer
|
||||
|expr-number|
|
||||
*hl-NvimNumberPrefix* Type `0` for |octal-number|
|
||||
`0x` for |hex-number|
|
||||
`0b` for |binary-number|
|
||||
*hl-NvimFloat* NvimNumber Floating-point
|
||||
number
|
||||
|
||||
*hl-NvimOptionSigil* Type `&` in |expr-option|
|
||||
*hl-NvimOptionScope* NvimIdentifierScope Option scope if any
|
||||
*hl-NvimOptionScopeDelimiter* NvimIdentifierScopeDelimiter
|
||||
`:` after option scope
|
||||
*hl-NvimOptionName* NvimIdentifier Option name
|
||||
|
||||
*hl-NvimEnvironmentSigil* NvimOptionSigil `$` in |expr-env|
|
||||
*hl-NvimEnvironmentName* NvimIdentifier Env variable name
|
||||
|
||||
*hl-NvimString* String Generic string
|
||||
*hl-NvimStringBody* NvimString Generic string
|
||||
literal body
|
||||
*hl-NvimStringQuote* NvimString Generic string quote
|
||||
*hl-NvimStringSpecial* SpecialChar Generic string
|
||||
non-literal body
|
||||
|
||||
*hl-NvimSingleQuote* NvimStringQuote `'` in |expr-'|
|
||||
*hl-NvimSingleQuotedBody* NvimStringBody Literal part of
|
||||
|expr-'| string body
|
||||
*hl-NvimSingleQuotedQuote* NvimStringSpecial `''` inside |expr-'|
|
||||
string body
|
||||
|
||||
*hl-NvimDoubleQuote* NvimStringQuote `"` in |expr-quote|
|
||||
*hl-NvimDoubleQuotedBody* NvimStringBody Literal part of
|
||||
|expr-quote| body
|
||||
*hl-NvimDoubleQuotedEscape* NvimStringSpecial Valid |expr-quote|
|
||||
escape sequence
|
||||
*hl-NvimDoubleQuotedUnknownEscape* NvimInvalidValue Unrecognized
|
||||
|expr-quote| escape
|
||||
sequence
|
||||
|
||||
vim:tw=78:ts=8:noet:ft=help:norl:
|
||||
|
@ -24,10 +24,8 @@ Each time a new or existing file is edited, Vim will try to recognize the type
|
||||
of the file and set the 'filetype' option. This will trigger the FileType
|
||||
event, which can be used to set the syntax highlighting, set options, etc.
|
||||
|
||||
Detail: The ":filetype on" command will load one of these files:
|
||||
Mac $VIMRUNTIME/filetype.vim
|
||||
MS-DOS $VIMRUNTIME\filetype.vim
|
||||
Unix $VIMRUNTIME/filetype.vim
|
||||
Detail: The ":filetype on" command will load this file:
|
||||
$VIMRUNTIME/filetype.vim
|
||||
This file is a Vim script that defines autocommands for the
|
||||
BufNewFile and BufRead events. If the file type is not found by the
|
||||
name, the file $VIMRUNTIME/scripts.vim is used to detect it from the
|
||||
|
@ -4,42 +4,19 @@
|
||||
VIM REFERENCE MANUAL by Andy Kahn
|
||||
|
||||
*cscope* *Cscope*
|
||||
This document explains how to use Vim's cscope interface.
|
||||
Cscope is a "code intelligence" tool that helps you navigate C programs. It
|
||||
can also perform some refactoring tasks, such as renaming a global variable in
|
||||
all source files. Think of it as "ctags on steroids".
|
||||
|
||||
Cscope is a tool like ctags, but think of it as ctags on steroids since it
|
||||
does a lot more than what ctags provides. In Vim, jumping to a result from
|
||||
a cscope query is just like jumping to any tag; it is saved on the tag stack
|
||||
so that with the right keyboard mappings, you can jump back and forth between
|
||||
functions as you normally would with |tags|.
|
||||
See |cscope-usage| for a quickstart.
|
||||
|
||||
Type |gO| to see the table of contents.
|
||||
|
||||
==============================================================================
|
||||
1. Cscope introduction *cscope-intro*
|
||||
Cscope introduction *cscope-intro*
|
||||
|
||||
The following text is taken from a version of the cscope man page:
|
||||
|
||||
-----
|
||||
|
||||
Cscope is an interactive screen-oriented tool that helps you:
|
||||
|
||||
Learn how a C program works without endless flipping through a thick
|
||||
listing.
|
||||
|
||||
Locate the section of code to change to fix a bug without having to
|
||||
learn the entire program.
|
||||
|
||||
Examine the effect of a proposed change such as adding a value to an
|
||||
enum variable.
|
||||
|
||||
Verify that a change has been made in all source files such as adding
|
||||
an argument to an existing function.
|
||||
|
||||
Rename a global variable in all source files.
|
||||
|
||||
Change a constant to a preprocessor symbol in selected lines of files.
|
||||
|
||||
It is designed to answer questions like:
|
||||
Cscope is designed to answer questions like:
|
||||
Where is this symbol used?
|
||||
Where is it defined?
|
||||
Where did this variable get its value?
|
||||
@ -51,35 +28,17 @@ The following text is taken from a version of the cscope man page:
|
||||
Where is this source file in the directory structure?
|
||||
What files include this header file?
|
||||
|
||||
Cscope answers these questions from a symbol database that it builds the
|
||||
first time it is used on the source files. On a subsequent call, cscope
|
||||
rebuilds the database only if a source file has changed or the list of
|
||||
source files is different. When the database is rebuilt the data for the
|
||||
unchanged files is copied from the old database, which makes rebuilding
|
||||
much faster than the initial build.
|
||||
|
||||
-----
|
||||
|
||||
When cscope is normally invoked, you will get a full-screen selection
|
||||
screen allowing you to make a query for one of the above questions.
|
||||
However, once a match is found to your query and you have entered your
|
||||
text editor to edit the source file containing match, you cannot simply
|
||||
jump from tag to tag as you normally would with vi's Ctrl-] or :tag
|
||||
command.
|
||||
|
||||
Vim's cscope interface is done by invoking cscope with its line-oriented
|
||||
interface, and then parsing the output returned from a query. The end
|
||||
result is that cscope query results become just like regular tags, so
|
||||
you can jump to them just like you do with normal tags (Ctrl-] or :tag)
|
||||
and then go back by popping off the tagstack with Ctrl-T. (Please note
|
||||
however, that you don't actually jump to a cscope tag simply by doing
|
||||
Ctrl-] or :tag without remapping these commands or setting an option.
|
||||
See the remaining sections on how the cscope interface works and for
|
||||
suggested use.)
|
||||
Cscope answers these questions from a symbol database that it builds the first
|
||||
time it is used on the source files. On a subsequent call, cscope rebuilds
|
||||
the database only if a source file has changed or the list of source files is
|
||||
different. When the database is rebuilt the data for the unchanged files is
|
||||
copied from the old database, which makes rebuilding much faster than the
|
||||
initial build.
|
||||
|
||||
See |cscope-usage| to get started.
|
||||
|
||||
==============================================================================
|
||||
2. Cscope related commands *cscope-commands*
|
||||
Cscope commands *cscope-commands*
|
||||
|
||||
*:cscope* *:cs* *:scs* *:scscope* *E259* *E262* *E561* *E560*
|
||||
All cscope commands are accessed through suboptions to the cscope commands.
|
||||
@ -232,7 +191,7 @@ through your tags file(s).
|
||||
|
||||
|
||||
==============================================================================
|
||||
3. Cscope options *cscope-options*
|
||||
Cscope options *cscope-options*
|
||||
|
||||
Use the |:set| command to set all cscope options. Ideally, you would do
|
||||
this in one of your startup files (e.g., vimrc). Some cscope related
|
||||
@ -245,7 +204,6 @@ started will have no effect!
|
||||
:set csprg=/usr/local/bin/cscope
|
||||
<
|
||||
*cscopequickfix* *csqf* *E469*
|
||||
{not available when compiled without the |+quickfix| feature}
|
||||
'cscopequickfix' specifies whether to use quickfix window to show cscope
|
||||
results. This is a list of comma-separated values. Each item consists of
|
||||
|cscope-find| command (s, g, d, c, t, e, f, i or a) and flag (+, - or 0).
|
||||
@ -260,81 +218,56 @@ seems to be useful: >
|
||||
If 'cscopetag' is set, the commands ":tag" and CTRL-] as well as "vim -t"
|
||||
will always use |:cstag| instead of the default :tag behavior. Effectively,
|
||||
by setting 'cst', you will always search your cscope databases as well as
|
||||
your tag files. The default is off. Examples: >
|
||||
:set cst
|
||||
:set nocst
|
||||
<
|
||||
your tag files. The default is off.
|
||||
|
||||
*cscoperelative* *csre*
|
||||
If 'cscoperelative' is set, then in absence of a prefix given to cscope
|
||||
(prefix is the argument of -P option of cscope), basename of cscope.out
|
||||
location (usually the project root directory) will be used as the prefix
|
||||
to construct an absolute path. The default is off. Note: This option is
|
||||
only effective when cscope (cscopeprg) is initialized without a prefix
|
||||
path (-P). Examples: >
|
||||
:set csre
|
||||
:set nocsre
|
||||
<
|
||||
path (-P).
|
||||
|
||||
*cscopetagorder* *csto*
|
||||
The value of 'csto' determines the order in which |:cstag| performs a search.
|
||||
If 'csto' is set to zero, cscope database(s) are searched first, followed
|
||||
by tag file(s) if cscope did not return any matches. If 'csto' is set to
|
||||
one, tag file(s) are searched before cscope database(s). The default is zero.
|
||||
Examples: >
|
||||
:set csto=0
|
||||
:set csto=1
|
||||
<
|
||||
*cscopeverbose* *csverb*
|
||||
If 'cscopeverbose' is not set (the default), messages will not be printed
|
||||
indicating success or failure when adding a cscope database. Ideally, you
|
||||
should reset this option in your |init.vim| before adding any cscope
|
||||
databases, and after adding them, set it. From then on, when you add more
|
||||
databases within Vim, you will get a (hopefully) useful message should the
|
||||
database fail to be added. Examples: >
|
||||
:set csverb
|
||||
:set nocsverb
|
||||
<
|
||||
|
||||
*cscopepathcomp* *cspc*
|
||||
The value of 'cspc' determines how many components of a file's path to
|
||||
display. With the default value of zero the entire path will be displayed.
|
||||
'cscopepathcomp' determines how many components of a file's path to display.
|
||||
With the default value of zero the entire path will be displayed.
|
||||
The value one will display only the filename with no path. Other values
|
||||
display that many components. For example: >
|
||||
:set cspc=3
|
||||
:set cscopepathcomp=3
|
||||
will display the last 3 components of the file's path, including the file
|
||||
name itself.
|
||||
|
||||
==============================================================================
|
||||
4. How to use cscope in Vim *cscope-howtouse*
|
||||
Using cscope in Nvim *cscope-usage* *cscope-howtouse*
|
||||
|
||||
The first thing you need to do is to build a cscope database for your
|
||||
source files. For the most basic case, simply do "cscope -b". Please
|
||||
refer to the cscope man page for more details.
|
||||
To get started, build the cscope database in your project root directory: >
|
||||
cscope -bcqR
|
||||
|
||||
Assuming you have a cscope database, you need to "add" the database to Vim.
|
||||
This establishes a cscope "connection" and makes it available for Vim to use.
|
||||
You can do this in your vimrc file, or you can do it manually after starting
|
||||
vim. For example, to add the cscope database "cscope.out", you would do:
|
||||
See the cscope manpage for details: >
|
||||
:Man cscope
|
||||
|
||||
:cs add cscope.out
|
||||
By default the cscope database file is named "cscope.out". After building the
|
||||
database, connect to it from Nvim: >
|
||||
:cscope add cscope.out
|
||||
|
||||
You can double-check the result of this by executing ":cs show". This will
|
||||
produce output which looks like this:
|
||||
That establishes a cscope connection for Nvim to use. You can check the
|
||||
result with ":cs show". It will show something like:
|
||||
|
||||
# pid database name prepend path
|
||||
0 28806 cscope.out <none>
|
||||
|
||||
Note:
|
||||
Because of the Microsoft RTL limitations, Win32 version shows 0 instead
|
||||
of the real pid.
|
||||
|
||||
Once a cscope connection is established, you can make queries to cscope and
|
||||
the results will be printed to you. Queries are made using the command
|
||||
":cs find". For example:
|
||||
|
||||
the results will be printed. Queries are made using the command ":cs find".
|
||||
For example: >
|
||||
:cs find g ALIGN_SIZE
|
||||
|
||||
This can get a little cumbersome since one ends up doing a significant
|
||||
amount of typing. Fortunately, there are ways around this by mapping
|
||||
shortcut keys. See |cscope-suggestions| for suggested usage.
|
||||
To make this easier you can configure mappings, see |cscope-suggestions|.
|
||||
|
||||
If the results return only one match, you will automatically be taken to it.
|
||||
If there is more than one match, you will be given a selection screen to pick
|
||||
@ -343,39 +276,28 @@ simply hit Ctrl-T to get back to the previous one.
|
||||
|
||||
|
||||
==============================================================================
|
||||
5. Limitations *cscope-limitations*
|
||||
|
||||
Cscope support for Vim is only available on systems that support these four
|
||||
system calls: fork(), pipe(), execl(), waitpid(). This means it is mostly
|
||||
limited to Unix systems.
|
||||
|
||||
Additionally Cscope support works for Win32. For more information and a
|
||||
cscope version for Win32 see:
|
||||
|
||||
http://iamphet.nm.ru/cscope/index.html
|
||||
Limitations *cscope-limitations*
|
||||
|
||||
Hard-coded limitation: doing a |:tjump| when |:cstag| searches the tag files
|
||||
is not configurable (e.g., you can't do a tselect instead).
|
||||
|
||||
==============================================================================
|
||||
6. Suggested usage *cscope-suggestions*
|
||||
|
||||
Put these entries in your vimrc (adjust the pathname accordingly to your
|
||||
setup): >
|
||||
==============================================================================
|
||||
Sample config *cscope-suggestions*
|
||||
|
||||
Copy this into your init.vim (adjust paths for your system): >
|
||||
|
||||
if has("cscope")
|
||||
set csprg=/usr/local/bin/cscope
|
||||
set csto=0
|
||||
set cst
|
||||
set nocsverb
|
||||
" add any database in current directory
|
||||
if filereadable("cscope.out")
|
||||
cs add cscope.out
|
||||
silent cs add cscope.out
|
||||
" else add database pointed to by environment
|
||||
elseif $CSCOPE_DB != ""
|
||||
cs add $CSCOPE_DB
|
||||
silent cs add $CSCOPE_DB
|
||||
endif
|
||||
set csverb
|
||||
endif
|
||||
|
||||
By setting 'cscopetag', we have effectively replaced all instances of the :tag
|
||||
@ -447,47 +369,6 @@ Cscope Home Page (http://cscope.sourceforge.net/): >
|
||||
\:vert scs find d <C-R>=expand("<cword>")<CR><CR>
|
||||
nmap <C-Space><C-Space>a
|
||||
\:vert scs find a <C-R>=expand("<cword>")<CR><CR>
|
||||
|
||||
==============================================================================
|
||||
7. Cscope availability and information *cscope-info*
|
||||
|
||||
If you do not already have cscope (it did not come with your compiler
|
||||
license or OS distribution), then you can download it for free from:
|
||||
http://cscope.sourceforge.net/
|
||||
This is released by SCO under the BSD license.
|
||||
|
||||
If you want a newer version of cscope, you will probably have to buy it.
|
||||
According to the (old) nvi documentation:
|
||||
|
||||
You can buy version 13.3 source with an unrestricted license
|
||||
for $400 from AT&T Software Solutions by calling +1-800-462-8146.
|
||||
|
||||
Also you can download cscope 13.x and mlcscope 14.x (multi-lingual cscope
|
||||
which supports C, C++, Java, lex, yacc, breakpoint listing, Ingres, and SDL)
|
||||
from World-Wide Exptools Open Source packages page:
|
||||
http://www.bell-labs.com/project/wwexptools/packages.html
|
||||
|
||||
In Solaris 2.x, if you have the C compiler license, you will also have
|
||||
cscope. Both are usually located under /opt/SUNWspro/bin
|
||||
|
||||
SGI developers can also get it. Search for Cscope on this page:
|
||||
http://freeware.sgi.com/index-by-alpha.html
|
||||
https://toolbox.sgi.com/toolbox/utilities/cscope/
|
||||
The second one is for those who have a password for the SGI toolbox.
|
||||
|
||||
There is source to an older version of a cscope clone (called "cs") available
|
||||
on the net. Due to various reasons, this is not supported with Vim.
|
||||
|
||||
The cscope interface/support for Vim was originally written by
|
||||
Andy Kahn <ackahn@netapp.com>. The original structure (as well as a tiny
|
||||
bit of code) was adapted from the cscope interface in nvi. Please report
|
||||
any problems, suggestions, patches, et al., you have for the usage of
|
||||
cscope within Vim to him.
|
||||
*cscope-win32*
|
||||
For a cscope version for Win32 see:
|
||||
http://code.google.com/p/cscope-win32/
|
||||
|
||||
Win32 support was added by Sergey Khorev <sergey.khorev@gmail.com>. Contact
|
||||
him if you have Win32-specific issues.
|
||||
<
|
||||
|
||||
vim:tw=78:ts=8:ft=help:norl:
|
||||
|
@ -320,6 +320,21 @@ The examples below assume a 'shiftwidth' of 4.
|
||||
{ {
|
||||
void function(); void function();
|
||||
} }
|
||||
<
|
||||
*cino-E*
|
||||
EN Indent inside C++ linkage specifications (extern "C" or
|
||||
extern "C++") N characters extra compared to a normal block.
|
||||
(default 0).
|
||||
|
||||
cino= cino=E-s >
|
||||
extern "C" { extern "C" {
|
||||
void function(); void function();
|
||||
} }
|
||||
|
||||
extern "C" extern "C"
|
||||
{ {
|
||||
void function(); void function();
|
||||
} }
|
||||
<
|
||||
*cino-p*
|
||||
pN Parameter declarations for K&R-style function declarations will
|
||||
@ -550,7 +565,7 @@ The examples below assume a 'shiftwidth' of 4.
|
||||
|
||||
|
||||
The defaults, spelled out in full, are:
|
||||
cinoptions=>s,e0,n0,f0,{0,}0,^0,L-1,:s,=s,l0,b0,gs,hs,N0,ps,ts,is,+s,
|
||||
cinoptions=>s,e0,n0,f0,{0,}0,^0,L-1,:s,=s,l0,b0,gs,hs,N0,E0,ps,ts,is,+s,
|
||||
c3,C0,/0,(2s,us,U0,w0,W0,k0,m0,j0,J0,)20,*70,#0
|
||||
|
||||
Vim puts a line in column 1 if:
|
||||
|
@ -40,10 +40,11 @@ char action ~
|
||||
*i_CTRL-[* *i_<Esc>*
|
||||
<Esc> or CTRL-[ End insert or Replace mode, go back to Normal mode. Finish
|
||||
abbreviation.
|
||||
Note: If your <Esc> key is hard to hit on your keyboard, train
|
||||
yourself to use CTRL-[.
|
||||
If Esc doesn't work and you are using a Mac, try CTRL-Esc.
|
||||
Or disable Listening under Accessibility preferences.
|
||||
Note: If your <Esc> key is hard to hit, try CTRL-[ instead.
|
||||
*i_META* *i_ALT*
|
||||
|ALT| (|META|) acts like <Esc> if the chord is not mapped.
|
||||
For example <A-x> acts like <Esc>x if <A-x> does not have an
|
||||
insert-mode mapping.
|
||||
*i_CTRL-C*
|
||||
CTRL-C Quit insert mode, go back to Normal mode. Do not check for
|
||||
abbreviations. Does not trigger the |InsertLeave| autocommand
|
||||
@ -1077,6 +1078,8 @@ items:
|
||||
item with the same word is already present.
|
||||
empty when non-zero this match will be added even when it is
|
||||
an empty string
|
||||
user_data custom data which is associated with the item and
|
||||
available in |v:completed_item|
|
||||
|
||||
All of these except "icase", "dup" and "empty" must be a string. If an item
|
||||
does not meet these requirements then an error message is given and further
|
||||
@ -1170,6 +1173,8 @@ The menu is used when:
|
||||
|
||||
The 'pumheight' option can be used to set a maximum height. The default is to
|
||||
use all space available.
|
||||
The 'pumwidth' option can be used to set a minimum width. The default is 15
|
||||
characters.
|
||||
|
||||
There are three states:
|
||||
1. A complete match has been inserted, e.g., after using CTRL-N or CTRL-P.
|
||||
|
@ -58,7 +58,7 @@ Description of what happens:
|
||||
- The first shell is idle, waiting to read commands from its stdin.
|
||||
- The second shell is started with -c which executes the command (a for-loop
|
||||
printing 0 through 9) and then exits.
|
||||
- `JobHandler()` callback is passed to |jobstart()| to handle various job
|
||||
- `OnEvent()` callback is passed to |jobstart()| to handle various job
|
||||
events. It displays stdout/stderr data received from the shells.
|
||||
|
||||
For |on_stdout| and |on_stderr| see |channel-callback|.
|
||||
|
@ -232,8 +232,10 @@ For this reason the following is blocked:
|
||||
- Editing another buffer.
|
||||
- The |:normal| command.
|
||||
- Moving the cursor is allowed, but it is restored afterwards.
|
||||
- If the cmdline is changed, the old text and cursor position are restored.
|
||||
If you want the mapping to do any of these let the returned characters do
|
||||
that.
|
||||
that. Alternatively use a |<Cmd>| mapping which doesn't have these
|
||||
restrictions.
|
||||
|
||||
You can use getchar(), it consumes typeahead if there is any. E.g., if you
|
||||
have these mappings: >
|
||||
@ -272,6 +274,29 @@ again for using <expr>. This does work: >
|
||||
Using 0x80 as a single byte before other text does not work, it will be seen
|
||||
as a special key.
|
||||
|
||||
*<Cmd>* *:map-command*
|
||||
A command mapping is a mapping that directly executes a command. Command
|
||||
mappings are written by placing a command in between <Cmd> and <CR> in the
|
||||
rhs of a mapping (in any mode): >
|
||||
noremap <f3> <Cmd>echo mode(1)<cr>
|
||||
<
|
||||
*E5520*
|
||||
The command must be complete and ended with a <CR>. If the command is
|
||||
incomplete, an error is raised. |Command-line| mode is never entered.
|
||||
|
||||
This is more flexible than using `:<c-u>` in visual and operator pending
|
||||
mode, or `<c-o>:` in insert mode, as the commands are exectued directly in the
|
||||
mode, and not normal mode. Also visual mode is not aborted. Commands can be
|
||||
invoked directly in cmdline mode, which is not simple otherwise (a timer has
|
||||
to be used). Unlike <expr> mappings, there are not any specific restrictions
|
||||
what the command can do, except for what is normally possible to do in every
|
||||
specific mode. The command should be executed the same way as if an
|
||||
(unrestricted) |autocmd| was invoked or an async event event was processed.
|
||||
|
||||
Note: In select mode, |:map| or |:vmap| command mappings will be executed in
|
||||
visual mode. If a mapping is intended to work in select mode, it is
|
||||
recomendend to map it using |:smap|, possibly in addition to the same mapping
|
||||
with |:map| or |:xmap|.
|
||||
|
||||
1.3 MAPPING AND MODES *:map-modes*
|
||||
*mapmode-nvo* *mapmode-n* *mapmode-v* *mapmode-o* *mapmode-t*
|
||||
|
@ -70,9 +70,8 @@ An rpc socket is automatically created with each instance. The socket
|
||||
location is stored in |v:servername|. By default this is a named pipe
|
||||
with an automatically generated address. See |XXX|.
|
||||
|
||||
To make Nvim listen on a TCP/IP socket instead, set the
|
||||
|$NVIM_LISTEN_ADDRESS| environment variable before starting Nvim: >
|
||||
NVIM_LISTEN_ADDRESS=127.0.0.1:6666 nvim
|
||||
To make Nvim listen on a TCP/IP socket instead, specify |--listen|: >
|
||||
nvim --listen 127.0.0.1:6666
|
||||
<Also, more sockets and named pipes can be listened on using |serverstart()|.
|
||||
|
||||
Note that localhost TCP sockets are generally less secure than named pipes,
|
||||
@ -242,4 +241,4 @@ Even for statically compiled clients it is good practice to avoid hardcoding
|
||||
the type codes, because a client may be built against one Nvim version but
|
||||
connect to another with different type codes.
|
||||
|
||||
|
||||
vim:tw=78:ts=8:ft=help:norl:
|
||||
|
@ -1807,12 +1807,6 @@ A jump table for the options with a short description can be found at |Q_op|.
|
||||
Determines the order in which ":cstag" performs a search. See
|
||||
|cscopetagorder|.
|
||||
|
||||
*'cscopeverbose'* *'csverb'*
|
||||
*'nocscopeverbose'* *'nocsverb'*
|
||||
'cscopeverbose' 'csverb' boolean (default off)
|
||||
global
|
||||
Give messages when adding a cscope database. See |cscopeverbose|.
|
||||
|
||||
*'cursorbind'* *'crb'* *'nocursorbind'* *'nocrb'*
|
||||
'cursorbind' 'crb' boolean (default off)
|
||||
local to window
|
||||
@ -2042,6 +2036,11 @@ A jump table for the options with a short description can be found at |Q_op|.
|
||||
column of the last screen line. Overrules "lastline".
|
||||
uhex Show unprintable characters hexadecimal as <xx>
|
||||
instead of using ^C and ~C.
|
||||
msgsep When showing messages longer than 'cmdheight' lines,
|
||||
only scroll the message lines and not the entire
|
||||
screen. This also shows a separator line filled with
|
||||
chars determined by 'fillchars' option, and
|
||||
highlighted with the |MsgSeparator| group.
|
||||
|
||||
When neither "lastline" nor "truncate" is included, a last line that
|
||||
doesn't fit is replaced with "@" lines.
|
||||
@ -2383,7 +2382,7 @@ A jump table for the options with a short description can be found at |Q_op|.
|
||||
Only normal file name characters can be used, "/\*?[|<>" are illegal.
|
||||
|
||||
*'fillchars'* *'fcs'*
|
||||
'fillchars' 'fcs' string (default "vert:|,fold:-")
|
||||
'fillchars' 'fcs' string (default "")
|
||||
global
|
||||
{not available when compiled without the |+windows|
|
||||
and |+folding| features}
|
||||
@ -2393,16 +2392,20 @@ A jump table for the options with a short description can be found at |Q_op|.
|
||||
item default Used for ~
|
||||
stl:c ' ' or '^' statusline of the current window
|
||||
stlnc:c ' ' or '=' statusline of the non-current windows
|
||||
vert:c '|' vertical separators |:vsplit|
|
||||
fold:c '-' filling 'foldtext'
|
||||
vert:c '│' or '|' vertical separators |:vsplit|
|
||||
fold:c '·' or '-' filling 'foldtext'
|
||||
diff:c '-' deleted lines of the 'diff' option
|
||||
msgsep:c ' ' message separator 'display'
|
||||
|
||||
Any one that is omitted will fall back to the default. For "stl" and
|
||||
"stlnc" the space will be used when there is highlighting, '^' or '='
|
||||
otherwise.
|
||||
|
||||
If 'ambiwidth' is "double" then "vert" and "fold" default to
|
||||
single-byte alternatives.
|
||||
|
||||
Example: >
|
||||
:set fillchars=stl:^,stlnc:=,vert:\|,fold:-,diff:-
|
||||
:set fillchars=stl:^,stlnc:=,vert:│,fold:·,diff:-
|
||||
< This is similar to the default, except that these characters will also
|
||||
be used when there is highlighting.
|
||||
|
||||
@ -2712,6 +2715,10 @@ A jump table for the options with a short description can be found at |Q_op|.
|
||||
:s///g subst. one subst. all
|
||||
:s///gg subst. all subst. one
|
||||
|
||||
DEPRECATED: Setting this option may break plugins that are not aware
|
||||
of this option. Also, many users get confused that adding the /g flag
|
||||
has the opposite effect of that it normally does.
|
||||
|
||||
*'grepformat'* *'gfm'*
|
||||
'grepformat' 'gfm' string (default "%f:%l:%m,%f:%l%m,%f %l%m")
|
||||
global
|
||||
@ -3301,7 +3308,17 @@ A jump table for the options with a short description can be found at |Q_op|.
|
||||
pattern and/or a lot of text the match may not be found. This is to
|
||||
avoid that Vim hangs while you are typing the pattern.
|
||||
The |hl-IncSearch| highlight group determines the highlighting.
|
||||
See also: 'hlsearch'.
|
||||
When 'hlsearch' is on, all matched strings are highlighted too while typing
|
||||
a search command. See also: 'hlsearch'.
|
||||
If you don't want turn 'hlsearch' on, but want to highlight all matches
|
||||
while searching, you can turn on and off 'hlsearch' with autocmd.
|
||||
Example: >
|
||||
augroup vimrc-incsearch-highlight
|
||||
autocmd!
|
||||
autocmd CmdlineEnter /,\? :set hlsearch
|
||||
autocmd CmdlineLeave /,\? :set nohlsearch
|
||||
augroup END
|
||||
<
|
||||
CTRL-L can be used to add one character from after the current match
|
||||
to the command line. If 'ignorecase' and 'smartcase' are set and the
|
||||
command line has no uppercase characters, the added character is
|
||||
@ -3672,7 +3689,7 @@ A jump table for the options with a short description can be found at |Q_op|.
|
||||
< Minimum value is 2, maximum value is 1000.
|
||||
|
||||
*'linespace'* *'lsp'*
|
||||
'linespace' 'lsp' number (default 0, 1 for Win32 GUI)
|
||||
'linespace' 'lsp' number (default 0)
|
||||
global
|
||||
{only in the GUI}
|
||||
Number of pixel lines inserted between characters. Useful if the font
|
||||
@ -3809,6 +3826,23 @@ A jump table for the options with a short description can be found at |Q_op|.
|
||||
This option cannot be set from a |modeline| or in the |sandbox|, for
|
||||
security reasons.
|
||||
|
||||
*'makeencoding'* *'menc'*
|
||||
'makeencoding' 'menc' string (default "")
|
||||
global or local to buffer |global-local|
|
||||
{only available when compiled with the |+multi_byte|
|
||||
feature}
|
||||
{not in Vi}
|
||||
Encoding used for reading the output of external commands. When empty,
|
||||
encoding is not converted.
|
||||
This is used for `:make`, `:lmake`, `:grep`, `:lgrep`, `:grepadd`,
|
||||
`:lgrepadd`, `:cfile`, `:cgetfile`, `:caddfile`, `:lfile`, `:lgetfile`,
|
||||
and `:laddfile`.
|
||||
|
||||
This would be mostly useful when you use MS-Windows. If |+iconv| is
|
||||
enabled and GNU libiconv is used, setting 'makeencoding' to "char" has
|
||||
the same effect as setting to the system locale encoding. Example: >
|
||||
:set makeencoding=char " system locale is used
|
||||
<
|
||||
*'makeprg'* *'mp'*
|
||||
'makeprg' 'mp' string (default "make")
|
||||
global or local to buffer |global-local|
|
||||
@ -5132,10 +5166,10 @@ A jump table for the options with a short description can be found at |Q_op|.
|
||||
security reasons.
|
||||
|
||||
*'shellcmdflag'* *'shcf'*
|
||||
'shellcmdflag' 'shcf' string (default: "-c"; Windows: "/c")
|
||||
'shellcmdflag' 'shcf' string (default: "-c"; Windows: "/s /c")
|
||||
global
|
||||
Flag passed to the shell to execute "!" and ":!" commands; e.g.,
|
||||
"bash.exe -c ls" or "cmd.exe /c dir". For Windows
|
||||
`bash.exe -c ls` or `cmd.exe /s /c "dir"`. For Windows
|
||||
systems, the default is set according to the value of 'shell', to
|
||||
reduce the need to set this option by the user.
|
||||
On Unix it can have more than one flag. Each white space separated
|
||||
@ -5256,7 +5290,7 @@ A jump table for the options with a short description can be found at |Q_op|.
|
||||
to execute most external commands with cmd.exe.
|
||||
|
||||
*'shellxquote'* *'sxq'*
|
||||
'shellxquote' 'sxq' string (default: "")
|
||||
'shellxquote' 'sxq' string (default: "", Windows: "\"")
|
||||
global
|
||||
Quoting character(s), put around the command passed to the shell, for
|
||||
the "!" and ":!" commands. Includes the redirection. See
|
||||
@ -5420,14 +5454,13 @@ A jump table for the options with a short description can be found at |Q_op|.
|
||||
See |tab-page| for more information about tab pages.
|
||||
|
||||
*'sidescroll'* *'ss'*
|
||||
'sidescroll' 'ss' number (default 0)
|
||||
'sidescroll' 'ss' number (default 1)
|
||||
global
|
||||
The minimal number of columns to scroll horizontally. Used only when
|
||||
the 'wrap' option is off and the cursor is moved off of the screen.
|
||||
When it is zero the cursor will be put in the middle of the screen.
|
||||
When using a slow terminal set it to a large number or 0. When using
|
||||
a fast terminal use a small number or 1. Not used for "zh" and "zl"
|
||||
commands.
|
||||
When using a slow terminal set it to a large number or 0. Not used
|
||||
for "zh" and "zl" commands.
|
||||
|
||||
*'sidescrolloff'* *'siso'*
|
||||
'sidescrolloff' 'siso' number (default 0)
|
||||
@ -6192,7 +6225,6 @@ A jump table for the options with a short description can be found at |Q_op|.
|
||||
When on, uses |highlight-guifg| and |highlight-guibg| attributes in
|
||||
the terminal (thus using 24-bit color). Requires a ISO-8613-3
|
||||
compatible terminal.
|
||||
Must be set at startup (in your |init.vim| or |--cmd|).
|
||||
|
||||
*'terse'* *'noterse'*
|
||||
'terse' boolean (default off)
|
||||
@ -6258,15 +6290,14 @@ A jump table for the options with a short description can be found at |Q_op|.
|
||||
*'timeoutlen'* *'tm'*
|
||||
'timeoutlen' 'tm' number (default 1000)
|
||||
global
|
||||
The time in milliseconds that is waited for a mapped sequence to
|
||||
complete.
|
||||
Time in milliseconds to wait for a mapped sequence to complete.
|
||||
|
||||
*'ttimeoutlen'* *'ttm'*
|
||||
'ttimeoutlen' 'ttm' number (default 50)
|
||||
global
|
||||
The time in milliseconds that is waited for a key code
|
||||
sequence to complete. Also used for CTRL-\ CTRL-N and CTRL-\ CTRL-G
|
||||
when part of a command has been typed.
|
||||
Time in milliseconds to wait for a key code sequence to complete. Also
|
||||
used for CTRL-\ CTRL-N and CTRL-\ CTRL-G when part of a command has
|
||||
been typed.
|
||||
|
||||
*'title'* *'notitle'*
|
||||
'title' boolean (default off)
|
||||
@ -6424,6 +6455,7 @@ A jump table for the options with a short description can be found at |Q_op|.
|
||||
Currently, these messages are given:
|
||||
>= 1 When the shada file is read or written.
|
||||
>= 2 When a file is ":source"'ed.
|
||||
>= 3 UI info, terminal capabilities
|
||||
>= 5 Every searched tags file and include file.
|
||||
>= 8 Files for which a group of autocommands is executed.
|
||||
>= 9 Every executed autocommand.
|
||||
@ -6895,7 +6927,8 @@ A jump table for the options with a short description can be found at |Q_op|.
|
||||
'writedelay' 'wd' number (default 0)
|
||||
global
|
||||
The number of milliseconds to wait for each character sent to the
|
||||
screen. When non-zero, characters are sent to the terminal one by
|
||||
one. For debugging purposes.
|
||||
screen. When positive, characters are sent to the UI one by one.
|
||||
When negative, all redrawn characters cause a delay, even if the
|
||||
character already was displayed by the UI. For debugging purposes.
|
||||
|
||||
vim:tw=78:ts=8:ft=help:noet:norl:
|
||||
|
@ -33,20 +33,20 @@ To use Vim Python 2/3 plugins with Nvim:
|
||||
|
||||
- For Python 2 plugins, make sure an interpreter for Python 2.6 or 2.7 is
|
||||
available in your `$PATH`, then install the `neovim` Python package systemwide: >
|
||||
$ sudo pip2 install --upgrade neovim
|
||||
sudo pip2 install --upgrade neovim
|
||||
<
|
||||
or for the current user: >
|
||||
$ pip2 install --user --upgrade neovim
|
||||
pip2 install --user --upgrade neovim
|
||||
<
|
||||
- For Python 3 plugins, make sure an interpreter for Python 3.3 or above is
|
||||
available in your `$PATH`, then install the `neovim` Python package systemwide: >
|
||||
$ sudo pip3 install --upgrade neovim
|
||||
sudo pip3 install --upgrade neovim
|
||||
<
|
||||
or for the current user: >
|
||||
$ pip3 install --user --upgrade neovim
|
||||
pip3 install --user --upgrade neovim
|
||||
<
|
||||
Note: The `--upgrade` flag ensures you have the latest version even if
|
||||
a previous version was already installed.
|
||||
a previous version was already installed.
|
||||
|
||||
PYTHON PROVIDER CONFIGURATION ~
|
||||
*g:python_host_prog*
|
||||
@ -93,7 +93,7 @@ Run |:checkhealth| to see if your system is up-to-date.
|
||||
RUBY QUICKSTART ~
|
||||
|
||||
To use Vim Ruby plugins with Nvim, just install the latest `neovim` RubyGem: >
|
||||
$ gem install neovim
|
||||
gem install neovim
|
||||
|
||||
RUBY PROVIDER CONFIGURATION ~
|
||||
*g:loaded_ruby_provider*
|
||||
@ -112,7 +112,30 @@ To use an absolute path (e.g. to an rbenv installation): >
|
||||
To use the RVM "system" Ruby installation: >
|
||||
let g:ruby_host_prog = 'rvm system do neovim-ruby-host'
|
||||
<
|
||||
==============================================================================
|
||||
Node.js integration *provider-nodejs*
|
||||
|
||||
Nvim supports Node.js |remote-plugin|s.
|
||||
https://github.com/neovim/node-client/
|
||||
https://nodejs.org/
|
||||
|
||||
NODEJS QUICKSTART~
|
||||
|
||||
To use javascript remote-plugins with Nvim, install the `neovim` npm package: >
|
||||
npm install -g neovim
|
||||
<
|
||||
NODEJS PROVIDER CONFIGURATION~
|
||||
*g:loaded_node_provider*
|
||||
To disable Node support: >
|
||||
:let g:loaded_node_provider = 1
|
||||
<
|
||||
*g:node_host_prog*
|
||||
Command to start the Node host. Setting this makes startup faster.
|
||||
|
||||
By default, Nvim searches for `neovim-node-host` using "npm root -g", which
|
||||
can be slow. To avoid this, set g:node_host_prog to an absolute path: >
|
||||
let g:node_host_prog = '/usr/local/bin/neovim-node-host'
|
||||
<
|
||||
==============================================================================
|
||||
Clipboard integration *provider-clipboard* *clipboard*
|
||||
|
||||
|
@ -165,6 +165,9 @@ processing a quickfix or location list command, it will be aborted.
|
||||
keep Vim running while compiling. If you give the
|
||||
name of the errorfile, the 'errorfile' option will
|
||||
be set to [errorfile]. See |:cc| for [!].
|
||||
If the encoding of the error file differs from the
|
||||
'encoding' option, you can use the 'makeencoding'
|
||||
option to specify the encoding.
|
||||
|
||||
*:lf* *:lfile*
|
||||
:lf[ile][!] [errorfile] Same as ":cfile", except the location list for the
|
||||
@ -176,6 +179,9 @@ processing a quickfix or location list command, it will be aborted.
|
||||
:cg[etfile] [errorfile] *:cg* *:cgetfile*
|
||||
Read the error file. Just like ":cfile" but don't
|
||||
jump to the first error.
|
||||
If the encoding of the error file differs from the
|
||||
'encoding' option, you can use the 'makeencoding'
|
||||
option to specify the encoding.
|
||||
|
||||
|
||||
:lg[etfile] [errorfile] *:lg* *:lgetfile*
|
||||
@ -186,6 +192,9 @@ processing a quickfix or location list command, it will be aborted.
|
||||
:caddf[ile] [errorfile] Read the error file and add the errors from the
|
||||
errorfile to the current quickfix list. If a quickfix
|
||||
list is not present, then a new list is created.
|
||||
If the encoding of the error file differs from the
|
||||
'encoding' option, you can use the 'makeencoding'
|
||||
option to specify the encoding.
|
||||
|
||||
*:laddf* *:laddfile*
|
||||
:laddf[ile] [errorfile] Same as ":caddfile", except the location list for the
|
||||
@ -322,6 +331,7 @@ use this code: >
|
||||
endfunction
|
||||
|
||||
au QuickfixCmdPost make call QfMakeConv()
|
||||
Another option is using 'makeencoding'.
|
||||
|
||||
EXECUTE A COMMAND IN ALL THE BUFFERS IN QUICKFIX OR LOCATION LIST:
|
||||
*:cdo*
|
||||
@ -460,7 +470,11 @@ keep its height, ignoring 'winheight' and 'equalalways'. You can change the
|
||||
height manually (e.g., by dragging the status line above it with the mouse).
|
||||
|
||||
In the quickfix window, each line is one error. The line number is equal to
|
||||
the error number. You can use ":.cc" to jump to the error under the cursor.
|
||||
the error number. The current entry is highlighted with the QuickFixLine
|
||||
highlighting. You can change it to your liking, e.g.: >
|
||||
:hi QuickFixLine ctermbg=Yellow guibg=Yellow
|
||||
|
||||
You can use ":.cc" to jump to the error under the cursor.
|
||||
Hitting the <Enter> key or double-clicking the mouse on a line has the same
|
||||
effect. The file containing the error is opened in the window above the
|
||||
quickfix window. If there already is a window for that file, it is used
|
||||
@ -586,6 +600,9 @@ lists, use ":cnewer 99" first.
|
||||
like |:cnext| and |:cprevious|, see above.
|
||||
This command does not accept a comment, any "
|
||||
characters are considered part of the arguments.
|
||||
If the encoding of the program output differs from the
|
||||
'encoding' option, you can use the 'makeencoding'
|
||||
option to specify the encoding.
|
||||
|
||||
*:lmak* *:lmake*
|
||||
:lmak[e][!] [arguments]
|
||||
@ -645,6 +662,7 @@ read the error messages: >
|
||||
au QuickfixCmdPost make call QfMakeConv()
|
||||
|
||||
(Example by Faque Cheng)
|
||||
Another option is using 'makeencoding'.
|
||||
|
||||
==============================================================================
|
||||
5. Using :vimgrep and :grep *grep* *lid*
|
||||
@ -759,6 +777,9 @@ id-utils) in a similar way to its compiler integration (see |:make| above).
|
||||
When 'grepprg' is "internal" this works like
|
||||
|:vimgrep|. Note that the pattern needs to be
|
||||
enclosed in separator characters then.
|
||||
If the encoding of the program output differs from the
|
||||
'encoding' option, you can use the 'makeencoding'
|
||||
option to specify the encoding.
|
||||
|
||||
*:lgr* *:lgrep*
|
||||
:lgr[ep][!] [arguments] Same as ":grep", except the location list for the
|
||||
@ -783,6 +804,10 @@ id-utils) in a similar way to its compiler integration (see |:make| above).
|
||||
\ | catch /E480:/
|
||||
\ | endtry"
|
||||
<
|
||||
If the encoding of the program output differs from the
|
||||
'encoding' option, you can use the 'makeencoding'
|
||||
option to specify the encoding.
|
||||
|
||||
*:lgrepa* *:lgrepadd*
|
||||
:lgrepa[dd][!] [arguments]
|
||||
Same as ":grepadd", except the location list for the
|
||||
|
@ -655,7 +655,6 @@ Short explanation of each option: *option-list*
|
||||
'cscoperelative' 'csre' Use cscope.out path basename as prefix
|
||||
'cscopetag' 'cst' use cscope for tag commands
|
||||
'cscopetagorder' 'csto' determines ":cstag" search order
|
||||
'cscopeverbose' 'csverb' give messages when adding a cscope database
|
||||
'cursorbind' 'crb' move cursor in window as it moves in other windows
|
||||
'cursorcolumn' 'cuc' highlight the screen column of the cursor
|
||||
'cursorline' 'cul' highlight the screen line of the cursor
|
||||
@ -762,6 +761,7 @@ Short explanation of each option: *option-list*
|
||||
'loadplugins' 'lpl' load plugin scripts when starting up
|
||||
'magic' changes special characters in search patterns
|
||||
'makeef' 'mef' name of the errorfile for ":make"
|
||||
'makeencoding' 'menc' encoding of external make/grep commands
|
||||
'makeprg' 'mp' program to use for the ":make" command
|
||||
'matchpairs' 'mps' pairs of characters that "%" can match
|
||||
'matchtime' 'mat' tenths of a second to show matching paren
|
||||
|
@ -249,14 +249,14 @@ argument.
|
||||
for reading or writing a ShaDa file. Can be used to find
|
||||
out what is happening upon startup and exit.
|
||||
Example: >
|
||||
vim -V8 foobar
|
||||
nvim -V8
|
||||
|
||||
-V[N]{filename}
|
||||
Like -V and set 'verbosefile' to {filename}. The result is
|
||||
that messages are not displayed but written to the file
|
||||
{filename}. {filename} must not start with a digit.
|
||||
Like -V and set 'verbosefile' to {filename}. Messages are not
|
||||
displayed; instead they are written to the file {filename}.
|
||||
{filename} must not start with a digit.
|
||||
Example: >
|
||||
vim -V20vimlog foobar
|
||||
nvim -V20vimlog
|
||||
<
|
||||
*-D*
|
||||
-D Debugging. Go to debugging mode when executing the first
|
||||
@ -355,6 +355,10 @@ argument.
|
||||
instead.
|
||||
See also |silent-mode|, which does start a (limited) UI.
|
||||
|
||||
--listen {addr} *--listen*
|
||||
Start |RPC| server on pipe or TCP address {addr}. Sets the
|
||||
primary listen address |v:servername| to {addr}. |serverstart()|
|
||||
|
||||
==============================================================================
|
||||
2. Initialization *initialization* *startup*
|
||||
|
||||
@ -439,15 +443,14 @@ accordingly. Vim proceeds in this order:
|
||||
:runtime! filetype.vim
|
||||
:runtime! ftplugin.vim
|
||||
:runtime! indent.vim
|
||||
< This step is skipped if ":filetype ..." was called before now or if
|
||||
the "-u NONE" command line argument was given.
|
||||
< Skipped if ":filetype … off" was called or if the "-u NONE" command
|
||||
line argument was given.
|
||||
|
||||
5. Enable syntax highlighting.
|
||||
This does the same as the command: >
|
||||
:runtime! syntax/syntax.vim
|
||||
< Note: This enables filetype detection even if ":filetype off" was
|
||||
called before now.
|
||||
This step is skipped if the "-u NONE" command line argument was given.
|
||||
< Skipped if ":syntax off" was called or if the "-u NONE" command
|
||||
line argument was given.
|
||||
|
||||
6. Load the plugin scripts. *load-plugins*
|
||||
This does the same as the command: >
|
||||
@ -1392,4 +1395,4 @@ RPC clients for debugging. $NVIM_LOG_FILE contains the log file path: >
|
||||
Usually the file is ~/.local/share/nvim/log unless that path is inaccessible
|
||||
or if $NVIM_LOG_FILE was set before |startup|.
|
||||
|
||||
vim:tw=78:ts=8:ft=help:norl:
|
||||
vim:noet:tw=78:ts=8:ft=help:norl:
|
||||
|
@ -4709,17 +4709,7 @@ ctermbg={color-nr} *highlight-ctermbg*
|
||||
"cterm". For example, on some systems "cterm=bold ctermfg=3" gives
|
||||
another color, on others you just get color 3.
|
||||
|
||||
For an xterm this depends on your resources, and is a bit
|
||||
unpredictable. See your xterm documentation for the defaults. The
|
||||
colors for a color-xterm can be changed from the .Xdefaults file.
|
||||
Unfortunately this means that it's not possible to get the same colors
|
||||
for each user.
|
||||
|
||||
The MSDOS standard colors are fixed (in a console window), so these
|
||||
have been used for the names. But the meaning of color names in X11
|
||||
are fixed, so these color settings have been used, to make the
|
||||
highlighting settings portable (complicated, isn't it?). The
|
||||
following names are recognized, with the color number used:
|
||||
The following names are recognized, with the color number used:
|
||||
|
||||
*cterm-colors*
|
||||
NR-16 NR-8 COLOR NAME ~
|
||||
@ -4919,6 +4909,8 @@ MatchParen The character under the cursor or just before it, if it
|
||||
|
||||
*hl-ModeMsg*
|
||||
ModeMsg 'showmode' message (e.g., "-- INSERT --")
|
||||
*hl-MsgSeparator*
|
||||
MsgSeparator Separator for scrolled messages, `msgsep` flag of 'display'
|
||||
*hl-MoreMsg*
|
||||
MoreMsg |more-prompt|
|
||||
*hl-NonText*
|
||||
|
@ -38,13 +38,13 @@ Otherwise Nvim cannot know what sequences your terminal expects, and weird
|
||||
or sub-optimal behavior will result (scrolling quirks, wrong colors, etc.).
|
||||
|
||||
$TERM is also important because it is mirrored by SSH to the remote session,
|
||||
unlike other common client-end environment variables ($COLORTERM,
|
||||
$XTERM_VERSION, $VTE_VERSION, $KONSOLE_PROFILE_NAME, $TERM_PROGRAM, ...).
|
||||
unlike most other environment variables.
|
||||
|
||||
For this terminal Set $TERM to |builtin-terms|
|
||||
-------------------------------------------------------------------------
|
||||
iTerm (original) iterm, iTerm.app N
|
||||
iTerm2 (new capabilities) iterm2, iTerm2.app Y
|
||||
Konsole konsole-256color N
|
||||
anything libvte-based vte, vte-256color Y
|
||||
(e.g. GNOME Terminal) (aliases: gnome, gnome-256color)
|
||||
tmux tmux, tmux-256color Y
|
||||
@ -232,11 +232,6 @@ correct values. See |:mode|.
|
||||
Slow and fast terminals *slow-fast-terminal*
|
||||
*slow-terminal*
|
||||
|
||||
If you have a fast terminal you may like to set the 'ruler' option. The
|
||||
cursor position is shown in the status line. If you are using horizontal
|
||||
scrolling ('wrap' option off) consider setting 'sidescroll' to a small
|
||||
number.
|
||||
|
||||
If you have a slow terminal you may want to reset the 'showcmd' and 'ruler'
|
||||
options. The command characters and cursor positions will not be shown in the
|
||||
status line (which involves a lot of cursor motions and attribute changes for
|
||||
|
@ -9,7 +9,7 @@ Nvim UI protocol *ui*
|
||||
Type |gO| to see the table of contents.
|
||||
|
||||
==============================================================================
|
||||
Introduction *ui-intro*
|
||||
UI Events *ui-events*
|
||||
|
||||
GUIs can be implemented as external processes communicating with Nvim over the
|
||||
RPC API. The UI model consists of a terminal-like grid with a single,
|
||||
@ -30,10 +30,22 @@ a dictionary with these (optional) keys:
|
||||
`ext_cmdline` Externalize the cmdline. |ui-cmdline|
|
||||
`ext_wildmenu` Externalize the wildmenu. |ui-ext-wildmenu|
|
||||
|
||||
Nvim will then send msgpack-rpc notifications, with the method name "redraw"
|
||||
and a single argument, an array of screen update events.
|
||||
Update events are tuples whose first element is the event name and remaining
|
||||
elements the event parameters.
|
||||
Specifying a non-existent option is an error. To facilitate an ui that
|
||||
supports different versions of Nvim, the |api-metadata| key `ui_options`
|
||||
contains the list of supported options. Additionally Nvim currently requires
|
||||
that all connected UIs use the same set of widgets. Therefore the active
|
||||
widgets will be the intersection of the requested widget sets of all connected
|
||||
UIs. The "option_set" event will be used to specify which widgets actually are
|
||||
active.
|
||||
|
||||
After attaching, Nvim will send msgpack-rpc notifications, with the method
|
||||
name "redraw" and a single argument, an array of screen update events. Update
|
||||
events are arrays whose first element is the event name and remaining elements
|
||||
are each tuples of event parameters. This allows multiple events of the same
|
||||
kind to be sent in a row without the event name being repeated. This batching
|
||||
is mostly used for "put", as each "put" event just puts contents in one screen
|
||||
cell, but clients must be prepared for multiple argument sets being batched
|
||||
for all event kinds.
|
||||
|
||||
Events must be handled in order. The user should only see the updated screen
|
||||
state after all events in the same "redraw" batch are processed (not any
|
||||
@ -80,6 +92,29 @@ Global Events *ui-global*
|
||||
|
||||
Some keys are missing in some modes.
|
||||
|
||||
["option_set", name, value]
|
||||
The value of ui related option `name` changed. The sent options are
|
||||
listed below:
|
||||
|
||||
'arabicshape'
|
||||
'ambiwith'
|
||||
'emoji'
|
||||
'guifont'
|
||||
'guifontset'
|
||||
'guifontwide'
|
||||
'linespace'
|
||||
'showtabline'
|
||||
'termguicolors'
|
||||
`ext_*` (all |ui-ext-options|)
|
||||
|
||||
Options are not added to the list if their effects are already taken
|
||||
care of. For instance, instead of forwarding the raw 'mouse' option
|
||||
value, `mouse_on` and `mouse_off` directly indicate if mouse support
|
||||
is active right now. Some options like 'ambiwith' have already taken
|
||||
effect on the grid, where appropriate empty cells are added, however
|
||||
an ui might still use these options when rendering raw text sent from
|
||||
Nvim, like the text of the cmdline when |ui-ext-cmdline| is set.
|
||||
|
||||
["mode_change", mode, mode_idx]
|
||||
The mode changed. The first parameter `mode` is a string representing
|
||||
the current mode. `mode_idx` is an index into the array received in
|
||||
|
@ -207,21 +207,18 @@ g8 Print the hex values of the bytes used in the
|
||||
:sh[ell] Removed. |vim-differences| {Nvim}
|
||||
|
||||
*:terminal* *:te*
|
||||
:te[rminal][!] [{cmd}] Execute {cmd} with 'shell' in a new |terminal| buffer.
|
||||
Equivalent to: >
|
||||
:enew
|
||||
:call termopen('{cmd}')
|
||||
<
|
||||
See |termopen()|.
|
||||
:te[rminal][!] [{cmd}] Execute {cmd} with 'shell' in a new |terminal-emulator|
|
||||
buffer. Without {cmd}, start an interactive 'shell'.
|
||||
|
||||
Without {cmd}, start an interactive shell.
|
||||
Type |i| to enter |Terminal-mode|, then keys are sent to
|
||||
the job running in the terminal. Type <C-\><C-N> to
|
||||
leave Terminal-mode. |CTRL-\_CTRL-N|
|
||||
|
||||
Creating the terminal buffer fails when changes have been
|
||||
made to the current buffer, unless 'hidden' is set.
|
||||
Fails if changes have been made to the current buffer,
|
||||
unless 'hidden' is set.
|
||||
|
||||
To enter |Terminal-mode| automatically: >
|
||||
autocmd BufEnter term://* startinsert
|
||||
autocmd BufLeave term://* stopinsert
|
||||
autocmd TermOpen * startinsert
|
||||
<
|
||||
*:!cmd* *:!* *E34*
|
||||
:!{cmd} Execute {cmd} with 'shell'. See also |:terminal|.
|
||||
|
@ -32,8 +32,10 @@ a complete and centralized reference of those differences.
|
||||
- 'backupdir' defaults to .,~/.local/share/nvim/backup (|xdg|)
|
||||
- 'belloff' defaults to "all"
|
||||
- 'complete' doesn't include "i"
|
||||
- 'cscopeverbose' is enabled
|
||||
- 'directory' defaults to ~/.local/share/nvim/swap// (|xdg|), auto-created
|
||||
- 'display' defaults to "lastline"
|
||||
- 'display' defaults to "lastline,msgsep"
|
||||
- 'fillchars' defaults (in effect) to "vert:│,fold:·"
|
||||
- 'formatoptions' defaults to "tcqj"
|
||||
- 'history' defaults to 10000 (the maximum)
|
||||
- 'hlsearch' is set by default
|
||||
@ -47,6 +49,7 @@ a complete and centralized reference of those differences.
|
||||
- 'ruler' is set by default
|
||||
- 'sessionoptions' doesn't include "options"
|
||||
- 'showcmd' is set by default
|
||||
- 'sidescroll' defaults to 1
|
||||
- 'smarttab' is set by default
|
||||
- 'tabpagemax' defaults to 50
|
||||
- 'tags' defaults to "./tags;,tags"
|
||||
@ -70,6 +73,7 @@ Providers
|
||||
Ruby plugins |provider-ruby|
|
||||
Shared data |shada|
|
||||
Embedded terminal |terminal|
|
||||
VimL parser |nvim_parse_expression()|
|
||||
XDG base directories |xdg|
|
||||
|
||||
USER EXPERIENCE ~
|
||||
@ -126,7 +130,9 @@ Some `CTRL-SHIFT-...` key chords are distinguished from `CTRL-...` variants
|
||||
|
||||
Options:
|
||||
'cpoptions' flags: |cpo-_|
|
||||
'display' flag `msgsep` to minimize scrolling when showing messages
|
||||
'guicursor' works in the terminal
|
||||
'fillchars' flag `msgsep` (see 'display' above)
|
||||
'inccommand' shows interactive results for |:substitute|-like commands
|
||||
'scrollback'
|
||||
'statusline' supports unlimited alignment sections
|
||||
@ -160,19 +166,23 @@ Events:
|
||||
|
||||
Highlight groups:
|
||||
|hl-NormalNC| highlights non-current windows
|
||||
|hl-MsgSeparator| highlights separator for scrolled messages
|
||||
|hl-QuickFixLine|
|
||||
|hl-Substitute|
|
||||
|hl-TermCursor|
|
||||
|hl-TermCursorNC|
|
||||
|hl-Whitespace| highlights 'listchars' whitespace
|
||||
|expr-highlight| highlight groups (prefixed with "Nvim")
|
||||
|
||||
UI:
|
||||
*E5408* *E5409* *g:Nvim_color_expr* *g:Nvim_color_cmdline*
|
||||
Command-line coloring is supported. Only |input()| and |inputdialog()| may
|
||||
be colored. For testing purposes expressions (e.g. |i_CTRL-R_=|) and regular
|
||||
command-line (|:|) are colored by callbacks defined in `g:Nvim_color_expr`
|
||||
and `g:Nvim_color_cmdline` respectively (these callbacks are for testing
|
||||
only, and will be removed in a future version).
|
||||
Command-line highlighting:
|
||||
The expression prompt (|@=|, |c_CTRL-R_=|, |i_CTRL-R_=|) is highlighted
|
||||
using a built-in VimL expression parser. |expr-highlight|
|
||||
*E5408* *E5409*
|
||||
|input()|, |inputdialog()| support custom highlighting. |input()-highlight|
|
||||
*g:Nvim_color_cmdline*
|
||||
(Experimental) Command-line (|:|) is colored by callback defined in
|
||||
`g:Nvim_color_cmdline` (this callback is for testing only, and will be
|
||||
removed in the future).
|
||||
|
||||
==============================================================================
|
||||
4. Changed features *nvim-features-changed*
|
||||
@ -299,7 +309,8 @@ Highlight groups:
|
||||
|hl-ColorColumn|, |hl-CursorColumn| are lower priority than most other
|
||||
groups
|
||||
|
||||
The variable name "count" is no fallback for |v:count| anymore.
|
||||
VimL (Vim script) compatibility:
|
||||
`count` does not alias to |v:count|
|
||||
|
||||
==============================================================================
|
||||
5. Missing legacy features *nvim-features-missing*
|
||||
@ -327,22 +338,26 @@ Ed-compatible mode:
|
||||
":set noedcompatible" is ignored
|
||||
":set edcompatible" is an error
|
||||
|
||||
*t_xx* *:set-termcap* *termcap-options* *t_AB* *t_Sb* *t_vb* *t_SI*
|
||||
*t_xx* *termcap-options* *t_AB* *t_Sb* *t_vb* *t_SI*
|
||||
Nvim does not have special `t_XX` options nor <t_XX> keycodes to configure
|
||||
terminal capabilities. Instead Nvim treats the terminal as any other UI. For
|
||||
example, 'guicursor' sets the terminal cursor style if possible.
|
||||
|
||||
*'term'* *E529* *E530* *E531*
|
||||
*:set-termcap*
|
||||
Start Nvim with 'verbose' level 3 to see the terminal capabilities. >
|
||||
nvim -V3
|
||||
<
|
||||
*'term'* *E529* *E530* *E531*
|
||||
'term' reflects the terminal type derived from |$TERM| and other environment
|
||||
checks. For debugging only; not reliable during startup. >
|
||||
:echo &term
|
||||
"builtin_x" means one of the |builtin-terms| was chosen, because the expected
|
||||
terminfo file was not found on the system.
|
||||
|
||||
*termcap*
|
||||
*termcap*
|
||||
Nvim never uses the termcap database, only |terminfo| and |builtin-terms|.
|
||||
|
||||
*xterm-8bit* *xterm-8-bit*
|
||||
*xterm-8bit* *xterm-8-bit*
|
||||
Xterm can be run in a mode where it uses true 8-bit CSI. Supporting this
|
||||
requires autodetection of whether the terminal is in UTF-8 mode or non-UTF-8
|
||||
mode, as the 8-bit CSI character has to be written differently in each case.
|
||||
@ -365,7 +380,6 @@ MS-DOS support:
|
||||
Test functions:
|
||||
test_alloc_fail()
|
||||
test_autochdir()
|
||||
test_disable_char_avail()
|
||||
test_garbagecollect_now()
|
||||
test_null_channel()
|
||||
test_null_dict()
|
||||
@ -373,6 +387,7 @@ Test functions:
|
||||
test_null_list()
|
||||
test_null_partial()
|
||||
test_null_string()
|
||||
test_override()
|
||||
test_settime()
|
||||
|
||||
Other options:
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -6,7 +6,7 @@ if exists('b:did_ftplugin') || &filetype !=# 'man'
|
||||
endif
|
||||
let b:did_ftplugin = 1
|
||||
|
||||
let s:pager = !exists('b:man_sect')
|
||||
let s:pager = get(s:, 'pager', 0) || !exists('b:man_sect')
|
||||
|
||||
if s:pager
|
||||
call man#init_pager()
|
||||
@ -35,7 +35,7 @@ if !exists('g:no_plugin_maps') && !exists('g:no_man_maps')
|
||||
nnoremap <silent> <buffer> <C-]> :Man<CR>
|
||||
nnoremap <silent> <buffer> K :Man<CR>
|
||||
nnoremap <silent> <buffer> <C-T> :call man#pop_tag()<CR>
|
||||
if s:pager
|
||||
if 1 == bufnr('%') || s:pager
|
||||
nnoremap <silent> <buffer> <nowait> q :lclose<CR>:q<CR>
|
||||
else
|
||||
nnoremap <silent> <buffer> <nowait> q :lclose<CR><C-W>c
|
||||
|
168
runtime/lua/man.lua
Normal file
168
runtime/lua/man.lua
Normal file
@ -0,0 +1,168 @@
|
||||
local buf_hls = {}
|
||||
|
||||
local function highlight_line(line, linenr)
|
||||
local chars = {}
|
||||
local prev_char = ''
|
||||
local overstrike, escape = false, false
|
||||
local hls = {} -- Store highlight groups as { attr, start, final }
|
||||
local NONE, BOLD, UNDERLINE, ITALIC = 0, 1, 2, 3
|
||||
local hl_groups = {[BOLD]="manBold", [UNDERLINE]="manUnderline", [ITALIC]="manItalic"}
|
||||
local attr = NONE
|
||||
local byte = 0 -- byte offset
|
||||
|
||||
local function end_attr_hl(attr)
|
||||
for i, hl in ipairs(hls) do
|
||||
if hl.attr == attr and hl.final == -1 then
|
||||
hl.final = byte
|
||||
hls[i] = hl
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function add_attr_hl(code)
|
||||
local continue_hl = true
|
||||
if code == 0 then
|
||||
attr = NONE
|
||||
continue_hl = false
|
||||
elseif code == 1 then
|
||||
attr = BOLD
|
||||
elseif code == 22 then
|
||||
attr = BOLD
|
||||
continue_hl = false
|
||||
elseif code == 3 then
|
||||
attr = ITALIC
|
||||
elseif code == 23 then
|
||||
attr = ITALIC
|
||||
continue_hl = false
|
||||
elseif code == 4 then
|
||||
attr = UNDERLINE
|
||||
elseif code == 24 then
|
||||
attr = UNDERLINE
|
||||
continue_hl = false
|
||||
else
|
||||
attr = NONE
|
||||
return
|
||||
end
|
||||
|
||||
if continue_hl then
|
||||
hls[#hls + 1] = {attr=attr, start=byte, final=-1}
|
||||
else
|
||||
if attr == NONE then
|
||||
for a, _ in pairs(hl_groups) do
|
||||
end_attr_hl(a)
|
||||
end
|
||||
else
|
||||
end_attr_hl(attr)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Break input into UTF8 code points. ASCII code points (from 0x00 to 0x7f)
|
||||
-- can be represented in one byte. Any code point above that is represented by
|
||||
-- a leading byte (0xc0 and above) and continuation bytes (0x80 to 0xbf, or
|
||||
-- decimal 128 to 191).
|
||||
for char in line:gmatch("[^\128-\191][\128-\191]*") do
|
||||
if overstrike then
|
||||
local last_hl = hls[#hls]
|
||||
if char == prev_char then
|
||||
if char == '_' and attr == UNDERLINE and last_hl and last_hl.final == byte then
|
||||
-- This underscore is in the middle of an underlined word
|
||||
attr = UNDERLINE
|
||||
else
|
||||
attr = BOLD
|
||||
end
|
||||
elseif prev_char == '_' then
|
||||
-- char is underlined
|
||||
attr = UNDERLINE
|
||||
elseif prev_char == '+' and char == 'o' then
|
||||
-- bullet (overstrike text '+^Ho')
|
||||
attr = BOLD
|
||||
char = '·'
|
||||
elseif prev_char == '·' and char == 'o' then
|
||||
-- bullet (additional handling for '+^H+^Ho^Ho')
|
||||
attr = BOLD
|
||||
char = '·'
|
||||
else
|
||||
-- use plain char
|
||||
attr = NONE
|
||||
end
|
||||
|
||||
-- Grow the previous highlight group if possible
|
||||
if last_hl and last_hl.attr == attr and last_hl.final == byte then
|
||||
last_hl.final = byte + #char
|
||||
else
|
||||
hls[#hls + 1] = {attr=attr, start=byte, final=byte + #char}
|
||||
end
|
||||
|
||||
overstrike = false
|
||||
prev_char = ''
|
||||
byte = byte + #char
|
||||
chars[#chars + 1] = char
|
||||
elseif escape then
|
||||
-- Use prev_char to store the escape sequence
|
||||
prev_char = prev_char .. char
|
||||
-- We only want to match against SGR sequences, which consist of ESC
|
||||
-- followed by '[', then a series of parameter and intermediate bytes in
|
||||
-- the range 0x20 - 0x3f, then 'm'. (See ECMA-48, sections 5.4 & 8.3.117)
|
||||
local sgr = prev_char:match("^%[([\032-\063]*)m$")
|
||||
if sgr then
|
||||
local match = ''
|
||||
while sgr and #sgr > 0 do
|
||||
-- Match against SGR parameters, which may be separated by ';'
|
||||
match, sgr = sgr:match("^(%d*);?(.*)")
|
||||
add_attr_hl(match + 0) -- coerce to number
|
||||
end
|
||||
escape = false
|
||||
elseif not prev_char:match("^%[[\032-\063]*$") then
|
||||
-- Stop looking if this isn't a partial CSI sequence
|
||||
escape = false
|
||||
end
|
||||
elseif char == "\027" then
|
||||
escape = true
|
||||
prev_char = ''
|
||||
elseif char == "\b" then
|
||||
overstrike = true
|
||||
prev_char = chars[#chars]
|
||||
byte = byte - #prev_char
|
||||
chars[#chars] = nil
|
||||
else
|
||||
byte = byte + #char
|
||||
chars[#chars + 1] = char
|
||||
end
|
||||
end
|
||||
|
||||
for _, hl in ipairs(hls) do
|
||||
if hl.attr ~= NONE then
|
||||
buf_hls[#buf_hls + 1] = {
|
||||
0,
|
||||
-1,
|
||||
hl_groups[hl.attr],
|
||||
linenr - 1,
|
||||
hl.start,
|
||||
hl.final
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
return table.concat(chars, '')
|
||||
end
|
||||
|
||||
local function highlight_man_page()
|
||||
local mod = vim.api.nvim_buf_get_option(0, "modifiable")
|
||||
vim.api.nvim_buf_set_option(0, "modifiable", true)
|
||||
|
||||
local lines = vim.api.nvim_buf_get_lines(0, 0, -1, false)
|
||||
for i, line in ipairs(lines) do
|
||||
lines[i] = highlight_line(line, i)
|
||||
end
|
||||
vim.api.nvim_buf_set_lines(0, 0, -1, false, lines)
|
||||
|
||||
for _, args in ipairs(buf_hls) do
|
||||
vim.api.nvim_buf_add_highlight(unpack(args))
|
||||
end
|
||||
buf_hls = {}
|
||||
|
||||
vim.api.nvim_buf_set_option(0, "modifiable", mod)
|
||||
end
|
||||
|
||||
return { highlight_man_page = highlight_man_page }
|
@ -1087,6 +1087,9 @@ if has("quickfix")
|
||||
call <SID>OptionG("gp", &gp)
|
||||
call append("$", "grepformat\tlist of formats for output of 'grepprg'")
|
||||
call <SID>OptionG("gfm", &gfm)
|
||||
call append("$", "makeencoding\tencoding of the \":make\" and \":grep\" output")
|
||||
call append("$", "\t(global or local to buffer)")
|
||||
call <SID>OptionG("menc", &menc)
|
||||
endif
|
||||
|
||||
|
||||
|
@ -1,8 +1 @@
|
||||
function! s:complete(lead, _line, _pos) abort
|
||||
return sort(filter(map(globpath(&runtimepath, 'autoload/health/*', 1, 1),
|
||||
\ 'fnamemodify(v:val, ":t:r")'),
|
||||
\ 'empty(a:lead) || v:val[:strlen(a:lead)-1] ==# a:lead'))
|
||||
endfunction
|
||||
|
||||
command! -nargs=* -complete=customlist,s:complete CheckHealth
|
||||
\ call health#check([<f-args>])
|
||||
autocmd CmdUndefined CheckHealth checkhealth
|
||||
|
@ -56,6 +56,6 @@ function! s:LoadRemotePlugins() abort
|
||||
endif
|
||||
endfunction
|
||||
|
||||
command! UpdateRemotePlugins call remote#host#UpdateRemotePlugins()
|
||||
command! -bar UpdateRemotePlugins call remote#host#UpdateRemotePlugins()
|
||||
|
||||
call s:LoadRemotePlugins()
|
||||
|
@ -1,11 +1,15 @@
|
||||
" Vim support file to detect file types in scripts
|
||||
"
|
||||
" Maintainer: Bram Moolenaar <Bram@vim.org>
|
||||
" Last change: 2017 Aug 27
|
||||
" Last change: 2017 Nov 11
|
||||
|
||||
" This file is called by an autocommand for every file that has just been
|
||||
" loaded into a buffer. It checks if the type of file can be recognized by
|
||||
" the file contents. The autocommand is in $VIMRUNTIME/filetype.vim.
|
||||
"
|
||||
" Note that the pattern matches are done with =~# to avoid the value of the
|
||||
" 'ignorecase' option making a difference. Where case is to be ignored use
|
||||
" =~? instead. Do not use =~ anywhere.
|
||||
|
||||
|
||||
" Only do the rest when the FileType autocommand has not been triggered yet.
|
||||
@ -28,12 +32,12 @@ set cpo&vim
|
||||
|
||||
let s:line1 = getline(1)
|
||||
|
||||
if s:line1 =~ "^#!"
|
||||
if s:line1 =~# "^#!"
|
||||
" A script that starts with "#!".
|
||||
|
||||
" Check for a line like "#!/usr/bin/env VAR=val bash". Turn it into
|
||||
" "#!/usr/bin/bash" to make matching easier.
|
||||
if s:line1 =~ '^#!\s*\S*\<env\s'
|
||||
if s:line1 =~# '^#!\s*\S*\<env\s'
|
||||
let s:line1 = substitute(s:line1, '\S\+=\S\+', '', 'g')
|
||||
let s:line1 = substitute(s:line1, '\<env\s\+', '', '')
|
||||
endif
|
||||
@ -44,11 +48,11 @@ if s:line1 =~ "^#!"
|
||||
" "#!/usr/bin/env perl [path/args]"
|
||||
" If there is no path use the first word: "#!perl [path/args]".
|
||||
" Otherwise get the last word after a slash: "#!/usr/bin/perl [path/args]".
|
||||
if s:line1 =~ '^#!\s*\a:[/\\]'
|
||||
if s:line1 =~# '^#!\s*\a:[/\\]'
|
||||
let s:name = substitute(s:line1, '^#!.*[/\\]\(\i\+\).*', '\1', '')
|
||||
elseif s:line1 =~ '^#!.*\<env\>'
|
||||
elseif s:line1 =~# '^#!.*\<env\>'
|
||||
let s:name = substitute(s:line1, '^#!.*\<env\>\s\+\(\i\+\).*', '\1', '')
|
||||
elseif s:line1 =~ '^#!\s*[^/\\ ]*\>\([^/\\]\|$\)'
|
||||
elseif s:line1 =~# '^#!\s*[^/\\ ]*\>\([^/\\]\|$\)'
|
||||
let s:name = substitute(s:line1, '^#!\s*\([^/\\ ]*\>\).*', '\1', '')
|
||||
else
|
||||
let s:name = substitute(s:line1, '^#!\s*\S*[/\\]\(\i\+\).*', '\1', '')
|
||||
@ -56,116 +60,116 @@ if s:line1 =~ "^#!"
|
||||
|
||||
" tcl scripts may have #!/bin/sh in the first line and "exec wish" in the
|
||||
" third line. Suggested by Steven Atkinson.
|
||||
if getline(3) =~ '^exec wish'
|
||||
if getline(3) =~# '^exec wish'
|
||||
let s:name = 'wish'
|
||||
endif
|
||||
|
||||
" Bourne-like shell scripts: bash bash2 ksh ksh93 sh
|
||||
if s:name =~ '^\(bash\d*\|\|ksh\d*\|sh\)\>'
|
||||
call SetFileTypeSH(s:line1) " defined in filetype.vim
|
||||
if s:name =~# '^\(bash\d*\|\|ksh\d*\|sh\)\>'
|
||||
call dist#ft#SetFileTypeSH(s:line1) " defined in filetype.vim
|
||||
|
||||
" csh scripts
|
||||
elseif s:name =~ '^csh\>'
|
||||
elseif s:name =~# '^csh\>'
|
||||
if exists("g:filetype_csh")
|
||||
call SetFileTypeShell(g:filetype_csh)
|
||||
call dist#ft#SetFileTypeShell(g:filetype_csh)
|
||||
else
|
||||
call SetFileTypeShell("csh")
|
||||
call dist#ft#SetFileTypeShell("csh")
|
||||
endif
|
||||
|
||||
" tcsh scripts
|
||||
elseif s:name =~ '^tcsh\>'
|
||||
call SetFileTypeShell("tcsh")
|
||||
elseif s:name =~# '^tcsh\>'
|
||||
call dist#ft#SetFileTypeShell("tcsh")
|
||||
|
||||
" Z shell scripts
|
||||
elseif s:name =~ '^zsh\>'
|
||||
elseif s:name =~# '^zsh\>'
|
||||
set ft=zsh
|
||||
|
||||
" TCL scripts
|
||||
elseif s:name =~ '^\(tclsh\|wish\|expectk\|itclsh\|itkwish\)\>'
|
||||
elseif s:name =~# '^\(tclsh\|wish\|expectk\|itclsh\|itkwish\)\>'
|
||||
set ft=tcl
|
||||
|
||||
" Expect scripts
|
||||
elseif s:name =~ '^expect\>'
|
||||
elseif s:name =~# '^expect\>'
|
||||
set ft=expect
|
||||
|
||||
" Gnuplot scripts
|
||||
elseif s:name =~ '^gnuplot\>'
|
||||
elseif s:name =~# '^gnuplot\>'
|
||||
set ft=gnuplot
|
||||
|
||||
" Makefiles
|
||||
elseif s:name =~ 'make\>'
|
||||
elseif s:name =~# 'make\>'
|
||||
set ft=make
|
||||
|
||||
" Lua
|
||||
elseif s:name =~ 'lua'
|
||||
elseif s:name =~# 'lua'
|
||||
set ft=lua
|
||||
|
||||
" Perl 6
|
||||
elseif s:name =~ 'perl6'
|
||||
elseif s:name =~# 'perl6'
|
||||
set ft=perl6
|
||||
|
||||
" Perl
|
||||
elseif s:name =~ 'perl'
|
||||
elseif s:name =~# 'perl'
|
||||
set ft=perl
|
||||
|
||||
" PHP
|
||||
elseif s:name =~ 'php'
|
||||
elseif s:name =~# 'php'
|
||||
set ft=php
|
||||
|
||||
" Python
|
||||
elseif s:name =~ 'python'
|
||||
elseif s:name =~# 'python'
|
||||
set ft=python
|
||||
|
||||
" Groovy
|
||||
elseif s:name =~ '^groovy\>'
|
||||
elseif s:name =~# '^groovy\>'
|
||||
set ft=groovy
|
||||
|
||||
" Ruby
|
||||
elseif s:name =~ 'ruby'
|
||||
elseif s:name =~# 'ruby'
|
||||
set ft=ruby
|
||||
|
||||
" JavaScript
|
||||
elseif s:name =~ 'node\(js\)\=\>' || s:name =~ 'rhino\>'
|
||||
elseif s:name =~# 'node\(js\)\=\>' || s:name =~# 'rhino\>'
|
||||
set ft=javascript
|
||||
|
||||
" BC calculator
|
||||
elseif s:name =~ '^bc\>'
|
||||
elseif s:name =~# '^bc\>'
|
||||
set ft=bc
|
||||
|
||||
" sed
|
||||
elseif s:name =~ 'sed\>'
|
||||
elseif s:name =~# 'sed\>'
|
||||
set ft=sed
|
||||
|
||||
" OCaml-scripts
|
||||
elseif s:name =~ 'ocaml'
|
||||
elseif s:name =~# 'ocaml'
|
||||
set ft=ocaml
|
||||
|
||||
" Awk scripts
|
||||
elseif s:name =~ 'awk\>'
|
||||
elseif s:name =~# 'awk\>'
|
||||
set ft=awk
|
||||
|
||||
" Website MetaLanguage
|
||||
elseif s:name =~ 'wml'
|
||||
elseif s:name =~# 'wml'
|
||||
set ft=wml
|
||||
|
||||
" Scheme scripts
|
||||
elseif s:name =~ 'scheme'
|
||||
elseif s:name =~# 'scheme'
|
||||
set ft=scheme
|
||||
|
||||
" CFEngine scripts
|
||||
elseif s:name =~ 'cfengine'
|
||||
elseif s:name =~# 'cfengine'
|
||||
set ft=cfengine
|
||||
|
||||
" Erlang scripts
|
||||
elseif s:name =~ 'escript'
|
||||
elseif s:name =~# 'escript'
|
||||
set ft=erlang
|
||||
|
||||
" Haskell
|
||||
elseif s:name =~ 'haskell'
|
||||
elseif s:name =~# 'haskell'
|
||||
set ft=haskell
|
||||
|
||||
" Scala
|
||||
elseif s:name =~ 'scala\>'
|
||||
elseif s:name =~# 'scala\>'
|
||||
set ft=scala
|
||||
|
||||
endif
|
||||
@ -180,28 +184,28 @@ else
|
||||
let s:line5 = getline(5)
|
||||
|
||||
" Bourne-like shell scripts: sh ksh bash bash2
|
||||
if s:line1 =~ '^:$'
|
||||
call SetFileTypeSH(s:line1) " defined in filetype.vim
|
||||
if s:line1 =~# '^:$'
|
||||
call dist#ft#SetFileTypeSH(s:line1) " defined in filetype.vim
|
||||
|
||||
" Z shell scripts
|
||||
elseif s:line1 =~ '^#compdef\>' || s:line1 =~ '^#autoload\>' ||
|
||||
\ "\n".s:line1."\n".s:line2."\n".s:line3."\n".s:line4."\n".s:line5 =~ '\n\s*emulate\s\+\%(-[LR]\s\+\)\=[ckz]\=sh\>'
|
||||
elseif s:line1 =~# '^#compdef\>' || s:line1 =~# '^#autoload\>' ||
|
||||
\ "\n".s:line1."\n".s:line2."\n".s:line3."\n".s:line4."\n".s:line5 =~# '\n\s*emulate\s\+\%(-[LR]\s\+\)\=[ckz]\=sh\>'
|
||||
set ft=zsh
|
||||
|
||||
" ELM Mail files
|
||||
elseif s:line1 =~ '^From \([a-zA-Z][a-zA-Z_0-9\.=-]*\(@[^ ]*\)\=\|-\) .* \(19\|20\)\d\d$'
|
||||
elseif s:line1 =~# '^From \([a-zA-Z][a-zA-Z_0-9\.=-]*\(@[^ ]*\)\=\|-\) .* \(19\|20\)\d\d$'
|
||||
set ft=mail
|
||||
|
||||
" Mason
|
||||
elseif s:line1 =~ '^<[%&].*>'
|
||||
elseif s:line1 =~# '^<[%&].*>'
|
||||
set ft=mason
|
||||
|
||||
" Vim scripts (must have '" vim' as the first line to trigger this)
|
||||
elseif s:line1 =~ '^" *[vV]im$'
|
||||
elseif s:line1 =~# '^" *[vV]im$'
|
||||
set ft=vim
|
||||
|
||||
" MOO
|
||||
elseif s:line1 =~ '^\*\* LambdaMOO Database, Format Version \%([1-3]\>\)\@!\d\+ \*\*$'
|
||||
elseif s:line1 =~# '^\*\* LambdaMOO Database, Format Version \%([1-3]\>\)\@!\d\+ \*\*$'
|
||||
set ft=moo
|
||||
|
||||
" Diff file:
|
||||
@ -215,40 +219,45 @@ else
|
||||
" - "=== ", "--- ", "+++ " (bzr diff, common case)
|
||||
" - "=== (removed|added|renamed|modified)" (bzr diff, alternative)
|
||||
" - "# HG changeset patch" in first line (Mercurial export format)
|
||||
elseif s:line1 =~ '^\(diff\>\|Only in \|\d\+\(,\d\+\)\=[cda]\d\+\>\|# It was generated by makepatch \|Index:\s\+\f\+\r\=$\|===== \f\+ \d\+\.\d\+ vs edited\|==== //\f\+#\d\+\|# HG changeset patch\)'
|
||||
\ || (s:line1 =~ '^--- ' && s:line2 =~ '^+++ ')
|
||||
\ || (s:line1 =~ '^\* looking for ' && s:line2 =~ '^\* comparing to ')
|
||||
\ || (s:line1 =~ '^\*\*\* ' && s:line2 =~ '^--- ')
|
||||
\ || (s:line1 =~ '^=== ' && ((s:line2 =~ '^=\{66\}' && s:line3 =~ '^--- ' && s:line4 =~ '^+++') || (s:line2 =~ '^--- ' && s:line3 =~ '^+++ ')))
|
||||
\ || (s:line1 =~ '^=== \(removed\|added\|renamed\|modified\)')
|
||||
elseif s:line1 =~# '^\(diff\>\|Only in \|\d\+\(,\d\+\)\=[cda]\d\+\>\|# It was generated by makepatch \|Index:\s\+\f\+\r\=$\|===== \f\+ \d\+\.\d\+ vs edited\|==== //\f\+#\d\+\|# HG changeset patch\)'
|
||||
\ || (s:line1 =~# '^--- ' && s:line2 =~# '^+++ ')
|
||||
\ || (s:line1 =~# '^\* looking for ' && s:line2 =~# '^\* comparing to ')
|
||||
\ || (s:line1 =~# '^\*\*\* ' && s:line2 =~# '^--- ')
|
||||
\ || (s:line1 =~# '^=== ' && ((s:line2 =~# '^=\{66\}' && s:line3 =~# '^--- ' && s:line4 =~# '^+++') || (s:line2 =~# '^--- ' && s:line3 =~# '^+++ ')))
|
||||
\ || (s:line1 =~# '^=== \(removed\|added\|renamed\|modified\)')
|
||||
set ft=diff
|
||||
|
||||
" PostScript Files (must have %!PS as the first line, like a2ps output)
|
||||
elseif s:line1 =~ '^%![ \t]*PS'
|
||||
elseif s:line1 =~# '^%![ \t]*PS'
|
||||
set ft=postscr
|
||||
|
||||
" M4 scripts: Guess there is a line that starts with "dnl".
|
||||
elseif s:line1 =~ '^\s*dnl\>'
|
||||
\ || s:line2 =~ '^\s*dnl\>'
|
||||
\ || s:line3 =~ '^\s*dnl\>'
|
||||
\ || s:line4 =~ '^\s*dnl\>'
|
||||
\ || s:line5 =~ '^\s*dnl\>'
|
||||
elseif s:line1 =~# '^\s*dnl\>'
|
||||
\ || s:line2 =~# '^\s*dnl\>'
|
||||
\ || s:line3 =~# '^\s*dnl\>'
|
||||
\ || s:line4 =~# '^\s*dnl\>'
|
||||
\ || s:line5 =~# '^\s*dnl\>'
|
||||
set ft=m4
|
||||
|
||||
" AmigaDos scripts
|
||||
elseif $TERM == "amiga"
|
||||
\ && (s:line1 =~# "^;" || s:line1 =~? '^\.bra')
|
||||
set ft=amiga
|
||||
|
||||
" SiCAD scripts (must have procn or procd as the first line to trigger this)
|
||||
elseif s:line1 =~? '^ *proc[nd] *$'
|
||||
set ft=sicad
|
||||
|
||||
" Purify log files start with "**** Purify"
|
||||
elseif s:line1 =~ '^\*\*\*\* Purify'
|
||||
elseif s:line1 =~# '^\*\*\*\* Purify'
|
||||
set ft=purifylog
|
||||
|
||||
" XML
|
||||
elseif s:line1 =~ '<?\s*xml.*?>'
|
||||
elseif s:line1 =~# '<?\s*xml.*?>'
|
||||
set ft=xml
|
||||
|
||||
" XHTML (e.g.: PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN")
|
||||
elseif s:line1 =~ '\<DTD\s\+XHTML\s'
|
||||
elseif s:line1 =~# '\<DTD\s\+XHTML\s'
|
||||
set ft=xhtml
|
||||
|
||||
" HTML (e.g.: <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN")
|
||||
@ -257,43 +266,43 @@ else
|
||||
set ft=html
|
||||
|
||||
" PDF
|
||||
elseif s:line1 =~ '^%PDF-'
|
||||
elseif s:line1 =~# '^%PDF-'
|
||||
set ft=pdf
|
||||
|
||||
" XXD output
|
||||
elseif s:line1 =~ '^\x\{7}: \x\{2} \=\x\{2} \=\x\{2} \=\x\{2} '
|
||||
elseif s:line1 =~# '^\x\{7}: \x\{2} \=\x\{2} \=\x\{2} \=\x\{2} '
|
||||
set ft=xxd
|
||||
|
||||
" RCS/CVS log output
|
||||
elseif s:line1 =~ '^RCS file:' || s:line2 =~ '^RCS file:'
|
||||
elseif s:line1 =~# '^RCS file:' || s:line2 =~# '^RCS file:'
|
||||
set ft=rcslog
|
||||
|
||||
" CVS commit
|
||||
elseif s:line2 =~ '^CVS:' || getline("$") =~ '^CVS: '
|
||||
elseif s:line2 =~# '^CVS:' || getline("$") =~# '^CVS: '
|
||||
set ft=cvs
|
||||
|
||||
" Prescribe
|
||||
elseif s:line1 =~ '^!R!'
|
||||
elseif s:line1 =~# '^!R!'
|
||||
set ft=prescribe
|
||||
|
||||
" Send-pr
|
||||
elseif s:line1 =~ '^SEND-PR:'
|
||||
elseif s:line1 =~# '^SEND-PR:'
|
||||
set ft=sendpr
|
||||
|
||||
" SNNS files
|
||||
elseif s:line1 =~ '^SNNS network definition file'
|
||||
elseif s:line1 =~# '^SNNS network definition file'
|
||||
set ft=snnsnet
|
||||
elseif s:line1 =~ '^SNNS pattern definition file'
|
||||
elseif s:line1 =~# '^SNNS pattern definition file'
|
||||
set ft=snnspat
|
||||
elseif s:line1 =~ '^SNNS result file'
|
||||
elseif s:line1 =~# '^SNNS result file'
|
||||
set ft=snnsres
|
||||
|
||||
" Virata
|
||||
elseif s:line1 =~ '^%.\{-}[Vv]irata'
|
||||
\ || s:line2 =~ '^%.\{-}[Vv]irata'
|
||||
\ || s:line3 =~ '^%.\{-}[Vv]irata'
|
||||
\ || s:line4 =~ '^%.\{-}[Vv]irata'
|
||||
\ || s:line5 =~ '^%.\{-}[Vv]irata'
|
||||
elseif s:line1 =~# '^%.\{-}[Vv]irata'
|
||||
\ || s:line2 =~# '^%.\{-}[Vv]irata'
|
||||
\ || s:line3 =~# '^%.\{-}[Vv]irata'
|
||||
\ || s:line4 =~# '^%.\{-}[Vv]irata'
|
||||
\ || s:line5 =~# '^%.\{-}[Vv]irata'
|
||||
set ft=virata
|
||||
|
||||
" Strace
|
||||
@ -301,17 +310,17 @@ else
|
||||
set ft=strace
|
||||
|
||||
" VSE JCL
|
||||
elseif s:line1 =~ '^\* $$ JOB\>' || s:line1 =~ '^// *JOB\>'
|
||||
elseif s:line1 =~# '^\* $$ JOB\>' || s:line1 =~# '^// *JOB\>'
|
||||
set ft=vsejcl
|
||||
|
||||
" TAK and SINDA
|
||||
elseif s:line4 =~ 'K & K Associates' || s:line2 =~ 'TAK 2000'
|
||||
elseif s:line4 =~# 'K & K Associates' || s:line2 =~# 'TAK 2000'
|
||||
set ft=takout
|
||||
elseif s:line3 =~ 'S Y S T E M S I M P R O V E D '
|
||||
elseif s:line3 =~# 'S Y S T E M S I M P R O V E D '
|
||||
set ft=sindaout
|
||||
elseif getline(6) =~ 'Run Date: '
|
||||
elseif getline(6) =~# 'Run Date: '
|
||||
set ft=takcmp
|
||||
elseif getline(9) =~ 'Node File 1'
|
||||
elseif getline(9) =~# 'Node File 1'
|
||||
set ft=sindacmp
|
||||
|
||||
" DNS zone files
|
||||
@ -319,34 +328,34 @@ else
|
||||
set ft=bindzone
|
||||
|
||||
" BAAN
|
||||
elseif s:line1 =~ '|\*\{1,80}' && s:line2 =~ 'VRC '
|
||||
\ || s:line2 =~ '|\*\{1,80}' && s:line3 =~ 'VRC '
|
||||
elseif s:line1 =~# '|\*\{1,80}' && s:line2 =~# 'VRC '
|
||||
\ || s:line2 =~# '|\*\{1,80}' && s:line3 =~# 'VRC '
|
||||
set ft=baan
|
||||
|
||||
" Valgrind
|
||||
elseif s:line1 =~ '^==\d\+== valgrind' || s:line3 =~ '^==\d\+== Using valgrind'
|
||||
elseif s:line1 =~# '^==\d\+== valgrind' || s:line3 =~# '^==\d\+== Using valgrind'
|
||||
set ft=valgrind
|
||||
|
||||
" Go docs
|
||||
elseif s:line1 =~ '^PACKAGE DOCUMENTATION$'
|
||||
elseif s:line1 =~# '^PACKAGE DOCUMENTATION$'
|
||||
set ft=godoc
|
||||
|
||||
" Renderman Interface Bytestream
|
||||
elseif s:line1 =~ '^##RenderMan'
|
||||
elseif s:line1 =~# '^##RenderMan'
|
||||
set ft=rib
|
||||
|
||||
" Scheme scripts
|
||||
elseif s:line1 =~ 'exec\s\+\S*scheme' || s:line2 =~ 'exec\s\+\S*scheme'
|
||||
elseif s:line1 =~# 'exec\s\+\S*scheme' || s:line2 =~# 'exec\s\+\S*scheme'
|
||||
set ft=scheme
|
||||
|
||||
" Git output
|
||||
elseif s:line1 =~ '^\(commit\|tree\|object\) \x\{40\}\>\|^tag \S\+$'
|
||||
elseif s:line1 =~# '^\(commit\|tree\|object\) \x\{40\}\>\|^tag \S\+$'
|
||||
set ft=git
|
||||
|
||||
" Gprof (gnu profiler)
|
||||
elseif s:line1 == 'Flat profile:'
|
||||
\ && s:line2 == ''
|
||||
\ && s:line3 =~ '^Each sample counts as .* seconds.$'
|
||||
\ && s:line3 =~# '^Each sample counts as .* seconds.$'
|
||||
set ft=gprof
|
||||
|
||||
" Erlang terms
|
||||
@ -357,18 +366,18 @@ else
|
||||
" CVS diff
|
||||
else
|
||||
let s:lnum = 1
|
||||
while getline(s:lnum) =~ "^? " && s:lnum < line("$")
|
||||
while getline(s:lnum) =~# "^? " && s:lnum < line("$")
|
||||
let s:lnum += 1
|
||||
endwhile
|
||||
if getline(s:lnum) =~ '^Index:\s\+\f\+$'
|
||||
if getline(s:lnum) =~# '^Index:\s\+\f\+$'
|
||||
set ft=diff
|
||||
|
||||
" locale input files: Formal Definitions of Cultural Conventions
|
||||
" filename must be like en_US, fr_FR@euro or en_US.UTF-8
|
||||
elseif expand("%") =~ '\a\a_\a\a\($\|[.@]\)\|i18n$\|POSIX$\|translit_'
|
||||
elseif expand("%") =~# '\a\a_\a\a\($\|[.@]\)\|i18n$\|POSIX$\|translit_'
|
||||
let s:lnum = 1
|
||||
while s:lnum < 100 && s:lnum < line("$")
|
||||
if getline(s:lnum) =~ '^LC_\(IDENTIFICATION\|CTYPE\|COLLATE\|MONETARY\|NUMERIC\|TIME\|MESSAGES\|PAPER\|TELEPHONE\|MEASUREMENT\|NAME\|ADDRESS\)$'
|
||||
if getline(s:lnum) =~# '^LC_\(IDENTIFICATION\|CTYPE\|COLLATE\|MONETARY\|NUMERIC\|TIME\|MESSAGES\|PAPER\|TELEPHONE\|MEASUREMENT\|NAME\|ADDRESS\)$'
|
||||
setf fdcc
|
||||
break
|
||||
endif
|
||||
|
BIN
runtime/spell/en.utf-8.spl
Normal file
BIN
runtime/spell/en.utf-8.spl
Normal file
Binary file not shown.
@ -32,7 +32,7 @@ syntax match dircolorsEscape '\\[abefnrtv?_\\^#]'
|
||||
syntax match dircolorsEscape '\\[0-9]\{3}'
|
||||
syntax match dircolorsEscape '\\x[0-9a-f]\{3}'
|
||||
|
||||
if !has('gui_running') && &t_Co == ''
|
||||
if !(has('gui_running') || &termguicolors) && &t_Co == ''
|
||||
syntax match dircolorsNumber '\<\d\+\>'
|
||||
highlight default link dircolorsNumber Number
|
||||
endif
|
||||
@ -84,7 +84,7 @@ endfunction
|
||||
|
||||
function! s:get_hi_str(color, place) abort
|
||||
if a:color >= 0 && a:color <= 255
|
||||
if has('gui_running')
|
||||
if has('gui_running') || &termguicolors
|
||||
return ' gui' . a:place . '=' . s:termguicolors[a:color]
|
||||
elseif a:color <= 7 || &t_Co == 256 || &t_Co == 88
|
||||
return ' cterm' . a:place . '=' . a:color
|
||||
@ -169,7 +169,7 @@ function! s:preview_color(linenr) abort
|
||||
\ ' "\_s\zs' . colordef . '\ze\_s"'
|
||||
let hi_attrs_str = ''
|
||||
if !empty(hi_attrs)
|
||||
if has('gui_running')
|
||||
if has('gui_running') || &termguicolors
|
||||
let hi_attrs_str = ' gui=' . join(hi_attrs, ',')
|
||||
else
|
||||
let hi_attrs_str = ' cterm=' . join(hi_attrs, ',')
|
||||
@ -199,11 +199,11 @@ endfunction
|
||||
|
||||
let b:dc_next_index = 0
|
||||
|
||||
if has('gui_running')
|
||||
if has('gui_running') || &termguicolors
|
||||
call s:set_guicolors()
|
||||
endif
|
||||
|
||||
if has('gui_running') || &t_Co != ''
|
||||
if has('gui_running') || &termguicolors || &t_Co != ''
|
||||
call s:reset_colors()
|
||||
|
||||
autocmd CursorMoved,CursorMovedI <buffer> call s:preview_color('.')
|
||||
|
@ -18,6 +18,10 @@ highlight default link manOptionDesc Constant
|
||||
highlight default link manReference PreProc
|
||||
highlight default link manSubHeading Function
|
||||
|
||||
highlight default manUnderline cterm=underline gui=underline
|
||||
highlight default manBold cterm=bold gui=bold
|
||||
highlight default manItalic cterm=italic gui=italic
|
||||
|
||||
if &filetype != 'man'
|
||||
" May have been included by some other filetype.
|
||||
finish
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,45 +1,43 @@
|
||||
{
|
||||
"expect": {
|
||||
"24": -1,
|
||||
"102": "The cow jumped over the moon.",
|
||||
"122": "There is some text missing from this line.",
|
||||
"123": "There is some text missing from this line.",
|
||||
"141": "There is some text missing from this line.",
|
||||
"142": "There is some text missing from this line.",
|
||||
"143": "There is also some text missing here.",
|
||||
"144": "There is also some text missing here.",
|
||||
"215": "There are some words that don't belong in this sentence.",
|
||||
"231": "Somebody typed the end of this line twice.",
|
||||
"271": -1,
|
||||
"290": "This line of words is cleaned up.",
|
||||
"304": -1,
|
||||
"305": -1,
|
||||
"306": -1,
|
||||
"307": -1,
|
||||
"308": -1,
|
||||
"103": "The cow jumped over the moon.",
|
||||
"124": "There is some text missing from this line.",
|
||||
"125": "There is some text missing from this line.",
|
||||
"144": "There is some text missing from this line.",
|
||||
"145": "There is some text missing from this line.",
|
||||
"146": "There is also some text missing here.",
|
||||
"147": "There is also some text missing here.",
|
||||
"220": "There are some words that don't belong in this sentence.",
|
||||
"236": "Somebody typed the end of this line twice.",
|
||||
"276": -1,
|
||||
"295": "This line of words is cleaned up.",
|
||||
"309": -1,
|
||||
"310": -1,
|
||||
"325": "Fix the errors on this line and replace them with undo.",
|
||||
"365": -1,
|
||||
"366": -1,
|
||||
"367": -1,
|
||||
"368": -1,
|
||||
"382": "When this line was typed in, someone pressed some wrong keys!",
|
||||
"383": "When this line was typed in, someone pressed some wrong keys!",
|
||||
"403": "This line has a few words that need changing using the change operator.",
|
||||
"404": "This line has a few words that need changing using the change operator.",
|
||||
"424": "The end of this line needs to be corrected using the c$ command.",
|
||||
"425": "The end of this line needs to be corrected using the c$ command.",
|
||||
"487": -1,
|
||||
"506": -1,
|
||||
"531": "Usually the best time to see the flowers is in the spring.",
|
||||
"722": -1,
|
||||
"727": -1,
|
||||
"744": "This line will allow you to practice appending text to a line.",
|
||||
"745": "This line will allow you to practice appending text to a line.",
|
||||
"765": "Adding 123 to 456 gives you 579.",
|
||||
"766": "Adding 123 to 456 gives you 579.",
|
||||
"790": "a) This is the first item.",
|
||||
"791": " b) This is the second item."
|
||||
"311": -1,
|
||||
"312": -1,
|
||||
"313": -1,
|
||||
"314": -1,
|
||||
"315": -1,
|
||||
"332": "Fix the errors on this line and replace them with undo.",
|
||||
"372": -1,
|
||||
"373": -1,
|
||||
"374": -1,
|
||||
"375": -1,
|
||||
"389": "When this line was typed in, someone pressed some wrong keys!",
|
||||
"390": "When this line was typed in, someone pressed some wrong keys!",
|
||||
"411": "This line has a few words that need changing using the change operator.",
|
||||
"412": "This line has a few words that need changing using the change operator.",
|
||||
"432": "The end of this line needs to be corrected using the c$ command.",
|
||||
"433": "The end of this line needs to be corrected using the c$ command.",
|
||||
"497": -1,
|
||||
"516": -1,
|
||||
"541": "Usually the best time to see the flowers is in the spring.",
|
||||
"759": "This line will allow you to practice appending text to a line.",
|
||||
"760": "This line will allow you to practice appending text to a line.",
|
||||
"780": "Adding 123 to 456 gives you 579.",
|
||||
"781": "Adding 123 to 456 gives you 579.",
|
||||
"807": "a) This is the first item.",
|
||||
"808": " b) This is the second item."
|
||||
}
|
||||
}
|
||||
|
@ -45,6 +45,8 @@ if sys.version_info[0] < 3:
|
||||
doc_filename = 'api.txt'
|
||||
# String used to find the start of the generated part of the doc.
|
||||
section_start_token = '*api-global*'
|
||||
# Required prefix for API function names.
|
||||
api_func_name_prefix = 'nvim_'
|
||||
|
||||
# Section name overrides.
|
||||
section_name = {
|
||||
@ -260,11 +262,11 @@ def parse_parblock(parent, width=62):
|
||||
def parse_source_xml(filename):
|
||||
"""Collects API functions.
|
||||
|
||||
This returns two strings:
|
||||
1. The API functions
|
||||
2. The deprecated API functions
|
||||
Returns two strings:
|
||||
1. API functions
|
||||
2. Deprecated API functions
|
||||
|
||||
The caller decides what to do with the deprecated documentation.
|
||||
Caller decides what to do with the deprecated documentation.
|
||||
"""
|
||||
global xrefs
|
||||
xrefs = set()
|
||||
@ -294,9 +296,8 @@ def parse_source_xml(filename):
|
||||
annotations = get_text(get_child(member, 'argsstring'))
|
||||
if annotations and ')' in annotations:
|
||||
annotations = annotations.rsplit(')', 1)[-1].strip()
|
||||
# XXX: (doxygen 1.8.11) 'argsstring' only includes FUNC_ATTR_*
|
||||
# attributes if the function signature is non-void.
|
||||
# Force attributes here for such functions.
|
||||
# XXX: (doxygen 1.8.11) 'argsstring' only includes attributes of
|
||||
# non-void functions. Special-case void functions here.
|
||||
if name == 'nvim_get_mode' and len(annotations) == 0:
|
||||
annotations += 'FUNC_API_ASYNC'
|
||||
annotations = filter(None, map(lambda x: annotation_map.get(x),
|
||||
@ -379,7 +380,7 @@ def parse_source_xml(filename):
|
||||
|
||||
if 'Deprecated' in xrefs:
|
||||
deprecated_functions.append(func_doc)
|
||||
else:
|
||||
elif name.startswith(api_func_name_prefix):
|
||||
functions.append(func_doc)
|
||||
|
||||
xrefs.clear()
|
||||
@ -477,7 +478,7 @@ def gen_docs(config):
|
||||
docs += '\n\n\n'
|
||||
|
||||
docs = docs.rstrip() + '\n\n'
|
||||
docs += ' vim:tw=78:ts=8:ft=help:norl:'
|
||||
docs += ' vim:tw=78:ts=8:ft=help:norl:\n'
|
||||
|
||||
doc_file = os.path.join(base_dir, 'runtime/doc', doc_filename)
|
||||
delete_lines_below(doc_file, section_start_token)
|
||||
|
@ -11,6 +11,8 @@ if [ -z "$ARCH" ]; then
|
||||
export ARCH="$(arch)"
|
||||
fi
|
||||
|
||||
TAG=$1
|
||||
|
||||
# App name, used by generate_appimage.
|
||||
APP=nvim
|
||||
|
||||
@ -35,7 +37,7 @@ VERSION=$("$ROOT_DIR"/build/bin/nvim --version | head -n 1 | grep -o 'v.*')
|
||||
|
||||
cd "$APP_BUILD_DIR"
|
||||
|
||||
curl -Lo "$APP_BUILD_DIR"/appimage_functions.sh https://github.com/probonopd/AppImages/raw/master/functions.sh
|
||||
curl -Lo "$APP_BUILD_DIR"/appimage_functions.sh https://github.com/AppImage/AppImages/raw/master/functions.sh
|
||||
. ./appimage_functions.sh
|
||||
|
||||
# Copy desktop and icon file to AppDir for AppRun to pick them up.
|
||||
@ -53,7 +55,7 @@ move_lib
|
||||
|
||||
# Delete stuff that should not go into the AppImage.
|
||||
# Delete dangerous libraries; see
|
||||
# https://github.com/probonopd/AppImages/blob/master/excludelist
|
||||
# https://github.com/AppImage/AppImages/blob/master/excludelist
|
||||
delete_blacklisted
|
||||
|
||||
########################################################################
|
||||
@ -69,14 +71,16 @@ cd "$APP_BUILD_DIR" # Get out of AppImage directory.
|
||||
# - Expects: $ARCH, $APP, $VERSION env vars
|
||||
# - Expects: ./$APP.AppDir/ directory
|
||||
# - Produces: ../out/$APP-$VERSION.glibc$GLIBC_NEEDED-$ARCH.AppImage
|
||||
generate_appimage
|
||||
if [ -n "$TAG" ]; then
|
||||
generate_type2_appimage -u "gh-releases-zsync|neovim|neovim|$TAG|nvim.appimage.zsync"
|
||||
else
|
||||
generate_type2_appimage
|
||||
fi
|
||||
|
||||
# NOTE: There is currently a bug in the `generate_appimage` function (see
|
||||
# https://github.com/probonopd/AppImages/issues/228) that causes repeated builds
|
||||
# that result in the same name to fail.
|
||||
# Moving the final executable to a different folder gets around this issue.
|
||||
# Moving the final executable to a different folder so it isn't in the
|
||||
# way for a subsequent build.
|
||||
|
||||
mv "$ROOT_DIR"/out/*.AppImage "$ROOT_DIR"/build/bin
|
||||
mv "$ROOT_DIR"/out/*.AppImage* "$ROOT_DIR"/build/bin
|
||||
# Remove the (now empty) folder the AppImage was built in
|
||||
rmdir "$ROOT_DIR"/out
|
||||
|
||||
|
@ -343,13 +343,15 @@ run_analysis() {(
|
||||
|
||||
cd "$tgt"
|
||||
|
||||
# pvs-studio-analyzer exits with a non-zero exit code when there are detected
|
||||
# errors, so ignore its return
|
||||
pvs-studio-analyzer \
|
||||
analyze \
|
||||
--threads "$(get_jobs_num)" \
|
||||
--output-file PVS-studio.log \
|
||||
--verbose \
|
||||
--file build/compile_commands.json \
|
||||
--sourcetree-root .
|
||||
--sourcetree-root . || true
|
||||
|
||||
plog-converter -t xml -o PVS-studio.xml PVS-studio.log
|
||||
plog-converter -t errorfile -o PVS-studio.err PVS-studio.log
|
||||
|
@ -1,50 +0,0 @@
|
||||
#!/usr/bin/env expect
|
||||
|
||||
if {$argc < 2} {
|
||||
puts "Need commands for running the tests and for starting nvim"
|
||||
exit 1
|
||||
}
|
||||
|
||||
set timeout 60
|
||||
set run_tests [split [lindex $argv 0] " "]
|
||||
set run_nvim [split [lindex $argv 1] " "]
|
||||
|
||||
# don't echo to stdout
|
||||
log_user 0
|
||||
# set NVIM_LISTEN_ADDRESS, so nvim will listen on a known socket
|
||||
set env(NVIM_LISTEN_ADDRESS) "/tmp/nvim-[exec date +%s%N].sock"
|
||||
# start nvim
|
||||
spawn {*}$run_nvim
|
||||
# save the job descriptor
|
||||
set nvim_id $spawn_id
|
||||
# Reset function that can be invoked by test runners to put nvim in a cleaner
|
||||
# state
|
||||
send {
|
||||
:echo "read"."y"
|
||||
}
|
||||
# wait until nvim is ready
|
||||
expect "ready"
|
||||
# run tests
|
||||
spawn {*}$run_tests
|
||||
set tests_id $spawn_id
|
||||
set status 1
|
||||
# listen for test output in the background
|
||||
expect_background {
|
||||
* {
|
||||
# show test output to the user
|
||||
send_user -- $expect_out(buffer)
|
||||
}
|
||||
eof {
|
||||
# collect the exit status code
|
||||
set spawn_id $tests_id
|
||||
catch wait result
|
||||
set status [lindex $result 3]
|
||||
set spawn_id $nvim_id
|
||||
# quit nvim
|
||||
send ":qa!\r"
|
||||
}
|
||||
}
|
||||
# switch back nvim and wait until it exits
|
||||
set spawn_id $nvim_id
|
||||
expect eof
|
||||
exit $status
|
@ -1,4 +1,4 @@
|
||||
#!/usr/bin/env python3.4
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import os
|
||||
import sys
|
||||
|
@ -14,26 +14,34 @@ readonly BRANCH_PREFIX="vim-"
|
||||
CREATED_FILES=()
|
||||
|
||||
usage() {
|
||||
echo "Helper script for porting Vim patches. For more information, see"
|
||||
echo "Port Vim patches to Neovim"
|
||||
echo "https://github.com/neovim/neovim/wiki/Merging-patches-from-upstream-vim"
|
||||
echo
|
||||
echo "Usage: ${BASENAME} [-h | -l | -p vim-revision | -r pr-number]"
|
||||
echo
|
||||
echo "Options:"
|
||||
echo " -h Show this message and exit."
|
||||
echo " -l Show list of Vim patches missing from Neovim."
|
||||
echo " -p {vim-revision} Download and generate the specified Vim patch."
|
||||
echo " vim-revision can be a version number '8.0.xxx'"
|
||||
echo " or a valid Git ref (hash, tag, etc.)."
|
||||
echo " -P {vim-revision} Download, generate and apply the Vim patch."
|
||||
echo " -g {vim-revision} Download the Vim patch vim-revision."
|
||||
echo " vim-revision can be a version number of the "
|
||||
echo " format '7.4.xxx' or a Git commit hash."
|
||||
echo " -s Submit a vim-patch pull request to Neovim."
|
||||
echo " -r {pr-number} Review a vim-patch pull request to Neovim."
|
||||
echo " -l List missing Vim patches."
|
||||
echo " -L List missing Vim patches (for scripts)."
|
||||
echo " -M List all merged patch-numbers (at current v:version)."
|
||||
echo " -p {vim-revision} Download and generate a Vim patch. vim-revision"
|
||||
echo " can be a Vim version (8.0.xxx) or a Git hash."
|
||||
echo " -P {vim-revision} Download, generate and apply a Vim patch."
|
||||
echo " -g {vim-revision} Download a Vim patch."
|
||||
echo " -s Create a vim-patch pull request."
|
||||
echo " -r {pr-number} Review a vim-patch pull request."
|
||||
echo ' -V Clone the Vim source code to $VIM_SOURCE_DIR.'
|
||||
echo
|
||||
echo "Set VIM_SOURCE_DIR to change where Vim's sources are stored."
|
||||
echo "Default is '${VIM_SOURCE_DIR_DEFAULT}'."
|
||||
echo ' $VIM_SOURCE_DIR controls where Vim sources are found'
|
||||
echo " (default: '${VIM_SOURCE_DIR_DEFAULT}')"
|
||||
}
|
||||
|
||||
msg_ok() {
|
||||
printf "\e[32m✔\e[0m $@\n"
|
||||
}
|
||||
|
||||
msg_err() {
|
||||
printf "\e[31m✘\e[0m $@\n"
|
||||
}
|
||||
|
||||
# Checks if a program is in the user's PATH, and is executable.
|
||||
@ -73,26 +81,29 @@ get_vim_sources() {
|
||||
require_executable git
|
||||
|
||||
if [[ ! -d ${VIM_SOURCE_DIR} ]]; then
|
||||
echo "Cloning Vim sources into '${VIM_SOURCE_DIR}'."
|
||||
echo "Cloning Vim into: ${VIM_SOURCE_DIR}"
|
||||
git clone https://github.com/vim/vim.git "${VIM_SOURCE_DIR}"
|
||||
cd "${VIM_SOURCE_DIR}"
|
||||
else
|
||||
if [[ ! -d "${VIM_SOURCE_DIR}/.git" ]]; then
|
||||
echo "✘ ${VIM_SOURCE_DIR} does not appear to be a git repository."
|
||||
msg_err "${VIM_SOURCE_DIR} does not appear to be a git repository."
|
||||
echo " Please remove it and try again."
|
||||
exit 1
|
||||
fi
|
||||
cd "${VIM_SOURCE_DIR}"
|
||||
echo "Updating Vim sources in '${VIM_SOURCE_DIR}'."
|
||||
echo "Updating Vim sources: ${VIM_SOURCE_DIR}"
|
||||
git pull &&
|
||||
echo "✔ Updated Vim sources." ||
|
||||
echo "✘ Could not update Vim sources; ignoring error."
|
||||
msg_ok "Updated Vim sources." ||
|
||||
msg_err "Could not update Vim sources; ignoring error."
|
||||
fi
|
||||
}
|
||||
|
||||
commit_message() {
|
||||
printf 'vim-patch:%s\n\n%s\n\n%s' "${vim_version}" \
|
||||
"${vim_message}" "${vim_commit_url}"
|
||||
if [[ -n "$vim_tag" ]]; then
|
||||
printf '%s\n%s' "${vim_message}" "${vim_commit_url}"
|
||||
else
|
||||
printf 'vim-patch:%s\n\n%s\n%s' "$vim_version" "$vim_message" "$vim_commit_url"
|
||||
fi
|
||||
}
|
||||
|
||||
find_git_remote() {
|
||||
@ -107,22 +118,23 @@ assign_commit_details() {
|
||||
vim_tag="v${1}"
|
||||
vim_commit=$(cd "${VIM_SOURCE_DIR}" \
|
||||
&& git log -1 --format="%H" "${vim_tag}")
|
||||
local strip_commit_line=true
|
||||
local munge_commit_line=true
|
||||
else
|
||||
# Interpret parameter as commit hash.
|
||||
vim_version="${1:0:12}"
|
||||
vim_tag=
|
||||
vim_commit=$(cd "${VIM_SOURCE_DIR}" \
|
||||
&& git log -1 --format="%H" "${vim_version}")
|
||||
local strip_commit_line=false
|
||||
local munge_commit_line=false
|
||||
fi
|
||||
|
||||
vim_commit_url="https://github.com/vim/vim/commit/${vim_commit}"
|
||||
vim_message="$(cd "${VIM_SOURCE_DIR}" \
|
||||
&& git log -1 --pretty='format:%B' "${vim_commit}" \
|
||||
| sed -e 's/\(#[0-9]*\)/vim\/vim\1/g')"
|
||||
if [[ ${strip_commit_line} == "true" ]]; then
|
||||
if [[ ${munge_commit_line} == "true" ]]; then
|
||||
# Remove first line of commit message.
|
||||
vim_message="$(echo "${vim_message}" | sed -e '1d')"
|
||||
vim_message="$(echo "${vim_message}" | sed -e '1s/^patch /vim-patch:/')"
|
||||
fi
|
||||
patch_file="vim-${vim_version}.patch"
|
||||
}
|
||||
@ -147,6 +159,10 @@ preprocess_patch() {
|
||||
local na_src_testdir='Make_amiga.mak\|Make_dos.mak\|Make_ming.mak\|Make_vms.mms'
|
||||
2>/dev/null $nvim --cmd 'set dir=/tmp' +'g@^diff --git a/src/testdir/\<\%('${na_src_testdir}'\)\>@norm! d/\v(^diff)|%$
' +w +q "$file"
|
||||
|
||||
# Remove version.c #7555
|
||||
local na_po='version.c'
|
||||
2>/dev/null $nvim --cmd 'set dir=/tmp' +'g@^diff --git a/src/\<\%('${na_po}'\)\>@norm! d/\v(^diff)|%$
' +w +q "$file"
|
||||
|
||||
# Remove some *.po files. #5622
|
||||
local na_po='sjiscorr.c\|ja.sjis.po\|ko.po\|pl.cp1250.po\|pl.po\|ru.cp1251.po\|uk.cp1251.po\|zh_CN.cp936.po\|zh_CN.po\|zh_TW.po'
|
||||
2>/dev/null $nvim --cmd 'set dir=/tmp' +'g@^diff --git a/src/po/\<\%('${na_po}'\)\>@norm! d/\v(^diff)|%$
' +w +q "$file"
|
||||
@ -164,16 +180,16 @@ preprocess_patch() {
|
||||
"$file" > "$file".tmp && mv "$file".tmp "$file"
|
||||
}
|
||||
|
||||
get_vim_patch() {
|
||||
get_vimpatch() {
|
||||
get_vim_sources
|
||||
|
||||
assign_commit_details "${1}"
|
||||
|
||||
git log -1 "${vim_commit}" -- >/dev/null 2>&1 || {
|
||||
>&2 echo "✘ Couldn't find Vim revision '${vim_commit}'."
|
||||
>&2 msg_err "Couldn't find Vim revision '${vim_commit}'."
|
||||
exit 3
|
||||
}
|
||||
echo "✔ Found Vim revision '${vim_commit}'."
|
||||
msg_ok "Found Vim revision '${vim_commit}'."
|
||||
|
||||
local patch_content
|
||||
patch_content="$(git --no-pager show --color=never -1 --pretty=medium "${vim_commit}")"
|
||||
@ -186,11 +202,11 @@ get_vim_patch() {
|
||||
printf "Pre-processing patch...\n"
|
||||
preprocess_patch "${NVIM_SOURCE_DIR}/${patch_file}"
|
||||
|
||||
printf "✔ Saved patch to '${NVIM_SOURCE_DIR}/${patch_file}'.\n"
|
||||
msg_ok "Saved patch to '${NVIM_SOURCE_DIR}/${patch_file}'.\n"
|
||||
}
|
||||
|
||||
stage_patch() {
|
||||
get_vim_patch "$1"
|
||||
get_vimpatch "$1"
|
||||
local try_apply="${2:-}"
|
||||
|
||||
local git_remote
|
||||
@ -199,34 +215,36 @@ stage_patch() {
|
||||
checked_out_branch="$(git rev-parse --abbrev-ref HEAD)"
|
||||
|
||||
if [[ "${checked_out_branch}" == ${BRANCH_PREFIX}* ]]; then
|
||||
echo "✔ Current branch '${checked_out_branch}' seems to be a vim-patch"
|
||||
msg_ok "Current branch '${checked_out_branch}' seems to be a vim-patch"
|
||||
echo " branch; not creating a new branch."
|
||||
else
|
||||
printf "\nFetching '${git_remote}/master'.\n"
|
||||
output="$(git fetch "${git_remote}" master 2>&1)" &&
|
||||
echo "✔ ${output}" ||
|
||||
(echo "✘ ${output}"; false)
|
||||
msg_ok "${output}" ||
|
||||
(msg_err "${output}"; false)
|
||||
|
||||
local nvim_branch="${BRANCH_PREFIX}${vim_version}"
|
||||
echo
|
||||
echo "Creating new branch '${nvim_branch}' based on '${git_remote}/master'."
|
||||
cd "${NVIM_SOURCE_DIR}"
|
||||
output="$(git checkout -b "${nvim_branch}" "${git_remote}/master" 2>&1)" &&
|
||||
echo "✔ ${output}" ||
|
||||
(echo "✘ ${output}"; false)
|
||||
msg_ok "${output}" ||
|
||||
(msg_err "${output}"; false)
|
||||
fi
|
||||
|
||||
printf "\nCreating empty commit with correct commit message.\n"
|
||||
output="$(commit_message | git commit --allow-empty --file 2>&1 -)" &&
|
||||
echo "✔ ${output}" ||
|
||||
(echo "✘ ${output}"; false)
|
||||
msg_ok "${output}" ||
|
||||
(msg_err "${output}"; false)
|
||||
|
||||
if test -n "$try_apply" ; then
|
||||
if ! check_executable patch; then
|
||||
printf "\n✘ 'patch' command not found\n"
|
||||
printf "\n"
|
||||
msg_err "'patch' command not found\n"
|
||||
else
|
||||
printf "\nApplying patch...\n"
|
||||
patch -p1 --posix < "${patch_file}"
|
||||
patch -p1 < "${patch_file}" || true
|
||||
find -name '*.orig' -type f -delete
|
||||
fi
|
||||
printf "\nInstructions:\n Proceed to port the patch.\n"
|
||||
else
|
||||
@ -274,16 +292,17 @@ submit_pr() {
|
||||
local checked_out_branch
|
||||
checked_out_branch="$(git rev-parse --abbrev-ref HEAD)"
|
||||
if [[ "${checked_out_branch}" != ${BRANCH_PREFIX}* ]]; then
|
||||
echo "✘ Current branch '${checked_out_branch}' doesn't seem to be a vim-patch branch."
|
||||
msg_err "Current branch '${checked_out_branch}' doesn't seem to be a vim-patch branch."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
local git_remote
|
||||
git_remote="$(find_git_remote)"
|
||||
local pr_body
|
||||
pr_body="$(git log --reverse --format='#### %s%n%n%b%n' "${git_remote}"/master..HEAD)"
|
||||
pr_body="$(git log --grep=vim-patch --reverse --format='#### %s%n%n%b%n' "${git_remote}"/master..HEAD)"
|
||||
local patches
|
||||
patches=("$(git log --reverse --format='%s' "${git_remote}"/master..HEAD)")
|
||||
# Extract just the "vim-patch:X.Y.ZZZZ" or "vim-patch:sha" portion of each log
|
||||
patches=("$(git log --grep=vim-patch --reverse --format='%s' "${git_remote}"/master..HEAD | sed 's/: .*//')")
|
||||
patches=(${patches[@]//vim-patch:}) # Remove 'vim-patch:' prefix for each item in array.
|
||||
local pr_title="${patches[*]}" # Create space-separated string from array.
|
||||
pr_title="${pr_title// /,}" # Replace spaces with commas.
|
||||
@ -294,16 +313,16 @@ submit_pr() {
|
||||
if [[ $push_first -ne 0 ]]; then
|
||||
echo "Pushing to 'origin/${checked_out_branch}'."
|
||||
output="$(git push origin "${checked_out_branch}" 2>&1)" &&
|
||||
echo "✔ ${output}" ||
|
||||
(echo "✘ ${output}"; false)
|
||||
msg_ok "${output}" ||
|
||||
(msg_err "${output}"; false)
|
||||
|
||||
echo
|
||||
fi
|
||||
|
||||
echo "Creating pull request."
|
||||
output="$(${submit_fn} "${pr_message}" 2>&1)" &&
|
||||
echo "✔ ${output}" ||
|
||||
(echo "✘ ${output}"; false)
|
||||
msg_ok "${output}" ||
|
||||
(msg_err "${output}"; false)
|
||||
|
||||
echo
|
||||
echo "Cleaning up files."
|
||||
@ -314,43 +333,74 @@ submit_pr() {
|
||||
continue
|
||||
fi
|
||||
rm -- "${NVIM_SOURCE_DIR}/${patch_file}"
|
||||
echo "✔ Removed '${NVIM_SOURCE_DIR}/${patch_file}'."
|
||||
msg_ok "Removed '${NVIM_SOURCE_DIR}/${patch_file}'."
|
||||
done
|
||||
}
|
||||
|
||||
list_vim_patches() {
|
||||
get_vim_sources
|
||||
# Gets all Vim commits since the "start" commit.
|
||||
list_vim_commits() { (
|
||||
cd "${VIM_SOURCE_DIR}" && git log --reverse --format='%H' v8.0.0000..HEAD
|
||||
) }
|
||||
|
||||
printf "\nVim patches missing from Neovim:\n"
|
||||
# Prints all (sorted) "vim-patch:xxx" tokens found in the Nvim git log.
|
||||
list_vimpatch_tokens() {
|
||||
local tokens
|
||||
# Find all "vim-patch:xxx" tokens in the Nvim git log.
|
||||
tokens="$(cd "${NVIM_SOURCE_DIR}" && git log -E --grep='vim-patch:[^ ]+' | grep 'vim-patch')"
|
||||
echo "$tokens" | grep -E 'vim-patch:[^ ,{]{7,}' \
|
||||
| sed 's/.*\(vim-patch:[.0-9a-z]\+\).*/\1/' \
|
||||
| sort \
|
||||
| uniq
|
||||
}
|
||||
|
||||
# Prints all patch-numbers (for the current v:version) for which there is
|
||||
# a "vim-patch:xxx" token in the Nvim git log.
|
||||
list_vimpatch_numbers() {
|
||||
# Transform "vim-patch:X.Y.ZZZZ" to "ZZZZ".
|
||||
list_vimpatch_tokens | while read vimpatch_token; do
|
||||
echo "$vimpatch_token" | grep '8\.0\.' | sed 's/.*vim-patch:8\.0\.\([0-9a-z]\+\).*/\1/'
|
||||
done
|
||||
}
|
||||
|
||||
# Prints a newline-delimited list of Vim commits, for use by scripts.
|
||||
list_missing_vimpatches() {
|
||||
local tokens vim_commit vim_commits is_missing vim_tag patch_number
|
||||
|
||||
# Find all "vim-patch:xxx" tokens in the Nvim git log.
|
||||
tokens="$(list_vimpatch_tokens)"
|
||||
|
||||
# Get missing Vim commits
|
||||
local vim_commits
|
||||
vim_commits="$(cd "${VIM_SOURCE_DIR}" && git log --reverse --format='%H' v8.0.0000..HEAD)"
|
||||
|
||||
local vim_commit
|
||||
vim_commits="$(list_vim_commits)"
|
||||
for vim_commit in ${vim_commits}; do
|
||||
local is_missing
|
||||
local vim_tag
|
||||
# This fails for untagged commits (e.g., runtime file updates) so mask the return status
|
||||
vim_tag="$(cd "${VIM_SOURCE_DIR}" && git describe --tags --exact-match "${vim_commit}" 2>/dev/null)" || true
|
||||
if [[ -n "${vim_tag}" ]]; then
|
||||
local patch_number="${vim_tag:5}" # Remove prefix like "v7.4."
|
||||
patch_number="$(echo ${patch_number} | sed 's/^0*//g')" # Remove prefix "0"
|
||||
# Tagged Vim patch, check 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")"
|
||||
# Check for vim-patch:<commit_hash> (usually runtime updates).
|
||||
is_missing="$(echo "$tokens" | >/dev/null 2>&1 grep "vim\-patch:${vim_commit:0:7}" && echo false || echo true)"
|
||||
|
||||
if ! [ "$is_missing" = "false" ] \
|
||||
&& vim_tag="$(cd "${VIM_SOURCE_DIR}" && git describe --tags --exact-match "${vim_commit}" 2>/dev/null)"
|
||||
then
|
||||
# Vim version number (not commit hash).
|
||||
# Check for vim-patch:<tag> (not commit hash).
|
||||
patch_number="${vim_tag:1}" # "v7.4.0001" => "7.4.0001"
|
||||
is_missing="$(echo "$tokens" | >/dev/null 2>&1 grep "vim\-patch:${patch_number}" && 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
|
||||
vim_commit="${vim_commit} (+runtime)"
|
||||
fi
|
||||
else
|
||||
# Untagged Vim patch (e.g. runtime updates), check the Neovim git log:
|
||||
is_missing="$(cd "${NVIM_SOURCE_DIR}" &&
|
||||
git log -1 --no-merges --grep="vim\-patch:${vim_commit:0:7}" --pretty=format:false)"
|
||||
fi
|
||||
|
||||
if [[ ${is_missing} != "false" ]]; then
|
||||
echo " • ${vim_commit}"
|
||||
if ! [ "$is_missing" = "false" ]; then
|
||||
echo "${vim_commit}"
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
# Prints a human-formatted list of Vim commits, with instructional messages.
|
||||
show_vimpatches() {
|
||||
get_vim_sources
|
||||
printf "\nVim patches missing from Neovim:\n"
|
||||
|
||||
list_missing_vimpatches | while read vim_commit; do
|
||||
if (cd "${VIM_SOURCE_DIR}" && git --no-pager show --color=never --name-only "v${vim_commit}" 2>/dev/null) | grep -q ^runtime; then
|
||||
printf " • ${vim_commit} (+runtime)\n"
|
||||
else
|
||||
printf " • ${vim_commit}\n"
|
||||
fi
|
||||
done
|
||||
|
||||
@ -380,9 +430,9 @@ review_commit() {
|
||||
|
||||
echo
|
||||
if [[ -n "${vim_version}" ]]; then
|
||||
echo "✔ Detected Vim patch '${vim_version}'."
|
||||
msg_ok "Detected Vim patch '${vim_version}'."
|
||||
else
|
||||
echo "✘ Could not detect the Vim patch number."
|
||||
msg_err "Could not detect the Vim patch number."
|
||||
echo " This script assumes that the PR contains only commits"
|
||||
echo " with 'vim-patch:XXX' in their title."
|
||||
echo
|
||||
@ -405,9 +455,9 @@ review_commit() {
|
||||
local commit_message
|
||||
commit_message="$(tail -n +4 <<< "${nvim_patch}" | head -n "${message_length}")"
|
||||
if [[ "${commit_message#${git_patch_prefix}}" == "${expected_commit_message}" ]]; then
|
||||
echo "✔ Found expected commit message."
|
||||
msg_ok "Found expected commit message."
|
||||
else
|
||||
echo "✘ Wrong commit message."
|
||||
msg_err "Wrong commit message."
|
||||
echo " Expected:"
|
||||
echo "${expected_commit_message}"
|
||||
echo " Actual:"
|
||||
@ -417,10 +467,10 @@ review_commit() {
|
||||
echo
|
||||
echo "Creating files."
|
||||
echo "${nvim_patch}" > "${NVIM_SOURCE_DIR}/n${patch_file}"
|
||||
echo "✔ Saved pull request diff to '${NVIM_SOURCE_DIR}/n${patch_file}'."
|
||||
msg_ok "Saved pull request diff to '${NVIM_SOURCE_DIR}/n${patch_file}'."
|
||||
CREATED_FILES+=("${NVIM_SOURCE_DIR}/n${patch_file}")
|
||||
|
||||
get_vim_patch "${vim_version}"
|
||||
get_vimpatch "${vim_version}"
|
||||
CREATED_FILES+=("${NVIM_SOURCE_DIR}/${patch_file}")
|
||||
|
||||
echo
|
||||
@ -461,14 +511,22 @@ review_pr() {
|
||||
clean_files
|
||||
}
|
||||
|
||||
while getopts "hlp:P:g:r:s" opt; do
|
||||
while getopts "hlLMVp:P:g:r:s" opt; do
|
||||
case ${opt} in
|
||||
h)
|
||||
usage
|
||||
exit 0
|
||||
;;
|
||||
l)
|
||||
list_vim_patches
|
||||
show_vimpatches
|
||||
exit 0
|
||||
;;
|
||||
L)
|
||||
list_missing_vimpatches
|
||||
exit 0
|
||||
;;
|
||||
M)
|
||||
list_vimpatch_numbers
|
||||
exit 0
|
||||
;;
|
||||
p)
|
||||
@ -480,7 +538,7 @@ while getopts "hlp:P:g:r:s" opt; do
|
||||
exit 0
|
||||
;;
|
||||
g)
|
||||
get_vim_patch "${OPTARG}"
|
||||
get_vimpatch "${OPTARG}"
|
||||
exit 0
|
||||
;;
|
||||
r)
|
||||
@ -491,6 +549,10 @@ while getopts "hlp:P:g:r:s" opt; do
|
||||
submit_pr
|
||||
exit 0
|
||||
;;
|
||||
V)
|
||||
get_vim_sources
|
||||
exit 0
|
||||
;;
|
||||
*)
|
||||
exit 1
|
||||
;;
|
||||
|
67
scripts/vimpatch.lua
Executable file
67
scripts/vimpatch.lua
Executable file
@ -0,0 +1,67 @@
|
||||
-- Updates version.c list of applied Vim patches.
|
||||
--
|
||||
-- Usage:
|
||||
-- VIM_SOURCE_DIR=~/neovim/.vim-src/ nvim -i NONE -u NONE --headless +'luafile ./scripts/vimpatch.lua' +q
|
||||
|
||||
local nvim = vim.api
|
||||
|
||||
local function pprint(o)
|
||||
print(nvim.nvim_call_function('string', { o }))
|
||||
end
|
||||
|
||||
local function systemlist(...)
|
||||
local rv = nvim.nvim_call_function('systemlist', ...)
|
||||
local err = nvim.nvim_get_vvar('shell_error')
|
||||
local args_str = nvim.nvim_call_function('string', ...)
|
||||
if 0 ~= err then
|
||||
error('command failed: '..args_str)
|
||||
end
|
||||
return rv
|
||||
end
|
||||
|
||||
local function vimpatch_sh_list_numbers()
|
||||
return systemlist( { { 'bash', '-c', 'scripts/vim-patch.sh -M', } } )
|
||||
end
|
||||
|
||||
-- Generates the lines to be inserted into the src/version.c
|
||||
-- `included_patches[]` definition.
|
||||
local function gen_version_c_lines()
|
||||
-- Set of merged Vim 8.0.zzzz patch numbers.
|
||||
local merged_patch_numbers = {}
|
||||
local highest = 0
|
||||
for _, n in ipairs(vimpatch_sh_list_numbers()) do
|
||||
if n then
|
||||
merged_patch_numbers[tonumber(n)] = true
|
||||
highest = math.max(highest, n)
|
||||
end
|
||||
end
|
||||
|
||||
local lines = {}
|
||||
for i = highest, 0, -1 do
|
||||
local is_merged = (nil ~= merged_patch_numbers[i])
|
||||
if is_merged then
|
||||
table.insert(lines, string.format(' %s,', i))
|
||||
else
|
||||
table.insert(lines, string.format(' // %s,', i))
|
||||
end
|
||||
end
|
||||
|
||||
return lines
|
||||
end
|
||||
|
||||
local function patch_version_c()
|
||||
local lines = gen_version_c_lines()
|
||||
|
||||
nvim.nvim_command('silent noswapfile noautocmd edit src/nvim/version.c')
|
||||
nvim.nvim_command('/static const int included_patches')
|
||||
-- Delete the existing lines.
|
||||
nvim.nvim_command('silent normal! j0d/};\rk')
|
||||
-- Insert the lines.
|
||||
nvim.nvim_call_function('append', {
|
||||
nvim.nvim_eval('line(".")'),
|
||||
lines,
|
||||
})
|
||||
nvim.nvim_command('silent write')
|
||||
end
|
||||
|
||||
patch_version_c()
|
41
snap/snapcraft.yaml
Normal file
41
snap/snapcraft.yaml
Normal file
@ -0,0 +1,41 @@
|
||||
name: neovim
|
||||
version: git
|
||||
summary: Vim-fork focused on extensibility and agility.
|
||||
description: |
|
||||
Neovim is a project that seeks to aggressively refactor Vim in order to:
|
||||
|
||||
Simplify maintenance and encourage contributions
|
||||
Split the work between multiple developers
|
||||
Enable the implementation of new/modern user interfaces without any modifications to the core source
|
||||
Improve extensibility with a new plugin architecture
|
||||
For lots more details, see the wiki!
|
||||
confinement: classic
|
||||
|
||||
apps:
|
||||
neovim:
|
||||
command: usr/local/bin/nvim
|
||||
plugs: [network, network-bind, x11]
|
||||
environment:
|
||||
HOME: /home/$USER
|
||||
VIM: $SNAP/usr/local/share/nvim/runtime
|
||||
|
||||
parts:
|
||||
neovim:
|
||||
source: .
|
||||
plugin: make
|
||||
make-parameters:
|
||||
- CMAKE_BUILD_TYPE=Release
|
||||
build-packages:
|
||||
- ninja-build
|
||||
- libtool
|
||||
- libtool-bin
|
||||
- autoconf
|
||||
- automake
|
||||
- cmake
|
||||
- g++
|
||||
- pkg-config
|
||||
- unzip
|
||||
snap:
|
||||
- usr/local/bin
|
||||
- usr/local/share/nvim
|
||||
- -usr/local/share/man
|
@ -1,3 +1,7 @@
|
||||
# multiqueue.h pointer arithmetic is not accepted by asan
|
||||
fun:multiqueue_node_data
|
||||
fun:tv_dict_watcher_node_data
|
||||
|
||||
# Allocation in loop_schedule_deferred() is freed by loop_deferred_event(), but
|
||||
# this sometimes does not happen during teardown.
|
||||
func:loop_schedule_deferred
|
||||
|
18
src/clint.py
18
src/clint.py
@ -201,6 +201,7 @@ _ERROR_CATEGORIES = [
|
||||
'runtime/printf',
|
||||
'runtime/printf_format',
|
||||
'runtime/threadsafe_fn',
|
||||
'runtime/deprecated',
|
||||
'syntax/parenthesis',
|
||||
'whitespace/alignment',
|
||||
'whitespace/blank_line',
|
||||
@ -2123,8 +2124,10 @@ def CheckExpressionAlignment(filename, clean_lines, linenum, error, startpos=0):
|
||||
+ (level_starts[depth][2] == '{')):
|
||||
if depth not in ignore_error_levels:
|
||||
error(filename, linenum, 'whitespace/alignment', 2,
|
||||
'Inner expression should be aligned '
|
||||
'as opening brace + 1 (+ 2 in case of {)')
|
||||
('Inner expression should be aligned '
|
||||
'as opening brace + 1 (+ 2 in case of {{). '
|
||||
'Relevant opening is on line {0!r}').format(
|
||||
level_starts[depth][3]))
|
||||
prev_line_start = pos
|
||||
elif brace == 'e':
|
||||
pass
|
||||
@ -2141,7 +2144,8 @@ def CheckExpressionAlignment(filename, clean_lines, linenum, error, startpos=0):
|
||||
ignore_error_levels.add(depth)
|
||||
line_ended_with_opening = (
|
||||
pos == len(line) - 2 * (line.endswith(' \\')) - 1)
|
||||
level_starts[depth] = (pos, line_ended_with_opening, brace)
|
||||
level_starts[depth] = (pos, line_ended_with_opening, brace,
|
||||
linenum)
|
||||
if line_ended_with_opening:
|
||||
depth_line_starts[depth] = (prev_line_start, brace)
|
||||
else:
|
||||
@ -3200,6 +3204,14 @@ def CheckLanguage(filename, clean_lines, linenum, file_extension,
|
||||
if match:
|
||||
error(filename, linenum, 'runtime/printf', 4,
|
||||
'Use xstrlcat or snprintf instead of %s' % match.group(1))
|
||||
if not Search(r'eval/typval\.[ch]$', filename):
|
||||
match = Search(r'(?:\.|->)'
|
||||
r'(?:lv_(?:first|last|refcount|len|watch|idx(?:_item)?'
|
||||
r'|copylist|lock)'
|
||||
r'|li_(?:next|prev|tv))\b', line)
|
||||
if match:
|
||||
error(filename, linenum, 'runtime/deprecated', 4,
|
||||
'Accessing list_T internals directly is prohibited')
|
||||
|
||||
# Check for suspicious usage of "if" like
|
||||
# } if (a == b) {
|
||||
|
@ -13,6 +13,9 @@ endif()
|
||||
if(WIN32)
|
||||
# tell MinGW compiler to enable wmain
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -municode")
|
||||
elseif(CMAKE_SYSTEM_NAME STREQUAL "Darwin")
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -framework CoreFoundation")
|
||||
set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} -framework CoreFoundation")
|
||||
endif()
|
||||
|
||||
set(TOUCHES_DIR ${PROJECT_BINARY_DIR}/touches)
|
||||
@ -86,6 +89,8 @@ foreach(subdir
|
||||
event
|
||||
eval
|
||||
lua
|
||||
viml
|
||||
viml/parser
|
||||
)
|
||||
if(${subdir} MATCHES "tui" AND NOT FEAT_TUI)
|
||||
continue()
|
||||
@ -170,7 +175,7 @@ endif()
|
||||
|
||||
get_directory_property(gen_cdefs COMPILE_DEFINITIONS)
|
||||
foreach(gen_cdef ${gen_cdefs} DO_NOT_DEFINE_EMPTY_ATTRIBUTES)
|
||||
if(NOT "${gen_cdef}" MATCHES "INCLUDE_GENERATED_DECLARATIONS")
|
||||
if(NOT ${gen_cdef} MATCHES "INCLUDE_GENERATED_DECLARATIONS")
|
||||
list(APPEND gen_cflags "-D${gen_cdef}")
|
||||
endif()
|
||||
endforeach()
|
||||
@ -182,6 +187,10 @@ get_directory_property(gen_includes INCLUDE_DIRECTORIES)
|
||||
foreach(gen_include ${gen_includes} ${LUA_PREFERRED_INCLUDE_DIRS})
|
||||
list(APPEND gen_cflags "-I${gen_include}")
|
||||
endforeach()
|
||||
if(CMAKE_SYSTEM_NAME STREQUAL "Darwin" AND CMAKE_OSX_SYSROOT)
|
||||
list(APPEND gen_cflags "-isysroot")
|
||||
list(APPEND gen_cflags "${CMAKE_OSX_SYSROOT}")
|
||||
endif()
|
||||
string(TOUPPER "${CMAKE_BUILD_TYPE}" build_type)
|
||||
separate_arguments(C_FLAGS_ARRAY UNIX_COMMAND ${CMAKE_C_FLAGS})
|
||||
separate_arguments(C_FLAGS_${build_type}_ARRAY UNIX_COMMAND ${CMAKE_C_FLAGS_${build_type}})
|
||||
@ -350,6 +359,10 @@ endforeach()
|
||||
|
||||
# Our dependencies come first.
|
||||
|
||||
if (CMAKE_SYSTEM_NAME MATCHES "OpenBSD")
|
||||
list(APPEND NVIM_LINK_LIBRARIES pthread c++abi)
|
||||
endif()
|
||||
|
||||
if (LibIntl_FOUND)
|
||||
list(APPEND NVIM_LINK_LIBRARIES ${LibIntl_LIBRARY})
|
||||
endif()
|
||||
@ -428,6 +441,7 @@ if(WIN32)
|
||||
COMMAND ${CMAKE_COMMAND} -E copy "${DEPS_PREFIX}/bin/tidy.exe" ${PROJECT_BINARY_DIR}/windows_runtime_deps/
|
||||
COMMAND ${CMAKE_COMMAND} -E copy "${DEPS_PREFIX}/bin/win32yank.exe" ${PROJECT_BINARY_DIR}/windows_runtime_deps/
|
||||
COMMAND ${CMAKE_COMMAND} -E copy "${DEPS_PREFIX}/bin/winpty-agent.exe" ${PROJECT_BINARY_DIR}/windows_runtime_deps/
|
||||
COMMAND ${CMAKE_COMMAND} -E copy "${DEPS_PREFIX}/bin/xxd.exe" ${PROJECT_BINARY_DIR}/windows_runtime_deps/
|
||||
|
||||
COMMAND ${CMAKE_COMMAND} -E copy "${DEPS_PREFIX}/bin/D3Dcompiler_47.dll" ${PROJECT_BINARY_DIR}/windows_runtime_deps/
|
||||
COMMAND ${CMAKE_COMMAND} -E copy "${DEPS_PREFIX}/bin/libEGL.dll" ${PROJECT_BINARY_DIR}/windows_runtime_deps/
|
||||
@ -446,6 +460,8 @@ if(WIN32)
|
||||
COMMAND ${CMAKE_COMMAND} -E copy "${DEPS_PREFIX}/bin/platforms/qwindows.dll" ${PROJECT_BINARY_DIR}/windows_runtime_deps/platforms/
|
||||
)
|
||||
add_dependencies(nvim_runtime_deps external_blobs)
|
||||
else()
|
||||
add_custom_target(nvim_runtime_deps) # Stub target to avoid CMP0046.
|
||||
endif()
|
||||
|
||||
add_library(
|
||||
|
@ -1,10 +1,22 @@
|
||||
Nvim core source
|
||||
================
|
||||
Nvim core
|
||||
=========
|
||||
|
||||
Module-specific details are documented at the top of each module (`terminal.c`,
|
||||
`screen.c`, ...).
|
||||
`screen.c`, …).
|
||||
|
||||
See `:help development` for more guidelines.
|
||||
See `:help dev` for guidelines.
|
||||
|
||||
Filename conventions
|
||||
--------------------
|
||||
|
||||
The source files use extensions to hint about their purpose.
|
||||
|
||||
- `*.c`, `*.generated.c` - full C files, with all includes, etc.
|
||||
- `*.c.h` - parametrized C files, contain all necessary includes, but require
|
||||
defining macros before actually using. Example: `typval_encode.c.h`
|
||||
- `*.h` - full headers, with all includes. Does *not* apply to `*.generated.h`.
|
||||
- `*.h.generated.h` - exported functions’ declarations.
|
||||
- `*.c.generated.h` - static functions’ declarations.
|
||||
|
||||
Logs
|
||||
----
|
||||
@ -20,17 +32,75 @@ UI events are logged at level 0 (`DEBUG_LOG_LEVEL`).
|
||||
rm -rf build/
|
||||
make CMAKE_EXTRA_FLAGS="-DMIN_LOG_LEVEL=0"
|
||||
|
||||
Filename conventions
|
||||
--------------------
|
||||
Build with ASAN
|
||||
---------------
|
||||
|
||||
The source files use extensions to hint about their purpose.
|
||||
Building Nvim with Clang sanitizers (Address Sanitizer: ASan, Undefined
|
||||
Behavior Sanitizer: UBSan, Memory Sanitizer: MSan, Thread Sanitizer: TSan) is
|
||||
a good way to catch undefined behavior, leaks and other errors as soon as they
|
||||
happen. It's significantly faster than Valgrind.
|
||||
|
||||
- `*.c`, `*.generated.c` - full C files, with all includes, etc.
|
||||
- `*.c.h` - parametrized C files, contain all necessary includes, but require
|
||||
defining macros before actually using. Example: `typval_encode.c.h`
|
||||
- `*.h` - full headers, with all includes. Does *not* apply to `*.generated.h`.
|
||||
- `*.h.generated.h` - exported functions’ declarations.
|
||||
- `*.c.generated.h` - static functions’ declarations.
|
||||
Requires clang 3.4 or later:
|
||||
|
||||
clang --version
|
||||
|
||||
Build Nvim with sanitizer instrumentation:
|
||||
|
||||
CC=clang make CMAKE_EXTRA_FLAGS="-DCLANG_ASAN_UBSAN=ON"
|
||||
|
||||
Create a directory to store logs:
|
||||
|
||||
mkdir -p "$HOME/logs"
|
||||
|
||||
Enable the sanitizer(s) via these environment variables:
|
||||
|
||||
# Change to detect_leaks=1 to detect memory leaks (slower).
|
||||
export ASAN_OPTIONS="detect_leaks=0:log_path=$HOME/logs/asan"
|
||||
export ASAN_SYMBOLIZER_PATH=/usr/lib/llvm-5.0/bin/llvm-symbolizer
|
||||
|
||||
export MSAN_SYMBOLIZER_PATH=/usr/lib/llvm-5.0/bin/llvm-symbolizer
|
||||
export TSAN_OPTIONS="external_symbolizer_path=/usr/lib/llvm-5.0/bin/llvm-symbolizer log_path=${HOME}/logs/tsan"
|
||||
|
||||
Logs will be written to `${HOME}/logs/*san.PID`.
|
||||
|
||||
TUI debugging
|
||||
-------------
|
||||
|
||||
### TUI troubleshoot
|
||||
|
||||
Nvim logs its internal terminfo state at 'verbose' level 3. This makes it
|
||||
possible to see exactly what terminfo values Nvim is using on any system.
|
||||
|
||||
nvim -V3log
|
||||
|
||||
### TUI trace
|
||||
|
||||
The ancient `script` command is still the "state of the art" for tracing
|
||||
terminal behavior. The libvterm `vterm-dump` utility formats the result for
|
||||
human-readability.
|
||||
|
||||
Record a Nvim terminal session and format it with `vterm-dump`:
|
||||
|
||||
script foo
|
||||
./build/bin/nvim -u NONE
|
||||
# Exit the script session with CTRL-d
|
||||
|
||||
# Use `vterm-dump` utility to format the result.
|
||||
./.deps/usr/bin/vterm-dump foo > bar
|
||||
|
||||
Then you can compare `bar` with another session, to debug TUI behavior.
|
||||
|
||||
### TUI redraw
|
||||
|
||||
Set the 'writedelay' option to see where and when the UI is painted.
|
||||
|
||||
:set writedelay=1
|
||||
|
||||
### Terminal reference
|
||||
|
||||
- `man terminfo`
|
||||
- http://bazaar.launchpad.net/~libvterm/libvterm/trunk/view/head:/doc/seqs.txt
|
||||
- http://invisible-island.net/xterm/ctlseqs/ctlseqs.html
|
||||
|
||||
Nvim lifecycle
|
||||
--------------
|
||||
@ -39,7 +109,7 @@ Following describes how Nvim processes input.
|
||||
|
||||
Consider a typical Vim-like editing session:
|
||||
|
||||
01. Vim dispays the welcome screen
|
||||
01. Vim displays the welcome screen
|
||||
02. User types: `:`
|
||||
03. Vim enters command-line mode
|
||||
04. User types: `edit README.txt<CR>`
|
||||
|
@ -399,7 +399,11 @@ void nvim_buf_set_lines(uint64_t channel_id,
|
||||
// Only adjust marks if we managed to switch to a window that holds
|
||||
// the buffer, otherwise line numbers will be invalid.
|
||||
if (save_curbuf.br_buf == NULL) {
|
||||
mark_adjust((linenr_T)start, (linenr_T)(end - 1), MAXLNUM, extra, false);
|
||||
mark_adjust((linenr_T)start,
|
||||
(linenr_T)(end - 1),
|
||||
MAXLNUM,
|
||||
(long)extra,
|
||||
false);
|
||||
}
|
||||
|
||||
changed_lines((linenr_T)start, 0, (linenr_T)end, (long)extra);
|
||||
@ -763,8 +767,8 @@ ArrayOf(Integer, 2) nvim_buf_get_mark(Buffer buffer, String name, Error *err)
|
||||
/// or -1 for ungrouped highlight
|
||||
/// @param hl_group Name of the highlight group to use
|
||||
/// @param line Line to highlight (zero-indexed)
|
||||
/// @param col_start Start of range of columns to highlight
|
||||
/// @param col_end End of range of columns to highlight,
|
||||
/// @param col_start Start of (byte-indexed) column range to highlight
|
||||
/// @param col_end End of (byte-indexed) column range to highlight,
|
||||
/// or -1 to highlight to end of line
|
||||
/// @param[out] err Error details, if any
|
||||
/// @return The src_id that was used
|
||||
@ -806,7 +810,7 @@ Integer nvim_buf_add_highlight(Buffer buffer,
|
||||
|
||||
/// Clears highlights from a given source group and a range of lines
|
||||
///
|
||||
/// To clear a source group in the entire buffer, pass in 1 and -1 to
|
||||
/// To clear a source group in the entire buffer, pass in 0 and -1 to
|
||||
/// line_start and line_end respectively.
|
||||
///
|
||||
/// @param buffer Buffer handle
|
||||
|
@ -47,7 +47,7 @@ typedef enum {
|
||||
/// Internal call from lua code
|
||||
#define LUA_INTERNAL_CALL (VIML_INTERNAL_CALL + 1)
|
||||
|
||||
static inline bool is_internal_call(uint64_t channel_id)
|
||||
static inline bool is_internal_call(const uint64_t channel_id)
|
||||
REAL_FATTR_ALWAYS_INLINE REAL_FATTR_CONST;
|
||||
|
||||
/// Check whether call is internal
|
||||
|
@ -26,6 +26,7 @@
|
||||
#include "nvim/version.h"
|
||||
#include "nvim/lib/kvec.h"
|
||||
#include "nvim/getchar.h"
|
||||
#include "nvim/ui.h"
|
||||
|
||||
/// Helper structure for vim_to_object
|
||||
typedef struct {
|
||||
@ -46,13 +47,15 @@ typedef struct {
|
||||
/// @param[out] tstate Location where try state should be saved.
|
||||
void try_enter(TryState *const tstate)
|
||||
{
|
||||
// TODO(ZyX-I): Check whether try_enter()/try_leave() may use
|
||||
// enter_cleanup()/leave_cleanup(). Or
|
||||
// save_dbg_stuff()/restore_dbg_stuff().
|
||||
*tstate = (TryState) {
|
||||
.current_exception = current_exception,
|
||||
.msg_list = (const struct msglist *const *)msg_list,
|
||||
.private_msg_list = NULL,
|
||||
.trylevel = trylevel,
|
||||
.got_int = got_int,
|
||||
.did_throw = did_throw,
|
||||
.need_rethrow = need_rethrow,
|
||||
.did_emsg = did_emsg,
|
||||
};
|
||||
@ -60,7 +63,6 @@ void try_enter(TryState *const tstate)
|
||||
current_exception = NULL;
|
||||
trylevel = 1;
|
||||
got_int = false;
|
||||
did_throw = false;
|
||||
need_rethrow = false;
|
||||
did_emsg = false;
|
||||
}
|
||||
@ -81,7 +83,6 @@ bool try_leave(const TryState *const tstate, Error *const err)
|
||||
assert(trylevel == 0);
|
||||
assert(!need_rethrow);
|
||||
assert(!got_int);
|
||||
assert(!did_throw);
|
||||
assert(!did_emsg);
|
||||
assert(msg_list == &tstate->private_msg_list);
|
||||
assert(*msg_list == NULL);
|
||||
@ -90,7 +91,6 @@ bool try_leave(const TryState *const tstate, Error *const err)
|
||||
current_exception = tstate->current_exception;
|
||||
trylevel = tstate->trylevel;
|
||||
got_int = tstate->got_int;
|
||||
did_throw = tstate->did_throw;
|
||||
need_rethrow = tstate->need_rethrow;
|
||||
did_emsg = tstate->did_emsg;
|
||||
return ret;
|
||||
@ -126,7 +126,7 @@ bool try_end(Error *err)
|
||||
did_emsg = false;
|
||||
|
||||
if (got_int) {
|
||||
if (did_throw) {
|
||||
if (current_exception) {
|
||||
// If we got an interrupt, discard the current exception
|
||||
discard_current_exception();
|
||||
}
|
||||
@ -145,7 +145,7 @@ bool try_end(Error *err)
|
||||
if (should_free) {
|
||||
xfree(msg);
|
||||
}
|
||||
} else if (did_throw) {
|
||||
} else if (current_exception) {
|
||||
api_set_error(err, kErrorTypeException, "%s", current_exception->value);
|
||||
discard_current_exception();
|
||||
}
|
||||
@ -566,7 +566,7 @@ static inline void typval_encode_dict_end(EncodedData *const edata)
|
||||
typval_encode_dict_end(edata)
|
||||
|
||||
#define TYPVAL_ENCODE_CONV_RECURSE(val, conv_type) \
|
||||
TYPVAL_ENCODE_CONV_NIL()
|
||||
TYPVAL_ENCODE_CONV_NIL(val)
|
||||
|
||||
#define TYPVAL_ENCODE_SCOPE static
|
||||
#define TYPVAL_ENCODE_NAME object
|
||||
@ -783,22 +783,20 @@ bool object_to_vim(Object obj, typval_T *tv, Error *err)
|
||||
break;
|
||||
|
||||
case kObjectTypeArray: {
|
||||
list_T *const list = tv_list_alloc();
|
||||
list_T *const list = tv_list_alloc((ptrdiff_t)obj.data.array.size);
|
||||
|
||||
for (uint32_t i = 0; i < obj.data.array.size; i++) {
|
||||
Object item = obj.data.array.items[i];
|
||||
listitem_T *li = tv_list_item_alloc();
|
||||
typval_T li_tv;
|
||||
|
||||
if (!object_to_vim(item, &li->li_tv, err)) {
|
||||
// cleanup
|
||||
tv_list_item_free(li);
|
||||
if (!object_to_vim(item, &li_tv, err)) {
|
||||
tv_list_free(list);
|
||||
return false;
|
||||
}
|
||||
|
||||
tv_list_append(list, li);
|
||||
tv_list_append_owned_tv(list, li_tv);
|
||||
}
|
||||
list->lv_refcount++;
|
||||
tv_list_ref(list);
|
||||
|
||||
tv->v_type = VAR_LIST;
|
||||
tv->vval.v_list = list;
|
||||
@ -957,6 +955,12 @@ static void init_ui_event_metadata(Dictionary *metadata)
|
||||
msgpack_rpc_to_object(&unpacked.data, &ui_events);
|
||||
msgpack_unpacked_destroy(&unpacked);
|
||||
PUT(*metadata, "ui_events", ui_events);
|
||||
Array ui_options = ARRAY_DICT_INIT;
|
||||
ADD(ui_options, STRING_OBJ(cstr_to_string("rgb")));
|
||||
for (UIExtension i = 0; i < kUIExtCount; i++) {
|
||||
ADD(ui_options, STRING_OBJ(cstr_to_string(ui_ext_names[i])));
|
||||
}
|
||||
PUT(*metadata, "ui_options", ARRAY_OBJ(ui_options));
|
||||
}
|
||||
|
||||
static void init_error_type_metadata(Dictionary *metadata)
|
||||
|
@ -93,7 +93,6 @@ typedef struct {
|
||||
const struct msglist *const *msg_list;
|
||||
int trylevel;
|
||||
int got_int;
|
||||
int did_throw;
|
||||
int need_rethrow;
|
||||
int did_emsg;
|
||||
} TryState;
|
||||
|
@ -43,10 +43,10 @@ void remote_ui_disconnect(uint64_t channel_id)
|
||||
return;
|
||||
}
|
||||
UIData *data = ui->data;
|
||||
// destroy pending screen updates
|
||||
api_free_array(data->buffer);
|
||||
api_free_array(data->buffer); // Destroy pending screen updates.
|
||||
pmap_del(uint64_t)(connected_uis, channel_id);
|
||||
xfree(ui->data);
|
||||
ui->data = NULL; // Flag UI as "stopped".
|
||||
ui_detach_impl(ui);
|
||||
xfree(ui);
|
||||
}
|
||||
@ -56,7 +56,8 @@ void nvim_ui_attach(uint64_t channel_id, Integer width, Integer height,
|
||||
FUNC_API_SINCE(1) FUNC_API_REMOTE_ONLY
|
||||
{
|
||||
if (pmap_has(uint64_t)(connected_uis, channel_id)) {
|
||||
api_set_error(err, kErrorTypeException, "UI already attached for channel");
|
||||
api_set_error(err, kErrorTypeException,
|
||||
"UI already attached to channel: %" PRId64, channel_id);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -86,6 +87,7 @@ void nvim_ui_attach(uint64_t channel_id, Integer width, Integer height,
|
||||
ui->put = remote_ui_put;
|
||||
ui->bell = remote_ui_bell;
|
||||
ui->visual_bell = remote_ui_visual_bell;
|
||||
ui->default_colors_set = remote_ui_default_colors_set;
|
||||
ui->update_fg = remote_ui_update_fg;
|
||||
ui->update_bg = remote_ui_update_bg;
|
||||
ui->update_sp = remote_ui_update_sp;
|
||||
@ -93,6 +95,7 @@ void nvim_ui_attach(uint64_t channel_id, Integer width, Integer height,
|
||||
ui->suspend = remote_ui_suspend;
|
||||
ui->set_title = remote_ui_set_title;
|
||||
ui->set_icon = remote_ui_set_icon;
|
||||
ui->option_set = remote_ui_option_set;
|
||||
ui->event = remote_ui_event;
|
||||
|
||||
memset(ui->ui_ext, 0, sizeof(ui->ui_ext));
|
||||
@ -128,7 +131,8 @@ void nvim_ui_detach(uint64_t channel_id, Error *err)
|
||||
FUNC_API_SINCE(1) FUNC_API_REMOTE_ONLY
|
||||
{
|
||||
if (!pmap_has(uint64_t)(connected_uis, channel_id)) {
|
||||
api_set_error(err, kErrorTypeException, "UI is not attached for channel");
|
||||
api_set_error(err, kErrorTypeException,
|
||||
"UI not attached to channel: %" PRId64, channel_id);
|
||||
return;
|
||||
}
|
||||
remote_ui_disconnect(channel_id);
|
||||
@ -140,7 +144,8 @@ void nvim_ui_try_resize(uint64_t channel_id, Integer width,
|
||||
FUNC_API_SINCE(1) FUNC_API_REMOTE_ONLY
|
||||
{
|
||||
if (!pmap_has(uint64_t)(connected_uis, channel_id)) {
|
||||
api_set_error(err, kErrorTypeException, "UI is not attached for channel");
|
||||
api_set_error(err, kErrorTypeException,
|
||||
"UI not attached to channel: %" PRId64, channel_id);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -161,7 +166,8 @@ void nvim_ui_set_option(uint64_t channel_id, String name,
|
||||
FUNC_API_SINCE(1) FUNC_API_REMOTE_ONLY
|
||||
{
|
||||
if (!pmap_has(uint64_t)(connected_uis, channel_id)) {
|
||||
api_set_error(error, kErrorTypeException, "UI is not attached for channel");
|
||||
api_set_error(error, kErrorTypeException,
|
||||
"UI not attached to channel: %" PRId64, channel_id);
|
||||
return;
|
||||
}
|
||||
UI *ui = pmap_get(uint64_t)(connected_uis, channel_id);
|
||||
@ -174,18 +180,6 @@ void nvim_ui_set_option(uint64_t channel_id, String name,
|
||||
|
||||
static void ui_set_option(UI *ui, String name, Object value, Error *error)
|
||||
{
|
||||
#define UI_EXT_OPTION(o, e) \
|
||||
do { \
|
||||
if (strequal(name.data, #o)) { \
|
||||
if (value.type != kObjectTypeBoolean) { \
|
||||
api_set_error(error, kErrorTypeValidation, #o " must be a Boolean"); \
|
||||
return; \
|
||||
} \
|
||||
ui->ui_ext[(e)] = value.data.boolean; \
|
||||
return; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
if (strequal(name.data, "rgb")) {
|
||||
if (value.type != kObjectTypeBoolean) {
|
||||
api_set_error(error, kErrorTypeValidation, "rgb must be a Boolean");
|
||||
@ -195,13 +189,21 @@ static void ui_set_option(UI *ui, String name, Object value, Error *error)
|
||||
return;
|
||||
}
|
||||
|
||||
UI_EXT_OPTION(ext_cmdline, kUICmdline);
|
||||
UI_EXT_OPTION(ext_popupmenu, kUIPopupmenu);
|
||||
UI_EXT_OPTION(ext_tabline, kUITabline);
|
||||
UI_EXT_OPTION(ext_wildmenu, kUIWildmenu);
|
||||
for (UIExtension i = 0; i < kUIExtCount; i++) {
|
||||
if (strequal(name.data, ui_ext_names[i])) {
|
||||
if (value.type != kObjectTypeBoolean) {
|
||||
snprintf((char *)IObuff, IOSIZE, "%s must be a Boolean",
|
||||
ui_ext_names[i]);
|
||||
api_set_error(error, kErrorTypeValidation, (char *)IObuff);
|
||||
return;
|
||||
}
|
||||
ui->ui_ext[i] = value.data.boolean;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (strequal(name.data, "popupmenu_external")) {
|
||||
// LEGACY: Deprecated option, use `ui_ext` instead.
|
||||
// LEGACY: Deprecated option, use `ext_cmdline` instead.
|
||||
if (value.type != kObjectTypeBoolean) {
|
||||
api_set_error(error, kErrorTypeValidation,
|
||||
"popupmenu_external must be a Boolean");
|
||||
@ -211,7 +213,8 @@ static void ui_set_option(UI *ui, String name, Object value, Error *error)
|
||||
return;
|
||||
}
|
||||
|
||||
api_set_error(error, kErrorTypeValidation, "No such ui option");
|
||||
api_set_error(error, kErrorTypeValidation, "No such UI option: %s",
|
||||
name.data);
|
||||
#undef UI_EXT_OPTION
|
||||
}
|
||||
|
||||
@ -242,7 +245,7 @@ static void push_call(UI *ui, char *name, Array args)
|
||||
static void remote_ui_highlight_set(UI *ui, HlAttrs attrs)
|
||||
{
|
||||
Array args = ARRAY_DICT_INIT;
|
||||
Dictionary hl = hlattrs2dict(attrs);
|
||||
Dictionary hl = hlattrs2dict(&attrs, ui->rgb);
|
||||
|
||||
ADD(args, DICTIONARY_OBJ(hl));
|
||||
push_call(ui, "highlight_set", args);
|
||||
|
@ -47,17 +47,22 @@ void visual_bell(void)
|
||||
void flush(void)
|
||||
FUNC_API_SINCE(3) FUNC_API_REMOTE_IMPL;
|
||||
void update_fg(Integer fg)
|
||||
FUNC_API_SINCE(3);
|
||||
FUNC_API_SINCE(3) FUNC_API_BRIDGE_IMPL;
|
||||
void update_bg(Integer bg)
|
||||
FUNC_API_SINCE(3);
|
||||
FUNC_API_SINCE(3) FUNC_API_BRIDGE_IMPL;
|
||||
void update_sp(Integer sp)
|
||||
FUNC_API_SINCE(3);
|
||||
FUNC_API_SINCE(3) FUNC_API_BRIDGE_IMPL;
|
||||
void default_colors_set(Integer rgb_fg, Integer rgb_bg, Integer rgb_sp,
|
||||
Integer cterm_fg, Integer cterm_bg)
|
||||
FUNC_API_SINCE(4);
|
||||
void suspend(void)
|
||||
FUNC_API_SINCE(3) FUNC_API_BRIDGE_IMPL;
|
||||
void set_title(String title)
|
||||
FUNC_API_SINCE(3);
|
||||
void set_icon(String icon)
|
||||
FUNC_API_SINCE(3);
|
||||
void option_set(String name, Object value)
|
||||
FUNC_API_SINCE(4);
|
||||
|
||||
void popupmenu_show(Array items, Integer selected, Integer row, Integer col)
|
||||
FUNC_API_SINCE(3) FUNC_API_REMOTE_ONLY;
|
||||
|
@ -33,6 +33,10 @@
|
||||
#include "nvim/syntax.h"
|
||||
#include "nvim/getchar.h"
|
||||
#include "nvim/os/input.h"
|
||||
#include "nvim/os/process.h"
|
||||
#include "nvim/viml/parser/expressions.h"
|
||||
#include "nvim/viml/parser/parser.h"
|
||||
#include "nvim/ui.h"
|
||||
|
||||
#define LINE_BUFFER_SIZE 4096
|
||||
|
||||
@ -41,14 +45,15 @@
|
||||
#endif
|
||||
|
||||
/// Executes an ex-command.
|
||||
/// On VimL error: Returns the VimL error; v:errmsg is not updated.
|
||||
///
|
||||
/// On parse error: forwards the Vim error; does not update v:errmsg.
|
||||
/// On runtime error: forwards the Vim error; does not update v:errmsg.
|
||||
///
|
||||
/// @param command Ex-command string
|
||||
/// @param[out] err Error details (including actual VimL error), if any
|
||||
/// @param[out] err Error details (Vim error), if any
|
||||
void nvim_command(String command, Error *err)
|
||||
FUNC_API_SINCE(1)
|
||||
{
|
||||
// Run the command
|
||||
try_start();
|
||||
do_cmdline_cmd(command.data);
|
||||
update_screen(VALID);
|
||||
@ -205,18 +210,51 @@ String nvim_replace_termcodes(String str, Boolean from_part, Boolean do_lt,
|
||||
return cstr_as_string(ptr);
|
||||
}
|
||||
|
||||
String nvim_command_output(String str, Error *err)
|
||||
/// Executes an ex-command and returns its (non-error) output.
|
||||
/// Shell |:!| output is not captured.
|
||||
///
|
||||
/// On parse error: forwards the Vim error; does not update v:errmsg.
|
||||
/// On runtime error: forwards the Vim error; does not update v:errmsg.
|
||||
///
|
||||
/// @param command Ex-command string
|
||||
/// @param[out] err Error details (Vim error), if any
|
||||
String nvim_command_output(String command, Error *err)
|
||||
FUNC_API_SINCE(1)
|
||||
{
|
||||
do_cmdline_cmd("redir => v:command_output");
|
||||
nvim_command(str, err);
|
||||
do_cmdline_cmd("redir END");
|
||||
const int save_msg_silent = msg_silent;
|
||||
garray_T *const save_capture_ga = capture_ga;
|
||||
garray_T capture_local;
|
||||
ga_init(&capture_local, 1, 80);
|
||||
|
||||
try_start();
|
||||
msg_silent++;
|
||||
capture_ga = &capture_local;
|
||||
do_cmdline_cmd(command.data);
|
||||
capture_ga = save_capture_ga;
|
||||
msg_silent = save_msg_silent;
|
||||
try_end(err);
|
||||
|
||||
if (ERROR_SET(err)) {
|
||||
return (String)STRING_INIT;
|
||||
goto theend;
|
||||
}
|
||||
|
||||
return cstr_to_string((char *)get_vim_var_str(VV_COMMAND_OUTPUT));
|
||||
if (capture_local.ga_len > 1) {
|
||||
String s = (String){
|
||||
.data = capture_local.ga_data,
|
||||
.size = (size_t)capture_local.ga_len,
|
||||
};
|
||||
// redir usually (except :echon) prepends a newline.
|
||||
if (s.data[0] == '\n') {
|
||||
memmove(s.data, s.data + 1, s.size);
|
||||
s.data[s.size - 1] = '\0';
|
||||
s.size = s.size - 1;
|
||||
}
|
||||
return s; // Caller will free the memory.
|
||||
}
|
||||
|
||||
theend:
|
||||
ga_clear(&capture_local);
|
||||
return (String)STRING_INIT;
|
||||
}
|
||||
|
||||
/// Evaluates a VimL expression (:help expression).
|
||||
@ -787,6 +825,10 @@ ArrayOf(Dictionary) nvim_get_keymap(String mode)
|
||||
return keymap_array(mode, NULL);
|
||||
}
|
||||
|
||||
/// Returns a 2-tuple (Array), where item 0 is the current channel id and item
|
||||
/// 1 is the |api-metadata| map (Dictionary).
|
||||
///
|
||||
/// @returns 2-tuple [{channel-id}, {api-metadata}]
|
||||
Array nvim_get_api_info(uint64_t channel_id)
|
||||
FUNC_API_SINCE(1) FUNC_API_ASYNC FUNC_API_REMOTE_ONLY
|
||||
{
|
||||
@ -889,6 +931,460 @@ theend:
|
||||
return rv;
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
ExprASTNode **node_p;
|
||||
Object *ret_node_p;
|
||||
} ExprASTConvStackItem;
|
||||
|
||||
/// @cond DOXYGEN_NOT_A_FUNCTION
|
||||
typedef kvec_withinit_t(ExprASTConvStackItem, 16) ExprASTConvStack;
|
||||
/// @endcond
|
||||
|
||||
/// Parse a VimL expression
|
||||
///
|
||||
/// @param[in] expr Expression to parse. Is always treated as a single line.
|
||||
/// @param[in] flags Flags:
|
||||
///
|
||||
/// - "m" if multiple expressions in a row are allowed (only
|
||||
/// the first one will be parsed),
|
||||
/// - "E" if EOC tokens are not allowed (determines whether
|
||||
/// they will stop parsing process or be recognized as an
|
||||
/// operator/space, though also yielding an error).
|
||||
/// - "l" when needing to start parsing with lvalues for
|
||||
/// ":let" or ":for".
|
||||
///
|
||||
/// Common flag sets:
|
||||
/// - "m" to parse like for ":echo".
|
||||
/// - "E" to parse like for "<C-r>=".
|
||||
/// - empty string for ":call".
|
||||
/// - "lm" to parse for ":let".
|
||||
/// @param[in] highlight If true, return value will also include "highlight"
|
||||
/// key containing array of 4-tuples (arrays) (Integer,
|
||||
/// Integer, Integer, String), where first three numbers
|
||||
/// define the highlighted region and represent line,
|
||||
/// starting column and ending column (latter exclusive:
|
||||
/// one should highlight region [start_col, end_col)).
|
||||
///
|
||||
/// @return AST: top-level dictionary with these keys:
|
||||
///
|
||||
/// "error": Dictionary with error, present only if parser saw some
|
||||
/// error. Contains the following keys:
|
||||
///
|
||||
/// "message": String, error message in printf format, translated.
|
||||
/// Must contain exactly one "%.*s".
|
||||
/// "arg": String, error message argument.
|
||||
///
|
||||
/// "len": Amount of bytes successfully parsed. With flags equal to ""
|
||||
/// that should be equal to the length of expr string.
|
||||
///
|
||||
/// @note: “Sucessfully parsed” here means “participated in AST
|
||||
/// creation”, not “till the first error”.
|
||||
///
|
||||
/// "ast": AST, either nil or a dictionary with these keys:
|
||||
///
|
||||
/// "type": node type, one of the value names from ExprASTNodeType
|
||||
/// stringified without "kExprNode" prefix.
|
||||
/// "start": a pair [line, column] describing where node is “started”
|
||||
/// where "line" is always 0 (will not be 0 if you will be
|
||||
/// using nvim_parse_viml() on e.g. ":let", but that is not
|
||||
/// present yet). Both elements are Integers.
|
||||
/// "len": “length” of the node. This and "start" are there for
|
||||
/// debugging purposes primary (debugging parser and providing
|
||||
/// debug information).
|
||||
/// "children": a list of nodes described in top/"ast". There always
|
||||
/// is zero, one or two children, key will not be present
|
||||
/// if node has no children. Maximum number of children
|
||||
/// may be found in node_maxchildren array.
|
||||
///
|
||||
/// Local values (present only for certain nodes):
|
||||
///
|
||||
/// "scope": a single Integer, specifies scope for "Option" and
|
||||
/// "PlainIdentifier" nodes. For "Option" it is one of
|
||||
/// ExprOptScope values, for "PlainIdentifier" it is one of
|
||||
/// ExprVarScope values.
|
||||
/// "ident": identifier (without scope, if any), present for "Option",
|
||||
/// "PlainIdentifier", "PlainKey" and "Environment" nodes.
|
||||
/// "name": Integer, register name (one character) or -1. Only present
|
||||
/// for "Register" nodes.
|
||||
/// "cmp_type": String, comparison type, one of the value names from
|
||||
/// ExprComparisonType, stringified without "kExprCmp"
|
||||
/// prefix. Only present for "Comparison" nodes.
|
||||
/// "ccs_strategy": String, case comparison strategy, one of the
|
||||
/// value names from ExprCaseCompareStrategy,
|
||||
/// stringified without "kCCStrategy" prefix. Only
|
||||
/// present for "Comparison" nodes.
|
||||
/// "augmentation": String, augmentation type for "Assignment" nodes.
|
||||
/// Is either an empty string, "Add", "Subtract" or
|
||||
/// "Concat" for "=", "+=", "-=" or ".=" respectively.
|
||||
/// "invert": Boolean, true if result of comparison needs to be
|
||||
/// inverted. Only present for "Comparison" nodes.
|
||||
/// "ivalue": Integer, integer value for "Integer" nodes.
|
||||
/// "fvalue": Float, floating-point value for "Float" nodes.
|
||||
/// "svalue": String, value for "SingleQuotedString" and
|
||||
/// "DoubleQuotedString" nodes.
|
||||
Dictionary nvim_parse_expression(String expr, String flags, Boolean highlight,
|
||||
Error *err)
|
||||
FUNC_API_SINCE(4) FUNC_API_ASYNC
|
||||
{
|
||||
int pflags = 0;
|
||||
for (size_t i = 0 ; i < flags.size ; i++) {
|
||||
switch (flags.data[i]) {
|
||||
case 'm': { pflags |= kExprFlagsMulti; break; }
|
||||
case 'E': { pflags |= kExprFlagsDisallowEOC; break; }
|
||||
case 'l': { pflags |= kExprFlagsParseLet; break; }
|
||||
case NUL: {
|
||||
api_set_error(err, kErrorTypeValidation, "Invalid flag: '\\0' (%u)",
|
||||
(unsigned)flags.data[i]);
|
||||
return (Dictionary)ARRAY_DICT_INIT;
|
||||
}
|
||||
default: {
|
||||
api_set_error(err, kErrorTypeValidation, "Invalid flag: '%c' (%u)",
|
||||
flags.data[i], (unsigned)flags.data[i]);
|
||||
return (Dictionary)ARRAY_DICT_INIT;
|
||||
}
|
||||
}
|
||||
}
|
||||
ParserLine plines[] = {
|
||||
{
|
||||
.data = expr.data,
|
||||
.size = expr.size,
|
||||
.allocated = false,
|
||||
},
|
||||
{ NULL, 0, false },
|
||||
};
|
||||
ParserLine *plines_p = plines;
|
||||
ParserHighlight colors;
|
||||
kvi_init(colors);
|
||||
ParserHighlight *const colors_p = (highlight ? &colors : NULL);
|
||||
ParserState pstate;
|
||||
viml_parser_init(
|
||||
&pstate, parser_simple_get_line, &plines_p, colors_p);
|
||||
ExprAST east = viml_pexpr_parse(&pstate, pflags);
|
||||
|
||||
const size_t ret_size = (
|
||||
2 // "ast", "len"
|
||||
+ (size_t)(east.err.msg != NULL) // "error"
|
||||
+ (size_t)highlight // "highlight"
|
||||
+ 0);
|
||||
Dictionary ret = {
|
||||
.items = xmalloc(ret_size * sizeof(ret.items[0])),
|
||||
.size = 0,
|
||||
.capacity = ret_size,
|
||||
};
|
||||
ret.items[ret.size++] = (KeyValuePair) {
|
||||
.key = STATIC_CSTR_TO_STRING("ast"),
|
||||
.value = NIL,
|
||||
};
|
||||
ret.items[ret.size++] = (KeyValuePair) {
|
||||
.key = STATIC_CSTR_TO_STRING("len"),
|
||||
.value = INTEGER_OBJ((Integer)(pstate.pos.line == 1
|
||||
? plines[0].size
|
||||
: pstate.pos.col)),
|
||||
};
|
||||
if (east.err.msg != NULL) {
|
||||
Dictionary err_dict = {
|
||||
.items = xmalloc(2 * sizeof(err_dict.items[0])),
|
||||
.size = 2,
|
||||
.capacity = 2,
|
||||
};
|
||||
err_dict.items[0] = (KeyValuePair) {
|
||||
.key = STATIC_CSTR_TO_STRING("message"),
|
||||
.value = STRING_OBJ(cstr_to_string(east.err.msg)),
|
||||
};
|
||||
if (east.err.arg == NULL) {
|
||||
err_dict.items[1] = (KeyValuePair) {
|
||||
.key = STATIC_CSTR_TO_STRING("arg"),
|
||||
.value = STRING_OBJ(STRING_INIT),
|
||||
};
|
||||
} else {
|
||||
err_dict.items[1] = (KeyValuePair) {
|
||||
.key = STATIC_CSTR_TO_STRING("arg"),
|
||||
.value = STRING_OBJ(((String) {
|
||||
.data = xmemdupz(east.err.arg, (size_t)east.err.arg_len),
|
||||
.size = (size_t)east.err.arg_len,
|
||||
})),
|
||||
};
|
||||
}
|
||||
ret.items[ret.size++] = (KeyValuePair) {
|
||||
.key = STATIC_CSTR_TO_STRING("error"),
|
||||
.value = DICTIONARY_OBJ(err_dict),
|
||||
};
|
||||
}
|
||||
if (highlight) {
|
||||
Array hl = (Array) {
|
||||
.items = xmalloc(kv_size(colors) * sizeof(hl.items[0])),
|
||||
.capacity = kv_size(colors),
|
||||
.size = kv_size(colors),
|
||||
};
|
||||
for (size_t i = 0 ; i < kv_size(colors) ; i++) {
|
||||
const ParserHighlightChunk chunk = kv_A(colors, i);
|
||||
Array chunk_arr = (Array) {
|
||||
.items = xmalloc(4 * sizeof(chunk_arr.items[0])),
|
||||
.capacity = 4,
|
||||
.size = 4,
|
||||
};
|
||||
chunk_arr.items[0] = INTEGER_OBJ((Integer)chunk.start.line);
|
||||
chunk_arr.items[1] = INTEGER_OBJ((Integer)chunk.start.col);
|
||||
chunk_arr.items[2] = INTEGER_OBJ((Integer)chunk.end_col);
|
||||
chunk_arr.items[3] = STRING_OBJ(cstr_to_string(chunk.group));
|
||||
hl.items[i] = ARRAY_OBJ(chunk_arr);
|
||||
}
|
||||
ret.items[ret.size++] = (KeyValuePair) {
|
||||
.key = STATIC_CSTR_TO_STRING("highlight"),
|
||||
.value = ARRAY_OBJ(hl),
|
||||
};
|
||||
}
|
||||
kvi_destroy(colors);
|
||||
|
||||
// Walk over the AST, freeing nodes in process.
|
||||
ExprASTConvStack ast_conv_stack;
|
||||
kvi_init(ast_conv_stack);
|
||||
kvi_push(ast_conv_stack, ((ExprASTConvStackItem) {
|
||||
.node_p = &east.root,
|
||||
.ret_node_p = &ret.items[0].value,
|
||||
}));
|
||||
while (kv_size(ast_conv_stack)) {
|
||||
ExprASTConvStackItem cur_item = kv_last(ast_conv_stack);
|
||||
ExprASTNode *const node = *cur_item.node_p;
|
||||
if (node == NULL) {
|
||||
assert(kv_size(ast_conv_stack) == 1);
|
||||
kv_drop(ast_conv_stack, 1);
|
||||
} else {
|
||||
if (cur_item.ret_node_p->type == kObjectTypeNil) {
|
||||
const size_t ret_node_items_size = (size_t)(
|
||||
3 // "type", "start" and "len"
|
||||
+ (node->children != NULL) // "children"
|
||||
+ (node->type == kExprNodeOption
|
||||
|| node->type == kExprNodePlainIdentifier) // "scope"
|
||||
+ (node->type == kExprNodeOption
|
||||
|| node->type == kExprNodePlainIdentifier
|
||||
|| node->type == kExprNodePlainKey
|
||||
|| node->type == kExprNodeEnvironment) // "ident"
|
||||
+ (node->type == kExprNodeRegister) // "name"
|
||||
+ (3 // "cmp_type", "ccs_strategy", "invert"
|
||||
* (node->type == kExprNodeComparison))
|
||||
+ (node->type == kExprNodeInteger) // "ivalue"
|
||||
+ (node->type == kExprNodeFloat) // "fvalue"
|
||||
+ (node->type == kExprNodeDoubleQuotedString
|
||||
|| node->type == kExprNodeSingleQuotedString) // "svalue"
|
||||
+ (node->type == kExprNodeAssignment) // "augmentation"
|
||||
+ 0);
|
||||
Dictionary ret_node = {
|
||||
.items = xmalloc(ret_node_items_size * sizeof(ret_node.items[0])),
|
||||
.capacity = ret_node_items_size,
|
||||
.size = 0,
|
||||
};
|
||||
*cur_item.ret_node_p = DICTIONARY_OBJ(ret_node);
|
||||
}
|
||||
Dictionary *ret_node = &cur_item.ret_node_p->data.dictionary;
|
||||
if (node->children != NULL) {
|
||||
const size_t num_children = 1 + (node->children->next != NULL);
|
||||
Array children_array = {
|
||||
.items = xmalloc(num_children * sizeof(children_array.items[0])),
|
||||
.capacity = num_children,
|
||||
.size = num_children,
|
||||
};
|
||||
for (size_t i = 0; i < num_children; i++) {
|
||||
children_array.items[i] = NIL;
|
||||
}
|
||||
ret_node->items[ret_node->size++] = (KeyValuePair) {
|
||||
.key = STATIC_CSTR_TO_STRING("children"),
|
||||
.value = ARRAY_OBJ(children_array),
|
||||
};
|
||||
kvi_push(ast_conv_stack, ((ExprASTConvStackItem) {
|
||||
.node_p = &node->children,
|
||||
.ret_node_p = &children_array.items[0],
|
||||
}));
|
||||
} else if (node->next != NULL) {
|
||||
kvi_push(ast_conv_stack, ((ExprASTConvStackItem) {
|
||||
.node_p = &node->next,
|
||||
.ret_node_p = cur_item.ret_node_p + 1,
|
||||
}));
|
||||
} else if (node != NULL) {
|
||||
kv_drop(ast_conv_stack, 1);
|
||||
ret_node->items[ret_node->size++] = (KeyValuePair) {
|
||||
.key = STATIC_CSTR_TO_STRING("type"),
|
||||
.value = STRING_OBJ(cstr_to_string(east_node_type_tab[node->type])),
|
||||
};
|
||||
Array start_array = {
|
||||
.items = xmalloc(2 * sizeof(start_array.items[0])),
|
||||
.capacity = 2,
|
||||
.size = 2,
|
||||
};
|
||||
start_array.items[0] = INTEGER_OBJ((Integer)node->start.line);
|
||||
start_array.items[1] = INTEGER_OBJ((Integer)node->start.col);
|
||||
ret_node->items[ret_node->size++] = (KeyValuePair) {
|
||||
.key = STATIC_CSTR_TO_STRING("start"),
|
||||
.value = ARRAY_OBJ(start_array),
|
||||
};
|
||||
ret_node->items[ret_node->size++] = (KeyValuePair) {
|
||||
.key = STATIC_CSTR_TO_STRING("len"),
|
||||
.value = INTEGER_OBJ((Integer)node->len),
|
||||
};
|
||||
switch (node->type) {
|
||||
case kExprNodeDoubleQuotedString:
|
||||
case kExprNodeSingleQuotedString: {
|
||||
ret_node->items[ret_node->size++] = (KeyValuePair) {
|
||||
.key = STATIC_CSTR_TO_STRING("svalue"),
|
||||
.value = STRING_OBJ(((String) {
|
||||
.data = node->data.str.value,
|
||||
.size = node->data.str.size,
|
||||
})),
|
||||
};
|
||||
break;
|
||||
}
|
||||
case kExprNodeOption: {
|
||||
ret_node->items[ret_node->size++] = (KeyValuePair) {
|
||||
.key = STATIC_CSTR_TO_STRING("scope"),
|
||||
.value = INTEGER_OBJ(node->data.opt.scope),
|
||||
};
|
||||
ret_node->items[ret_node->size++] = (KeyValuePair) {
|
||||
.key = STATIC_CSTR_TO_STRING("ident"),
|
||||
.value = STRING_OBJ(((String) {
|
||||
.data = xmemdupz(node->data.opt.ident,
|
||||
node->data.opt.ident_len),
|
||||
.size = node->data.opt.ident_len,
|
||||
})),
|
||||
};
|
||||
break;
|
||||
}
|
||||
case kExprNodePlainIdentifier: {
|
||||
ret_node->items[ret_node->size++] = (KeyValuePair) {
|
||||
.key = STATIC_CSTR_TO_STRING("scope"),
|
||||
.value = INTEGER_OBJ(node->data.var.scope),
|
||||
};
|
||||
ret_node->items[ret_node->size++] = (KeyValuePair) {
|
||||
.key = STATIC_CSTR_TO_STRING("ident"),
|
||||
.value = STRING_OBJ(((String) {
|
||||
.data = xmemdupz(node->data.var.ident,
|
||||
node->data.var.ident_len),
|
||||
.size = node->data.var.ident_len,
|
||||
})),
|
||||
};
|
||||
break;
|
||||
}
|
||||
case kExprNodePlainKey: {
|
||||
ret_node->items[ret_node->size++] = (KeyValuePair) {
|
||||
.key = STATIC_CSTR_TO_STRING("ident"),
|
||||
.value = STRING_OBJ(((String) {
|
||||
.data = xmemdupz(node->data.var.ident,
|
||||
node->data.var.ident_len),
|
||||
.size = node->data.var.ident_len,
|
||||
})),
|
||||
};
|
||||
break;
|
||||
}
|
||||
case kExprNodeEnvironment: {
|
||||
ret_node->items[ret_node->size++] = (KeyValuePair) {
|
||||
.key = STATIC_CSTR_TO_STRING("ident"),
|
||||
.value = STRING_OBJ(((String) {
|
||||
.data = xmemdupz(node->data.env.ident,
|
||||
node->data.env.ident_len),
|
||||
.size = node->data.env.ident_len,
|
||||
})),
|
||||
};
|
||||
break;
|
||||
}
|
||||
case kExprNodeRegister: {
|
||||
ret_node->items[ret_node->size++] = (KeyValuePair) {
|
||||
.key = STATIC_CSTR_TO_STRING("name"),
|
||||
.value = INTEGER_OBJ(node->data.reg.name),
|
||||
};
|
||||
break;
|
||||
}
|
||||
case kExprNodeComparison: {
|
||||
ret_node->items[ret_node->size++] = (KeyValuePair) {
|
||||
.key = STATIC_CSTR_TO_STRING("cmp_type"),
|
||||
.value = STRING_OBJ(cstr_to_string(
|
||||
eltkn_cmp_type_tab[node->data.cmp.type])),
|
||||
};
|
||||
ret_node->items[ret_node->size++] = (KeyValuePair) {
|
||||
.key = STATIC_CSTR_TO_STRING("ccs_strategy"),
|
||||
.value = STRING_OBJ(cstr_to_string(
|
||||
ccs_tab[node->data.cmp.ccs])),
|
||||
};
|
||||
ret_node->items[ret_node->size++] = (KeyValuePair) {
|
||||
.key = STATIC_CSTR_TO_STRING("invert"),
|
||||
.value = BOOLEAN_OBJ(node->data.cmp.inv),
|
||||
};
|
||||
break;
|
||||
}
|
||||
case kExprNodeFloat: {
|
||||
ret_node->items[ret_node->size++] = (KeyValuePair) {
|
||||
.key = STATIC_CSTR_TO_STRING("fvalue"),
|
||||
.value = FLOAT_OBJ(node->data.flt.value),
|
||||
};
|
||||
break;
|
||||
}
|
||||
case kExprNodeInteger: {
|
||||
ret_node->items[ret_node->size++] = (KeyValuePair) {
|
||||
.key = STATIC_CSTR_TO_STRING("ivalue"),
|
||||
.value = INTEGER_OBJ((Integer)(
|
||||
node->data.num.value > API_INTEGER_MAX
|
||||
? API_INTEGER_MAX
|
||||
: (Integer)node->data.num.value)),
|
||||
};
|
||||
break;
|
||||
}
|
||||
case kExprNodeAssignment: {
|
||||
const ExprAssignmentType asgn_type = node->data.ass.type;
|
||||
ret_node->items[ret_node->size++] = (KeyValuePair) {
|
||||
.key = STATIC_CSTR_TO_STRING("augmentation"),
|
||||
.value = STRING_OBJ(
|
||||
asgn_type == kExprAsgnPlain
|
||||
? (String)STRING_INIT
|
||||
: cstr_to_string(expr_asgn_type_tab[asgn_type])),
|
||||
};
|
||||
break;
|
||||
}
|
||||
case kExprNodeMissing:
|
||||
case kExprNodeOpMissing:
|
||||
case kExprNodeTernary:
|
||||
case kExprNodeTernaryValue:
|
||||
case kExprNodeSubscript:
|
||||
case kExprNodeListLiteral:
|
||||
case kExprNodeUnaryPlus:
|
||||
case kExprNodeBinaryPlus:
|
||||
case kExprNodeNested:
|
||||
case kExprNodeCall:
|
||||
case kExprNodeComplexIdentifier:
|
||||
case kExprNodeUnknownFigure:
|
||||
case kExprNodeLambda:
|
||||
case kExprNodeDictLiteral:
|
||||
case kExprNodeCurlyBracesIdentifier:
|
||||
case kExprNodeComma:
|
||||
case kExprNodeColon:
|
||||
case kExprNodeArrow:
|
||||
case kExprNodeConcat:
|
||||
case kExprNodeConcatOrSubscript:
|
||||
case kExprNodeOr:
|
||||
case kExprNodeAnd:
|
||||
case kExprNodeUnaryMinus:
|
||||
case kExprNodeBinaryMinus:
|
||||
case kExprNodeNot:
|
||||
case kExprNodeMultiplication:
|
||||
case kExprNodeDivision:
|
||||
case kExprNodeMod: {
|
||||
break;
|
||||
}
|
||||
}
|
||||
assert(cur_item.ret_node_p->data.dictionary.size
|
||||
== cur_item.ret_node_p->data.dictionary.capacity);
|
||||
xfree(*cur_item.node_p);
|
||||
*cur_item.node_p = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
kvi_destroy(ast_conv_stack);
|
||||
|
||||
assert(ret.size == ret.capacity);
|
||||
// Should be a no-op actually, leaving it in case non-nodes will need to be
|
||||
// freed later.
|
||||
viml_pexpr_free_ast(east);
|
||||
viml_parser_destroy(&pstate);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/// Writes a message to vim output or error buffer. The string is split
|
||||
/// and flushed after each newline. Incomplete lines are kept for writing
|
||||
@ -976,3 +1472,95 @@ Float nvim__id_float(Float flt)
|
||||
{
|
||||
return flt;
|
||||
}
|
||||
|
||||
/// Gets a list of dictionaries representing attached UIs.
|
||||
///
|
||||
/// @return Array of UI dictionaries
|
||||
Array nvim_list_uis(void)
|
||||
FUNC_API_SINCE(4)
|
||||
{
|
||||
return ui_array();
|
||||
}
|
||||
|
||||
/// Gets the immediate children of process `pid`.
|
||||
///
|
||||
/// @return Array of child process ids, empty if process not found.
|
||||
Array nvim_get_proc_children(Integer pid, Error *err)
|
||||
FUNC_API_SINCE(4)
|
||||
{
|
||||
Array rvobj = ARRAY_DICT_INIT;
|
||||
int *proc_list = NULL;
|
||||
|
||||
if (pid <= 0 || pid > INT_MAX) {
|
||||
api_set_error(err, kErrorTypeException, "Invalid pid: %" PRId64, pid);
|
||||
goto end;
|
||||
}
|
||||
|
||||
size_t proc_count;
|
||||
int rv = os_proc_children((int)pid, &proc_list, &proc_count);
|
||||
if (rv != 0) {
|
||||
// syscall failed (possibly because of kernel options), try shelling out.
|
||||
DLOG("fallback to vim._os_proc_children()");
|
||||
Array a = ARRAY_DICT_INIT;
|
||||
ADD(a, INTEGER_OBJ(pid));
|
||||
String s = cstr_to_string("return vim._os_proc_children(select(1, ...))");
|
||||
Object o = nvim_execute_lua(s, a, err);
|
||||
api_free_string(s);
|
||||
api_free_array(a);
|
||||
if (o.type == kObjectTypeArray) {
|
||||
rvobj = o.data.array;
|
||||
} else if (!ERROR_SET(err)) {
|
||||
api_set_error(err, kErrorTypeException,
|
||||
"Failed to get process children. pid=%" PRId64 " error=%d",
|
||||
pid, rv);
|
||||
}
|
||||
goto end;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < proc_count; i++) {
|
||||
ADD(rvobj, INTEGER_OBJ(proc_list[i]));
|
||||
}
|
||||
|
||||
end:
|
||||
xfree(proc_list);
|
||||
return rvobj;
|
||||
}
|
||||
|
||||
/// Gets info describing process `pid`.
|
||||
///
|
||||
/// @return Map of process properties, or NIL if process not found.
|
||||
Object nvim_get_proc(Integer pid, Error *err)
|
||||
FUNC_API_SINCE(4)
|
||||
{
|
||||
Object rvobj = OBJECT_INIT;
|
||||
rvobj.data.dictionary = (Dictionary)ARRAY_DICT_INIT;
|
||||
rvobj.type = kObjectTypeDictionary;
|
||||
|
||||
if (pid <= 0 || pid > INT_MAX) {
|
||||
api_set_error(err, kErrorTypeException, "Invalid pid: %" PRId64, pid);
|
||||
return NIL;
|
||||
}
|
||||
#ifdef WIN32
|
||||
rvobj.data.dictionary = os_proc_info((int)pid);
|
||||
if (rvobj.data.dictionary.size == 0) { // Process not found.
|
||||
return NIL;
|
||||
}
|
||||
#else
|
||||
// Cross-platform process info APIs are miserable, so use `ps` instead.
|
||||
Array a = ARRAY_DICT_INIT;
|
||||
ADD(a, INTEGER_OBJ(pid));
|
||||
String s = cstr_to_string("return vim._os_proc_info(select(1, ...))");
|
||||
Object o = nvim_execute_lua(s, a, err);
|
||||
api_free_string(s);
|
||||
api_free_array(a);
|
||||
if (o.type == kObjectTypeArray && o.data.array.size == 0) {
|
||||
return NIL; // Process not found.
|
||||
} else if (o.type == kObjectTypeDictionary) {
|
||||
rvobj.data.dictionary = o.data.dictionary;
|
||||
} else if (!ERROR_SET(err)) {
|
||||
api_set_error(err, kErrorTypeException,
|
||||
"Failed to get process info. pid=%" PRId64, pid);
|
||||
}
|
||||
#endif
|
||||
return rvobj;
|
||||
}
|
||||
|
1070
src/nvim/arabic.c
1070
src/nvim/arabic.c
File diff suppressed because it is too large
Load Diff
@ -3,6 +3,7 @@
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "nvim/macros.h"
|
||||
#include "nvim/func_attr.h"
|
||||
#include "nvim/os/os_defs.h"
|
||||
|
||||
@ -98,6 +99,10 @@ static inline bool ascii_isxdigit(int)
|
||||
REAL_FATTR_CONST
|
||||
REAL_FATTR_ALWAYS_INLINE;
|
||||
|
||||
static inline bool ascii_isident(int)
|
||||
REAL_FATTR_CONST
|
||||
REAL_FATTR_ALWAYS_INLINE;
|
||||
|
||||
static inline bool ascii_isbdigit(int)
|
||||
REAL_FATTR_CONST
|
||||
REAL_FATTR_ALWAYS_INLINE;
|
||||
@ -138,6 +143,14 @@ static inline bool ascii_isxdigit(int c)
|
||||
|| (c >= 'A' && c <= 'F');
|
||||
}
|
||||
|
||||
/// Checks if `c` is an “identifier” character
|
||||
///
|
||||
/// That is, whether it is alphanumeric character or underscore.
|
||||
static inline bool ascii_isident(int c)
|
||||
{
|
||||
return ASCII_ISALNUM(c) || c == '_';
|
||||
}
|
||||
|
||||
/// Checks if `c` is a binary digit, that is, 0-1.
|
||||
///
|
||||
/// @see {ascii_isdigit}
|
||||
|
@ -129,7 +129,7 @@ read_buffer(
|
||||
if (read_stdin) {
|
||||
// Set or reset 'modified' before executing autocommands, so that
|
||||
// it can be changed there.
|
||||
if (!readonlymode && !bufempty()) {
|
||||
if (!readonlymode && !BUFEMPTY()) {
|
||||
changed();
|
||||
} else if (retval != FAIL) {
|
||||
unchanged(curbuf, false);
|
||||
@ -1387,31 +1387,40 @@ void set_curbuf(buf_T *buf, int action)
|
||||
/* Don't restart Select mode after switching to another buffer. */
|
||||
VIsual_reselect = FALSE;
|
||||
|
||||
/* close_windows() or apply_autocmds() may change curbuf */
|
||||
// close_windows() or apply_autocmds() may change curbuf and wipe out "buf"
|
||||
prevbuf = curbuf;
|
||||
bufref_T bufref;
|
||||
set_bufref(&bufref, prevbuf);
|
||||
bufref_T newbufref;
|
||||
bufref_T prevbufref;
|
||||
set_bufref(&prevbufref, prevbuf);
|
||||
set_bufref(&newbufref, buf);
|
||||
|
||||
// Autocommands may delete the curren buffer and/or the buffer we wan to go
|
||||
// to. In those cases don't close the buffer.
|
||||
if (!apply_autocmds(EVENT_BUFLEAVE, NULL, NULL, false, curbuf)
|
||||
|| (bufref_valid(&bufref) && !aborting())) {
|
||||
|| (bufref_valid(&prevbufref) && bufref_valid(&newbufref)
|
||||
&& !aborting())) {
|
||||
if (prevbuf == curwin->w_buffer) {
|
||||
reset_synblock(curwin);
|
||||
}
|
||||
if (unload) {
|
||||
close_windows(prevbuf, false);
|
||||
}
|
||||
if (bufref_valid(&bufref) && !aborting()) {
|
||||
if (bufref_valid(&prevbufref) && !aborting()) {
|
||||
win_T *previouswin = curwin;
|
||||
if (prevbuf == curbuf)
|
||||
u_sync(FALSE);
|
||||
close_buffer(prevbuf == curwin->w_buffer ? curwin : NULL, prevbuf,
|
||||
unload ? action : (action == DOBUF_GOTO
|
||||
&& !P_HID(prevbuf)
|
||||
&& !bufIsChanged(
|
||||
prevbuf)) ? DOBUF_UNLOAD : 0, FALSE);
|
||||
if (curwin != previouswin && win_valid(previouswin))
|
||||
/* autocommands changed curwin, Grr! */
|
||||
if (prevbuf == curbuf) {
|
||||
u_sync(false);
|
||||
}
|
||||
close_buffer(prevbuf == curwin->w_buffer ? curwin : NULL,
|
||||
prevbuf,
|
||||
unload
|
||||
? action
|
||||
: (action == DOBUF_GOTO && !buf_hide(prevbuf)
|
||||
&& !bufIsChanged(prevbuf)) ? DOBUF_UNLOAD : 0,
|
||||
false);
|
||||
if (curwin != previouswin && win_valid(previouswin)) {
|
||||
// autocommands changed curwin, Grr!
|
||||
curwin = previouswin;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* An autocommand may have deleted "buf", already entered it (e.g., when
|
||||
@ -1616,7 +1625,7 @@ buf_T * buflist_new(char_u *ffname, char_u *sfname, linenr_T lnum, int flags)
|
||||
&& curbuf != NULL
|
||||
&& curbuf->b_ffname == NULL
|
||||
&& curbuf->b_nwindows <= 1
|
||||
&& (curbuf->b_ml.ml_mfp == NULL || bufempty())) {
|
||||
&& (curbuf->b_ml.ml_mfp == NULL || BUFEMPTY())) {
|
||||
buf = curbuf;
|
||||
/* It's like this buffer is deleted. Watch out for autocommands that
|
||||
* change curbuf! If that happens, allocate a new buffer anyway. */
|
||||
@ -1775,6 +1784,7 @@ void free_buf_options(buf_T *buf, int free_p_ff)
|
||||
clear_string_option(&buf->b_p_flp);
|
||||
clear_string_option(&buf->b_p_isk);
|
||||
clear_string_option(&buf->b_p_keymap);
|
||||
keymap_ga_clear(&buf->b_kmap_ga);
|
||||
ga_clear(&buf->b_kmap_ga);
|
||||
clear_string_option(&buf->b_p_com);
|
||||
clear_string_option(&buf->b_p_cms);
|
||||
@ -1808,6 +1818,7 @@ void free_buf_options(buf_T *buf, int free_p_ff)
|
||||
buf->b_p_ul = NO_LOCAL_UNDOLEVEL;
|
||||
clear_string_option(&buf->b_p_lw);
|
||||
clear_string_option(&buf->b_p_bkc);
|
||||
clear_string_option(&buf->b_p_menc);
|
||||
}
|
||||
|
||||
|
||||
@ -1870,7 +1881,7 @@ int buflist_getfile(int n, linenr_T lnum, int options, int forceit)
|
||||
// If 'switchbuf' contains "split", "vsplit" or "newtab" and the
|
||||
// current buffer isn't empty: open new tab or window
|
||||
if (wp == NULL && (swb_flags & (SWB_VSPLIT | SWB_SPLIT | SWB_NEWTAB))
|
||||
&& !bufempty()) {
|
||||
&& !BUFEMPTY()) {
|
||||
if (swb_flags & SWB_NEWTAB) {
|
||||
tabpage_new();
|
||||
} else if (win_split(0, (swb_flags & SWB_VSPLIT) ? WSP_VERT : 0)
|
||||
@ -2672,7 +2683,7 @@ void buflist_altfpos(win_T *win)
|
||||
}
|
||||
|
||||
/// Check that "ffname" is not the same file as current file.
|
||||
/// Fname must have a full path (expanded by path_get_absolute_path()).
|
||||
/// Fname must have a full path (expanded by path_to_absolute()).
|
||||
///
|
||||
/// @param ffname full path name to check
|
||||
bool otherfile(char_u *ffname)
|
||||
@ -2682,7 +2693,7 @@ bool otherfile(char_u *ffname)
|
||||
}
|
||||
|
||||
/// Check that "ffname" is not the same file as the file loaded in "buf".
|
||||
/// Fname must have a full path (expanded by path_get_absolute_path()).
|
||||
/// Fname must have a full path (expanded by path_to_absolute()).
|
||||
///
|
||||
/// @param buf buffer to check
|
||||
/// @param ffname full path name to check
|
||||
@ -4406,12 +4417,12 @@ do_arg_all (
|
||||
}
|
||||
wp->w_arg_idx = i;
|
||||
|
||||
if (i == opened_len && !keep_tabs) { /* close this window */
|
||||
if (P_HID(buf) || forceit || buf->b_nwindows > 1
|
||||
if (i == opened_len && !keep_tabs) { // close this window
|
||||
if (buf_hide(buf) || forceit || buf->b_nwindows > 1
|
||||
|| !bufIsChanged(buf)) {
|
||||
/* If the buffer was changed, and we would like to hide it,
|
||||
* try autowriting. */
|
||||
if (!P_HID(buf) && buf->b_nwindows <= 1 && bufIsChanged(buf)) {
|
||||
if (!buf_hide(buf) && buf->b_nwindows <= 1 && bufIsChanged(buf)) {
|
||||
bufref_T bufref;
|
||||
set_bufref(&bufref, buf);
|
||||
(void)autowrite(buf, false);
|
||||
@ -4426,7 +4437,7 @@ do_arg_all (
|
||||
&& (first_tabpage->tp_next == NULL || !had_tab)) {
|
||||
use_firstwin = true;
|
||||
} else {
|
||||
win_close(wp, !P_HID(buf) && !bufIsChanged(buf));
|
||||
win_close(wp, !buf_hide(buf) && !bufIsChanged(buf));
|
||||
// check if autocommands removed the next window
|
||||
if (!win_valid(wpnext)) {
|
||||
// start all over...
|
||||
@ -4460,11 +4471,12 @@ do_arg_all (
|
||||
last_curwin = curwin;
|
||||
last_curtab = curtab;
|
||||
win_enter(lastwin, false);
|
||||
/* ":drop all" should re-use an empty window to avoid "--remote-tab"
|
||||
* leaving an empty tab page when executed locally. */
|
||||
if (keep_tabs && bufempty() && curbuf->b_nwindows == 1
|
||||
&& curbuf->b_ffname == NULL && !curbuf->b_changed)
|
||||
use_firstwin = TRUE;
|
||||
// ":drop all" should re-use an empty window to avoid "--remote-tab"
|
||||
// leaving an empty tab page when executed locally.
|
||||
if (keep_tabs && BUFEMPTY() && curbuf->b_nwindows == 1
|
||||
&& curbuf->b_ffname == NULL && !curbuf->b_changed) {
|
||||
use_firstwin = true;
|
||||
}
|
||||
|
||||
for (i = 0; i < count && i < opened_len && !got_int; ++i) {
|
||||
if (alist == &global_alist && i == global_alist.al_ga.ga_len - 1)
|
||||
@ -4503,14 +4515,15 @@ do_arg_all (
|
||||
new_curwin = curwin;
|
||||
new_curtab = curtab;
|
||||
}
|
||||
(void)do_ecmd(0, alist_name(&AARGLIST(alist)[i]), NULL, NULL,
|
||||
ECMD_ONE,
|
||||
((P_HID(curwin->w_buffer)
|
||||
|| bufIsChanged(curwin->w_buffer)) ? ECMD_HIDE : 0)
|
||||
+ ECMD_OLDBUF, curwin);
|
||||
if (use_firstwin)
|
||||
++autocmd_no_leave;
|
||||
use_firstwin = FALSE;
|
||||
(void)do_ecmd(0, alist_name(&AARGLIST(alist)[i]), NULL, NULL, ECMD_ONE,
|
||||
((buf_hide(curwin->w_buffer)
|
||||
|| bufIsChanged(curwin->w_buffer))
|
||||
? ECMD_HIDE : 0) + ECMD_OLDBUF,
|
||||
curwin);
|
||||
if (use_firstwin) {
|
||||
autocmd_no_leave++;
|
||||
}
|
||||
use_firstwin = false;
|
||||
}
|
||||
os_breakcheck();
|
||||
|
||||
@ -4697,14 +4710,14 @@ void ex_buffer_all(exarg_T *eap)
|
||||
* Close superfluous windows.
|
||||
*/
|
||||
for (wp = lastwin; open_wins > count; ) {
|
||||
r = (P_HID(wp->w_buffer) || !bufIsChanged(wp->w_buffer)
|
||||
|| autowrite(wp->w_buffer, FALSE) == OK);
|
||||
r = (buf_hide(wp->w_buffer) || !bufIsChanged(wp->w_buffer)
|
||||
|| autowrite(wp->w_buffer, false) == OK);
|
||||
if (!win_valid(wp)) {
|
||||
/* BufWrite Autocommands made the window invalid, start over */
|
||||
wp = lastwin;
|
||||
} else if (r) {
|
||||
win_close(wp, !P_HID(wp->w_buffer));
|
||||
--open_wins;
|
||||
win_close(wp, !buf_hide(wp->w_buffer));
|
||||
open_wins--;
|
||||
wp = lastwin;
|
||||
} else {
|
||||
wp = wp->w_prev;
|
||||
|
@ -637,6 +637,7 @@ struct file_buffer {
|
||||
uint32_t b_p_fex_flags; ///< flags for 'formatexpr'
|
||||
char_u *b_p_kp; ///< 'keywordprg'
|
||||
int b_p_lisp; ///< 'lisp'
|
||||
char_u *b_p_menc; ///< 'makeencoding'
|
||||
char_u *b_p_mps; ///< 'matchpairs'
|
||||
int b_p_ml; ///< 'modeline'
|
||||
int b_p_ml_nobin; ///< b_p_ml saved for binary mode
|
||||
@ -717,6 +718,7 @@ struct file_buffer {
|
||||
int b_ind_hash_comment;
|
||||
int b_ind_cpp_namespace;
|
||||
int b_ind_if_for_while;
|
||||
int b_ind_cpp_extern_c;
|
||||
|
||||
linenr_T b_no_eol_lnum; /* non-zero lnum when last line of next binary
|
||||
* write should not have an end-of-line */
|
||||
|
@ -4,6 +4,7 @@
|
||||
#include "nvim/api/ui.h"
|
||||
#include "nvim/channel.h"
|
||||
#include "nvim/eval.h"
|
||||
#include "nvim/eval/encode.h"
|
||||
#include "nvim/event/socket.h"
|
||||
#include "nvim/msgpack_rpc/channel.h"
|
||||
#include "nvim/msgpack_rpc/server.h"
|
||||
@ -179,10 +180,12 @@ static Channel *channel_alloc(ChannelStreamType type)
|
||||
}
|
||||
|
||||
/// Not implemented, only logging for now
|
||||
void channel_create_event(Channel *chan, char *ext_source)
|
||||
void channel_create_event(Channel *chan, const char *ext_source)
|
||||
{
|
||||
#if MIN_LOG_LEVEL <= INFO_LOG_LEVEL
|
||||
char *stream_desc, *mode_desc, *source;
|
||||
const char *stream_desc;
|
||||
const char *mode_desc;
|
||||
const char *source;
|
||||
|
||||
switch (chan->streamtype) {
|
||||
case kChannelStreamProc:
|
||||
@ -222,8 +225,8 @@ void channel_create_event(Channel *chan, char *ext_source)
|
||||
// external events should be included.
|
||||
source = ext_source;
|
||||
} else {
|
||||
eval_format_source_name_line((char *)IObuff, sizeof(IObuff));
|
||||
source = (char *)IObuff;
|
||||
eval_fmt_source_name_line((char *)IObuff, sizeof(IObuff));
|
||||
source = (const char *)IObuff;
|
||||
}
|
||||
|
||||
ILOG("new channel %" PRIu64 " (%s%s): %s", chan->id, stream_desc,
|
||||
@ -234,15 +237,16 @@ void channel_create_event(Channel *chan, char *ext_source)
|
||||
#endif
|
||||
}
|
||||
|
||||
void channel_incref(Channel *channel)
|
||||
void channel_incref(Channel *chan)
|
||||
{
|
||||
channel->refcount++;
|
||||
chan->refcount++;
|
||||
}
|
||||
|
||||
void channel_decref(Channel *channel)
|
||||
void channel_decref(Channel *chan)
|
||||
{
|
||||
if (!(--channel->refcount)) {
|
||||
multiqueue_put(main_loop.fast_events, free_channel_event, 1, channel);
|
||||
if (!(--chan->refcount)) {
|
||||
// delay free, so that libuv is done with the handles
|
||||
multiqueue_put(main_loop.events, free_channel_event, 1, chan);
|
||||
}
|
||||
}
|
||||
|
||||
@ -264,18 +268,18 @@ void callback_reader_start(CallbackReader *reader)
|
||||
|
||||
static void free_channel_event(void **argv)
|
||||
{
|
||||
Channel *channel = argv[0];
|
||||
if (channel->is_rpc) {
|
||||
rpc_free(channel);
|
||||
Channel *chan = argv[0];
|
||||
if (chan->is_rpc) {
|
||||
rpc_free(chan);
|
||||
}
|
||||
|
||||
callback_reader_free(&channel->on_stdout);
|
||||
callback_reader_free(&channel->on_stderr);
|
||||
callback_free(&channel->on_exit);
|
||||
callback_reader_free(&chan->on_stdout);
|
||||
callback_reader_free(&chan->on_stderr);
|
||||
callback_free(&chan->on_exit);
|
||||
|
||||
pmap_del(uint64_t)(channels, channel->id);
|
||||
multiqueue_free(channel->events);
|
||||
xfree(channel);
|
||||
pmap_del(uint64_t)(channels, chan->id);
|
||||
multiqueue_free(chan->events);
|
||||
xfree(chan);
|
||||
}
|
||||
|
||||
static void channel_destroy_early(Channel *chan)
|
||||
@ -283,12 +287,15 @@ static void channel_destroy_early(Channel *chan)
|
||||
if ((chan->id != --next_chan_id)) {
|
||||
abort();
|
||||
}
|
||||
pmap_del(uint64_t)(channels, chan->id);
|
||||
chan->id = 0;
|
||||
|
||||
if ((--chan->refcount != 0)) {
|
||||
abort();
|
||||
}
|
||||
|
||||
free_channel_event((void **)&chan);
|
||||
// uv will keep a reference to handles until next loop tick, so delay free
|
||||
multiqueue_put(main_loop.events, free_channel_event, 1, chan);
|
||||
}
|
||||
|
||||
|
||||
@ -391,17 +398,22 @@ uint64_t channel_connect(bool tcp, const char *address,
|
||||
bool rpc, CallbackReader on_output,
|
||||
int timeout, const char **error)
|
||||
{
|
||||
Channel *channel;
|
||||
|
||||
if (!tcp && rpc) {
|
||||
char *path = fix_fname(address);
|
||||
if (server_owns_pipe_address(path)) {
|
||||
// avoid deadlock
|
||||
xfree(path);
|
||||
return channel_create_internal_rpc();
|
||||
}
|
||||
bool loopback = server_owns_pipe_address(path);
|
||||
xfree(path);
|
||||
if (loopback) {
|
||||
// Create a loopback channel. This avoids deadlock if nvim connects to
|
||||
// its own named pipe.
|
||||
channel = channel_alloc(kChannelStreamInternal);
|
||||
rpc_start(channel);
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
|
||||
Channel *channel = channel_alloc(kChannelStreamSocket);
|
||||
channel = channel_alloc(kChannelStreamSocket);
|
||||
if (!socket_connect(&main_loop, &channel->stream.socket,
|
||||
tcp, address, timeout, error)) {
|
||||
channel_destroy_early(channel);
|
||||
@ -421,7 +433,8 @@ uint64_t channel_connect(bool tcp, const char *address,
|
||||
rstream_start(&channel->stream.socket, on_socket_output, channel);
|
||||
}
|
||||
|
||||
channel_create_event(channel, NULL);
|
||||
end:
|
||||
channel_create_event(channel, address);
|
||||
return channel->id;
|
||||
}
|
||||
|
||||
@ -440,15 +453,6 @@ void channel_from_connection(SocketWatcher *watcher)
|
||||
channel_create_event(channel, watcher->addr);
|
||||
}
|
||||
|
||||
/// Creates a loopback channel. This is used to avoid deadlock
|
||||
/// when an instance connects to its own named pipe.
|
||||
static uint64_t channel_create_internal_rpc(void)
|
||||
{
|
||||
Channel *channel = channel_alloc(kChannelStreamInternal);
|
||||
rpc_start(channel);
|
||||
return channel->id;
|
||||
}
|
||||
|
||||
/// Creates an API channel from stdin/stdout. This is used when embedding
|
||||
/// Neovim
|
||||
uint64_t channel_from_stdio(bool rpc, CallbackReader on_output,
|
||||
@ -522,32 +526,21 @@ err:
|
||||
return 0;
|
||||
}
|
||||
|
||||
/// NB: mutates buf in place!
|
||||
static list_T *buffer_to_tv_list(char *buf, size_t count)
|
||||
/// Convert binary byte array to a readfile()-style list
|
||||
///
|
||||
/// @param[in] buf Array to convert.
|
||||
/// @param[in] len Array length.
|
||||
///
|
||||
/// @return [allocated] Converted list.
|
||||
static inline list_T *buffer_to_tv_list(const char *const buf, const size_t len)
|
||||
FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_ALWAYS_INLINE
|
||||
{
|
||||
list_T *ret = tv_list_alloc();
|
||||
char *ptr = buf;
|
||||
size_t remaining = count;
|
||||
size_t off = 0;
|
||||
|
||||
while (off < remaining) {
|
||||
// append the line
|
||||
if (ptr[off] == NL) {
|
||||
tv_list_append_string(ret, ptr, (ssize_t)off);
|
||||
size_t skip = off + 1;
|
||||
ptr += skip;
|
||||
remaining -= skip;
|
||||
off = 0;
|
||||
continue;
|
||||
}
|
||||
if (ptr[off] == NUL) {
|
||||
// Translate NUL to NL
|
||||
ptr[off] = NL;
|
||||
}
|
||||
off++;
|
||||
}
|
||||
tv_list_append_string(ret, ptr, (ssize_t)off);
|
||||
return ret;
|
||||
list_T *const l = tv_list_alloc(kListLenMayKnow);
|
||||
// Empty buffer should be represented by [''], encode_list_write() thinks
|
||||
// empty list is fine for the case.
|
||||
tv_list_append_string(l, "", 0);
|
||||
encode_list_write(l, buf, len);
|
||||
return l;
|
||||
}
|
||||
|
||||
// vimscript job callbacks must be executed on Nvim main loop
|
||||
@ -599,6 +592,7 @@ static void on_stdio_input(Stream *stream, RBuffer *buf, size_t count,
|
||||
on_channel_output(stream, chan, buf, count, eof, &chan->on_stdout, "stdin");
|
||||
}
|
||||
|
||||
/// @param type must have static lifetime
|
||||
static void on_channel_output(Stream *stream, Channel *chan, RBuffer *buf,
|
||||
size_t count, bool eof, CallbackReader *reader,
|
||||
const char *type)
|
||||
@ -613,14 +607,20 @@ static void on_channel_output(Stream *stream, Channel *chan, RBuffer *buf,
|
||||
if (reader->cb.type != kCallbackNone) {
|
||||
process_channel_event(chan, &reader->cb, type, reader->buffer.ga_data,
|
||||
(size_t)reader->buffer.ga_len, 0);
|
||||
ga_clear(&reader->buffer);
|
||||
} else if (reader->self) {
|
||||
list_T *data = buffer_to_tv_list(reader->buffer.ga_data,
|
||||
(size_t)reader->buffer.ga_len);
|
||||
tv_dict_add_list(reader->self, type, strlen(type), data);
|
||||
if (tv_dict_find(reader->self, type, -1) == NULL) {
|
||||
list_T *data = buffer_to_tv_list(reader->buffer.ga_data,
|
||||
(size_t)reader->buffer.ga_len);
|
||||
tv_dict_add_list(reader->self, type, strlen(type), data);
|
||||
} else {
|
||||
// can't display error message now, defer it.
|
||||
channel_incref(chan);
|
||||
multiqueue_put(chan->events, on_buffered_error, 2, chan, type);
|
||||
}
|
||||
} else {
|
||||
abort();
|
||||
}
|
||||
ga_clear(&reader->buffer);
|
||||
} else if (reader->cb.type != kCallbackNone) {
|
||||
process_channel_event(chan, &reader->cb, type, ptr, 0, 0);
|
||||
}
|
||||
@ -641,6 +641,14 @@ static void on_channel_output(Stream *stream, Channel *chan, RBuffer *buf,
|
||||
}
|
||||
}
|
||||
|
||||
static void on_buffered_error(void **args)
|
||||
{
|
||||
Channel *chan = (Channel *)args[0];
|
||||
const char *stream = (const char *)args[1];
|
||||
EMSG3(_(e_streamkey), stream, chan->id);
|
||||
channel_decref(chan);
|
||||
}
|
||||
|
||||
static void channel_process_exit_cb(Process *proc, int status, void *data)
|
||||
{
|
||||
Channel *chan = data;
|
||||
@ -673,7 +681,7 @@ static void on_channel_event(void **args)
|
||||
argv[1].v_type = VAR_LIST;
|
||||
argv[1].v_lock = VAR_UNLOCKED;
|
||||
argv[1].vval.v_list = ev->received;
|
||||
argv[1].vval.v_list->lv_refcount++;
|
||||
tv_list_ref(argv[1].vval.v_list);
|
||||
} else {
|
||||
argv[1].v_type = VAR_NUMBER;
|
||||
argv[1].v_lock = VAR_UNLOCKED;
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user