Merge 'upstream/master' into pr-win-erw7

This commit is contained in:
Justin M. Keyes 2018-12-27 22:49:44 +01:00
commit c1015121ec
202 changed files with 16938 additions and 2339 deletions

View File

@ -8,6 +8,7 @@ IndentCaseLabels: true
BreakBeforeBraces: Linux
AlignEscapedNewlinesLeft: false
AllowShortFunctionsOnASingleLine: false
AlignTrailingComments: true
SpacesBeforeTrailingComments: 2
PenaltyReturnTypeOnItsOwnLine: 200
AllowAllParametersOfDeclarationOnNextLine: false
@ -15,4 +16,5 @@ AllowShortIfStatementsOnASingleLine: false
AllowShortLoopsOnASingleLine: false
BinPackParameters: false
BreakBeforeBinaryOperators: true
BreakBeforeTernaryOperators: true
ContinuationIndentWidth: 4

View File

@ -1,5 +1,5 @@
dist: trusty
sudo: false
dist: xenial
language: c
env:
@ -25,7 +25,7 @@ env:
-DBUSTED_OUTPUT_TYPE=nvim
-DDEPS_PREFIX=$DEPS_BUILD_DIR/usr
-DMIN_LOG_LEVEL=3"
- DEPS_CMAKE_FLAGS="-DDEPS_DOWNLOAD_DIR:PATH=$DEPS_DOWNLOAD_DIR"
- DEPS_CMAKE_FLAGS="-DDEPS_DOWNLOAD_DIR:PATH=$DEPS_DOWNLOAD_DIR -DUSE_BUNDLED_GPERF=OFF"
# Additional CMake flags for 32-bit builds.
- CMAKE_FLAGS_32BIT="-DCMAKE_SYSTEM_LIBRARY_PATH=/lib32:/usr/lib32:/usr/local/lib32
-DCMAKE_IGNORE_PATH=/lib:/usr/lib:/usr/local/lib
@ -34,6 +34,7 @@ env:
- ASAN_OPTIONS="detect_leaks=1:check_initialization_order=1:log_path=$LOG_DIR/asan"
- TSAN_OPTIONS="log_path=$LOG_DIR/tsan"
- UBSAN_OPTIONS="print_stacktrace=1 log_path=$LOG_DIR/ubsan"
- ASAN_SYMBOLIZE=asan_symbolize
# Environment variables for Valgrind.
- VALGRIND_LOG="$LOG_DIR/valgrind-%p.log"
# If this file exists, the cache is valid (compile was successful).
@ -50,12 +51,12 @@ jobs:
include:
- stage: normal builds
os: linux
compiler: clang
compiler: clang-4.0
# Use Lua so that ASAN can test our embedded Lua support. 8fec4d53d0f6
env: >
CLANG_SANITIZER=ASAN_UBSAN
# Use Lua so that ASAN can test our embedded Lua support. 8fec4d53d0f6
CMAKE_FLAGS="$CMAKE_FLAGS -DPREFER_LUA=ON"
sudo: true
ASAN_SYMBOLIZE=asan_symbolize-4.0
- os: linux
compiler: gcc
env: >
@ -96,29 +97,35 @@ before_cache: ci/before_cache.sh
addons:
apt:
packages:
- apport
- autoconf
- automake
- apport
- build-essential
- clang
- clang-4.0
- cmake
- cscope
- g++-multilib
- gcc-multilib
- gdb
- gperf
- language-pack-tr
- libc6-dev-i386
- libtool
- libtool-bin
- locales
- ninja-build
- pkg-config
- unzip
- valgrind
- xclip
homebrew:
update: true
packages:
- ccache
- ninja
branches:
except:
- nightly
only:
- master
cache:
apt: true

View File

@ -6,7 +6,10 @@ cmake_minimum_required(VERSION 2.8.12)
project(nvim C)
if(POLICY CMP0059)
cmake_policy(SET CMP0059 OLD) # Needed until cmake 2.8.12. #4389
# Needed for use of DEFINITIONS variable, which is used to collect the
# compilation flags for reporting in "nvim --version"
# https://github.com/neovim/neovim/pull/8558#issuecomment-398033140
cmake_policy(SET CMP0059 OLD)
endif()
# Point CMake at any custom modules we may ship
@ -386,7 +389,7 @@ include_directories(SYSTEM ${MSGPACK_INCLUDE_DIRS})
option(PREFER_LUA "Prefer Lua over LuaJIT in the nvim executable." OFF)
if(PREFER_LUA)
find_package(Lua REQUIRED)
find_package(Lua 5.1 REQUIRED)
set(LUA_PREFERRED_INCLUDE_DIRS ${LUA_INCLUDE_DIR})
set(LUA_PREFERRED_LIBRARIES ${LUA_LIBRARIES})
# Passive (not REQUIRED): if LUAJIT_FOUND is not set, nvim-test is skipped.
@ -407,6 +410,7 @@ main(void)
return MSGPACK_OBJECT_FLOAT32;
}
" MSGPACK_HAS_FLOAT32)
unset(CMAKE_REQUIRED_LIBRARIES)
if(MSGPACK_HAS_FLOAT32)
add_definitions(-DNVIM_MSGPACK_HAS_FLOAT32)
endif()
@ -428,11 +432,13 @@ if(FEAT_TUI)
return unibi_num_from_var(unibi_var_from_num(0));
}
" UNIBI_HAS_VAR_FROM)
unset(CMAKE_REQUIRED_INCLUDES)
unset(CMAKE_REQUIRED_LIBRARIES)
if(UNIBI_HAS_VAR_FROM)
add_definitions(-DNVIM_UNIBI_HAS_VAR_FROM)
endif()
find_package(LibTermkey REQUIRED)
find_package(LibTermkey 0.18 REQUIRED)
include_directories(SYSTEM ${LIBTERMKEY_INCLUDE_DIRS})
endif()
@ -440,7 +446,7 @@ find_package(LibVterm REQUIRED)
include_directories(SYSTEM ${LIBVTERM_INCLUDE_DIRS})
if(WIN32)
find_package(Winpty REQUIRED)
find_package(Winpty 0.4.3 REQUIRED)
include_directories(SYSTEM ${WINPTY_INCLUDE_DIRS})
endif()
@ -700,7 +706,7 @@ if(LUACHECK_PRG)
-P ${PROJECT_SOURCE_DIR}/cmake/RunLuacheck.cmake)
add_custom_target(
blobcodelint
lintbuiltinlua
COMMAND
${CMAKE_COMMAND}
-DLUACHECK_PRG=${LUACHECK_PRG}
@ -709,10 +715,21 @@ if(LUACHECK_PRG)
-DREAD_GLOBALS=vim
-P ${PROJECT_SOURCE_DIR}/cmake/RunLuacheck.cmake
)
add_custom_target(
lintruntimelua
COMMAND
${CMAKE_COMMAND}
-DLUACHECK_PRG=${LUACHECK_PRG}
-DLUAFILES_DIR=${CMAKE_CURRENT_SOURCE_DIR}/runtime/lua
-DCMAKE_SYSTEM_NAME=${CMAKE_SYSTEM_NAME}
-DREAD_GLOBALS=vim
-P ${PROJECT_SOURCE_DIR}/cmake/RunLuacheck.cmake
)
# TODO(ZyX-I): Run linter for all lua code in src
add_custom_target(
lualint
DEPENDS blobcodelint
DEPENDS lintruntimelua
DEPENDS lintbuiltinlua
)
endif()

View File

@ -103,6 +103,10 @@ endif
helptags: | nvim
+$(BUILD_CMD) -C build helptags
# Builds help HTML _and_ checks for invalid help tags.
helphtml: | nvim helptags
+$(BUILD_CMD) -C build doc_html
functionaltest: | nvim
+$(BUILD_CMD) -C build functionaltest

View File

@ -59,7 +59,10 @@ To list all targets:
cmake --build build --target help
To skip "bundled" (`third-party/*`) dependencies, define `USE_BUNDLED=NO`.
To skip "bundled" dependencies (`third-party/*`) define `USE_BUNDLED=NO`:
sudo apt install gperf libluajit-5.1-dev libunibilium-dev libmsgpack-dev libtermkey-dev libvterm-dev libjemalloc-dev
make USE_BUNDLED=NO
See the [Building Neovim](https://github.com/neovim/neovim/wiki/Building-Neovim) wiki page for details.
@ -83,7 +86,7 @@ Project layout
├─ ci/ build automation
├─ cmake/ build scripts
├─ runtime/ user plugins/docs
├─ src/ application source code (see src/nvim/README.md)
├─ src/nvim/ application source code (see src/nvim/README.md)
│ ├─ api/ API subsystem
│ ├─ eval/ VimL subsystem
│ ├─ event/ event-loop subsystem

View File

@ -7,10 +7,6 @@ if [[ "${CI_TARGET}" == lint ]]; then
exit
fi
if [[ "${TRAVIS_OS_NAME}" == osx ]]; then
>/dev/null brew update
fi
echo 'python info:'
(
2>&1 python --version || true

View File

@ -50,6 +50,9 @@ if ($compiler -eq 'MINGW') {
# Add MinGW to the PATH
$env:PATH = "C:\msys64\mingw$bits\bin;$env:PATH"
# Avoid pacman "warning" which causes non-zero return code. https://github.com/open62541/open62541/issues/2068
& C:\msys64\usr\bin\mkdir -p /var/cache/pacman/pkg
# 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 $mingwPackages" ; exitIfFailed
@ -65,14 +68,14 @@ elseif ($compiler -eq 'MSVC') {
}
# Setup python (use AppVeyor system python)
C:\Python27\python.exe -m pip install neovim ; exitIfFailed
C:\Python35\python.exe -m pip install neovim ; exitIfFailed
C:\Python27\python.exe -m pip install pynvim ; exitIfFailed
C:\Python35\python.exe -m pip install pynvim ; 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
python -c "import pynvim; print(str(pynvim))" ; exitIfFailed
python3 -c "import pynvim; print(str(pynvim))" ; exitIfFailed
$env:PATH = "C:\Ruby24\bin;$env:PATH"
gem.cmd install neovim

View File

@ -83,7 +83,7 @@ valgrind_check() {
asan_check() {
if test "${CLANG_SANITIZER}" = "ASAN_UBSAN" ; then
check_logs "${1}" "*san.*" | asan_symbolize
check_logs "${1}" "*san.*" | $ASAN_SYMBOLIZE
fi
}

View File

@ -8,10 +8,6 @@ if [[ "${CI_TARGET}" == lint ]]; then
fi
if [[ "${TRAVIS_OS_NAME}" == osx ]]; then
brew install ninja
brew install gettext
brew reinstall -s libtool
brew install ccache
export PATH="/usr/local/opt/ccache/libexec:$PATH"
fi
@ -26,11 +22,11 @@ if ! [ "${TRAVIS_OS_NAME}" = osx ] ; then
# Use default CC to avoid compilation problems when installing Python modules.
echo "Install neovim module for Python 2."
CC=cc python2.7 -m pip -q install --user --upgrade neovim
echo "Install neovim RubyGem."
gem install --no-document --version ">= 0.2.0" neovim
fi
echo "Install neovim RubyGem."
gem install --no-document --version ">= 0.8.0" neovim
echo "Install neovim npm package"
npm install -g neovim
npm link neovim

View File

@ -38,7 +38,10 @@ 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 --lpath=?.lua ${TEST_PATH}
--lpath=${BUILD_DIR}/?.lua
--lpath=${WORKING_DIR}/runtime/lua/?.lua
--lpath=?.lua
${TEST_PATH}
WORKING_DIRECTORY ${WORKING_DIR}
ERROR_VARIABLE err
RESULT_VARIABLE res

View File

@ -13,7 +13,9 @@ coverage:
status:
project: yes
patch: yes
patch:
default:
threshold: 1
changes: no
parsers:

View File

@ -20,10 +20,21 @@
.Sh DESCRIPTION
.Nm
is a text editor based on Vim.
Commands in this program start with colon
Start
.Nm
followed by any number of options and/or files:
.Pp
.Dl nvim [options] [file ...]
.Pp
Commands in
.Nm
begin with colon
.Pq Sq \&: .
Use the :help command to get help, for example ":help quickref"
is a condensed overview of almost all commands.
Type ":help subject" to get help on a specific subject.
Use <Tab> and CTRL-D to complete subjects (":help cmdline\-completion").
.Pp
The "quickref" help section is a condensed reference of editor features:
.Dl :help quickref
.Pp
If you are new to Vim/Nvim, start with the 30-minute tutorial:
.Dl :Tutor
@ -34,28 +45,25 @@ After installing/updating Nvim, it's a good idea to run the self-check:
.Bl -tag -width Fl
.It Ar file ...
File(s) to edit.
If none are specified, open an empty buffer.
If multiple files are specified, open one buffer for each file.
Opens one buffer per file.
To switch between buffers, use the
.Ic :next
and
.Ic :previous
commands.
.It Fl
Read text from standard input until
Reads text from standard input until
.Dv EOF ,
then open a buffer with that text.
then opens a buffer with that text.
User input is read from standard error, which should be a terminal.
.Sh OPTIONS
.Bl -tag -width Fl
.It Fl t Ar tag
The file to edit and the initial cursor position depends on a
tag, a sort of goto label.
Finds
.Ar tag
is looked up in the tags file, the associated file becomes the current
in the tags file, the associated file becomes the current
file and the associated command is executed.
If
.Ar tag
is a function name, the file containing that function is opened
with the cursor positioned at the start of the function.
Cursor is positioned at the tag location in the file.
.Ic ":help tag-commands"
.It Fl q Op Ar errorfile
QuickFix mode.
@ -69,7 +77,6 @@ Further errors can be jumped to with the
.Ic :cnext
command.
.Ic ":help quickfix"
.It There are a number of other options:
.It Fl -
End of options.
Remaining arguments are treated as literal file names, including filenames starting with hyphen

View File

@ -68,9 +68,9 @@ foreach(DF ${DOCFILES})
endforeach()
add_custom_target(helptags
COMMAND ${CMAKE_COMMAND} -E remove ${GENERATED_RUNTIME_DIR}/doc/*
COMMAND ${CMAKE_COMMAND} -E remove doc/*
COMMAND ${CMAKE_COMMAND} -E copy_directory
${PROJECT_SOURCE_DIR}/runtime/doc ${GENERATED_RUNTIME_DIR}/doc
${PROJECT_SOURCE_DIR}/runtime/doc doc
COMMAND "${PROJECT_BINARY_DIR}/bin/nvim"
-u NONE -i NONE -e --headless -c "helptags ++t doc" -c quit
DEPENDS
@ -87,7 +87,7 @@ add_custom_command(OUTPUT ${GENERATED_HELP_TAGS}
add_custom_target(doc_html
COMMAND make html
DEPENDS
${GENERATED_HELP_TAGS}
helptags
WORKING_DIRECTORY "${GENERATED_RUNTIME_DIR}/doc"
)

View File

@ -152,10 +152,10 @@ function! s:check_clipboard() abort
endif
endfunction
" Get the latest Neovim Python client version from PyPI.
" Get the latest Neovim Python client (pynvim) version from PyPI.
function! s:latest_pypi_version() abort
let pypi_version = 'unable to get pypi response'
let pypi_response = s:download('https://pypi.python.org/pypi/neovim/json')
let pypi_response = s:download('https://pypi.python.org/pypi/pynvim/json')
if !empty(pypi_response)
try
let pypi_data = json_decode(pypi_response)
@ -192,9 +192,9 @@ function! s:version_info(python) abort
let nvim_path = s:trim(s:system([
\ a:python, '-c',
\ 'import sys; sys.path.remove(""); ' .
\ 'import neovim; print(neovim.__file__)']))
\ 'import pynvim; print(pynvim.__file__)']))
if s:shell_error || empty(nvim_path)
return [python_version, 'unable to load neovim Python module', pypi_version,
return [python_version, 'unable to load pynvim Python module', pypi_version,
\ nvim_path]
endif
@ -206,13 +206,13 @@ function! s:version_info(python) abort
return a == b ? 0 : a > b ? 1 : -1
endfunction
" Try to get neovim.VERSION (added in 0.1.11dev).
" Try to get pynvim.VERSION (added in 0.1.11dev).
let nvim_version = s:system([a:python, '-c',
\ 'from neovim import VERSION as v; '.
\ 'from pynvim import VERSION as v; '.
\ 'print("{}.{}.{}{}".format(v.major, v.minor, v.patch, v.prerelease))'],
\ '', 1, 1)
if empty(nvim_version)
let nvim_version = 'unable to find neovim Python module version'
let nvim_version = 'unable to find pynvim Python module version'
let base = fnamemodify(nvim_path, ':h')
let metas = glob(base.'-*/METADATA', 1, 1)
\ + glob(base.'-*/PKG-INFO', 1, 1)
@ -293,7 +293,7 @@ function! s:check_python(version) abort
let [pyname, pythonx_errs] = provider#pythonx#Detect(a:version)
if empty(pyname)
call health#report_warn('No Python interpreter was found with the neovim '
call health#report_warn('No Python interpreter was found with the pynvim '
\ . 'module. Using the first available for diagnostics.')
elseif exists('g:'.host_prog_var)
let python_bin = pyname
@ -352,7 +352,7 @@ function! s:check_python(version) abort
call health#report_warn('pyenv is not set up optimally.', [
\ printf('Create a virtualenv specifically '
\ . 'for Neovim using pyenv, and set `g:%s`. This will avoid '
\ . 'the need to install the Neovim Python module in each '
\ . 'the need to install the pynvim module in each '
\ . 'version/virtualenv.', host_prog_var)
\ ])
elseif !empty(venv)
@ -366,7 +366,7 @@ function! s:check_python(version) abort
call health#report_warn('Your virtualenv is not set up optimally.', [
\ printf('Create a virtualenv specifically '
\ . 'for Neovim and use `g:%s`. This will avoid '
\ . 'the need to install Neovim''s Python module in each '
\ . 'the need to install the pynvim module in each '
\ . 'virtualenv.', host_prog_var)
\ ])
endif
@ -400,6 +400,8 @@ function! s:check_python(version) abort
endfor
endif
let pip = 'pip' . (a:version == 2 ? '' : '3')
if !empty(python_bin)
let [pyversion, current, latest, status] = s:version_info(python_bin)
if a:version != str2nr(pyversion)
@ -410,28 +412,35 @@ function! s:check_python(version) abort
call health#report_warn('Python 3.3+ is recommended.')
endif
call health#report_info('Python'.a:version.' version: ' . pyversion)
call health#report_info('Python version: ' . pyversion)
if s:is_bad_response(status)
call health#report_info(printf('%s-neovim version: %s (%s)', pyname, current, status))
call health#report_info(printf('pynvim version: %s (%s)', current, status))
else
call health#report_info(printf('%s-neovim version: %s', pyname, current))
call health#report_info(printf('pynvim version: %s', current))
let [module_found, _msg] = provider#pythonx#CheckForModule(python_bin,
\ 'neovim', a:version)
if !module_found
call health#report_error('Importing "neovim" failed.',
\ "Reinstall \"pynvim\" and optionally \"neovim\" packages.\n" .
\ pip ." uninstall pynvim neovim\n" .
\ pip ." install pynvim\n" .
\ pip ." install neovim # only if needed by third-party software")
endif
endif
if s:is_bad_response(current)
call health#report_error(
\ "Neovim Python client is not installed.\nError: ".current,
\ ['Run in shell: pip' . a:version . ' install neovim'])
\ "pynvim is not installed.\nError: ".current,
\ ['Run in shell: '. pip .' install pynvim'])
endif
if s:is_bad_response(latest)
call health#report_warn('Could not contact PyPI to get latest version.')
call health#report_error('HTTP request failed: '.latest)
elseif s:is_bad_response(status)
call health#report_warn(printf('Latest %s-neovim is NOT installed: %s',
\ pyname, latest))
call health#report_warn(printf('Latest pynvim is NOT installed: %s', latest))
elseif !s:is_bad_response(current)
call health#report_ok(printf('Latest %s-neovim is installed: %s',
\ pyname, latest))
call health#report_ok(printf('Latest pynvim is installed.'))
endif
endif

View File

@ -60,6 +60,7 @@ function! provider#clipboard#Executable() abort
let s:err = 'clipboard: invalid g:clipboard'
return ''
endif
let s:copy = get(g:clipboard, 'copy', { '+': v:null, '*': v:null })
let s:paste = get(g:clipboard, 'paste', { '+': v:null, '*': v:null })
let s:cache_enabled = get(g:clipboard, 'cache_enabled', 0)
@ -71,18 +72,24 @@ function! provider#clipboard#Executable() abort
let s:paste['*'] = s:paste['+']
let s:cache_enabled = 0
return 'pbcopy'
elseif exists('$DISPLAY') && executable('xsel') && s:cmd_ok('xsel -o -b')
let s:copy['+'] = 'xsel --nodetach -i -b'
let s:paste['+'] = 'xsel -o -b'
let s:copy['*'] = 'xsel --nodetach -i -p'
let s:paste['*'] = 'xsel -o -p'
return 'xsel'
elseif exists('$WAYLAND_DISPLAY') && executable('wl-copy') && executable('wl-paste')
let s:copy['+'] = 'wl-copy --foreground'
let s:paste['+'] = 'wl-paste --no-newline'
let s:copy['*'] = 'wl-copy --foreground --primary'
let s:paste['*'] = 'wl-paste --no-newline --primary'
return 'wl-copy'
elseif exists('$DISPLAY') && executable('xclip')
let s:copy['+'] = 'xclip -quiet -i -selection clipboard'
let s:paste['+'] = 'xclip -o -selection clipboard'
let s:copy['*'] = 'xclip -quiet -i -selection primary'
let s:paste['*'] = 'xclip -o -selection primary'
return 'xclip'
elseif exists('$DISPLAY') && executable('xsel') && s:cmd_ok('xsel -o -b')
let s:copy['+'] = 'xsel --nodetach -i -b'
let s:paste['+'] = 'xsel -o -b'
let s:copy['*'] = 'xsel --nodetach -i -p'
let s:paste['*'] = 'xsel -o -p'
return 'xsel'
elseif executable('lemonade')
let s:copy['+'] = 'lemonade copy'
let s:paste['+'] = 'lemonade paste'
@ -95,9 +102,9 @@ function! provider#clipboard#Executable() abort
let s:copy['*'] = s:copy['+']
let s:paste['*'] = s:paste['+']
return 'doitclient'
elseif executable('win32yank')
let s:copy['+'] = 'win32yank -i --crlf'
let s:paste['+'] = 'win32yank -o --lf'
elseif executable('win32yank.exe')
let s:copy['+'] = 'win32yank.exe -i --crlf'
let s:paste['+'] = 'win32yank.exe -o --lf'
let s:copy['*'] = s:copy['+']
let s:paste['*'] = s:paste['+']
return 'win32yank'
@ -121,7 +128,9 @@ if empty(provider#clipboard#Executable())
endif
function! s:clipboard.get(reg) abort
if s:selections[a:reg].owner > 0
if type(s:paste[a:reg]) == v:t_func
return s:paste[a:reg]()
elseif s:selections[a:reg].owner > 0
return s:selections[a:reg].data
end
return s:try_cmd(s:paste[a:reg])
@ -135,6 +144,12 @@ function! s:clipboard.set(lines, regtype, reg) abort
end
return 0
end
if type(s:copy[a:reg]) == v:t_func
call s:copy[a:reg](a:lines, a:regtype)
return 0
end
if s:cache_enabled == 0
call s:try_cmd(s:copy[a:reg], a:lines)
return 0

View File

@ -49,7 +49,7 @@ endfunction
function! provider#node#Detect() abort
if exists('g:node_host_prog')
return g:node_host_prog
return expand(g:node_host_prog)
endif
if !s:is_minimum_version(v:null, 6, 0)
return ''

View File

@ -10,7 +10,7 @@ function! provider#pythonx#Require(host) abort
" Python host arguments
let prog = (ver == '2' ? provider#python#Prog() : provider#python3#Prog())
let args = [prog, '-c', 'import sys; sys.path.remove(""); import neovim; neovim.start_host()']
let args = [prog, '-c', 'import sys; sys.path.remove(""); import pynvim; pynvim.start_host()']
" Collect registered Python plugins into args
let python_plugins = remote#host#PluginsForHost(a:host.name)
@ -24,13 +24,13 @@ endfunction
function! provider#pythonx#Detect(major_ver) abort
if a:major_ver == 2
if exists('g:python_host_prog')
return [g:python_host_prog, '']
return [expand(g:python_host_prog), '']
else
let progs = ['python2', 'python2.7', 'python2.6', 'python']
endif
else
if exists('g:python3_host_prog')
return [g:python3_host_prog, '']
return [expand(g:python3_host_prog), '']
else
let progs = ['python3', 'python3.7', 'python3.6', 'python3.5',
\ 'python3.4', 'python3.3', 'python']
@ -40,7 +40,7 @@ function! provider#pythonx#Detect(major_ver) abort
let errors = []
for prog in progs
let [result, err] = s:check_interpreter(prog, a:major_ver)
let [result, err] = provider#pythonx#CheckForModule(prog, 'pynvim', a:major_ver)
if result
return [prog, err]
endif
@ -54,46 +54,53 @@ function! provider#pythonx#Detect(major_ver) abort
\ . ":\n" . join(errors, "\n")]
endfunction
function! s:check_interpreter(prog, major_ver) abort
" Returns array: [prog_exitcode, prog_version]
function! s:import_module(prog, module) abort
let prog_version = system([a:prog, '-c' , printf(
\ 'import sys; ' .
\ 'sys.path.remove(""); ' .
\ 'sys.stdout.write(str(sys.version_info[0]) + "." + str(sys.version_info[1])); ' .
\ 'import pkgutil; ' .
\ 'exit(2*int(pkgutil.get_loader("%s") is None))',
\ a:module)])
return [v:shell_error, prog_version]
endfunction
" Returns array: [was_success, error_message]
function! provider#pythonx#CheckForModule(prog, module, major_version) abort
let prog_path = exepath(a:prog)
if prog_path ==# ''
return [0, a:prog . ' not found in search path or not executable.']
endif
let min_version = (a:major_ver == 2) ? '2.6' : '3.3'
let min_version = (a:major_version == 2) ? '2.6' : '3.3'
" Try to load neovim module, and output Python version.
" Return codes:
" 0 Neovim module can be loaded.
" 2 Neovim module cannot be loaded.
" Try to load pynvim module, and output Python version.
" Exit codes:
" 0 pynvim module can be loaded.
" 2 pynvim module cannot be loaded.
" Otherwise something else went wrong (e.g. 1 or 127).
let prog_ver = system([ a:prog , '-c' ,
\ 'import sys; ' .
\ 'sys.path.remove(""); ' .
\ 'sys.stdout.write(str(sys.version_info[0]) + "." + str(sys.version_info[1])); ' .
\ 'import pkgutil; ' .
\ 'exit(2*int(pkgutil.get_loader("neovim") is None))'
\ ])
let [prog_exitcode, prog_version] = s:import_module(a:prog, 'pynvim')
if v:shell_error == 2 || v:shell_error == 0
if prog_exitcode == 2 || prog_exitcode == 0
" Check version only for expected return codes.
if prog_ver !~ '^' . a:major_ver
return [0, prog_path . ' is Python ' . prog_ver . ' and cannot provide Python '
\ . a:major_ver . '.']
elseif prog_ver =~ '^' . a:major_ver && prog_ver < min_version
return [0, prog_path . ' is Python ' . prog_ver . ' and cannot provide Python >= '
if prog_version !~ '^' . a:major_version
return [0, prog_path . ' is Python ' . prog_version . ' and cannot provide Python '
\ . a:major_version . '.']
elseif prog_version =~ '^' . a:major_version && prog_version < min_version
return [0, prog_path . ' is Python ' . prog_version . ' and cannot provide Python >= '
\ . min_version . '.']
endif
endif
if v:shell_error == 2
return [0, prog_path.' does not have the "neovim" module. :help provider-python']
elseif v:shell_error == 127
if prog_exitcode == 2
return [0, prog_path.' does not have the "pynvim" module. :help provider-python']
elseif prog_exitcode == 127
" This can happen with pyenv's shims.
return [0, prog_path . ' does not exist: ' . prog_ver]
elseif v:shell_error
return [0, prog_path . ' does not exist: ' . prog_version]
elseif prog_exitcode
return [0, 'Checking ' . prog_path . ' caused an unknown error. '
\ . '(' . v:shell_error . ', output: ' . prog_ver . ')'
\ . '(' . prog_exitcode . ', output: ' . prog_version . ')'
\ . ' Report this at https://github.com/neovim/neovim']
endif

View File

@ -45,7 +45,7 @@ endfunction
function! s:detect()
if exists("g:ruby_host_prog")
return g:ruby_host_prog
return expand(g:ruby_host_prog)
elseif has('win32')
return exepath('neovim-ruby-host.bat')
else

View File

@ -153,15 +153,14 @@ fun! tar#Browse(tarfile)
let tarfile=substitute(system("cygpath -u ".shellescape(tarfile,0)),'\n$','','e')
endif
let gzip_command = s:get_gzip_command(tarfile)
let curlast= line("$")
if tarfile =~# '\.\(gz\|tgz\)$'
let gzip_command = s:get_gzip_command(tarfile)
" call Decho("1: exe silent r! gzip -d -c -- ".shellescape(tarfile,1)." | ".g:tar_cmd." -".g:tar_browseoptions." - ")
exe "sil! r! " . gzip_command . " -d -c -- ".shellescape(tarfile,1)." | ".g:tar_cmd." -".g:tar_browseoptions." - "
elseif tarfile =~# '\.lrp'
" call Decho("2: exe silent r! cat -- ".shellescape(tarfile,1)."|gzip -d -c -|".g:tar_cmd." -".g:tar_browseoptions." - ")
exe "sil! r! cat -- ".shellescape(tarfile,1)."|" . gzip_command . " -d -c -|".g:tar_cmd." -".g:tar_browseoptions." - "
exe "sil! r! cat -- ".shellescape(tarfile,1)."|gzip -d -c -|".g:tar_cmd." -".g:tar_browseoptions." - "
elseif tarfile =~# '\.\(bz2\|tbz\|tb2\)$'
" call Decho("3: exe silent r! bzip2 -d -c -- ".shellescape(tarfile,1)." | ".g:tar_cmd." -".g:tar_browseoptions." - ")
exe "sil! r! bzip2 -d -c -- ".shellescape(tarfile,1)." | ".g:tar_cmd." -".g:tar_browseoptions." - "
@ -291,17 +290,16 @@ fun! tar#Read(fname,mode)
let tar_secure= " "
endif
let gzip_command = s:get_gzip_command(tarfile)
if tarfile =~# '\.bz2$'
" call Decho("7: exe silent r! bzip2 -d -c ".shellescape(tarfile,1)."| ".g:tar_cmd." -".g:tar_readoptions." - ".tar_secure.shellescape(fname,1).decmp)
exe "sil! r! bzip2 -d -c -- ".shellescape(tarfile,1)."| ".g:tar_cmd." -".g:tar_readoptions." - ".tar_secure.shellescape(fname,1).decmp
elseif tarfile =~# '\.\(gz\|tgz\)$'
let gzip_command = s:get_gzip_command(tarfile)
" call Decho("5: exe silent r! gzip -d -c -- ".shellescape(tarfile,1)."| ".g:tar_cmd.' -'.g:tar_readoptions.' - '.tar_secure.shellescape(fname,1))
exe "sil! r! " . gzip_command . " -d -c -- ".shellescape(tarfile,1)."| ".g:tar_cmd." -".g:tar_readoptions." - ".tar_secure.shellescape(fname,1).decmp
elseif tarfile =~# '\.lrp$'
" call Decho("6: exe silent r! cat ".shellescape(tarfile,1)." | gzip -d -c - | ".g:tar_cmd." -".g:tar_readoptions." - ".tar_secure.shellescape(fname,1).decmp)
exe "sil! r! cat -- ".shellescape(tarfile,1)." | " . gzip_command . " -d -c - | ".g:tar_cmd." -".g:tar_readoptions." - ".tar_secure.shellescape(fname,1).decmp
exe "sil! r! cat -- ".shellescape(tarfile,1)." | gzip -d -c - | ".g:tar_cmd." -".g:tar_readoptions." - ".tar_secure.shellescape(fname,1).decmp
elseif tarfile =~# '\.lzma$'
" call Decho("7: exe silent r! lzma -d -c ".shellescape(tarfile,1)."| ".g:tar_cmd." -".g:tar_readoptions." - ".tar_secure.shellescape(fname,1).decmp)
exe "sil! r! lzma -d -c -- ".shellescape(tarfile,1)."| ".g:tar_cmd." -".g:tar_readoptions." - ".tar_secure.shellescape(fname,1).decmp
@ -589,8 +587,9 @@ fun! tar#Vimuntar(...)
" if necessary, decompress the tarball; then, extract it
if tartail =~ '\.tgz'
if executable("bzip2")
silent exe "!bzip2 -d ".shellescape(tartail)
let gzip_command = s:get_gzip_command(tarfile)
if executable(gzip_command)
silent exe "!" . gzip_command . " -d ".shellescape(tartail)
elseif executable("gunzip")
silent exe "!gunzip ".shellescape(tartail)
elseif executable("gzip")
@ -630,11 +629,24 @@ fun! tar#Vimuntar(...)
endfun
func s:get_gzip_command(file)
if a:file =~# 'z$' && executable('bzip2')
" Some .tgz files are actually compressed with bzip2. Since bzip2 can
" handle the format from gzip, use it if the command exists.
" Try using the "file" command to get the actual compression type, since
" there is no standard way for the naming: ".tgz", ".tbz", ".txz", etc.
" If the "file" command doesn't work fall back to just using the file name.
if a:file =~# 'z$'
let filetype = system('file ' . a:file)
if filetype =~ 'bzip2 compressed' && executable('bzip2')
return 'bzip2'
endif
if filetype =~ 'XZ compressed' && executable('xz')
return 'xz'
endif
endif
if a:file =~# 'bz2$'
return 'bzip2'
endif
if a:file =~# 'xz$'
return 'xz'
endif
return 'gzip'
endfunc

View File

@ -79,6 +79,19 @@ As Nvim evolves the API may change in compliance with this CONTRACT:
- Existing items will not be removed (after release).
- Deprecated functions will not be removed until Nvim version 2.0
==============================================================================
Global events *api-global-events*
When a client invokes an API request as an async notification, it is not
possible for Nvim to send an error response. Instead, in case of error, the
following notification will be sent to the client:
*nvim_error_event*
nvim_error_event[{type}, {message}]
{type} is a numeric id as defined by `api_info().error_types`, and {message} is
a string with the error message.
==============================================================================
Buffer update events *api-buffer-updates*
@ -97,7 +110,7 @@ nvim_buf_lines_event[{buf}, {changedtick}, {firstline}, {lastline}, {linedata},
When {changedtick} is |v:null| this means the screen lines (display) changed
but not the buffer contents. {linedata} contains the changed screen lines.
This happens when |inccommand| shows a buffer preview.
This happens when 'inccommand' shows a buffer preview.
Properties:~
{buf} API buffer handle (buffer number)
@ -138,7 +151,7 @@ nvim_buf_changedtick_event[{buf}, {changedtick}] *nvim_buf_changedtick_event*
nvim_buf_detach_event[{buf}] *nvim_buf_detach_event*
When buffer is detached (i.e. updates are disabled). Triggered explicitly by
|nvim_buf_detach| or implicitly in these cases:
|nvim_buf_detach()| or implicitly in these cases:
- Buffer was |abandon|ed and 'hidden' is not set.
- Buffer was reloaded, e.g. with |:edit| or an external change triggered
|:checktime| or 'autoread'.
@ -206,7 +219,7 @@ Example using the Nvim python-client:
buf.clear_highlight(src)
<
If the highlights don't need to be deleted or updated, just pass -1 as
src_id (this is the default in python). Use |nvim_buf_clear_highlight()| to
src_id (this is the default in python). Use |nvim_buf_clear_namespace()| to
clear highlights from a specific source, in a specific line range or the
entire buffer by passing in the line range 0, -1 (the latter is the default in
python as used above).
@ -218,7 +231,7 @@ An example of calling the api from vimscript: >
call nvim_buf_add_highlight(0, src, "Identifier", 0, 5, -1)
" later
call nvim_buf_clear_highlight(0, src, 0, -1)
call nvim_buf_clear_namespace(0, src, 0, -1)
>
==============================================================================
Global Functions *api-global*
@ -478,6 +491,9 @@ nvim_err_writeln({str}) *nvim_err_writeln()*
nvim_list_bufs() *nvim_list_bufs()*
Gets the current list of buffer handles
Includes unlisted (unloaded/deleted) buffers, like `:ls!`. Use
|nvim_buf_is_loaded()| to check if a buffer is loaded.
Return: ~
List of buffer handles
@ -529,6 +545,30 @@ nvim_set_current_tabpage({tabpage}) *nvim_set_current_tabpage()*
Parameters: ~
{tabpage} Tabpage handle
nvim_create_namespace({name}) *nvim_create_namespace()*
create a new namespace, or get one with an exisiting name
Namespaces are currently used for buffer highlighting and
virtual text, see |nvim_buf_add_highlight| and
|nvim_buf_set_virtual_text|.
Namespaces can have a name of be anonymous. If `name` is a
non-empty string, and a namespace already exists with that
name,the existing namespace id is returned. If an empty string
is used, a new anonymous namespace is returned.
Parameters: ~
{name} Name of the namespace or empty string
Return: ~
the namespace id
nvim_get_namespaces() *nvim_get_namespaces()*
Get existing named namespaces
Return: ~
dict that maps from names to namespace ids.
nvim_subscribe({event}) *nvim_subscribe()*
Subscribes to event broadcasts
@ -638,7 +678,7 @@ nvim_set_client_info({name}, {version}, {type}, {methods},
Clients might define their own keys, but the
following are suggested: "website" Website
of client (for instance github repository)
"license" Informal descripton of the
"license" Informal description of the
license, such as "Apache 2", "GPLv3" or
"MIT" "logo" URI or path to image,
preferably small logo or icon. .png or .svg
@ -862,8 +902,7 @@ nvim_buf_line_count({buffer}) *nvim_buf_line_count()*
{buffer} Buffer handle
Return: ~
Line count, or `0` if the buffer has been unloaded (see
|api-buffer|).
Line count, or 0 for unloaded buffer. |api-buffer|
nvim_buf_attach({buffer}, {send_buffer}, {opts}) *nvim_buf_attach()*
Activate updates from this buffer to the current channel.
@ -912,8 +951,7 @@ nvim_buf_get_lines({buffer}, {start}, {end}, {strict_indexing})
error.
Return: ~
Array of lines. If the buffer has been unloaded then an
empty array will be returned instead. (See |api-buffer|.)
Array of lines, or empty array for unloaded buffer.
*nvim_buf_set_lines()*
nvim_buf_set_lines({buffer}, {start}, {end}, {strict_indexing},
@ -940,6 +978,25 @@ nvim_buf_set_lines({buffer}, {start}, {end}, {strict_indexing},
error.
{replacement} Array of lines to use as replacement
nvim_buf_get_offset({buffer}, {index}) *nvim_buf_get_offset()*
Returns the byte offset for a line.
Line 1 (index=0) has offset 0. UTF-8 bytes are counted. EOL is
one byte. 'fileformat' and 'fileencoding' are ignored. The
line index just after the last line gives the total byte-count
of the buffer. A final EOL byte is counted if it would be
written, see 'eol'.
Unlike |line2byte()|, throws error for out-of-bounds indexing.
Returns -1 for unloaded buffer.
Parameters: ~
{buffer} Buffer handle
{index} Line index
Return: ~
Integer byte offset, or -1 for unloaded buffer.
nvim_buf_get_var({buffer}, {name}) *nvim_buf_get_var()*
Gets a buffer-scoped (b:) variable.
@ -1065,35 +1122,36 @@ nvim_buf_get_mark({buffer}, {name}) *nvim_buf_get_mark()*
(row, col) tuple
*nvim_buf_add_highlight()*
nvim_buf_add_highlight({buffer}, {src_id}, {hl_group}, {line},
nvim_buf_add_highlight({buffer}, {ns_id}, {hl_group}, {line},
{col_start}, {col_end})
Adds a highlight to buffer.
Useful for plugins that dynamically generate highlights to a
buffer (like a semantic highlighter or linter). The function
adds a single highlight to a buffer. Unlike matchaddpos()
adds a single highlight to a buffer. Unlike |matchaddpos()|
highlights follow changes to line numbering (as lines are
inserted/removed above the highlighted line), like signs and
marks do.
`src_id` is useful for batch deletion/updating of a set of
highlights. When called with `src_id = 0`, an unique source id
is generated and returned. Successive calls can pass that
`src_id` to associate new highlights with the same source
group. All highlights in the same group can be cleared with
`nvim_buf_clear_highlight`. If the highlight never will be
manually deleted, pass `src_id = -1`.
Namespaces are used for batch deletion/updating of a set of
highlights. To create a namespace, use |nvim_create_namespace|
which returns a namespace id. Pass it in to this function as
`ns_id` to add highlights to the namespace. All highlights in
the same namespace can then be cleared with single call to
|nvim_buf_clear_namespace|. If the highlight never will be
deleted by an API call, pass `ns_id = -1`.
If `hl_group` is the empty string no highlight is added, but a
new `src_id` is still returned. This is useful for an external
plugin to synchrounously request an unique `src_id` at
initialization, and later asynchronously add and clear
highlights in response to buffer changes.
As a shorthand, `ns_id = 0` can be used to create a new
namespace for the highlight, the allocated id is then
returned. If `hl_group` is the empty string no highlight is
added, but a new `ns_id` is still returned. This is supported
for backwards compatibility, new code should use
|nvim_create_namespace| to create a new empty namespace.
Parameters: ~
{buffer} Buffer handle
{src_id} Source group to use or 0 to use a new group,
or -1 for ungrouped highlight
{ns_id} namespace to use or -1 for ungrouped
highlight
{hl_group} Name of the highlight group to use
{line} Line to highlight (zero-indexed)
{col_start} Start of (byte-indexed) column range to
@ -1102,39 +1160,50 @@ nvim_buf_add_highlight({buffer}, {src_id}, {hl_group}, {line},
highlight, or -1 to highlight to end of line
Return: ~
The src_id that was used
The ns_id that was used
*nvim_buf_clear_highlight()*
nvim_buf_clear_highlight({buffer}, {src_id}, {line_start}, {line_end})
Clears highlights from a given source group and a range of
lines
*nvim_buf_clear_namespace()*
nvim_buf_clear_namespace({buffer}, {ns_id}, {line_start}, {line_end})
Clears namespaced objects, highlights and virtual text, from a
line range
To clear a source group in the entire buffer, pass in 0 and -1
To clear the namespace in the entire buffer, pass in 0 and -1
to line_start and line_end respectively.
Parameters: ~
{buffer} Buffer handle
{src_id} Highlight source group to clear, or -1 to
clear all.
{ns_id} Namespace to clear, or -1 to clear all
namespaces.
{line_start} Start of range of lines to clear
{line_end} End of range of lines to clear (exclusive)
or -1 to clear to end of file.
or -1 to clear to end of buffer.
*nvim_buf_set_virtual_text()*
nvim_buf_set_virtual_text({buffer}, {src_id}, {line}, {chunks},
{opts})
nvim_buf_set_virtual_text({buffer}, {ns_id}, {line}, {chunks}, {opts})
Set the virtual text (annotation) for a buffer line.
By default (and currently the only option) the text will be
placed after the buffer text. Virtual text will never cause
reflow, rather virtual text will be truncated at the end of
the screen line. The virtual text will begin after one cell to
the right of the ordinary text, this will contain the |lcs-
eol| char if set, otherwise just be a space.
the screen line. The virtual text will begin one cell (|lcs-
eol| or space) after the ordinary text.
Namespaces are used to support batch deletion/updating of
virtual text. To create a namespace, use
|nvim_create_namespace|. Virtual text is cleared using
|nvim_buf_clear_namespace|. The same `ns_id` can be used for
both virtual text and highlights added by
|nvim_buf_add_highlight|, both can then be cleared with a
single call to |nvim_buf_clear_namespace|. If the virtual text
never will be cleared by an API call, pass `ns_id = -1`.
As a shorthand, `ns_id = 0` can be used to create a new
namespace for the virtual text, the allocated id is then
returned.
Parameters: ~
{buffer} Buffer handle
{src_id} Source group to use or 0 to use a new group, or
{ns_id} Namespace to use or 0 to create a namespace, or
-1 for a ungrouped annotation
{line} Line to annotate with virtual text (zero-
indexed)
@ -1145,7 +1214,7 @@ nvim_buf_set_virtual_text({buffer}, {src_id}, {line}, {chunks},
{opts} Optional parameters. Currently not used.
Return: ~
The src_id that was used
The ns_id that was used
==============================================================================
@ -1160,6 +1229,13 @@ nvim_win_get_buf({window}) *nvim_win_get_buf()*
Return: ~
Buffer handle
nvim_win_set_buf({window}, {buffer}) *nvim_win_set_buf()*
Sets the current buffer in a window, without side-effects
Parameters: ~
{window} Window handle
{buffer} Buffer handle
nvim_win_get_cursor({window}) *nvim_win_get_cursor()*
Gets the cursor position in the window

View File

@ -278,7 +278,7 @@ Name triggered by ~
|VimEnter| after doing all the startup stuff
|GUIEnter| after starting the GUI successfully
|GUIFailed| after starting the GUI failed
|TermResponse| after the terminal response to |t_RV| is received
|TermResponse| after the terminal response to t_RV is received
|QuitPre| when using `:quit`, before deciding whether to exit
|ExitPre| when using a command that may make Vim exit
|VimLeavePre| before exiting Nvim, before writing the shada file
@ -521,25 +521,24 @@ CmdUndefined When a user command is used but it isn't
command is defined. An alternative is to
always define the user command and have it
invoke an autoloaded function. See |autoload|.
*CmdlineChanged*
CmdlineChanged After a change was made to the text in the
command line. Be careful not to mess up
the command line, it may cause Vim to lock up.
*CmdlineChanged*
CmdlineChanged After a change was made to the text inside
command line. Be careful not to mess up the
command line, it may cause Vim to lock up.
<afile> is set to the |cmdline-char|.
*CmdlineEnter*
CmdlineEnter After moving the cursor to the command line,
where the user can type a command or search
string.
<afile> is set to a single character,
indicating the type of command-line.
|cmdline-char|
CmdlineEnter After entering the command-line (including
non-interactive use of ":" in a mapping: use
|<Cmd>| instead to avoid this).
<afile> is set to the |cmdline-char|.
Sets these |v:event| keys:
cmdlevel
cmdtype
*CmdlineLeave*
CmdlineLeave Before leaving the command line.
<afile> is set to a single character,
indicating the type of command-line.
|cmdline-char|
CmdlineLeave Before leaving the command-line (including
non-interactive use of ":" in a mapping: use
|<Cmd>| instead to avoid this).
<afile> is set to the |cmdline-char|.
Sets these |v:event| keys:
abort (mutable)
cmdlevel
@ -630,6 +629,11 @@ CursorMoved After the cursor was moved in Normal or Visual
CursorMovedI After the cursor was moved in Insert mode.
Not triggered when the popup menu is visible.
Otherwise the same as CursorMoved.
*DiffUpdated*
DiffUpdated After diffs have been updated. Depending on
what kind of diff is being used (internal or
external) this can be triggered on every
change or when doing |:diffupdate|.
*DirChanged*
DirChanged After the |current-directory| was changed.
Sets these |v:event| keys:
@ -989,7 +993,7 @@ TermClose When a |terminal| job ends.
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
TermResponse After the response to t_RV is received from
the terminal. The value of |v:termresponse|
can be used to do things depending on the
terminal version. Note that this event may be

View File

@ -212,7 +212,7 @@ CTRL-\ e {expr} *c_CTRL-\_e*
*c_CTRL-Y*
CTRL-Y When there is a modeless selection, copy the selection into
the clipboard. |modeless-selection|
the clipboard.
If there is no selection CTRL-Y is inserted as a character.
CTRL-M or CTRL-J *c_CTRL-M* *c_CTRL-J* *c_<NL>* *c_<CR>* *c_CR*

View File

@ -162,12 +162,8 @@ In WinDbg: choose Open Crash Dump on the File menu. Follow the instructions in
*get-ms-debuggers*
3.5 Obtaining Microsoft Debugging Tools ~
The Debugging Tools for Windows (including WinDbg) can be downloaded from
http://www.microsoft.com/whdc/devtools/debugging/default.mspx
This includes the WinDbg debugger.
Visual C++ 2005 Express Edition can be downloaded for free from:
http://msdn.microsoft.com/vstudio/express/visualC/default.aspx
Visual Studio 2017 Community Edition can be downloaded for free from:
https://visualstudio.microsoft.com/downloads/
=========================================================================
vim:tw=78:ts=8:noet:ft=help:norl:

View File

@ -37,15 +37,17 @@ Functions ~
*file_readable()* Obsolete name for |filereadable()|.
*highlight_exists()* Obsolete name for |hlexists()|.
*highlightID()* Obsolete name for |hlID()|.
*inputdialog()* Use |input()| instead.
*jobclose()* Obsolete name for |chanclose()|
*jobsend()* Obsolete name for |chansend()|
*last_buffer_nr()* Obsolete name for bufnr("$").
Modifiers ~
*cpo-<*
*:menu-<special>*
*:menu-special* <> notation is always enabled. |cpo-<|
*:menu-special* <> notation is always enabled.
*:map-<special>*
*:map-special* <> notation is always enabled. |cpo-<|
*:map-special* <> notation is always enabled.
Normal commands ~
*]f*

View File

@ -6,19 +6,20 @@
Development of Nvim *development*
Nvim is open source software. Everybody is encouraged to contribute.
https://github.com/neovim/neovim/blob/master/CONTRIBUTING.md
This reference describes design constraints and guidelines, for developing
Nvim applications or Nvim itself.
Architecture and internal concepts are covered in src/nvim/README.md
See src/nvim/README.md for an overview of the source code.
Nvim is free and open source. Everybody is encouraged to contribute.
https://github.com/neovim/neovim/blob/master/CONTRIBUTING.md
Type |gO| to see the table of contents.
==============================================================================
Design goals *design-goals*
Most important things come first (roughly).
Note that some items conflict; this is intentional. A balance must be found.
Most important things come first (roughly). Some items conflict; this is
intentional. A balance must be found.
NVIM IS... IMPROVED *design-improved*
@ -81,41 +82,6 @@ include the kitchen sink... but it's good for plumbing."
Developer guidelines *dev*
JARGON *dev-jargon*
API client ~
All external UIs and remote plugins (as opposed to regular Vim plugins) are
"clients" in general; but we call something an "API client" if its purpose is
to abstract or wrap the RPC API for the convenience of other applications
(just like a REST client or SDK such as boto3 for AWS: you can speak AWS REST
using an HTTP client like curl, but boto3 wraps that in a convenient python
interface). For example, the Nvim lua-client is an API client:
https://github.com/neovim/lua-client
Host ~
A plugin "host" is both a client (of the Nvim API) and a server (of an
external platform, e.g. python). It is a remote plugin that hosts other
plugins.
Remote plugin ~
Arbitrary code registered via |:UpdateRemotePlugins|, that runs in a separate
process and communicates with Nvim via the |api|.
Window ~
The word "window" is commonly used for several things: A window on the screen,
the xterm window, a window inside Vim to view a buffer.
To avoid confusion, other items that are sometimes called window have been
given another name. Here is an overview of the related items:
screen The whole display.
shell The Vim application. This can cover the whole screen (e.g.,
when running in a console) or part of it (xterm or GUI).
window View on a buffer. There can be several windows in Vim,
together with the command line, menubar, toolbar, etc. they
fit in the shell.
frame Windows are kept in a tree of frames. Each frame contains
a column, row, or window ("leaf" frame).
PROVIDERS *dev-provider*
A goal of Nvim is to allow extension of the editor without special knowledge
@ -215,6 +181,8 @@ Standard Features ~
- Clients should call |nvim_set_client_info()| after connecting, so users and
plugins can detect the client by handling the |ChanInfo| event. This
avoids the need for special variables or other client hints.
- Clients should handle |nvim_error_event| notifications, which will be sent
if an async request to nvim was rejected or caused an error.
Package Naming ~

View File

@ -27,7 +27,9 @@ The second and following arguments may also be a directory name. Vim will
then append the file name of the first argument to the directory name to find
the file.
This only works when a standard "diff" command is available. See 'diffexpr'.
By default an internal diff library will be used. When 'diffopt' or
'diffexpr' has been set an external "diff" command will be used. This only
works when such a diff program is available.
Diffs are local to the current tab page |tab-page|. You can't see diffs with
a window in another tab page. This does make it possible to have several
@ -332,8 +334,9 @@ between file1 and file2: >
The ">" is replaced with the value of 'shellredir'.
The output of "diff" must be a normal "ed" style diff. Do NOT use a context
diff. This example explains the format that Vim expects: >
The output of "diff" must be a normal "ed" style diff or a unified diff. Do
NOT use a context diff. This example explains the format that Vim expects for
the "ed" style diff: >
1a2
> bbb

View File

@ -2137,8 +2137,6 @@ index({list}, {expr} [, {start} [, {ic}]])
Number index in {list} where {expr} appears
input({prompt} [, {text} [, {completion}]])
String get input from the user
inputdialog({prompt} [, {text} [, {completion}]])
String like input() but in a GUI dialog
inputlist({textlist}) Number let the user pick from a choice list
inputrestore() Number restore typeahead
inputsave() Number save and clear typeahead
@ -2925,7 +2923,7 @@ confirm({msg} [, {choices} [, {default} [, {type}]]])
made. It returns the number of the choice. For the first
choice this is 1.
{msg} is displayed in a |dialog| with {choices} as the
{msg} is displayed in a dialog with {choices} as the
alternatives. When {choices} is missing or empty, "&OK" is
used (and translated).
{msg} is a String, use '\n' to include a newline. Only on
@ -3381,9 +3379,7 @@ expand({expr} [, {nosuf} [, {list}]]) *expand()*
If {list} is given and it is |TRUE|, a List will be returned.
Otherwise the result is a String and when there are several
matches, they are separated by <NL> characters. [Note: in
version 5.0 a space was used, which caused problems when a
file name contains a space]
matches, they are separated by <NL> characters.
If the expansion fails, the result is an empty string. A name
for a non-existing file is not included, unless {expr} does
@ -3444,7 +3440,7 @@ expand({expr} [, {nosuf} [, {list}]]) *expand()*
all "README" files in the current directory and below: >
:echo expand("**/README")
<
Expand() can also be used to expand variables and environment
expand() can also be used to expand variables and environment
variables that are only known in a shell. But this can be
slow, because a shell may be used to do the expansion. See
|expr-env-expand|.
@ -4915,20 +4911,6 @@ input({opts})
: call inputrestore()
:endfunction
inputdialog({prompt} [, {text} [, {cancelreturn}]]) *inputdialog()*
inputdialog({opts})
Like |input()|, but when the GUI is running and text dialogs
are supported, a dialog window pops up to input the text.
Example: >
:let n = inputdialog("value for shiftwidth", shiftwidth())
:if n != ""
: let &sw = n
:endif
< When the dialog is cancelled {cancelreturn} is returned. When
omitted an empty string is returned.
Hitting <Enter> works like pressing the OK button. Hitting
<Esc> works like pressing the Cancel button.
inputlist({textlist}) *inputlist()*
{textlist} must be a |List| of strings. This |List| is
displayed, one string per line. The user will be prompted to
@ -8560,7 +8542,7 @@ tag_old_static Compiled with support for old static tags
|tag-old-static|.
tag_any_white Compiled with support for any white characters in tags
files |tag-any-white|.
termresponse Compiled with support for |t_RV| and |v:termresponse|.
termresponse Compiled with support for t_RV and |v:termresponse|.
textobjects Compiled with support for |text-objects|.
timers Compiled with |timer_start()| support.
title Compiled with window title support |'title'|.

View File

@ -150,6 +150,7 @@ GUI ~
Interfaces ~
|if_cscop.txt| using Cscope with Vim
|if_lua.txt| Lua interface
|if_pyth.txt| Python interface
|if_ruby.txt| Ruby interface
|sign.txt| debugging signs
@ -160,6 +161,9 @@ Versions ~
*standard-plugin-list*
Standard plugins ~
|pi_gzip.txt| Reading and writing compressed files
|pi_health.txt| Healthcheck framework
|pi_matchit.txt| Extended "%" matching
|pi_msgpack.txt| msgpack utilities
|pi_netrw.txt| Reading and writing files over a network
|pi_paren.txt| Highlight matching parens
|pi_spec.txt| Filetype plugin to work with rpm spec files

View File

@ -229,8 +229,7 @@ shared between command calls. All Lua default libraries are available. In
addition, Lua "print" function has its output redirected to the Nvim message
area, with arguments separated by a white space instead of a tab.
Lua uses the "vim" module (see |lua-vim|) to issue commands to Nvim
and manage buffers (|lua-buffer|) and windows (|lua-window|). However,
Lua uses the "vim" module (see |lua-vim|) to issue commands to Nvim. However,
procedures that alter buffer content, open new buffers, and change cursor
position are restricted when the command is executed in the |sandbox|.
@ -261,7 +260,7 @@ vim.stricmp(a, b) *lua-vim.stricmp*
greater then b or a is lesser then b respectively.
vim.type_idx *lua-vim.type_idx*
Type index for use in |lua-special-tables|. Specifying one of the
Type index for use in |lua-special-tbl|. Specifying one of the
values from |lua-vim.types| allows typing the empty table (it is
unclear whether empty lua table represents empty list or empty array)
and forcing integral numbers to be |Float|. See |lua-special-tbl| for

View File

@ -1472,7 +1472,6 @@ tag command action ~
|:sfind| :sf[ind] split current window and edit file in 'path'
|:sfirst| :sfir[st] split window and go to first file in the
argument list
|:simalt| :sim[alt] Win32 GUI: simulate Windows ALT key
|:sign| :sig[n] manipulate signs
|:silent| :sil[ent] run a command silently
|:sleep| :sl[eep] do nothing for a few seconds

View File

@ -1,7 +1,7 @@
*intro.txt* Nvim
VIM REFERENCE MANUAL by Bram Moolenaar
NVIM REFERENCE MANUAL
Introduction to Vim *ref* *reference*
@ -9,7 +9,7 @@ Introduction to Vim *ref* *reference*
Type |gO| to see the table of contents.
==============================================================================
1. Introduction *intro*
Introduction *intro*
Vim stands for Vi IMproved. It used to be Vi IMitation, but there are so many
improvements that a name change was appropriate. Vim is a text editor which
@ -28,8 +28,8 @@ is not located in the default place. You can jump to subjects like with tags:
Use CTRL-] to jump to a subject under the cursor, use CTRL-T to jump back.
*pronounce*
Vim is pronounced as one word, like Jim, not vi-ai-em. It's written with a
capital, since it's a name, again like Jim.
Vim is pronounced as one word, like Jim. Nvim is pronounced as N-vim, or,
continuing with the Jim simile, N-Jim, which sounds like Ninja.
This manual is a reference for all the Vim commands and options. This is not
an introduction to the use of Vi or Vim, it gets a bit complicated here and
@ -37,134 +37,67 @@ there. For beginners, there is a hands-on |tutor|. To learn using Vim, read
the user manual |usr_toc.txt|.
*book*
There are many books on Vi that contain a section for beginners. There are
two books I can recommend:
There are many books on Vi and Vim. We recommend these books:
"Practical Vim" by Drew Neil
"Modern Vim" by Drew Neil
https://vimcasts.org/publications/
"Practical Vim" is a popular because of its focus on quickly learning common
editing tasks with Vim. "Modern Vim" explores new features introduced by Nvim
and Vim 8.
"Vim - Vi Improved" by Steve Oualline
This is the very first book completely dedicated to Vim. It is very good for
beginners. The most often used commands are explained with pictures and
examples. The less often used commands are also explained, the more advanced
features are summarized. There is a comprehensive index and a quick
reference. Parts of this book have been included in the user manual
|frombook|.
Published by New Riders Publishing. ISBN: 0735710015
This is the first book dedicated to Vim. Parts of it were included in the
user manual. |frombook| ISBN: 0735710015
For more information try one of these:
http://iccf-holland.org/click5.html
http://www.vim.org/iccf/click5.html
"Learning the Vi editor" by Linda Lamb and Arnold Robbins
This is a book about Vi that includes a chapter on Vim (in the sixth edition).
The first steps in Vi are explained very well. The commands that Vim adds are
only briefly mentioned. There is also a German translation.
Published by O'Reilly. ISBN: 1-56592-426-6.
https://iccf-holland.org/click5.html
https://www.vim.org/iccf/click5.html
==============================================================================
2. Vim on the internet *internet*
Nvim on the interwebs *internet*
*www* *WWW* *faq* *FAQ* *distribution* *download*
The Vim pages contain the most recent information about Vim. They also
contain links to the most recent version of Vim. The FAQ is a list of
Frequently Asked Questions. Read this if you have problems.
Vim home page: http://www.vim.org/
Vim FAQ: http://vimdoc.sf.net/
Downloading: ftp://ftp.vim.org/pub/vim/MIRRORS
Usenet News group where Vim is discussed: *news* *usenet*
comp.editors
This group is also for other editors. If you write about Vim, don't forget to
mention that.
*mail-list* *maillist*
There are several mailing lists for Vim:
<vim@vim.org> *vim-use* *vim_use*
For discussions about using existing versions of Vim: Useful mappings,
questions, answers, where to get a specific version, etc. There are
quite a few people watching this list and answering questions, also
for beginners. Don't hesitate to ask your question here.
<vim-dev@vim.org> *vim-dev* *vim_dev* *vimdev*
For discussions about changing Vim: New features, porting, patches,
beta-test versions, etc.
<vim-announce@vim.org> *vim-announce* *vim_announce*
Announcements about new versions of Vim; also for beta-test versions
and ports to different systems. This is a read-only list.
<vim-mac@vim.org> *vim-mac* *vim_mac*
For discussions about using and improving the Macintosh version of
Vim.
See http://www.vim.org/maillist.php for the latest information.
NOTE:
- You can only send messages to these lists if you have subscribed!
- You need to send the messages from the same location as where you subscribed
from (to avoid spam mail).
- Maximum message size is 40000 characters.
*subscribe-maillist*
If you want to join, send a message to
<vim-subscribe@vim.org>
Make sure that your "From:" address is correct. Then the list server will
give you help on how to subscribe.
*maillist-archive*
For more information and archives look on the Vim maillist page:
http://www.vim.org/maillist.php
Nvim home page: https://neovim.io/
Nvim FAQ: https://github.com/neovim/neovim/wiki/FAQ
Downloads: https://github.com/neovim/neovim/releases
Vim FAQ: https://vimhelp.appspot.com/vim_faq.txt.html
Vim home page: https://www.vim.org/
Bug reports: *bugs* *bug-reports* *bugreport.vim*
Report bugs on GitHub: https://github.com/neovim/neovim/issues
Please be brief; all the time that is spent on answering mail is subtracted
from the time that is spent on improving Vim! Always give a reproducible
example and try to find out which settings or other things trigger the bug.
Be brief, yet complete. Always give a reproducible example and try to find
out which settings or other things trigger the bug.
Preferably start Vim with: >
vim --clean -u reproduce.vim
Where reproduce.vim is a script that reproduces the problem. Try different
machines, if relevant (is this an MS-Windows specific bug perhaps?).
Send me patches if you can!
It will help to include information about the version of Vim you are using and
your setup. You can get the information with this command: >
:so $VIMRUNTIME/bugreport.vim
This will create a file "bugreport.txt" in the current directory, with a lot
of information of your environment. Before sending this out, check if it
doesn't contain any confidential information!
If Vim crashes, please try to find out where. You can find help on this here:
|debug.txt|.
In case of doubt or when you wonder if the problem has already been fixed but
you can't find a fix for it, become a member of the vim-dev maillist and ask
your question there. |maillist|
*year-2000* *Y2K*
Since Vim internally doesn't use dates for editing, there is no year 2000
problem to worry about. Vim does use the time in the form of seconds since
January 1st 1970. It is used for a time-stamp check of the edited file and
the swap file, which is not critical and should only cause warning messages.
There might be a year 2038 problem, when the seconds don't fit in a 32 bit int
anymore. This depends on the compiler, libraries and operating system.
Specifically, time_t and the ctime() function are used. And the time_t is
stored in four bytes in the swap file. But that's only used for printing a
file date/time for recovery, it will never affect normal editing.
The Vim strftime() function directly uses the strftime() system function.
localtime() uses the time() system function. getftime() uses the time
returned by the stat() system function. If your system libraries are year
2000 compliant, Vim is too.
The user may create scripts for Vim that use external commands. These might
introduce Y2K problems, but those are not really part of Vim itself.
If Nvim crashes, try to get a backtrace. See |debug.txt|.
==============================================================================
3. Credits *credits* *author* *Bram* *Moolenaar*
Sponsor Vim/Nvim development *sponsor* *register*
Fixing bugs and adding new features takes a lot of time and effort. To show
your appreciation for the work and motivate Bram and others to continue
working on Vim please send a donation.
Since Bram is back to a paid job the money will now be used to help children
in Uganda. See |uganda|. But at the same time donations increase Bram's
motivation to keep working on Vim!
For the most recent information about sponsoring look on the Vim web site:
https://www.vim.org/sponsor/
Neovim development is funded separately from Vim:
https://neovim.io/#sponsor
==============================================================================
Credits *credits* *author* *Bram* *Moolenaar*
Most of Vim was written by Bram Moolenaar <Bram@vim.org>.
@ -273,7 +206,7 @@ Elvis Another Vi clone, made by Steve Kirkendall. Very compact but isn't
freely available.
==============================================================================
4. Notation *notation*
Notation *notation*
When syntax highlighting is used to read this, text that is not typed
literally is often highlighted with the Special group. These are items in [],
@ -494,7 +427,7 @@ examples and use them directly. Or type them literally, including the '<' and
":autocmd"!
==============================================================================
5. Modes, introduction *vim-modes-intro* *vim-modes*
Modes, introduction *vim-modes-intro* *vim-modes*
Vim has seven BASIC modes:
@ -579,7 +512,7 @@ Insert Select mode Entered when starting Select mode from Insert mode.
is shown at the bottom of the window.
==============================================================================
6. Switching from mode to mode *mode-switching*
Switching from mode to mode *mode-switching*
If for any reason you do not know which mode you are in, you can always get
back to Normal mode by typing <Esc> twice. This doesn't work for Ex mode
@ -650,7 +583,7 @@ Q or gQ Switch to Ex mode. This is like typing ":" commands
Use the ":vi" command |:visual| to exit this mode.
==============================================================================
7. The window contents *window-contents*
The window contents *window-contents*
In Normal mode and Insert/Replace mode the screen window will show the current
contents of the buffer: What You See Is What You Get. There are two
@ -769,18 +702,15 @@ window. You may make the window as small as you like, but if it gets too
small not a single line will fit in it. Make it at least 40 characters wide
to be able to read most messages on the last line.
On most Unix systems, resizing the window is recognized and handled correctly
by Vim.
==============================================================================
8. Definitions *definitions*
Definitions *definitions* *jargon*
buffer Contains lines of text, usually read from a file.
screen The whole area that Vim uses to work in. This can be
a terminal emulator window. Also called "the Vim
window".
buffer Contains lines of text, usually from a file.
screen The whole area that Nvim uses to display things.
window A view on a buffer. There can be multiple windows for
one buffer.
frame Windows are kept in a tree of frames. Each frame
contains a column, row, or window ("leaf" frame).
A screen contains one or more windows, separated by status lines and with the
command line at the bottom.
@ -813,7 +743,7 @@ A difference is made between four types of lines:
lines with wrapping, line breaks, etc. applied. They
can only be as long as the width of the window allows,
longer lines are wrapped or truncated.
screen lines The lines of the screen that Vim uses. Consists of
screen lines The lines of the screen that Nvim uses. Consists of
the window lines of all windows, with status lines
and the command line added. They can only be as long
as the width of the screen allows. When the command
@ -837,5 +767,27 @@ buffer lines logical lines window lines screen lines ~
5. ddd 13. (command line)
6. ~
API client ~
All external UIs and remote plugins (as opposed to regular Vim plugins) are
"clients" in general; but we call something an "API client" if its purpose is
to abstract or wrap the RPC API for the convenience of other applications
(just like a REST client or SDK such as boto3 for AWS: you can speak AWS REST
using an HTTP client like curl, but boto3 wraps that in a convenient python
interface). For example, the Nvim lua-client is an API client:
https://github.com/neovim/lua-client
Host ~
A plugin "host" is both a client (of the Nvim API) and a server (of an
external platform, e.g. python). It is a remote plugin that hosts other
plugins.
Remote plugin ~
Arbitrary code registered via |:UpdateRemotePlugins|, that runs in a separate
process and communicates with Nvim via the |api|.
==============================================================================
vim:tw=78:ts=8:noet:ft=help:norl:

View File

@ -286,6 +286,9 @@ current mode (instead of always going to normal-mode). Visual-mode is
preserved, so tricks with |gv| are not needed. Commands can be invoked
directly in cmdline-mode (which otherwise would require timer hacks).
Because <Cmd> avoids mode-changes (unlike ":") it does not trigger
|CmdlineEnter| and |CmdlineLeave| events. This helps performance.
Unlike <expr> mappings, there are no special restrictions on the <Cmd>
command: it is executed as if an (unrestricted) |autocmd| was invoked or an
async event event was processed.

View File

@ -514,15 +514,6 @@ command. The script can then again read another script. This can continue
for about 14 levels. When more nesting is done, Vim assumes that there is a
recursive loop somewhere and stops with this error message.
*E319* >
The command is not available in this version
You have used a command that is not present in the version of Vim you are
using. When compiling Vim, many different features can be enabled or
disabled. This depends on how big Vim has chosen to be and the operating
system. See |+feature-list| for when which feature is available. The
|:version| command shows which feature Vim was compiled with.
*E300* >
Swap file already exists (symlink attack?)

View File

@ -703,47 +703,24 @@ A jump table for the options with a short description can be found at |Q_op|.
been set.
*'background'* *'bg'*
'background' 'bg' string (default "dark" or "light", see below)
'background' 'bg' string (default "dark")
global
When set to "dark", Vim will try to use colors that look good on a
dark background. When set to "light", Vim will try to use colors that
look good on a light background. Any other value is illegal.
Vim tries to set the default value according to the terminal used.
This will not always be correct.
Setting this option does not change the background color, it tells Vim
what the background color looks like. For changing the background
color, see |:hi-normal|.
When set to "dark" or "light", Nvim will adjust the default color
groups for a dark or light background, respectively.
When 'background' is set Vim will adjust the default color groups for
the new value. But the colors used for syntax highlighting will not
change. *g:colors_name*
This option does NOT change the background color, it tells Nvim what
the "inherited" (terminal/GUI) background looks like.
See |:hi-normal| if you want to set the background color explicitly.
*g:colors_name*
When a color scheme is loaded (the "g:colors_name" variable is set)
setting 'background' will cause the color scheme to be reloaded. If
the color scheme adjusts to the value of 'background' this will work.
However, if the color scheme sets 'background' itself the effect may
be undone. First delete the "g:colors_name" variable when needed.
When setting 'background' to the default value with: >
:set background&
< Vim will guess the value. In the GUI this should work correctly,
in other cases Vim might not be able to guess the right value.
When starting the GUI, the default value for 'background' will be
"light". When the value is not set in the gvimrc, and Vim detects
that the background is actually quite dark, 'background' is set to
"dark". But this happens only AFTER the gvimrc file has been read
(because the window needs to be opened to find the actual background
color). To get around this, force the GUI window to be opened by
putting a ":gui" command in the gvimrc file, before where the value
of 'background' is used (e.g., before ":syntax on").
For Windows the default is "dark". "dark" should be used if $COLORFGBG
suggests a dark background (not yet implemented). Otherwise the default
is "light".
Normally this option would be set in the vimrc file. Possibly
depending on the terminal name. Example: >
:if $TERM == "xterm"
:if $TERM ==# "xterm"
: set background=dark
:endif
< When this option is set, the default settings for the highlight groups
@ -1485,7 +1462,7 @@ A jump table for the options with a short description can be found at |Q_op|.
global
When 'confirm' is on, certain operations that would normally
fail because of unsaved changes to a buffer, e.g. ":q" and ":e",
instead raise a |dialog| asking if you wish to save the current
instead raise a dialog asking if you wish to save the current
file(s). You can still use a ! to unconditionally |abandon| a buffer.
If 'confirm' is off you can still activate confirmation for one
command only (this is most useful in mappings) with the |:confirm|
@ -1882,13 +1859,13 @@ A jump table for the options with a short description can be found at |Q_op|.
*'dex'* *'diffexpr'*
'diffexpr' 'dex' string (default "")
global
Expression which is evaluated to obtain an ed-style diff file from two
versions of a file. See |diff-diffexpr|.
Expression which is evaluated to obtain a diff file (either ed-style
or unified-style) from two versions of a file. See |diff-diffexpr|.
This option cannot be set from a |modeline| or in the |sandbox|, for
security reasons.
*'dip'* *'diffopt'*
'diffopt' 'dip' string (default "filler")
'diffopt' 'dip' string (default "internal,filler")
global
Option settings for diff mode. It can consist of the following items.
All are optional. Items must be separated by a comma.
@ -1948,11 +1925,31 @@ A jump table for the options with a short description can be found at |Q_op|.
foldcolumn:{n} Set the 'foldcolumn' option to {n} when
starting diff mode. Without this 2 is used.
Examples: >
internal Use the internal diff library. This is
ignored when 'diffexpr' is set. *E960*
When running out of memory when writing a
buffer this item will be ignored for diffs
involving that buffer. Set the 'verbose'
option to see when this happens.
:set diffopt=filler,context:4
indent-heuristic
Use the indent heuristic for the internal
diff library.
algorithm:{text} Use the specified diff algorithm with the
internal diff engine. Currently supported
algorithms are:
myers the default algorithm
minimal spend extra time to generate the
smallest possible diff
patience patience diff algorithm
histogram histogram diff algorithm
Examples: >
:set diffopt=internal,filler,context:4
:set diffopt=
:set diffopt=filler,foldcolumn:3
:set diffopt=internal,filler,foldcolumn:3
:set diffopt-=internal " do NOT use the internal diff parser
<
*'digraph'* *'dg'* *'nodigraph'* *'nodg'*
'digraph' 'dg' boolean (default off)
@ -2803,8 +2800,7 @@ A jump table for the options with a short description can be found at |Q_op|.
:set guifont=*
< will bring up a font requester, where you can pick the font you want.
The font name depends on the GUI used. See |setting-guifont| for a
way to set 'guifont' for various systems.
The font name depends on the GUI used.
For Mac OSX you can use something like this: >
:set guifont=Monaco:h10
@ -6586,8 +6582,7 @@ A jump table for the options with a short description can be found at |Q_op|.
menu. This conflicts with the use of the ALT key for mappings and
entering special characters. This option tells what to do:
no Don't use ALT keys for menus. ALT key combinations can be
mapped, but there is no automatic handling. This can then be
done with the |:simalt| command.
mapped, but there is no automatic handling.
yes ALT key handling is done by the windowing system. ALT key
combinations cannot be mapped.
menu Using ALT in combination with a character that is a menu

View File

@ -1,4 +1,4 @@
*pi_msgpack.txt* Nvim
*pi_msgpack.txt* msgpack utilities
Author: Nikolay Pavlov <kp-pav@yandex.ru>
Copyright: (c) 2015 by Nikolay Pavlov

View File

@ -4,14 +4,21 @@
NVIM REFERENCE MANUAL by Thiago de Arruda
Providers *provider*
Providers *provider*
Nvim delegates some features to dynamic "providers".
Nvim delegates some features to dynamic "providers". This document describes
the providers and how to install them.
*E319*
Use of a feature requiring a missing provider is an error: >
E319: No "foo" provider found. Run ":checkhealth provider"
Run the |:checkhealth| command, and review the sections below.
Type |gO| to see the table of contents.
==============================================================================
Python integration *provider-python*
Python integration *provider-python*
Nvim supports Python |remote-plugin|s and the Vim legacy |python2| and
|python3| interfaces (which are implemented as remote-plugins).
@ -19,23 +26,23 @@ Note: Only the Vim 7.3 API is supported; bindeval (Vim 7.4) is not.
PYTHON QUICKSTART ~
Install the "neovim" Python package:
Install the "pynvim" Python package:
- Run |:checkhealth| to see if you already have the package (some package
managers install the "neovim" Python package with Nvim itself).
managers install the "pynvim" Python package with Nvim itself).
- For Python 2 plugins, make sure Python 2.7 is available in your $PATH, then
install the package systemwide: >
sudo pip2 install --upgrade neovim
sudo pip2 install --upgrade pynvim
< or for the current user: >
pip2 install --user --upgrade neovim
pip2 install --user --upgrade pynvim
< If "pip2" is missing, try "pip".
- For Python 3 plugins, make sure Python 3.4+ is available in your $PATH, then
install the package systemwide: >
sudo pip3 install --upgrade neovim
sudo pip3 install --upgrade pynvim
< or for the current user: >
pip3 install --user --upgrade neovim
pip3 install --user --upgrade pynvim
< If "pip3" is missing, try "pip".
- The `--upgrade` flag ensures you have the latest version even if a previous
@ -64,14 +71,14 @@ PYTHON VIRTUALENVS ~
If you plan to use per-project virtualenvs often, you should assign one
virtualenv for Neovim and hard-code the interpreter path via
|g:python3_host_prog| (or |g:python_host_prog|) so that the "neovim" package
|g:python3_host_prog| (or |g:python_host_prog|) so that the "pynvim" package
is not required for each virtualenv.
Example using pyenv: >
pyenv install 3.4.4
pyenv virtualenv 3.4.4 py3nvim
pyenv activate py3nvim
pip install neovim
pip install pynvim
pyenv which python # Note the path
The last command reports the interpreter path, add it to your init.vim: >
let g:python3_host_prog = '/path/to/py3nvim/bin/python'
@ -150,16 +157,19 @@ The presence of a working clipboard tool implicitly enables the '+' and '*'
registers. Nvim looks for these clipboard tools, in order of priority:
- |g:clipboard|
- pbcopy/pbpaste (macOS)
- xsel (if $DISPLAY is set)
- pbcopy, pbpaste (macOS)
- wl-copy, wl-paste (if $WAYLAND_DISPLAY is set)
- xclip (if $DISPLAY is set)
- xsel (if $DISPLAY is set)
- lemonade (for SSH) https://github.com/pocke/lemonade
- doitclient (for SSH) http://www.chiark.greenend.org.uk/~sgtatham/doit/
- win32yank (Windows)
- tmux (if $TMUX is set)
*g:clipboard*
To configure a custom clipboard tool, set `g:clipboard` to a dictionary: >
To configure a custom clipboard tool, set g:clipboard to a dictionary.
For example this configuration integrates the tmux clipboard: >
let g:clipboard = {
\ 'name': 'myClipboard',
\ 'copy': {
@ -173,9 +183,28 @@ To configure a custom clipboard tool, set `g:clipboard` to a dictionary: >
\ 'cache_enabled': 1,
\ }
If `cache_enabled` is |TRUE| then when a selection is copied, Nvim will cache
If "cache_enabled" is |TRUE| then when a selection is copied Nvim will cache
the selection until the copy command process dies. When pasting, if the copy
process has not died, the cached selection is applied.
process has not died the cached selection is applied.
g:clipboard can also use functions (see |lambda|) instead of strings.
For example this configuration uses the g:foo variable as a fake clipboard: >
let g:clipboard = {
\ 'name': 'myClipboard',
\ 'copy': {
\ '+': {lines, regtype -> extend(g:, {'foo': [lines, regtype]}) },
\ '*': {lines, regtype -> extend(g:, {'foo': [lines, regtype]}) },
\ },
\ 'paste': {
\ '+': {-> get(g:, 'foo', [])},
\ '*': {-> get(g:, 'foo', [])},
\ },
\ }
The "copy" function stores a list of lines and the register type. The "paste"
function returns the clipboard as a `[lines, regtype]` list, where `lines` is
a list of lines and `regtype` is a register type conforming to |setreg()|.
==============================================================================
X11 selection mechanism *clipboard-x11* *x11-selection*

View File

@ -167,11 +167,6 @@ a client and send strings to other instances of Vim on the same X11 display.
When an X11 GUI Vim (gvim) is started, it will try to register a send-server
name on the 'VimRegistry' property on the root window.
A non GUI Vim with access to the X11 display (|xterm-clipboard| enabled), can
also act as a command server if a server name is explicitly given with the
--servername argument, or when Vim was build with the |+autoservername|
feature.
An empty --servername argument will cause the command server to be disabled.
To send commands to a Vim server from another application, read the source

View File

@ -42,15 +42,15 @@ what a Python plugin looks like. This plugin exports a command, a function, and
an autocmd. The plugin is called 'Limit', and all it does is limit the number
of requests made to it. Here's the plugin source code:
>
import neovim
import pynvim
@neovim.plugin
@pynvim.plugin
class Limit(object):
def __init__(self, vim):
self.vim = vim
self.calls = 0
@neovim.command('Cmd', range='', nargs='*', sync=True)
@pynvim.command('Cmd', range='', nargs='*', sync=True)
def command_handler(self, args, range):
self._increment_calls()
self.vim.current.line = (
@ -58,14 +58,14 @@ of requests made to it. Here's the plugin source code:
args,
range))
@neovim.autocmd('BufEnter', pattern='*.py', eval='expand("<afile>")',
@pynvim.autocmd('BufEnter', pattern='*.py', eval='expand("<afile>")',
sync=True)
def autocmd_handler(self, filename):
self._increment_calls()
self.vim.current.line = (
'Autocmd: Called %s times, file: %s' % (self.calls, filename))
@neovim.function('Func')
@pynvim.function('Func')
def function_handler(self, args):
self._increment_calls()
self.vim.current.line = (

View File

@ -305,6 +305,9 @@ For writing a Vim script, see chapter 41 of the user manual |usr_41.txt|.
first sourced. The number is used for the script ID
|<SID>|.
:scr[iptnames][!] {scriptId} *:script*
Edit script {scriptId}. Suggested name is ":script".
*:fini* *:finish* *E168*
:fini[sh] Stop sourcing a script. Can only be used in a Vim
script file. This is a quick way to skip the rest of

View File

@ -79,7 +79,6 @@ DEFINING A SIGN. *:sign-define* *E255* *E160* *E612*
will cause redraw problems.
toolkit supports ~
Win32 .bmp, .ico, .cur
pixmap (.xpm) |+xpm_w32|
linehl={group}
Highlighting group used for the whole line the sign is placed

View File

@ -1,216 +0,0 @@
*sponsor.txt* Nvim
VIM REFERENCE MANUAL by Bram Moolenaar
SPONSOR VIM DEVELOPMENT *sponsor*
Fixing bugs and adding new features takes a lot of time and effort. To show
your appreciation for the work and motivate Bram and others to continue
working on Vim please send a donation.
Since Bram is back to a paid job the money will now be used to help children
in Uganda. See |uganda|. But at the same time donations increase Bram's
motivation to keep working on Vim!
For the most recent information about sponsoring look on the Vim web site:
http://www.vim.org/sponsor/
More explanations can be found in the |sponsor-faq|.
REGISTERED VIM USER *register*
You can become a registered Vim user by sending at least 10 euro. This works
similar to sponsoring Vim, see |sponsor| above. Registration was made
possible for the situation where your boss or bookkeeper may be willing to
register software, but does not like the terms "sponsoring" and "donation".
More explanations can be found in the |register-faq|.
VOTE FOR FEATURES *vote-for-features*
To give registered Vim users and sponsors an advantage over lurkers they can
vote for the items Bram should work on. How does this voting work?
1. You send at least 10 euro. See below for ways to transfer money
|send-money|.
2. You will be e-mailed a registration key. Enter this key on your account
page on the Vim website. You can easily create an account if you don't
have one yet.
3. You can enter your votes on the voting page. There is a link to that page
on your account page after entering a registration key. Your votes will
be counted for two years.
4. The voting results appear on the results page, which is visible for
everybody: http://www.vim.org/sponsor/vote_results.php
Additionally, once you have sent 100 euro or more in total, your name appears
in the "Vim hall of honour": http://www.vim.org/sponsor/hall_of_honour.php
But only if you enable this on your account page.
HOW TO SEND MONEY *send-money*
Credit card Through PayPal, see the PayPal site for information:
https://www.paypal.com/en_US/mrb/pal=XAC62PML3GF8Q
The e-mail address for sending sponsorship money is:
donate@vim.org
The e-mail address for Vim registration is:
register@vim.org
Using Euro is preferred, other currencies are also accepted.
In Euro countries a bank transfer is preferred, this has lower
costs.
Other methods See |iccf-donations|.
Include "Vim sponsor" or "Vim registration" in the comment of
your money transfer. Send me an e-mail that mentions the
amount you transferred if you want to vote for features and
show others you are a registered Vim user or sponsor.
Cash Small amounts can be sent with ordinary mail. Put something
around the money, so that it's not noticeable from the
outside. Mention your e-mail address if you want to vote for
features and show others you are a registered Vim user or
sponsor.
You can use this permanent address:
Bram Moolenaar
Finsterruetihof 1
8134 Adliswil
Switzerland
QUESTIONS AND ANSWERS *sponsor-faq* *register-faq*
Why should I give money?
If you do not show your appreciation for Vim then Bram will be less motivated
to fix bugs and add new features. He will do something else instead.
How much money should I send?
That is up to you. The more you give, the more children will be helped.
An indication for individuals that use Vim at home: 10 Euro per year. For
professional use: 30 Euro per year per person. Send at least 10 euro to be
able to vote for features.
What do I get in return?
Each registered Vim user and sponsor who donates at least 10 euro will be able
to vote for new features. These votes will give priority to the work on Vim.
The votes are valid for two years. The more money you send the more your
votes count |votes-counted|.
If you send 100 Euro or more in total you will be mentioned on the "Vim hall
of honour" page on the Vim web site. But only if you enable this on your
account page. You can also select whether the amount will be visible.
How do I become a Vim sponsor or registered Vim user?
Send money, as explained above |send-money| and include your e-mail address.
When the money has been received you will receive a unique registration key.
This key can be used on the Vim website to activate voting on your Vim
account. You will then get an extra page where you can vote for features and
choose whether others will be able to see that you donated. There is a link
to this page on your "My Account" page.
What is the difference between sponsoring and registering?
It has a different name. Use the term "registration" if your boss doesn't
like "sponsoring" or "donation". The benefits are the same.
How can I send money?
See |send-money|. Check the web site for the most recent information:
http://www.vim.org/sponsor/
Why don't you use the SourceForge donation system?
SourceForge takes 5% of the donations for themselves. If you want to support
SourceForge you can send money to them directly.
I cannot afford to send money, may I still use Vim?
Yes.
I did not register Vim, can I use all available features?
Yes.
I noticed a bug, do I need to register before I can report it?
No, suggestions for improving Vim can always be given. For improvements use
the developer |maillist|, for reporting bugs see |bugs|.
How are my votes counted? *votes-counted*
You may vote when you send 10 euro or more. You can enter up to ten votes.
You can select the same item several times to give it more points. You can
also enter three counter votes, these count as negative points.
When you send 30 euro or more the points are doubled. Above 100 euro they
count four times, above 300 euro they count six times, above 1000 euro ten
times.
Can I change my votes?
You can change your votes any time you like, up to two years after you
sent money. The points will be counted right away.
Can I add an item to vote on?
Not directly. You can suggest items to vote on to Bram. He will consider
fitting your item into the list.
How about Charityware?
Currently the Vim donations go to |uganda| anyway. Thus it doesn't matter if
you sponsor Vim or ICCF. Except that Vim sponsoring will allow you to vote
for features.
I donated $$$, now please add feature XYZ!
There is no direct relation between your donation and the work Bram does.
Otherwise you would be paying for work and we would have to pay tax over the
donation. If you want to hire Bram for specific work, contact him directly,
don't use the donation system.
Are the donations tax deductible?
That depends on your country. The donations to help the children in |Uganda|
are tax deductible in Holland, Germany, Canada and in the USA. See the ICCF
website http://iccf-holland.org/donate.html. You must send an e-mail to Bram
to let him know that the donation is done because of the use of Vim.
Can you send me a bill?
No, because there is no relation between the money you send and the work that
is done. But a receipt is possible.
vim:tw=78:ts=8:noet:ft=help:norl:

View File

@ -410,20 +410,17 @@ accordingly. Vim proceeds in this order:
3. Execute Ex commands, from environment variables and/or files
An environment variable is read as one Ex command line, where multiple
commands must be separated with '|' or "<NL>".
*init.vim* *vimrc* *exrc*
A file that contains initialization commands is called a "vimrc" file.
Each line in a vimrc file is executed as an Ex command line. It is
sometimes also referred to as "exrc" file. They are the same type of
file, but "exrc" is what Vi always used, "vimrc" is a Vim specific
name, "init.vim" is Neovim specific location for vimrc file. Also see
|vimrc-intro|.
commands must be separated with '|' or <NL>.
*config* *init.vim* *vimrc* *exrc*
A file that contains initialization commands is generically called
a "vimrc" or config file. Each line in a vimrc file is executed as an
Ex command line. See also |vimrc-intro| and |base-directories|.
Places for your personal initializations (see |base-directories|):
Unix $XDG_CONFIG_HOME/nvim/init.vim
(default for $XDG_CONFIG_HOME is ~/.config)
Windows $XDG_CONFIG_HOME/nvim/init.vim
(default for $XDG_CONFIG_HOME is ~/AppData/Local)
The Nvim config file is named "init.vim", located at:
Unix ~/.config/nvim/init.vim
Windows ~/AppData/Local/nvim/init.vim
Or if |$XDG_CONFIG_HOME| is defined:
$XDG_CONFIG_HOME/nvim/init.vim
RECOMMENDATION: Put all your Vim configuration stuff in the
$HOME/.config/nvim/ directory. That makes it easy to copy it to
@ -439,10 +436,11 @@ accordingly. Vim proceeds in this order:
If Vim was started in Ex mode with the "-s" argument, all following
initializations until 4. are skipped. Only the "-u" option is
interpreted.
*system-vimrc*
a. For Unix, MS-Windows, and Macintosh, the system vimrc file is read for
initializations. The path of this file is shown with the
":version" command. Mostly it's "$VIM/vimrc".
*system-vimrc* *sysinit.vim*
a. The system vimrc file is read for initializations. If
nvim/sysinit.vim file exists in one of $XDG_CONFIG_DIRS, it will be
used. Otherwise, the system vimrc file is used. The path of this file
is shown with the ":version" command. Mostly it's "$VIM/sysinit.vim".
*VIMINIT* *EXINIT* *$MYVIMRC*
b. Four places are searched for initializations. The first that exists

View File

@ -167,7 +167,7 @@ the editor.
mouse support is active. Some options like 'ambiwidth' have already
taken effect on the grid, where appropriate empty cells are added,
however a UI might still use such options when rendering raw text
sent from Nvim, like for |ui-ext-cmdline|.
sent from Nvim, like for |ui-cmdline|.
["mode_change", mode, mode_idx]
The mode changed. The first parameter `mode` is a string representing
@ -325,14 +325,14 @@ numerical highlight `id`:s to the actual attributes.
+-------------------------+ src_top |
| src (moved up) and dst | |
|-------------------------| dst_bot |
| src (cleared) | |
| src (invalid) | |
+=========================+ src_bot
<
If `rows` is less than zero, move a rectangle in the SR down, this can
happen while scrolling up.
>
+=========================+ src_top
| src (cleared) | |
| src (invalid) | |
|------------------------ | dst_top |
| src (moved down) and dst| |
+-------------------------+ src_bot |
@ -348,6 +348,10 @@ numerical highlight `id`:s to the actual attributes.
end-exclusive, which is consistent with API conventions, but different
from `set_scroll_region` which was end-inclusive.
The scrolled-in area will be filled using |ui-event-grid_line| directly
after the scroll event. The UI thus doesn't need to clear this area as
part of handling the scroll event.
==============================================================================
Legacy Grid Events (cell based) *ui-grid-old*

View File

@ -68,9 +68,9 @@ For more info see |vimrc|.
==============================================================================
*01.3* Using the Vim tutor *tutor* *vimtutor*
Instead of reading the text (boring!) you can use the vimtutor to learn your
first Vim commands. This is a 30 minute tutorial that teaches the most basic
Vim functionality hands-on.
Instead of reading the text (boring!) you can use :Tutor to learn your first
Vim commands. This is a 30 minute tutorial that teaches the most basic Vim
functionality hands-on.
To start the tutorial, execute >

View File

@ -321,7 +321,7 @@ Where can you find plugins?
- Some come with Vim. You can find them in the directory $VIMRUNTIME/macros
and its sub-directories and under $VIM/vimfiles/pack/dist/opt/.
- Download from the net. There is a large collection on http://www.vim.org.
- They are sometimes posted in a Vim |maillist|.
- They are sometimes posted in a Vim maillist.
- You could write one yourself, see |write-plugin|.

View File

@ -203,8 +203,7 @@ USING UNICODE IN A UNICODE TERMINAL
There are terminals that support Unicode directly. The standard xterm that
comes with XFree86 is one of them. Let's use that as an example.
First of all, the xterm must have been compiled with Unicode support. See
|UTF8-xterm| how to check that and how to compile it when needed.
First of all, the xterm must have been compiled with Unicode support.
Start the xterm with the "-u8" argument. You might also need so specify a
font. Example: >

View File

@ -381,7 +381,7 @@ T *+tag_binary* binary searching in tags file |tag-binary-search|
N *+tag_old_static* old method for static tags |tag-old-static|
m *+tag_any_white* any white space allowed in tags file |tag-any-white|
B *+termguicolors* 24-bit color in xterm-compatible terminals support
N *+termresponse* support for |t_RV| and |v:termresponse|
N *+termresponse* support for t_RV and |v:termresponse|
N *+textobjects* |text-objects| selection
N *+timers* the |timer_start()| function
N *+title* Setting the window 'title' and 'icon'
@ -517,14 +517,9 @@ m *+xim* X input method |xim|
:silent! /^begin
:if v:errmsg != ""
: ... pattern was not found
< ":silent" will also avoid the hit-enter prompt. When
using this for an external command, this may cause the
screen to be messed up. Use |CTRL-L| to clean it up
then.
":silent menu ..." defines a menu that will not echo a
Command-line command. The command will still produce
messages though. Use ":silent" in the command itself
to avoid that: ":silent menu .... :silent command".
< ":silent" also skips the hit-enter prompt.
Dialogs that prompt for user input (|confirm()|,
'swapfile', …) are never silent.
*:uns* *:unsilent*
:uns[ilent] {command} Execute {command} not silently. Only makes a

View File

@ -27,6 +27,7 @@ a complete and centralized reference of those differences.
- 'autoindent' is set by default
- 'autoread' is set by default
- 'background' always defaults to "dark"
- 'backspace' defaults to "indent,eol,start"
- 'backupdir' defaults to .,~/.local/share/nvim/backup (|xdg|)
- 'belloff' defaults to "all"

View File

@ -1,3 +1,5 @@
require('vim.compat')
local buf_hls = {}
local function highlight_line(line, linenr)
@ -10,9 +12,9 @@ local function highlight_line(line, linenr)
local attr = NONE
local byte = 0 -- byte offset
local function end_attr_hl(attr)
local function end_attr_hl(attr_)
for i, hl in ipairs(hls) do
if hl.attr == attr and hl.final == -1 then
if hl.attr == attr_ and hl.final == -1 then
hl.final = byte
hls[i] = hl
end
@ -106,7 +108,7 @@ local function highlight_line(line, linenr)
-- 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 = ''
local match
while sgr and #sgr > 0 do
-- Match against SGR parameters, which may be separated by ';'
match, sgr = sgr:match("^(%d*);?(.*)")

View File

@ -0,0 +1,12 @@
-- Lua 5.1 forward-compatibility layer.
-- For background see https://github.com/neovim/neovim/pull/9280
--
-- Reference the lua-compat-5.2 project for hints:
-- https://github.com/keplerproject/lua-compat-5.2/blob/c164c8f339b95451b572d6b4b4d11e944dc7169d/compat52/mstrict.lua
-- https://github.com/keplerproject/lua-compat-5.2/blob/c164c8f339b95451b572d6b4b4d11e944dc7169d/tests/test.lua
local lua_version = _VERSION:sub(-3)
if lua_version >= "5.2" then
unpack = table.unpack -- luacheck: ignore 121 143
end

View File

@ -0,0 +1,43 @@
" cfilter.vim: Plugin to filter entries from a quickfix/location list
" Last Change: May 12, 2018
" Maintainer: Yegappan Lakshmanan (yegappan AT yahoo DOT com)
" Version: 1.0
"
" Commands to filter the quickfix list:
" :Cfilter[!] {pat}
" Create a new quickfix list from entries matching {pat} in the current
" quickfix list. Both the file name and the text of the entries are
" matched against {pat}. If ! is supplied, then entries not matching
" {pat} are used.
" :Lfilter[!] {pat}
" Same as :Cfilter but operates on the current location list.
"
if exists("loaded_cfilter")
finish
endif
let loaded_cfilter = 1
func s:Qf_filter(qf, pat, bang)
if a:qf
let Xgetlist = function('getqflist')
let Xsetlist = function('setqflist')
let cmd = ':Cfilter' . a:bang
else
let Xgetlist = function('getloclist', [0])
let Xsetlist = function('setloclist', [0])
let cmd = ':Lfilter' . a:bang
endif
if a:bang == '!'
let cond = 'v:val.text !~# a:pat && bufname(v:val.bufnr) !~# a:pat'
else
let cond = 'v:val.text =~# a:pat || bufname(v:val.bufnr) =~# a:pat'
endif
let items = filter(Xgetlist(), cond)
let title = cmd . ' ' . a:pat
call Xsetlist([], ' ', {'title' : title, 'items' : items})
endfunc
com! -nargs=+ -bang Cfilter call s:Qf_filter(1, <q-args>, <q-bang>)
com! -nargs=+ -bang Lfilter call s:Qf_filter(0, <q-args>, <q-bang>)

View File

@ -1,19 +0,0 @@
The plugin directory is for standard Vim plugin scripts.
All files here ending in .vim will be sourced by Vim when it starts up.
Look in the file for hints on how it can be disabled without deleting it.
getscriptPlugin.vim get latest version of Vim scripts
gzip.vim edit compressed files
matchparen.vim highlight paren matching the one under the cursor
netrwPlugin.vim edit files over a network and browse (remote) directories
rrhelper.vim used for --remote-wait editing
spellfile.vim download a spellfile when it's missing
tarPlugin.vim edit (compressed) tar files
tohtml.vim convert a file with syntax highlighting to HTML
vimballPlugin.vim create and unpack .vba files
zipPlugin.vim edit zip archives
Note: the explorer.vim plugin is no longer here, the netrw.vim plugin has
taken over browsing directories (also for remote directories).

View File

@ -1,5 +1,5 @@
" matchit.vim: (global plugin) Extended "%" matching
" Last Change: 2017 Sep 15
" Last Change: 2018 Jul 3 by Christian Brabandt
" Maintainer: Benji Fisher PhD <benji@member.AMS.org>
" Version: 1.13.3, for Vim 6.3+
" Fix from Tommy Allen included.
@ -268,7 +268,7 @@ function! s:Match_wrapper(word, forward, mode) range
" execute "normal!" . curcol . "l"
" endif
if skip =~ 'synID' && !(has("syntax") && exists("g:syntax_on"))
let skip = "0"
let skip = '0'
else
execute "if " . skip . "| let skip = '0' | endif"
endif
@ -708,10 +708,16 @@ fun! s:MultiMatch(spflag, mode)
let openpat = substitute(openpat, ',', '\\|', 'g')
let closepat = substitute(close, '\(\\\@<!\(\\\\\)*\)\@<=\\(', '\\%(', 'g')
let closepat = substitute(closepat, ',', '\\|', 'g')
if skip =~ 'synID' && !(has("syntax") && exists("g:syntax_on"))
let skip = '0'
else
execute "if " . skip . "| let skip = '0' | endif"
try
execute "if " . skip . "| let skip = '0' | endif"
catch /^Vim\%((\a\+)\)\=:E363/
" We won't find anything, so skip searching, should keep Vim responsive.
return {}
endtry
endif
mark '
let level = v:count1

View File

@ -1,6 +1,6 @@
" Vim plugin for showing matching parens
" Maintainer: Bram Moolenaar <Bram@vim.org>
" Last Change: 2018 Jun 23
" Last Change: 2018 Jul 3
" Exit quickly when:
" - this plugin was already loaded (or disabled)
@ -103,18 +103,28 @@ function! s:Highlight_Matching_Pair()
call cursor(c_lnum, c_col - before)
endif
" Build an expression that detects whether the current cursor position is in
" certain syntax types (string, comment, etc.), for use as searchpairpos()'s
" skip argument.
" We match "escape" for special items, such as lispEscapeSpecial.
let s_skip = '!empty(filter(map(synstack(line("."), col(".")), ''synIDattr(v:val, "name")''), ' .
if !has("syntax") || !exists("g:syntax_on")
let s_skip = "0"
else
" Build an expression that detects whether the current cursor position is
" in certain syntax types (string, comment, etc.), for use as
" searchpairpos()'s skip argument.
" We match "escape" for special items, such as lispEscapeSpecial.
let s_skip = '!empty(filter(map(synstack(line("."), col(".")), ''synIDattr(v:val, "name")''), ' .
\ '''v:val =~? "string\\|character\\|singlequote\\|escape\\|comment"''))'
" If executing the expression determines that the cursor is currently in
" one of the syntax types, then we want searchpairpos() to find the pair
" within those syntax types (i.e., not skip). Otherwise, the cursor is
" outside of the syntax types and s_skip should keep its value so we skip any
" matching pair inside the syntax types.
execute 'if' s_skip '| let s_skip = 0 | endif'
" If executing the expression determines that the cursor is currently in
" one of the syntax types, then we want searchpairpos() to find the pair
" within those syntax types (i.e., not skip). Otherwise, the cursor is
" outside of the syntax types and s_skip should keep its value so we skip
" any matching pair inside the syntax types.
" Catch if this throws E363: pattern uses more memory than 'maxmempattern'.
try
execute 'if ' . s_skip . ' | let s_skip = "0" | endif'
catch /^Vim\%((\a\+)\)\=:E363/
" We won't find anything, so skip searching, should keep Vim responsive.
return
endtry
endif
" Limit the search to lines visible in the window.
let stoplinebottom = line('w$')

View File

@ -1,48 +0,0 @@
" Vim plugin with helper function(s) for --remote-wait
" Maintainer: Flemming Madsen <fma@cci.dk>
" Last Change: 2008 May 29
" Has this already been loaded?
if exists("loaded_rrhelper") || !has("clientserver")
finish
endif
let loaded_rrhelper = 1
" Setup answers for a --remote-wait client who will assume
" a SetupRemoteReplies() function in the command server
function SetupRemoteReplies()
let cnt = 0
let max = argc()
let id = expand("<client>")
if id == 0
return
endif
while cnt < max
" Handle same file from more clients and file being more than once
" on the command line by encoding this stuff in the group name
let uniqueGroup = "RemoteReply_".id."_".cnt
" Path separators are always forward slashes for the autocommand pattern.
" Escape special characters with a backslash.
let f = substitute(argv(cnt), '\\', '/', "g")
if exists('*fnameescape')
let f = fnameescape(f)
else
let f = escape(f, " \t\n*?[{`$\\%#'\"|!<")
endif
execute "augroup ".uniqueGroup
execute "autocmd ".uniqueGroup." BufUnload ". f ." call DoRemoteReply('".id."', '".cnt."', '".uniqueGroup."', '". f ."')"
let cnt = cnt + 1
endwhile
augroup END
endfunc
function DoRemoteReply(id, cnt, group, file)
call server2client(a:id, a:cnt)
execute 'autocmd! '.a:group.' BufUnload '.a:file
execute 'augroup! '.a:group
endfunc
" vim: set sw=2 sts=2 :

68
scripts/check_urls.vim Normal file
View File

@ -0,0 +1,68 @@
" Test for URLs in help documents.
"
" Opens a new window with all found URLS followed by return code from curl
" (anything other than 0 means unreachable)
"
" Written by Christian Brabandt.
func Test_check_URLs()
if has("win32")
echoerr "Doesn't work on MS-Windows"
return
endif
if executable('curl')
" Note: does not follow redirects!
let s:command = 'curl --silent --fail --output /dev/null --head '
elseif executable('wget')
" Note: only allow a couple of redirects
let s:command = 'wget --quiet -S --spider --max-redirect=2 --timeout=5 --tries=2 -O /dev/null '
else
echoerr 'Only works when "curl" or "wget" is available'
return
endif
let pat='\(https\?\|ftp\)://[^\t* ]\+'
exe 'helpgrep' pat
helpclose
let urls = map(getqflist(), 'v:val.text')
" do not use submatch(1)!
let urls = map(urls, {key, val -> matchstr(val, pat)})
" remove examples like user@host (invalid urls)
let urls = filter(urls, 'v:val !~ "@"')
" Remove example URLs which are invalid
let urls = filter(urls, {key, val -> val !~ '\<\(\(my\|some\)\?host\|machine\|hostname\|file\)\>'})
new
put =urls
" remove some more invalid items
" empty lines
v/./d
" remove # anchors
%s/#.*$//e
" remove trailing stuff (parenthesis, dot, comma, quotes), but only for HTTP
" links
g/^h/s#[.,)'"/>][:.]\?$##
g#^[hf]t\?tp:/\(/\?\.*\)$#d
silent! g/ftp://,$/d
silent! g/=$/d
let a = getline(1,'$')
let a = uniq(sort(a))
%d
call setline(1, a)
" Do the testing.
set nomore
%s/.*/\=TestURL(submatch(0))/
" highlight the failures
/.* \([0-9]*[1-9]\|[0-9]\{2,}\)$
endfunc
func TestURL(url)
" Relies on the return code to determine whether a page is valid
echom printf("Testing URL: %d/%d %s", line('.'), line('$'), a:url)
call system(s:command . shellescape(a:url))
return printf("%s %d", a:url, v:shell_error)
endfunc
call Test_check_URLs()

355
scripts/gen_help_html.py Normal file
View File

@ -0,0 +1,355 @@
# Converts Vim/Nvim documentation to HTML.
#
# Adapted from https://github.com/c4rlo/vimhelp/
# License: MIT
#
# Copyright (c) 2016 Carlo Teubner
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
import re, urllib.parse
from itertools import chain
HEAD = """\
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-type" content="text/html; charset={encoding}"/>
<title>Nvim: {filename}</title>
"""
HEAD_END = '</head>\n<body>\n'
INTRO = """
<h1>Nvim help files</h1>
<p>HTML export of the <a href="https://neovim.io/">Nvim</a> help pages{vers-note}.
Updated <a href="https://github.com/neovim/bot-ci" class="d">automatically</a> from the <a
href="https://github.com/vim/vim/tree/master/runtime/doc" class="d">Nvim source repository</a>.
Also includes the <a href="vim_faq.txt.html">Vim FAQ</a>, pulled from its
<a href="https://github.com/chrisbra/vim_faq" class="d">source repository</a>.</p>
"""
VERSION_NOTE = ", current as of Vim {version}"
SITENAVI_LINKS = """
Quick links:
<a href="/">help overview</a> &middot;
<a href="quickref.txt.html">quick reference</a> &middot;
<a href="usr_toc.txt.html">user manual toc</a> &middot;
<a href="{helptxt}#reference_toc">reference manual toc</a> &middot;
<a href="vim_faq.txt.html">faq</a>
"""
SITENAVI_LINKS_PLAIN = SITENAVI_LINKS.format(helptxt='help.txt.html')
SITENAVI_LINKS_WEB = SITENAVI_LINKS.format(helptxt='/')
SITENAVI_PLAIN = '<p>' + SITENAVI_LINKS_PLAIN + '</p>'
SITENAVI_WEB = '<p>' + SITENAVI_LINKS_WEB + '</p>'
SITENAVI_SEARCH = '<table width="100%"><tbody><tr><td>' + SITENAVI_LINKS_WEB + \
'</td><td style="text-align: right; max-width: 25vw"><div class="gcse-searchbox">' \
'</div></td></tr></tbody></table><div class="gcse-searchresults"></div>'
TEXTSTART = """
<div id="d1">
<pre id="sp"> </pre>
<div id="d2">
<pre>
"""
FOOTER = '</pre>'
FOOTER2 = """
<p id="footer">This site is maintained by Carlo Teubner (<i>(my first name) dot (my last name) at gmail dot com</i>).</p>
</div>
</div>
</body>
</html>
"""
VIM_FAQ_LINE = '<a href="vim_faq.txt.html#vim_faq.txt" class="l">' \
'vim_faq.txt</a> Frequently Asked Questions\n'
RE_TAGLINE = re.compile(r'(\S+)\s+(\S+)')
PAT_WORDCHAR = '[!#-)+-{}~\xC0-\xFF]'
PAT_HEADER = r'(^.*~$)'
PAT_GRAPHIC = r'(^.* `$)'
PAT_PIPEWORD = r'(?<!\\)\|([#-)!+-~]+)\|'
PAT_STARWORD = r'\*([#-)!+-~]+)\*(?:(?=\s)|$)'
PAT_COMMAND = r'`([^` ]+)`'
PAT_OPTWORD = r"('(?:[a-z]{2,}|t_..)')"
PAT_CTRL = r'(CTRL-(?:W_)?(?:\{char\}|<[A-Za-z]+?>|.)?)'
PAT_SPECIAL = r'(<.+?>|\{.+?}|' \
r'\[(?:range|line|count|offset|\+?cmd|[-+]?num|\+\+opt|' \
r'arg|arguments|ident|addr|group)]|' \
r'(?<=\s)\[[-a-z^A-Z0-9_]{2,}])'
PAT_TITLE = r'(Vim version [0-9.a-z]+|VIM REFERENCE.*)'
PAT_NOTE = r'((?<!' + PAT_WORDCHAR + r')(?:note|NOTE|Notes?):?' \
r'(?!' + PAT_WORDCHAR + r'))'
PAT_URL = r'((?:https?|ftp)://[^\'"<> \t]+[a-zA-Z0-9/])'
PAT_WORD = r'((?<!' + PAT_WORDCHAR + r')' + PAT_WORDCHAR + r'+' \
r'(?!' + PAT_WORDCHAR + r'))'
RE_LINKWORD = re.compile(
PAT_OPTWORD + '|' +
PAT_CTRL + '|' +
PAT_SPECIAL)
RE_TAGWORD = re.compile(
PAT_HEADER + '|' +
PAT_GRAPHIC + '|' +
PAT_PIPEWORD + '|' +
PAT_STARWORD + '|' +
PAT_COMMAND + '|' +
PAT_OPTWORD + '|' +
PAT_CTRL + '|' +
PAT_SPECIAL + '|' +
PAT_TITLE + '|' +
PAT_NOTE + '|' +
PAT_URL + '|' +
PAT_WORD)
RE_NEWLINE = re.compile(r'[\r\n]')
RE_HRULE = re.compile(r'[-=]{3,}.*[-=]{3,3}$')
RE_EG_START = re.compile(r'(?:.* )?>$')
RE_EG_END = re.compile(r'\S')
RE_SECTION = re.compile(r'[-A-Z .][-A-Z0-9 .()]*(?=\s+\*)')
RE_STARTAG = re.compile(r'\s\*([^ \t|]+)\*(?:\s|$)')
RE_LOCAL_ADD = re.compile(r'LOCAL ADDITIONS:\s+\*local-additions\*$')
class Link(object):
__slots__ = 'link_plain_same', 'link_pipe_same', \
'link_plain_foreign', 'link_pipe_foreign', \
'filename'
def __init__(self, link_plain_same, link_plain_foreign,
link_pipe_same, link_pipe_foreign, filename):
self.link_plain_same = link_plain_same
self.link_plain_foreign = link_plain_foreign
self.link_pipe_same = link_pipe_same
self.link_pipe_foreign = link_pipe_foreign
self.filename = filename
class VimH2H(object):
def __init__(self, tags, version=None, is_web_version=True):
self._urls = { }
self._version = version
self._is_web_version = is_web_version
for line in RE_NEWLINE.split(tags):
m = RE_TAGLINE.match(line)
if m:
tag, filename = m.group(1, 2)
self.do_add_tag(filename, tag)
def add_tags(self, filename, contents):
for match in RE_STARTAG.finditer(contents):
tag = match.group(1).replace('\\', '\\\\').replace('/', '\\/')
self.do_add_tag(str(filename), tag)
def do_add_tag(self, filename, tag):
tag_quoted = urllib.parse.quote_plus(tag)
def mkpart1(doc):
return '<a href="' + doc + '#' + tag_quoted + '" class="'
part1_same = mkpart1('')
if self._is_web_version and filename == 'help.txt':
doc = '/'
else:
doc = filename + '.html'
part1_foreign = mkpart1(doc)
part2 = '">' + html_escape[tag] + '</a>'
def mklinks(cssclass):
return (part1_same + cssclass + part2,
part1_foreign + cssclass + part2)
cssclass_plain = 'd'
m = RE_LINKWORD.match(tag)
if m:
opt, ctrl, special = m.groups()
if opt is not None: cssclass_plain = 'o'
elif ctrl is not None: cssclass_plain = 'k'
elif special is not None: cssclass_plain = 's'
links_plain = mklinks(cssclass_plain)
links_pipe = mklinks('l')
self._urls[tag] = Link(
links_plain[0], links_plain[1],
links_pipe[0], links_pipe[1],
filename)
def maplink(self, tag, curr_filename, css_class=None):
links = self._urls.get(tag)
if links is not None:
if links.filename == curr_filename:
if css_class == 'l': return links.link_pipe_same
else: return links.link_plain_same
else:
if css_class == 'l': return links.link_pipe_foreign
else: return links.link_plain_foreign
elif css_class is not None:
return '<span class="' + css_class + '">' + html_escape[tag] + \
'</span>'
else: return html_escape[tag]
def to_html(self, filename, contents, encoding):
out = [ ]
inexample = 0
filename = str(filename)
is_help_txt = (filename == 'help.txt')
faq_line = False
for line in RE_NEWLINE.split(contents):
line = line.rstrip('\r\n')
line_tabs = line
line = line.expandtabs()
if RE_HRULE.match(line):
out.extend(('<span class="h">', line, '</span>\n'))
continue
if inexample == 2:
if RE_EG_END.match(line):
inexample = 0
if line[0] == '<': line = line[1:]
else:
out.extend(('<span class="e">', html_escape[line],
'</span>\n'))
continue
if RE_EG_START.match(line_tabs):
inexample = 1
line = line[0:-1]
if RE_SECTION.match(line_tabs):
m = RE_SECTION.match(line)
out.extend((r'<span class="c">', m.group(0), r'</span>'))
line = line[m.end():]
if is_help_txt and RE_LOCAL_ADD.match(line_tabs):
faq_line = True
lastpos = 0
for match in RE_TAGWORD.finditer(line):
pos = match.start()
if pos > lastpos:
out.append(html_escape[line[lastpos:pos]])
lastpos = match.end()
header, graphic, pipeword, starword, command, opt, ctrl, \
special, title, note, url, word = match.groups()
if pipeword is not None:
out.append(self.maplink(pipeword, filename, 'l'))
elif starword is not None:
out.extend(('<a name="', urllib.parse.quote_plus(starword),
'" class="t">', html_escape[starword], '</a>'))
elif command is not None:
out.extend(('<span class="e">', html_escape[command],
'</span>'))
elif opt is not None:
out.append(self.maplink(opt, filename, 'o'))
elif ctrl is not None:
out.append(self.maplink(ctrl, filename, 'k'))
elif special is not None:
out.append(self.maplink(special, filename, 's'))
elif title is not None:
out.extend(('<span class="i">', html_escape[title],
'</span>'))
elif note is not None:
out.extend(('<span class="n">', html_escape[note],
'</span>'))
elif header is not None:
out.extend(('<span class="h">', html_escape[header[:-1]],
'</span>'))
elif graphic is not None:
out.append(html_escape[graphic[:-2]])
elif url is not None:
out.extend(('<a class="u" href="', url, '">' +
html_escape[url], '</a>'))
elif word is not None:
out.append(self.maplink(word, filename))
if lastpos < len(line):
out.append(html_escape[line[lastpos:]])
out.append('\n')
if inexample == 1: inexample = 2
if faq_line:
out.append(VIM_FAQ_LINE)
faq_line = False
header = []
header.append(HEAD.format(encoding=encoding, filename=filename))
header.append(HEAD_END)
if self._is_web_version and is_help_txt:
vers_note = VERSION_NOTE.replace('{version}', self._version) \
if self._version else ''
header.append(INTRO.replace('{vers-note}', vers_note))
if self._is_web_version:
header.append(SITENAVI_SEARCH)
sitenavi_footer = SITENAVI_WEB
else:
header.append(SITENAVI_PLAIN)
sitenavi_footer = SITENAVI_PLAIN
header.append(TEXTSTART)
return ''.join(chain(header, out, (FOOTER, sitenavi_footer, FOOTER2)))
class HtmlEscCache(dict):
def __missing__(self, key):
r = key.replace('&', '&amp;') \
.replace('<', '&lt;') \
.replace('>', '&gt;')
self[key] = r
return r
html_escape = HtmlEscCache()
import sys, os, os.path
#import cProfile
sys.path.append('.')
def slurp(filename):
try:
with open(filename, encoding='UTF-8') as f:
return f.read(), 'UTF-8'
except UnicodeError:
# 'ISO-8859-1' ?
with open(filename, encoding='latin-1') as f:
return f.read(), 'latin-1'
def usage():
return "usage: " + sys.argv[0] + " IN_DIR OUT_DIR [BASENAMES...]"
def main():
if len(sys.argv) < 3: sys.exit(usage())
in_dir = sys.argv[1]
out_dir = sys.argv[2]
basenames = sys.argv[3:]
print( "Processing tags...")
h2h = VimH2H(slurp(os.path.join(in_dir, 'tags'))[0], is_web_version=False)
if len(basenames) == 0:
basenames = os.listdir(in_dir)
for basename in basenames:
if os.path.splitext(basename)[1] != '.txt' and basename != 'tags':
print( "Ignoring " + basename)
continue
print( "Processing " + basename + "...")
path = os.path.join(in_dir, basename)
text, encoding = slurp(path)
outpath = os.path.join(out_dir, basename + '.html')
of = open(outpath, 'w')
of.write(h2h.to_html(basename, text, encoding))
of.close()
main()
#cProfile.run('main()')

View File

@ -62,8 +62,17 @@ delete_blacklisted
# AppDir complete. Now package it as an AppImage.
########################################################################
# No need for a fancy script. AppRun can just be a symlink to nvim.
ln -s usr/bin/nvim AppRun
# Appimage set the ARGV0 environment variable. This causes problems in zsh.
# To prevent this, we use wrapper script to unset ARGV0 as AppRun.
# See https://github.com/AppImage/AppImageKit/issues/852
#
cat << 'EOF' > AppRun
#!/bin/bash
unset ARGV0
exec "$(dirname "$(readlink -f "${0}")")/usr/bin/nvim" ${@+"$@"}
EOF
chmod 755 AppRun
cd "$APP_BUILD_DIR" # Get out of AppImage directory.

View File

@ -14,7 +14,7 @@ package.path = nvimsrcdir .. '/?.lua;' .. package.path
local lld = {}
local syn_fd = io.open(syntax_file, 'w')
lld.line_length = 0
local w = function(s)
local function w(s)
syn_fd:write(s)
if s:find('\n') then
lld.line_length = #(s:gsub('.*\n', ''))
@ -27,7 +27,7 @@ local options = require('options')
local auevents = require('auevents')
local ex_cmds = require('ex_cmds')
local cmd_kw = function(prev_cmd, cmd)
local function cmd_kw(prev_cmd, cmd)
if not prev_cmd then
return cmd:sub(1, 1) .. '[' .. cmd:sub(2) .. ']'
else
@ -43,6 +43,15 @@ local cmd_kw = function(prev_cmd, cmd)
end
end
-- Exclude these from the vimCommand keyword list, they are handled specially
-- in syntax/vim.vim (vimAugroupKey, vimAutoCmd). #9327
local function is_autocmd_cmd(cmd)
return (cmd == 'augroup'
or cmd == 'autocmd'
or cmd == 'doautocmd'
or cmd == 'doautoall')
end
vimcmd_start = 'syn keyword vimCommand contained '
w(vimcmd_start)
local prev_cmd = nil
@ -51,7 +60,7 @@ for _, cmd_desc in ipairs(ex_cmds) do
w('\n' .. vimcmd_start)
end
local cmd = cmd_desc.command
if cmd:match('%w') and cmd ~= 'z' then
if cmd:match('%w') and cmd ~= 'z' and not is_autocmd_cmd(cmd) then
w(' ' .. cmd_kw(prev_cmd, cmd))
end
prev_cmd = cmd

View File

@ -149,8 +149,8 @@ preprocess_patch() {
local na_src='proto\|Make*\|gui_*\|if_lua\|if_mzsch\|if_olepp\|if_ole\|if_perl\|if_py\|if_ruby\|if_tcl\|if_xcmdsrv'
2>/dev/null $nvim --cmd 'set dir=/tmp' +'g@^diff --git a/src/\S*\<\%(testdir/\)\@<!\%('${na_src}'\)@norm! d/\v(^diff)|%$ ' +w +q "$file"
# Remove channel.txt, netbeans.txt, os_*.txt, term.txt, todo.txt, version*.txt, tags
local na_doc='channel\.txt\|netbeans\.txt\|os_\w\+\.txt\|term\.txt\|todo\.txt\|version\d\.txt\|tags'
# Remove unwanted Vim doc files.
local na_doc='channel\.txt\|netbeans\.txt\|os_\w\+\.txt\|term\.txt\|todo\.txt\|version\d\.txt\|sponsor\.txt\|intro\.txt\|tags'
2>/dev/null $nvim --cmd 'set dir=/tmp' +'g@^diff --git a/runtime/doc/\<\%('${na_doc}'\)\>@norm! d/\v(^diff)|%$ ' +w +q "$file"
# Remove "Last change ..." changes in doc files.
@ -179,6 +179,16 @@ preprocess_patch() {
# Rename path to matchit plugin.
LC_ALL=C sed -e 's@\( [ab]/runtime\)/pack/dist/opt/matchit/\(plugin/matchit.vim\)@\1/\2@g' \
"$file" > "$file".tmp && mv "$file".tmp "$file"
LC_ALL=C sed -e 's@\( [ab]/runtime\)/pack/dist/opt/matchit/doc/\(matchit.txt\)@\1/doc/pi_\2@g' \
"$file" > "$file".tmp && mv "$file".tmp "$file"
# Rename test_urls.vim to check_urls.vim
LC_ALL=C sed -e 's@\( [ab]\)/runtime/doc/test\(_urls.vim\)@\1/scripts/check\2@g' \
"$file" > "$file".tmp && mv "$file".tmp "$file"
# Rename path to check_colors.vim
LC_ALL=C sed -e 's@\( [ab]/runtime\)/colors/\(tools/check_colors.vim\)@\1/\2@g' \
"$file" > "$file".tmp && mv "$file".tmp "$file"
}
get_vimpatch() {

View File

@ -79,6 +79,8 @@ file(MAKE_DIRECTORY ${LINT_SUPPRESSES_ROOT}/src)
file(GLOB NVIM_SOURCES *.c)
file(GLOB NVIM_HEADERS *.h)
file(GLOB XDIFF_SOURCES xdiff/*.c)
file(GLOB XDIFF_HEADERS xdiff/*.h)
foreach(subdir
os
@ -148,12 +150,13 @@ set(CONV_SOURCES
syntax.c
tag.c
window.c)
foreach(sfile ${CONV_SOURCES})
if(NOT EXISTS "${CMAKE_CURRENT_LIST_DIR}/${sfile}")
message(FATAL_ERROR "${sfile} doesn't exist (it was added to CONV_SOURCES)")
endif()
endforeach()
# xdiff: inlined external project, we don't maintain it. #9306
list(APPEND CONV_SOURCES ${XDIFF_SOURCES})
if(NOT MSVC)
set_source_files_properties(
@ -404,7 +407,8 @@ if(POLICY CMP0069)
endif()
add_executable(nvim ${NVIM_GENERATED_FOR_SOURCES} ${NVIM_GENERATED_FOR_HEADERS}
${NVIM_GENERATED_SOURCES} ${NVIM_SOURCES} ${NVIM_HEADERS})
${NVIM_GENERATED_SOURCES} ${NVIM_SOURCES} ${NVIM_HEADERS}
${XDIFF_SOURCES} ${XDIFF_HEADERS})
target_link_libraries(nvim ${NVIM_EXEC_LINK_LIBRARIES})
install_helper(TARGETS nvim)
@ -490,6 +494,7 @@ add_library(
EXCLUDE_FROM_ALL
${NVIM_SOURCES} ${NVIM_GENERATED_SOURCES}
${NVIM_HEADERS} ${NVIM_GENERATED_FOR_SOURCES} ${NVIM_GENERATED_FOR_HEADERS}
${XDIFF_SOURCES} ${XDIFF_HEADERS}
)
set_property(TARGET libnvim APPEND PROPERTY
INCLUDE_DIRECTORIES ${LUA_PREFERRED_INCLUDE_DIRS})
@ -514,6 +519,7 @@ else()
EXCLUDE_FROM_ALL
${NVIM_SOURCES} ${NVIM_GENERATED_SOURCES}
${NVIM_HEADERS} ${NVIM_GENERATED_FOR_SOURCES} ${NVIM_GENERATED_FOR_HEADERS}
${XDIFF_SOURCES} ${XDIFF_HEADERS}
${UNIT_TEST_FIXTURES}
)
target_link_libraries(nvim-test ${NVIM_TEST_LINK_LIBRARIES})

View File

@ -51,8 +51,7 @@
///
/// @param buffer Buffer handle
/// @param[out] err Error details, if any
/// @return Line count, or \`0` if the buffer has been unloaded (see
/// |api-buffer|).
/// @return Line count, or 0 for unloaded buffer. |api-buffer|
Integer nvim_buf_line_count(Buffer buffer, Error *err)
FUNC_API_SINCE(1)
{
@ -227,8 +226,7 @@ ArrayOf(String) buffer_get_line_slice(Buffer buffer,
/// @param end Last line index (exclusive)
/// @param strict_indexing Whether out-of-bounds should be an error.
/// @param[out] err Error details, if any
/// @return Array of lines. If the buffer has been unloaded then an empty array
/// will be returned instead. (See |api-buffer|.)
/// @return Array of lines, or empty array for unloaded buffer.
ArrayOf(String) nvim_buf_get_lines(uint64_t channel_id,
Buffer buffer,
Integer start,
@ -491,12 +489,12 @@ end:
try_end(err);
}
/// Return the byte offset for a line.
//
/// The first line returns 0. UTF-8 bytes are counted, and EOL counts as one
/// byte. 'fileformat' and 'fileencoding' are ignored. Sending in the index
/// just below the last line gives the total byte count for the entire buffer.
/// A final EOL is included if it would be written, see 'eol'.
/// Returns the byte offset for a line.
///
/// Line 1 (index=0) has offset 0. UTF-8 bytes are counted. EOL is one byte.
/// 'fileformat' and 'fileencoding' are ignored. The line index just after the
/// last line gives the total byte-count of the buffer. A final EOL byte is
/// counted if it would be written, see 'eol'.
///
/// Unlike |line2byte()|, throws error for out-of-bounds indexing.
/// Returns -1 for unloaded buffer.
@ -504,7 +502,7 @@ end:
/// @param buffer Buffer handle
/// @param index Line index
/// @param[out] err Error details, if any
/// @return Integer Byte offset
/// @return Integer byte offset, or -1 for unloaded buffer.
Integer nvim_buf_get_offset(Buffer buffer, Integer index, Error *err)
FUNC_API_SINCE(5)
{
@ -907,34 +905,34 @@ ArrayOf(Integer, 2) nvim_buf_get_mark(Buffer buffer, String name, Error *err)
///
/// Useful for plugins that dynamically generate highlights to a buffer
/// (like a semantic highlighter or linter). The function adds a single
/// highlight to a buffer. Unlike matchaddpos() highlights follow changes to
/// highlight to a buffer. Unlike |matchaddpos()| highlights follow changes to
/// line numbering (as lines are inserted/removed above the highlighted line),
/// like signs and marks do.
///
/// `src_id` is useful for batch deletion/updating of a set of highlights. When
/// called with `src_id = 0`, an unique source id is generated and returned.
/// Successive calls can pass that `src_id` to associate new highlights with
/// the same source group. All highlights in the same group can be cleared
/// with `nvim_buf_clear_highlight`. If the highlight never will be manually
/// deleted, pass `src_id = -1`.
/// Namespaces are used for batch deletion/updating of a set of highlights. To
/// create a namespace, use |nvim_create_namespace| which returns a namespace
/// id. Pass it in to this function as `ns_id` to add highlights to the
/// namespace. All highlights in the same namespace can then be cleared with
/// single call to |nvim_buf_clear_namespace|. If the highlight never will be
/// deleted by an API call, pass `ns_id = -1`.
///
/// If `hl_group` is the empty string no highlight is added, but a new `src_id`
/// is still returned. This is useful for an external plugin to synchrounously
/// request an unique `src_id` at initialization, and later asynchronously add
/// and clear highlights in response to buffer changes.
/// As a shorthand, `ns_id = 0` can be used to create a new namespace for the
/// highlight, the allocated id is then returned. If `hl_group` is the empty
/// string no highlight is added, but a new `ns_id` is still returned. This is
/// supported for backwards compatibility, new code should use
/// |nvim_create_namespace| to create a new empty namespace.
///
/// @param buffer Buffer handle
/// @param src_id Source group to use or 0 to use a new group,
/// or -1 for ungrouped highlight
/// @param ns_id namespace to use 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 (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
/// @return The ns_id that was used
Integer nvim_buf_add_highlight(Buffer buffer,
Integer src_id,
Integer ns_id,
String hl_group,
Integer line,
Integer col_start,
@ -964,28 +962,28 @@ Integer nvim_buf_add_highlight(Buffer buffer,
hlg_id = syn_check_group((char_u *)hl_group.data, (int)hl_group.size);
}
src_id = bufhl_add_hl(buf, (int)src_id, hlg_id, (linenr_T)line+1,
(colnr_T)col_start+1, (colnr_T)col_end);
return src_id;
ns_id = bufhl_add_hl(buf, (int)ns_id, hlg_id, (linenr_T)line+1,
(colnr_T)col_start+1, (colnr_T)col_end);
return ns_id;
}
/// Clears highlights and virtual text from a given source id and range of lines
/// Clears namespaced objects, highlights and virtual text, from a line range
///
/// To clear a source group in the entire buffer, pass in 0 and -1 to
/// To clear the namespace in the entire buffer, pass in 0 and -1 to
/// line_start and line_end respectively.
///
/// @param buffer Buffer handle
/// @param src_id Highlight source group to clear, or -1 to clear all.
/// @param ns_id Namespace to clear, or -1 to clear all namespaces.
/// @param line_start Start of range of lines to clear
/// @param line_end End of range of lines to clear (exclusive) or -1 to clear
/// to end of file.
/// to end of buffer.
/// @param[out] err Error details, if any
void nvim_buf_clear_highlight(Buffer buffer,
Integer src_id,
void nvim_buf_clear_namespace(Buffer buffer,
Integer ns_id,
Integer line_start,
Integer line_end,
Error *err)
FUNC_API_SINCE(1)
FUNC_API_SINCE(5)
{
buf_T *buf = find_buffer_by_handle(buffer, err);
if (!buf) {
@ -1000,7 +998,27 @@ void nvim_buf_clear_highlight(Buffer buffer,
line_end = MAXLNUM;
}
bufhl_clear_line_range(buf, (int)src_id, (int)line_start+1, (int)line_end);
bufhl_clear_line_range(buf, (int)ns_id, (int)line_start+1, (int)line_end);
}
/// Clears highlights and virtual text from namespace and range of lines
///
/// @deprecated use |nvim_buf_clear_namespace|.
///
/// @param buffer Buffer handle
/// @param ns_id Namespace to clear, or -1 to clear all.
/// @param line_start Start of range of lines to clear
/// @param line_end End of range of lines to clear (exclusive) or -1 to clear
/// to end of file.
/// @param[out] err Error details, if any
void nvim_buf_clear_highlight(Buffer buffer,
Integer ns_id,
Integer line_start,
Integer line_end,
Error *err)
FUNC_API_SINCE(1)
{
nvim_buf_clear_namespace(buffer, ns_id, line_start, line_end, err);
}
@ -1009,15 +1027,20 @@ void nvim_buf_clear_highlight(Buffer buffer,
/// By default (and currently the only option) the text will be placed after
/// the buffer text. Virtual text will never cause reflow, rather virtual
/// text will be truncated at the end of the screen line. The virtual text will
/// begin after one cell to the right of the ordinary text, this will contain
/// the |lcs-eol| char if set, otherwise just be a space.
/// begin one cell (|lcs-eol| or space) after the ordinary text.
///
/// The same src_id can be used for both virtual text and highlights added by
/// nvim_buf_add_highlight. Virtual text is cleared using
/// nvim_buf_clear_highlight.
/// Namespaces are used to support batch deletion/updating of virtual text.
/// To create a namespace, use |nvim_create_namespace|. Virtual text is
/// cleared using |nvim_buf_clear_namespace|. The same `ns_id` can be used for
/// both virtual text and highlights added by |nvim_buf_add_highlight|, both
/// can then be cleared with a single call to |nvim_buf_clear_namespace|. If the
/// virtual text never will be cleared by an API call, pass `ns_id = -1`.
///
/// As a shorthand, `ns_id = 0` can be used to create a new namespace for the
/// virtual text, the allocated id is then returned.
///
/// @param buffer Buffer handle
/// @param src_id Source group to use or 0 to use a new group,
/// @param ns_id Namespace to use or 0 to create a namespace,
/// or -1 for a ungrouped annotation
/// @param line Line to annotate with virtual text (zero-indexed)
/// @param chunks A list of [text, hl_group] arrays, each representing a
@ -1025,9 +1048,9 @@ void nvim_buf_clear_highlight(Buffer buffer,
/// can be omitted for no highlight.
/// @param opts Optional parameters. Currently not used.
/// @param[out] err Error details, if any
/// @return The src_id that was used
/// @return The ns_id that was used
Integer nvim_buf_set_virtual_text(Buffer buffer,
Integer src_id,
Integer ns_id,
Integer line,
Array chunks,
Dictionary opts,
@ -1077,9 +1100,9 @@ Integer nvim_buf_set_virtual_text(Buffer buffer,
kv_push(virt_text, ((VirtTextChunk){ .text = text, .hl_id = hl_id }));
}
src_id = bufhl_add_virt_text(buf, (int)src_id, (linenr_T)line+1,
virt_text);
return src_id;
ns_id = bufhl_add_virt_text(buf, (int)ns_id, (linenr_T)line+1,
virt_text);
return ns_id;
free_exit:
kv_destroy(virt_text);

View File

@ -46,6 +46,24 @@
# include "api/vim.c.generated.h"
#endif
void api_vim_init(void)
FUNC_API_NOEXPORT
{
namespace_ids = map_new(String, handle_T)();
}
void api_vim_free_all_mem(void)
FUNC_API_NOEXPORT
{
String name;
handle_T id;
map_foreach(namespace_ids, name, id, {
(void)id;
xfree(name.data);
})
map_free(String, handle_T)(namespace_ids);
}
/// Executes an ex-command.
///
/// On execution error: fails with VimL error, does not update v:errmsg.
@ -725,6 +743,9 @@ void nvim_err_writeln(String str)
/// Gets the current list of buffer handles
///
/// Includes unlisted (unloaded/deleted) buffers, like `:ls!`.
/// Use |nvim_buf_is_loaded()| to check if a buffer is loaded.
///
/// @return List of buffer handles
ArrayOf(Buffer) nvim_list_bufs(void)
FUNC_API_SINCE(1)
@ -884,6 +905,49 @@ void nvim_set_current_tabpage(Tabpage tabpage, Error *err)
}
}
/// create a new namespace, or get one with an exisiting name
///
/// Namespaces are currently used for buffer highlighting and virtual text, see
/// |nvim_buf_add_highlight| and |nvim_buf_set_virtual_text|.
///
/// Namespaces can have a name of be anonymous. If `name` is a non-empty string,
/// and a namespace already exists with that name,the existing namespace id is
/// returned. If an empty string is used, a new anonymous namespace is returned.
///
/// @param name Name of the namespace or empty string
/// @return the namespace id
Integer nvim_create_namespace(String name)
FUNC_API_SINCE(5)
{
handle_T id = map_get(String, handle_T)(namespace_ids, name);
if (id > 0) {
return id;
}
id = next_namespace_id++;
if (name.size > 0) {
String name_alloc = copy_string(name);
map_put(String, handle_T)(namespace_ids, name_alloc, id);
}
return (Integer)id;
}
/// Get existing named namespaces
///
/// @return dict that maps from names to namespace ids.
Dictionary nvim_get_namespaces(void)
FUNC_API_SINCE(5)
{
Dictionary retval = ARRAY_DICT_INIT;
String name;
handle_T id;
map_foreach(namespace_ids, name, id, {
PUT(retval, name.data, INTEGER_OBJ(id));
})
return retval;
}
/// Subscribes to event broadcasts
///
/// @param channel_id Channel id (passed automatically by the dispatcher)
@ -1028,7 +1092,7 @@ Array nvim_get_api_info(uint64_t channel_id)
/// @param attributes Informal attributes describing the client. Clients might
/// define their own keys, but the following are suggested:
/// - "website" Website of client (for instance github repository)
/// - "license" Informal descripton of the license, such as "Apache 2",
/// - "license" Informal description of the license, such as "Apache 2",
/// "GPLv3" or "MIT"
/// - "logo" URI or path to image, preferably small logo or icon.
/// .png or .svg format is preferred.

View File

@ -4,6 +4,10 @@
#include <stdint.h>
#include "nvim/api/private/defs.h"
#include "nvim/map.h"
EXTERN Map(String, handle_T) *namespace_ids INIT(= NULL);
EXTERN handle_T next_namespace_id INIT(= 1);
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "api/vim.h.generated.h"

View File

@ -10,6 +10,7 @@
#include "nvim/api/private/defs.h"
#include "nvim/api/private/helpers.h"
#include "nvim/vim.h"
#include "nvim/buffer.h"
#include "nvim/cursor.h"
#include "nvim/window.h"
#include "nvim/screen.h"
@ -33,6 +34,41 @@ Buffer nvim_win_get_buf(Window window, Error *err)
return win->w_buffer->handle;
}
/// Sets the current buffer in a window, without side-effects
///
/// @param window Window handle
/// @param buffer Buffer handle
/// @param[out] err Error details, if any
void nvim_win_set_buf(Window window, Buffer buffer, Error *err)
FUNC_API_SINCE(5)
{
win_T *win = find_window_by_handle(window, err), *save_curwin = curwin;
buf_T *buf = find_buffer_by_handle(buffer, err);
tabpage_T *tab = win_find_tabpage(win), *save_curtab = curtab;
if (!win || !buf) {
return;
}
if (switch_win(&save_curwin, &save_curtab, win, tab, false) == FAIL) {
api_set_error(err,
kErrorTypeException,
"Failed to switch to window %d",
window);
}
try_start();
int result = do_buffer(DOBUF_GOTO, DOBUF_FIRST, FORWARD, buf->b_fnum, 0);
if (!try_end(err) && result == FAIL) {
api_set_error(err,
kErrorTypeException,
"Failed to set buffer %d",
buffer);
}
restore_win(save_curwin, save_curtab, false);
}
/// Gets the cursor position in the window
///
/// @param window Window handle

View File

@ -26,7 +26,6 @@ void aucmd_schedule_focusgained(bool gained)
}
static void do_autocmd_focusgained(bool gained)
FUNC_ATTR_NONNULL_ALL
{
static bool recursive = false;

View File

@ -21,6 +21,7 @@ return {
'BufWritePre', -- before writing a buffer
'ChanInfo', -- info was received about channel
'ChanOpen', -- channel was opened
'CmdLineChanged', -- command line was modified
'CmdLineEnter', -- after entering cmdline mode
'CmdLineLeave', -- before leaving cmdline mode
'CmdUndefined', -- command undefined
@ -33,6 +34,7 @@ return {
'CursorHoldI', -- idem, in Insert mode
'CursorMoved', -- cursor was moved
'CursorMovedI', -- cursor was moved in Insert mode
'DiffUpdated', -- diffs have been updated
'DirChanged', -- directory changed
'EncodingChanged', -- after changing the 'encoding' option
'ExitPre', -- before exiting

View File

@ -26,6 +26,7 @@
#include "nvim/api/private/handle.h"
#include "nvim/api/private/helpers.h"
#include "nvim/api/vim.h"
#include "nvim/ascii.h"
#include "nvim/assert.h"
#include "nvim/vim.h"
@ -5327,10 +5328,10 @@ int bufhl_add_hl(buf_T *buf,
int hl_id,
linenr_T lnum,
colnr_T col_start,
colnr_T col_end) {
static int next_src_id = 1;
colnr_T col_end)
{
if (src_id == 0) {
src_id = next_src_id++;
src_id = (int)nvim_create_namespace((String)STRING_INIT);
}
if (hl_id <= 0) {
// no highlight group or invalid line, just return src_id
@ -5395,9 +5396,8 @@ int bufhl_add_virt_text(buf_T *buf,
linenr_T lnum,
VirtText virt_text)
{
static int next_src_id = 1;
if (src_id == 0) {
src_id = next_src_id++;
src_id = (int)nvim_create_namespace((String)STRING_INIT);
}
BufhlLine *lineinfo = bufhl_tree_ref(&buf->b_bufhl_info, lnum, true);

View File

@ -58,10 +58,10 @@ typedef struct {
* functions that set or reset the flags.
*
* VALID_BOTLINE VALID_BOTLINE_AP
* on on w_botline valid
* off on w_botline approximated
* off off w_botline not valid
* on off not possible
* on on w_botline valid
* off on w_botline approximated
* off off w_botline not valid
* on off not possible
*/
#define VALID_WROW 0x01 /* w_wrow (window row) is valid */
#define VALID_WCOL 0x02 /* w_wcol (window col) is valid */
@ -159,7 +159,7 @@ typedef struct {
int wo_arab;
# define w_p_arab w_onebuf_opt.wo_arab /* 'arabic' */
int wo_bri;
# define w_p_bri w_onebuf_opt.wo_bri /* 'breakindent' */
# define w_p_bri w_onebuf_opt.wo_bri // 'breakindent'
char_u *wo_briopt;
# define w_p_briopt w_onebuf_opt.wo_briopt /* 'breakindentopt' */
int wo_diff;
@ -412,13 +412,13 @@ typedef struct {
* syntax state too often.
* b_sst_array[] is allocated to hold the state for all displayed lines,
* and states for 1 out of about 20 other lines.
* b_sst_array pointer to an array of synstate_T
* b_sst_len number of entries in b_sst_array[]
* b_sst_first pointer to first used entry in b_sst_array[] or NULL
* b_sst_firstfree pointer to first free entry in b_sst_array[] or NULL
* b_sst_freecount number of free entries in b_sst_array[]
* b_sst_check_lnum entries after this lnum need to be checked for
* validity (MAXLNUM means no check needed)
* b_sst_array pointer to an array of synstate_T
* b_sst_len number of entries in b_sst_array[]
* b_sst_first pointer to first used entry in b_sst_array[] or NULL
* b_sst_firstfree pointer to first free entry in b_sst_array[] or NULL
* b_sst_freecount number of free entries in b_sst_array[]
* b_sst_check_lnum entries after this lnum need to be checked for
* validity (MAXLNUM means no check needed)
*/
synstate_T *b_sst_array;
int b_sst_len;
@ -475,15 +475,15 @@ struct file_buffer {
int b_locked; // Buffer is being closed or referenced, don't
// let autocommands wipe it out.
/*
* b_ffname has the full path of the file (NULL for no name).
* b_sfname is the name as the user typed it (or NULL).
* b_fname is the same as b_sfname, unless ":cd" has been done,
* then it is the same as b_ffname (NULL for no name).
*/
char_u *b_ffname; /* full path file name */
char_u *b_sfname; /* short file name */
char_u *b_fname; /* current file name */
//
// b_ffname has the full path of the file (NULL for no name).
// b_sfname is the name as the user typed it (or NULL).
// b_fname is the same as b_sfname, unless ":cd" has been done,
// then it is the same as b_ffname (NULL for no name).
//
char_u *b_ffname; // full path file name
char_u *b_sfname; // short file name
char_u *b_fname; // current file name
bool file_id_valid;
FileID file_id;
@ -587,12 +587,12 @@ struct file_buffer {
bool b_scanned; /* ^N/^P have scanned this buffer */
/* flags for use of ":lmap" and IM control */
long b_p_iminsert; /* input mode for insert */
long b_p_imsearch; /* input mode for search */
#define B_IMODE_USE_INSERT -1 /* Use b_p_iminsert value for search */
#define B_IMODE_NONE 0 /* Input via none */
#define B_IMODE_LMAP 1 /* Input via langmap */
// flags for use of ":lmap" and IM control
long b_p_iminsert; // input mode for insert
long b_p_imsearch; // input mode for search
#define B_IMODE_USE_INSERT -1 // Use b_p_iminsert value for search
#define B_IMODE_NONE 0 // Input via none
#define B_IMODE_LMAP 1 // Input via langmap
# define B_IMODE_LAST 1
short b_kmap_state; /* using "lmap" mappings */
@ -760,7 +760,7 @@ struct file_buffer {
/* Two special kinds of buffers:
* help buffer - used for help files, won't use a swap file.
* spell buffer - used for spell info, never displayed and doesn't have a
* file name.
* file name.
*/
bool b_help; /* TRUE for help file buffer (when set b_p_bt
is "help") */
@ -787,6 +787,8 @@ struct file_buffer {
// array of channelids which have asked to receive updates for this
// buffer.
kvec_t(uint64_t) update_channels;
int b_diff_failed; // internal diff failed for this buffer
};
/*
@ -840,6 +842,7 @@ struct tabpage_S {
diff_T *tp_first_diff;
buf_T *(tp_diffbuf[DB_COUNT]);
int tp_diff_invalid; ///< list of diffs is outdated
int tp_diff_update; ///< update diffs before redrawing
frame_T *(tp_snapshot[SNAP_COUNT]); ///< window layout snapshots
ScopeDictDictItem tp_winvar; ///< Variable for "t:" Dictionary.
dict_T *tp_vars; ///< Internal variables, local to tab page.
@ -916,9 +919,9 @@ typedef struct {
/// Same as lpos_T, but with additional field len.
typedef struct
{
linenr_T lnum; ///< line number
colnr_T col; ///< column number
int len; ///< length: 0 - to the end of line
linenr_T lnum; ///< line number
colnr_T col; ///< column number
int len; ///< length: 0 - to the end of line
} llpos_T;
/// posmatch_T provides an array for storing match items for matchaddpos()
@ -926,10 +929,10 @@ typedef struct
typedef struct posmatch posmatch_T;
struct posmatch
{
llpos_T pos[MAXPOSMATCH]; ///< array of positions
int cur; ///< internal position counter
linenr_T toplnum; ///< top buffer line
linenr_T botlnum; ///< bottom buffer line
llpos_T pos[MAXPOSMATCH]; ///< array of positions
int cur; ///< internal position counter
linenr_T toplnum; ///< top buffer line
linenr_T botlnum; ///< bottom buffer line
};
/*
@ -1036,7 +1039,7 @@ struct window_S {
* Recomputing is minimized by storing the result of computations.
* Use functions in screen.c to check if they are valid and to update.
* w_valid is a bitfield of flags, which indicate if specific values are
* valid or need to be recomputed.
* valid or need to be recomputed.
*/
int w_valid;
pos_T w_valid_cursor; /* last known position of w_cursor, used

View File

@ -161,7 +161,6 @@ void channel_init(void)
channels = pmap_new(uint64_t)();
channel_alloc(kChannelStreamStderr);
rpc_init();
remote_ui_init();
}
/// Allocates a channel.
@ -284,6 +283,8 @@ Channel *channel_job_start(char **argv, CallbackReader on_stdout,
uint16_t pty_width, uint16_t pty_height,
char *term_name, varnumber_T *status_out)
{
assert(cwd == NULL || os_isdir_executable(cwd));
Channel *chan = channel_alloc(kChannelStreamProc);
chan->on_stdout = on_stdout;
chan->on_stderr = on_stderr;
@ -605,12 +606,15 @@ static void on_channel_output(Stream *stream, Channel *chan, RBuffer *buf,
}
rbuffer_consumed(buf, count);
// if buffer wasn't consumed, a pending callback is stalled. Aggregate the
// received data and avoid a "burst" of multiple callbacks.
bool buffer_set = reader->buffer.ga_len > 0;
ga_concat_len(&reader->buffer, ptr, count);
if (!reader->buffered && !buffer_set && callback_reader_set(*reader)) {
process_channel_event(chan, &reader->cb, type, reader, 0);
if (callback_reader_set(*reader) || reader->buffered) {
// if buffer wasn't consumed, a pending callback is stalled. Aggregate the
// received data and avoid a "burst" of multiple callbacks.
bool buffer_set = reader->buffer.ga_len > 0;
ga_concat_len(&reader->buffer, ptr, count);
if (callback_reader_set(*reader) && !reader->buffered && !buffer_set) {
process_channel_event(chan, &reader->cb, type, reader, 0);
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -3127,10 +3127,16 @@ static void ins_compl_restart(void)
*/
static void ins_compl_set_original_text(char_u *str)
{
/* Replace the original text entry. */
if (compl_first_match->cp_flags & ORIGINAL_TEXT) { /* safety check */
// Replace the original text entry.
// The ORIGINAL_TEXT flag is either at the first item or might possibly be
// at the last item for backward completion
if (compl_first_match->cp_flags & ORIGINAL_TEXT) { // safety check
xfree(compl_first_match->cp_str);
compl_first_match->cp_str = vim_strsave(str);
} else if (compl_first_match->cp_prev != NULL
&& (compl_first_match->cp_prev->cp_flags & ORIGINAL_TEXT)) {
xfree(compl_first_match->cp_prev->cp_str);
compl_first_match->cp_prev->cp_str = vim_strsave(str);
}
}
@ -3189,7 +3195,8 @@ static bool ins_compl_prep(int c)
/* Ignore end of Select mode mapping and mouse scroll buttons. */
if (c == K_SELECT || c == K_MOUSEDOWN || c == K_MOUSEUP
|| c == K_MOUSELEFT || c == K_MOUSERIGHT || c == K_EVENT) {
|| c == K_MOUSELEFT || c == K_MOUSERIGHT || c == K_EVENT
|| c == K_COMMAND) {
return retval;
}

View File

@ -2728,6 +2728,12 @@ void ex_call(exarg_T *eap)
lnum = eap->line1;
for (; lnum <= eap->line2; lnum++) {
if (eap->addr_count > 0) { // -V560
if (lnum > curbuf->b_ml.ml_line_count) {
// If the function deleted lines or switched to another buffer
// the line number may become invalid.
EMSG(_(e_invrange));
break;
}
curwin->w_cursor.lnum = lnum;
curwin->w_cursor.col = 0;
curwin->w_cursor.coladd = 0;
@ -8119,6 +8125,7 @@ static void f_execute(typval_T *argvars, typval_T *rettv, FunPtr fptr)
const int save_msg_silent = msg_silent;
const int save_emsg_silent = emsg_silent;
const bool save_emsg_noredir = emsg_noredir;
const bool save_redir_off = redir_off;
garray_T *const save_capture_ga = capture_ga;
if (check_secure()) {
@ -8146,6 +8153,7 @@ static void f_execute(typval_T *argvars, typval_T *rettv, FunPtr fptr)
garray_T capture_local;
ga_init(&capture_local, (int)sizeof(char), 80);
capture_ga = &capture_local;
redir_off = false;
if (argvars[0].v_type != VAR_LIST) {
do_cmdline_cmd(tv_get_string(&argvars[0]));
@ -8163,6 +8171,7 @@ static void f_execute(typval_T *argvars, typval_T *rettv, FunPtr fptr)
msg_silent = save_msg_silent;
emsg_silent = save_emsg_silent;
emsg_noredir = save_emsg_noredir;
redir_off = save_redir_off;
ga_append(capture_ga, NUL);
rettv->v_type = VAR_STRING;
@ -10326,10 +10335,10 @@ static void f_getwininfo(typval_T *argvars, typval_T *rettv, FunPtr fptr)
tabnr++;
int16_t winnr = 0;
FOR_ALL_WINDOWS_IN_TAB(wp, tp) {
winnr++;
if (wparg != NULL && wp != wparg) {
continue;
}
winnr++;
dict_T *const d = get_win_info(wp, tabnr, winnr);
tv_list_append_dict(rettv->vval.v_list, d);
if (wparg != NULL) {
@ -10793,17 +10802,6 @@ static void f_has(typval_T *argvars, typval_T *rettv, FunPtr fptr)
n = true;
}
if (STRICMP(name, "ruby") == 0 && n == true) {
char *rubyhost = call_func_retstr("provider#ruby#Detect", 0, NULL, true);
if (rubyhost) {
if (*rubyhost == NUL) {
// Invalid rubyhost executable. Gem is probably not installed.
n = false;
}
xfree(rubyhost);
}
}
rettv->vval.v_number = n;
}
@ -11718,7 +11716,7 @@ static void f_jobstart(typval_T *argvars, typval_T *rettv, FunPtr fptr)
if (new_cwd && strlen(new_cwd) > 0) {
cwd = new_cwd;
// The new cwd must be a directory.
if (!os_isdir((char_u *)cwd)) {
if (!os_isdir_executable((const char *)cwd)) {
EMSG2(_(e_invarg2), "expected valid directory");
shell_free_argv(argv);
return;
@ -16763,7 +16761,7 @@ static void f_termopen(typval_T *argvars, typval_T *rettv, FunPtr fptr)
if (new_cwd && *new_cwd != NUL) {
cwd = new_cwd;
// The new cwd must be a directory.
if (!os_isdir((const char_u *)cwd)) {
if (!os_isdir_executable((const char *)cwd)) {
EMSG2(_(e_invarg2), "expected valid directory");
shell_free_argv(argv);
return;
@ -19244,7 +19242,8 @@ static void set_var(const char *name, const size_t name_len, typval_T *const tv,
}
return;
} else if (v->di_tv.v_type != tv->v_type) {
internal_error("set_var()");
EMSG2(_("E963: setting %s to value with wrong type"), name);
return;
}
}
@ -19532,6 +19531,7 @@ void ex_echo(exarg_T *eap)
typval_T rettv;
bool needclr = true;
bool atstart = true;
const int did_emsg_before = did_emsg;
if (eap->skip)
++emsg_skip;
@ -19546,7 +19546,7 @@ void ex_echo(exarg_T *eap)
// Report the invalid expression unless the expression evaluation
// has been cancelled due to an aborting error, an interrupt, or an
// exception.
if (!aborting()) {
if (!aborting() && did_emsg == did_emsg_before) {
EMSG2(_(e_invexpr2), p);
}
need_clr_eos = false;
@ -19635,7 +19635,7 @@ void ex_execute(exarg_T *eap)
int ret = OK;
char_u *p;
garray_T ga;
int save_did_emsg;
int save_did_emsg = did_emsg;
ga_init(&ga, 1, 80);
@ -19649,8 +19649,9 @@ void ex_execute(exarg_T *eap)
* has been cancelled due to an aborting error, an interrupt, or an
* exception.
*/
if (!aborting())
if (!aborting() && did_emsg == save_did_emsg) {
EMSG2(_(e_invexpr2), p);
}
ret = FAIL;
break;
}
@ -22758,7 +22759,18 @@ bool eval_has_provider(const char *name)
CHECK_PROVIDER(python);
return has_python;
} else if (strequal(name, "ruby")) {
bool need_check_ruby = (has_ruby == -1);
CHECK_PROVIDER(ruby);
if (need_check_ruby && has_ruby == 1) {
char *rubyhost = call_func_retstr("provider#ruby#Detect", 0, NULL, true);
if (rubyhost) {
if (*rubyhost == NUL) {
// Invalid rubyhost executable. Gem is probably not installed.
has_ruby = 0;
}
xfree(rubyhost);
}
}
return has_ruby;
}

View File

@ -933,7 +933,7 @@ char *encode_tv2json(typval_T *tv, size_t *len)
#define TYPVAL_ENCODE_CONV_BOOL(tv, num) \
do { \
if ((num)) { \
if (num) { \
msgpack_pack_true(packer); \
} else { \
msgpack_pack_false(packer); \

View File

@ -2850,7 +2850,7 @@ const char *tv_get_string_buf_chk(const typval_T *const tv, char *const buf)
/// Get the string value of a "stringish" VimL object.
///
/// @warning For number and special values it uses a single, static buffer. It
/// may be used only once, next call to get_tv_string may reuse it. Use
/// may be used only once, next call to tv_get_string may reuse it. Use
/// tv_get_string_buf() if you need to use tv_get_string() output after
/// calling it again.
///
@ -2869,7 +2869,7 @@ const char *tv_get_string_chk(const typval_T *const tv)
/// Get the string value of a "stringish" VimL object.
///
/// @warning For number and special values it uses a single, static buffer. It
/// may be used only once, next call to get_tv_string may reuse it. Use
/// may be used only once, next call to tv_get_string may reuse it. Use
/// tv_get_string_buf() if you need to use tv_get_string() output after
/// calling it again.
///

View File

@ -816,10 +816,23 @@ int do_move(linenr_T line1, linenr_T line2, linenr_T dest)
linenr_T last_line; // Last line in file after adding new text
if (dest >= line1 && dest < line2) {
EMSG(_("E134: Move lines into themselves"));
EMSG(_("E134: Cannot move a range of lines into itself"));
return FAIL;
}
// Do nothing if we are not actually moving any lines. This will prevent
// the 'modified' flag from being set without cause.
if (dest == line1 - 1 || dest == line2) {
// Move the cursor as if lines were moved (see below) to be backwards
// compatible.
if (dest >= line1) {
curwin->w_cursor.lnum = dest;
} else {
curwin->w_cursor.lnum = dest + (line2 - line1) + 1;
}
return OK;
}
num_lines = line2 - line1 + 1;
/*
@ -5672,6 +5685,14 @@ void ex_sign(exarg_T *eap)
int len;
arg += 5;
for (s = arg; s + 1 < p; s++) {
if (*s == '\\') {
// Remove a backslash, so that it is possible
// to use a space.
STRMOVE(s, s + 1);
p--;
}
}
// Count cells and check for non-printable chars
cells = 0;

View File

@ -28,15 +28,15 @@ local FILES = bit.bor(XFILE, EXTRA)
local WORD1 = bit.bor(EXTRA, NOSPC)
local FILE1 = bit.bor(FILES, NOSPC)
local ADDR_LINES = 0
local ADDR_WINDOWS = 1
local ADDR_ARGUMENTS = 2
local ADDR_LOADED_BUFFERS = 3
local ADDR_BUFFERS = 4
local ADDR_TABS = 5
local ADDR_TABS_RELATIVE = 6
local ADDR_QUICKFIX = 7
local ADDR_OTHER = 99
local ADDR_LINES = 0 -- buffer line numbers
local ADDR_WINDOWS = 1 -- window number
local ADDR_ARGUMENTS = 2 -- argument number
local ADDR_LOADED_BUFFERS = 3 -- buffer number of loaded buffer
local ADDR_BUFFERS = 4 -- buffer number
local ADDR_TABS = 5 -- tab page number
local ADDR_TABS_RELATIVE = 6 -- Tab page that only relative
local ADDR_QUICKFIX = 7 -- quickfix list entry number
local ADDR_OTHER = 99 -- something else
-- The following table is described in ex_cmds_defs.h file.
return {
@ -1706,24 +1706,6 @@ return {
addr_type=ADDR_LINES,
func='ex_next',
},
{
command='nbkey',
flags=bit.bor(EXTRA, NOTADR, NEEDARG),
addr_type=ADDR_LINES,
func='ex_ni',
},
{
command='nbclose',
flags=bit.bor(TRLBAR, CMDWIN),
addr_type=ADDR_LINES,
func='ex_ni',
},
{
command='nbstart',
flags=bit.bor(WORD1, TRLBAR, CMDWIN),
addr_type=ADDR_LINES,
func='ex_ni',
},
{
command='new',
flags=bit.bor(BANG, FILE1, RANGE, NOTADR, EDITCMD, ARGOPT, TRLBAR),
@ -1958,18 +1940,6 @@ return {
addr_type=ADDR_LINES,
func='ex_previous',
},
{
command='promptfind',
flags=bit.bor(EXTRA, NOTRLCOM, CMDWIN),
addr_type=ADDR_LINES,
func='ex_ni',
},
{
command='promptrepl',
flags=bit.bor(EXTRA, NOTRLCOM, CMDWIN),
addr_type=ADDR_LINES,
func='ex_ni',
},
{
command='profile',
flags=bit.bor(BANG, EXTRA, TRLBAR, CMDWIN),
@ -2326,8 +2296,8 @@ return {
},
{
command='scriptnames',
flags=bit.bor(TRLBAR, CMDWIN),
addr_type=ADDR_LINES,
flags=bit.bor(BANG, RANGE, NOTADR, COUNT, TRLBAR, CMDWIN),
addr_type=ADDR_OTHER,
func='ex_scriptnames',
},
{
@ -3116,12 +3086,6 @@ return {
addr_type=ADDR_LINES,
func='do_wqall',
},
{
command='wsverb',
flags=bit.bor(EXTRA, NOTADR, NEEDARG),
addr_type=ADDR_LINES,
func='ex_ni',
},
{
command='wshada',
flags=bit.bor(BANG, FILE1, TRLBAR, CMDWIN),

View File

@ -3069,6 +3069,17 @@ theend:
/// ":scriptnames"
void ex_scriptnames(exarg_T *eap)
{
if (eap->addr_count > 0) {
// :script {scriptId}: edit the script
if (eap->line2 < 1 || eap->line2 > script_items.ga_len) {
EMSG(_(e_invarg));
} else {
eap->arg = SCRIPT_ITEM(eap->line2).sn_name;
do_exedit(eap, NULL);
}
return;
}
for (int i = 1; i <= script_items.ga_len && !got_int; i++) {
if (SCRIPT_ITEM(i).sn_name != NULL) {
home_replace(NULL, SCRIPT_ITEM(i).sn_name,
@ -3506,7 +3517,12 @@ static char *get_locale_val(int what)
}
#endif
// Return true when "lang" starts with a valid language name.
// Rejects NULL, empty string, "C", "C.UTF-8" and others.
static bool is_valid_mess_lang(char *lang)
{
return lang != NULL && ASCII_ISALPHA(lang[0]) && ASCII_ISALPHA(lang[1]);
}
/// Obtain the current messages language. Used to set the default for
/// 'helplang'. May return NULL or an empty string.
@ -3526,14 +3542,14 @@ char *get_mess_lang(void)
# endif
# else
p = os_getenv("LC_ALL");
if (p == NULL) {
if (!is_valid_mess_lang(p)) {
p = os_getenv("LC_MESSAGES");
if (p == NULL) {
if (!is_valid_mess_lang(p)) {
p = os_getenv("LANG");
}
}
# endif
return p;
return is_valid_mess_lang(p) ? p : NULL;
}
// Complicated #if; matches with where get_mess_env() is used below.
@ -3812,7 +3828,13 @@ static void script_host_execute(char *name, exarg_T *eap)
// current range
tv_list_append_number(args, (int)eap->line1);
tv_list_append_number(args, (int)eap->line2);
(void)eval_call_provider(name, "execute", args);
if (!eval_has_provider(name)) {
emsgf("E319: No \"%s\" provider found. Run \":checkhealth provider\"",
name);
} else {
(void)eval_call_provider(name, "execute", args);
}
}
}

View File

@ -1804,15 +1804,19 @@ static char_u * do_one_cmd(char_u **cmdlinep,
errormsg = (char_u *)_(get_text_locked_msg());
goto doend;
}
/* Disallow editing another buffer when "curbuf_lock" is set.
* Do allow ":edit" (check for argument later).
* Do allow ":checktime" (it's postponed). */
// Disallow editing another buffer when "curbuf_lock" is set.
// Do allow ":checktime" (it is postponed).
// Do allow ":edit" (check for an argument later).
// Do allow ":file" with no arguments (check for an argument later).
if (!(ea.argt & CMDWIN)
&& ea.cmdidx != CMD_edit
&& ea.cmdidx != CMD_checktime
&& ea.cmdidx != CMD_edit
&& ea.cmdidx != CMD_file
&& !IS_USER_CMDIDX(ea.cmdidx)
&& curbuf_locked())
&& curbuf_locked()) {
goto doend;
}
if (!ni && !(ea.argt & RANGE) && ea.addr_count > 0) {
/* no range allowed */
@ -1884,6 +1888,11 @@ static char_u * do_one_cmd(char_u **cmdlinep,
else
ea.arg = skipwhite(p);
// ":file" cannot be run with an argument when "curbuf_lock" is set
if (ea.cmdidx == CMD_file && *ea.arg != NUL && curbuf_locked()) {
goto doend;
}
/*
* Check for "++opt=val" argument.
* Must be first, allow ":w ++enc=utf8 !cmd"
@ -8645,7 +8654,10 @@ eval_vars (
break;
case SPEC_AFILE: // file name for autocommand
if (autocmd_fname != NULL && !path_is_absolute(autocmd_fname)) {
if (autocmd_fname != NULL
&& !path_is_absolute(autocmd_fname)
// For CmdlineEnter and related events, <afile> is not a path! #9348
&& !strequal("/", (char *)autocmd_fname)) {
// Still need to turn the fname into a full path. It was
// postponed to avoid a delay when <afile> is not used.
result = (char_u *)FullName_save((char *)autocmd_fname, false);

View File

@ -1804,6 +1804,37 @@ static int empty_pattern(char_u *p)
static int command_line_changed(CommandLineState *s)
{
// Trigger CmdlineChanged autocommands.
if (has_event(EVENT_CMDLINECHANGED)) {
TryState tstate;
Error err = ERROR_INIT;
bool tl_ret = true;
dict_T *dict = get_vim_var_dict(VV_EVENT);
char firstcbuf[2];
firstcbuf[0] = s->firstc > 0 ? s->firstc : '-';
firstcbuf[1] = 0;
// set v:event to a dictionary with information about the commandline
tv_dict_add_str(dict, S_LEN("cmdtype"), firstcbuf);
tv_dict_add_nr(dict, S_LEN("cmdlevel"), ccline.level);
tv_dict_set_keys_readonly(dict);
try_enter(&tstate);
apply_autocmds(EVENT_CMDLINECHANGED, (char_u *)firstcbuf,
(char_u *)firstcbuf, false, curbuf);
tv_dict_clear(dict);
tl_ret = try_leave(&tstate, &err);
if (!tl_ret && ERROR_SET(&err)) {
msg_putchar('\n');
msg_printf_attr(HL_ATTR(HLF_E)|MSG_HIST, (char *)e_autocmd_err, err.msg);
api_clear_error(&err);
redrawcmd();
}
tl_ret = true;
}
// 'incsearch' highlighting.
if (p_is && !cmd_silent && (s->firstc == '/' || s->firstc == '?')) {
pos_T end_pos;

View File

@ -1739,13 +1739,13 @@ failed:
close(0);
#ifndef WIN32
// On Unix, use stderr for stdin, makes shell commands work.
ignored = dup(2);
vim_ignored = dup(2);
#else
// On Windows, use the console input handle for stdin.
HANDLE conin = CreateFile("CONIN$", GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ, (LPSECURITY_ATTRIBUTES)NULL,
OPEN_EXISTING, 0, (HANDLE)NULL);
ignored = _open_osfhandle(conin, _O_RDONLY);
vim_ignored = _open_osfhandle(conin, _O_RDONLY);
#endif
}
@ -4531,48 +4531,83 @@ bool vim_fgets(char_u *buf, int size, FILE *fp) FUNC_ATTR_NONNULL_ALL
}
/// Read 2 bytes from "fd" and turn them into an int, MSB first.
/// Returns -1 when encountering EOF.
int get2c(FILE *fd)
{
int n;
n = getc(fd);
n = (n << 8) + getc(fd);
return n;
const int n = getc(fd);
if (n == EOF) {
return -1;
}
const int c = getc(fd);
if (c == EOF) {
return -1;
}
return (n << 8) + c;
}
/// Read 3 bytes from "fd" and turn them into an int, MSB first.
/// Returns -1 when encountering EOF.
int get3c(FILE *fd)
{
int n;
n = getc(fd);
n = (n << 8) + getc(fd);
n = (n << 8) + getc(fd);
return n;
int n = getc(fd);
if (n == EOF) {
return -1;
}
int c = getc(fd);
if (c == EOF) {
return -1;
}
n = (n << 8) + c;
c = getc(fd);
if (c == EOF) {
return -1;
}
return (n << 8) + c;
}
/// Read 4 bytes from "fd" and turn them into an int, MSB first.
/// Returns -1 when encountering EOF.
int get4c(FILE *fd)
{
// Use unsigned rather than int otherwise result is undefined
// when left-shift sets the MSB.
unsigned n;
n = (unsigned)getc(fd);
n = (n << 8) + (unsigned)getc(fd);
n = (n << 8) + (unsigned)getc(fd);
n = (n << 8) + (unsigned)getc(fd);
int c = getc(fd);
if (c == EOF) {
return -1;
}
n = (unsigned)c;
c = getc(fd);
if (c == EOF) {
return -1;
}
n = (n << 8) + (unsigned)c;
c = getc(fd);
if (c == EOF) {
return -1;
}
n = (n << 8) + (unsigned)c;
c = getc(fd);
if (c == EOF) {
return -1;
}
n = (n << 8) + (unsigned)c;
return (int)n;
}
/// Read 8 bytes from `fd` and turn them into a time_t, MSB first.
/// Returns -1 when encountering EOF.
time_t get8ctime(FILE *fd)
{
time_t n = 0;
int i;
for (i = 0; i < 8; i++) {
n = (n << 8) + getc(fd);
for (int i = 0; i < 8; i++) {
const int c = getc(fd);
if (c == EOF) {
return -1;
}
n = (n << 8) + c;
}
return n;
}
@ -5932,19 +5967,19 @@ void au_event_restore(char_u *old_ei)
* will be automatically executed for <event>
* when editing a file matching <pat>, in
* the current group.
* :autocmd <event> <pat> Show the auto-commands associated with
* :autocmd <event> <pat> Show the autocommands associated with
* <event> and <pat>.
* :autocmd <event> Show the auto-commands associated with
* :autocmd <event> Show the autocommands associated with
* <event>.
* :autocmd Show all auto-commands.
* :autocmd! <event> <pat> <cmd> Remove all auto-commands associated with
* :autocmd Show all autocommands.
* :autocmd! <event> <pat> <cmd> Remove all autocommands associated with
* <event> and <pat>, and add the command
* <cmd>, for the current group.
* :autocmd! <event> <pat> Remove all auto-commands associated with
* :autocmd! <event> <pat> Remove all autocommands associated with
* <event> and <pat> for the current group.
* :autocmd! <event> Remove all auto-commands associated with
* :autocmd! <event> Remove all autocommands associated with
* <event> for the current group.
* :autocmd! Remove ALL auto-commands for the current
* :autocmd! Remove ALL autocommands for the current
* group.
*
* Multiple events and patterns may be given separated by commas. Here are
@ -6037,8 +6072,8 @@ void do_autocmd(char_u *arg_in, int forceit)
* Print header when showing autocommands.
*/
if (!forceit && *cmd == NUL) {
/* Highlight title */
MSG_PUTS_TITLE(_("\n--- Auto-Commands ---"));
// Highlight title
MSG_PUTS_TITLE(_("\n--- Autocommands ---"));
}
/*
@ -6868,7 +6903,13 @@ static bool apply_autocmds_group(event_T event, char_u *fname, char_u *fname_io,
} else {
sfname = vim_strsave(fname);
// Don't try expanding the following events.
if (event == EVENT_COLORSCHEME
if (event == EVENT_CMDLINECHANGED
|| event == EVENT_CMDLINEENTER
|| event == EVENT_CMDLINELEAVE
|| event == EVENT_CMDWINENTER
|| event == EVENT_CMDWINLEAVE
|| event == EVENT_CMDUNDEFINED
|| event == EVENT_COLORSCHEME
|| event == EVENT_COLORSCHEMEPRE
|| event == EVENT_DIRCHANGED
|| event == EVENT_FILETYPE
@ -6907,8 +6948,8 @@ static bool apply_autocmds_group(event_T event, char_u *fname, char_u *fname_io,
autocmd_match = fname;
/* Don't redraw while doing auto commands. */
++RedrawingDisabled;
// Don't redraw while doing autocommands.
RedrawingDisabled++;
save_sourcing_name = sourcing_name;
sourcing_name = NULL; /* don't free this one */
save_sourcing_lnum = sourcing_lnum;
@ -7119,7 +7160,7 @@ auto_next_pat (
apc->tail, ap->allow_dirs)
: ap->buflocal_nr == apc->arg_bufnr) {
const char *const name = event_nr2name(apc->event);
s = _("%s Auto commands for \"%s\"");
s = _("%s Autocommands for \"%s\"");
const size_t sourcing_name_len = (STRLEN(s) + strlen(name) + ap->patlen
+ 1);
sourcing_name = xmalloc(sourcing_name_len);

View File

@ -171,9 +171,8 @@ bool hasFoldingWin(
int low_level = 0;
checkupdate(win);
/*
* Return quickly when there is no folding at all in this window.
*/
// Return quickly when there is no folding at all in this window.
if (!hasAnyFolding(win)) {
if (infop != NULL)
infop->fi_level = 0;
@ -2851,8 +2850,9 @@ static void foldlevelIndent(fline_T *flp)
flp->lvl = 0;
else
flp->lvl = -1;
} else
flp->lvl = get_indent_buf(buf, lnum) / get_sw_value(curbuf);
} else {
flp->lvl = get_indent_buf(buf, lnum) / get_sw_value(buf);
}
if (flp->lvl > flp->wp->w_p_fdn) {
flp->lvl = (int) MAX(0, flp->wp->w_p_fdn);
}

View File

@ -1125,8 +1125,7 @@ EXTERN FILE *time_fd INIT(= NULL); /* where to write startup timing */
* can't do anything useful with the value. Assign to this variable to avoid
* the warning.
*/
EXTERN int ignored;
EXTERN char *ignoredp;
EXTERN int vim_ignored;
// Start a msgpack-rpc channel over stdin/stdout.
EXTERN bool embedded_mode INIT(= false);

View File

@ -177,8 +177,27 @@ void update_window_hl(win_T *wp, bool invalid)
}
}
/// Gets HL_UNDERLINE highlight.
int hl_get_underline(void)
{
return get_attr_entry((HlEntry){
.attr = (HlAttrs){
.cterm_ae_attr = (int16_t)HL_UNDERLINE,
.cterm_fg_color = 0,
.cterm_bg_color = 0,
.rgb_ae_attr = (int16_t)HL_UNDERLINE,
.rgb_fg_color = -1,
.rgb_bg_color = -1,
.rgb_sp_color = -1,
},
.kind = kHlUI,
.id1 = 0,
.id2 = 0,
});
}
/// Get attribute code for forwarded :terminal highlights.
int get_term_attr_entry(HlAttrs *aep)
int hl_get_term_attr(HlAttrs *aep)
{
return get_attr_entry((HlEntry){ .attr= *aep, .kind = kHlTerminal,
.id1 = 0, .id2 = 0 });

View File

@ -22,7 +22,7 @@ typedef enum {
/// Stores a complete highlighting entry, including colors and attributes
/// for both TUI and GUI.
typedef struct attr_entry {
int16_t rgb_ae_attr, cterm_ae_attr; // HL_BOLD, etc.
int16_t rgb_ae_attr, cterm_ae_attr; ///< HlAttrFlags
RgbValue rgb_fg_color, rgb_bg_color, rgb_sp_color;
int cterm_fg_color, cterm_bg_color;
} HlAttrs;
@ -37,17 +37,6 @@ typedef struct attr_entry {
.cterm_bg_color = 0, \
}
// sentinel value that compares unequal to any valid highlight
#define HLATTRS_INVALID (HlAttrs) { \
.rgb_ae_attr = -1, \
.cterm_ae_attr = -1, \
.rgb_fg_color = -1, \
.rgb_bg_color = -1, \
.rgb_sp_color = -1, \
.cterm_fg_color = 0, \
.cterm_bg_color = 0, \
}
/// Values for index in highlight_attr[].
/// When making changes, also update hlf_names below!
typedef enum {
@ -94,8 +83,8 @@ typedef enum {
, HLF_TP // tabpage line
, HLF_TPS // tabpage line selected
, HLF_TPF // tabpage line filler
, HLF_CUC // 'cursurcolumn'
, HLF_CUL // 'cursurline'
, HLF_CUC // 'cursorcolumn'
, HLF_CUL // 'cursorline'
, HLF_MC // 'colorcolumn'
, HLF_QFL // selected quickfix line
, HLF_0 // Whitespace

View File

@ -73,6 +73,7 @@
#ifndef WIN32
# include "nvim/os/pty_process_unix.h"
#endif
#include "nvim/api/vim.h"
// Maximum number of commands from + or -c arguments.
#define MAX_ARG_CMDS 10
@ -150,6 +151,8 @@ void event_init(void)
signal_init();
// finish mspgack-rpc initialization
channel_init();
remote_ui_init();
api_vim_init();
terminal_init();
}
@ -1719,6 +1722,48 @@ static void exe_commands(mparm_T *parmp)
TIME_MSG("executing command arguments");
}
/// Source system-wide vimrc if built with one defined
///
/// Does one of the following things, stops after whichever succeeds:
///
/// 1. Source system vimrc file from $XDG_CONFIG_DIRS/nvim/sysinit.vim
/// 2. Source system vimrc file from $VIM
static void do_system_initialization(void)
{
char *const config_dirs = stdpaths_get_xdg_var(kXDGConfigDirs);
if (config_dirs != NULL) {
const void *iter = NULL;
const char path_tail[] = {
'n', 'v', 'i', 'm', PATHSEP,
's', 'y', 's', 'i', 'n', 'i', 't', '.', 'v', 'i', 'm', NUL
};
do {
const char *dir;
size_t dir_len;
iter = vim_env_iter(':', config_dirs, iter, &dir, &dir_len);
if (dir == NULL || dir_len == 0) {
break;
}
char *vimrc = xmalloc(dir_len + sizeof(path_tail) + 1);
memcpy(vimrc, dir, dir_len);
vimrc[dir_len] = PATHSEP;
memcpy(vimrc + dir_len + 1, path_tail, sizeof(path_tail));
if (do_source((char_u *)vimrc, false, DOSO_NONE) != FAIL) {
xfree(vimrc);
xfree(config_dirs);
return;
}
xfree(vimrc);
} while (iter != NULL);
xfree(config_dirs);
}
#ifdef SYS_VIMRC_FILE
// Get system wide defaults, if the file name is defined.
(void)do_source((char_u *)SYS_VIMRC_FILE, false, DOSO_NONE);
#endif
}
/// Source vimrc or do other user initialization
///
/// Does one of the following things, stops after whichever succeeds:
@ -1801,10 +1846,7 @@ static void source_startup_scripts(const mparm_T *const parmp)
}
}
} else if (!silent_mode) {
#ifdef SYS_VIMRC_FILE
// Get system wide defaults, if the file name is defined.
(void) do_source((char_u *)SYS_VIMRC_FILE, false, DOSO_NONE);
#endif
do_system_initialization();
if (do_user_initialization()) {
// Read initialization commands from ".vimrc" or ".exrc" in current

View File

@ -166,3 +166,4 @@ MAP_IMPL(handle_T, ptr_t, DEFAULT_INITIALIZER)
MAP_IMPL(String, MsgpackRpcRequestHandler, MSGPACK_HANDLER_INITIALIZER)
#define KVEC_INITIALIZER { .size = 0, .capacity = 0, .items = NULL }
MAP_IMPL(HlEntry, int, DEFAULT_INITIALIZER)
MAP_IMPL(String, handle_T, 0)

View File

@ -37,6 +37,7 @@ MAP_DECLS(uint64_t, ptr_t)
MAP_DECLS(handle_T, ptr_t)
MAP_DECLS(String, MsgpackRpcRequestHandler)
MAP_DECLS(HlEntry, int)
MAP_DECLS(String, handle_T)
#define map_new(T, U) map_##T##_##U##_new
#define map_free(T, U) map_##T##_##U##_free

View File

@ -16,6 +16,7 @@
#include "nvim/message.h"
#include "nvim/misc1.h"
#include "nvim/ui.h"
#include "nvim/api/vim.h"
#ifdef HAVE_JEMALLOC
// Force je_ prefix on jemalloc functions.
@ -681,6 +682,7 @@ void free_all_mem(void)
break;
eval_clear();
api_vim_free_all_mem();
// Free all buffers. Reset 'autochdir' to avoid accessing things that
// were freed already.

View File

@ -505,7 +505,7 @@ int emsg(const char_u *s_)
*/
if (cause_errthrow((char_u *)s, severe, &ignore) == true) {
if (!ignore) {
did_emsg = true;
did_emsg++;
}
return true;
}
@ -554,7 +554,7 @@ int emsg(const char_u *s_)
} else {
flush_buffers(FLUSH_MINIMAL); // flush internal buffers
}
did_emsg = true; // flag for DoOneCmd()
did_emsg++; // flag for DoOneCmd()
}
emsg_on_display = true; // remember there is an error message
@ -1896,6 +1896,9 @@ static void msg_scroll_up(void)
} else {
screen_del_lines(0, 1, (int)Rows, 0, Columns);
}
// TODO(bfredl): when msgsep display is properly batched, this fill should be
// eliminated.
screen_fill(Rows-1, Rows, 0, (int)Columns, ' ', ' ', 0);
}
/*
@ -2311,6 +2314,7 @@ static int do_more_prompt(int typed_char)
if (toscroll == -1
&& screen_ins_lines(0, 1, (int)Rows, 0, (int)Columns) == OK) {
screen_fill(0, 1, 0, (int)Columns, ' ', ' ', 0);
// display line at top
(void)disp_sb_line(0, mp);
} else {
@ -2821,7 +2825,6 @@ do_dialog (
Ex command */
)
{
int oldState;
int retval = 0;
char_u *hotkeys;
int c;
@ -2834,7 +2837,10 @@ do_dialog (
}
oldState = State;
int save_msg_silent = msg_silent;
int oldState = State;
msg_silent = 0; // If dialog prompts for input, user needs to see it! #8788
State = CONFIRM;
setmouse();
@ -2887,6 +2893,7 @@ do_dialog (
xfree(hotkeys);
msg_silent = save_msg_silent;
State = oldState;
setmouse();
--no_wait_return;

View File

@ -52,6 +52,7 @@
#include "nvim/window.h"
#include "nvim/os/os.h"
#include "nvim/os/shell.h"
#include "nvim/os/signal.h"
#include "nvim/os/input.h"
#include "nvim/os/time.h"
#include "nvim/event/stream.h"
@ -1121,8 +1122,9 @@ int get_last_leader_offset(char_u *line, char_u **flags)
if (ascii_iswhite(string[0])) {
if (i == 0 || !ascii_iswhite(line[i - 1]))
continue;
while (ascii_iswhite(string[0]))
++string;
while (ascii_iswhite(*string)) {
string++;
}
}
for (j = 0; string[j] != NUL && string[j] == line[i + j]; ++j)
/* do nothing */;
@ -1138,6 +1140,19 @@ int get_last_leader_offset(char_u *line, char_u **flags)
continue;
}
if (vim_strchr(part_buf, COM_MIDDLE) != NULL) {
// For a middlepart comment, only consider it to match if
// everything before the current position in the line is
// whitespace. Otherwise we would think we are inside a
// comment if the middle part appears somewhere in the middle
// of the line. E.g. for C the "*" appears often.
for (j = 0; ascii_iswhite(line[j]) && j <= i; j++) {
}
if (j < i) {
continue;
}
}
/*
* We have found a match, stop searching.
*/
@ -1936,10 +1951,10 @@ changed_lines(
{
changed_lines_buf(curbuf, lnum, lnume, xtra);
if (xtra == 0 && curwin->w_p_diff) {
/* When the number of lines doesn't change then mark_adjust() isn't
* called and other diff buffers still need to be marked for
* displaying. */
if (xtra == 0 && curwin->w_p_diff && !diff_internal()) {
// When the number of lines doesn't change then mark_adjust() isn't
// called and other diff buffers still need to be marked for
// displaying.
linenr_T wlnum;
FOR_ALL_WINDOWS_IN_TAB(wp, curtab) {
@ -2008,6 +2023,10 @@ static void changed_common(linenr_T lnum, colnr_T col, linenr_T lnume, long xtra
/* mark the buffer as modified */
changed();
if (curwin->w_p_diff && diff_internal()) {
curtab->tp_diff_update = true;
}
/* set the '. mark */
if (!cmdmod.keepjumps) {
RESET_FMARK(&curbuf->b_last_change, ((pos_T) {lnum, col, 0}), 0);
@ -2653,6 +2672,8 @@ void preserve_exit(void)
}
really_exiting = true;
// Ignore SIGHUP while we are already exiting. #9274
signal_reject_deadly();
mch_errmsg(IObuff);
mch_errmsg("\n");
ui_flush();

View File

@ -918,9 +918,9 @@ void curs_columns(
extra = ((int)prev_skipcol - (int)curwin->w_skipcol) / width;
if (extra > 0) {
win_ins_lines(curwin, 0, extra, false);
win_ins_lines(curwin, 0, extra);
} else if (extra < 0) {
win_del_lines(curwin, 0, -extra, false);
win_del_lines(curwin, 0, -extra);
}
} else {
curwin->w_skipcol = 0;

View File

@ -641,7 +641,16 @@ static WBuffer *serialize_response(uint64_t channel_id,
{
msgpack_packer pac;
msgpack_packer_init(&pac, sbuffer, msgpack_sbuffer_write);
msgpack_rpc_serialize_response(response_id, err, arg, &pac);
if (ERROR_SET(err) && response_id == NO_RESPONSE) {
Array args = ARRAY_DICT_INIT;
ADD(args, INTEGER_OBJ(err->type));
ADD(args, STRING_OBJ(cstr_to_string(err->msg)));
msgpack_rpc_serialize_request(0, cstr_as_string("nvim_error_event"),
args, &pac);
api_free_array(args);
} else {
msgpack_rpc_serialize_response(response_id, err, arg, &pac);
}
log_server_msg(channel_id, sbuffer);
WBuffer *rv = wstream_new_buffer(xmemdup(sbuffer->data, sbuffer->size),
sbuffer->size,

View File

@ -1325,6 +1325,14 @@ static int normal_check(VimState *state)
normal_check_cursor_moved(s);
normal_check_text_changed(s);
// Updating diffs from changed() does not always work properly,
// esp. updating folds. Do an update just before redrawing if
// needed.
if (curtab->tp_diff_update || curtab->tp_diff_invalid) {
ex_diffupdate(NULL);
curtab->tp_diff_update = false;
}
// Scroll-binding for diff mode may have been postponed until
// here. Avoids doing it for every change.
if (diff_need_scrollbind) {

View File

@ -1068,6 +1068,10 @@ void set_helplang_default(const char *lang)
if (STRNICMP(p_hlg, "zh_", 3) == 0 && STRLEN(p_hlg) >= 5) {
p_hlg[0] = (char_u)TOLOWER_ASC(p_hlg[3]);
p_hlg[1] = (char_u)TOLOWER_ASC(p_hlg[4]);
} else if (STRLEN(p_hlg) >= 1 && *p_hlg == 'C') {
// any C like setting, such as C.UTF-8, becomes "en"
p_hlg[0] = 'e';
p_hlg[1] = 'n';
}
p_hlg[2] = NUL;
options[idx].flags |= P_ALLOCED;
@ -1769,14 +1773,13 @@ do_set (
// Set the new value.
*(char_u **)(varp) = newval;
if (!starting && origval != NULL && newval != NULL) {
// origval may be freed by
// did_set_string_option(), make a copy.
saved_origval = xstrdup((char *)origval);
// newval (and varp) may become invalid if the
// buffer is closed by autocommands.
saved_newval = xstrdup((char *)newval);
}
// origval may be freed by
// did_set_string_option(), make a copy.
saved_origval = (origval != NULL) ? xstrdup((char *)origval) : 0;
// newval (and varp) may become invalid if the
// buffer is closed by autocommands.
saved_newval = (newval != NULL) ? xstrdup((char *)newval) : 0;
// Handle side effects, and set the global value for
// ":set" on local options. Note: when setting 'syntax'
@ -1786,8 +1789,14 @@ do_set (
new_value_alloced, oldval, errbuf, opt_flags);
if (errmsg == NULL) {
trigger_optionsset_string(opt_idx, opt_flags, saved_origval,
saved_newval);
if (!starting) {
trigger_optionsset_string(opt_idx, opt_flags, saved_origval,
saved_newval);
}
if (options[opt_idx].flags & P_UI_OPTION) {
ui_call_option_set(cstr_as_string(options[opt_idx].fullname),
STRING_OBJ(cstr_as_string(saved_newval)));
}
}
xfree(saved_origval);
xfree(saved_newval);
@ -2378,8 +2387,8 @@ static char *set_string_option(const int opt_idx, const char *const value,
char *const oldval = *varp;
*varp = s;
char *const saved_oldval = (starting ? NULL : xstrdup(oldval));
char *const saved_newval = (starting ? NULL : xstrdup(s));
char *const saved_oldval = xstrdup(oldval);
char *const saved_newval = xstrdup(s);
char *const r = (char *)did_set_string_option(
opt_idx, (char_u **)varp, (int)true, (char_u *)oldval, NULL, opt_flags);
@ -2389,8 +2398,13 @@ static char *set_string_option(const int opt_idx, const char *const value,
// call autocommand after handling side effects
if (r == NULL) {
trigger_optionsset_string(opt_idx, opt_flags,
saved_oldval, saved_newval);
if (!starting) {
trigger_optionsset_string(opt_idx, opt_flags, saved_oldval, saved_newval);
}
if (options[opt_idx].flags & P_UI_OPTION) {
ui_call_option_set(cstr_as_string(options[opt_idx].fullname),
STRING_OBJ(cstr_as_string(saved_newval)));
}
}
xfree(saved_oldval);
xfree(saved_newval);
@ -4056,10 +4070,11 @@ static char *set_bool_option(const int opt_idx, char_u *const varp,
(char_u *) options[opt_idx].fullname,
NULL, false, NULL);
reset_v_option_vars();
if (options[opt_idx].flags & P_UI_OPTION) {
ui_call_option_set(cstr_as_string(options[opt_idx].fullname),
BOOLEAN_OBJ(value));
}
}
if (options[opt_idx].flags & P_UI_OPTION) {
ui_call_option_set(cstr_as_string(options[opt_idx].fullname),
BOOLEAN_OBJ(value));
}
comp_col(); /* in case 'ruler' or 'showcmd' changed */
@ -4429,10 +4444,11 @@ static char *set_num_option(int opt_idx, char_u *varp, long value,
(char_u *) options[opt_idx].fullname,
NULL, false, NULL);
reset_v_option_vars();
if (options[opt_idx].flags & P_UI_OPTION) {
ui_call_option_set(cstr_as_string(options[opt_idx].fullname),
INTEGER_OBJ(value));
}
}
if (errmsg == NULL && options[opt_idx].flags & P_UI_OPTION) {
ui_call_option_set(cstr_as_string(options[opt_idx].fullname),
INTEGER_OBJ(value));
}
comp_col(); /* in case 'columns' or 'ls' changed */
@ -4461,10 +4477,6 @@ static void trigger_optionsset_string(int opt_idx, int opt_flags,
apply_autocmds(EVENT_OPTIONSET,
(char_u *)options[opt_idx].fullname, NULL, false, NULL);
reset_v_option_vars();
if (options[opt_idx].flags & P_UI_OPTION) {
ui_call_option_set(cstr_as_string(options[opt_idx].fullname),
STRING_OBJ(cstr_as_string(newval)));
}
}
}

View File

@ -132,10 +132,10 @@ return {
{
full_name='background', abbreviation='bg',
type='string', scope={'global'},
vi_def=true,
vim=true,
redraw={'all_windows'},
varname='p_bg',
defaults={if_true={vi="light"}}
defaults={if_true={vi="light",vim="dark"}}
},
{
full_name='backspace', abbreviation='bs',
@ -615,7 +615,7 @@ return {
alloced=true,
redraw={'current_window'},
varname='p_dip',
defaults={if_true={vi="filler"}}
defaults={if_true={vi="internal,filler"}}
},
{
full_name='digraph', abbreviation='dg',

View File

@ -110,7 +110,7 @@ bool os_isrealdir(const char *name)
/// Check if the given path is a directory or not.
///
/// @return `true` if `fname` is a directory.
/// @return `true` if `name` is a directory.
bool os_isdir(const char_u *name)
FUNC_ATTR_NONNULL_ALL
{
@ -126,6 +126,25 @@ bool os_isdir(const char_u *name)
return true;
}
/// Check if the given path is a directory and is executable.
/// Gives the same results as `os_isdir()` on Windows.
///
/// @return `true` if `name` is a directory and executable.
bool os_isdir_executable(const char *name)
FUNC_ATTR_NONNULL_ALL
{
int32_t mode = os_getperm((const char *)name);
if (mode < 0) {
return false;
}
#ifdef WIN32
return (S_ISDIR(mode));
#else
return (S_ISDIR(mode) && (S_IXUSR & mode));
#endif
}
/// Check what `name` is:
/// @return NODE_NORMAL: file or directory (or doesn't exist)
/// NODE_WRITABLE: writable device, socket, fifo, etc.

View File

@ -17,14 +17,31 @@ void lang_init(void)
{
#ifdef __APPLE__
if (os_getenv("LANG") == NULL) {
CFLocaleRef cf_locale = CFLocaleCopyCurrent();
CFTypeRef cf_lang_region = CFLocaleGetValue(cf_locale,
kCFLocaleIdentifier);
CFRetain(cf_lang_region);
CFRelease(cf_locale);
const char *lang_region = NULL;
CFTypeRef cf_lang_region = NULL;
CFLocaleRef cf_locale = CFLocaleCopyCurrent();
if (cf_locale) {
cf_lang_region = CFLocaleGetValue(cf_locale, kCFLocaleIdentifier);
CFRetain(cf_lang_region);
lang_region = CFStringGetCStringPtr(cf_lang_region,
kCFStringEncodingUTF8);
CFRelease(cf_locale);
} else {
// Use the primary language defined in Preferences -> Language & Region
CFArrayRef cf_langs = CFLocaleCopyPreferredLanguages();
if (cf_langs && CFArrayGetCount(cf_langs) > 0) {
cf_lang_region = CFArrayGetValueAtIndex(cf_langs, 0);
CFRetain(cf_lang_region);
CFRelease(cf_langs);
lang_region = CFStringGetCStringPtr(cf_lang_region,
kCFStringEncodingUTF8);
} else {
ELOG("$LANG is empty and your primary language cannot be inferred.");
return;
}
}
const char *lang_region = CFStringGetCStringPtr(cf_lang_region,
kCFStringEncodingUTF8);
if (lang_region) {
os_setenv("LANG", lang_region, true);
} else {
@ -37,6 +54,11 @@ void lang_init(void)
CFRelease(cf_lang_region);
# ifdef HAVE_LOCALE_H
setlocale(LC_ALL, "");
# ifdef LC_NUMERIC
// Make sure strtod() uses a decimal point, not a comma.
setlocale(LC_NUMERIC, "C");
# endif
# endif
}
#endif

View File

@ -12,7 +12,7 @@
#include <sys/ioctl.h>
// forkpty is not in POSIX, so headers are platform-specific
#if defined(__FreeBSD__) || defined (__DragonFly__)
#if defined(__FreeBSD__) || defined(__DragonFly__)
# include <libutil.h>
#elif defined(__OpenBSD__) || defined(__NetBSD__) || defined(__APPLE__)
# include <util.h>

View File

@ -8,6 +8,7 @@ if(NOT LANGUAGES)
af
ca
cs
da
de
en_GB
eo

Some files were not shown because too many files have changed in this diff Show More