mirror of
https://github.com/neovim/neovim.git
synced 2025-02-25 18:55:25 -06:00
Merge branch 'master' into expression-parser
This commit is contained in:
commit
76f0466536
@ -7,6 +7,10 @@ end_of_line = lf
|
|||||||
insert_final_newline = true
|
insert_final_newline = true
|
||||||
charset = utf_8
|
charset = utf_8
|
||||||
|
|
||||||
|
[runtime/doc/*.txt]
|
||||||
|
indent_style = tab
|
||||||
|
indent_size = 8
|
||||||
|
|
||||||
[Makefile]
|
[Makefile]
|
||||||
indent_style = tab
|
indent_style = tab
|
||||||
tab_width = 4
|
tab_width = 4
|
||||||
|
1
.gitignore
vendored
1
.gitignore
vendored
@ -1,5 +1,6 @@
|
|||||||
# Build/deps dir
|
# Build/deps dir
|
||||||
/build/
|
/build/
|
||||||
|
/cmake-build-debug/
|
||||||
/dist/
|
/dist/
|
||||||
/.deps/
|
/.deps/
|
||||||
/tmp/
|
/tmp/
|
||||||
|
4
BSDmakefile
Normal file
4
BSDmakefile
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
.DONE:
|
||||||
|
@echo "Please use GNU Make (gmake) to build neovim"
|
||||||
|
.DEFAULT:
|
||||||
|
@echo "Please use GNU Make (gmake) to build neovim"
|
@ -254,7 +254,10 @@ if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
|
|||||||
if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS "4.8.5")
|
if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS "4.8.5")
|
||||||
# Array-bounds testing is broken in some GCC versions before 4.8.5.
|
# Array-bounds testing is broken in some GCC versions before 4.8.5.
|
||||||
# https://gcc.gnu.org/bugzilla/show_bug.cgi?id=56273
|
# https://gcc.gnu.org/bugzilla/show_bug.cgi?id=56273
|
||||||
add_definitions(-Wno-array-bounds)
|
check_c_compiler_flag(-Wno-array-bounds HAS_NO_ARRAY_BOUNDS_FLAG)
|
||||||
|
if(HAS_NO_ARRAY_BOUNDS_FLAG)
|
||||||
|
add_definitions(-Wno-array-bounds)
|
||||||
|
endif()
|
||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
@ -344,6 +347,21 @@ if(FEAT_TUI)
|
|||||||
find_package(Unibilium REQUIRED)
|
find_package(Unibilium REQUIRED)
|
||||||
include_directories(SYSTEM ${UNIBILIUM_INCLUDE_DIRS})
|
include_directories(SYSTEM ${UNIBILIUM_INCLUDE_DIRS})
|
||||||
|
|
||||||
|
list(APPEND CMAKE_REQUIRED_INCLUDES "${UNIBILIUM_INCLUDE_DIRS}")
|
||||||
|
list(APPEND CMAKE_REQUIRED_LIBRARIES "${UNIBILIUM_LIBRARIES}")
|
||||||
|
check_c_source_compiles("
|
||||||
|
#include <unibilium.h>
|
||||||
|
|
||||||
|
int
|
||||||
|
main(void)
|
||||||
|
{
|
||||||
|
return unibi_num_from_var(unibi_var_from_num(0));
|
||||||
|
}
|
||||||
|
" UNIBI_HAS_VAR_FROM)
|
||||||
|
if(UNIBI_HAS_VAR_FROM)
|
||||||
|
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DNVIM_UNIBI_HAS_VAR_FROM")
|
||||||
|
endif()
|
||||||
|
|
||||||
find_package(LibTermkey REQUIRED)
|
find_package(LibTermkey REQUIRED)
|
||||||
include_directories(SYSTEM ${LIBTERMKEY_INCLUDE_DIRS})
|
include_directories(SYSTEM ${LIBTERMKEY_INCLUDE_DIRS})
|
||||||
endif()
|
endif()
|
||||||
|
27
README.md
27
README.md
@ -48,17 +48,24 @@ and [more](https://github.com/neovim/neovim/wiki/Installing-Neovim)!
|
|||||||
Project layout
|
Project layout
|
||||||
--------------
|
--------------
|
||||||
|
|
||||||
├─ ci/ Build server scripts
|
├─ ci/ build automation
|
||||||
├─ cmake/ Build scripts
|
├─ cmake/ build scripts
|
||||||
├─ runtime/ User plugins/docs
|
├─ runtime/ user plugins/docs
|
||||||
├─ src/ Source code
|
├─ src/ application source code (see src/nvim/README.md)
|
||||||
├─ third-party/ CMake subproject to build dependencies
|
│ ├─ api/ API subsystem
|
||||||
└─ test/ Test code
|
│ ├─ eval/ VimL subsystem
|
||||||
|
│ ├─ event/ event-loop subsystem
|
||||||
|
│ ├─ generators/ code generation (pre-compilation)
|
||||||
|
│ ├─ lib/ generic data structures
|
||||||
|
│ ├─ lua/ lua subsystem
|
||||||
|
│ ├─ msgpack_rpc/ RPC subsystem
|
||||||
|
│ ├─ os/ low-level platform code
|
||||||
|
│ └─ tui/ built-in UI
|
||||||
|
├─ third-party/ cmake subproject to build dependencies
|
||||||
|
└─ test/ tests (see test/README.md)
|
||||||
|
|
||||||
- `third-party/` is activated if `USE_BUNDLED_DEPS` is undefined or the
|
- To disable `third-party/` specify `USE_BUNDLED_DEPS=NO` or `USE_BUNDLED=NO`
|
||||||
`USE_BUNDLED` CMake option is true.
|
(CMake option).
|
||||||
- [Source README](src/nvim/README.md)
|
|
||||||
- [Test README](test/README.md)
|
|
||||||
|
|
||||||
Features
|
Features
|
||||||
--------
|
--------
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
version: '{build}'
|
version: '{build}'
|
||||||
|
environment:
|
||||||
|
APPVEYOR_CACHE_ENTRY_ZIP_ARGS: "-t7z -m0=lzma -mx=9"
|
||||||
configuration:
|
configuration:
|
||||||
- MINGW_64
|
- MINGW_64
|
||||||
- MINGW_32
|
- MINGW_32
|
||||||
|
@ -11,6 +11,18 @@ if [[ "${TRAVIS_OS_NAME}" == osx ]]; then
|
|||||||
brew update
|
brew update
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
echo 'python info:'
|
||||||
|
(
|
||||||
|
2>&1 python --version || true
|
||||||
|
2>&1 python2 --version || true
|
||||||
|
2>&1 python3 --version || true
|
||||||
|
2>&1 pip --version || true
|
||||||
|
2>&1 pip2 --version || true
|
||||||
|
2>&1 pip3 --version || true
|
||||||
|
echo 'pyenv versions:'
|
||||||
|
2>&1 pyenv versions || true
|
||||||
|
) | sed 's/^/ /'
|
||||||
|
|
||||||
echo "Upgrade Python 2 pip."
|
echo "Upgrade Python 2 pip."
|
||||||
pip2.7 -q install --user --upgrade pip
|
pip2.7 -q install --user --upgrade pip
|
||||||
|
|
||||||
@ -21,5 +33,7 @@ if [[ "${TRAVIS_OS_NAME}" == osx ]]; then
|
|||||||
pip3 -q install --user --upgrade pip
|
pip3 -q install --user --upgrade pip
|
||||||
else
|
else
|
||||||
echo "Upgrade Python 3 pip."
|
echo "Upgrade Python 3 pip."
|
||||||
pip3 -q install --user --upgrade pip
|
# Allow failure. pyenv pip3 on travis is broken:
|
||||||
|
# https://github.com/travis-ci/travis-ci/issues/8363
|
||||||
|
pip3 -q install --user --upgrade pip || true
|
||||||
fi
|
fi
|
||||||
|
@ -17,7 +17,9 @@ echo "Install neovim module and coveralls for Python 2."
|
|||||||
CC=cc pip2.7 -q install --user --upgrade neovim cpp-coveralls
|
CC=cc pip2.7 -q install --user --upgrade neovim cpp-coveralls
|
||||||
|
|
||||||
echo "Install neovim module for Python 3."
|
echo "Install neovim module for Python 3."
|
||||||
CC=cc pip3 -q install --user --upgrade neovim
|
# Allow failure. pyenv pip3 on travis is broken:
|
||||||
|
# https://github.com/travis-ci/travis-ci/issues/8363
|
||||||
|
CC=cc pip3 -q install --user --upgrade neovim || true
|
||||||
|
|
||||||
echo "Install neovim RubyGem."
|
echo "Install neovim RubyGem."
|
||||||
gem install --no-document --version ">= 0.2.0" neovim
|
gem install --no-document --version ">= 0.2.0" neovim
|
||||||
|
@ -46,6 +46,7 @@ check_c_source_compiles("
|
|||||||
|
|
||||||
int main(int argc, char** argv) {
|
int main(int argc, char** argv) {
|
||||||
gettext(\"foo\");
|
gettext(\"foo\");
|
||||||
|
ngettext(\"foo\", \"bar\", 1);
|
||||||
bindtextdomain(\"foo\", \"bar\");
|
bindtextdomain(\"foo\", \"bar\");
|
||||||
bind_textdomain_codeset(\"foo\", \"bar\");
|
bind_textdomain_codeset(\"foo\", \"bar\");
|
||||||
textdomain(\"foo\");
|
textdomain(\"foo\");
|
||||||
|
@ -71,6 +71,7 @@ foreach(DF ${DOCFILES})
|
|||||||
endforeach()
|
endforeach()
|
||||||
|
|
||||||
add_custom_target(helptags
|
add_custom_target(helptags
|
||||||
|
COMMAND ${CMAKE_COMMAND} -E remove_directory ${GENERATED_RUNTIME_DIR}/doc
|
||||||
COMMAND ${CMAKE_COMMAND} -E copy_directory
|
COMMAND ${CMAKE_COMMAND} -E copy_directory
|
||||||
${PROJECT_SOURCE_DIR}/runtime/doc ${GENERATED_RUNTIME_DIR}/doc
|
${PROJECT_SOURCE_DIR}/runtime/doc ${GENERATED_RUNTIME_DIR}/doc
|
||||||
COMMAND "${PROJECT_BINARY_DIR}/bin/nvim"
|
COMMAND "${PROJECT_BINARY_DIR}/bin/nvim"
|
||||||
|
@ -1,15 +1,15 @@
|
|||||||
function! s:enhance_syntax() abort
|
function! s:enhance_syntax() abort
|
||||||
syntax case match
|
syntax case match
|
||||||
|
|
||||||
syntax keyword healthError ERROR
|
syntax keyword healthError ERROR[:]
|
||||||
\ containedin=markdownCodeBlock,mkdListItemLine
|
\ containedin=markdownCodeBlock,mkdListItemLine
|
||||||
highlight link healthError Error
|
highlight link healthError Error
|
||||||
|
|
||||||
syntax keyword healthWarning WARNING
|
syntax keyword healthWarning WARNING[:]
|
||||||
\ containedin=markdownCodeBlock,mkdListItemLine
|
\ containedin=markdownCodeBlock,mkdListItemLine
|
||||||
highlight link healthWarning WarningMsg
|
highlight link healthWarning WarningMsg
|
||||||
|
|
||||||
syntax keyword healthSuccess SUCCESS
|
syntax keyword healthSuccess OK[:]
|
||||||
\ containedin=markdownCodeBlock,mkdListItemLine
|
\ containedin=markdownCodeBlock,mkdListItemLine
|
||||||
highlight healthSuccess guibg=#5fff00 guifg=#080808 ctermbg=82 ctermfg=232
|
highlight healthSuccess guibg=#5fff00 guifg=#080808 ctermbg=82 ctermfg=232
|
||||||
|
|
||||||
@ -90,27 +90,27 @@ endfunction
|
|||||||
|
|
||||||
" Changes ':h clipboard' to ':help |clipboard|'.
|
" Changes ':h clipboard' to ':help |clipboard|'.
|
||||||
function! s:help_to_link(s) abort
|
function! s:help_to_link(s) abort
|
||||||
return substitute(a:s, '\v:h%[elp] ([^|][^"\r\n]+)', ':help |\1|', 'g')
|
return substitute(a:s, '\v:h%[elp] ([^|][^"\r\n ]+)', ':help |\1|', 'g')
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
" Format a message for a specific report item
|
" Format a message for a specific report item
|
||||||
function! s:format_report_message(status, msg, ...) abort " {{{
|
function! s:format_report_message(status, msg, ...) abort " {{{
|
||||||
let output = ' - ' . a:status . ': ' . s:indent_after_line1(a:msg, 4)
|
let output = ' - ' . a:status . ': ' . s:indent_after_line1(a:msg, 4)
|
||||||
let suggestions = []
|
let advice = []
|
||||||
|
|
||||||
" Optional parameters
|
" Optional parameters
|
||||||
if a:0 > 0
|
if a:0 > 0
|
||||||
let suggestions = type(a:1) == type("") ? [a:1] : a:1
|
let advice = type(a:1) == type("") ? [a:1] : a:1
|
||||||
if type(suggestions) != type([])
|
if type(advice) != type([])
|
||||||
echoerr "Expected String or List"
|
throw "Expected String or List"
|
||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
|
|
||||||
" Report each suggestion
|
" Report each suggestion
|
||||||
if len(suggestions) > 0
|
if len(advice) > 0
|
||||||
let output .= "\n - SUGGESTIONS:"
|
let output .= "\n - ADVICE:"
|
||||||
endif
|
endif
|
||||||
for suggestion in suggestions
|
for suggestion in advice
|
||||||
let output .= "\n - " . s:indent_after_line1(suggestion, 10)
|
let output .= "\n - " . s:indent_after_line1(suggestion, 10)
|
||||||
endfor
|
endfor
|
||||||
|
|
||||||
@ -124,7 +124,7 @@ endfunction " }}}
|
|||||||
|
|
||||||
" Reports a successful healthcheck.
|
" Reports a successful healthcheck.
|
||||||
function! health#report_ok(msg) abort " {{{
|
function! health#report_ok(msg) abort " {{{
|
||||||
echo s:format_report_message('SUCCESS', a:msg)
|
echo s:format_report_message('OK', a:msg)
|
||||||
endfunction " }}}
|
endfunction " }}}
|
||||||
|
|
||||||
" Reports a health warning.
|
" Reports a health warning.
|
||||||
|
@ -10,6 +10,12 @@ function! s:check_config() abort
|
|||||||
\ [ "Use the 'guicursor' option to configure cursor shape. :help 'guicursor'",
|
\ [ "Use the 'guicursor' option to configure cursor shape. :help 'guicursor'",
|
||||||
\ 'https://github.com/neovim/neovim/wiki/Following-HEAD#20170402' ])
|
\ 'https://github.com/neovim/neovim/wiki/Following-HEAD#20170402' ])
|
||||||
endif
|
endif
|
||||||
|
if &paste
|
||||||
|
let ok = v:false
|
||||||
|
call health#report_error("'paste' is enabled. This option is only for pasting text.\nIt should not be set in your config.",
|
||||||
|
\ [ 'Remove `set paste` from your init.vim, if applicable.',
|
||||||
|
\ 'Check `:verbose set paste?` to see if a plugin or script set the option.', ])
|
||||||
|
endif
|
||||||
|
|
||||||
if ok
|
if ok
|
||||||
call health#report_ok('no issues found')
|
call health#report_ok('no issues found')
|
||||||
|
@ -121,14 +121,14 @@ function! s:check_clipboard() abort
|
|||||||
call health#report_start('Clipboard (optional)')
|
call health#report_start('Clipboard (optional)')
|
||||||
|
|
||||||
let clipboard_tool = provider#clipboard#Executable()
|
let clipboard_tool = provider#clipboard#Executable()
|
||||||
if empty(clipboard_tool)
|
if exists('g:clipboard') && empty(clipboard_tool)
|
||||||
call health#report_warn(
|
|
||||||
\ 'No clipboard tool found. Clipboard registers will not work.',
|
|
||||||
\ [':help clipboard'])
|
|
||||||
elseif exists('g:clipboard') && (type({}) != type(g:clipboard)
|
|
||||||
\ || !has_key(g:clipboard, 'copy') || !has_key(g:clipboard, 'paste'))
|
|
||||||
call health#report_error(
|
call health#report_error(
|
||||||
\ 'g:clipboard exists but is malformed. It must be a dictionary with the keys documented at :help g:clipboard')
|
\ provider#clipboard#Error(),
|
||||||
|
\ ["Use the example in :help g:clipboard as a template, or don't set g:clipboard at all."])
|
||||||
|
elseif empty(clipboard_tool)
|
||||||
|
call health#report_warn(
|
||||||
|
\ 'No clipboard tool found. Clipboard registers (`"+` and `"*`) will not work.',
|
||||||
|
\ [':help clipboard'])
|
||||||
else
|
else
|
||||||
call health#report_ok('Clipboard tool found: '. clipboard_tool)
|
call health#report_ok('Clipboard tool found: '. clipboard_tool)
|
||||||
endif
|
endif
|
||||||
@ -239,7 +239,7 @@ function! s:check_python(version) abort
|
|||||||
|
|
||||||
let pyname = 'python'.(a:version == 2 ? '' : '3')
|
let pyname = 'python'.(a:version == 2 ? '' : '3')
|
||||||
let pyenv = resolve(exepath('pyenv'))
|
let pyenv = resolve(exepath('pyenv'))
|
||||||
let pyenv_root = exists('$PYENV_ROOT') ? resolve($PYENV_ROOT) : 'n'
|
let pyenv_root = exists('$PYENV_ROOT') ? resolve($PYENV_ROOT) : ''
|
||||||
let venv = exists('$VIRTUAL_ENV') ? resolve($VIRTUAL_ENV) : ''
|
let venv = exists('$VIRTUAL_ENV') ? resolve($VIRTUAL_ENV) : ''
|
||||||
let host_prog_var = pyname.'_host_prog'
|
let host_prog_var = pyname.'_host_prog'
|
||||||
let loaded_var = 'g:loaded_'.pyname.'_provider'
|
let loaded_var = 'g:loaded_'.pyname.'_provider'
|
||||||
@ -251,6 +251,19 @@ function! s:check_python(version) abort
|
|||||||
return
|
return
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
if !empty(pyenv)
|
||||||
|
if empty(pyenv_root)
|
||||||
|
call health#report_warn(
|
||||||
|
\ 'pyenv was found, but $PYENV_ROOT is not set.',
|
||||||
|
\ ['Did you follow the final install instructions?',
|
||||||
|
\ 'If you use a shell "framework" like Prezto or Oh My Zsh, try without.',
|
||||||
|
\ 'Try a different shell (bash).']
|
||||||
|
\ )
|
||||||
|
else
|
||||||
|
call health#report_ok(printf('pyenv found: "%s"', pyenv))
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
|
||||||
if exists('g:'.host_prog_var)
|
if exists('g:'.host_prog_var)
|
||||||
call health#report_info(printf('Using: g:%s = "%s"', host_prog_var, get(g:, host_prog_var)))
|
call health#report_info(printf('Using: g:%s = "%s"', host_prog_var, get(g:, host_prog_var)))
|
||||||
endif
|
endif
|
||||||
@ -282,15 +295,6 @@ function! s:check_python(version) abort
|
|||||||
endif
|
endif
|
||||||
|
|
||||||
if !empty(pyenv)
|
if !empty(pyenv)
|
||||||
if empty(pyenv_root)
|
|
||||||
call health#report_warn(
|
|
||||||
\ 'pyenv was found, but $PYENV_ROOT is not set.',
|
|
||||||
\ ['Did you follow the final install instructions?']
|
|
||||||
\ )
|
|
||||||
else
|
|
||||||
call health#report_ok(printf('pyenv found: "%s"', pyenv))
|
|
||||||
endif
|
|
||||||
|
|
||||||
let python_bin = s:trim(s:system([pyenv, 'which', pyname], '', 1))
|
let python_bin = s:trim(s:system([pyenv, 'which', pyname], '', 1))
|
||||||
|
|
||||||
if empty(python_bin)
|
if empty(python_bin)
|
||||||
@ -320,9 +324,8 @@ function! s:check_python(version) abort
|
|||||||
|
|
||||||
if python_bin =~# '\<shims\>'
|
if python_bin =~# '\<shims\>'
|
||||||
call health#report_warn(printf('`%s` appears to be a pyenv shim.', python_bin), [
|
call health#report_warn(printf('`%s` appears to be a pyenv shim.', python_bin), [
|
||||||
\ 'The `pyenv` executable is not in $PATH,',
|
\ '`pyenv` is not in $PATH, your pyenv installation is broken. '
|
||||||
\ 'Your pyenv installation is broken. You should set '
|
\ .'Set `g:'.host_prog_var.'` to avoid surprises.',
|
||||||
\ . '`g:'.host_prog_var.'` to avoid surprises.',
|
|
||||||
\ ])
|
\ ])
|
||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
@ -335,7 +338,7 @@ function! s:check_python(version) abort
|
|||||||
call health#report_warn('pyenv is not set up optimally.', [
|
call health#report_warn('pyenv is not set up optimally.', [
|
||||||
\ printf('Create a virtualenv specifically '
|
\ printf('Create a virtualenv specifically '
|
||||||
\ . 'for Neovim using pyenv, and set `g:%s`. This will avoid '
|
\ . 'for Neovim using pyenv, and set `g:%s`. This will avoid '
|
||||||
\ . 'the need to install Neovim''s Python module in each '
|
\ . 'the need to install the Neovim Python module in each '
|
||||||
\ . 'version/virtualenv.', host_prog_var)
|
\ . 'version/virtualenv.', host_prog_var)
|
||||||
\ ])
|
\ ])
|
||||||
elseif !empty(venv) && exists('g:'.host_prog_var)
|
elseif !empty(venv) && exists('g:'.host_prog_var)
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
let s:stderr = {}
|
let s:stderr = {}
|
||||||
|
|
||||||
function! provider#stderr_collector(chan_id, data, event) dict
|
function! provider#stderr_collector(chan_id, data, event)
|
||||||
let stderr = get(s:stderr, a:chan_id, [''])
|
let stderr = get(s:stderr, a:chan_id, [''])
|
||||||
let stderr[-1] .= a:data[0]
|
let stderr[-1] .= a:data[0]
|
||||||
call extend(stderr, a:data[1:])
|
call extend(stderr, a:data[1:])
|
||||||
@ -10,7 +10,9 @@ function! provider#stderr_collector(chan_id, data, event) dict
|
|||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
function! provider#clear_stderr(chan_id)
|
function! provider#clear_stderr(chan_id)
|
||||||
silent! call delete(s:stderr, a:chan_id)
|
if has_key(s:stderr, a:chan_id)
|
||||||
|
call remove(s:stderr, a:chan_id)
|
||||||
|
endif
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
function! provider#get_stderr(chan_id)
|
function! provider#get_stderr(chan_id)
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
" available.
|
" available.
|
||||||
let s:copy = {}
|
let s:copy = {}
|
||||||
let s:paste = {}
|
let s:paste = {}
|
||||||
|
let s:clipboard = {}
|
||||||
|
|
||||||
" When caching is enabled, store the jobid of the xclip/xsel process keeping
|
" When caching is enabled, store the jobid of the xclip/xsel process keeping
|
||||||
" ownership of the selection, so we know how long the cache is valid.
|
" ownership of the selection, so we know how long the cache is valid.
|
||||||
@ -23,7 +24,7 @@ function! s:selection.on_exit(jobid, data, event) abort
|
|||||||
call provider#clear_stderr(a:jobid)
|
call provider#clear_stderr(a:jobid)
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
let s:selections = { '*': s:selection, '+': copy(s:selection)}
|
let s:selections = { '*': s:selection, '+': copy(s:selection) }
|
||||||
|
|
||||||
function! s:try_cmd(cmd, ...) abort
|
function! s:try_cmd(cmd, ...) abort
|
||||||
let argv = split(a:cmd, " ")
|
let argv = split(a:cmd, " ")
|
||||||
@ -31,7 +32,7 @@ function! s:try_cmd(cmd, ...) abort
|
|||||||
if v:shell_error
|
if v:shell_error
|
||||||
if !exists('s:did_error_try_cmd')
|
if !exists('s:did_error_try_cmd')
|
||||||
echohl WarningMsg
|
echohl WarningMsg
|
||||||
echomsg "clipboard: error: ".(len(out) ? out[0] : '')
|
echomsg "clipboard: error: ".(len(out) ? out[0] : v:shell_error)
|
||||||
echohl None
|
echohl None
|
||||||
let s:did_error_try_cmd = 1
|
let s:did_error_try_cmd = 1
|
||||||
endif
|
endif
|
||||||
@ -55,9 +56,15 @@ endfunction
|
|||||||
|
|
||||||
function! provider#clipboard#Executable() abort
|
function! provider#clipboard#Executable() abort
|
||||||
if exists('g:clipboard')
|
if exists('g:clipboard')
|
||||||
|
if type({}) isnot# type(g:clipboard)
|
||||||
|
\ || type({}) isnot# type(get(g:clipboard, 'copy', v:null))
|
||||||
|
\ || type({}) isnot# type(get(g:clipboard, 'paste', v:null))
|
||||||
|
let s:err = 'clipboard: invalid g:clipboard'
|
||||||
|
return ''
|
||||||
|
endif
|
||||||
let s:copy = get(g:clipboard, 'copy', { '+': v:null, '*': v:null })
|
let s:copy = get(g:clipboard, 'copy', { '+': v:null, '*': v:null })
|
||||||
let s:paste = get(g:clipboard, 'paste', { '+': v:null, '*': v:null })
|
let s:paste = get(g:clipboard, 'paste', { '+': v:null, '*': v:null })
|
||||||
let s:cache_enabled = get(g:clipboard, 'cache_enabled', 1)
|
let s:cache_enabled = get(g:clipboard, 'cache_enabled', 0)
|
||||||
return get(g:clipboard, 'name', 'g:clipboard')
|
return get(g:clipboard, 'name', 'g:clipboard')
|
||||||
elseif has('mac') && executable('pbcopy')
|
elseif has('mac') && executable('pbcopy')
|
||||||
let s:copy['+'] = 'pbcopy'
|
let s:copy['+'] = 'pbcopy'
|
||||||
@ -104,16 +111,17 @@ function! provider#clipboard#Executable() abort
|
|||||||
return 'tmux'
|
return 'tmux'
|
||||||
endif
|
endif
|
||||||
|
|
||||||
let s:err = 'clipboard: No clipboard tool available. :help clipboard'
|
let s:err = 'clipboard: No clipboard tool. :help clipboard'
|
||||||
return ''
|
return ''
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
if empty(provider#clipboard#Executable())
|
if empty(provider#clipboard#Executable())
|
||||||
|
" provider#clipboard#Call() *must not* be defined if the provider is broken.
|
||||||
|
" Otherwise eval_has_provider() thinks the clipboard provider is
|
||||||
|
" functioning, and eval_call_provider() will happily call it.
|
||||||
finish
|
finish
|
||||||
endif
|
endif
|
||||||
|
|
||||||
let s:clipboard = {}
|
|
||||||
|
|
||||||
function! s:clipboard.get(reg) abort
|
function! s:clipboard.get(reg) abort
|
||||||
if s:selections[a:reg].owner > 0
|
if s:selections[a:reg].owner > 0
|
||||||
return s:selections[a:reg].data
|
return s:selections[a:reg].data
|
||||||
@ -154,9 +162,19 @@ function! s:clipboard.set(lines, regtype, reg) abort
|
|||||||
echohl WarningMsg
|
echohl WarningMsg
|
||||||
echomsg 'clipboard: failed to execute: '.(s:copy[a:reg])
|
echomsg 'clipboard: failed to execute: '.(s:copy[a:reg])
|
||||||
echohl None
|
echohl None
|
||||||
|
return 0
|
||||||
endif
|
endif
|
||||||
|
return 1
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
function! provider#clipboard#Call(method, args) abort
|
function! provider#clipboard#Call(method, args) abort
|
||||||
return call(s:clipboard[a:method],a:args,s:clipboard)
|
if get(s:, 'here', v:false) " Clipboard provider must not recurse. #7184
|
||||||
|
return 0
|
||||||
|
endif
|
||||||
|
let s:here = v:true
|
||||||
|
try
|
||||||
|
return call(s:clipboard[a:method],a:args,s:clipboard)
|
||||||
|
finally
|
||||||
|
let s:here = v:false
|
||||||
|
endtry
|
||||||
endfunction
|
endfunction
|
||||||
|
@ -89,7 +89,8 @@ endfunction
|
|||||||
|
|
||||||
function! remote#define#AutocmdOnHost(host, method, sync, name, opts)
|
function! remote#define#AutocmdOnHost(host, method, sync, name, opts)
|
||||||
let group = s:GetNextAutocmdGroup()
|
let group = s:GetNextAutocmdGroup()
|
||||||
let forward = '"doau '.group.' '.a:name.' ".'.'expand("<amatch>")'
|
let forward = '"doau '.group.' '.a:name.' ".'
|
||||||
|
\ . 'fnameescape(expand("<amatch>"))'
|
||||||
let a:opts.group = group
|
let a:opts.group = group
|
||||||
let bootstrap_def = s:GetAutocmdPrefix(a:name, a:opts)
|
let bootstrap_def = s:GetAutocmdPrefix(a:name, a:opts)
|
||||||
\ .' call remote#define#AutocmdBootstrap("'.a:host.'"'
|
\ .' call remote#define#AutocmdBootstrap("'.a:host.'"'
|
||||||
|
@ -171,8 +171,8 @@ nvim_replace_termcodes({str}, {from_part}, {do_lt}, {special})
|
|||||||
Parameters:~
|
Parameters:~
|
||||||
{str} String to be converted.
|
{str} String to be converted.
|
||||||
{from_part} Legacy Vim parameter. Usually true.
|
{from_part} Legacy Vim parameter. Usually true.
|
||||||
{do_lt} Also translate <lt>. Does nothing if
|
{do_lt} Also translate <lt>. Ignored if `special` is
|
||||||
`special` is false.
|
false.
|
||||||
{special} Replace |keycodes|, e.g. <CR> becomes a "\n"
|
{special} Replace |keycodes|, e.g. <CR> becomes a "\n"
|
||||||
char.
|
char.
|
||||||
|
|
||||||
@ -309,20 +309,24 @@ nvim_set_option({name}, {value}) *nvim_set_option()*
|
|||||||
{value} New option value
|
{value} New option value
|
||||||
|
|
||||||
nvim_out_write({str}) *nvim_out_write()*
|
nvim_out_write({str}) *nvim_out_write()*
|
||||||
Writes a message to vim output buffer
|
Writes a message to the Vim output buffer. Does not append
|
||||||
|
"\n", the message is buffered (won't display) until a linefeed
|
||||||
|
is written.
|
||||||
|
|
||||||
Parameters:~
|
Parameters:~
|
||||||
{str} Message
|
{str} Message
|
||||||
|
|
||||||
nvim_err_write({str}) *nvim_err_write()*
|
nvim_err_write({str}) *nvim_err_write()*
|
||||||
Writes a message to vim error buffer
|
Writes a message to the Vim error buffer. Does not append
|
||||||
|
"\n", the message is buffered (won't display) until a linefeed
|
||||||
|
is written.
|
||||||
|
|
||||||
Parameters:~
|
Parameters:~
|
||||||
{str} Message
|
{str} Message
|
||||||
|
|
||||||
nvim_err_writeln({str}) *nvim_err_writeln()*
|
nvim_err_writeln({str}) *nvim_err_writeln()*
|
||||||
Writes a message to vim error buffer. Appends a linefeed to
|
Writes a message to the Vim error buffer. Appends "\n", so the
|
||||||
ensure all contents are written.
|
buffer is flushed (and displayed).
|
||||||
|
|
||||||
Parameters:~
|
Parameters:~
|
||||||
{str} Message
|
{str} Message
|
||||||
|
@ -1271,7 +1271,7 @@ Commands for changing the working directory can be suffixed with a bang "!"
|
|||||||
|
|
||||||
*:lcd-*
|
*:lcd-*
|
||||||
:lcd[!] - Change to the previous current directory (before the
|
:lcd[!] - Change to the previous current directory (before the
|
||||||
previous ":tcd {path}" command).
|
previous ":lcd {path}" command).
|
||||||
|
|
||||||
*:pw* *:pwd* *E187*
|
*:pw* *:pwd* *E187*
|
||||||
:pw[d] Print the current directory name.
|
:pw[d] Print the current directory name.
|
||||||
|
@ -1522,14 +1522,16 @@ v:errors Errors found by assert functions, such as |assert_true()|.
|
|||||||
|
|
||||||
*v:event* *event-variable*
|
*v:event* *event-variable*
|
||||||
v:event Dictionary of event data for the current |autocommand|. Valid
|
v:event Dictionary of event data for the current |autocommand|. Valid
|
||||||
only during the autocommand lifetime: storing or passing
|
only during the event lifetime; storing or passing v:event is
|
||||||
`v:event` is invalid. Copy it instead: >
|
invalid! Copy it instead: >
|
||||||
au TextYankPost * let g:foo = deepcopy(v:event)
|
au TextYankPost * let g:foo = deepcopy(v:event)
|
||||||
< Keys vary by event; see the documentation for the specific
|
< Keys vary by event; see the documentation for the specific
|
||||||
event, e.g. |TextYankPost|.
|
event, e.g. |DirChanged| or |TextYankPost|.
|
||||||
KEY DESCRIPTION ~
|
KEY DESCRIPTION ~
|
||||||
operator The current |operator|. Also set for
|
cwd Current working directory
|
||||||
Ex commands (unlike |v:operator|). For
|
scope Event-specific scope name.
|
||||||
|
operator Current |operator|. Also set for Ex
|
||||||
|
commands (unlike |v:operator|). For
|
||||||
example if |TextYankPost| is triggered
|
example if |TextYankPost| is triggered
|
||||||
by the |:yank| Ex command then
|
by the |:yank| Ex command then
|
||||||
`v:event['operator']` is "y".
|
`v:event['operator']` is "y".
|
||||||
@ -4726,7 +4728,8 @@ input({opts})
|
|||||||
"-complete=" argument. Refer to |:command-completion| for
|
"-complete=" argument. Refer to |:command-completion| for
|
||||||
more information. Example: >
|
more information. Example: >
|
||||||
let fname = input("File: ", "", "file")
|
let fname = input("File: ", "", "file")
|
||||||
< *E5400* *E5402*
|
|
||||||
|
< *input()-highlight* *E5400* *E5402*
|
||||||
The optional `highlight` key allows specifying function which
|
The optional `highlight` key allows specifying function which
|
||||||
will be used for highlighting user input. This function
|
will be used for highlighting user input. This function
|
||||||
receives user input as its only argument and must return
|
receives user input as its only argument and must return
|
||||||
@ -4744,6 +4747,30 @@ input({opts})
|
|||||||
sections must be ordered so that next hl_start_col is greater
|
sections must be ordered so that next hl_start_col is greater
|
||||||
then or equal to previous hl_end_col.
|
then or equal to previous hl_end_col.
|
||||||
|
|
||||||
|
Example (try some input with parentheses): >
|
||||||
|
highlight RBP1 guibg=Red ctermbg=red
|
||||||
|
highlight RBP2 guibg=Yellow ctermbg=yellow
|
||||||
|
highlight RBP3 guibg=Green ctermbg=green
|
||||||
|
highlight RBP4 guibg=Blue ctermbg=blue
|
||||||
|
let g:rainbow_levels = 4
|
||||||
|
function! RainbowParens(cmdline)
|
||||||
|
let ret = []
|
||||||
|
let i = 0
|
||||||
|
let lvl = 0
|
||||||
|
while i < len(a:cmdline)
|
||||||
|
if a:cmdline[i] is# '('
|
||||||
|
call add(ret, [i, i + 1, 'RBP' . ((lvl % g:rainbow_levels) + 1)])
|
||||||
|
let lvl += 1
|
||||||
|
elseif a:cmdline[i] is# ')'
|
||||||
|
let lvl -= 1
|
||||||
|
call add(ret, [i, i + 1, 'RBP' . ((lvl % g:rainbow_levels) + 1)])
|
||||||
|
endif
|
||||||
|
let i += 1
|
||||||
|
endwhile
|
||||||
|
return ret
|
||||||
|
endfunction
|
||||||
|
call input({'prompt':'>','highlight':'RainbowParens'})
|
||||||
|
<
|
||||||
Highlight function is called at least once for each new
|
Highlight function is called at least once for each new
|
||||||
displayed input string, before command-line is redrawn. It is
|
displayed input string, before command-line is redrawn. It is
|
||||||
expected that function is pure for the duration of one input()
|
expected that function is pure for the duration of one input()
|
||||||
|
@ -449,12 +449,6 @@ changed. To avoid the message reset the 'warn' option.
|
|||||||
Something inside Vim went wrong and resulted in a NULL pointer. If you know
|
Something inside Vim went wrong and resulted in a NULL pointer. If you know
|
||||||
how to reproduce this problem, please report it. |bugs|
|
how to reproduce this problem, please report it. |bugs|
|
||||||
|
|
||||||
*E172* >
|
|
||||||
Only one file name allowed
|
|
||||||
|
|
||||||
The ":edit" command only accepts one file name. When you want to specify
|
|
||||||
several files for editing use ":next" |:next|.
|
|
||||||
|
|
||||||
*E41* *E82* *E83* *E342* >
|
*E41* *E82* *E83* *E342* >
|
||||||
Out of memory!
|
Out of memory!
|
||||||
Out of memory! (allocating {number} bytes)
|
Out of memory! (allocating {number} bytes)
|
||||||
|
@ -6267,11 +6267,11 @@ A jump table for the options with a short description can be found at |Q_op|.
|
|||||||
when part of a command has been typed.
|
when part of a command has been typed.
|
||||||
|
|
||||||
*'title'* *'notitle'*
|
*'title'* *'notitle'*
|
||||||
'title' boolean (default off, on when title can be restored)
|
'title' boolean (default off)
|
||||||
global
|
global
|
||||||
When on, the title of the window will be set to the value of
|
When on, the title of the window will be set to the value of
|
||||||
'titlestring' (if it is not empty), or to:
|
'titlestring' (if it is not empty), or to:
|
||||||
filename [+=-] (path) - VIM
|
filename [+=-] (path) - NVIM
|
||||||
Where:
|
Where:
|
||||||
filename the name of the file being edited
|
filename the name of the file being edited
|
||||||
- indicates the file cannot be modified, 'ma' off
|
- indicates the file cannot be modified, 'ma' off
|
||||||
@ -6279,7 +6279,7 @@ A jump table for the options with a short description can be found at |Q_op|.
|
|||||||
= indicates the file is read-only
|
= indicates the file is read-only
|
||||||
=+ indicates the file is read-only and modified
|
=+ indicates the file is read-only and modified
|
||||||
(path) is the path of the file being edited
|
(path) is the path of the file being edited
|
||||||
- VIM the server name |v:servername| or "VIM"
|
- NVIM the server name |v:servername| or "NVIM"
|
||||||
|
|
||||||
*'titlelen'*
|
*'titlelen'*
|
||||||
'titlelen' number (default 85)
|
'titlelen' number (default 85)
|
||||||
@ -6295,11 +6295,10 @@ A jump table for the options with a short description can be found at |Q_op|.
|
|||||||
'titlelen' is also used for the 'titlestring' option.
|
'titlelen' is also used for the 'titlestring' option.
|
||||||
|
|
||||||
*'titleold'*
|
*'titleold'*
|
||||||
'titleold' string (default "Thanks for flying Vim")
|
'titleold' string (default "")
|
||||||
global
|
global
|
||||||
This option will be used for the window title when exiting Vim if the
|
If not empty, this option will be used to set the window title when
|
||||||
original title cannot be restored. Only happens if 'title' is on or
|
exiting. Only if 'title' is enabled.
|
||||||
'titlestring' is not empty.
|
|
||||||
This option cannot be set from a |modeline| or in the |sandbox|, for
|
This option cannot be set from a |modeline| or in the |sandbox|, for
|
||||||
security reasons.
|
security reasons.
|
||||||
*'titlestring'*
|
*'titlestring'*
|
||||||
@ -6748,19 +6747,19 @@ A jump table for the options with a short description can be found at |Q_op|.
|
|||||||
*'winhighlight'* *'winhl'*
|
*'winhighlight'* *'winhl'*
|
||||||
'winhighlight' 'winhl' string (default empty)
|
'winhighlight' 'winhl' string (default empty)
|
||||||
local to window
|
local to window
|
||||||
Window-local highlights. Comma-delimited list of |group-name| pairs
|
Window-local highlights. Comma-delimited list of highlight
|
||||||
"{hl-builtin}:{hl-group},..." where each {hl-builtin} is a group (from
|
|group-name| pairs "{hl-builtin}:{hl},..." where each {hl-builtin} is
|
||||||
|highlight-groups|) to be overridden by {hl-group} in the window where
|
a built-in |highlight-groups| item to be overridden by {hl} group in
|
||||||
this option was set. Only builting ui highlights are supported, not
|
the window. Only built-in |highlight-groups| are supported, not
|
||||||
syntax highlighting. For that purpose, use |:ownsyntax|.
|
syntax highlighting (use |:ownsyntax| for that).
|
||||||
|
|
||||||
Most highlights occuring within the frame of a window are supported.
|
|
||||||
Highlights of vertical separators are determined by the window to the
|
Highlights of vertical separators are determined by the window to the
|
||||||
left of the separator. The highlight of a tabpage in |tabline| is
|
left of the separator. The highlight of a tabpage in |tabline| is
|
||||||
determined by the last focused window in the tabpage. Highlights of
|
determine by the last-focused window of the tabpage. Highlights of
|
||||||
the popupmenu are determined by the current window. Highlights in the
|
the popupmenu are determined by the current window. Highlights in the
|
||||||
message area are not overridable. Example for overriding the
|
message area cannot be overridden.
|
||||||
backgrond color: >
|
|
||||||
|
Example: show a different color for non-current windows: >
|
||||||
set winhighlight=Normal:MyNormal,NormalNC:MyNormalNC
|
set winhighlight=Normal:MyNormal,NormalNC:MyNormalNC
|
||||||
<
|
<
|
||||||
*'winfixheight'* *'wfh'* *'nowinfixheight'* *'nowfh'*
|
*'winfixheight'* *'wfh'* *'nowinfixheight'* *'nowfh'*
|
||||||
|
@ -64,11 +64,11 @@ health#report_info({msg}) *health#report_info*
|
|||||||
health#report_ok({msg}) *health#report_ok*
|
health#report_ok({msg}) *health#report_ok*
|
||||||
Displays a "success" message.
|
Displays a "success" message.
|
||||||
|
|
||||||
health#report_warn({msg}, [{suggestions}]) *health#report_warn*
|
health#report_warn({msg}, [{advice}]) *health#report_warn*
|
||||||
Displays a warning. {suggestions} is an optional List of suggestions.
|
Displays a warning. {advice} is an optional List of suggestions.
|
||||||
|
|
||||||
health#report_error({msg}, [{suggestions}]) *health#report_error*
|
health#report_error({msg}, [{advice}]) *health#report_error*
|
||||||
Displays an error. {suggestions} is an optional List of suggestions.
|
Displays an error. {advice} is an optional List of suggestions.
|
||||||
|
|
||||||
health#{plugin}#check() *health.user_checker*
|
health#{plugin}#check() *health.user_checker*
|
||||||
This is the form of a healthcheck definition. Call the above functions
|
This is the form of a healthcheck definition. Call the above functions
|
||||||
|
@ -3270,11 +3270,10 @@ improve screen updating rates (see |:syn-sync| for more on this). >
|
|||||||
The g:vimsyn_embed option allows users to select what, if any, types of
|
The g:vimsyn_embed option allows users to select what, if any, types of
|
||||||
embedded script highlighting they wish to have. >
|
embedded script highlighting they wish to have. >
|
||||||
|
|
||||||
g:vimsyn_embed == 0 : don't embed any scripts
|
g:vimsyn_embed == 0 : disable (don't embed any scripts)
|
||||||
g:vimsyn_embed =~ 'P' : support embedded python
|
g:vimsyn_embed == 'lPr' : support embedded lua, python and ruby
|
||||||
<
|
<
|
||||||
By default, g:vimsyn_embed is a string supporting interpreters that your vim
|
This option is disabled by default.
|
||||||
itself supports.
|
|
||||||
*g:vimsyn_folding*
|
*g:vimsyn_folding*
|
||||||
|
|
||||||
Some folding is now supported with syntax/vim.vim: >
|
Some folding is now supported with syntax/vim.vim: >
|
||||||
|
@ -41,16 +41,17 @@ $TERM is also important because it is mirrored by SSH to the remote session,
|
|||||||
unlike other common client-end environment variables ($COLORTERM,
|
unlike other common client-end environment variables ($COLORTERM,
|
||||||
$XTERM_VERSION, $VTE_VERSION, $KONSOLE_PROFILE_NAME, $TERM_PROGRAM, ...).
|
$XTERM_VERSION, $VTE_VERSION, $KONSOLE_PROFILE_NAME, $TERM_PROGRAM, ...).
|
||||||
|
|
||||||
For this terminal Set $TERM to |builtin-terms|?
|
For this terminal Set $TERM to |builtin-terms|
|
||||||
|
-------------------------------------------------------------------------
|
||||||
iTerm.app "iterm" or "iTerm.app" Y
|
iTerm (original) iterm, iTerm.app N
|
||||||
anything libvte based "vte" or "vte-256color" Y
|
iTerm2 (new capabilities) iterm2, iTerm2.app Y
|
||||||
(e.g. GNOME Terminal) (aliases: "gnome", "gnome-256color")
|
anything libvte-based vte, vte-256color Y
|
||||||
tmux "tmux" or "tmux-256color" Y
|
(e.g. GNOME Terminal) (aliases: gnome, gnome-256color)
|
||||||
screen "screen" or "screen-256color" Y
|
tmux tmux, tmux-256color Y
|
||||||
PuTTY "putty" or "putty-256color" Y
|
screen screen, screen-256color Y
|
||||||
Terminal.app "nsterm" N
|
PuTTY putty, putty-256color Y
|
||||||
Linux virtual terminal "linux" or "linux-256color" Y
|
Terminal.app nsterm N
|
||||||
|
Linux virtual terminal linux, linux-256color Y
|
||||||
|
|
||||||
*builtin-terms* *builtin_terms*
|
*builtin-terms* *builtin_terms*
|
||||||
If a |terminfo| database is not available, or no entry for the terminal type is
|
If a |terminfo| database is not available, or no entry for the terminal type is
|
||||||
|
@ -212,7 +212,6 @@ g8 Print the hex values of the bytes used in the
|
|||||||
Equivalent to: >
|
Equivalent to: >
|
||||||
:enew
|
:enew
|
||||||
:call termopen('{cmd}')
|
:call termopen('{cmd}')
|
||||||
:startinsert
|
|
||||||
<
|
<
|
||||||
See |termopen()|.
|
See |termopen()|.
|
||||||
|
|
||||||
|
@ -6,9 +6,8 @@
|
|||||||
|
|
||||||
Differences between Nvim and Vim *vim-differences*
|
Differences between Nvim and Vim *vim-differences*
|
||||||
|
|
||||||
Throughout the help files, differences between Nvim and Vim are indicated via
|
Nvim differs from Vim in many ways, big and small. This document is
|
||||||
the "{Nvim}" tag. This document is a complete and centralized list of all
|
a complete and centralized reference of those differences.
|
||||||
these differences.
|
|
||||||
|
|
||||||
Type <M-]> to see the table of contents.
|
Type <M-]> to see the table of contents.
|
||||||
|
|
||||||
@ -72,12 +71,18 @@ Clipboard integration |provider-clipboard|
|
|||||||
|
|
||||||
USER EXPERIENCE ~
|
USER EXPERIENCE ~
|
||||||
|
|
||||||
Working intuitively and consistently is a major goal of Nvim. Examples:
|
Working intuitively and consistently is a major goal of Nvim.
|
||||||
|
|
||||||
- Nvim does not have `-X`, a platform-specific option "sometimes" available in
|
*feature-compile*
|
||||||
Vim (with potential surprises: http://stackoverflow.com/q/14635295). Nvim
|
- Nvim always includes ALL features, in contrast to Vim (which ships with
|
||||||
avoids features that cannot be provided on all platforms--instead that is
|
various combinations of 100+ optional features). Think of it as a leaner
|
||||||
delegated to external plugins/extensions.
|
version of Vim's "HUGE" build. This reduces surface area for bugs, and
|
||||||
|
removes a common source of confusion and friction for users.
|
||||||
|
|
||||||
|
- Nvim avoids features that cannot be provided on all platforms; instead that
|
||||||
|
is delegated to external plugins/extensions. E.g. the `-X` platform-specific
|
||||||
|
option is "sometimes" available in Vim (with potential surprises:
|
||||||
|
http://stackoverflow.com/q/14635295).
|
||||||
|
|
||||||
- Vim's internal test functions (test_autochdir(), test_settime(), etc.) are
|
- Vim's internal test functions (test_autochdir(), test_settime(), etc.) are
|
||||||
not exposed (nor implemented); instead Nvim has a robust API.
|
not exposed (nor implemented); instead Nvim has a robust API.
|
||||||
@ -268,13 +273,16 @@ Lua interface (|if_lua.txt|):
|
|||||||
- Lua has direct access to Nvim |API| via `vim.api`.
|
- Lua has direct access to Nvim |API| via `vim.api`.
|
||||||
- Lua package.path and package.cpath are automatically updated according to
|
- Lua package.path and package.cpath are automatically updated according to
|
||||||
'runtimepath': |lua-require|.
|
'runtimepath': |lua-require|.
|
||||||
- Currently, most legacy Vim features are missing.
|
|
||||||
|
|
||||||
|input()| and |inputdialog()| gained support for each other’s features (return
|
|input()| and |inputdialog()| support for each other’s features (return on
|
||||||
on cancel and completion respectively) via dictionary argument (replaces all
|
cancel and completion respectively) via dictionary argument (replaces all
|
||||||
other arguments if used).
|
other arguments if used).
|
||||||
|
|
||||||
|input()| and |inputdialog()| now support user-defined cmdline highlighting.
|
|input()| and |inputdialog()| support user-defined cmdline highlighting.
|
||||||
|
|
||||||
|
Highlight groups:
|
||||||
|
|hl-ColorColumn|, |hl-CursorColumn|, |hl-CursorLine| are lower priority than
|
||||||
|
(overridden by) most other highlight groups.
|
||||||
|
|
||||||
==============================================================================
|
==============================================================================
|
||||||
5. Missing legacy features *nvim-features-missing*
|
5. Missing legacy features *nvim-features-missing*
|
||||||
@ -282,7 +290,7 @@ other arguments if used).
|
|||||||
Some legacy Vim features are not implemented:
|
Some legacy Vim features are not implemented:
|
||||||
|
|
||||||
- |if_py|: vim.bindeval() and vim.Function() are not supported
|
- |if_py|: vim.bindeval() and vim.Function() are not supported
|
||||||
- |if_lua|: the `vim` object currently only supports `vim.api`
|
- |if_lua|: the `vim` object is missing most legacy methods
|
||||||
- *if_perl*
|
- *if_perl*
|
||||||
- *if_mzscheme*
|
- *if_mzscheme*
|
||||||
- *if_tcl*
|
- *if_tcl*
|
||||||
@ -290,7 +298,7 @@ Some legacy Vim features are not implemented:
|
|||||||
==============================================================================
|
==============================================================================
|
||||||
6. Removed features *nvim-features-removed*
|
6. Removed features *nvim-features-removed*
|
||||||
|
|
||||||
These features are in Vim, but have been intentionally removed from Nvim.
|
These Vim features were intentionally removed from Nvim.
|
||||||
|
|
||||||
*'cp'* *'nocompatible'* *'nocp'* *'compatible'*
|
*'cp'* *'nocompatible'* *'nocp'* *'compatible'*
|
||||||
Nvim is always "non-compatible" with Vi.
|
Nvim is always "non-compatible" with Vi.
|
||||||
|
@ -3,8 +3,8 @@
|
|||||||
" #############################################################################
|
" #############################################################################
|
||||||
" #############################################################################
|
" #############################################################################
|
||||||
" Note: Be careful when merging the upstream version of this file.
|
" Note: Be careful when merging the upstream version of this file.
|
||||||
" Much of this is generated by scripts/genvimvim.lua (result is installed
|
" Much of this is generated by scripts/genvimvim.lua
|
||||||
" to: $VIMRUNTIME/syntax/vim/generated.vim)
|
" (installs to $VIMRUNTIME/syntax/vim/generated.vim)
|
||||||
" #############################################################################
|
" #############################################################################
|
||||||
" #############################################################################
|
" #############################################################################
|
||||||
|
|
||||||
@ -128,6 +128,13 @@ if exists("g:vimsyntax_noerror")
|
|||||||
let g:vimsyn_noerror= g:vimsyntax_noerror
|
let g:vimsyn_noerror= g:vimsyntax_noerror
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
" Variable options {{{2
|
||||||
|
if exists("g:vim_maxlines")
|
||||||
|
let s:vimsyn_maxlines= g:vim_maxlines
|
||||||
|
else
|
||||||
|
let s:vimsyn_maxlines= 60
|
||||||
|
endif
|
||||||
|
|
||||||
" Numbers {{{2
|
" Numbers {{{2
|
||||||
" =======
|
" =======
|
||||||
syn match vimNumber "\<\d\+\%(\.\d\+\%([eE][+-]\=\d\+\)\=\)\=" skipwhite nextgroup=vimGlobal,vimSubst,vimCommand
|
syn match vimNumber "\<\d\+\%(\.\d\+\%([eE][+-]\=\d\+\)\=\)\=" skipwhite nextgroup=vimGlobal,vimSubst,vimCommand
|
||||||
@ -601,7 +608,7 @@ syn region vimGlobal matchgroup=Statement start='\<v\%[global]!\=/' skip='\\.' e
|
|||||||
" g:vimsyn_embed =~# 'r' : embed ruby
|
" g:vimsyn_embed =~# 'r' : embed ruby
|
||||||
" g:vimsyn_embed =~# 't' : embed tcl
|
" g:vimsyn_embed =~# 't' : embed tcl
|
||||||
if !exists("g:vimsyn_embed")
|
if !exists("g:vimsyn_embed")
|
||||||
let g:vimsyn_embed= "lpPr"
|
let g:vimsyn_embed= 0
|
||||||
endif
|
endif
|
||||||
|
|
||||||
" [-- lua --] {{{3
|
" [-- lua --] {{{3
|
||||||
@ -744,9 +751,10 @@ if !filereadable(s:mzschemepath)
|
|||||||
endif
|
endif
|
||||||
if g:vimsyn_embed =~# 'm' && filereadable(s:mzschemepath)
|
if g:vimsyn_embed =~# 'm' && filereadable(s:mzschemepath)
|
||||||
unlet! b:current_syntax
|
unlet! b:current_syntax
|
||||||
let iskKeep= &isk
|
let s:iskKeep= &isk
|
||||||
exe "syn include @vimMzSchemeScript ".s:mzschemepath
|
exe "syn include @vimMzSchemeScript ".s:mzschemepath
|
||||||
let &isk= iskKeep
|
let &isk= s:iskKeep
|
||||||
|
unlet s:iskKeep
|
||||||
VimFoldm syn region vimMzSchemeRegion matchgroup=vimScriptDelim start=+mz\%[scheme]\s*<<\s*\z(.*\)$+ end=+^\z1$+ contains=@vimMzSchemeScript
|
VimFoldm syn region vimMzSchemeRegion matchgroup=vimScriptDelim start=+mz\%[scheme]\s*<<\s*\z(.*\)$+ end=+^\z1$+ contains=@vimMzSchemeScript
|
||||||
VimFoldm syn region vimMzSchemeRegion matchgroup=vimScriptDelim start=+mz\%[scheme]\s*<<\s*$+ end=+\.$+ contains=@vimMzSchemeScript
|
VimFoldm syn region vimMzSchemeRegion matchgroup=vimScriptDelim start=+mz\%[scheme]\s*<<\s*$+ end=+\.$+ contains=@vimMzSchemeScript
|
||||||
syn cluster vimFuncBodyList add=vimMzSchemeRegion
|
syn cluster vimFuncBodyList add=vimMzSchemeRegion
|
||||||
@ -761,11 +769,7 @@ unlet s:mzschemepath
|
|||||||
if exists("g:vimsyn_minlines")
|
if exists("g:vimsyn_minlines")
|
||||||
exe "syn sync minlines=".g:vimsyn_minlines
|
exe "syn sync minlines=".g:vimsyn_minlines
|
||||||
endif
|
endif
|
||||||
if exists("g:vimsyn_maxlines")
|
exe "syn sync maxlines=".s:vimsyn_maxlines
|
||||||
exe "syn sync maxlines=".g:vimsyn_maxlines
|
|
||||||
else
|
|
||||||
syn sync maxlines=60
|
|
||||||
endif
|
|
||||||
syn sync linecont "^\s\+\\"
|
syn sync linecont "^\s\+\\"
|
||||||
syn sync match vimAugroupSyncA groupthere NONE "\<aug\%[roup]\>\s\+[eE][nN][dD]"
|
syn sync match vimAugroupSyncA groupthere NONE "\<aug\%[roup]\>\s\+[eE][nN][dD]"
|
||||||
|
|
||||||
@ -778,7 +782,7 @@ if !exists("skip_vim_syntax_inits")
|
|||||||
hi def link vimBehaveError vimError
|
hi def link vimBehaveError vimError
|
||||||
hi def link vimCollClassErr vimError
|
hi def link vimCollClassErr vimError
|
||||||
hi def link vimErrSetting vimError
|
hi def link vimErrSetting vimError
|
||||||
hi def link vimEmbedError vimError
|
hi def link vimEmbedError Normal
|
||||||
hi def link vimFTError vimError
|
hi def link vimFTError vimError
|
||||||
hi def link vimFunctionError vimError
|
hi def link vimFunctionError vimError
|
||||||
hi def link vimFunc vimError
|
hi def link vimFunc vimError
|
||||||
@ -935,6 +939,11 @@ if !exists("skip_vim_syntax_inits")
|
|||||||
hi def link vimUserFunc Normal
|
hi def link vimUserFunc Normal
|
||||||
hi def link vimVar Identifier
|
hi def link vimVar Identifier
|
||||||
hi def link vimWarn WarningMsg
|
hi def link vimWarn WarningMsg
|
||||||
|
|
||||||
|
hi def link nvimAutoEvent vimAutoEvent
|
||||||
|
hi def link nvimHLGroup vimHLGroup
|
||||||
|
hi def link nvimMap vimMap
|
||||||
|
hi def link nvimUnmap vimUnmap
|
||||||
endif
|
endif
|
||||||
|
|
||||||
" Current Syntax Variable: {{{2
|
" Current Syntax Variable: {{{2
|
||||||
|
@ -23,7 +23,7 @@ relevant help (hopefully), and pressing K over any word will try to do so too.
|
|||||||
Sometimes you will be required to modify text like
|
Sometimes you will be required to modify text like
|
||||||
this here
|
this here
|
||||||
Once you have done the changes correctly, the ✗ sign at the left will change
|
Once you have done the changes correctly, the ✗ sign at the left will change
|
||||||
to ✓. I imagine you can already see how neat Vim can be ;)
|
to ✓. I imagine you can already see how neat Vim can be. ;)
|
||||||
Other times, you'll be prompted to run a command (I'll explain this later):
|
Other times, you'll be prompted to run a command (I'll explain this later):
|
||||||
~~~ cmd
|
~~~ cmd
|
||||||
:help <Enter>
|
:help <Enter>
|
||||||
@ -36,30 +36,30 @@ or press a sequence of keys
|
|||||||
Text within <'s and >'s (like `<Enter>`{normal}) describes a key to press instead of text
|
Text within <'s and >'s (like `<Enter>`{normal}) describes a key to press instead of text
|
||||||
to type.
|
to type.
|
||||||
|
|
||||||
Now, move to the next lesson (remember, use j).
|
Now, move to the next lesson (remember, use the `j`{normal} key to scroll down).
|
||||||
|
|
||||||
## Lesson 1.1: MOVING THE CURSOR
|
## Lesson 1.1: MOVING THE CURSOR
|
||||||
|
|
||||||
** To move the cursor, press the `h`, `j`, `k`, `l` keys as indicated. **
|
** To move the cursor, press the `h`, `j`, `k`, `l` keys as indicated. **
|
||||||
|
|
||||||
↑
|
↑
|
||||||
k Hint: The h key is at the left and moves left.
|
k Hint: The `h`{normal} key is at the left and moves left.
|
||||||
← h l → The l key is at the right and moves right.
|
← h l → The `l`{normal} key is at the right and moves right.
|
||||||
j The j key looks like a down arrow.
|
j The `j`{normal} key looks like a down arrow.
|
||||||
↓
|
↓
|
||||||
|
|
||||||
1. Move the cursor around the screen until you are comfortable.
|
1. Move the cursor around the screen until you are comfortable.
|
||||||
|
|
||||||
2. Hold down the down key (j) until it repeats.
|
2. Hold down the down key (`j`{normal}) until it repeats.
|
||||||
Now you know how to move to the next lesson.
|
Now you know how to move to the next lesson.
|
||||||
|
|
||||||
3. Using the down key, move to Lesson 1.2.
|
3. Using the down key, move to Lesson 1.2.
|
||||||
|
|
||||||
NOTE: If you are ever unsure about something you typed, press <Esc> to place
|
NOTE: If you are ever unsure about something you typed, press <Esc> to place
|
||||||
you in Normal mode. Then retype the command you wanted.
|
you in Normal mode. Then retype the command you wanted.
|
||||||
|
|
||||||
NOTE: The cursor keys should also work. But using hjkl you will be able to
|
NOTE: The cursor keys should also work. But using hjkl you will be able to
|
||||||
move around much faster, once you get used to it. Really!
|
move around much faster, once you get used to it. Really!
|
||||||
|
|
||||||
# Lesson 1.2: EXITING VIM
|
# Lesson 1.2: EXITING VIM
|
||||||
|
|
||||||
@ -81,7 +81,7 @@ NOTE: The cursor keys should also work. But using hjkl you will be able to
|
|||||||
4. If you have these steps memorized and are confident, execute steps
|
4. If you have these steps memorized and are confident, execute steps
|
||||||
1 through 3 to exit and re-enter the editor.
|
1 through 3 to exit and re-enter the editor.
|
||||||
|
|
||||||
NOTE: [:q!](:q) <Enter> discards any changes you made. In a few lessons you
|
NOTE: [:q!](:q) <Enter> discards any changes you made. In a few lessons you
|
||||||
will learn how to save the changes to a file.
|
will learn how to save the changes to a file.
|
||||||
|
|
||||||
5. Move the cursor down to Lesson 1.3.
|
5. Move the cursor down to Lesson 1.3.
|
||||||
@ -90,18 +90,18 @@ NOTE: [:q!](:q) <Enter> discards any changes you made. In a few lessons you
|
|||||||
|
|
||||||
** Press `x`{normal} to delete the character under the cursor. **
|
** Press `x`{normal} to delete the character under the cursor. **
|
||||||
|
|
||||||
1. Move the cursor to the line below marked --->.
|
1. Move the cursor to the line below marked --->.
|
||||||
|
|
||||||
2. To fix the errors, move the cursor until it is on top of the
|
2. To fix the errors, move the cursor until it is on top of the
|
||||||
character to be deleted.
|
character to be deleted.
|
||||||
|
|
||||||
3. Press [the x key](x) to delete the unwanted character.
|
3. Press [the x key](x) to delete the unwanted character.
|
||||||
|
|
||||||
4. Repeat steps 2 through 4 until the sentence is correct.
|
4. Repeat steps 2 through 4 until the sentence is correct.
|
||||||
|
|
||||||
The ccow jumpedd ovverr thhe mooon.
|
The ccow jumpedd ovverr thhe mooon.
|
||||||
|
|
||||||
5. Now that the line is correct, go on to Lesson 1.4.
|
5. Now that the line is correct, go on to Lesson 1.4.
|
||||||
|
|
||||||
NOTE: As you go through this tutor, do not try to memorize, learn by usage.
|
NOTE: As you go through this tutor, do not try to memorize, learn by usage.
|
||||||
|
|
||||||
@ -114,15 +114,15 @@ NOTE: As you go through this tutor, do not try to memorize, learn by usage.
|
|||||||
2. To make the first line the same as the second, move the cursor on top
|
2. To make the first line the same as the second, move the cursor on top
|
||||||
of the first character AFTER where the text is to be inserted.
|
of the first character AFTER where the text is to be inserted.
|
||||||
|
|
||||||
3. Press i and type in the necessary additions.
|
3. Press `i`{normal} and type in the necessary additions.
|
||||||
|
|
||||||
4. As each error is fixed press <Esc> to return to Normal mode.
|
4. As each error is fixed press `<Esc>`{normal} to return to Normal mode.
|
||||||
Repeat steps 2 through 4 to correct the sentence.
|
Repeat steps 2 through 4 to correct the sentence.
|
||||||
|
|
||||||
There is text misng this .
|
There is text misng this .
|
||||||
There is some text missing from this line.
|
There is some text missing from this line.
|
||||||
|
|
||||||
5. When you are comfortable inserting text move to lesson 1.5.
|
5. When you are comfortable inserting text move to Lesson 1.5.
|
||||||
|
|
||||||
# Lesson 1.5: TEXT EDITING: APPENDING
|
# Lesson 1.5: TEXT EDITING: APPENDING
|
||||||
|
|
||||||
@ -131,9 +131,9 @@ There is some text missing from this line.
|
|||||||
1. Move the cursor to the first line below marked --->.
|
1. Move the cursor to the first line below marked --->.
|
||||||
It does not matter on what character the cursor is in that line.
|
It does not matter on what character the cursor is in that line.
|
||||||
|
|
||||||
2. Press [A](A) and type in the necessary additions.
|
2. Press [A](A) and type in the necessary additions.
|
||||||
|
|
||||||
3. As the text has been appended press <Esc> to return to Normal mode.
|
3. As the text has been appended press `<Esc>`{normal} to return to Normal mode.
|
||||||
|
|
||||||
4. Move the cursor to the second line marked ---> and repeat
|
4. Move the cursor to the second line marked ---> and repeat
|
||||||
steps 2 and 3 to correct this sentence.
|
steps 2 and 3 to correct this sentence.
|
||||||
@ -143,7 +143,7 @@ There is some text missing from this line.
|
|||||||
There is also some text miss
|
There is also some text miss
|
||||||
There is also some text missing here.
|
There is also some text missing here.
|
||||||
|
|
||||||
5. When you are comfortable appending text move to lesson 1.6.
|
5. When you are comfortable appending text move to Lesson 1.6.
|
||||||
|
|
||||||
# Lesson 1.6: EDITING A FILE
|
# Lesson 1.6: EDITING A FILE
|
||||||
|
|
||||||
@ -151,7 +151,7 @@ There is also some text missing here.
|
|||||||
|
|
||||||
!! NOTE: Before executing any of the steps below, read this entire lesson !!
|
!! NOTE: Before executing any of the steps below, read this entire lesson !!
|
||||||
|
|
||||||
1. Exit this tutor as you did in lesson 1.2: :q!
|
1. Exit this tutor as you did in Lesson 1.2: `:q!`{vim}
|
||||||
Or, if you have access to another terminal, do the following there.
|
Or, if you have access to another terminal, do the following there.
|
||||||
|
|
||||||
2. At the shell prompt type this command:
|
2. At the shell prompt type this command:
|
||||||
@ -159,7 +159,7 @@ There is also some text missing here.
|
|||||||
$ vim tutor
|
$ vim tutor
|
||||||
~~~
|
~~~
|
||||||
'vim' is the command to start the Vim editor, 'tutor' is the name of the
|
'vim' is the command to start the Vim editor, 'tutor' is the name of the
|
||||||
file you wish to edit. Use a file that may be changed.
|
file you wish to edit. Use a file that may be changed.
|
||||||
|
|
||||||
3. Insert and delete text as you learned in the previous lessons.
|
3. Insert and delete text as you learned in the previous lessons.
|
||||||
|
|
||||||
@ -186,14 +186,14 @@ There is also some text missing here.
|
|||||||
$ vim FILENAME
|
$ vim FILENAME
|
||||||
~~~
|
~~~
|
||||||
|
|
||||||
3. To exit Vim type: <Esc> :q! <Enter> to trash all changes.
|
3. To exit Vim type: `<Esc>`{normal} `:q!`{vim} `<Enter>`{normal} to trash all changes.
|
||||||
OR type: <Esc> :wq <Enter> to save the changes.
|
OR type: `<Esc>`{normal} `:wq`{vim} `<Enter>`{normal} to save the changes.
|
||||||
|
|
||||||
4. To delete the character at the cursor type: `x`{normal}
|
4. To delete the character at the cursor type: `x`{normal}
|
||||||
|
|
||||||
5. To insert or append text type:
|
5. To insert or append text type:
|
||||||
`i`{normal} type inserted text `<Esc>`{normal} insert before the cursor
|
`i`{normal} insert text `<Esc>`{normal} insert before the cursor.
|
||||||
`A`{normal} type appended text `<Esc>`{normal} append after the line
|
`A`{normal} append text `<Esc>`{normal} append after the line.
|
||||||
|
|
||||||
NOTE: Pressing `<Esc>`{normal} will place you in Normal mode or will cancel
|
NOTE: Pressing `<Esc>`{normal} will place you in Normal mode or will cancel
|
||||||
an unwanted and partially completed command.
|
an unwanted and partially completed command.
|
||||||
@ -210,7 +210,7 @@ Now continue with Lesson 2.
|
|||||||
|
|
||||||
3. Move the cursor to the beginning of a word that needs to be deleted.
|
3. Move the cursor to the beginning of a word that needs to be deleted.
|
||||||
|
|
||||||
4. Type [d](d)[w](w) to make the word disappear.
|
4. Type [d](d)[w](w) to make the word disappear.
|
||||||
|
|
||||||
There are a some words fun that don't belong paper in this sentence.
|
There are a some words fun that don't belong paper in this sentence.
|
||||||
|
|
||||||
@ -218,9 +218,9 @@ There are a some words fun that don't belong paper in this sentence.
|
|||||||
|
|
||||||
# Lesson 2.2: MORE DELETION COMMANDS
|
# Lesson 2.2: MORE DELETION COMMANDS
|
||||||
|
|
||||||
** Type `d$`{normal} to delete to the end of the line. **
|
** Type `d$`{normal} to delete to the end of the line. **
|
||||||
|
|
||||||
1. Press <Esc> to make sure you are in Normal mode.
|
1. Press `<Esc>`{normal} to make sure you are in Normal mode.
|
||||||
|
|
||||||
2. Move the cursor to the line below marked --->.
|
2. Move the cursor to the line below marked --->.
|
||||||
|
|
||||||
@ -236,7 +236,7 @@ Somebody typed the end of this line twice. end of this line twice.
|
|||||||
|
|
||||||
|
|
||||||
Many commands that change text are made from an [operator](operator) and a [motion](navigation).
|
Many commands that change text are made from an [operator](operator) and a [motion](navigation).
|
||||||
The format for a delete command with the [d](d) delete operator is as follows:
|
The format for a delete command with the [d](d) delete operator is as follows:
|
||||||
|
|
||||||
d motion
|
d motion
|
||||||
|
|
||||||
@ -249,7 +249,7 @@ The format for a delete command with the [d](d) delete operator is as follows:
|
|||||||
[e](e) - to the end of the current word, INCLUDING the last character.
|
[e](e) - to the end of the current word, INCLUDING the last character.
|
||||||
[$]($) - to the end of the line, INCLUDING the last character.
|
[$]($) - to the end of the line, INCLUDING the last character.
|
||||||
|
|
||||||
Thus typing `de`{normal} will delete from the cursor to the end of the word.
|
Thus typing `de`{normal} will delete from the cursor to the end of the word.
|
||||||
|
|
||||||
NOTE: Pressing just the motion while in Normal mode without an operator will
|
NOTE: Pressing just the motion while in Normal mode without an operator will
|
||||||
move the cursor as specified.
|
move the cursor as specified.
|
||||||
@ -260,11 +260,11 @@ NOTE: Pressing just the motion while in Normal mode without an operator will
|
|||||||
|
|
||||||
1. Move the cursor to the start of the line marked ---> below.
|
1. Move the cursor to the start of the line marked ---> below.
|
||||||
|
|
||||||
2. Type `2w`{normal} to move the cursor two words forward.
|
2. Type `2w`{normal} to move the cursor two words forward.
|
||||||
|
|
||||||
3. Type `3e`{normal} to move the cursor to the end of the third word forward.
|
3. Type `3e`{normal} to move the cursor to the end of the third word forward.
|
||||||
|
|
||||||
4. Type `0`{normal} ([zero](0)) to move to the start of the line.
|
4. Type `0`{normal} ([zero](0)) to move to the start of the line.
|
||||||
|
|
||||||
5. Repeat steps 2 and 3 with different numbers.
|
5. Repeat steps 2 and 3 with different numbers.
|
||||||
|
|
||||||
@ -282,22 +282,22 @@ insert a count before the motion to delete more:
|
|||||||
|
|
||||||
1. Move the cursor to the first UPPER CASE word in the line marked --->.
|
1. Move the cursor to the first UPPER CASE word in the line marked --->.
|
||||||
|
|
||||||
2. Type `d2w`{normal} to delete the two UPPER CASE words
|
2. Type `d2w`{normal} to delete the two UPPER CASE words
|
||||||
|
|
||||||
3. Repeat steps 1 and 2 with a different count to delete the consecutive
|
3. Repeat steps 1 and 2 with a different count to delete the consecutive
|
||||||
UPPER CASE words with one command
|
UPPER CASE words with one command
|
||||||
|
|
||||||
this ABC DE line FGHI JK LMN OP of words is Q RS TUV cleaned up.
|
This ABC DE line FGHI JK LMN OP of words is Q RS TUV cleaned up.
|
||||||
|
|
||||||
# Lesson 2.6: OPERATING ON LINES
|
# Lesson 2.6: OPERATING ON LINES
|
||||||
|
|
||||||
** Type dd to delete a whole line. **
|
** Type `dd`{normal} to delete a whole line. **
|
||||||
|
|
||||||
Due to the frequency of whole line deletion, the designers of Vi decided
|
Due to the frequency of whole line deletion, the designers of Vi decided
|
||||||
it would be easier to simply type two d's to delete a line.
|
it would be easier to simply type two d's to delete a line.
|
||||||
|
|
||||||
1. Move the cursor to the second line in the phrase below.
|
1. Move the cursor to the second line in the phrase below.
|
||||||
2. Type [dd](dd) to delete the line.
|
2. Type [dd](dd) to delete the line.
|
||||||
3. Now move to the fourth line.
|
3. Now move to the fourth line.
|
||||||
4. Type `2dd`{normal} to delete two lines.
|
4. Type `2dd`{normal} to delete two lines.
|
||||||
|
|
||||||
@ -311,20 +311,20 @@ this ABC DE line FGHI JK LMN OP of words is Q RS TUV cleaned up.
|
|||||||
|
|
||||||
# Lesson 2.7: THE UNDO COMMAND
|
# Lesson 2.7: THE UNDO COMMAND
|
||||||
|
|
||||||
** Press u to undo the last commands, U to fix a whole line. **
|
** Press `u`{normal} to undo the last commands, `U`{normal} to fix a whole line. **
|
||||||
|
|
||||||
1. Move the cursor to the line below marked ---> and place it on the
|
1. Move the cursor to the line below marked ---> and place it on the
|
||||||
first error.
|
first error.
|
||||||
2. Type `x`{normal} to delete the first unwanted character.
|
2. Type `x`{normal} to delete the first unwanted character.
|
||||||
3. Now type `u`{normal} to undo the last command executed.
|
3. Now type `u`{normal} to undo the last command executed.
|
||||||
4. This time fix all the errors on the line using the `x`{normal} command.
|
4. This time fix all the errors on the line using the `x`{normal} command.
|
||||||
5. Now type a capital `U`{normal} to return the line to its original state.
|
5. Now type a capital `U`{normal} to return the line to its original state.
|
||||||
6. Now type `u`{normal} a few times to undo the U and preceding commands.
|
6. Now type `u`{normal} a few times to undo the `U`{normal} and preceding commands.
|
||||||
7. Now type `<Ctrl-r>`{normal} a few times to redo the commands (undo the undo's).
|
7. Now type `<Ctrl-r>`{normal} a few times to redo the commands (undo the undo's).
|
||||||
|
|
||||||
Fiix the errors oon thhis line and reeplace them witth undo.
|
Fiix the errors oon thhis line and reeplace them witth undo.
|
||||||
|
|
||||||
8. These are very useful commands. Now move on to the Lesson 2 Summary.
|
8. These are very useful commands. Now move on to the Lesson 2 Summary.
|
||||||
|
|
||||||
# Lesson 2 SUMMARY
|
# Lesson 2 SUMMARY
|
||||||
|
|
||||||
@ -336,13 +336,13 @@ Fiix the errors oon thhis line and reeplace them witth undo.
|
|||||||
5. The format for a change command is:
|
5. The format for a change command is:
|
||||||
operator [number] motion
|
operator [number] motion
|
||||||
where:
|
where:
|
||||||
operator - is what to do, such as [d](d) for delete
|
operator - is what to do, such as [d](d) for delete
|
||||||
[number] - is an optional count to repeat the motion
|
[number] - is an optional count to repeat the motion
|
||||||
motion - moves over the text to operate on, such as:
|
motion - moves over the text to operate on, such as:
|
||||||
[w](w) (word),
|
[w](w) (word),
|
||||||
[$]($) (to the end of line), etc.
|
[$]($) (to the end of line), etc.
|
||||||
|
|
||||||
6. To move to the start of the line use a zero: [0](0)
|
6. To move to the start of the line use a zero: [0](0)
|
||||||
|
|
||||||
7. To undo previous actions, type: `u`{normal} (lowercase u)
|
7. To undo previous actions, type: `u`{normal} (lowercase u)
|
||||||
To undo all the changes on a line, type: `U`{normal} (capital U)
|
To undo all the changes on a line, type: `U`{normal} (capital U)
|
||||||
@ -350,15 +350,15 @@ Fiix the errors oon thhis line and reeplace them witth undo.
|
|||||||
|
|
||||||
# Lesson 3.1: THE PUT COMMAND
|
# Lesson 3.1: THE PUT COMMAND
|
||||||
|
|
||||||
** Type p to put previously deleted text after the cursor. **
|
** Type `p`{normal} to put previously deleted text after the cursor. **
|
||||||
|
|
||||||
1. Move the cursor to the first ---> line below.
|
1. Move the cursor to the first ---> line below.
|
||||||
|
|
||||||
2. Type `dd`{normal} to delete the line and store it in a Vim register.
|
2. Type `dd`{normal} to delete the line and store it in a Vim register.
|
||||||
|
|
||||||
3. Move the cursor to the c) line, ABOVE where the deleted line should go.
|
3. Move the cursor to the c) line, ABOVE where the deleted line should go.
|
||||||
|
|
||||||
4. Type `p`{normal} to put the line below the cursor.
|
4. Type `p`{normal} to put the line below the cursor.
|
||||||
|
|
||||||
5. Repeat steps 2 through 4 to put all the lines in correct order.
|
5. Repeat steps 2 through 4 to put all the lines in correct order.
|
||||||
|
|
||||||
@ -388,11 +388,11 @@ NOTE: Remember that you should be learning by doing, not memorization.
|
|||||||
|
|
||||||
# Lesson 3.3: THE CHANGE OPERATOR
|
# Lesson 3.3: THE CHANGE OPERATOR
|
||||||
|
|
||||||
** To change until the end of a word, type `ce`{normal} **
|
** To change until the end of a word, type `ce`{normal}. **
|
||||||
|
|
||||||
1. Move the cursor to the first line below marked --->.
|
1. Move the cursor to the first line below marked --->.
|
||||||
|
|
||||||
2. Place the cursor on the "u" in "lubw".
|
2. Place the cursor on the "u" in "lubw".
|
||||||
|
|
||||||
3. Type `ce`{normal} and the correct word (in this case, type "ine" ).
|
3. Type `ce`{normal} and the correct word (in this case, type "ine" ).
|
||||||
|
|
||||||
@ -405,11 +405,11 @@ This line has a few words that need changing using the change operator.
|
|||||||
|
|
||||||
Notice that [c](c)e deletes the word and places you in Insert mode.
|
Notice that [c](c)e deletes the word and places you in Insert mode.
|
||||||
|
|
||||||
# Lesson 3.4: MORE CHANGES USING c
|
# Lesson 3.4: MORE CHANGES USING `c`{normal}
|
||||||
|
|
||||||
** The change operator is used with the same motions as delete. **
|
** The change operator is used with the same motions as delete. **
|
||||||
|
|
||||||
1. The change operator works in the same way as delete. The format is:
|
1. The change operator works in the same way as delete. The format is:
|
||||||
|
|
||||||
c [number] motion
|
c [number] motion
|
||||||
|
|
||||||
@ -422,13 +422,13 @@ Notice that [c](c)e deletes the word and places you in Insert mode.
|
|||||||
5. Type `c$`{normal} and type the rest of the line like the second and press `<Esc>`{normal}.
|
5. Type `c$`{normal} and type the rest of the line like the second and press `<Esc>`{normal}.
|
||||||
|
|
||||||
The end of this line needs some help to make it like the second.
|
The end of this line needs some help to make it like the second.
|
||||||
The end of this line needs to be corrected using the c$ command.
|
The end of this line needs to be corrected using the `c$`{normal} command.
|
||||||
|
|
||||||
NOTE: You can use the Backspace key to correct mistakes while typing.
|
NOTE: You can use the Backspace key to correct mistakes while typing.
|
||||||
|
|
||||||
# Lesson 3 SUMMARY
|
# Lesson 3 SUMMARY
|
||||||
|
|
||||||
1. To put back text that has just been deleted, type [p](p). This puts the
|
1. To put back text that has just been deleted, type [p](p). This puts the
|
||||||
deleted text AFTER the cursor (if a line was deleted it will go on the
|
deleted text AFTER the cursor (if a line was deleted it will go on the
|
||||||
line below the cursor).
|
line below the cursor).
|
||||||
|
|
||||||
@ -436,8 +436,8 @@ NOTE: You can use the Backspace key to correct mistakes while typing.
|
|||||||
character you want to have there.
|
character you want to have there.
|
||||||
|
|
||||||
3. The [change operator](c) allows you to change from the cursor to where the
|
3. The [change operator](c) allows you to change from the cursor to where the
|
||||||
motion takes you. eg. Type `ce`{normal} to change from the cursor to the end of
|
motion takes you. Type `ce`{normal} to change from the cursor to the end of
|
||||||
the word, `c$`{normal} to change to the end of a line.
|
the word, `c$`{normal} to change to the end of a line.
|
||||||
|
|
||||||
4. The format for change is:
|
4. The format for change is:
|
||||||
|
|
||||||
@ -448,21 +448,21 @@ Now go on to the next lesson.
|
|||||||
# Lesson 4.1: CURSOR LOCATION AND FILE STATUS
|
# Lesson 4.1: CURSOR LOCATION AND FILE STATUS
|
||||||
|
|
||||||
** Type `<Ctrl-g>`{normal} to show your location in the file and the file status.
|
** Type `<Ctrl-g>`{normal} to show your location in the file and the file status.
|
||||||
Type `G`{normal} to move to a line in the file. **
|
Type `G`{normal} to move to a line in the file. **
|
||||||
|
|
||||||
NOTE: Read this entire lesson before executing any of the steps!!
|
NOTE: Read this entire lesson before executing any of the steps!!
|
||||||
|
|
||||||
1. Hold down the `<Ctrl>`{normal} key and press `g`{normal}. We call this `<Ctrl-g>`{normal}.
|
1. Hold down the `<Ctrl>`{normal} key and press `g`{normal}. We call this `<Ctrl-g>`{normal}.
|
||||||
A message will appear at the bottom of the page with the filename and the
|
A message will appear at the bottom of the page with the filename and the
|
||||||
position in the file. Remember the line number for Step 3.
|
position in the file. Remember the line number for Step 3.
|
||||||
|
|
||||||
NOTE: You may see the cursor position in the lower right corner of the screen
|
NOTE: You may see the cursor position in the lower right corner of the screen
|
||||||
This happens when the ['ruler']('ruler') option is set (see :help 'ruler' )
|
This happens when the ['ruler']('ruler') option is set (see `:help 'ruler'`{vim} ).
|
||||||
|
|
||||||
2. Press [G](G) to move you to the bottom of the file.
|
2. Press [G](G) to move you to the bottom of the file.
|
||||||
Type [gg](gg) to move you to the start of the file.
|
Type [gg](gg) to move you to the start of the file.
|
||||||
|
|
||||||
3. Type the number of the line you were on and then `G`{normal} . This will
|
3. Type the number of the line you were on and then `G`{normal}. This will
|
||||||
return you to the line you were on when you first pressed `<Ctrl-g>`{normal}.
|
return you to the line you were on when you first pressed `<Ctrl-g>`{normal}.
|
||||||
|
|
||||||
4. If you feel confident to do this, execute steps 1 through 3.
|
4. If you feel confident to do this, execute steps 1 through 3.
|
||||||
@ -471,20 +471,20 @@ NOTE: You may see the cursor position in the lower right corner of the screen
|
|||||||
|
|
||||||
** Type `/`{normal} followed by a phrase to search for the phrase. **
|
** Type `/`{normal} followed by a phrase to search for the phrase. **
|
||||||
|
|
||||||
1. In Normal mode type the `/`{normal} character. Notice that it and the cursor
|
1. In Normal mode type the `/`{normal} character. Notice that it and the cursor
|
||||||
appear at the bottom of the screen as with the : command.
|
appear at the bottom of the screen as with the `:`{normal} command.
|
||||||
|
|
||||||
2. Now type 'errroor' `<Enter>`{normal}. This is the word you want to search for.
|
2. Now type 'errroor' `<Enter>`{normal}. This is the word you want to search for.
|
||||||
|
|
||||||
3. To search for the same phrase again, simply type [n](n) .
|
3. To search for the same phrase again, simply type [n](n).
|
||||||
To search for the same phrase in the opposite direction, type [N](N) .
|
To search for the same phrase in the opposite direction, type [N](N).
|
||||||
|
|
||||||
4. To search for a phrase in the backward direction, use [?](?) instead of / .
|
4. To search for a phrase in the backward direction, use [?](?) instead of `/`{normal}.
|
||||||
|
|
||||||
5. To go back to where you came from press `<Ctrl-o>`{normal} (Keep Ctrl down while
|
5. To go back to where you came from press `<Ctrl-o>`{normal} (keep `<Ctrl>`{normal} pressed down while
|
||||||
pressing the letter o). Repeat to go back further. `<Ctrl-i>`{normal} goes forward.
|
pressing the letter `o`{normal}). Repeat to go back further. `<Ctrl-i>`{normal} goes forward.
|
||||||
|
|
||||||
"errroor" is not the way to spell error; errroor is an error.
|
"errroor" is not the way to spell error; errroor is an error.
|
||||||
|
|
||||||
NOTE: When the search reaches the end of the file it will continue at the
|
NOTE: When the search reaches the end of the file it will continue at the
|
||||||
start, unless the ['wrapscan']('wrapscan') option has been reset.
|
start, unless the ['wrapscan']('wrapscan') option has been reset.
|
||||||
@ -495,7 +495,7 @@ NOTE: When the search reaches the end of the file it will continue at the
|
|||||||
|
|
||||||
1. Place the cursor on any (, [, or { in the line below marked --->.
|
1. Place the cursor on any (, [, or { in the line below marked --->.
|
||||||
|
|
||||||
2. Now type the [%](%) character.
|
2. Now type the [%](%) character.
|
||||||
|
|
||||||
3. The cursor will move to the matching parenthesis or bracket.
|
3. The cursor will move to the matching parenthesis or bracket.
|
||||||
|
|
||||||
@ -528,7 +528,7 @@ NOTE: This is very useful in debugging a program with unmatched parentheses!
|
|||||||
Adding the g [flag](:s_flags) means to substitute globally in the line, change
|
Adding the g [flag](:s_flags) means to substitute globally in the line, change
|
||||||
all occurrences of "thee" in the line.
|
all occurrences of "thee" in the line.
|
||||||
|
|
||||||
thee best time to see thee flowers is in thee spring.
|
Usually thee best time to see thee flowers is in thee spring.
|
||||||
|
|
||||||
4. To change every occurrence of a character string between two lines, type
|
4. To change every occurrence of a character string between two lines, type
|
||||||
~~~ cmd
|
~~~ cmd
|
||||||
@ -589,20 +589,20 @@ thee best time to see thee flowers is in thee spring.
|
|||||||
** Type `:!`{vim} followed by an external command to execute that command. **
|
** Type `:!`{vim} followed by an external command to execute that command. **
|
||||||
|
|
||||||
1. Type the familiar command `:`{normal} to set the cursor at the bottom of the
|
1. Type the familiar command `:`{normal} to set the cursor at the bottom of the
|
||||||
screen. This allows you to enter a command-line command.
|
screen. This allows you to enter a command-line command.
|
||||||
|
|
||||||
2. Now type the [!](!cmd) (exclamation point) character. This allows you to
|
2. Now type the [!](!cmd) (exclamation point) character. This allows you to
|
||||||
execute any external shell command.
|
execute any external shell command.
|
||||||
|
|
||||||
3. As an example type "ls" following the "!" and then hit `<Enter>`{normal}. This
|
3. As an example type "ls" following the "!" and then hit `<Enter>`{normal}. This
|
||||||
will show you a listing of your directory, just as if you were at the
|
will show you a listing of your directory, just as if you were at the
|
||||||
shell prompt.
|
shell prompt.
|
||||||
|
|
||||||
NOTE: It is possible to execute any external command this way, also with
|
NOTE: It is possible to execute any external command this way, also with
|
||||||
arguments.
|
arguments.
|
||||||
|
|
||||||
NOTE: All : commands must be finished by hitting <Enter>
|
NOTE: All `:`{vim} commands must be finished by hitting `<Enter>`{normal}.
|
||||||
From here on we will not always mention it.
|
From here on we will not always mention it.
|
||||||
|
|
||||||
# Lesson 5.2: MORE ON WRITING FILES
|
# Lesson 5.2: MORE ON WRITING FILES
|
||||||
|
|
||||||
@ -622,7 +622,7 @@ NOTE: All : commands must be finished by hitting <Enter>
|
|||||||
4. This saves the whole file (the Vim Tutor) under the name TEST.
|
4. This saves the whole file (the Vim Tutor) under the name TEST.
|
||||||
To verify this, type `:!ls`{vim} again to see your directory.
|
To verify this, type `:!ls`{vim} again to see your directory.
|
||||||
|
|
||||||
NOTE: If you were to exit Vim and start it again with vim TEST , the file
|
NOTE: If you were to exit Vim and start it again with `nvim TEST`, the file
|
||||||
would be an exact copy of the tutor when you saved it.
|
would be an exact copy of the tutor when you saved it.
|
||||||
|
|
||||||
5. Now remove the file by typing:
|
5. Now remove the file by typing:
|
||||||
@ -632,14 +632,14 @@ NOTE: If you were to exit Vim and start it again with vim TEST , the file
|
|||||||
|
|
||||||
# Lesson 5.3: SELECTING TEXT TO WRITE
|
# Lesson 5.3: SELECTING TEXT TO WRITE
|
||||||
|
|
||||||
** To save part of the file, type `v`{normal} motion `:w FILENAME`{vim} **
|
** To save part of the file, type `v`{normal} motion `:w FILENAME`{vim}. **
|
||||||
|
|
||||||
1. Move the cursor to this line.
|
1. Move the cursor to this line.
|
||||||
|
|
||||||
2. Press [v](v) and move the cursor to the fifth item below. Notice that the
|
2. Press [v](v) and move the cursor to the fifth item below. Notice that the
|
||||||
text is highlighted.
|
text is highlighted.
|
||||||
|
|
||||||
3. Press the `:`{normal} character. At the bottom of the screen
|
3. Press the `:`{normal} character. At the bottom of the screen
|
||||||
|
|
||||||
:'<,'>
|
:'<,'>
|
||||||
|
|
||||||
@ -649,27 +649,27 @@ NOTE: If you were to exit Vim and start it again with vim TEST , the file
|
|||||||
|
|
||||||
`:w TEST`{vim}
|
`:w TEST`{vim}
|
||||||
|
|
||||||
where TEST is a filename that does not exist yet. Verify that you see
|
where TEST is a filename that does not exist yet. Verify that you see
|
||||||
|
|
||||||
`:'<,'>w TEST`{vim}
|
`:'<,'>w TEST`{vim}
|
||||||
|
|
||||||
before you press `<Enter>`{normal}.
|
before you press `<Enter>`{normal}.
|
||||||
|
|
||||||
5. Vim will write the selected lines to the file TEST. Use `:!ls`{vim} to see it.
|
5. Vim will write the selected lines to the file TEST. Use `:!ls`{vim} to see it.
|
||||||
Do not remove it yet! We will use it in the next lesson.
|
Do not remove it yet! We will use it in the next lesson.
|
||||||
|
|
||||||
NOTE: Pressing [v](v) starts [Visual selection](visual-mode). You can move
|
NOTE: Pressing [v](v) starts [Visual selection](visual-mode). You can move
|
||||||
the cursor around to make the selection bigger or smaller. Then you can
|
the cursor around to make the selection bigger or smaller. Then you can
|
||||||
use an operator to do something with the text. For example, `d`{normal} deletes
|
use an operator to do something with the text. For example, `d`{normal} deletes
|
||||||
the text.
|
the text.
|
||||||
|
|
||||||
# Lesson 5.4: RETRIEVING AND MERGING FILES
|
# Lesson 5.4: RETRIEVING AND MERGING FILES
|
||||||
|
|
||||||
** To insert the contents of a file, type `:r FILENAME`{vim} **
|
** To insert the contents of a file, type `:r FILENAME`{vim}. **
|
||||||
|
|
||||||
1. Place the cursor just above this line.
|
1. Place the cursor just above this line.
|
||||||
|
|
||||||
NOTE: After executing Step 2 you will see text from Lesson 5.3. Then move
|
NOTE: After executing Step 2 you will see text from Lesson 5.3. Then move
|
||||||
DOWN to see this lesson again.
|
DOWN to see this lesson again.
|
||||||
|
|
||||||
2. Now retrieve your TEST file using the command
|
2. Now retrieve your TEST file using the command
|
||||||
@ -682,31 +682,31 @@ NOTE: After executing Step 2 you will see text from Lesson 5.3. Then move
|
|||||||
3. To verify that a file was retrieved, cursor back and notice that there
|
3. To verify that a file was retrieved, cursor back and notice that there
|
||||||
are now two copies of Lesson 5.3, the original and the file version.
|
are now two copies of Lesson 5.3, the original and the file version.
|
||||||
|
|
||||||
NOTE: You can also read the output of an external command. For example,
|
NOTE: You can also read the output of an external command. For example,
|
||||||
|
|
||||||
`:r !ls`{vim}
|
`:r !ls`{vim}
|
||||||
|
|
||||||
reads the output of the `ls` command and puts it below the cursor.
|
reads the output of the `ls` command and puts it below the cursor.
|
||||||
|
|
||||||
# Lesson 5 SUMMARY
|
# Lesson 5 SUMMARY
|
||||||
|
|
||||||
1. [:!command](:!cmd) executes an external command.
|
1. [:!command](:!cmd) executes an external command.
|
||||||
|
|
||||||
Some useful examples are:
|
Some useful examples are:
|
||||||
`:!ls`{vim} - shows a directory listing
|
`:!ls`{vim} - shows a directory listing
|
||||||
`:!rm FILENAME`{vim} - removes file FILENAME
|
`:!rm FILENAME`{vim} - removes file FILENAME
|
||||||
|
|
||||||
2. [:w](:w) FILENAME writes the current Vim file to disk with
|
2. [:w](:w) FILENAME writes the current Vim file to disk with
|
||||||
name FILENAME.
|
name FILENAME.
|
||||||
|
|
||||||
3. [v](v) motion :w FILENAME saves the Visually selected lines in file
|
3. [v](v) motion :w FILENAME saves the Visually selected lines in file
|
||||||
FILENAME.
|
FILENAME.
|
||||||
|
|
||||||
4. [:r](:r) FILENAME retrieves disk file FILENAME and puts it
|
4. [:r](:r) FILENAME retrieves disk file FILENAME and puts it
|
||||||
below the cursor position.
|
below the cursor position.
|
||||||
|
|
||||||
5. [:r !dir](:r!) reads the output of the dir command and
|
5. [:r !dir](:r!) reads the output of the dir command and
|
||||||
puts it below the cursor position.
|
puts it below the cursor position.
|
||||||
|
|
||||||
# Lesson 6.1: THE OPEN COMMAND
|
# Lesson 6.1: THE OPEN COMMAND
|
||||||
|
|
||||||
@ -719,10 +719,10 @@ NOTE: You can also read the output of an external command. For example,
|
|||||||
|
|
||||||
3. Now type some text and press `<Esc>`{normal} to exit Insert mode.
|
3. Now type some text and press `<Esc>`{normal} to exit Insert mode.
|
||||||
|
|
||||||
After typing o the cursor is placed on the open line in Insert mode.
|
After typing `o`{normal} the cursor is placed on the open line in Insert mode.
|
||||||
|
|
||||||
4. To open up a line ABOVE the cursor, simply type a [capital O](O), rather
|
4. To open up a line ABOVE the cursor, simply type a [capital O](O), rather
|
||||||
than a lowercase `o`{normal}. Try this on the line below.
|
than a lowercase `o`{normal}. Try this on the line below.
|
||||||
|
|
||||||
Open up a line above this by typing O while the cursor is on this line.
|
Open up a line above this by typing O while the cursor is on this line.
|
||||||
|
|
||||||
@ -734,9 +734,9 @@ Open up a line above this by typing O while the cursor is on this line.
|
|||||||
|
|
||||||
2. Press `e`{normal} until the cursor is on the end of "li".
|
2. Press `e`{normal} until the cursor is on the end of "li".
|
||||||
|
|
||||||
3. Type an `a`{normal} (lowercase) to [append](a) text AFTER the cursor.
|
3. Type the lowercase letter `a`{normal} to [append](a) text AFTER the cursor.
|
||||||
|
|
||||||
4. Complete the word like the line below it. Press `<Esc>`{normal} to exit Insert
|
4. Complete the word like the line below it. Press `<Esc>`{normal} to exit Insert
|
||||||
mode.
|
mode.
|
||||||
|
|
||||||
5. Use `e`{normal} to move to the next incomplete word and repeat steps 3 and 4.
|
5. Use `e`{normal} to move to the next incomplete word and repeat steps 3 and 4.
|
||||||
@ -744,20 +744,20 @@ Open up a line above this by typing O while the cursor is on this line.
|
|||||||
This li will allow you to pract appendi text to a line.
|
This li will allow you to pract appendi text to a line.
|
||||||
This line will allow you to practice appending text to a line.
|
This line will allow you to practice appending text to a line.
|
||||||
|
|
||||||
NOTE: [a](a), [i](i) and [A](A) all go to the same Insert mode, the only difference is where
|
NOTE: [a](a), [i](i) and [A](A) all go to the same Insert mode, the only difference is where
|
||||||
the characters are inserted.
|
the characters are inserted.
|
||||||
|
|
||||||
# Lesson 6.3: ANOTHER WAY TO REPLACE
|
# Lesson 6.3: ANOTHER WAY TO REPLACE
|
||||||
|
|
||||||
** Type a capital `R`{normal} to replace more than one character. **
|
** Type a capital `R`{normal} to replace more than one character. **
|
||||||
|
|
||||||
1. Move the cursor to the first line below marked --->. Move the cursor to
|
1. Move the cursor to the first line below marked --->. Move the cursor to
|
||||||
the beginning of the first "xxx".
|
the beginning of the first "xxx".
|
||||||
|
|
||||||
2. Now press `R`{normal} ([capital R](R)) and type the number below it in the second line, so that it
|
2. Now press `R`{normal} ([capital R](R)) and type the number below it in the second line, so that it
|
||||||
replaces the "xxx".
|
replaces the "xxx".
|
||||||
|
|
||||||
3. Press `<Esc>`{normal} to leave [Replace mode](mode-replace). Notice that the rest of the line
|
3. Press `<Esc>`{normal} to leave [Replace mode](mode-replace). Notice that the rest of the line
|
||||||
remains unmodified.
|
remains unmodified.
|
||||||
|
|
||||||
4. Repeat the steps to replace the remaining "xxx".
|
4. Repeat the steps to replace the remaining "xxx".
|
||||||
@ -765,12 +765,12 @@ NOTE: [a](a), [i](i) and [A](A) all go to the same Insert mode, the only differ
|
|||||||
Adding 123 to xxx gives you xxx.
|
Adding 123 to xxx gives you xxx.
|
||||||
Adding 123 to 456 gives you 579.
|
Adding 123 to 456 gives you 579.
|
||||||
|
|
||||||
NOTE: Replace mode is like Insert mode, but every typed character deletes an
|
NOTE: Replace mode is like Insert mode, but every typed character deletes an
|
||||||
existing character.
|
existing character.
|
||||||
|
|
||||||
# Lesson 6.4: COPY AND PASTE TEXT
|
# Lesson 6.4: COPY AND PASTE TEXT
|
||||||
|
|
||||||
** Use the `y`{normal} operator to copy text and `p`{normal} to paste it **
|
** Use the `y`{normal} operator to copy text and `p`{normal} to paste it. **
|
||||||
|
|
||||||
1. Go to the line marked with ---> below and place the cursor after "a)".
|
1. Go to the line marked with ---> below and place the cursor after "a)".
|
||||||
|
|
||||||
@ -780,35 +780,37 @@ NOTE: Replace mode is like Insert mode, but every typed character deletes an
|
|||||||
|
|
||||||
4. Move the cursor to the end of the next line: `j$`{normal}
|
4. Move the cursor to the end of the next line: `j$`{normal}
|
||||||
|
|
||||||
5. Type `p`{normal} to [put](put) (paste) the text. Then type: "a second"`<Esc>`{normal}.
|
5. Type `p`{normal} to [put](put) (paste) the text.
|
||||||
|
|
||||||
6. Use Visual mode to select " item.", yank it with `y`{normal}, move to the end of
|
6. Press `a`{normal} and then type "second". Press `<Esc>`{normal} to leave Insert mode.
|
||||||
|
|
||||||
|
7. Use Visual mode to select " item.", yank it with `y`{normal}, move to the end of
|
||||||
the next line with `j$`{normal} and put the text there with `p`{normal}.
|
the next line with `j$`{normal} and put the text there with `p`{normal}.
|
||||||
|
|
||||||
a) this is the first item.
|
a) This is the first item.
|
||||||
b)
|
b)
|
||||||
|
|
||||||
NOTE: you can also use `y`{normal} as an operator; `yw`{normal} yanks one word.
|
NOTE: you can also use `y`{normal} as an operator; `yw`{normal} yanks one word.
|
||||||
|
|
||||||
# Lesson 6.5: SET OPTION
|
# Lesson 6.5: SET OPTION
|
||||||
|
|
||||||
** Set an option so a search or substitute ignores case **
|
** Set an option so a search or substitute ignores case. **
|
||||||
|
|
||||||
1. Search for 'ignore' by entering: `/ignore`
|
1. Search for 'ignore' by entering: `/ignore`
|
||||||
Repeat several times by pressing `n`{normal}.
|
Repeat several times by pressing `n`{normal}.
|
||||||
|
|
||||||
2. Set the 'ic' (Ignore case) option by entering:
|
2. Set the 'ic' (Ignore case) option by entering:
|
||||||
~~~ cmd
|
~~~ cmd
|
||||||
:set ic
|
:set ic
|
||||||
~~~
|
~~~
|
||||||
3. Now search for 'ignore' again by pressing n
|
3. Now search for 'ignore' again by pressing `n`{normal}.
|
||||||
Notice that Ignore and IGNORE are now also found.
|
Notice that Ignore and IGNORE are now also found.
|
||||||
|
|
||||||
4. Set the 'hlsearch' and 'incsearch' options:
|
4. Set the 'hlsearch' and 'incsearch' options:
|
||||||
~~~ cmd
|
~~~ cmd
|
||||||
:set hls is
|
:set hls is
|
||||||
~~~
|
~~~
|
||||||
5. Now type the search command again and see what happens: /ignore <Enter>
|
5. Now type the search command again and see what happens: /ignore <Enter>
|
||||||
|
|
||||||
6. To disable ignoring case enter:
|
6. To disable ignoring case enter:
|
||||||
~~~ cmd
|
~~~ cmd
|
||||||
@ -818,12 +820,12 @@ a) this is the first item.
|
|||||||
~~~ cmd
|
~~~ cmd
|
||||||
:set invic
|
:set invic
|
||||||
~~~
|
~~~
|
||||||
NOTE: To remove the highlighting of matches enter:
|
NOTE: To remove the highlighting of matches enter:
|
||||||
~~~ cmd
|
~~~ cmd
|
||||||
:nohlsearch
|
:nohlsearch
|
||||||
~~~
|
~~~
|
||||||
NOTE: If you want to ignore case for just one search command, use [\c](/\c)
|
NOTE: If you want to ignore case for just one search command, use [\c](/\c)
|
||||||
in the phrase: /ignore\c <Enter>
|
in the phrase: /ignore\c <Enter>
|
||||||
|
|
||||||
# Lesson 6 SUMMARY
|
# Lesson 6 SUMMARY
|
||||||
|
|
||||||
@ -839,7 +841,7 @@ NOTE: If you want to ignore case for just one search command, use [\c](/\c)
|
|||||||
|
|
||||||
5. Typing a capital `R`{normal} enters Replace mode until `<Esc>`{normal} is pressed.
|
5. Typing a capital `R`{normal} enters Replace mode until `<Esc>`{normal} is pressed.
|
||||||
|
|
||||||
6. Typing "[:set](:set) xxx" sets the option "xxx". Some options are:
|
6. Typing "[:set](:set) xxx" sets the option "xxx". Some options are:
|
||||||
|
|
||||||
'ic' 'ignorecase' ignore upper/lower case when searching
|
'ic' 'ignorecase' ignore upper/lower case when searching
|
||||||
'is' 'incsearch' show partial matches for a search phrase
|
'is' 'incsearch' show partial matches for a search phrase
|
||||||
@ -858,9 +860,9 @@ NOTE: If you want to ignore case for just one search command, use [\c](/\c)
|
|||||||
|
|
||||||
# Lesson 7.1: GETTING HELP
|
# Lesson 7.1: GETTING HELP
|
||||||
|
|
||||||
** Use the on-line help system **
|
** Use the on-line help system. **
|
||||||
|
|
||||||
Vim has a comprehensive on-line help system. To get started, try one of
|
Vim has a comprehensive on-line help system. To get started, try one of
|
||||||
these three:
|
these three:
|
||||||
- press the `<HELP>`{normal} key (if you have one)
|
- press the `<HELP>`{normal} key (if you have one)
|
||||||
- press the `<F1>`{normal} key (if you have one)
|
- press the `<F1>`{normal} key (if you have one)
|
||||||
@ -872,7 +874,7 @@ Type `<Ctrl-w><Ctrl-w>`{normal} to jump from one window to another.
|
|||||||
Type `:q`{vim} to close the help window.
|
Type `:q`{vim} to close the help window.
|
||||||
|
|
||||||
You can find help on just about any subject, by giving an argument to the
|
You can find help on just about any subject, by giving an argument to the
|
||||||
":help" command. Try these (don't forget pressing <Enter>):
|
":help" command. Try these (don't forget pressing <Enter>):
|
||||||
~~~ cmd
|
~~~ cmd
|
||||||
:help w
|
:help w
|
||||||
:help c_CTRL-D
|
:help c_CTRL-D
|
||||||
@ -881,13 +883,13 @@ You can find help on just about any subject, by giving an argument to the
|
|||||||
~~~
|
~~~
|
||||||
# Lesson 7.2: CREATE A STARTUP SCRIPT
|
# Lesson 7.2: CREATE A STARTUP SCRIPT
|
||||||
|
|
||||||
** Enable Vim features **
|
** Enable Vim features. **
|
||||||
|
|
||||||
Vim has many more features than Vi, but most of them are disabled by
|
Vim has many more features than Vi, but most of them are disabled by
|
||||||
default. To start using more features you have to create a "vimrc" file.
|
default. To start using more features you have to create a "vimrc" file.
|
||||||
|
|
||||||
1. Start editing the "vimrc" file. This depends on your system:
|
1. Start editing the "vimrc" file. This depends on your system:
|
||||||
`:e ~/.config/nvim/init.vim`{vim} for Unix-like systems
|
`:e ~/.config/nvim/init.vim`{vim} for Unix-like systems
|
||||||
|
|
||||||
2. Now read the example "vimrc" file contents:
|
2. Now read the example "vimrc" file contents:
|
||||||
`:r $VIMRUNTIME/vimrc_example.vim`{vim}
|
`:r $VIMRUNTIME/vimrc_example.vim`{vim}
|
||||||
@ -897,15 +899,15 @@ default. To start using more features you have to create a "vimrc" file.
|
|||||||
|
|
||||||
The next time you start Vim it will use syntax highlighting.
|
The next time you start Vim it will use syntax highlighting.
|
||||||
You can add all your preferred settings to this "vimrc" file.
|
You can add all your preferred settings to this "vimrc" file.
|
||||||
For more information type :help vimrc-intro
|
For more information type `:help vimrc-intro`{vim}.
|
||||||
|
|
||||||
# Lesson 7.3: COMPLETION
|
# Lesson 7.3: COMPLETION
|
||||||
|
|
||||||
** Command line completion with `<Ctrl-d>`{normal} and `<Tab>`{normal} **
|
** Command line completion with `<Ctrl-d>`{normal} and `<Tab>`{normal}. **
|
||||||
|
|
||||||
1. Look what files exist in the directory: `:!ls`{vim}
|
1. Look what files exist in the directory: `:!ls`{vim}
|
||||||
|
|
||||||
2. Type the start of a command: `:e`{vim}
|
2. Type the start of a command: `:e`{vim}
|
||||||
|
|
||||||
3. Press `<Ctrl-d>`{normal} and Vim will show a list of commands that start with "e".
|
3. Press `<Ctrl-d>`{normal} and Vim will show a list of commands that start with "e".
|
||||||
|
|
||||||
@ -913,20 +915,20 @@ default. To start using more features you have to create a "vimrc" file.
|
|||||||
|
|
||||||
5. Now add a space and the start of an existing file name: `:edit FIL`{vim}
|
5. Now add a space and the start of an existing file name: `:edit FIL`{vim}
|
||||||
|
|
||||||
6. Press `<Tab>`{normal}. Vim will complete the name (if it is unique).
|
6. Press `<Tab>`{normal}. Vim will complete the name (if it is unique).
|
||||||
|
|
||||||
NOTE: Completion works for many commands. It is especially useful for `:help`{vim}.
|
NOTE: Completion works for many commands. It is especially useful for `:help`{vim}.
|
||||||
|
|
||||||
# Lesson 7 SUMMARY
|
# Lesson 7 SUMMARY
|
||||||
|
|
||||||
1. Type `:help`{vim}
|
1. Type `:help`{vim}
|
||||||
or press `<F1>`{normal} or `<Help>`{normal} to open a help window.
|
or press `<F1>`{normal} or `<Help>`{normal} to open a help window.
|
||||||
|
|
||||||
2. Type `:help TOPIC`{vim} to find help on TOPIC.
|
2. Type `:help TOPIC`{vim} to find help on TOPIC.
|
||||||
|
|
||||||
3. Type `<Ctrl-w><Ctrl-w>`{normal} to jump to another window
|
3. Type `<Ctrl-w><Ctrl-w>`{normal} to jump to another window
|
||||||
|
|
||||||
4. Type `:q`{vim} to close the help window
|
4. Type `:q`{vim} to close the help window
|
||||||
|
|
||||||
5. Create a vimrc startup script to keep your preferred settings.
|
5. Create a vimrc startup script to keep your preferred settings.
|
||||||
|
|
||||||
@ -937,24 +939,24 @@ NOTE: Completion works for many commands. It is especially useful for `:help`{v
|
|||||||
|
|
||||||
This was intended to give a brief overview of the Vim editor, just enough to
|
This was intended to give a brief overview of the Vim editor, just enough to
|
||||||
allow you to use the editor fairly easily. It is far from complete as Vim has
|
allow you to use the editor fairly easily. It is far from complete as Vim has
|
||||||
many many more commands. Consult the help often.
|
many many more commands. Consult the help often.
|
||||||
|
|
||||||
There are many resources online to learn more about vim. Here's a bunch of them:
|
There are many resources online to learn more about vim. Here's a bunch of them:
|
||||||
|
|
||||||
- *Learn Vim Progressively*: http://yannesposito.com/Scratch/en/blog/Learn-Vim-Progressively/
|
- *Learn Vim Progressively*: http://yannesposito.com/Scratch/en/blog/Learn-Vim-Progressively/
|
||||||
- *Learning Vim in 2014*: http://benmccormick.org/learning-vim-in-2014/
|
- *Learning Vim in 2014*: http://benmccormick.org/learning-vim-in-2014/
|
||||||
- Vimcasts: http://vimcasts.org/
|
- *Vimcasts*: http://vimcasts.org/
|
||||||
- Vim Video-Tutorials by Derek Wyatt: http://derekwyatt.org/vim/tutorials/
|
- *Vim Video-Tutorials by Derek Wyatt*: http://derekwyatt.org/vim/tutorials/
|
||||||
- *Learn Vimscript the Hard Way*: http://learnvimscriptthehardway.stevelosh.com/
|
- *Learn Vimscript the Hard Way*: http://learnvimscriptthehardway.stevelosh.com/
|
||||||
- *7 Habits of Effective Text Editing*: http://www.moolenaar.net/habits.html
|
- *7 Habits of Effective Text Editing*: http://www.moolenaar.net/habits.html
|
||||||
- *vim-galore*: https://github.com/mhinz/vim-galore
|
- *vim-galore*: https://github.com/mhinz/vim-galore
|
||||||
|
|
||||||
If you prefer a book, *Practical Vim* by Drew Neil is recommended often (the sequel, *Modern
|
If you prefer a book, *Practical Vim* by Drew Neil is recommended often (the sequel, *Modern
|
||||||
Vim*, includes material specific to nvim!).
|
Vim*, includes material specific to nvim).
|
||||||
|
|
||||||
This tutorial was written by Michael C. Pierce and Robert K. Ware, Colorado
|
This tutorial was written by Michael C. Pierce and Robert K. Ware, Colorado
|
||||||
School of Mines using ideas supplied by Charles Smith, Colorado State
|
School of Mines using ideas supplied by Charles Smith, Colorado State
|
||||||
University. E-mail: bware@mines.colorado.edu.
|
University. E-mail: bware@mines.colorado.edu.
|
||||||
|
|
||||||
Modified for Vim by Bram Moolenaar.
|
Modified for Vim by Bram Moolenaar.
|
||||||
Modified for vim-tutor-mode by Felipe Morales.
|
Modified for vim-tutor-mode by Felipe Morales.
|
||||||
|
@ -11,7 +11,7 @@
|
|||||||
"215": "There are some words that don't belong in this sentence.",
|
"215": "There are some words that don't belong in this sentence.",
|
||||||
"231": "Somebody typed the end of this line twice.",
|
"231": "Somebody typed the end of this line twice.",
|
||||||
"271": -1,
|
"271": -1,
|
||||||
"290": "this line of words is cleaned up.",
|
"290": "This line of words is cleaned up.",
|
||||||
"304": -1,
|
"304": -1,
|
||||||
"305": -1,
|
"305": -1,
|
||||||
"306": -1,
|
"306": -1,
|
||||||
@ -32,14 +32,14 @@
|
|||||||
"425": "The end of this line needs to be corrected using the c$ command.",
|
"425": "The end of this line needs to be corrected using the c$ command.",
|
||||||
"487": -1,
|
"487": -1,
|
||||||
"506": -1,
|
"506": -1,
|
||||||
"531": "the best time to see the flowers is in the spring.",
|
"531": "Usually the best time to see the flowers is in the spring.",
|
||||||
"722": -1,
|
"722": -1,
|
||||||
"727": -1,
|
"727": -1,
|
||||||
"744": "This line will allow you to practice appending text to a line.",
|
"744": "This line will allow you to practice appending text to a line.",
|
||||||
"745": "This line will allow you to practice appending text to a line.",
|
"745": "This line will allow you to practice appending text to a line.",
|
||||||
"765": "Adding 123 to 456 gives you 579.",
|
"765": "Adding 123 to 456 gives you 579.",
|
||||||
"766": "Adding 123 to 456 gives you 579.",
|
"766": "Adding 123 to 456 gives you 579.",
|
||||||
"788": "a) this is the first item.",
|
"790": "a) This is the first item.",
|
||||||
"789": " b) this is the second item."
|
"791": " b) This is the second item."
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -133,7 +133,7 @@ preprocess_patch() {
|
|||||||
|
|
||||||
# Remove *.proto, Make*, gui_*, some if_*
|
# Remove *.proto, Make*, gui_*, some if_*
|
||||||
local na_src='proto\|Make*\|gui_*\|if_lua\|if_mzsch\|if_olepp\|if_ole\|if_perl\|if_py\|if_ruby\|if_tcl\|if_xcmdsrv'
|
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*\<\%('${na_src}'\)@norm! d/\v(^diff)|%$
' +w +q "$file"
|
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
|
# 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'
|
local na_doc='channel\.txt\|netbeans\.txt\|os_\w\+\.txt\|term\.txt\|todo\.txt\|version\d\.txt\|tags'
|
||||||
|
@ -10,6 +10,11 @@ if(USE_GCOV)
|
|||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if(WIN32)
|
||||||
|
# tell MinGW compiler to enable wmain
|
||||||
|
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -municode")
|
||||||
|
endif()
|
||||||
|
|
||||||
set(TOUCHES_DIR ${PROJECT_BINARY_DIR}/touches)
|
set(TOUCHES_DIR ${PROJECT_BINARY_DIR}/touches)
|
||||||
set(GENERATOR_DIR ${CMAKE_CURRENT_LIST_DIR}/generators)
|
set(GENERATOR_DIR ${CMAKE_CURRENT_LIST_DIR}/generators)
|
||||||
set(GENERATED_DIR ${PROJECT_BINARY_DIR}/src/nvim/auto)
|
set(GENERATED_DIR ${PROJECT_BINARY_DIR}/src/nvim/auto)
|
||||||
|
@ -215,6 +215,7 @@ static void ui_set_option(UI *ui, String name, Object value, Error *error)
|
|||||||
#undef UI_EXT_OPTION
|
#undef UI_EXT_OPTION
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Pushes data into UI.UIData, to be consumed later by remote_ui_flush().
|
||||||
static void push_call(UI *ui, char *name, Array args)
|
static void push_call(UI *ui, char *name, Array args)
|
||||||
{
|
{
|
||||||
Array call = ARRAY_DICT_INIT;
|
Array call = ARRAY_DICT_INIT;
|
||||||
@ -241,39 +242,7 @@ static void push_call(UI *ui, char *name, Array args)
|
|||||||
static void remote_ui_highlight_set(UI *ui, HlAttrs attrs)
|
static void remote_ui_highlight_set(UI *ui, HlAttrs attrs)
|
||||||
{
|
{
|
||||||
Array args = ARRAY_DICT_INIT;
|
Array args = ARRAY_DICT_INIT;
|
||||||
Dictionary hl = ARRAY_DICT_INIT;
|
Dictionary hl = hlattrs2dict(attrs);
|
||||||
|
|
||||||
if (attrs.bold) {
|
|
||||||
PUT(hl, "bold", BOOLEAN_OBJ(true));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (attrs.underline) {
|
|
||||||
PUT(hl, "underline", BOOLEAN_OBJ(true));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (attrs.undercurl) {
|
|
||||||
PUT(hl, "undercurl", BOOLEAN_OBJ(true));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (attrs.italic) {
|
|
||||||
PUT(hl, "italic", BOOLEAN_OBJ(true));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (attrs.reverse) {
|
|
||||||
PUT(hl, "reverse", BOOLEAN_OBJ(true));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (attrs.foreground != -1) {
|
|
||||||
PUT(hl, "foreground", INTEGER_OBJ(attrs.foreground));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (attrs.background != -1) {
|
|
||||||
PUT(hl, "background", INTEGER_OBJ(attrs.background));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (attrs.special != -1) {
|
|
||||||
PUT(hl, "special", INTEGER_OBJ(attrs.special));
|
|
||||||
}
|
|
||||||
|
|
||||||
ADD(args, DICTIONARY_OBJ(hl));
|
ADD(args, DICTIONARY_OBJ(hl));
|
||||||
push_call(ui, "highlight_set", args);
|
push_call(ui, "highlight_set", args);
|
||||||
|
@ -55,6 +55,47 @@ void nvim_command(String command, Error *err)
|
|||||||
try_end(err);
|
try_end(err);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Gets a highlight definition by name.
|
||||||
|
///
|
||||||
|
/// @param name Highlight group name
|
||||||
|
/// @param rgb Export RGB colors
|
||||||
|
/// @param[out] err Error details, if any
|
||||||
|
/// @return Highlight definition map
|
||||||
|
/// @see nvim_get_hl_by_id
|
||||||
|
Dictionary nvim_get_hl_by_name(String name, Boolean rgb, Error *err)
|
||||||
|
FUNC_API_SINCE(3)
|
||||||
|
{
|
||||||
|
Dictionary result = ARRAY_DICT_INIT;
|
||||||
|
int id = syn_name2id((const char_u *)name.data);
|
||||||
|
|
||||||
|
if (id == 0) {
|
||||||
|
api_set_error(err, kErrorTypeException, "Invalid highlight name: %s",
|
||||||
|
name.data);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
result = nvim_get_hl_by_id(id, rgb, err);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Gets a highlight definition by id. |hlID()|
|
||||||
|
///
|
||||||
|
/// @param hl_id Highlight id as returned by |hlID()|
|
||||||
|
/// @param rgb Export RGB colors
|
||||||
|
/// @param[out] err Error details, if any
|
||||||
|
/// @return Highlight definition map
|
||||||
|
/// @see nvim_get_hl_by_name
|
||||||
|
Dictionary nvim_get_hl_by_id(Integer hl_id, Boolean rgb, Error *err)
|
||||||
|
FUNC_API_SINCE(3)
|
||||||
|
{
|
||||||
|
Dictionary dic = ARRAY_DICT_INIT;
|
||||||
|
if (syn_get_final_id((int)hl_id) == 0) {
|
||||||
|
api_set_error(err, kErrorTypeException, "Invalid highlight id: %d", hl_id);
|
||||||
|
return dic;
|
||||||
|
}
|
||||||
|
int attrcode = syn_id2attr((int)hl_id);
|
||||||
|
return hl_get_attr_by_id(attrcode, rgb, err);
|
||||||
|
}
|
||||||
|
|
||||||
/// Passes input keys to Nvim.
|
/// Passes input keys to Nvim.
|
||||||
/// On VimL error: Does not fail, but updates v:errmsg.
|
/// On VimL error: Does not fail, but updates v:errmsg.
|
||||||
///
|
///
|
||||||
@ -255,12 +296,11 @@ free_vim_args:
|
|||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Execute lua code. Parameters might be passed, they are available inside
|
/// Execute lua code. Parameters (if any) are available as `...` inside the
|
||||||
/// the chunk as `...`. The chunk can return a value.
|
/// chunk. The chunk can return a value.
|
||||||
///
|
///
|
||||||
/// To evaluate an expression, it must be prefixed with "return ". For
|
/// Only statements are executed. To evaluate an expression, prefix it
|
||||||
/// instance, to call a lua function with arguments sent in and get its
|
/// with `return`: return my_function(...)
|
||||||
/// return value back, use the code "return my_function(...)".
|
|
||||||
///
|
///
|
||||||
/// @param code lua code to execute
|
/// @param code lua code to execute
|
||||||
/// @param args Arguments to the code
|
/// @param args Arguments to the code
|
||||||
@ -423,29 +463,18 @@ void nvim_del_var(String name, Error *err)
|
|||||||
dict_set_var(&globvardict, name, NIL, true, false, err);
|
dict_set_var(&globvardict, name, NIL, true, false, err);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Sets a global variable
|
|
||||||
///
|
|
||||||
/// @deprecated
|
/// @deprecated
|
||||||
///
|
/// @see nvim_set_var
|
||||||
/// @param name Variable name
|
|
||||||
/// @param value Variable value
|
|
||||||
/// @param[out] err Error details, if any
|
|
||||||
/// @return Old value or nil if there was no previous value.
|
/// @return Old value or nil if there was no previous value.
|
||||||
///
|
/// @warning May return nil if there was no previous value
|
||||||
/// @warning It may return nil if there was no previous value
|
/// OR if previous value was `v:null`.
|
||||||
/// or if previous value was `v:null`.
|
|
||||||
Object vim_set_var(String name, Object value, Error *err)
|
Object vim_set_var(String name, Object value, Error *err)
|
||||||
{
|
{
|
||||||
return dict_set_var(&globvardict, name, value, false, true, err);
|
return dict_set_var(&globvardict, name, value, false, true, err);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Removes a global variable
|
|
||||||
///
|
|
||||||
/// @deprecated
|
/// @deprecated
|
||||||
///
|
/// @see nvim_del_var
|
||||||
/// @param name Variable name
|
|
||||||
/// @param[out] err Error details, if any
|
|
||||||
/// @return Old value
|
|
||||||
Object vim_del_var(String name, Error *err)
|
Object vim_del_var(String name, Error *err)
|
||||||
{
|
{
|
||||||
return dict_set_var(&globvardict, name, NIL, true, true, err);
|
return dict_set_var(&globvardict, name, NIL, true, true, err);
|
||||||
@ -484,7 +513,8 @@ void nvim_set_option(String name, Object value, Error *err)
|
|||||||
set_option_to(NULL, SREQ_GLOBAL, name, value, err);
|
set_option_to(NULL, SREQ_GLOBAL, name, value, err);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Writes a message to vim output buffer
|
/// Writes a message to the Vim output buffer. Does not append "\n", the
|
||||||
|
/// message is buffered (won't display) until a linefeed is written.
|
||||||
///
|
///
|
||||||
/// @param str Message
|
/// @param str Message
|
||||||
void nvim_out_write(String str)
|
void nvim_out_write(String str)
|
||||||
@ -493,7 +523,8 @@ void nvim_out_write(String str)
|
|||||||
write_msg(str, false);
|
write_msg(str, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Writes a message to vim error buffer
|
/// Writes a message to the Vim error buffer. Does not append "\n", the
|
||||||
|
/// message is buffered (won't display) until a linefeed is written.
|
||||||
///
|
///
|
||||||
/// @param str Message
|
/// @param str Message
|
||||||
void nvim_err_write(String str)
|
void nvim_err_write(String str)
|
||||||
@ -502,8 +533,8 @@ void nvim_err_write(String str)
|
|||||||
write_msg(str, true);
|
write_msg(str, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Writes a message to vim error buffer. Appends a linefeed to ensure all
|
/// Writes a message to the Vim error buffer. Appends "\n", so the buffer is
|
||||||
/// contents are written.
|
/// flushed (and displayed).
|
||||||
///
|
///
|
||||||
/// @param str Message
|
/// @param str Message
|
||||||
/// @see nvim_err_write()
|
/// @see nvim_err_write()
|
||||||
|
41
src/nvim/aucmd.c
Normal file
41
src/nvim/aucmd.c
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
// This is an open source non-commercial project. Dear PVS-Studio, please check
|
||||||
|
// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
|
||||||
|
|
||||||
|
#include "nvim/os/os.h"
|
||||||
|
#include "nvim/fileio.h"
|
||||||
|
#include "nvim/vim.h"
|
||||||
|
#include "nvim/main.h"
|
||||||
|
#include "nvim/ui.h"
|
||||||
|
|
||||||
|
#ifdef INCLUDE_GENERATED_DECLARATIONS
|
||||||
|
# include "aucmd.c.generated.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static void focusgained_event(void **argv)
|
||||||
|
{
|
||||||
|
bool *gainedp = argv[0];
|
||||||
|
do_autocmd_focusgained(*gainedp);
|
||||||
|
xfree(gainedp);
|
||||||
|
}
|
||||||
|
void aucmd_schedule_focusgained(bool gained)
|
||||||
|
{
|
||||||
|
bool *gainedp = xmalloc(sizeof(*gainedp));
|
||||||
|
*gainedp = gained;
|
||||||
|
loop_schedule_deferred(&main_loop,
|
||||||
|
event_create(focusgained_event, 1, gainedp));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void do_autocmd_focusgained(bool gained)
|
||||||
|
FUNC_ATTR_NONNULL_ALL
|
||||||
|
{
|
||||||
|
static bool recursive = false;
|
||||||
|
|
||||||
|
if (recursive) {
|
||||||
|
return; // disallow recursion
|
||||||
|
}
|
||||||
|
recursive = true;
|
||||||
|
apply_autocmds((gained ? EVENT_FOCUSGAINED : EVENT_FOCUSLOST),
|
||||||
|
NULL, NULL, false, curbuf);
|
||||||
|
recursive = false;
|
||||||
|
}
|
||||||
|
|
9
src/nvim/aucmd.h
Normal file
9
src/nvim/aucmd.h
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
#ifndef NVIM_AUCMD_H
|
||||||
|
#define NVIM_AUCMD_H
|
||||||
|
|
||||||
|
#ifdef INCLUDE_GENERATED_DECLARATIONS
|
||||||
|
# include "aucmd.h.generated.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif // NVIM_AUCMD_H
|
||||||
|
|
@ -3069,8 +3069,8 @@ static bool ti_change(char_u *str, char_u **last)
|
|||||||
/// Set current window title
|
/// Set current window title
|
||||||
void resettitle(void)
|
void resettitle(void)
|
||||||
{
|
{
|
||||||
ui_call_set_title(cstr_as_string((char *)lasttitle));
|
|
||||||
ui_call_set_icon(cstr_as_string((char *)lasticon));
|
ui_call_set_icon(cstr_as_string((char *)lasticon));
|
||||||
|
ui_call_set_title(cstr_as_string((char *)lasttitle));
|
||||||
ui_flush();
|
ui_flush();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -762,7 +762,7 @@ bool vim_isIDc(int c)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Check that "c" is a keyword character:
|
/// Check that "c" is a keyword character:
|
||||||
/// Letters and characters from 'iskeyword' option for current buffer.
|
/// Letters and characters from 'iskeyword' option for the current buffer.
|
||||||
/// For multi-byte characters mb_get_class() is used (builtin rules).
|
/// For multi-byte characters mb_get_class() is used (builtin rules).
|
||||||
///
|
///
|
||||||
/// @param c character to check
|
/// @param c character to check
|
||||||
|
@ -135,6 +135,20 @@ void diff_buf_add(buf_T *buf)
|
|||||||
EMSGN(_("E96: Cannot diff more than %" PRId64 " buffers"), DB_COUNT);
|
EMSGN(_("E96: Cannot diff more than %" PRId64 " buffers"), DB_COUNT);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Remove all buffers to make diffs for.
|
||||||
|
///
|
||||||
|
static void diff_buf_clear(void)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < DB_COUNT; i++) {
|
||||||
|
if (curtab->tp_diffbuf[i] != NULL) {
|
||||||
|
curtab->tp_diffbuf[i] = NULL;
|
||||||
|
curtab->tp_diff_invalid = true;
|
||||||
|
diff_redraw(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Find buffer "buf" in the list of diff buffers for the current tab page.
|
/// Find buffer "buf" in the list of diff buffers for the current tab page.
|
||||||
///
|
///
|
||||||
/// @param buf The buffer to find.
|
/// @param buf The buffer to find.
|
||||||
@ -1175,6 +1189,11 @@ void ex_diffoff(exarg_T *eap)
|
|||||||
diffwin |= wp->w_p_diff;
|
diffwin |= wp->w_p_diff;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Also remove hidden buffers from the list.
|
||||||
|
if (eap->forceit) {
|
||||||
|
diff_buf_clear();
|
||||||
|
}
|
||||||
|
|
||||||
// Remove "hor" from from 'scrollopt' if there are no diff windows left.
|
// Remove "hor" from from 'scrollopt' if there are no diff windows left.
|
||||||
if (!diffwin && (vim_strchr(p_sbo, 'h') != NULL)) {
|
if (!diffwin && (vim_strchr(p_sbo, 'h') != NULL)) {
|
||||||
do_cmdline_cmd("set sbo-=hor");
|
do_cmdline_cmd("set sbo-=hor");
|
||||||
|
@ -974,14 +974,6 @@ static int insert_handle_key(InsertState *s)
|
|||||||
multiqueue_process_events(main_loop.events);
|
multiqueue_process_events(main_loop.events);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case K_FOCUSGAINED: // Neovim has been given focus
|
|
||||||
apply_autocmds(EVENT_FOCUSGAINED, NULL, NULL, false, curbuf);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case K_FOCUSLOST: // Neovim has lost focus
|
|
||||||
apply_autocmds(EVENT_FOCUSLOST, NULL, NULL, false, curbuf);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case K_HOME: // <Home>
|
case K_HOME: // <Home>
|
||||||
case K_KHOME:
|
case K_KHOME:
|
||||||
case K_S_HOME:
|
case K_S_HOME:
|
||||||
@ -2406,6 +2398,7 @@ void set_completion(colnr_T startcol, list_T *list)
|
|||||||
ins_compl_prep(' ');
|
ins_compl_prep(' ');
|
||||||
}
|
}
|
||||||
ins_compl_clear();
|
ins_compl_clear();
|
||||||
|
ins_compl_free();
|
||||||
|
|
||||||
compl_direction = FORWARD;
|
compl_direction = FORWARD;
|
||||||
if (startcol > curwin->w_cursor.col)
|
if (startcol > curwin->w_cursor.col)
|
||||||
@ -3166,8 +3159,7 @@ static bool ins_compl_prep(int c)
|
|||||||
|
|
||||||
/* Ignore end of Select mode mapping and mouse scroll buttons. */
|
/* Ignore end of Select mode mapping and mouse scroll buttons. */
|
||||||
if (c == K_SELECT || c == K_MOUSEDOWN || c == K_MOUSEUP
|
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_FOCUSGAINED || c == K_FOCUSLOST) {
|
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6733,6 +6733,39 @@ static void prepare_assert_error(garray_T *gap)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Append "str" to "gap", escaping unprintable characters.
|
||||||
|
// Changes NL to \n, CR to \r, etc.
|
||||||
|
static void ga_concat_esc(garray_T *gap, char_u *str)
|
||||||
|
{
|
||||||
|
char_u *p;
|
||||||
|
char_u buf[NUMBUFLEN];
|
||||||
|
|
||||||
|
if (str == NULL) {
|
||||||
|
ga_concat(gap, (char_u *)"NULL");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (p = str; *p != NUL; p++) {
|
||||||
|
switch (*p) {
|
||||||
|
case BS: ga_concat(gap, (char_u *)"\\b"); break;
|
||||||
|
case ESC: ga_concat(gap, (char_u *)"\\e"); break;
|
||||||
|
case FF: ga_concat(gap, (char_u *)"\\f"); break;
|
||||||
|
case NL: ga_concat(gap, (char_u *)"\\n"); break;
|
||||||
|
case TAB: ga_concat(gap, (char_u *)"\\t"); break;
|
||||||
|
case CAR: ga_concat(gap, (char_u *)"\\r"); break;
|
||||||
|
case '\\': ga_concat(gap, (char_u *)"\\\\"); break;
|
||||||
|
default:
|
||||||
|
if (*p < ' ') {
|
||||||
|
vim_snprintf((char *)buf, NUMBUFLEN, "\\x%02x", *p);
|
||||||
|
ga_concat(gap, buf);
|
||||||
|
} else {
|
||||||
|
ga_append(gap, *p);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Fill "gap" with information about an assert error.
|
// Fill "gap" with information about an assert error.
|
||||||
static void fill_assert_error(garray_T *gap, typval_T *opt_msg_tv,
|
static void fill_assert_error(garray_T *gap, typval_T *opt_msg_tv,
|
||||||
char_u *exp_str, typval_T *exp_tv,
|
char_u *exp_str, typval_T *exp_tv,
|
||||||
@ -6747,28 +6780,30 @@ static void fill_assert_error(garray_T *gap, typval_T *opt_msg_tv,
|
|||||||
} else {
|
} else {
|
||||||
if (atype == ASSERT_MATCH || atype == ASSERT_NOTMATCH) {
|
if (atype == ASSERT_MATCH || atype == ASSERT_NOTMATCH) {
|
||||||
ga_concat(gap, (char_u *)"Pattern ");
|
ga_concat(gap, (char_u *)"Pattern ");
|
||||||
|
} else if (atype == ASSERT_NOTEQUAL) {
|
||||||
|
ga_concat(gap, (char_u *)"Expected not equal to ");
|
||||||
} else {
|
} else {
|
||||||
ga_concat(gap, (char_u *)"Expected ");
|
ga_concat(gap, (char_u *)"Expected ");
|
||||||
}
|
}
|
||||||
if (exp_str == NULL) {
|
if (exp_str == NULL) {
|
||||||
tofree = (char_u *) encode_tv2string(exp_tv, NULL);
|
tofree = (char_u *)encode_tv2string(exp_tv, NULL);
|
||||||
ga_concat(gap, tofree);
|
ga_concat_esc(gap, tofree);
|
||||||
xfree(tofree);
|
xfree(tofree);
|
||||||
} else {
|
} else {
|
||||||
ga_concat(gap, exp_str);
|
ga_concat_esc(gap, exp_str);
|
||||||
}
|
}
|
||||||
tofree = (char_u *)encode_tv2string(got_tv, NULL);
|
if (atype != ASSERT_NOTEQUAL) {
|
||||||
if (atype == ASSERT_MATCH) {
|
if (atype == ASSERT_MATCH) {
|
||||||
ga_concat(gap, (char_u *)" does not match ");
|
ga_concat(gap, (char_u *)" does not match ");
|
||||||
} else if (atype == ASSERT_NOTMATCH) {
|
} else if (atype == ASSERT_NOTMATCH) {
|
||||||
ga_concat(gap, (char_u *)" does match ");
|
ga_concat(gap, (char_u *)" does match ");
|
||||||
} else if (atype == ASSERT_NOTEQUAL) {
|
} else {
|
||||||
ga_concat(gap, (char_u *)" differs from ");
|
ga_concat(gap, (char_u *)" but got ");
|
||||||
} else {
|
}
|
||||||
ga_concat(gap, (char_u *)" but got ");
|
tofree = (char_u *)encode_tv2string(got_tv, NULL);
|
||||||
|
ga_concat_esc(gap, tofree);
|
||||||
|
xfree(tofree);
|
||||||
}
|
}
|
||||||
ga_concat(gap, tofree);
|
|
||||||
xfree(tofree);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -17493,7 +17528,7 @@ static void f_winsaveview(typval_T *argvars, typval_T *rettv, FunPtr fptr)
|
|||||||
tv_dict_add_nr(dict, S_LEN("skipcol"), (varnumber_T)curwin->w_skipcol);
|
tv_dict_add_nr(dict, S_LEN("skipcol"), (varnumber_T)curwin->w_skipcol);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Writes list of strings to file
|
/// Write "list" of strings to file "fd".
|
||||||
///
|
///
|
||||||
/// @param fp File to write to.
|
/// @param fp File to write to.
|
||||||
/// @param[in] list List to write.
|
/// @param[in] list List to write.
|
||||||
@ -22775,7 +22810,7 @@ typval_T eval_call_provider(char *provider, char *method, list_T *arguments)
|
|||||||
|
|
||||||
bool eval_has_provider(const char *name)
|
bool eval_has_provider(const char *name)
|
||||||
{
|
{
|
||||||
#define check_provider(name) \
|
#define CHECK_PROVIDER(name) \
|
||||||
if (has_##name == -1) { \
|
if (has_##name == -1) { \
|
||||||
has_##name = !!find_func((char_u *)"provider#" #name "#Call"); \
|
has_##name = !!find_func((char_u *)"provider#" #name "#Call"); \
|
||||||
if (!has_##name) { \
|
if (!has_##name) { \
|
||||||
@ -22791,17 +22826,17 @@ bool eval_has_provider(const char *name)
|
|||||||
static int has_python3 = -1;
|
static int has_python3 = -1;
|
||||||
static int has_ruby = -1;
|
static int has_ruby = -1;
|
||||||
|
|
||||||
if (!strcmp(name, "clipboard")) {
|
if (strequal(name, "clipboard")) {
|
||||||
check_provider(clipboard);
|
CHECK_PROVIDER(clipboard);
|
||||||
return has_clipboard;
|
return has_clipboard;
|
||||||
} else if (!strcmp(name, "python3")) {
|
} else if (strequal(name, "python3")) {
|
||||||
check_provider(python3);
|
CHECK_PROVIDER(python3);
|
||||||
return has_python3;
|
return has_python3;
|
||||||
} else if (!strcmp(name, "python")) {
|
} else if (strequal(name, "python")) {
|
||||||
check_provider(python);
|
CHECK_PROVIDER(python);
|
||||||
return has_python;
|
return has_python;
|
||||||
} else if (!strcmp(name, "ruby")) {
|
} else if (strequal(name, "ruby")) {
|
||||||
check_provider(ruby);
|
CHECK_PROVIDER(ruby);
|
||||||
return has_ruby;
|
return has_ruby;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -59,7 +59,14 @@ void loop_poll_events(Loop *loop, int ms)
|
|||||||
multiqueue_process_events(loop->fast_events);
|
multiqueue_process_events(loop->fast_events);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Schedule an event from another thread
|
/// Schedules an event from another thread.
|
||||||
|
///
|
||||||
|
/// @note Event is queued into `fast_events`, which is processed outside of the
|
||||||
|
/// primary `events` queue by loop_poll_events(). For `main_loop`, that
|
||||||
|
/// means `fast_events` is NOT processed in an "editor mode"
|
||||||
|
/// (VimState.execute), so redraw and other side-effects are likely to be
|
||||||
|
/// skipped.
|
||||||
|
/// @see loop_schedule_deferred
|
||||||
void loop_schedule(Loop *loop, Event event)
|
void loop_schedule(Loop *loop, Event event)
|
||||||
{
|
{
|
||||||
uv_mutex_lock(&loop->mutex);
|
uv_mutex_lock(&loop->mutex);
|
||||||
@ -68,6 +75,24 @@ void loop_schedule(Loop *loop, Event event)
|
|||||||
uv_mutex_unlock(&loop->mutex);
|
uv_mutex_unlock(&loop->mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Schedules an event from another thread. Unlike loop_schedule(), the event
|
||||||
|
/// is forwarded to `Loop.events`, instead of being processed immediately.
|
||||||
|
///
|
||||||
|
/// @see loop_schedule
|
||||||
|
void loop_schedule_deferred(Loop *loop, Event event)
|
||||||
|
{
|
||||||
|
Event *eventp = xmalloc(sizeof(*eventp));
|
||||||
|
*eventp = event;
|
||||||
|
loop_schedule(loop, event_create(loop_deferred_event, 2, loop, eventp));
|
||||||
|
}
|
||||||
|
static void loop_deferred_event(void **argv)
|
||||||
|
{
|
||||||
|
Loop *loop = argv[0];
|
||||||
|
Event *eventp = argv[1];
|
||||||
|
multiqueue_put_event(loop->events, *eventp);
|
||||||
|
xfree(eventp);
|
||||||
|
}
|
||||||
|
|
||||||
void loop_on_put(MultiQueue *queue, void *data)
|
void loop_on_put(MultiQueue *queue, void *data)
|
||||||
{
|
{
|
||||||
Loop *loop = data;
|
Loop *loop = data;
|
||||||
|
@ -16,10 +16,28 @@ KLIST_INIT(WatcherPtr, WatcherPtr, _noop)
|
|||||||
|
|
||||||
typedef struct loop {
|
typedef struct loop {
|
||||||
uv_loop_t uv;
|
uv_loop_t uv;
|
||||||
MultiQueue *events, *fast_events, *thread_events;
|
MultiQueue *events;
|
||||||
|
MultiQueue *thread_events;
|
||||||
|
// Immediate events:
|
||||||
|
// "Events that should be processed after exiting uv_run() (to avoid
|
||||||
|
// recursion), but before returning from loop_poll_events()."
|
||||||
|
// 502aee690c980fcb3cfcb3f211dcfad06103db46
|
||||||
|
// Practical consequence: these events are processed by
|
||||||
|
// state_enter()..os_inchar()
|
||||||
|
// whereas "regular" (main_loop.events) events are processed by
|
||||||
|
// state_enter()..VimState.execute()
|
||||||
|
// But state_enter()..os_inchar() can be "too early" if you want the event
|
||||||
|
// to trigger UI updates and other user-activity-related side-effects.
|
||||||
|
MultiQueue *fast_events;
|
||||||
|
|
||||||
|
// used by process/job-control subsystem
|
||||||
klist_t(WatcherPtr) *children;
|
klist_t(WatcherPtr) *children;
|
||||||
uv_signal_t children_watcher;
|
uv_signal_t children_watcher;
|
||||||
uv_timer_t children_kill_timer, poll_timer;
|
uv_timer_t children_kill_timer;
|
||||||
|
|
||||||
|
// generic timer, used by loop_poll_events()
|
||||||
|
uv_timer_t poll_timer;
|
||||||
|
|
||||||
size_t children_stop_requests;
|
size_t children_stop_requests;
|
||||||
uv_async_t async;
|
uv_async_t async;
|
||||||
uv_mutex_t mutex;
|
uv_mutex_t mutex;
|
||||||
|
@ -233,8 +233,7 @@ void process_stop(Process *proc) FUNC_ATTR_NONNULL_ALL
|
|||||||
switch (proc->type) {
|
switch (proc->type) {
|
||||||
case kProcessTypeUv:
|
case kProcessTypeUv:
|
||||||
// Close the process's stdin. If the process doesn't close its own
|
// Close the process's stdin. If the process doesn't close its own
|
||||||
// stdout/stderr, they will be closed when it exits(possibly due to being
|
// stdout/stderr, they will be closed when it exits (voluntarily or not).
|
||||||
// terminated after a timeout)
|
|
||||||
process_close_in(proc);
|
process_close_in(proc);
|
||||||
ILOG("Sending SIGTERM to pid %d", proc->pid);
|
ILOG("Sending SIGTERM to pid %d", proc->pid);
|
||||||
uv_kill(proc->pid, SIGTERM);
|
uv_kill(proc->pid, SIGTERM);
|
||||||
|
@ -118,7 +118,7 @@ static void read_cb(uv_stream_t *uvstream, ssize_t cnt, const uv_buf_t *buf)
|
|||||||
// to `alloc_cb` will return the same unused pointer(`rbuffer_produced`
|
// to `alloc_cb` will return the same unused pointer(`rbuffer_produced`
|
||||||
// won't be called)
|
// won't be called)
|
||||||
&& cnt != 0) {
|
&& cnt != 0) {
|
||||||
DLOG("Closing Stream (%p): %s (%s)", stream,
|
DLOG("closing Stream: %p: %s (%s)", stream,
|
||||||
uv_err_name((int)cnt), os_strerror((int)cnt));
|
uv_err_name((int)cnt), os_strerror((int)cnt));
|
||||||
// Read error or EOF, either way stop the stream and invoke the callback
|
// Read error or EOF, either way stop the stream and invoke the callback
|
||||||
// with eof == true
|
// with eof == true
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
|
|
||||||
#include <uv.h>
|
#include <uv.h>
|
||||||
|
|
||||||
|
#include "nvim/log.h"
|
||||||
#include "nvim/rbuffer.h"
|
#include "nvim/rbuffer.h"
|
||||||
#include "nvim/macros.h"
|
#include "nvim/macros.h"
|
||||||
#include "nvim/event/stream.h"
|
#include "nvim/event/stream.h"
|
||||||
@ -81,6 +82,7 @@ void stream_close(Stream *stream, stream_close_cb on_stream_close, void *data)
|
|||||||
FUNC_ATTR_NONNULL_ARG(1)
|
FUNC_ATTR_NONNULL_ARG(1)
|
||||||
{
|
{
|
||||||
assert(!stream->closed);
|
assert(!stream->closed);
|
||||||
|
DLOG("closing Stream: %p", stream);
|
||||||
stream->closed = true;
|
stream->closed = true;
|
||||||
stream->close_cb = on_stream_close;
|
stream->close_cb = on_stream_close;
|
||||||
stream->close_cb_data = data;
|
stream->close_cb_data = data;
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
|
|
||||||
#include <uv.h>
|
#include <uv.h>
|
||||||
|
|
||||||
|
#include "nvim/log.h"
|
||||||
#include "nvim/event/loop.h"
|
#include "nvim/event/loop.h"
|
||||||
#include "nvim/event/wstream.h"
|
#include "nvim/event/wstream.h"
|
||||||
#include "nvim/vim.h"
|
#include "nvim/vim.h"
|
||||||
|
@ -3332,10 +3332,12 @@ static buf_T *do_sub(exarg_T *eap, proftime_T timeout)
|
|||||||
sub = regtilde(sub, p_magic);
|
sub = regtilde(sub, p_magic);
|
||||||
|
|
||||||
// Check for a match on each line.
|
// Check for a match on each line.
|
||||||
|
// If preview: limit to max('cmdwinheight', viewport).
|
||||||
linenr_T line2 = eap->line2;
|
linenr_T line2 = eap->line2;
|
||||||
for (linenr_T lnum = eap->line1;
|
for (linenr_T lnum = eap->line1;
|
||||||
lnum <= line2 && !(got_quit || aborting())
|
lnum <= line2 && !got_quit && !aborting()
|
||||||
&& (!preview || matched_lines.size <= (size_t)p_cwh);
|
&& (!preview || matched_lines.size < (size_t)p_cwh
|
||||||
|
|| lnum <= curwin->w_botline);
|
||||||
lnum++) {
|
lnum++) {
|
||||||
long nmatch = vim_regexec_multi(®match, curwin, curbuf, lnum,
|
long nmatch = vim_regexec_multi(®match, curwin, curbuf, lnum,
|
||||||
(colnr_T)0, NULL);
|
(colnr_T)0, NULL);
|
||||||
@ -3500,6 +3502,10 @@ static buf_T *do_sub(exarg_T *eap, proftime_T timeout)
|
|||||||
setmouse(); /* disable mouse in xterm */
|
setmouse(); /* disable mouse in xterm */
|
||||||
curwin->w_cursor.col = regmatch.startpos[0].col;
|
curwin->w_cursor.col = regmatch.startpos[0].col;
|
||||||
|
|
||||||
|
if (curwin->w_p_crb) {
|
||||||
|
do_check_cursorbind();
|
||||||
|
}
|
||||||
|
|
||||||
/* When 'cpoptions' contains "u" don't sync undo when
|
/* When 'cpoptions' contains "u" don't sync undo when
|
||||||
* asking for confirmation. */
|
* asking for confirmation. */
|
||||||
if (vim_strchr(p_cpo, CPO_UNDO) != NULL)
|
if (vim_strchr(p_cpo, CPO_UNDO) != NULL)
|
||||||
@ -3659,6 +3665,42 @@ static buf_T *do_sub(exarg_T *eap, proftime_T timeout)
|
|||||||
* use "\=col("."). */
|
* use "\=col("."). */
|
||||||
curwin->w_cursor.col = regmatch.startpos[0].col;
|
curwin->w_cursor.col = regmatch.startpos[0].col;
|
||||||
|
|
||||||
|
// When the match included the "$" of the last line it may
|
||||||
|
// go beyond the last line of the buffer.
|
||||||
|
if (nmatch > curbuf->b_ml.ml_line_count - sub_firstlnum + 1) {
|
||||||
|
nmatch = curbuf->b_ml.ml_line_count - sub_firstlnum + 1;
|
||||||
|
skip_match = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define ADJUST_SUB_FIRSTLNUM() \
|
||||||
|
do { \
|
||||||
|
/* For a multi-line match, make a copy of the last matched */ \
|
||||||
|
/* line and continue in that one. */ \
|
||||||
|
if (nmatch > 1) { \
|
||||||
|
sub_firstlnum += nmatch - 1; \
|
||||||
|
xfree(sub_firstline); \
|
||||||
|
sub_firstline = vim_strsave(ml_get(sub_firstlnum)); \
|
||||||
|
/* When going beyond the last line, stop substituting. */ \
|
||||||
|
if (sub_firstlnum <= line2) { \
|
||||||
|
do_again = true; \
|
||||||
|
} else { \
|
||||||
|
subflags.do_all = false; \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
if (skip_match) { \
|
||||||
|
/* Already hit end of the buffer, sub_firstlnum is one */ \
|
||||||
|
/* less than what it ought to be. */ \
|
||||||
|
xfree(sub_firstline); \
|
||||||
|
sub_firstline = vim_strsave((char_u *)""); \
|
||||||
|
copycol = 0; \
|
||||||
|
} \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
if (preview && !has_second_delim) {
|
||||||
|
ADJUST_SUB_FIRSTLNUM();
|
||||||
|
goto skip;
|
||||||
|
}
|
||||||
|
|
||||||
// 3. Substitute the string. During 'inccommand' preview only do this if
|
// 3. Substitute the string. During 'inccommand' preview only do this if
|
||||||
// there is a replace pattern.
|
// there is a replace pattern.
|
||||||
if (!preview || has_second_delim) {
|
if (!preview || has_second_delim) {
|
||||||
@ -3685,13 +3727,6 @@ static buf_T *do_sub(exarg_T *eap, proftime_T timeout)
|
|||||||
goto skip;
|
goto skip;
|
||||||
}
|
}
|
||||||
|
|
||||||
// When the match included the "$" of the last line it may
|
|
||||||
// go beyond the last line of the buffer.
|
|
||||||
if (nmatch > curbuf->b_ml.ml_line_count - sub_firstlnum + 1) {
|
|
||||||
nmatch = curbuf->b_ml.ml_line_count - sub_firstlnum + 1;
|
|
||||||
skip_match = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Need room for:
|
// Need room for:
|
||||||
// - result so far in new_start (not for first sub in line)
|
// - result so far in new_start (not for first sub in line)
|
||||||
// - original text up to match
|
// - original text up to match
|
||||||
@ -3722,30 +3757,10 @@ static buf_T *do_sub(exarg_T *eap, proftime_T timeout)
|
|||||||
// is beyond the end of the line after the substitution.
|
// is beyond the end of the line after the substitution.
|
||||||
curwin->w_cursor.col = 0;
|
curwin->w_cursor.col = 0;
|
||||||
|
|
||||||
// For a multi-line match, make a copy of the last matched
|
|
||||||
// line and continue in that one.
|
|
||||||
if (nmatch > 1) {
|
|
||||||
sub_firstlnum += nmatch - 1;
|
|
||||||
xfree(sub_firstline);
|
|
||||||
sub_firstline = vim_strsave(ml_get(sub_firstlnum));
|
|
||||||
// When going beyond the last line, stop substituting.
|
|
||||||
if (sub_firstlnum <= line2) {
|
|
||||||
do_again = true;
|
|
||||||
} else {
|
|
||||||
subflags.do_all = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Remember next character to be copied.
|
// Remember next character to be copied.
|
||||||
copycol = regmatch.endpos[0].col;
|
copycol = regmatch.endpos[0].col;
|
||||||
|
|
||||||
if (skip_match) {
|
ADJUST_SUB_FIRSTLNUM();
|
||||||
// Already hit end of the buffer, sub_firstlnum is one
|
|
||||||
// less than what it ought to be.
|
|
||||||
xfree(sub_firstline);
|
|
||||||
sub_firstline = vim_strsave((char_u *)"");
|
|
||||||
copycol = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Now the trick is to replace CTRL-M chars with a real line
|
// Now the trick is to replace CTRL-M chars with a real line
|
||||||
// break. This would make it impossible to insert a CTRL-M in
|
// break. This would make it impossible to insert a CTRL-M in
|
||||||
@ -4002,6 +4017,7 @@ skip:
|
|||||||
kv_destroy(matched_lines);
|
kv_destroy(matched_lines);
|
||||||
|
|
||||||
return preview_buf;
|
return preview_buf;
|
||||||
|
#undef ADJUST_SUB_FIRSTLNUM
|
||||||
} // NOLINT(readability/fn_size)
|
} // NOLINT(readability/fn_size)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -2319,16 +2319,6 @@ static void source_callback(char_u *fname, void *cookie)
|
|||||||
(void)do_source(fname, false, DOSO_NONE);
|
(void)do_source(fname, false, DOSO_NONE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Source the file "name" from all directories in 'runtimepath'.
|
|
||||||
/// "name" can contain wildcards.
|
|
||||||
/// When "flags" has DIP_ALL: source all files, otherwise only the first one.
|
|
||||||
///
|
|
||||||
/// return FAIL when no file could be sourced, OK otherwise.
|
|
||||||
int source_runtime(char_u *name, int flags)
|
|
||||||
{
|
|
||||||
return do_in_runtimepath(name, flags, source_callback, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Find the file "name" in all directories in "path" and invoke
|
/// Find the file "name" in all directories in "path" and invoke
|
||||||
/// "callback(fname, cookie)".
|
/// "callback(fname, cookie)".
|
||||||
/// "name" can contain wildcards.
|
/// "name" can contain wildcards.
|
||||||
@ -2434,21 +2424,21 @@ int do_in_path(char_u *path, char_u *name, int flags,
|
|||||||
return did_one ? OK : FAIL;
|
return did_one ? OK : FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Find "name" in 'runtimepath'. When found, invoke the callback function for
|
/// Find "name" in "path". When found, invoke the callback function for
|
||||||
/// it: callback(fname, "cookie")
|
/// it: callback(fname, "cookie")
|
||||||
/// When "flags" has DIP_ALL repeat for all matches, otherwise only the first
|
/// When "flags" has DIP_ALL repeat for all matches, otherwise only the first
|
||||||
/// one is used.
|
/// one is used.
|
||||||
/// Returns OK when at least one match found, FAIL otherwise.
|
/// Returns OK when at least one match found, FAIL otherwise.
|
||||||
/// If "name" is NULL calls callback for each entry in runtimepath. Cookie is
|
/// If "name" is NULL calls callback for each entry in "path". Cookie is
|
||||||
/// passed by reference in this case, setting it to NULL indicates that callback
|
/// passed by reference in this case, setting it to NULL indicates that callback
|
||||||
/// has done its job.
|
/// has done its job.
|
||||||
int do_in_runtimepath(char_u *name, int flags, DoInRuntimepathCB callback,
|
int do_in_path_and_pp(char_u *path, char_u *name, int flags,
|
||||||
void *cookie)
|
DoInRuntimepathCB callback, void *cookie)
|
||||||
{
|
{
|
||||||
int done = FAIL;
|
int done = FAIL;
|
||||||
|
|
||||||
if ((flags & DIP_NORTP) == 0) {
|
if ((flags & DIP_NORTP) == 0) {
|
||||||
done = do_in_path(p_rtp, name, flags, callback, cookie);
|
done = do_in_path(path, name, flags, callback, cookie);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((done == FAIL || (flags & DIP_ALL)) && (flags & DIP_START)) {
|
if ((done == FAIL || (flags & DIP_ALL)) && (flags & DIP_START)) {
|
||||||
@ -2476,6 +2466,29 @@ int do_in_runtimepath(char_u *name, int flags, DoInRuntimepathCB callback,
|
|||||||
return done;
|
return done;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Just like do_in_path_and_pp(), using 'runtimepath' for "path".
|
||||||
|
int do_in_runtimepath(char_u *name, int flags, DoInRuntimepathCB callback,
|
||||||
|
void *cookie)
|
||||||
|
{
|
||||||
|
return do_in_path_and_pp(p_rtp, name, flags, callback, cookie);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Source the file "name" from all directories in 'runtimepath'.
|
||||||
|
/// "name" can contain wildcards.
|
||||||
|
/// When "flags" has DIP_ALL: source all files, otherwise only the first one.
|
||||||
|
///
|
||||||
|
/// return FAIL when no file could be sourced, OK otherwise.
|
||||||
|
int source_runtime(char_u *name, int flags)
|
||||||
|
{
|
||||||
|
return source_in_path(p_rtp, name, flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Just like source_runtime(), but use "path" instead of 'runtimepath'.
|
||||||
|
int source_in_path(char_u *path, char_u *name, int flags)
|
||||||
|
{
|
||||||
|
return do_in_path_and_pp(path, name, flags, source_callback, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
// Expand wildcards in "pat" and invoke do_source() for each match.
|
// Expand wildcards in "pat" and invoke do_source() for each match.
|
||||||
static void source_all_matches(char_u *pat)
|
static void source_all_matches(char_u *pat)
|
||||||
{
|
{
|
||||||
@ -2498,6 +2511,7 @@ static int APP_BOTH;
|
|||||||
static void add_pack_plugin(char_u *fname, void *cookie)
|
static void add_pack_plugin(char_u *fname, void *cookie)
|
||||||
{
|
{
|
||||||
char_u *p4, *p3, *p2, *p1, *p;
|
char_u *p4, *p3, *p2, *p1, *p;
|
||||||
|
char_u *buf = NULL;
|
||||||
|
|
||||||
char *const ffname = fix_fname((char *)fname);
|
char *const ffname = fix_fname((char *)fname);
|
||||||
|
|
||||||
@ -2525,26 +2539,30 @@ static void add_pack_plugin(char_u *fname, void *cookie)
|
|||||||
// Find "ffname" in "p_rtp", ignoring '/' vs '\' differences
|
// Find "ffname" in "p_rtp", ignoring '/' vs '\' differences
|
||||||
size_t fname_len = strlen(ffname);
|
size_t fname_len = strlen(ffname);
|
||||||
const char *insp = (const char *)p_rtp;
|
const char *insp = (const char *)p_rtp;
|
||||||
for (;;) {
|
buf = try_malloc(MAXPATHL);
|
||||||
if (path_fnamencmp(insp, ffname, fname_len) == 0) {
|
if (buf == NULL) {
|
||||||
|
goto theend;
|
||||||
|
}
|
||||||
|
while (*insp != NUL) {
|
||||||
|
copy_option_part((char_u **)&insp, buf, MAXPATHL, ",");
|
||||||
|
add_pathsep((char *)buf);
|
||||||
|
char *const rtp_ffname = fix_fname((char *)buf);
|
||||||
|
if (rtp_ffname == NULL) {
|
||||||
|
goto theend;
|
||||||
|
}
|
||||||
|
bool match = path_fnamencmp(rtp_ffname, ffname, fname_len) == 0;
|
||||||
|
xfree(rtp_ffname);
|
||||||
|
if (match) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
insp = strchr(insp, ',');
|
|
||||||
if (insp == NULL) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
insp++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (insp == NULL) {
|
if (*insp == NUL) {
|
||||||
// not found, append at the end
|
// not found, append at the end
|
||||||
insp = (const char *)p_rtp + STRLEN(p_rtp);
|
insp = (const char *)p_rtp + STRLEN(p_rtp);
|
||||||
} else {
|
} else {
|
||||||
// append after the matching directory.
|
// append after the matching directory.
|
||||||
insp += strlen(ffname);
|
insp--;
|
||||||
while (*insp != NUL && *insp != ',') {
|
|
||||||
insp++;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
*p4 = c;
|
*p4 = c;
|
||||||
|
|
||||||
@ -2614,26 +2632,35 @@ static void add_pack_plugin(char_u *fname, void *cookie)
|
|||||||
}
|
}
|
||||||
|
|
||||||
theend:
|
theend:
|
||||||
|
xfree(buf);
|
||||||
xfree(ffname);
|
xfree(ffname);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool did_source_packages = false;
|
/// Add all packages in the "start" directory to 'runtimepath'.
|
||||||
|
void add_pack_start_dirs(void)
|
||||||
|
{
|
||||||
|
do_in_path(p_pp, (char_u *)"pack/*/start/*", DIP_ALL + DIP_DIR, // NOLINT
|
||||||
|
add_pack_plugin, &APP_ADD_DIR);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Load plugins from all packages in the "start" directory.
|
||||||
|
void load_start_packages(void)
|
||||||
|
{
|
||||||
|
did_source_packages = true;
|
||||||
|
do_in_path(p_pp, (char_u *)"pack/*/start/*", DIP_ALL + DIP_DIR, // NOLINT
|
||||||
|
add_pack_plugin, &APP_LOAD);
|
||||||
|
}
|
||||||
|
|
||||||
// ":packloadall"
|
// ":packloadall"
|
||||||
// Find plugins in the package directories and source them.
|
// Find plugins in the package directories and source them.
|
||||||
// "eap" is NULL when invoked during startup.
|
|
||||||
void ex_packloadall(exarg_T *eap)
|
void ex_packloadall(exarg_T *eap)
|
||||||
{
|
{
|
||||||
if (!did_source_packages || (eap != NULL && eap->forceit)) {
|
if (!did_source_packages || eap->forceit) {
|
||||||
did_source_packages = true;
|
|
||||||
|
|
||||||
// First do a round to add all directories to 'runtimepath', then load
|
// First do a round to add all directories to 'runtimepath', then load
|
||||||
// the plugins. This allows for plugins to use an autoload directory
|
// the plugins. This allows for plugins to use an autoload directory
|
||||||
// of another plugin.
|
// of another plugin.
|
||||||
do_in_path(p_pp, (char_u *)"pack/*/start/*", DIP_ALL + DIP_DIR, // NOLINT
|
add_pack_start_dirs();
|
||||||
add_pack_plugin, &APP_ADD_DIR);
|
load_start_packages();
|
||||||
do_in_path(p_pp, (char_u *)"pack/*/start/*", DIP_ALL + DIP_DIR, // NOLINT
|
|
||||||
add_pack_plugin, &APP_LOAD);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1668,8 +1668,8 @@ static char_u * do_one_cmd(char_u **cmdlinep,
|
|||||||
if (*ea.cmd == ';') {
|
if (*ea.cmd == ';') {
|
||||||
if (!ea.skip) {
|
if (!ea.skip) {
|
||||||
curwin->w_cursor.lnum = ea.line2;
|
curwin->w_cursor.lnum = ea.line2;
|
||||||
// Don't leave the cursor on an illegal line (caused by ';')
|
// don't leave the cursor on an illegal line or column
|
||||||
check_cursor_lnum();
|
check_cursor();
|
||||||
}
|
}
|
||||||
} else if (*ea.cmd != ',') {
|
} else if (*ea.cmd != ',') {
|
||||||
break;
|
break;
|
||||||
@ -1813,7 +1813,7 @@ static char_u * do_one_cmd(char_u **cmdlinep,
|
|||||||
if (text_locked() && !(ea.argt & CMDWIN)
|
if (text_locked() && !(ea.argt & CMDWIN)
|
||||||
&& !IS_USER_CMDIDX(ea.cmdidx)) {
|
&& !IS_USER_CMDIDX(ea.cmdidx)) {
|
||||||
// Command not allowed when editing the command line.
|
// Command not allowed when editing the command line.
|
||||||
errormsg = get_text_locked_msg();
|
errormsg = (char_u *)_(get_text_locked_msg());
|
||||||
goto doend;
|
goto doend;
|
||||||
}
|
}
|
||||||
/* Disallow editing another buffer when "curbuf_lock" is set.
|
/* Disallow editing another buffer when "curbuf_lock" is set.
|
||||||
@ -8810,11 +8810,12 @@ makeopens (
|
|||||||
&& buf->b_fname != NULL
|
&& buf->b_fname != NULL
|
||||||
&& buf->b_p_bl) {
|
&& buf->b_p_bl) {
|
||||||
if (fprintf(fd, "badd +%" PRId64 " ",
|
if (fprintf(fd, "badd +%" PRId64 " ",
|
||||||
buf->b_wininfo == NULL ?
|
buf->b_wininfo == NULL
|
||||||
(int64_t)1L :
|
? (int64_t)1L
|
||||||
(int64_t)buf->b_wininfo->wi_fpos.lnum) < 0
|
: (int64_t)buf->b_wininfo->wi_fpos.lnum) < 0
|
||||||
|| ses_fname(fd, buf, &ssop_flags) == FAIL)
|
|| ses_fname(fd, buf, &ssop_flags, true) == FAIL) {
|
||||||
return FAIL;
|
return FAIL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -8885,11 +8886,13 @@ makeopens (
|
|||||||
&& !bt_nofile(wp->w_buffer)
|
&& !bt_nofile(wp->w_buffer)
|
||||||
) {
|
) {
|
||||||
if (fputs(need_tabnew ? "tabedit " : "edit ", fd) < 0
|
if (fputs(need_tabnew ? "tabedit " : "edit ", fd) < 0
|
||||||
|| ses_fname(fd, wp->w_buffer, &ssop_flags) == FAIL)
|
|| ses_fname(fd, wp->w_buffer, &ssop_flags, true) == FAIL) {
|
||||||
return FAIL;
|
return FAIL;
|
||||||
need_tabnew = FALSE;
|
}
|
||||||
if (!wp->w_arg_idx_invalid)
|
need_tabnew = false;
|
||||||
|
if (!wp->w_arg_idx_invalid) {
|
||||||
edited_win = wp;
|
edited_win = wp;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -8933,6 +8936,8 @@ makeopens (
|
|||||||
// resized when moving between windows.
|
// resized when moving between windows.
|
||||||
// Do this before restoring the view, so that the topline and the
|
// Do this before restoring the view, so that the topline and the
|
||||||
// cursor can be set. This is done again below.
|
// cursor can be set. This is done again below.
|
||||||
|
// winminheight and winminwidth need to be set to avoid an error if the
|
||||||
|
// user has set winheight or winwidth.
|
||||||
if (put_line(fd, "set winminheight=1 winminwidth=1 winheight=1 winwidth=1")
|
if (put_line(fd, "set winminheight=1 winminwidth=1 winheight=1 winwidth=1")
|
||||||
== FAIL) {
|
== FAIL) {
|
||||||
return FAIL;
|
return FAIL;
|
||||||
@ -9221,24 +9226,35 @@ put_view (
|
|||||||
if (wp->w_buffer->b_ffname != NULL
|
if (wp->w_buffer->b_ffname != NULL
|
||||||
&& (!bt_nofile(wp->w_buffer) || wp->w_buffer->terminal)
|
&& (!bt_nofile(wp->w_buffer) || wp->w_buffer->terminal)
|
||||||
) {
|
) {
|
||||||
/*
|
// Editing a file in this buffer: use ":edit file".
|
||||||
* Editing a file in this buffer: use ":edit file".
|
// This may have side effects! (e.g., compressed or network file).
|
||||||
* This may have side effects! (e.g., compressed or network file).
|
//
|
||||||
*/
|
// Note, if a buffer for that file already exists, use :badd to
|
||||||
if (fputs("edit ", fd) < 0
|
// edit that buffer, to not lose folding information (:edit resets
|
||||||
|| ses_fname(fd, wp->w_buffer, flagp) == FAIL)
|
// folds in other buffers)
|
||||||
|
if (fputs("if bufexists('", fd) < 0
|
||||||
|
|| ses_fname(fd, wp->w_buffer, flagp, false) == FAIL
|
||||||
|
|| fputs("') | buffer ", fd) < 0
|
||||||
|
|| ses_fname(fd, wp->w_buffer, flagp, false) == FAIL
|
||||||
|
|| fputs(" | else | edit ", fd) < 0
|
||||||
|
|| ses_fname(fd, wp->w_buffer, flagp, false) == FAIL
|
||||||
|
|| fputs(" | endif", fd) < 0
|
||||||
|
|| put_eol(fd) == FAIL) {
|
||||||
return FAIL;
|
return FAIL;
|
||||||
} else {
|
|
||||||
/* No file in this buffer, just make it empty. */
|
|
||||||
if (put_line(fd, "enew") == FAIL)
|
|
||||||
return FAIL;
|
|
||||||
if (wp->w_buffer->b_ffname != NULL) {
|
|
||||||
/* The buffer does have a name, but it's not a file name. */
|
|
||||||
if (fputs("file ", fd) < 0
|
|
||||||
|| ses_fname(fd, wp->w_buffer, flagp) == FAIL)
|
|
||||||
return FAIL;
|
|
||||||
}
|
}
|
||||||
do_cursor = FALSE;
|
} else {
|
||||||
|
// No file in this buffer, just make it empty.
|
||||||
|
if (put_line(fd, "enew") == FAIL) {
|
||||||
|
return FAIL;
|
||||||
|
}
|
||||||
|
if (wp->w_buffer->b_ffname != NULL) {
|
||||||
|
// The buffer does have a name, but it's not a file name.
|
||||||
|
if (fputs("file ", fd) < 0
|
||||||
|
|| ses_fname(fd, wp->w_buffer, flagp, true) == FAIL) {
|
||||||
|
return FAIL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
do_cursor = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -9378,7 +9394,7 @@ ses_arglist (
|
|||||||
(void)vim_FullName((char *)s, (char *)buf, MAXPATHL, FALSE);
|
(void)vim_FullName((char *)s, (char *)buf, MAXPATHL, FALSE);
|
||||||
s = buf;
|
s = buf;
|
||||||
}
|
}
|
||||||
if (fputs("argadd ", fd) < 0 || ses_put_fname(fd, s, flagp) == FAIL
|
if (fputs("$argadd ", fd) < 0 || ses_put_fname(fd, s, flagp) == FAIL
|
||||||
|| put_eol(fd) == FAIL) {
|
|| put_eol(fd) == FAIL) {
|
||||||
xfree(buf);
|
xfree(buf);
|
||||||
return FAIL;
|
return FAIL;
|
||||||
@ -9389,12 +9405,10 @@ ses_arglist (
|
|||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/// Write a buffer name to the session file.
|
||||||
* Write a buffer name to the session file.
|
/// Also ends the line, if "add_eol" is true.
|
||||||
* Also ends the line.
|
/// Returns FAIL if writing fails.
|
||||||
* Returns FAIL if writing fails.
|
static int ses_fname(FILE *fd, buf_T *buf, unsigned *flagp, bool add_eol)
|
||||||
*/
|
|
||||||
static int ses_fname(FILE *fd, buf_T *buf, unsigned *flagp)
|
|
||||||
{
|
{
|
||||||
char_u *name;
|
char_u *name;
|
||||||
|
|
||||||
@ -9411,8 +9425,10 @@ static int ses_fname(FILE *fd, buf_T *buf, unsigned *flagp)
|
|||||||
name = buf->b_sfname;
|
name = buf->b_sfname;
|
||||||
else
|
else
|
||||||
name = buf->b_ffname;
|
name = buf->b_ffname;
|
||||||
if (ses_put_fname(fd, name, flagp) == FAIL || put_eol(fd) == FAIL)
|
if (ses_put_fname(fd, name, flagp) == FAIL
|
||||||
|
|| (add_eol && put_eol(fd) == FAIL)) {
|
||||||
return FAIL;
|
return FAIL;
|
||||||
|
}
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -9835,7 +9851,7 @@ static void ex_terminal(exarg_T *eap)
|
|||||||
if (*eap->arg != NUL) { // Run {cmd} in 'shell'.
|
if (*eap->arg != NUL) { // Run {cmd} in 'shell'.
|
||||||
char *name = (char *)vim_strsave_escaped(eap->arg, (char_u *)"\"\\");
|
char *name = (char *)vim_strsave_escaped(eap->arg, (char_u *)"\"\\");
|
||||||
snprintf(ex_cmd, sizeof(ex_cmd),
|
snprintf(ex_cmd, sizeof(ex_cmd),
|
||||||
":enew%s | call termopen(\"%s\") | startinsert",
|
":enew%s | call termopen(\"%s\")",
|
||||||
eap->forceit ? "!" : "", name);
|
eap->forceit ? "!" : "", name);
|
||||||
xfree(name);
|
xfree(name);
|
||||||
} else { // No {cmd}: run the job with tokenized 'shell'.
|
} else { // No {cmd}: run the job with tokenized 'shell'.
|
||||||
@ -9857,7 +9873,7 @@ static void ex_terminal(exarg_T *eap)
|
|||||||
shell_free_argv(argv);
|
shell_free_argv(argv);
|
||||||
|
|
||||||
snprintf(ex_cmd, sizeof(ex_cmd),
|
snprintf(ex_cmd, sizeof(ex_cmd),
|
||||||
":enew%s | call termopen([%s]) | startinsert",
|
":enew%s | call termopen([%s])",
|
||||||
eap->forceit ? "!" : "", shell_argv + 1);
|
eap->forceit ? "!" : "", shell_argv + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1620,14 +1620,6 @@ static int command_line_handle_key(CommandLineState *s)
|
|||||||
}
|
}
|
||||||
return command_line_not_changed(s);
|
return command_line_not_changed(s);
|
||||||
|
|
||||||
case K_FOCUSGAINED: // Neovim has been given focus
|
|
||||||
apply_autocmds(EVENT_FOCUSGAINED, NULL, NULL, false, curbuf);
|
|
||||||
return command_line_not_changed(s);
|
|
||||||
|
|
||||||
case K_FOCUSLOST: // Neovim has lost focus
|
|
||||||
apply_autocmds(EVENT_FOCUSLOST, NULL, NULL, false, curbuf);
|
|
||||||
return command_line_not_changed(s);
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
// Normal character with no special meaning. Just set mod_mask
|
// Normal character with no special meaning. Just set mod_mask
|
||||||
// to 0x0 so that typing Shift-Space in the GUI doesn't enter
|
// to 0x0 so that typing Shift-Space in the GUI doesn't enter
|
||||||
@ -1871,9 +1863,13 @@ char *getcmdline_prompt(const char firstc, const char *const prompt,
|
|||||||
ccline.input_fn = (firstc == '@');
|
ccline.input_fn = (firstc == '@');
|
||||||
ccline.highlight_callback = highlight_callback;
|
ccline.highlight_callback = highlight_callback;
|
||||||
|
|
||||||
|
int msg_silent_saved = msg_silent;
|
||||||
|
msg_silent = 0;
|
||||||
|
|
||||||
char *const ret = (char *)getcmdline(firstc, 1L, 0);
|
char *const ret = (char *)getcmdline(firstc, 1L, 0);
|
||||||
|
|
||||||
restore_cmdline(&save_ccline);
|
restore_cmdline(&save_ccline);
|
||||||
|
msg_silent = msg_silent_saved;
|
||||||
// Restore msg_col, the prompt from input() may have changed it.
|
// Restore msg_col, the prompt from input() may have changed it.
|
||||||
// But only if called recursively and the commandline is therefore being
|
// But only if called recursively and the commandline is therefore being
|
||||||
// restored to an old one; if not, the input() prompt stays on the screen,
|
// restored to an old one; if not, the input() prompt stays on the screen,
|
||||||
@ -5722,6 +5718,7 @@ static int ex_window(void)
|
|||||||
|
|
||||||
i = RedrawingDisabled;
|
i = RedrawingDisabled;
|
||||||
RedrawingDisabled = 0;
|
RedrawingDisabled = 0;
|
||||||
|
int save_count = save_batch_count();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Call the main loop until <CR> or CTRL-C is typed.
|
* Call the main loop until <CR> or CTRL-C is typed.
|
||||||
@ -5730,6 +5727,7 @@ static int ex_window(void)
|
|||||||
normal_enter(true, false);
|
normal_enter(true, false);
|
||||||
|
|
||||||
RedrawingDisabled = i;
|
RedrawingDisabled = i;
|
||||||
|
restore_batch_count(save_count);
|
||||||
|
|
||||||
int save_KeyTyped = KeyTyped;
|
int save_KeyTyped = KeyTyped;
|
||||||
|
|
||||||
|
@ -92,17 +92,15 @@ static int typeahead_char = 0; /* typeahead char that's not flushed */
|
|||||||
*/
|
*/
|
||||||
static int block_redo = FALSE;
|
static int block_redo = FALSE;
|
||||||
|
|
||||||
/*
|
// Make a hash value for a mapping.
|
||||||
* Make a hash value for a mapping.
|
// "mode" is the lower 4 bits of the State for the mapping.
|
||||||
* "mode" is the lower 4 bits of the State for the mapping.
|
// "c1" is the first character of the "lhs".
|
||||||
* "c1" is the first character of the "lhs".
|
// Returns a value between 0 and 255, index in maphash.
|
||||||
* Returns a value between 0 and 255, index in maphash.
|
// Put Normal/Visual mode mappings mostly separately from Insert/Cmdline mode.
|
||||||
* Put Normal/Visual mode mappings mostly separately from Insert/Cmdline mode.
|
|
||||||
*/
|
|
||||||
#define MAP_HASH(mode, \
|
#define MAP_HASH(mode, \
|
||||||
c1) (((mode) & \
|
c1) (((mode) & \
|
||||||
(NORMAL + VISUAL + SELECTMODE + \
|
(NORMAL + VISUAL + SELECTMODE + \
|
||||||
OP_PENDING)) ? (c1) : ((c1) ^ 0x80))
|
OP_PENDING + TERM_FOCUS)) ? (c1) : ((c1) ^ 0x80))
|
||||||
|
|
||||||
// Each mapping is put in one of the MAX_MAPHASH hash lists,
|
// Each mapping is put in one of the MAX_MAPHASH hash lists,
|
||||||
// to speed up finding it.
|
// to speed up finding it.
|
||||||
@ -870,20 +868,15 @@ int ins_typebuf(char_u *str, int noremap, int offset, int nottyped, bool silent)
|
|||||||
|
|
||||||
addlen = (int)STRLEN(str);
|
addlen = (int)STRLEN(str);
|
||||||
|
|
||||||
/*
|
|
||||||
* Easy case: there is room in front of typebuf.tb_buf[typebuf.tb_off]
|
|
||||||
*/
|
|
||||||
if (offset == 0 && addlen <= typebuf.tb_off) {
|
if (offset == 0 && addlen <= typebuf.tb_off) {
|
||||||
|
// Easy case: there is room in front of typebuf.tb_buf[typebuf.tb_off]
|
||||||
typebuf.tb_off -= addlen;
|
typebuf.tb_off -= addlen;
|
||||||
memmove(typebuf.tb_buf + typebuf.tb_off, str, (size_t)addlen);
|
memmove(typebuf.tb_buf + typebuf.tb_off, str, (size_t)addlen);
|
||||||
}
|
} else {
|
||||||
/*
|
// Need to allocate a new buffer.
|
||||||
* Need to allocate a new buffer.
|
// In typebuf.tb_buf there must always be room for 3 * MAXMAPLEN + 4
|
||||||
* In typebuf.tb_buf there must always be room for 3 * MAXMAPLEN + 4
|
// characters. We add some extra room to avoid having to allocate too
|
||||||
* characters. We add some extra room to avoid having to allocate too
|
// often.
|
||||||
* often.
|
|
||||||
*/
|
|
||||||
else {
|
|
||||||
newoff = MAXMAPLEN + 4;
|
newoff = MAXMAPLEN + 4;
|
||||||
newlen = typebuf.tb_len + addlen + newoff + 4 * (MAXMAPLEN + 4);
|
newlen = typebuf.tb_len + addlen + newoff + 4 * (MAXMAPLEN + 4);
|
||||||
if (newlen < 0) { /* string is getting too long */
|
if (newlen < 0) { /* string is getting too long */
|
||||||
@ -1665,10 +1658,10 @@ static int vgetorpeek(int advance)
|
|||||||
}
|
}
|
||||||
if (c != NUL && !got_int) {
|
if (c != NUL && !got_int) {
|
||||||
if (advance) {
|
if (advance) {
|
||||||
/* KeyTyped = FALSE; When the command that stuffed something
|
// KeyTyped = FALSE; When the command that stuffed something
|
||||||
* was typed, behave like the stuffed command was typed.
|
// was typed, behave like the stuffed command was typed.
|
||||||
* needed for CTRL-W CTRl-] to open a fold, for example. */
|
// needed for CTRL-W CTRL-] to open a fold, for example.
|
||||||
KeyStuffed = TRUE;
|
KeyStuffed = true;
|
||||||
}
|
}
|
||||||
if (typebuf.tb_no_abbr_cnt == 0)
|
if (typebuf.tb_no_abbr_cnt == 0)
|
||||||
typebuf.tb_no_abbr_cnt = 1; /* no abbreviations now */
|
typebuf.tb_no_abbr_cnt = 1; /* no abbreviations now */
|
||||||
|
@ -13,6 +13,7 @@
|
|||||||
#else
|
#else
|
||||||
# define _(x) ((char *)(x))
|
# define _(x) ((char *)(x))
|
||||||
# define N_(x) x
|
# define N_(x) x
|
||||||
|
# define ngettext(x, xs, n) ((n) == 1 ? (x) : (xs))
|
||||||
# define bindtextdomain(x, y) // empty
|
# define bindtextdomain(x, y) // empty
|
||||||
# define bind_textdomain_codeset(x, y) // empty
|
# define bind_textdomain_codeset(x, y) // empty
|
||||||
# define textdomain(x) // empty
|
# define textdomain(x) // empty
|
||||||
|
@ -407,6 +407,9 @@ EXTERN int garbage_collect_at_exit INIT(= FALSE);
|
|||||||
|
|
||||||
/* ID of script being sourced or was sourced to define the current function. */
|
/* ID of script being sourced or was sourced to define the current function. */
|
||||||
EXTERN scid_T current_SID INIT(= 0);
|
EXTERN scid_T current_SID INIT(= 0);
|
||||||
|
|
||||||
|
EXTERN bool did_source_packages INIT(= false);
|
||||||
|
|
||||||
// Scope information for the code that indirectly triggered the current
|
// Scope information for the code that indirectly triggered the current
|
||||||
// provider function call
|
// provider function call
|
||||||
EXTERN struct caller_scope {
|
EXTERN struct caller_scope {
|
||||||
@ -1120,8 +1123,9 @@ EXTERN char_u e_winheight[] INIT(= N_(
|
|||||||
EXTERN char_u e_winwidth[] INIT(= N_(
|
EXTERN char_u e_winwidth[] INIT(= N_(
|
||||||
"E592: 'winwidth' cannot be smaller than 'winminwidth'"));
|
"E592: 'winwidth' cannot be smaller than 'winminwidth'"));
|
||||||
EXTERN char_u e_write[] INIT(= N_("E80: Error while writing"));
|
EXTERN char_u e_write[] INIT(= N_("E80: Error while writing"));
|
||||||
EXTERN char_u e_zerocount[] INIT(= N_("Zero count"));
|
EXTERN char_u e_zerocount[] INIT(= N_("E939: Positive count required"));
|
||||||
EXTERN char_u e_usingsid[] INIT(= N_("E81: Using <SID> not in a script context"));
|
EXTERN char_u e_usingsid[] INIT(= N_(
|
||||||
|
"E81: Using <SID> not in a script context"));
|
||||||
EXTERN char_u e_intern2[] INIT(= N_("E685: Internal error: %s"));
|
EXTERN char_u e_intern2[] INIT(= N_("E685: Internal error: %s"));
|
||||||
EXTERN char_u e_maxmempat[] INIT(= N_(
|
EXTERN char_u e_maxmempat[] INIT(= N_(
|
||||||
"E363: pattern uses more memory than 'maxmempattern'"));
|
"E363: pattern uses more memory than 'maxmempattern'"));
|
||||||
|
@ -515,34 +515,41 @@ int cin_isscopedecl(char_u *s)
|
|||||||
/* Maximum number of lines to search back for a "namespace" line. */
|
/* Maximum number of lines to search back for a "namespace" line. */
|
||||||
#define FIND_NAMESPACE_LIM 20
|
#define FIND_NAMESPACE_LIM 20
|
||||||
|
|
||||||
/*
|
// Recognize a "namespace" scope declaration.
|
||||||
* Recognize a "namespace" scope declaration.
|
static bool cin_is_cpp_namespace(char_u *s)
|
||||||
*/
|
|
||||||
static int cin_is_cpp_namespace(char_u *s)
|
|
||||||
{
|
{
|
||||||
char_u *p;
|
char_u *p;
|
||||||
int has_name = FALSE;
|
bool has_name = false;
|
||||||
|
bool has_name_start = false;
|
||||||
|
|
||||||
s = cin_skipcomment(s);
|
s = cin_skipcomment(s);
|
||||||
if (STRNCMP(s, "namespace", 9) == 0 && (s[9] == NUL || !vim_iswordc(s[9]))) {
|
if (STRNCMP(s, "namespace", 9) == 0 && (s[9] == NUL || !vim_iswordc(s[9]))) {
|
||||||
p = cin_skipcomment(skipwhite(s + 9));
|
p = cin_skipcomment(skipwhite(s + 9));
|
||||||
while (*p != NUL) {
|
while (*p != NUL) {
|
||||||
if (ascii_iswhite(*p)) {
|
if (ascii_iswhite(*p)) {
|
||||||
has_name = TRUE; /* found end of a name */
|
has_name = true; // found end of a name
|
||||||
p = cin_skipcomment(skipwhite(p));
|
p = cin_skipcomment(skipwhite(p));
|
||||||
} else if (*p == '{') {
|
} else if (*p == '{') {
|
||||||
break;
|
break;
|
||||||
} else if (vim_iswordc(*p)) {
|
} else if (vim_iswordc(*p)) {
|
||||||
if (has_name)
|
has_name_start = true;
|
||||||
return FALSE; /* word character after skipping past name */
|
if (has_name) {
|
||||||
++p;
|
return false; // word character after skipping past name
|
||||||
|
}
|
||||||
|
p++;
|
||||||
|
} else if (p[0] == ':' && p[1] == ':' && vim_iswordc(p[2])) {
|
||||||
|
if (!has_name_start || has_name) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// C++ 17 nested namespace
|
||||||
|
p += 3;
|
||||||
} else {
|
} else {
|
||||||
return FALSE;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return TRUE;
|
return true;
|
||||||
}
|
}
|
||||||
return FALSE;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -727,16 +734,20 @@ static int cin_ispreproc(char_u *s)
|
|||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/// Return TRUE if line "*pp" at "*lnump" is a preprocessor statement or a
|
||||||
* Return TRUE if line "*pp" at "*lnump" is a preprocessor statement or a
|
/// continuation line of a preprocessor statement. Decrease "*lnump" to the
|
||||||
* continuation line of a preprocessor statement. Decrease "*lnump" to the
|
/// start and return the line in "*pp".
|
||||||
* start and return the line in "*pp".
|
/// Put the amount of indent in "*amount".
|
||||||
*/
|
static int cin_ispreproc_cont(char_u **pp, linenr_T *lnump, int *amount)
|
||||||
static int cin_ispreproc_cont(char_u **pp, linenr_T *lnump)
|
|
||||||
{
|
{
|
||||||
char_u *line = *pp;
|
char_u *line = *pp;
|
||||||
linenr_T lnum = *lnump;
|
linenr_T lnum = *lnump;
|
||||||
int retval = FALSE;
|
int retval = false;
|
||||||
|
int candidate_amount = *amount;
|
||||||
|
|
||||||
|
if (*line != NUL && line[STRLEN(line) - 1] == '\\') {
|
||||||
|
candidate_amount = get_indent_lnum(lnum);
|
||||||
|
}
|
||||||
|
|
||||||
for (;; ) {
|
for (;; ) {
|
||||||
if (cin_ispreproc(line)) {
|
if (cin_ispreproc(line)) {
|
||||||
@ -751,8 +762,12 @@ static int cin_ispreproc_cont(char_u **pp, linenr_T *lnump)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (lnum != *lnump)
|
if (lnum != *lnump) {
|
||||||
*pp = ml_get(*lnump);
|
*pp = ml_get(*lnump);
|
||||||
|
}
|
||||||
|
if (retval) {
|
||||||
|
*amount = candidate_amount;
|
||||||
|
}
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1987,10 +2002,12 @@ int get_c_indent(void)
|
|||||||
amount = -1;
|
amount = -1;
|
||||||
for (lnum = cur_curpos.lnum - 1; lnum > our_paren_pos.lnum; --lnum) {
|
for (lnum = cur_curpos.lnum - 1; lnum > our_paren_pos.lnum; --lnum) {
|
||||||
l = skipwhite(ml_get(lnum));
|
l = skipwhite(ml_get(lnum));
|
||||||
if (cin_nocode(l)) /* skip comment lines */
|
if (cin_nocode(l)) { // skip comment lines
|
||||||
continue;
|
continue;
|
||||||
if (cin_ispreproc_cont(&l, &lnum))
|
}
|
||||||
continue; /* ignore #define, #if, etc. */
|
if (cin_ispreproc_cont(&l, &lnum, &amount)) {
|
||||||
|
continue; // ignore #define, #if, etc.
|
||||||
|
}
|
||||||
curwin->w_cursor.lnum = lnum;
|
curwin->w_cursor.lnum = lnum;
|
||||||
|
|
||||||
/* Skip a comment or raw string. XXX */
|
/* Skip a comment or raw string. XXX */
|
||||||
@ -2346,15 +2363,14 @@ int get_c_indent(void)
|
|||||||
* up with it.
|
* up with it.
|
||||||
*/
|
*/
|
||||||
if (curwin->w_cursor.lnum <= ourscope) {
|
if (curwin->w_cursor.lnum <= ourscope) {
|
||||||
/* we reached end of scope:
|
// We reached end of scope:
|
||||||
* if looking for an enum or structure initialization
|
// If looking for a enum or structure initialization
|
||||||
* go further back:
|
// go further back:
|
||||||
* if it is an initializer (enum xxx or xxx =), then
|
// If it is an initializer (enum xxx or xxx =), then
|
||||||
* don't add ind_continuation, otherwise it is a variable
|
// don't add ind_continuation, otherwise it is a variable
|
||||||
* declaration:
|
// declaration:
|
||||||
* int x,
|
// int x,
|
||||||
* here; <-- add ind_continuation
|
// here; <-- add ind_continuation
|
||||||
*/
|
|
||||||
if (lookfor == LOOKFOR_ENUM_OR_INIT) {
|
if (lookfor == LOOKFOR_ENUM_OR_INIT) {
|
||||||
if (curwin->w_cursor.lnum == 0
|
if (curwin->w_cursor.lnum == 0
|
||||||
|| curwin->w_cursor.lnum
|
|| curwin->w_cursor.lnum
|
||||||
@ -2382,11 +2398,12 @@ int get_c_indent(void)
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
//
|
||||||
* Skip preprocessor directives and blank lines.
|
// Skip preprocessor directives and blank lines.
|
||||||
*/
|
//
|
||||||
if (cin_ispreproc_cont(&l, &curwin->w_cursor.lnum))
|
if (cin_ispreproc_cont(&l, &curwin->w_cursor.lnum, &amount)) {
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (cin_nocode(l))
|
if (cin_nocode(l))
|
||||||
continue;
|
continue;
|
||||||
@ -2490,9 +2507,10 @@ int get_c_indent(void)
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Skip preprocessor directives and blank lines. */
|
// Skip preprocessor directives and blank lines.
|
||||||
if (cin_ispreproc_cont(&l, &curwin->w_cursor.lnum))
|
if (cin_ispreproc_cont(&l, &curwin->w_cursor.lnum, &amount)) {
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
/* Finally the actual check for "namespace". */
|
/* Finally the actual check for "namespace". */
|
||||||
if (cin_is_cpp_namespace(l)) {
|
if (cin_is_cpp_namespace(l)) {
|
||||||
@ -2655,9 +2673,10 @@ int get_c_indent(void)
|
|||||||
* unlocked it)
|
* unlocked it)
|
||||||
*/
|
*/
|
||||||
l = get_cursor_line_ptr();
|
l = get_cursor_line_ptr();
|
||||||
if (cin_ispreproc_cont(&l, &curwin->w_cursor.lnum)
|
if (cin_ispreproc_cont(&l, &curwin->w_cursor.lnum, &amount)
|
||||||
|| cin_nocode(l))
|
|| cin_nocode(l)) {
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Are we at the start of a cpp base class declaration or
|
* Are we at the start of a cpp base class declaration or
|
||||||
@ -3302,11 +3321,12 @@ term_again:
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
//
|
||||||
* Skip preprocessor directives and blank lines.
|
// Skip preprocessor directives and blank lines.
|
||||||
*/
|
//
|
||||||
if (cin_ispreproc_cont(&l, &curwin->w_cursor.lnum))
|
if (cin_ispreproc_cont(&l, &curwin->w_cursor.lnum, &amount)) {
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (cin_nocode(l))
|
if (cin_nocode(l))
|
||||||
continue;
|
continue;
|
||||||
@ -3398,9 +3418,10 @@ term_again:
|
|||||||
|
|
||||||
while (curwin->w_cursor.lnum > 1) {
|
while (curwin->w_cursor.lnum > 1) {
|
||||||
look = ml_get(--curwin->w_cursor.lnum);
|
look = ml_get(--curwin->w_cursor.lnum);
|
||||||
if (!(cin_nocode(look) || cin_ispreproc_cont(
|
if (!(cin_nocode(look)
|
||||||
&look, &curwin->w_cursor.lnum)))
|
|| cin_ispreproc_cont(&look, &curwin->w_cursor.lnum, &amount))) {
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (curwin->w_cursor.lnum > 0
|
if (curwin->w_cursor.lnum > 0
|
||||||
&& cin_ends_in(look, (char_u *)"}", NULL))
|
&& cin_ends_in(look, (char_u *)"}", NULL))
|
||||||
|
@ -139,154 +139,153 @@ static char_u modifier_keys_table[] =
|
|||||||
};
|
};
|
||||||
|
|
||||||
static const struct key_name_entry {
|
static const struct key_name_entry {
|
||||||
int key; ///< Special key code or ASCII value.
|
int key; // Special key code or ascii value
|
||||||
const char *name; ///< Name of the key
|
const char *name; // Name of key
|
||||||
} key_names_table[] = {
|
} key_names_table[] =
|
||||||
{' ', "Space"},
|
{
|
||||||
{TAB, "Tab"},
|
{ ' ', "Space" },
|
||||||
{K_TAB, "Tab"},
|
{ TAB, "Tab" },
|
||||||
{NL, "NL"},
|
{ K_TAB, "Tab" },
|
||||||
{NL, "NewLine"}, // Alternative name
|
{ NL, "NL" },
|
||||||
{NL, "LineFeed"}, // Alternative name
|
{ NL, "NewLine" }, // Alternative name
|
||||||
{NL, "LF"}, // Alternative name
|
{ NL, "LineFeed" }, // Alternative name
|
||||||
{CAR, "CR"},
|
{ NL, "LF" }, // Alternative name
|
||||||
{CAR, "Return"}, // Alternative name
|
{ CAR, "CR" },
|
||||||
{CAR, "Enter"}, // Alternative name
|
{ CAR, "Return" }, // Alternative name
|
||||||
{K_BS, "BS"},
|
{ CAR, "Enter" }, // Alternative name
|
||||||
{K_BS, "BackSpace"}, // Alternative name
|
{ K_BS, "BS" },
|
||||||
{ESC, "Esc"},
|
{ K_BS, "BackSpace" }, // Alternative name
|
||||||
{CSI, "CSI"},
|
{ ESC, "Esc" },
|
||||||
{K_CSI, "xCSI"},
|
{ CSI, "CSI" },
|
||||||
{'|', "Bar"},
|
{ K_CSI, "xCSI" },
|
||||||
{'\\', "Bslash"},
|
{ '|', "Bar" },
|
||||||
{K_DEL, "Del"},
|
{ '\\', "Bslash" },
|
||||||
{K_DEL, "Delete"}, // Alternative name
|
{ K_DEL, "Del" },
|
||||||
{K_KDEL, "kDel"},
|
{ K_DEL, "Delete" }, // Alternative name
|
||||||
{K_UP, "Up"},
|
{ K_KDEL, "kDel" },
|
||||||
{K_DOWN, "Down"},
|
{ K_UP, "Up" },
|
||||||
{K_LEFT, "Left"},
|
{ K_DOWN, "Down" },
|
||||||
{K_RIGHT, "Right"},
|
{ K_LEFT, "Left" },
|
||||||
{K_XUP, "xUp"},
|
{ K_RIGHT, "Right" },
|
||||||
{K_XDOWN, "xDown"},
|
{ K_XUP, "xUp" },
|
||||||
{K_XLEFT, "xLeft"},
|
{ K_XDOWN, "xDown" },
|
||||||
{K_XRIGHT, "xRight"},
|
{ K_XLEFT, "xLeft" },
|
||||||
|
{ K_XRIGHT, "xRight" },
|
||||||
|
|
||||||
{K_F1, "F1"},
|
{ K_F1, "F1" },
|
||||||
{K_F2, "F2"},
|
{ K_F2, "F2" },
|
||||||
{K_F3, "F3"},
|
{ K_F3, "F3" },
|
||||||
{K_F4, "F4"},
|
{ K_F4, "F4" },
|
||||||
{K_F5, "F5"},
|
{ K_F5, "F5" },
|
||||||
{K_F6, "F6"},
|
{ K_F6, "F6" },
|
||||||
{K_F7, "F7"},
|
{ K_F7, "F7" },
|
||||||
{K_F8, "F8"},
|
{ K_F8, "F8" },
|
||||||
{K_F9, "F9"},
|
{ K_F9, "F9" },
|
||||||
{K_F10, "F10"},
|
{ K_F10, "F10" },
|
||||||
|
|
||||||
{K_F11, "F11"},
|
{ K_F11, "F11" },
|
||||||
{K_F12, "F12"},
|
{ K_F12, "F12" },
|
||||||
{K_F13, "F13"},
|
{ K_F13, "F13" },
|
||||||
{K_F14, "F14"},
|
{ K_F14, "F14" },
|
||||||
{K_F15, "F15"},
|
{ K_F15, "F15" },
|
||||||
{K_F16, "F16"},
|
{ K_F16, "F16" },
|
||||||
{K_F17, "F17"},
|
{ K_F17, "F17" },
|
||||||
{K_F18, "F18"},
|
{ K_F18, "F18" },
|
||||||
{K_F19, "F19"},
|
{ K_F19, "F19" },
|
||||||
{K_F20, "F20"},
|
{ K_F20, "F20" },
|
||||||
|
|
||||||
{K_F21, "F21"},
|
{ K_F21, "F21" },
|
||||||
{K_F22, "F22"},
|
{ K_F22, "F22" },
|
||||||
{K_F23, "F23"},
|
{ K_F23, "F23" },
|
||||||
{K_F24, "F24"},
|
{ K_F24, "F24" },
|
||||||
{K_F25, "F25"},
|
{ K_F25, "F25" },
|
||||||
{K_F26, "F26"},
|
{ K_F26, "F26" },
|
||||||
{K_F27, "F27"},
|
{ K_F27, "F27" },
|
||||||
{K_F28, "F28"},
|
{ K_F28, "F28" },
|
||||||
{K_F29, "F29"},
|
{ K_F29, "F29" },
|
||||||
{K_F30, "F30"},
|
{ K_F30, "F30" },
|
||||||
|
|
||||||
{K_F31, "F31"},
|
{ K_F31, "F31" },
|
||||||
{K_F32, "F32"},
|
{ K_F32, "F32" },
|
||||||
{K_F33, "F33"},
|
{ K_F33, "F33" },
|
||||||
{K_F34, "F34"},
|
{ K_F34, "F34" },
|
||||||
{K_F35, "F35"},
|
{ K_F35, "F35" },
|
||||||
{K_F36, "F36"},
|
{ K_F36, "F36" },
|
||||||
{K_F37, "F37"},
|
{ K_F37, "F37" },
|
||||||
|
|
||||||
{K_XF1, "xF1"},
|
{ K_XF1, "xF1" },
|
||||||
{K_XF2, "xF2"},
|
{ K_XF2, "xF2" },
|
||||||
{K_XF3, "xF3"},
|
{ K_XF3, "xF3" },
|
||||||
{K_XF4, "xF4"},
|
{ K_XF4, "xF4" },
|
||||||
|
|
||||||
{K_HELP, "Help"},
|
{ K_HELP, "Help" },
|
||||||
{K_UNDO, "Undo"},
|
{ K_UNDO, "Undo" },
|
||||||
{K_INS, "Insert"},
|
{ K_INS, "Insert" },
|
||||||
{K_INS, "Ins"}, // Alternative name
|
{ K_INS, "Ins" }, // Alternative name
|
||||||
{K_KINS, "kInsert"},
|
{ K_KINS, "kInsert" },
|
||||||
{K_HOME, "Home"},
|
{ K_HOME, "Home" },
|
||||||
{K_KHOME, "kHome"},
|
{ K_KHOME, "kHome" },
|
||||||
{K_XHOME, "xHome"},
|
{ K_XHOME, "xHome" },
|
||||||
{K_ZHOME, "zHome"},
|
{ K_ZHOME, "zHome" },
|
||||||
{K_END, "End"},
|
{ K_END, "End" },
|
||||||
{K_KEND, "kEnd"},
|
{ K_KEND, "kEnd" },
|
||||||
{K_XEND, "xEnd"},
|
{ K_XEND, "xEnd" },
|
||||||
{K_ZEND, "zEnd"},
|
{ K_ZEND, "zEnd" },
|
||||||
{K_PAGEUP, "PageUp"},
|
{ K_PAGEUP, "PageUp" },
|
||||||
{K_PAGEDOWN, "PageDown"},
|
{ K_PAGEDOWN, "PageDown" },
|
||||||
{K_KPAGEUP, "kPageUp"},
|
{ K_KPAGEUP, "kPageUp" },
|
||||||
{K_KPAGEDOWN, "kPageDown"},
|
{ K_KPAGEDOWN, "kPageDown" },
|
||||||
|
|
||||||
{K_KPLUS, "kPlus"},
|
{ K_KPLUS, "kPlus" },
|
||||||
{K_KMINUS, "kMinus"},
|
{ K_KMINUS, "kMinus" },
|
||||||
{K_KDIVIDE, "kDivide"},
|
{ K_KDIVIDE, "kDivide" },
|
||||||
{K_KMULTIPLY, "kMultiply"},
|
{ K_KMULTIPLY, "kMultiply" },
|
||||||
{K_KENTER, "kEnter"},
|
{ K_KENTER, "kEnter" },
|
||||||
{K_KPOINT, "kPoint"},
|
{ K_KPOINT, "kPoint" },
|
||||||
|
|
||||||
{K_K0, "k0"},
|
{ K_K0, "k0" },
|
||||||
{K_K1, "k1"},
|
{ K_K1, "k1" },
|
||||||
{K_K2, "k2"},
|
{ K_K2, "k2" },
|
||||||
{K_K3, "k3"},
|
{ K_K3, "k3" },
|
||||||
{K_K4, "k4"},
|
{ K_K4, "k4" },
|
||||||
{K_K5, "k5"},
|
{ K_K5, "k5" },
|
||||||
{K_K6, "k6"},
|
{ K_K6, "k6" },
|
||||||
{K_K7, "k7"},
|
{ K_K7, "k7" },
|
||||||
{K_K8, "k8"},
|
{ K_K8, "k8" },
|
||||||
{K_K9, "k9"},
|
{ K_K9, "k9" },
|
||||||
|
|
||||||
{'<', "lt"},
|
{ '<', "lt" },
|
||||||
|
|
||||||
{K_MOUSE, "Mouse"},
|
{ K_MOUSE, "Mouse" },
|
||||||
{K_LEFTMOUSE, "LeftMouse"},
|
{ K_LEFTMOUSE, "LeftMouse" },
|
||||||
{K_LEFTMOUSE_NM, "LeftMouseNM"},
|
{ K_LEFTMOUSE_NM, "LeftMouseNM" },
|
||||||
{K_LEFTDRAG, "LeftDrag"},
|
{ K_LEFTDRAG, "LeftDrag" },
|
||||||
{K_LEFTRELEASE, "LeftRelease"},
|
{ K_LEFTRELEASE, "LeftRelease" },
|
||||||
{K_LEFTRELEASE_NM, "LeftReleaseNM"},
|
{ K_LEFTRELEASE_NM, "LeftReleaseNM" },
|
||||||
{K_MIDDLEMOUSE, "MiddleMouse"},
|
{ K_MIDDLEMOUSE, "MiddleMouse" },
|
||||||
{K_MIDDLEDRAG, "MiddleDrag"},
|
{ K_MIDDLEDRAG, "MiddleDrag" },
|
||||||
{K_MIDDLERELEASE, "MiddleRelease"},
|
{ K_MIDDLERELEASE, "MiddleRelease" },
|
||||||
{K_RIGHTMOUSE, "RightMouse"},
|
{ K_RIGHTMOUSE, "RightMouse" },
|
||||||
{K_RIGHTDRAG, "RightDrag"},
|
{ K_RIGHTDRAG, "RightDrag" },
|
||||||
{K_RIGHTRELEASE, "RightRelease"},
|
{ K_RIGHTRELEASE, "RightRelease" },
|
||||||
{K_MOUSEDOWN, "ScrollWheelUp"},
|
{ K_MOUSEDOWN, "ScrollWheelUp" },
|
||||||
{K_MOUSEUP, "ScrollWheelDown"},
|
{ K_MOUSEUP, "ScrollWheelDown" },
|
||||||
{K_MOUSELEFT, "ScrollWheelRight"},
|
{ K_MOUSELEFT, "ScrollWheelRight" },
|
||||||
{K_MOUSERIGHT, "ScrollWheelLeft"},
|
{ K_MOUSERIGHT, "ScrollWheelLeft" },
|
||||||
{K_MOUSEDOWN, "MouseDown"}, // OBSOLETE: Use ScrollWheelXXX instead
|
{ K_MOUSEDOWN, "MouseDown" }, // OBSOLETE: Use
|
||||||
{K_MOUSEUP, "MouseUp"}, // Same
|
{ K_MOUSEUP, "MouseUp" }, // ScrollWheelXXX instead
|
||||||
{K_X1MOUSE, "X1Mouse"},
|
{ K_X1MOUSE, "X1Mouse" },
|
||||||
{K_X1DRAG, "X1Drag"},
|
{ K_X1DRAG, "X1Drag" },
|
||||||
{K_X1RELEASE, "X1Release"},
|
{ K_X1RELEASE, "X1Release" },
|
||||||
{K_X2MOUSE, "X2Mouse"},
|
{ K_X2MOUSE, "X2Mouse" },
|
||||||
{K_X2DRAG, "X2Drag"},
|
{ K_X2DRAG, "X2Drag" },
|
||||||
{K_X2RELEASE, "X2Release"},
|
{ K_X2RELEASE, "X2Release" },
|
||||||
{K_DROP, "Drop"},
|
{ K_DROP, "Drop" },
|
||||||
{K_ZERO, "Nul"},
|
{ K_ZERO, "Nul" },
|
||||||
{K_SNR, "SNR"},
|
{ K_SNR, "SNR" },
|
||||||
{K_PLUG, "Plug"},
|
{ K_PLUG, "Plug" },
|
||||||
{K_PASTE, "Paste"},
|
{ K_PASTE, "Paste" },
|
||||||
{K_FOCUSGAINED, "FocusGained"},
|
{ 0, NULL }
|
||||||
{K_FOCUSLOST, "FocusLost"},
|
|
||||||
{0, NULL}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct mousetable {
|
static struct mousetable {
|
||||||
@ -720,8 +719,8 @@ int get_special_key_code(const char_u *name)
|
|||||||
for (int i = 0; key_names_table[i].name != NULL; i++) {
|
for (int i = 0; key_names_table[i].name != NULL; i++) {
|
||||||
const char *const table_name = key_names_table[i].name;
|
const char *const table_name = key_names_table[i].name;
|
||||||
int j;
|
int j;
|
||||||
for (j = 0; vim_isIDc(name[j]) && table_name[j] != NUL; j++) {
|
for (j = 0; vim_isIDc(name[j]) && table_name[j] != NUL; j++)
|
||||||
if (TOLOWER_ASC(table_name[j]) != TOLOWER_ASC(name[j])) {
|
if (TOLOWER_ASC(table_name[j]) != TOLOWER_ASC(name[j]))
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -428,8 +428,6 @@ enum key_extra {
|
|||||||
#define K_CMDWIN TERMCAP2KEY(KS_EXTRA, KE_CMDWIN)
|
#define K_CMDWIN TERMCAP2KEY(KS_EXTRA, KE_CMDWIN)
|
||||||
|
|
||||||
#define K_DROP TERMCAP2KEY(KS_EXTRA, KE_DROP)
|
#define K_DROP TERMCAP2KEY(KS_EXTRA, KE_DROP)
|
||||||
#define K_FOCUSGAINED TERMCAP2KEY(KS_EXTRA, KE_FOCUSGAINED)
|
|
||||||
#define K_FOCUSLOST TERMCAP2KEY(KS_EXTRA, KE_FOCUSLOST)
|
|
||||||
|
|
||||||
#define K_EVENT TERMCAP2KEY(KS_EXTRA, KE_EVENT)
|
#define K_EVENT TERMCAP2KEY(KS_EXTRA, KE_EVENT)
|
||||||
#define K_PASTE TERMCAP2KEY(KS_EXTRA, KE_PASTE)
|
#define K_PASTE TERMCAP2KEY(KS_EXTRA, KE_PASTE)
|
||||||
|
@ -95,8 +95,12 @@ void log_unlock(void)
|
|||||||
uv_mutex_unlock(&mutex);
|
uv_mutex_unlock(&mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool do_log(int log_level, const char *func_name, int line_num, bool eol,
|
/// @param context description of a shared context or subsystem
|
||||||
const char* fmt, ...) FUNC_ATTR_UNUSED
|
/// @param func_name function name, or NULL
|
||||||
|
/// @param line_num source line number, or -1
|
||||||
|
bool do_log(int log_level, const char *context, const char *func_name,
|
||||||
|
int line_num, bool eol, const char *fmt, ...)
|
||||||
|
FUNC_ATTR_UNUSED
|
||||||
{
|
{
|
||||||
if (log_level < MIN_LOG_LEVEL) {
|
if (log_level < MIN_LOG_LEVEL) {
|
||||||
return false;
|
return false;
|
||||||
@ -112,8 +116,8 @@ bool do_log(int log_level, const char *func_name, int line_num, bool eol,
|
|||||||
|
|
||||||
va_list args;
|
va_list args;
|
||||||
va_start(args, fmt);
|
va_start(args, fmt);
|
||||||
ret = v_do_log_to_file(log_file, log_level, func_name, line_num, eol,
|
ret = v_do_log_to_file(log_file, log_level, context, func_name, line_num,
|
||||||
fmt, args);
|
eol, fmt, args);
|
||||||
va_end(args);
|
va_end(args);
|
||||||
|
|
||||||
if (log_file != stderr && log_file != stdout) {
|
if (log_file != stderr && log_file != stdout) {
|
||||||
@ -151,7 +155,7 @@ FILE *open_log_file(void)
|
|||||||
static bool opening_log_file = false;
|
static bool opening_log_file = false;
|
||||||
// check if it's a recursive call
|
// check if it's a recursive call
|
||||||
if (opening_log_file) {
|
if (opening_log_file) {
|
||||||
do_log_to_file(stderr, ERROR_LOG_LEVEL, __func__, __LINE__, true,
|
do_log_to_file(stderr, ERROR_LOG_LEVEL, NULL, __func__, __LINE__, true,
|
||||||
"Cannot LOG() recursively.");
|
"Cannot LOG() recursively.");
|
||||||
return stderr;
|
return stderr;
|
||||||
}
|
}
|
||||||
@ -171,7 +175,7 @@ FILE *open_log_file(void)
|
|||||||
// - LOG() is called before early_init()
|
// - LOG() is called before early_init()
|
||||||
// - Directory does not exist
|
// - Directory does not exist
|
||||||
// - File is not writable
|
// - File is not writable
|
||||||
do_log_to_file(stderr, ERROR_LOG_LEVEL, __func__, __LINE__, true,
|
do_log_to_file(stderr, ERROR_LOG_LEVEL, NULL, __func__, __LINE__, true,
|
||||||
"Logging to stderr, failed to open $" LOG_FILE_ENV ": %s",
|
"Logging to stderr, failed to open $" LOG_FILE_ENV ": %s",
|
||||||
log_file_path);
|
log_file_path);
|
||||||
return stderr;
|
return stderr;
|
||||||
@ -201,7 +205,7 @@ void log_callstack_to_file(FILE *log_file, const char *const func_name,
|
|||||||
// Now we have a command string like:
|
// Now we have a command string like:
|
||||||
// addr2line -e /path/to/exe -f -p 0x123 0x456 ...
|
// addr2line -e /path/to/exe -f -p 0x123 0x456 ...
|
||||||
|
|
||||||
do_log_to_file(log_file, DEBUG_LOG_LEVEL, func_name, line_num, true,
|
do_log_to_file(log_file, DEBUG_LOG_LEVEL, NULL, func_name, line_num, true,
|
||||||
"trace:");
|
"trace:");
|
||||||
FILE *fp = popen(cmdbuf, "r");
|
FILE *fp = popen(cmdbuf, "r");
|
||||||
char linebuf[IOSIZE];
|
char linebuf[IOSIZE];
|
||||||
@ -230,27 +234,28 @@ end:
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static bool do_log_to_file(FILE *log_file, int log_level,
|
static bool do_log_to_file(FILE *log_file, int log_level, const char *context,
|
||||||
const char *func_name, int line_num, bool eol,
|
const char *func_name, int line_num, bool eol,
|
||||||
const char* fmt, ...)
|
const char* fmt, ...)
|
||||||
{
|
{
|
||||||
va_list args;
|
va_list args;
|
||||||
va_start(args, fmt);
|
va_start(args, fmt);
|
||||||
bool ret = v_do_log_to_file(log_file, log_level, func_name, line_num, eol,
|
bool ret = v_do_log_to_file(log_file, log_level, context, func_name,
|
||||||
fmt, args);
|
line_num, eol, fmt, args);
|
||||||
va_end(args);
|
va_end(args);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool v_do_log_to_file(FILE *log_file, int log_level,
|
static bool v_do_log_to_file(FILE *log_file, int log_level,
|
||||||
const char *func_name, int line_num, bool eol,
|
const char *context, const char *func_name,
|
||||||
const char* fmt, va_list args)
|
int line_num, bool eol, const char *fmt,
|
||||||
|
va_list args)
|
||||||
{
|
{
|
||||||
static const char *log_levels[] = {
|
static const char *log_levels[] = {
|
||||||
[DEBUG_LOG_LEVEL] = "DEBUG",
|
[DEBUG_LOG_LEVEL] = "DEBUG",
|
||||||
[INFO_LOG_LEVEL] = "INFO ",
|
[INFO_LOG_LEVEL] = "INFO ",
|
||||||
[WARNING_LOG_LEVEL] = "WARN ",
|
[WARN_LOG_LEVEL] = "WARN ",
|
||||||
[ERROR_LOG_LEVEL] = "ERROR",
|
[ERROR_LOG_LEVEL] = "ERROR",
|
||||||
};
|
};
|
||||||
assert(log_level >= DEBUG_LOG_LEVEL && log_level <= ERROR_LOG_LEVEL);
|
assert(log_level >= DEBUG_LOG_LEVEL && log_level <= ERROR_LOG_LEVEL);
|
||||||
@ -268,8 +273,15 @@ static bool v_do_log_to_file(FILE *log_file, int log_level,
|
|||||||
|
|
||||||
// print the log message prefixed by the current timestamp and pid
|
// print the log message prefixed by the current timestamp and pid
|
||||||
int64_t pid = os_get_pid();
|
int64_t pid = os_get_pid();
|
||||||
if (fprintf(log_file, "%s %s %" PRId64 "/%s:%d: ", date_time,
|
int rv = (line_num == -1 || func_name == NULL)
|
||||||
log_levels[log_level], pid, func_name, line_num) < 0) {
|
? fprintf(log_file, "%s %s %" PRId64 " %s", date_time,
|
||||||
|
log_levels[log_level], pid,
|
||||||
|
(context == NULL ? "?:" : context))
|
||||||
|
: fprintf(log_file, "%s %s %" PRId64 " %s%s:%d: ", date_time,
|
||||||
|
log_levels[log_level], pid,
|
||||||
|
(context == NULL ? "" : context),
|
||||||
|
func_name, line_num);
|
||||||
|
if (rv < 0) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (vfprintf(log_file, fmt, args) < 0) {
|
if (vfprintf(log_file, fmt, args) < 0) {
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
|
|
||||||
#define DEBUG_LOG_LEVEL 0
|
#define DEBUG_LOG_LEVEL 0
|
||||||
#define INFO_LOG_LEVEL 1
|
#define INFO_LOG_LEVEL 1
|
||||||
#define WARNING_LOG_LEVEL 2
|
#define WARN_LOG_LEVEL 2
|
||||||
#define ERROR_LOG_LEVEL 3
|
#define ERROR_LOG_LEVEL 3
|
||||||
|
|
||||||
#define DLOG(...)
|
#define DLOG(...)
|
||||||
@ -22,42 +22,42 @@
|
|||||||
# define MIN_LOG_LEVEL INFO_LOG_LEVEL
|
# define MIN_LOG_LEVEL INFO_LOG_LEVEL
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define LOG(level, ...) do_log((level), __func__, __LINE__, true, \
|
#define LOG(level, ...) do_log((level), NULL, __func__, __LINE__, true, \
|
||||||
__VA_ARGS__)
|
__VA_ARGS__)
|
||||||
|
|
||||||
#if MIN_LOG_LEVEL <= DEBUG_LOG_LEVEL
|
#if MIN_LOG_LEVEL <= DEBUG_LOG_LEVEL
|
||||||
# undef DLOG
|
# undef DLOG
|
||||||
# undef DLOGN
|
# undef DLOGN
|
||||||
# define DLOG(...) do_log(DEBUG_LOG_LEVEL, __func__, __LINE__, true, \
|
# define DLOG(...) do_log(DEBUG_LOG_LEVEL, NULL, __func__, __LINE__, true, \
|
||||||
__VA_ARGS__)
|
__VA_ARGS__)
|
||||||
# define DLOGN(...) do_log(DEBUG_LOG_LEVEL, __func__, __LINE__, false, \
|
# define DLOGN(...) do_log(DEBUG_LOG_LEVEL, NULL, __func__, __LINE__, false, \
|
||||||
__VA_ARGS__)
|
__VA_ARGS__)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if MIN_LOG_LEVEL <= INFO_LOG_LEVEL
|
#if MIN_LOG_LEVEL <= INFO_LOG_LEVEL
|
||||||
# undef ILOG
|
# undef ILOG
|
||||||
# undef ILOGN
|
# undef ILOGN
|
||||||
# define ILOG(...) do_log(INFO_LOG_LEVEL, __func__, __LINE__, true, \
|
# define ILOG(...) do_log(INFO_LOG_LEVEL, NULL, __func__, __LINE__, true, \
|
||||||
__VA_ARGS__)
|
__VA_ARGS__)
|
||||||
# define ILOGN(...) do_log(INFO_LOG_LEVEL, __func__, __LINE__, false, \
|
# define ILOGN(...) do_log(INFO_LOG_LEVEL, NULL, __func__, __LINE__, false, \
|
||||||
__VA_ARGS__)
|
__VA_ARGS__)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if MIN_LOG_LEVEL <= WARNING_LOG_LEVEL
|
#if MIN_LOG_LEVEL <= WARN_LOG_LEVEL
|
||||||
# undef WLOG
|
# undef WLOG
|
||||||
# undef WLOGN
|
# undef WLOGN
|
||||||
# define WLOG(...) do_log(WARNING_LOG_LEVEL, __func__, __LINE__, true, \
|
# define WLOG(...) do_log(WARN_LOG_LEVEL, NULL, __func__, __LINE__, true, \
|
||||||
__VA_ARGS__)
|
__VA_ARGS__)
|
||||||
# define WLOGN(...) do_log(WARNING_LOG_LEVEL, __func__, __LINE__, false, \
|
# define WLOGN(...) do_log(WARN_LOG_LEVEL, NULL, __func__, __LINE__, false, \
|
||||||
__VA_ARGS__)
|
__VA_ARGS__)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if MIN_LOG_LEVEL <= ERROR_LOG_LEVEL
|
#if MIN_LOG_LEVEL <= ERROR_LOG_LEVEL
|
||||||
# undef ELOG
|
# undef ELOG
|
||||||
# undef ELOGN
|
# undef ELOGN
|
||||||
# define ELOG(...) do_log(ERROR_LOG_LEVEL, __func__, __LINE__, true, \
|
# define ELOG(...) do_log(ERROR_LOG_LEVEL, NULL, __func__, __LINE__, true, \
|
||||||
__VA_ARGS__)
|
__VA_ARGS__)
|
||||||
# define ELOGN(...) do_log(ERROR_LOG_LEVEL, __func__, __LINE__, false, \
|
# define ELOGN(...) do_log(ERROR_LOG_LEVEL, NULL, __func__, __LINE__, false, \
|
||||||
__VA_ARGS__)
|
__VA_ARGS__)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
126
src/nvim/main.c
126
src/nvim/main.c
@ -7,6 +7,11 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
#ifdef WIN32
|
||||||
|
# include <wchar.h>
|
||||||
|
# include <winnls.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <msgpack.h>
|
#include <msgpack.h>
|
||||||
|
|
||||||
#include "nvim/ascii.h"
|
#include "nvim/ascii.h"
|
||||||
@ -215,10 +220,22 @@ void early_init(void)
|
|||||||
|
|
||||||
#ifdef MAKE_LIB
|
#ifdef MAKE_LIB
|
||||||
int nvim_main(int argc, char **argv)
|
int nvim_main(int argc, char **argv)
|
||||||
|
#elif defined(WIN32)
|
||||||
|
int wmain(int argc, wchar_t **argv_w) // multibyte args on Windows. #7060
|
||||||
#else
|
#else
|
||||||
int main(int argc, char **argv)
|
int main(int argc, char **argv)
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
|
#if defined(WIN32) && !defined(MAKE_LIB)
|
||||||
|
char *argv[argc];
|
||||||
|
for (int i = 0; i < argc; i++) {
|
||||||
|
char *buf = NULL;
|
||||||
|
utf16_to_utf8(argv_w[i], &buf);
|
||||||
|
assert(buf);
|
||||||
|
argv[i] = buf;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
argv0 = argv[0];
|
argv0 = argv[0];
|
||||||
|
|
||||||
char_u *fname = NULL; // file name from command line
|
char_u *fname = NULL; // file name from command line
|
||||||
@ -632,6 +649,11 @@ void getout(int exitval)
|
|||||||
/* Position the cursor again, the autocommands may have moved it */
|
/* Position the cursor again, the autocommands may have moved it */
|
||||||
ui_cursor_goto((int)Rows - 1, 0);
|
ui_cursor_goto((int)Rows - 1, 0);
|
||||||
|
|
||||||
|
// Apply 'titleold'.
|
||||||
|
if (p_title && *p_titleold != NUL) {
|
||||||
|
ui_call_set_title(cstr_as_string((char *)p_titleold));
|
||||||
|
}
|
||||||
|
|
||||||
#if defined(USE_ICONV) && defined(DYNAMIC_ICONV)
|
#if defined(USE_ICONV) && defined(DYNAMIC_ICONV)
|
||||||
iconv_end();
|
iconv_end();
|
||||||
#endif
|
#endif
|
||||||
@ -1291,10 +1313,29 @@ static void set_window_layout(mparm_T *paramp)
|
|||||||
static void load_plugins(void)
|
static void load_plugins(void)
|
||||||
{
|
{
|
||||||
if (p_lpl) {
|
if (p_lpl) {
|
||||||
source_runtime((char_u *)"plugin/**/*.vim", DIP_ALL | DIP_NOAFTER); // NOLINT
|
char_u *rtp_copy = NULL;
|
||||||
TIME_MSG("loading plugins");
|
|
||||||
|
|
||||||
ex_packloadall(NULL);
|
// First add all package directories to 'runtimepath', so that their
|
||||||
|
// autoload directories can be found. Only if not done already with a
|
||||||
|
// :packloadall command.
|
||||||
|
// Make a copy of 'runtimepath', so that source_runtime does not use the
|
||||||
|
// pack directories.
|
||||||
|
if (!did_source_packages) {
|
||||||
|
rtp_copy = vim_strsave(p_rtp);
|
||||||
|
add_pack_start_dirs();
|
||||||
|
}
|
||||||
|
|
||||||
|
source_in_path(rtp_copy == NULL ? p_rtp : rtp_copy,
|
||||||
|
(char_u *)"plugin/**/*.vim", // NOLINT
|
||||||
|
DIP_ALL | DIP_NOAFTER);
|
||||||
|
TIME_MSG("loading plugins");
|
||||||
|
xfree(rtp_copy);
|
||||||
|
|
||||||
|
// Only source "start" packages if not done already with a :packloadall
|
||||||
|
// command.
|
||||||
|
if (!did_source_packages) {
|
||||||
|
load_start_packages();
|
||||||
|
}
|
||||||
TIME_MSG("loading packages");
|
TIME_MSG("loading packages");
|
||||||
|
|
||||||
source_runtime((char_u *)"plugin/**/*.vim", DIP_ALL | DIP_AFTER);
|
source_runtime((char_u *)"plugin/**/*.vim", DIP_ALL | DIP_AFTER);
|
||||||
@ -1878,54 +1919,47 @@ static void usage(void)
|
|||||||
signal_stop(); // kill us with CTRL-C here, if you like
|
signal_stop(); // kill us with CTRL-C here, if you like
|
||||||
|
|
||||||
mch_msg(_("Usage:\n"));
|
mch_msg(_("Usage:\n"));
|
||||||
mch_msg(_(" nvim [arguments] [file ...] Edit specified file(s)\n"));
|
mch_msg(_(" nvim [options] [file ...] Edit file(s)\n"));
|
||||||
mch_msg(_(" nvim [arguments] - Read text from stdin\n"));
|
mch_msg(_(" nvim [options] - Read text from stdin\n"));
|
||||||
mch_msg(_(" nvim [arguments] -t <tag> Edit file where tag is defined\n"));
|
mch_msg(_(" nvim [options] -t <tag> Edit file where tag is defined\n"));
|
||||||
mch_msg(_(" nvim [arguments] -q [errorfile] Edit file with first error\n"));
|
mch_msg(_(" nvim [options] -q [errorfile] Edit file with first error\n"));
|
||||||
mch_msg(_("\nArguments:\n"));
|
mch_msg(_("\nOptions:\n"));
|
||||||
mch_msg(_(" -- Only file names after this\n"));
|
mch_msg(_(" -- Only file names after this\n"));
|
||||||
|
mch_msg(_(" + Start at end of file\n"));
|
||||||
|
mch_msg(_(" --cmd <cmd> Execute <cmd> before any config\n"));
|
||||||
|
mch_msg(_(" +<cmd>, -c <cmd> Execute <cmd> after config and first file\n"));
|
||||||
|
mch_msg("\n");
|
||||||
|
mch_msg(_(" -b Binary mode\n"));
|
||||||
|
mch_msg(_(" -d Diff mode\n"));
|
||||||
|
mch_msg(_(" -e, -E Ex mode, Improved Ex mode\n"));
|
||||||
|
mch_msg(_(" -es Silent (batch) mode\n"));
|
||||||
|
mch_msg(_(" -h, --help Print this help message\n"));
|
||||||
|
mch_msg(_(" -i <shada> Use this shada file\n"));
|
||||||
|
mch_msg(_(" -m Modifications (writing files) not allowed\n"));
|
||||||
|
mch_msg(_(" -M Modifications in text not allowed\n"));
|
||||||
|
mch_msg(_(" -n No swap file, use memory only\n"));
|
||||||
|
mch_msg(_(" -o[N] Open N windows (default: one per file)\n"));
|
||||||
|
mch_msg(_(" -O[N] Open N vertical windows (default: one per file)\n"));
|
||||||
|
mch_msg(_(" -p[N] Open N tab pages (default: one per file)\n"));
|
||||||
|
mch_msg(_(" -r, -L List swap files\n"));
|
||||||
|
mch_msg(_(" -r <file> Recover edit state for this file\n"));
|
||||||
|
mch_msg(_(" -R Read-only mode\n"));
|
||||||
|
mch_msg(_(" -S <session> Source <session> after loading the first file\n"));
|
||||||
|
mch_msg(_(" -s <scriptin> Read Normal mode commands from <scriptin>\n"));
|
||||||
|
mch_msg(_(" -u <config> Use this config file\n"));
|
||||||
|
mch_msg(_(" -v, --version Print version information\n"));
|
||||||
|
mch_msg(_(" -V[N][file] Verbose [level][file]\n"));
|
||||||
|
mch_msg(_(" -Z Restricted mode\n"));
|
||||||
|
mch_msg("\n");
|
||||||
|
mch_msg(_(" --api-info Write msgpack-encoded API metadata to stdout\n"));
|
||||||
|
mch_msg(_(" --embed Use stdin/stdout as a msgpack-rpc channel\n"));
|
||||||
|
mch_msg(_(" --headless Don't start a user interface\n"));
|
||||||
#if !defined(UNIX)
|
#if !defined(UNIX)
|
||||||
mch_msg(_(" --literal Don't expand wildcards\n"));
|
mch_msg(_(" --literal Don't expand wildcards\n"));
|
||||||
#endif
|
#endif
|
||||||
mch_msg(_(" -e Ex mode\n"));
|
mch_msg(_(" --noplugin Don't load plugins\n"));
|
||||||
mch_msg(_(" -E Improved Ex mode\n"));
|
|
||||||
mch_msg(_(" -s Silent (batch) mode (only for ex mode)\n"));
|
|
||||||
mch_msg(_(" -d Diff mode\n"));
|
|
||||||
mch_msg(_(" -R Read-only mode\n"));
|
|
||||||
mch_msg(_(" -Z Restricted mode\n"));
|
|
||||||
mch_msg(_(" -m Modifications (writing files) not allowed\n"));
|
|
||||||
mch_msg(_(" -M Modifications in text not allowed\n"));
|
|
||||||
mch_msg(_(" -b Binary mode\n"));
|
|
||||||
mch_msg(_(" -l Lisp mode\n"));
|
|
||||||
mch_msg(_(" -A Arabic mode\n"));
|
|
||||||
mch_msg(_(" -F Farsi mode\n"));
|
|
||||||
mch_msg(_(" -H Hebrew mode\n"));
|
|
||||||
mch_msg(_(" -V[N][file] Be verbose [level N][log messages to file]\n"));
|
|
||||||
mch_msg(_(" -D Debugging mode\n"));
|
|
||||||
mch_msg(_(" -n No swap file, use memory only\n"));
|
|
||||||
mch_msg(_(" -r, -L List swap files and exit\n"));
|
|
||||||
mch_msg(_(" -r <file> Recover crashed session\n"));
|
|
||||||
mch_msg(_(" -u <vimrc> Use <vimrc> instead of the default\n"));
|
|
||||||
mch_msg(_(" -i <shada> Use <shada> instead of the default\n"));
|
|
||||||
mch_msg(_(" --noplugin Don't load plugin scripts\n"));
|
|
||||||
mch_msg(_(" -o[N] Open N windows (default: one for each file)\n"));
|
|
||||||
mch_msg(_(" -O[N] Like -o but split vertically\n"));
|
|
||||||
mch_msg(_(" -p[N] Open N tab pages (default: one for each file)\n"));
|
|
||||||
mch_msg(_(" + Start at end of file\n"));
|
|
||||||
mch_msg(_(" +<linenum> Start at line <linenum>\n"));
|
|
||||||
mch_msg(_(" +/<pattern> Start at first occurrence of <pattern>\n"));
|
|
||||||
mch_msg(_(" --cmd <command> Execute <command> before loading any vimrc\n"));
|
|
||||||
mch_msg(_(" -c <command> Execute <command> after loading the first file\n"));
|
|
||||||
mch_msg(_(" -S <session> Source <session> after loading the first file\n"));
|
|
||||||
mch_msg(_(" -s <scriptin> Read Normal mode commands from <scriptin>\n"));
|
|
||||||
mch_msg(_(" -w <scriptout> Append all typed characters to <scriptout>\n"));
|
|
||||||
mch_msg(_(" -W <scriptout> Write all typed characters to <scriptout>\n"));
|
|
||||||
mch_msg(_(" --startuptime <file> Write startup timing messages to <file>\n"));
|
mch_msg(_(" --startuptime <file> Write startup timing messages to <file>\n"));
|
||||||
mch_msg(_(" --api-info Dump API metadata serialized to msgpack and exit\n"));
|
mch_msg(_("\nSee \":help startup-options\" for all options.\n"));
|
||||||
mch_msg(_(" --embed Use stdin/stdout as a msgpack-rpc channel\n"));
|
|
||||||
mch_msg(_(" --headless Don't start a user interface\n"));
|
|
||||||
mch_msg(_(" -v, --version Print version information and exit\n"));
|
|
||||||
mch_msg(_(" -h, --help Print this help message and exit\n"));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -2164,16 +2164,21 @@ void do_check_cursorbind(void)
|
|||||||
int restart_edit_save = restart_edit;
|
int restart_edit_save = restart_edit;
|
||||||
restart_edit = true;
|
restart_edit = true;
|
||||||
check_cursor();
|
check_cursor();
|
||||||
|
if (curwin->w_p_cul || curwin->w_p_cuc) {
|
||||||
|
validate_cursor();
|
||||||
|
}
|
||||||
restart_edit = restart_edit_save;
|
restart_edit = restart_edit_save;
|
||||||
}
|
}
|
||||||
/* Correct cursor for multi-byte character. */
|
// Correct cursor for multi-byte character.
|
||||||
if (has_mbyte)
|
if (has_mbyte) {
|
||||||
mb_adjust_cursor();
|
mb_adjust_cursor();
|
||||||
|
}
|
||||||
redraw_later(VALID);
|
redraw_later(VALID);
|
||||||
|
|
||||||
/* Only scroll when 'scrollbind' hasn't done this. */
|
// Only scroll when 'scrollbind' hasn't done this.
|
||||||
if (!curwin->w_p_scb)
|
if (!curwin->w_p_scb) {
|
||||||
update_topline();
|
update_topline();
|
||||||
|
}
|
||||||
curwin->w_redr_status = true;
|
curwin->w_redr_status = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -62,7 +62,7 @@ typedef struct {
|
|||||||
ChannelType type;
|
ChannelType type;
|
||||||
msgpack_unpacker *unpacker;
|
msgpack_unpacker *unpacker;
|
||||||
union {
|
union {
|
||||||
Stream stream;
|
Stream stream; // bidirectional (socket)
|
||||||
Process *proc;
|
Process *proc;
|
||||||
struct {
|
struct {
|
||||||
Stream in;
|
Stream in;
|
||||||
@ -133,6 +133,9 @@ uint64_t channel_from_process(Process *proc, uint64_t id, char *source)
|
|||||||
rstream_init(proc->out, 0);
|
rstream_init(proc->out, 0);
|
||||||
rstream_start(proc->out, receive_msgpack, channel);
|
rstream_start(proc->out, receive_msgpack, channel);
|
||||||
|
|
||||||
|
DLOG("ch %" PRIu64 " in-stream=%p out-stream=%p", channel->id, proc->in,
|
||||||
|
proc->out);
|
||||||
|
|
||||||
return channel->id;
|
return channel->id;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -150,6 +153,9 @@ void channel_from_connection(SocketWatcher *watcher)
|
|||||||
wstream_init(&channel->data.stream, 0);
|
wstream_init(&channel->data.stream, 0);
|
||||||
rstream_init(&channel->data.stream, CHANNEL_BUFFER_SIZE);
|
rstream_init(&channel->data.stream, CHANNEL_BUFFER_SIZE);
|
||||||
rstream_start(&channel->data.stream, receive_msgpack, channel);
|
rstream_start(&channel->data.stream, receive_msgpack, channel);
|
||||||
|
|
||||||
|
DLOG("ch %" PRIu64 " in/out-stream=%p", channel->id,
|
||||||
|
&channel->data.stream);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @param source description of source function, rplugin name, TCP addr, etc
|
/// @param source description of source function, rplugin name, TCP addr, etc
|
||||||
@ -182,12 +188,11 @@ uint64_t channel_connect(bool tcp, const char *address, int timeout,
|
|||||||
return channel->id;
|
return channel->id;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Sends event/arguments to channel
|
/// Publishes an event to a channel.
|
||||||
///
|
///
|
||||||
/// @param id The channel id. If 0, the event will be sent to all
|
/// @param id Channel id. 0 means "broadcast to all subscribed channels"
|
||||||
/// channels that have subscribed to the event type
|
/// @param name Event name (application-defined)
|
||||||
/// @param name The event name, an arbitrary string
|
/// @param args Array of event arguments
|
||||||
/// @param args Array with event arguments
|
|
||||||
/// @return True if the event was sent successfully, false otherwise.
|
/// @return True if the event was sent successfully, false otherwise.
|
||||||
bool channel_send_event(uint64_t id, const char *name, Array args)
|
bool channel_send_event(uint64_t id, const char *name, Array args)
|
||||||
{
|
{
|
||||||
@ -209,7 +214,6 @@ bool channel_send_event(uint64_t id, const char *name, Array args)
|
|||||||
send_event(channel, name, args);
|
send_event(channel, name, args);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// TODO(tarruda): Implement event broadcasting in vimscript
|
|
||||||
broadcast_event(name, args);
|
broadcast_event(name, args);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -344,6 +348,9 @@ void channel_from_stdio(void)
|
|||||||
rstream_start(&channel->data.std.in, receive_msgpack, channel);
|
rstream_start(&channel->data.std.in, receive_msgpack, channel);
|
||||||
// write stream
|
// write stream
|
||||||
wstream_init_fd(&main_loop, &channel->data.std.out, 1, 0);
|
wstream_init_fd(&main_loop, &channel->data.std.out, 1, 0);
|
||||||
|
|
||||||
|
DLOG("ch %" PRIu64 " in-stream=%p out-stream=%p", channel->id,
|
||||||
|
&channel->data.std.in, &channel->data.std.out);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates a loopback channel. This is used to avoid deadlock
|
/// Creates a loopback channel. This is used to avoid deadlock
|
||||||
@ -363,6 +370,7 @@ void channel_process_exit(uint64_t id, int status)
|
|||||||
decref(channel);
|
decref(channel);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// rstream.c:read_event() invokes this as stream->read_cb().
|
||||||
static void receive_msgpack(Stream *stream, RBuffer *rbuf, size_t c,
|
static void receive_msgpack(Stream *stream, RBuffer *rbuf, size_t c,
|
||||||
void *data, bool eof)
|
void *data, bool eof)
|
||||||
{
|
{
|
||||||
@ -374,12 +382,24 @@ static void receive_msgpack(Stream *stream, RBuffer *rbuf, size_t c,
|
|||||||
char buf[256];
|
char buf[256];
|
||||||
snprintf(buf, sizeof(buf), "ch %" PRIu64 " was closed by the client",
|
snprintf(buf, sizeof(buf), "ch %" PRIu64 " was closed by the client",
|
||||||
channel->id);
|
channel->id);
|
||||||
call_set_error(channel, buf, WARNING_LOG_LEVEL);
|
call_set_error(channel, buf, WARN_LOG_LEVEL);
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((chan_wstream(channel) != NULL && chan_wstream(channel)->closed)
|
||||||
|
|| (chan_rstream(channel) != NULL && chan_rstream(channel)->closed)) {
|
||||||
|
char buf[256];
|
||||||
|
snprintf(buf, sizeof(buf),
|
||||||
|
"ch %" PRIu64 ": stream closed unexpectedly. "
|
||||||
|
"closing channel",
|
||||||
|
channel->id);
|
||||||
|
call_set_error(channel, buf, WARN_LOG_LEVEL);
|
||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t count = rbuffer_size(rbuf);
|
size_t count = rbuffer_size(rbuf);
|
||||||
DLOG("parsing %u bytes of msgpack data from Stream(%p)", count, stream);
|
DLOG("ch %" PRIu64 ": parsing %u bytes from msgpack Stream: %p",
|
||||||
|
channel->id, count, stream);
|
||||||
|
|
||||||
// Feed the unpacker with data
|
// Feed the unpacker with data
|
||||||
msgpack_unpacker_reserve_buffer(channel->unpacker, count);
|
msgpack_unpacker_reserve_buffer(channel->unpacker, count);
|
||||||
@ -435,8 +455,8 @@ static void parse_msgpack(Channel *channel)
|
|||||||
// causes for this error(search for 'goto _failed')
|
// causes for this error(search for 'goto _failed')
|
||||||
//
|
//
|
||||||
// A not so uncommon cause for this might be deserializing objects with
|
// A not so uncommon cause for this might be deserializing objects with
|
||||||
// a high nesting level: msgpack will break when it's internal parse stack
|
// a high nesting level: msgpack will break when its internal parse stack
|
||||||
// size exceeds MSGPACK_EMBED_STACK_SIZE(defined as 32 by default)
|
// size exceeds MSGPACK_EMBED_STACK_SIZE (defined as 32 by default)
|
||||||
send_error(channel, 0, "Invalid msgpack payload. "
|
send_error(channel, 0, "Invalid msgpack payload. "
|
||||||
"This error can also happen when deserializing "
|
"This error can also happen when deserializing "
|
||||||
"an object with high level of nesting");
|
"an object with high level of nesting");
|
||||||
@ -534,6 +554,39 @@ static void on_request_event(void **argv)
|
|||||||
api_clear_error(&error);
|
api_clear_error(&error);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns the Stream that a Channel writes to.
|
||||||
|
static Stream *chan_wstream(Channel *chan)
|
||||||
|
{
|
||||||
|
switch (chan->type) {
|
||||||
|
case kChannelTypeSocket:
|
||||||
|
return &chan->data.stream;
|
||||||
|
case kChannelTypeProc:
|
||||||
|
return chan->data.proc->in;
|
||||||
|
case kChannelTypeStdio:
|
||||||
|
return &chan->data.std.out;
|
||||||
|
case kChannelTypeInternal:
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the Stream that a Channel reads from.
|
||||||
|
static Stream *chan_rstream(Channel *chan)
|
||||||
|
{
|
||||||
|
switch (chan->type) {
|
||||||
|
case kChannelTypeSocket:
|
||||||
|
return &chan->data.stream;
|
||||||
|
case kChannelTypeProc:
|
||||||
|
return chan->data.proc->out;
|
||||||
|
case kChannelTypeStdio:
|
||||||
|
return &chan->data.std.in;
|
||||||
|
case kChannelTypeInternal:
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static bool channel_write(Channel *channel, WBuffer *buffer)
|
static bool channel_write(Channel *channel, WBuffer *buffer)
|
||||||
{
|
{
|
||||||
bool success = false;
|
bool success = false;
|
||||||
@ -545,13 +598,9 @@ static bool channel_write(Channel *channel, WBuffer *buffer)
|
|||||||
|
|
||||||
switch (channel->type) {
|
switch (channel->type) {
|
||||||
case kChannelTypeSocket:
|
case kChannelTypeSocket:
|
||||||
success = wstream_write(&channel->data.stream, buffer);
|
|
||||||
break;
|
|
||||||
case kChannelTypeProc:
|
case kChannelTypeProc:
|
||||||
success = wstream_write(channel->data.proc->in, buffer);
|
|
||||||
break;
|
|
||||||
case kChannelTypeStdio:
|
case kChannelTypeStdio:
|
||||||
success = wstream_write(&channel->data.std.out, buffer);
|
success = wstream_write(chan_wstream(channel), buffer);
|
||||||
break;
|
break;
|
||||||
case kChannelTypeInternal:
|
case kChannelTypeInternal:
|
||||||
incref(channel);
|
incref(channel);
|
||||||
@ -565,8 +614,8 @@ static bool channel_write(Channel *channel, WBuffer *buffer)
|
|||||||
char buf[256];
|
char buf[256];
|
||||||
snprintf(buf,
|
snprintf(buf,
|
||||||
sizeof(buf),
|
sizeof(buf),
|
||||||
"Before returning from a RPC call, ch %" PRIu64 " was "
|
"ch %" PRIu64 ": stream write failed. "
|
||||||
"closed due to a failed write",
|
"RPC canceled; closing channel",
|
||||||
channel->id);
|
channel->id);
|
||||||
call_set_error(channel, buf, ERROR_LOG_LEVEL);
|
call_set_error(channel, buf, ERROR_LOG_LEVEL);
|
||||||
}
|
}
|
||||||
@ -817,6 +866,7 @@ static void call_set_error(Channel *channel, char *msg, int loglevel)
|
|||||||
ChannelCallFrame *frame = kv_A(channel->call_stack, i);
|
ChannelCallFrame *frame = kv_A(channel->call_stack, i);
|
||||||
frame->returned = true;
|
frame->returned = true;
|
||||||
frame->errored = true;
|
frame->errored = true;
|
||||||
|
api_free_object(frame->result);
|
||||||
frame->result = STRING_OBJ(cstr_to_string(msg));
|
frame->result = STRING_OBJ(cstr_to_string(msg));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -88,7 +88,12 @@ bool msgpack_rpc_to_object(const msgpack_object *const obj, Object *const arg)
|
|||||||
{
|
{
|
||||||
bool ret = true;
|
bool ret = true;
|
||||||
kvec_t(MPToAPIObjectStackItem) stack = KV_INITIAL_VALUE;
|
kvec_t(MPToAPIObjectStackItem) stack = KV_INITIAL_VALUE;
|
||||||
kv_push(stack, ((MPToAPIObjectStackItem) { obj, arg, false, 0 }));
|
kv_push(stack, ((MPToAPIObjectStackItem) {
|
||||||
|
.mobj = obj,
|
||||||
|
.aobj = arg,
|
||||||
|
.container = false,
|
||||||
|
.idx = 0,
|
||||||
|
}));
|
||||||
while (ret && kv_size(stack)) {
|
while (ret && kv_size(stack)) {
|
||||||
MPToAPIObjectStackItem cur = kv_last(stack);
|
MPToAPIObjectStackItem cur = kv_last(stack);
|
||||||
if (!cur.container) {
|
if (!cur.container) {
|
||||||
@ -361,7 +366,7 @@ typedef struct {
|
|||||||
size_t idx;
|
size_t idx;
|
||||||
} APIToMPObjectStackItem;
|
} APIToMPObjectStackItem;
|
||||||
|
|
||||||
/// Convert type used by Neovim API to msgpack
|
/// Convert type used by Nvim API to msgpack type.
|
||||||
///
|
///
|
||||||
/// @param[in] result Object to convert.
|
/// @param[in] result Object to convert.
|
||||||
/// @param[out] res Structure that defines where conversion results are saved.
|
/// @param[out] res Structure that defines where conversion results are saved.
|
||||||
|
@ -13,6 +13,7 @@
|
|||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include "nvim/log.h"
|
||||||
#include "nvim/vim.h"
|
#include "nvim/vim.h"
|
||||||
#include "nvim/ascii.h"
|
#include "nvim/ascii.h"
|
||||||
#include "nvim/normal.h"
|
#include "nvim/normal.h"
|
||||||
@ -344,8 +345,6 @@ static const struct nv_cmd {
|
|||||||
{ K_F8, farsi_f8, 0, 0 },
|
{ K_F8, farsi_f8, 0, 0 },
|
||||||
{ K_F9, farsi_f9, 0, 0 },
|
{ K_F9, farsi_f9, 0, 0 },
|
||||||
{ K_EVENT, nv_event, NV_KEEPREG, 0 },
|
{ K_EVENT, nv_event, NV_KEEPREG, 0 },
|
||||||
{ K_FOCUSGAINED, nv_focusgained, NV_KEEPREG, 0 },
|
|
||||||
{ K_FOCUSLOST, nv_focuslost, NV_KEEPREG, 0 },
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Number of commands in nv_cmds[]. */
|
/* Number of commands in nv_cmds[]. */
|
||||||
@ -1943,8 +1942,11 @@ void do_pending_operator(cmdarg_T *cap, int old_col, bool gui_yank)
|
|||||||
* the lines. */
|
* the lines. */
|
||||||
auto_format(false, true);
|
auto_format(false, true);
|
||||||
|
|
||||||
if (restart_edit == 0)
|
if (restart_edit == 0) {
|
||||||
restart_edit = restart_edit_save;
|
restart_edit = restart_edit_save;
|
||||||
|
} else {
|
||||||
|
cap->retval |= CA_COMMAND_BUSY;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -7957,18 +7959,7 @@ static void nv_event(cmdarg_T *cap)
|
|||||||
may_garbage_collect = false;
|
may_garbage_collect = false;
|
||||||
multiqueue_process_events(main_loop.events);
|
multiqueue_process_events(main_loop.events);
|
||||||
cap->retval |= CA_COMMAND_BUSY; // don't call edit() now
|
cap->retval |= CA_COMMAND_BUSY; // don't call edit() now
|
||||||
}
|
finish_op = false;
|
||||||
|
|
||||||
/// Trigger FocusGained event.
|
|
||||||
static void nv_focusgained(cmdarg_T *cap)
|
|
||||||
{
|
|
||||||
apply_autocmds(EVENT_FOCUSGAINED, NULL, NULL, false, curbuf);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Trigger FocusLost event.
|
|
||||||
static void nv_focuslost(cmdarg_T *cap)
|
|
||||||
{
|
|
||||||
apply_autocmds(EVENT_FOCUSLOST, NULL, NULL, false, curbuf);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -55,12 +55,11 @@ static yankreg_T y_regs[NUM_REGISTERS];
|
|||||||
|
|
||||||
static yankreg_T *y_previous = NULL; /* ptr to last written yankreg */
|
static yankreg_T *y_previous = NULL; /* ptr to last written yankreg */
|
||||||
|
|
||||||
static bool clipboard_didwarn_unnamed = false;
|
|
||||||
|
|
||||||
// for behavior between start_batch_changes() and end_batch_changes())
|
// for behavior between start_batch_changes() and end_batch_changes())
|
||||||
static bool clipboard_delay_update = false; // delay clipboard update
|
|
||||||
static int batch_change_count = 0; // inside a script
|
static int batch_change_count = 0; // inside a script
|
||||||
|
static bool clipboard_delay_update = false; // delay clipboard update
|
||||||
static bool clipboard_needs_update = false; // clipboard was updated
|
static bool clipboard_needs_update = false; // clipboard was updated
|
||||||
|
static bool clipboard_didwarn = false;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* structure used by block_prep, op_delete and op_yank for blockwise operators
|
* structure used by block_prep, op_delete and op_yank for blockwise operators
|
||||||
@ -2061,7 +2060,7 @@ void op_insert(oparg_T *oap, long count1)
|
|||||||
}
|
}
|
||||||
|
|
||||||
t1 = oap->start;
|
t1 = oap->start;
|
||||||
edit(NUL, false, (linenr_T)count1);
|
(void)edit(NUL, false, (linenr_T)count1);
|
||||||
|
|
||||||
// When a tab was inserted, and the characters in front of the tab
|
// When a tab was inserted, and the characters in front of the tab
|
||||||
// have been converted to a tab as well, the column of the cursor
|
// have been converted to a tab as well, the column of the cursor
|
||||||
@ -5524,7 +5523,7 @@ int get_default_register_name(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Determine if register `*name` should be used as a clipboard.
|
/// Determine if register `*name` should be used as a clipboard.
|
||||||
/// In an unnammed operation, `*name` is `NUL` and will be adjusted to `'*'/'+'` if
|
/// In an unnamed operation, `*name` is `NUL` and will be adjusted to */+ if
|
||||||
/// `clipboard=unnamed[plus]` is set.
|
/// `clipboard=unnamed[plus]` is set.
|
||||||
///
|
///
|
||||||
/// @param name The name of register, or `NUL` if unnamed.
|
/// @param name The name of register, or `NUL` if unnamed.
|
||||||
@ -5535,33 +5534,41 @@ int get_default_register_name(void)
|
|||||||
/// if the register isn't a clipboard or provider isn't available.
|
/// if the register isn't a clipboard or provider isn't available.
|
||||||
static yankreg_T *adjust_clipboard_name(int *name, bool quiet, bool writing)
|
static yankreg_T *adjust_clipboard_name(int *name, bool quiet, bool writing)
|
||||||
{
|
{
|
||||||
if (*name == '*' || *name == '+') {
|
#define MSG_NO_CLIP "clipboard: No provider. " \
|
||||||
if(!eval_has_provider("clipboard")) {
|
"Try \":CheckHealth\" or \":h clipboard\"."
|
||||||
if (!quiet) {
|
|
||||||
EMSG("clipboard: No provider. Try \":CheckHealth\" or "
|
yankreg_T *target = NULL;
|
||||||
"\":h clipboard\".");
|
bool explicit_cb_reg = (*name == '*' || *name == '+');
|
||||||
}
|
bool implicit_cb_reg = (*name == NUL) && (cb_flags & CB_UNNAMEDMASK);
|
||||||
return NULL;
|
if (!explicit_cb_reg && !implicit_cb_reg) {
|
||||||
}
|
goto end;
|
||||||
return &y_regs[*name == '*' ? STAR_REGISTER : PLUS_REGISTER];
|
}
|
||||||
} else if ((*name == NUL) && (cb_flags & CB_UNNAMEDMASK)) {
|
|
||||||
if(!eval_has_provider("clipboard")) {
|
if (!eval_has_provider("clipboard")) {
|
||||||
if (!quiet && !clipboard_didwarn_unnamed) {
|
if (batch_change_count == 1 && !quiet
|
||||||
msg((char_u *)"clipboard: No provider. Try \":CheckHealth\" or "
|
&& (!clipboard_didwarn || (explicit_cb_reg && !redirecting()))) {
|
||||||
"\":h clipboard\".");
|
clipboard_didwarn = true;
|
||||||
clipboard_didwarn_unnamed = true;
|
// Do NOT error (emsg()) here--if it interrupts :redir we get into
|
||||||
}
|
// a weird state, stuck in "redirect mode".
|
||||||
return NULL;
|
msg((char_u *)MSG_NO_CLIP);
|
||||||
}
|
}
|
||||||
|
// ... else, be silent (don't flood during :while, :redir, etc.).
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (explicit_cb_reg) {
|
||||||
|
target = &y_regs[*name == '*' ? STAR_REGISTER : PLUS_REGISTER];
|
||||||
|
goto end;
|
||||||
|
} else { // unnamed register: "implicit" clipboard
|
||||||
if (writing && clipboard_delay_update) {
|
if (writing && clipboard_delay_update) {
|
||||||
|
// For "set" (copy), defer the clipboard call.
|
||||||
clipboard_needs_update = true;
|
clipboard_needs_update = true;
|
||||||
return NULL;
|
goto end;
|
||||||
} else if (!writing && clipboard_needs_update) {
|
} else if (!writing && clipboard_needs_update) {
|
||||||
// use the internal value
|
// For "get" (paste), use the internal value.
|
||||||
return NULL;
|
goto end;
|
||||||
}
|
}
|
||||||
|
|
||||||
yankreg_T *target;
|
|
||||||
if (cb_flags & CB_UNNAMEDPLUS) {
|
if (cb_flags & CB_UNNAMEDPLUS) {
|
||||||
*name = (cb_flags & CB_UNNAMED && writing) ? '"': '+';
|
*name = (cb_flags & CB_UNNAMED && writing) ? '"': '+';
|
||||||
target = &y_regs[PLUS_REGISTER];
|
target = &y_regs[PLUS_REGISTER];
|
||||||
@ -5569,10 +5576,11 @@ static yankreg_T *adjust_clipboard_name(int *name, bool quiet, bool writing)
|
|||||||
*name = '*';
|
*name = '*';
|
||||||
target = &y_regs[STAR_REGISTER];
|
target = &y_regs[STAR_REGISTER];
|
||||||
}
|
}
|
||||||
return target; // unnamed register
|
goto end;
|
||||||
}
|
}
|
||||||
// don't do anything for other register names
|
|
||||||
return NULL;
|
end:
|
||||||
|
return target;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool get_clipboard(int name, yankreg_T **target, bool quiet)
|
static bool get_clipboard(int name, yankreg_T **target, bool quiet)
|
||||||
@ -5740,17 +5748,16 @@ static void set_clipboard(int name, yankreg_T *reg)
|
|||||||
(void)eval_call_provider("clipboard", "set", args);
|
(void)eval_call_provider("clipboard", "set", args);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Avoid clipboard (slow) during batch operations (i.e., a script).
|
/// Avoid slow things (clipboard) during batch operations (while/for-loops).
|
||||||
void start_batch_changes(void)
|
void start_batch_changes(void)
|
||||||
{
|
{
|
||||||
if (++batch_change_count > 1) {
|
if (++batch_change_count > 1) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
clipboard_delay_update = true;
|
clipboard_delay_update = true;
|
||||||
clipboard_needs_update = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Update the clipboard after batch changes finished.
|
/// Counterpart to start_batch_changes().
|
||||||
void end_batch_changes(void)
|
void end_batch_changes(void)
|
||||||
{
|
{
|
||||||
if (--batch_change_count > 0) {
|
if (--batch_change_count > 0) {
|
||||||
@ -5759,11 +5766,37 @@ void end_batch_changes(void)
|
|||||||
}
|
}
|
||||||
clipboard_delay_update = false;
|
clipboard_delay_update = false;
|
||||||
if (clipboard_needs_update) {
|
if (clipboard_needs_update) {
|
||||||
set_clipboard(NUL, y_previous);
|
// must be before, as set_clipboard will invoke
|
||||||
|
// start/end_batch_changes recursively
|
||||||
clipboard_needs_update = false;
|
clipboard_needs_update = false;
|
||||||
|
// unnamed ("implicit" clipboard)
|
||||||
|
set_clipboard(NUL, y_previous);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int save_batch_count(void)
|
||||||
|
{
|
||||||
|
int save_count = batch_change_count;
|
||||||
|
batch_change_count = 0;
|
||||||
|
clipboard_delay_update = false;
|
||||||
|
if (clipboard_needs_update) {
|
||||||
|
clipboard_needs_update = false;
|
||||||
|
// unnamed ("implicit" clipboard)
|
||||||
|
set_clipboard(NUL, y_previous);
|
||||||
|
}
|
||||||
|
return save_count;
|
||||||
|
}
|
||||||
|
|
||||||
|
void restore_batch_count(int save_count)
|
||||||
|
{
|
||||||
|
assert(batch_change_count == 0);
|
||||||
|
batch_change_count = save_count;
|
||||||
|
if (batch_change_count > 0) {
|
||||||
|
clipboard_delay_update = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/// Check whether register is empty
|
/// Check whether register is empty
|
||||||
static inline bool reg_empty(const yankreg_T *const reg)
|
static inline bool reg_empty(const yankreg_T *const reg)
|
||||||
FUNC_ATTR_PURE
|
FUNC_ATTR_PURE
|
||||||
|
@ -1749,7 +1749,7 @@ do_set (
|
|||||||
|
|
||||||
if (flags & P_FLAGLIST) {
|
if (flags & P_FLAGLIST) {
|
||||||
// Remove flags that appear twice.
|
// Remove flags that appear twice.
|
||||||
for (s = newval; *s; s++) {
|
for (s = newval; *s;) {
|
||||||
// if options have P_FLAGLIST and P_ONECOMMA such as
|
// if options have P_FLAGLIST and P_ONECOMMA such as
|
||||||
// 'whichwrap'
|
// 'whichwrap'
|
||||||
if (flags & P_ONECOMMA) {
|
if (flags & P_ONECOMMA) {
|
||||||
@ -1757,15 +1757,16 @@ do_set (
|
|||||||
&& vim_strchr(s + 2, *s) != NULL) {
|
&& vim_strchr(s + 2, *s) != NULL) {
|
||||||
// Remove the duplicated value and the next comma.
|
// Remove the duplicated value and the next comma.
|
||||||
STRMOVE(s, s + 2);
|
STRMOVE(s, s + 2);
|
||||||
s -= 2;
|
continue;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if ((!(flags & P_COMMA) || *s != ',')
|
if ((!(flags & P_COMMA) || *s != ',')
|
||||||
&& vim_strchr(s + 1, *s) != NULL) {
|
&& vim_strchr(s + 1, *s) != NULL) {
|
||||||
STRMOVE(s, s + 1);
|
STRMOVE(s, s + 1);
|
||||||
s--;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
s++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2996,9 +2997,10 @@ did_set_string_option (
|
|||||||
if (s[-1] == 'k' || s[-1] == 's') {
|
if (s[-1] == 'k' || s[-1] == 's') {
|
||||||
/* skip optional filename after 'k' and 's' */
|
/* skip optional filename after 'k' and 's' */
|
||||||
while (*s && *s != ',' && *s != ' ') {
|
while (*s && *s != ',' && *s != ' ') {
|
||||||
if (*s == '\\')
|
if (*s == '\\' && s[1] != NUL) {
|
||||||
++s;
|
s++;
|
||||||
++s;
|
}
|
||||||
|
s++;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (errbuf != NULL) {
|
if (errbuf != NULL) {
|
||||||
|
@ -2498,7 +2498,7 @@ return {
|
|||||||
no_mkrc=true,
|
no_mkrc=true,
|
||||||
vi_def=true,
|
vi_def=true,
|
||||||
varname='p_titleold',
|
varname='p_titleold',
|
||||||
defaults={if_true={vi=N_("Thanks for flying Vim")}}
|
defaults={if_true={vi=N_("")}}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
full_name='titlestring',
|
full_name='titlestring',
|
||||||
|
@ -1690,6 +1690,9 @@ int vim_FullName(const char *fname, char *buf, size_t len, bool force)
|
|||||||
|
|
||||||
if (strlen(fname) > (len - 1)) {
|
if (strlen(fname) > (len - 1)) {
|
||||||
xstrlcpy(buf, fname, len); // truncate
|
xstrlcpy(buf, fname, len); // truncate
|
||||||
|
#ifdef WIN32
|
||||||
|
slash_adjust(buf);
|
||||||
|
#endif
|
||||||
return FAIL;
|
return FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1702,6 +1705,9 @@ int vim_FullName(const char *fname, char *buf, size_t len, bool force)
|
|||||||
if (rv == FAIL) {
|
if (rv == FAIL) {
|
||||||
xstrlcpy(buf, fname, len); // something failed; use the filename
|
xstrlcpy(buf, fname, len); // something failed; use the filename
|
||||||
}
|
}
|
||||||
|
#ifdef WIN32
|
||||||
|
slash_adjust(buf);
|
||||||
|
#endif
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2196,11 +2202,11 @@ static int path_get_absolute_path(const char_u *fname, char_u *buf,
|
|||||||
|
|
||||||
// expand it if forced or not an absolute path
|
// expand it if forced or not an absolute path
|
||||||
if (force || !path_is_absolute_path(fname)) {
|
if (force || !path_is_absolute_path(fname)) {
|
||||||
if ((p = vim_strrchr(fname, '/')) != NULL) {
|
if ((p = vim_strrchr(fname, PATHSEP)) != NULL) {
|
||||||
// relative to root
|
// relative to root
|
||||||
if (p == fname) {
|
if (p == fname) {
|
||||||
// only one path component
|
// only one path component
|
||||||
relative_directory[0] = '/';
|
relative_directory[0] = PATHSEP;
|
||||||
relative_directory[1] = NUL;
|
relative_directory[1] = NUL;
|
||||||
} else {
|
} else {
|
||||||
assert(p >= fname);
|
assert(p >= fname);
|
||||||
|
@ -3316,6 +3316,47 @@ bt_regexec_nl (
|
|||||||
return (int)r;
|
return (int)r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Wrapper around strchr which accounts for case-insensitive searches and
|
||||||
|
/// non-ASCII characters.
|
||||||
|
///
|
||||||
|
/// This function is used a lot for simple searches, keep it fast!
|
||||||
|
///
|
||||||
|
/// @param s string to search
|
||||||
|
/// @param c character to find in @a s
|
||||||
|
///
|
||||||
|
/// @return NULL if no match, otherwise pointer to the position in @a s
|
||||||
|
static inline char_u *cstrchr(const char_u *const s, const int c)
|
||||||
|
FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ALL
|
||||||
|
FUNC_ATTR_ALWAYS_INLINE
|
||||||
|
{
|
||||||
|
if (!rex.reg_ic) {
|
||||||
|
return vim_strchr(s, c);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Use folded case for UTF-8, slow! For ASCII use libc strpbrk which is
|
||||||
|
// expected to be highly optimized.
|
||||||
|
if (c > 0x80) {
|
||||||
|
const int folded_c = utf_fold(c);
|
||||||
|
for (const char_u *p = s; *p != NUL; p += utfc_ptr2len(p)) {
|
||||||
|
if (utf_fold(utf_ptr2char(p)) == folded_c) {
|
||||||
|
return (char_u *)p;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
int cc;
|
||||||
|
if (ASCII_ISUPPER(c)) {
|
||||||
|
cc = TOLOWER_ASC(c);
|
||||||
|
} else if (ASCII_ISLOWER(c)) {
|
||||||
|
cc = TOUPPER_ASC(c);
|
||||||
|
} else {
|
||||||
|
return vim_strchr(s, c);
|
||||||
|
}
|
||||||
|
|
||||||
|
char tofind[] = { (char)c, (char)cc, NUL };
|
||||||
|
return (char_u *)strpbrk((const char *)s, tofind);
|
||||||
|
}
|
||||||
|
|
||||||
/// Matches a regexp against multiple lines.
|
/// Matches a regexp against multiple lines.
|
||||||
/// "rmp->regprog" is a compiled regexp as returned by vim_regcomp().
|
/// "rmp->regprog" is a compiled regexp as returned by vim_regcomp().
|
||||||
@ -6320,42 +6361,6 @@ static int cstrncmp(char_u *s1, char_u *s2, int *n)
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* cstrchr: This function is used a lot for simple searches, keep it fast!
|
|
||||||
*/
|
|
||||||
static inline char_u *cstrchr(const char_u *const s, const int c)
|
|
||||||
FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ALL
|
|
||||||
FUNC_ATTR_ALWAYS_INLINE
|
|
||||||
{
|
|
||||||
if (!rex.reg_ic) {
|
|
||||||
return vim_strchr(s, c);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Use folded case for UTF-8, slow! For ASCII use libc strpbrk which is
|
|
||||||
// expected to be highly optimized.
|
|
||||||
if (c > 0x80) {
|
|
||||||
const int folded_c = utf_fold(c);
|
|
||||||
for (const char_u *p = s; *p != NUL; p += utfc_ptr2len(p)) {
|
|
||||||
if (utf_fold(utf_ptr2char(p)) == folded_c) {
|
|
||||||
return (char_u *)p;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
int cc;
|
|
||||||
if (ASCII_ISUPPER(c)) {
|
|
||||||
cc = TOLOWER_ASC(c);
|
|
||||||
} else if (ASCII_ISLOWER(c)) {
|
|
||||||
cc = TOUPPER_ASC(c);
|
|
||||||
} else {
|
|
||||||
return vim_strchr(s, c);
|
|
||||||
}
|
|
||||||
|
|
||||||
char tofind[] = { (char)c, (char)cc, NUL };
|
|
||||||
return (char_u *)strpbrk((const char *)s, tofind);
|
|
||||||
}
|
|
||||||
|
|
||||||
/***************************************************************
|
/***************************************************************
|
||||||
* regsub stuff *
|
* regsub stuff *
|
||||||
***************************************************************/
|
***************************************************************/
|
||||||
|
@ -2201,16 +2201,17 @@ win_line (
|
|||||||
int change_end = -1; /* last col of changed area */
|
int change_end = -1; /* last col of changed area */
|
||||||
colnr_T trailcol = MAXCOL; /* start of trailing spaces */
|
colnr_T trailcol = MAXCOL; /* start of trailing spaces */
|
||||||
int need_showbreak = false; // overlong line, skip first x chars
|
int need_showbreak = false; // overlong line, skip first x chars
|
||||||
int line_attr = 0; /* attribute for the whole line */
|
int line_attr = 0; // attribute for the whole line
|
||||||
matchitem_T *cur; /* points to the match list */
|
int line_attr_low_priority = 0; // current line, lowest priority
|
||||||
match_T *shl; /* points to search_hl or a match */
|
matchitem_T *cur; // points to the match list
|
||||||
int shl_flag; /* flag to indicate whether search_hl
|
match_T *shl; // points to search_hl or a match
|
||||||
has been processed or not */
|
int shl_flag; // flag to indicate whether search_hl
|
||||||
int prevcol_hl_flag; /* flag to indicate whether prevcol
|
// has been processed or not
|
||||||
equals startcol of search_hl or one
|
int prevcol_hl_flag; // flag to indicate whether prevcol
|
||||||
of the matches */
|
// equals startcol of search_hl or one
|
||||||
int prev_c = 0; /* previous Arabic character */
|
// of the matches
|
||||||
int prev_c1 = 0; /* first composing char for prev_c */
|
int prev_c = 0; // previous Arabic character
|
||||||
|
int prev_c1 = 0; // first composing char for prev_c
|
||||||
int did_line_attr = 0;
|
int did_line_attr = 0;
|
||||||
|
|
||||||
bool search_attr_from_match = false; // if search_attr is from :match
|
bool search_attr_from_match = false; // if search_attr is from :match
|
||||||
@ -2427,10 +2428,17 @@ win_line (
|
|||||||
filler_lines = wp->w_topfill;
|
filler_lines = wp->w_topfill;
|
||||||
filler_todo = filler_lines;
|
filler_todo = filler_lines;
|
||||||
|
|
||||||
/* If this line has a sign with line highlighting set line_attr. */
|
// 'cursorline' highlighting for the current window. Not when Visual mode is
|
||||||
|
// active, because it's not clear what is selected then.
|
||||||
|
if (wp->w_p_cul && lnum == wp->w_cursor.lnum
|
||||||
|
&& !(wp == curwin && VIsual_active)) {
|
||||||
|
line_attr_low_priority = win_hl_attr(wp, HLF_CUL);
|
||||||
|
}
|
||||||
|
|
||||||
v = buf_getsigntype(wp->w_buffer, lnum, SIGN_LINEHL);
|
v = buf_getsigntype(wp->w_buffer, lnum, SIGN_LINEHL);
|
||||||
if (v != 0)
|
if (v != 0) {
|
||||||
line_attr = sign_get_attr((int)v, TRUE);
|
line_attr = sign_get_attr((int)v, true);
|
||||||
|
}
|
||||||
|
|
||||||
// Highlight the current line in the quickfix window.
|
// Highlight the current line in the quickfix window.
|
||||||
if (bt_quickfix(wp->w_buffer) && qf_current_entry(wp) == lnum) {
|
if (bt_quickfix(wp->w_buffer) && qf_current_entry(wp) == lnum) {
|
||||||
@ -2441,7 +2449,7 @@ win_line (
|
|||||||
line_attr = hl_combine_attr(wp->w_hl_attr_normal, line_attr);
|
line_attr = hl_combine_attr(wp->w_hl_attr_normal, line_attr);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (line_attr != 0) {
|
if (line_attr_low_priority || line_attr) {
|
||||||
area_highlighting = true;
|
area_highlighting = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2663,20 +2671,6 @@ win_line (
|
|||||||
cur = cur->next;
|
cur = cur->next;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Cursor line highlighting for 'cursorline' in the current window. Not
|
|
||||||
* when Visual mode is active, because it's not clear what is selected
|
|
||||||
* then. */
|
|
||||||
if (wp->w_p_cul && lnum == wp->w_cursor.lnum
|
|
||||||
&& !(wp == curwin && VIsual_active)) {
|
|
||||||
if (line_attr != 0 && !(State & INSERT) && bt_quickfix(wp->w_buffer)
|
|
||||||
&& qf_current_entry(wp) == lnum) {
|
|
||||||
line_attr = hl_combine_attr(win_hl_attr(wp, HLF_CUL), line_attr);
|
|
||||||
} else {
|
|
||||||
line_attr = win_hl_attr(wp, HLF_CUL);
|
|
||||||
}
|
|
||||||
area_highlighting = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
off = (unsigned)(current_ScreenLine - ScreenLines);
|
off = (unsigned)(current_ScreenLine - ScreenLines);
|
||||||
col = 0;
|
col = 0;
|
||||||
if (wp->w_p_rl) {
|
if (wp->w_p_rl) {
|
||||||
@ -3594,15 +3588,15 @@ win_line (
|
|||||||
&& lcs_eol_one > 0) {
|
&& lcs_eol_one > 0) {
|
||||||
// Display a '$' after the line or highlight an extra
|
// Display a '$' after the line or highlight an extra
|
||||||
// character if the line break is included.
|
// character if the line break is included.
|
||||||
// For a diff line the highlighting continues after the
|
// For a diff line the highlighting continues after the "$".
|
||||||
// "$".
|
if (diff_hlf == (hlf_T)0
|
||||||
if (diff_hlf == (hlf_T)0 && line_attr == 0) {
|
&& line_attr == 0
|
||||||
/* In virtualedit, visual selections may extend
|
&& line_attr_low_priority == 0) {
|
||||||
* beyond end of line. */
|
// In virtualedit, visual selections may extend beyond end of line.
|
||||||
if (area_highlighting && virtual_active()
|
if (area_highlighting && virtual_active()
|
||||||
&& tocol != MAXCOL && vcol < tocol)
|
&& tocol != MAXCOL && vcol < tocol) {
|
||||||
n_extra = 0;
|
n_extra = 0;
|
||||||
else {
|
} else {
|
||||||
p_extra = at_end_str;
|
p_extra = at_end_str;
|
||||||
n_extra = 1;
|
n_extra = 1;
|
||||||
c_extra = NUL;
|
c_extra = NUL;
|
||||||
@ -3661,7 +3655,7 @@ win_line (
|
|||||||
(col < wp->w_width))) {
|
(col < wp->w_width))) {
|
||||||
c = ' ';
|
c = ' ';
|
||||||
ptr--; // put it back at the NUL
|
ptr--; // put it back at the NUL
|
||||||
} else if ((diff_hlf != (hlf_T)0 || line_attr != 0)
|
} else if ((diff_hlf != (hlf_T)0 || line_attr_low_priority || line_attr)
|
||||||
&& (wp->w_p_rl
|
&& (wp->w_p_rl
|
||||||
? (col >= 0)
|
? (col >= 0)
|
||||||
: (col - boguscols < wp->w_width))) {
|
: (col - boguscols < wp->w_width))) {
|
||||||
@ -3673,7 +3667,8 @@ win_line (
|
|||||||
did_line_attr++;
|
did_line_attr++;
|
||||||
|
|
||||||
// don't do search HL for the rest of the line
|
// don't do search HL for the rest of the line
|
||||||
if (line_attr != 0 && char_attr == search_attr && col > 0) {
|
if ((line_attr_low_priority || line_attr)
|
||||||
|
&& char_attr == search_attr && col > 0) {
|
||||||
char_attr = line_attr;
|
char_attr = line_attr;
|
||||||
}
|
}
|
||||||
if (diff_hlf == HLF_TXD) {
|
if (diff_hlf == HLF_TXD) {
|
||||||
@ -4035,13 +4030,16 @@ win_line (
|
|||||||
if (wp->w_p_cuc && VCOL_HLC == (long)wp->w_virtcol
|
if (wp->w_p_cuc && VCOL_HLC == (long)wp->w_virtcol
|
||||||
&& lnum != wp->w_cursor.lnum) {
|
&& lnum != wp->w_cursor.lnum) {
|
||||||
vcol_save_attr = char_attr;
|
vcol_save_attr = char_attr;
|
||||||
char_attr = hl_combine_attr(char_attr, win_hl_attr(wp, HLF_CUC));
|
char_attr = hl_combine_attr(win_hl_attr(wp, HLF_CUC), char_attr);
|
||||||
} else if (draw_color_col && VCOL_HLC == *color_cols) {
|
} else if (draw_color_col && VCOL_HLC == *color_cols) {
|
||||||
vcol_save_attr = char_attr;
|
vcol_save_attr = char_attr;
|
||||||
char_attr = hl_combine_attr(char_attr, win_hl_attr(wp, HLF_MC));
|
char_attr = hl_combine_attr(win_hl_attr(wp, HLF_MC), char_attr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Apply `line_attr_low_priority` now, so that everthing can override it.
|
||||||
|
char_attr = hl_combine_attr(line_attr_low_priority, char_attr);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Store character to be displayed.
|
* Store character to be displayed.
|
||||||
* Skip characters that are left of the screen for 'nowrap'.
|
* Skip characters that are left of the screen for 'nowrap'.
|
||||||
@ -5847,7 +5845,7 @@ static void screen_start_highlight(int attr)
|
|||||||
ui_start_highlight(attr);
|
ui_start_highlight(attr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void screen_stop_highlight(void)
|
static void screen_stop_highlight(void)
|
||||||
{
|
{
|
||||||
ui_stop_highlight();
|
ui_stop_highlight();
|
||||||
screen_attr = 0;
|
screen_attr = 0;
|
||||||
|
@ -3557,11 +3557,15 @@ extend:
|
|||||||
--start_lnum;
|
--start_lnum;
|
||||||
|
|
||||||
if (VIsual_active) {
|
if (VIsual_active) {
|
||||||
/* Problem: when doing "Vipipip" nothing happens in a single white
|
// Problem: when doing "Vipipip" nothing happens in a single white
|
||||||
* line, we get stuck there. Trap this here. */
|
// line, we get stuck there. Trap this here.
|
||||||
if (VIsual_mode == 'V' && start_lnum == curwin->w_cursor.lnum)
|
if (VIsual_mode == 'V' && start_lnum == curwin->w_cursor.lnum) {
|
||||||
goto extend;
|
goto extend;
|
||||||
VIsual.lnum = start_lnum;
|
}
|
||||||
|
if (VIsual.lnum != start_lnum) {
|
||||||
|
VIsual.lnum = start_lnum;
|
||||||
|
VIsual.col = 0;
|
||||||
|
}
|
||||||
VIsual_mode = 'V';
|
VIsual_mode = 'V';
|
||||||
redraw_curbuf_later(INVERTED); /* update the inversion */
|
redraw_curbuf_later(INVERTED); /* update the inversion */
|
||||||
showmode();
|
showmode();
|
||||||
|
@ -26,10 +26,11 @@ void state_enter(VimState *s)
|
|||||||
int check_result = s->check ? s->check(s) : 1;
|
int check_result = s->check ? s->check(s) : 1;
|
||||||
|
|
||||||
if (!check_result) {
|
if (!check_result) {
|
||||||
break;
|
break; // Terminate this state.
|
||||||
} else if (check_result == -1) {
|
} else if (check_result == -1) {
|
||||||
continue;
|
continue; // check() again.
|
||||||
}
|
}
|
||||||
|
// Execute this state.
|
||||||
|
|
||||||
int key;
|
int key;
|
||||||
|
|
||||||
@ -48,11 +49,13 @@ getkey:
|
|||||||
ui_flush();
|
ui_flush();
|
||||||
// Call `os_inchar` directly to block for events or user input without
|
// Call `os_inchar` directly to block for events or user input without
|
||||||
// consuming anything from `input_buffer`(os/input.c) or calling the
|
// consuming anything from `input_buffer`(os/input.c) or calling the
|
||||||
// mapping engine. If an event was put into the queue, we send K_EVENT
|
// mapping engine.
|
||||||
// directly.
|
|
||||||
(void)os_inchar(NULL, 0, -1, 0);
|
(void)os_inchar(NULL, 0, -1, 0);
|
||||||
input_disable_events();
|
input_disable_events();
|
||||||
key = !multiqueue_empty(main_loop.events) ? K_EVENT : safe_vgetc();
|
// If an event was put into the queue, we send K_EVENT directly.
|
||||||
|
key = !multiqueue_empty(main_loop.events)
|
||||||
|
? K_EVENT
|
||||||
|
: safe_vgetc();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (key == K_EVENT) {
|
if (key == K_EVENT) {
|
||||||
|
@ -42,6 +42,7 @@
|
|||||||
#include "nvim/ui.h"
|
#include "nvim/ui.h"
|
||||||
#include "nvim/os/os.h"
|
#include "nvim/os/os.h"
|
||||||
#include "nvim/os/time.h"
|
#include "nvim/os/time.h"
|
||||||
|
#include "nvim/api/private/helpers.h"
|
||||||
|
|
||||||
static bool did_syntax_onoff = false;
|
static bool did_syntax_onoff = false;
|
||||||
|
|
||||||
@ -81,7 +82,10 @@ struct hl_group {
|
|||||||
// highlight groups for 'highlight' option
|
// highlight groups for 'highlight' option
|
||||||
static garray_T highlight_ga = GA_EMPTY_INIT_VALUE;
|
static garray_T highlight_ga = GA_EMPTY_INIT_VALUE;
|
||||||
|
|
||||||
#define HL_TABLE() ((struct hl_group *)((highlight_ga.ga_data)))
|
static inline struct hl_group * HL_TABLE(void)
|
||||||
|
{
|
||||||
|
return ((struct hl_group *)((highlight_ga.ga_data)));
|
||||||
|
}
|
||||||
|
|
||||||
#define MAX_HL_ID 20000 /* maximum value for a highlight ID. */
|
#define MAX_HL_ID 20000 /* maximum value for a highlight ID. */
|
||||||
|
|
||||||
@ -100,10 +104,8 @@ static int include_none = 0; /* when 1 include "nvim/None" */
|
|||||||
static int include_default = 0; /* when 1 include "nvim/default" */
|
static int include_default = 0; /* when 1 include "nvim/default" */
|
||||||
static int include_link = 0; /* when 2 include "nvim/link" and "clear" */
|
static int include_link = 0; /* when 2 include "nvim/link" and "clear" */
|
||||||
|
|
||||||
/*
|
/// The "term", "cterm" and "gui" arguments can be any combination of the
|
||||||
* The "term", "cterm" and "gui" arguments can be any combination of the
|
/// following names, separated by commas (but no spaces!).
|
||||||
* following names, separated by commas (but no spaces!).
|
|
||||||
*/
|
|
||||||
static char *(hl_name_table[]) =
|
static char *(hl_name_table[]) =
|
||||||
{"bold", "standout", "underline", "undercurl",
|
{"bold", "standout", "underline", "undercurl",
|
||||||
"italic", "reverse", "inverse", "NONE"};
|
"italic", "reverse", "inverse", "NONE"};
|
||||||
@ -1775,8 +1777,9 @@ syn_current_attr (
|
|||||||
cur_si->si_trans_id = CUR_STATE(
|
cur_si->si_trans_id = CUR_STATE(
|
||||||
current_state.ga_len - 2).si_trans_id;
|
current_state.ga_len - 2).si_trans_id;
|
||||||
}
|
}
|
||||||
} else
|
} else {
|
||||||
cur_si->si_attr = syn_id2attr(syn_id);
|
cur_si->si_attr = syn_id2attr(syn_id);
|
||||||
|
}
|
||||||
cur_si->si_cont_list = NULL;
|
cur_si->si_cont_list = NULL;
|
||||||
cur_si->si_next_list = next_list;
|
cur_si->si_next_list = next_list;
|
||||||
check_keepend();
|
check_keepend();
|
||||||
@ -5252,12 +5255,10 @@ get_id_list (
|
|||||||
/*
|
/*
|
||||||
* Handle full group name.
|
* Handle full group name.
|
||||||
*/
|
*/
|
||||||
if (vim_strpbrk(name + 1, (char_u *)"\\.*^$~[") == NULL)
|
if (vim_strpbrk(name + 1, (char_u *)"\\.*^$~[") == NULL) {
|
||||||
id = syn_check_group(name + 1, (int)(end - p));
|
id = syn_check_group(name + 1, (int)(end - p));
|
||||||
else {
|
} else {
|
||||||
/*
|
// Handle match of regexp with group names.
|
||||||
* Handle match of regexp with group names.
|
|
||||||
*/
|
|
||||||
*name = '^';
|
*name = '^';
|
||||||
STRCAT(name, "$");
|
STRCAT(name, "$");
|
||||||
regmatch.regprog = vim_regcomp(name, RE_MAGIC);
|
regmatch.regprog = vim_regcomp(name, RE_MAGIC);
|
||||||
@ -5567,8 +5568,10 @@ bool syntax_present(win_T *win)
|
|||||||
|
|
||||||
|
|
||||||
static enum {
|
static enum {
|
||||||
EXP_SUBCMD, /* expand ":syn" sub-commands */
|
EXP_SUBCMD, // expand ":syn" sub-commands
|
||||||
EXP_CASE /* expand ":syn case" arguments */
|
EXP_CASE, // expand ":syn case" arguments
|
||||||
|
EXP_SPELL, // expand ":syn spell" arguments
|
||||||
|
EXP_SYNC // expand ":syn sync" arguments
|
||||||
} expand_what;
|
} expand_what;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -5612,6 +5615,10 @@ void set_context_in_syntax_cmd(expand_T *xp, const char *arg)
|
|||||||
xp->xp_context = EXPAND_NOTHING;
|
xp->xp_context = EXPAND_NOTHING;
|
||||||
} else if (STRNICMP(arg, "case", p - arg) == 0) {
|
} else if (STRNICMP(arg, "case", p - arg) == 0) {
|
||||||
expand_what = EXP_CASE;
|
expand_what = EXP_CASE;
|
||||||
|
} else if (STRNICMP(arg, "spell", p - arg) == 0) {
|
||||||
|
expand_what = EXP_SPELL;
|
||||||
|
} else if (STRNICMP(arg, "sync", p - arg) == 0) {
|
||||||
|
expand_what = EXP_SYNC;
|
||||||
} else if (STRNICMP(arg, "keyword", p - arg) == 0
|
} else if (STRNICMP(arg, "keyword", p - arg) == 0
|
||||||
|| STRNICMP(arg, "region", p - arg) == 0
|
|| STRNICMP(arg, "region", p - arg) == 0
|
||||||
|| STRNICMP(arg, "match", p - arg) == 0
|
|| STRNICMP(arg, "match", p - arg) == 0
|
||||||
@ -5624,17 +5631,33 @@ void set_context_in_syntax_cmd(expand_T *xp, const char *arg)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static char *(case_args[]) = {"match", "ignore", NULL};
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Function given to ExpandGeneric() to obtain the list syntax names for
|
* Function given to ExpandGeneric() to obtain the list syntax names for
|
||||||
* expansion.
|
* expansion.
|
||||||
*/
|
*/
|
||||||
char_u *get_syntax_name(expand_T *xp, int idx)
|
char_u *get_syntax_name(expand_T *xp, int idx)
|
||||||
{
|
{
|
||||||
if (expand_what == EXP_SUBCMD)
|
switch (expand_what) {
|
||||||
return (char_u *)subcommands[idx].name;
|
case EXP_SUBCMD:
|
||||||
return (char_u *)case_args[idx];
|
return (char_u *)subcommands[idx].name;
|
||||||
|
case EXP_CASE: {
|
||||||
|
static char *case_args[] = { "match", "ignore", NULL };
|
||||||
|
return (char_u *)case_args[idx];
|
||||||
|
}
|
||||||
|
case EXP_SPELL: {
|
||||||
|
static char *spell_args[] =
|
||||||
|
{ "toplevel", "notoplevel", "default", NULL };
|
||||||
|
return (char_u *)spell_args[idx];
|
||||||
|
}
|
||||||
|
case EXP_SYNC: {
|
||||||
|
static char *sync_args[] =
|
||||||
|
{ "ccomment", "clear", "fromstart",
|
||||||
|
"linebreaks=", "linecont", "lines=", "match",
|
||||||
|
"maxlines=", "minlines=", "region", NULL };
|
||||||
|
return (char_u *)sync_args[idx];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -5845,9 +5868,12 @@ static void syntime_report(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* sort on total time */
|
// Sort on total time. Skip if there are no items to avoid passing NULL
|
||||||
qsort(ga.ga_data, (size_t)ga.ga_len, sizeof(time_entry_T),
|
// pointer to qsort().
|
||||||
syn_compare_syntime);
|
if (ga.ga_len > 1) {
|
||||||
|
qsort(ga.ga_data, (size_t)ga.ga_len, sizeof(time_entry_T),
|
||||||
|
syn_compare_syntime);
|
||||||
|
}
|
||||||
|
|
||||||
MSG_PUTS_TITLE(_(
|
MSG_PUTS_TITLE(_(
|
||||||
" TOTAL COUNT MATCH SLOWEST AVERAGE NAME PATTERN"));
|
" TOTAL COUNT MATCH SLOWEST AVERAGE NAME PATTERN"));
|
||||||
@ -5958,6 +5984,7 @@ static char *highlight_init_light[] =
|
|||||||
"Title ctermfg=DarkMagenta gui=bold guifg=Magenta",
|
"Title ctermfg=DarkMagenta gui=bold guifg=Magenta",
|
||||||
"Visual guibg=LightGrey",
|
"Visual guibg=LightGrey",
|
||||||
"WarningMsg ctermfg=DarkRed guifg=Red",
|
"WarningMsg ctermfg=DarkRed guifg=Red",
|
||||||
|
"Normal gui=NONE",
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -5991,23 +6018,25 @@ static char *highlight_init_dark[] =
|
|||||||
"Title ctermfg=LightMagenta gui=bold guifg=Magenta",
|
"Title ctermfg=LightMagenta gui=bold guifg=Magenta",
|
||||||
"Visual guibg=DarkGrey",
|
"Visual guibg=DarkGrey",
|
||||||
"WarningMsg ctermfg=LightRed guifg=Red",
|
"WarningMsg ctermfg=LightRed guifg=Red",
|
||||||
|
"Normal gui=NONE",
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
void
|
|
||||||
init_highlight (
|
/// Load colors from a file if "g:colors_name" is set, otherwise load builtin
|
||||||
int both, /* include groups where 'bg' doesn't matter */
|
/// colors
|
||||||
int reset /* clear group first */
|
///
|
||||||
)
|
/// @param both include groups where 'bg' doesn't matter
|
||||||
|
/// @param reset clear groups first
|
||||||
|
void
|
||||||
|
init_highlight(int both, int reset)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
char **pp;
|
char **pp;
|
||||||
static int had_both = FALSE;
|
static int had_both = FALSE;
|
||||||
|
|
||||||
/*
|
// Try finding the color scheme file. Used when a color file was loaded
|
||||||
* Try finding the color scheme file. Used when a color file was loaded
|
// and 'background' or 't_Co' is changed.
|
||||||
* and 'background' or 't_Co' is changed.
|
|
||||||
*/
|
|
||||||
char_u *p = get_var_value("g:colors_name");
|
char_u *p = get_var_value("g:colors_name");
|
||||||
if (p != NULL) {
|
if (p != NULL) {
|
||||||
// Value of g:colors_name could be freed in load_colors() and make
|
// Value of g:colors_name could be freed in load_colors() and make
|
||||||
@ -6026,33 +6055,34 @@ init_highlight (
|
|||||||
if (both) {
|
if (both) {
|
||||||
had_both = TRUE;
|
had_both = TRUE;
|
||||||
pp = highlight_init_both;
|
pp = highlight_init_both;
|
||||||
for (i = 0; pp[i] != NULL; ++i)
|
for (i = 0; pp[i] != NULL; i++) {
|
||||||
do_highlight((char_u *)pp[i], reset, TRUE);
|
do_highlight((char_u *)pp[i], reset, true);
|
||||||
} else if (!had_both)
|
}
|
||||||
/* Don't do anything before the call with both == TRUE from main().
|
} else if (!had_both) {
|
||||||
* Not everything has been setup then, and that call will overrule
|
// Don't do anything before the call with both == TRUE from main().
|
||||||
* everything anyway. */
|
// Not everything has been setup then, and that call will overrule
|
||||||
|
// everything anyway.
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (*p_bg == 'l')
|
pp = (*p_bg == 'l') ? highlight_init_light : highlight_init_dark;
|
||||||
pp = highlight_init_light;
|
|
||||||
else
|
for (i = 0; pp[i] != NULL; i++) {
|
||||||
pp = highlight_init_dark;
|
do_highlight((char_u *)pp[i], reset, true);
|
||||||
for (i = 0; pp[i] != NULL; ++i)
|
}
|
||||||
do_highlight((char_u *)pp[i], reset, TRUE);
|
|
||||||
|
|
||||||
/* Reverse looks ugly, but grey may not work for 8 colors. Thus let it
|
/* Reverse looks ugly, but grey may not work for 8 colors. Thus let it
|
||||||
* depend on the number of colors available.
|
* depend on the number of colors available.
|
||||||
* With 8 colors brown is equal to yellow, need to use black for Search fg
|
* With 8 colors brown is equal to yellow, need to use black for Search fg
|
||||||
* to avoid Statement highlighted text disappears.
|
* to avoid Statement highlighted text disappears.
|
||||||
* Clear the attributes, needed when changing the t_Co value. */
|
* Clear the attributes, needed when changing the t_Co value. */
|
||||||
if (t_colors > 8)
|
if (t_colors > 8) {
|
||||||
do_highlight(
|
do_highlight(
|
||||||
(char_u *)(*p_bg == 'l'
|
(char_u *)(*p_bg == 'l'
|
||||||
? "Visual cterm=NONE ctermbg=LightGrey"
|
? "Visual cterm=NONE ctermbg=LightGrey"
|
||||||
: "Visual cterm=NONE ctermbg=DarkGrey"), FALSE,
|
: "Visual cterm=NONE ctermbg=DarkGrey"), false,
|
||||||
TRUE);
|
true);
|
||||||
else {
|
} else {
|
||||||
do_highlight((char_u *)"Visual cterm=reverse ctermbg=NONE",
|
do_highlight((char_u *)"Visual cterm=reverse ctermbg=NONE",
|
||||||
FALSE, TRUE);
|
FALSE, TRUE);
|
||||||
if (*p_bg == 'l')
|
if (*p_bg == 'l')
|
||||||
@ -6112,12 +6142,7 @@ int load_colors(char_u *name)
|
|||||||
/// "forceit" and "init" both TRUE.
|
/// "forceit" and "init" both TRUE.
|
||||||
/// @param init TRUE when called for initializing
|
/// @param init TRUE when called for initializing
|
||||||
void
|
void
|
||||||
do_highlight(
|
do_highlight(char_u *line, int forceit, int init) {
|
||||||
char_u *line,
|
|
||||||
int forceit,
|
|
||||||
int init
|
|
||||||
)
|
|
||||||
{
|
|
||||||
char_u *name_end;
|
char_u *name_end;
|
||||||
char_u *linep;
|
char_u *linep;
|
||||||
char_u *key_start;
|
char_u *key_start;
|
||||||
@ -6134,15 +6159,16 @@ do_highlight(
|
|||||||
int dolink = FALSE;
|
int dolink = FALSE;
|
||||||
int error = FALSE;
|
int error = FALSE;
|
||||||
int color;
|
int color;
|
||||||
int is_normal_group = FALSE; /* "Normal" group */
|
bool is_normal_group = false; // "Normal" group
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If no argument, list current highlighting.
|
* If no argument, list current highlighting.
|
||||||
*/
|
*/
|
||||||
if (ends_excmd(*line)) {
|
if (ends_excmd(*line)) {
|
||||||
for (int i = 1; i <= highlight_ga.ga_len && !got_int; ++i)
|
for (int i = 1; i <= highlight_ga.ga_len && !got_int; i++) {
|
||||||
/* TODO: only call when the group has attributes set */
|
// todo(vim): only call when the group has attributes set
|
||||||
highlight_list_one(i);
|
highlight_list_one(i);
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -6270,12 +6296,12 @@ do_highlight(
|
|||||||
return;
|
return;
|
||||||
idx = id - 1; /* index is ID minus one */
|
idx = id - 1; /* index is ID minus one */
|
||||||
|
|
||||||
/* Return if "default" was used and the group already has settings. */
|
// Return if "default" was used and the group already has settings
|
||||||
if (dodefault && hl_has_settings(idx, TRUE))
|
if (dodefault && hl_has_settings(idx, true)) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (STRCMP(HL_TABLE()[idx].sg_name_u, "NORMAL") == 0)
|
is_normal_group = (STRCMP(HL_TABLE()[idx].sg_name_u, "NORMAL") == 0);
|
||||||
is_normal_group = TRUE;
|
|
||||||
|
|
||||||
/* Clear the highlighting for ":hi clear {group}" and ":hi clear". */
|
/* Clear the highlighting for ":hi clear {group}" and ":hi clear". */
|
||||||
if (doclear || (forceit && init)) {
|
if (doclear || (forceit && init)) {
|
||||||
@ -6284,7 +6310,7 @@ do_highlight(
|
|||||||
HL_TABLE()[idx].sg_set = 0;
|
HL_TABLE()[idx].sg_set = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!doclear)
|
if (!doclear) {
|
||||||
while (!ends_excmd(*linep)) {
|
while (!ends_excmd(*linep)) {
|
||||||
key_start = linep;
|
key_start = linep;
|
||||||
if (*linep == '=') {
|
if (*linep == '=') {
|
||||||
@ -6390,12 +6416,12 @@ do_highlight(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (STRCMP(key, "FONT") == 0) {
|
} else if (STRCMP(key, "FONT") == 0) {
|
||||||
/* in non-GUI fonts are simply ignored */
|
// in non-GUI fonts are simply ignored
|
||||||
} else if (STRCMP(key,
|
} else if (STRCMP(key, "CTERMFG") == 0 || STRCMP(key, "CTERMBG") == 0) {
|
||||||
"CTERMFG") == 0 || STRCMP(key, "CTERMBG") == 0) {
|
|
||||||
if (!init || !(HL_TABLE()[idx].sg_set & SG_CTERM)) {
|
if (!init || !(HL_TABLE()[idx].sg_set & SG_CTERM)) {
|
||||||
if (!init)
|
if (!init) {
|
||||||
HL_TABLE()[idx].sg_set |= SG_CTERM;
|
HL_TABLE()[idx].sg_set |= SG_CTERM;
|
||||||
|
}
|
||||||
|
|
||||||
/* When setting the foreground color, and previously the "bold"
|
/* When setting the foreground color, and previously the "bold"
|
||||||
* flag was set for a light color, reset it now */
|
* flag was set for a light color, reset it now */
|
||||||
@ -6489,9 +6515,10 @@ do_highlight(
|
|||||||
* colors (on some terminals, e.g. "linux") */
|
* colors (on some terminals, e.g. "linux") */
|
||||||
if (color & 8) {
|
if (color & 8) {
|
||||||
HL_TABLE()[idx].sg_cterm |= HL_BOLD;
|
HL_TABLE()[idx].sg_cterm |= HL_BOLD;
|
||||||
HL_TABLE()[idx].sg_cterm_bold = TRUE;
|
HL_TABLE()[idx].sg_cterm_bold = true;
|
||||||
} else
|
} else {
|
||||||
HL_TABLE()[idx].sg_cterm &= ~HL_BOLD;
|
HL_TABLE()[idx].sg_cterm &= ~HL_BOLD;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
color &= 7; // truncate to 8 colors
|
color &= 7; // truncate to 8 colors
|
||||||
} else if (t_colors == 16 || t_colors == 88 || t_colors >= 256) {
|
} else if (t_colors == 16 || t_colors == 88 || t_colors >= 256) {
|
||||||
@ -6603,38 +6630,40 @@ do_highlight(
|
|||||||
/*
|
/*
|
||||||
* When highlighting has been given for a group, don't link it.
|
* When highlighting has been given for a group, don't link it.
|
||||||
*/
|
*/
|
||||||
if (!init || !(HL_TABLE()[idx].sg_set & SG_LINK))
|
if (!init || !(HL_TABLE()[idx].sg_set & SG_LINK)) {
|
||||||
HL_TABLE()[idx].sg_link = 0;
|
HL_TABLE()[idx].sg_link = 0;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Continue with next argument.
|
* Continue with next argument.
|
||||||
*/
|
*/
|
||||||
linep = skipwhite(linep);
|
linep = skipwhite(linep);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If there is an error, and it's a new entry, remove it from the table.
|
* If there is an error, and it's a new entry, remove it from the table.
|
||||||
*/
|
*/
|
||||||
if (error && idx == highlight_ga.ga_len)
|
if (error && idx == highlight_ga.ga_len) {
|
||||||
syn_unadd_group();
|
syn_unadd_group();
|
||||||
else {
|
} else {
|
||||||
if (is_normal_group) {
|
if (is_normal_group) {
|
||||||
HL_TABLE()[idx].sg_attr = 0;
|
|
||||||
// Need to update all groups, because they might be using "bg" and/or
|
// Need to update all groups, because they might be using "bg" and/or
|
||||||
// "fg", which have been changed now.
|
// "fg", which have been changed now.
|
||||||
highlight_attr_set_all();
|
highlight_attr_set_all();
|
||||||
// If the normal group has changed, it is simpler to refresh every UI
|
// If the normal group has changed, it is simpler to refresh every UI
|
||||||
ui_refresh();
|
ui_refresh();
|
||||||
} else
|
} else {
|
||||||
set_hl_attr(idx);
|
set_hl_attr(idx);
|
||||||
|
}
|
||||||
HL_TABLE()[idx].sg_scriptID = current_SID;
|
HL_TABLE()[idx].sg_scriptID = current_SID;
|
||||||
redraw_all_later(NOT_VALID);
|
redraw_all_later(NOT_VALID);
|
||||||
}
|
}
|
||||||
xfree(key);
|
xfree(key);
|
||||||
xfree(arg);
|
xfree(arg);
|
||||||
|
|
||||||
/* Only call highlight_changed() once, after sourcing a syntax file */
|
// Only call highlight_changed() once, after sourcing a syntax file
|
||||||
need_highlight_changed = TRUE;
|
need_highlight_changed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(EXITFREE)
|
#if defined(EXITFREE)
|
||||||
@ -6707,14 +6736,15 @@ static void highlight_clear(int idx)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/// Table with the specifications for an attribute number.
|
||||||
* Table with the specifications for an attribute number.
|
/// Note that this table is used by ALL buffers. This is required because the
|
||||||
* Note that this table is used by ALL buffers. This is required because the
|
/// GUI can redraw at any time for any buffer.
|
||||||
* GUI can redraw at any time for any buffer.
|
|
||||||
*/
|
|
||||||
static garray_T attr_table = GA_EMPTY_INIT_VALUE;
|
static garray_T attr_table = GA_EMPTY_INIT_VALUE;
|
||||||
|
|
||||||
#define ATTR_ENTRY(idx) ((attrentry_T *)attr_table.ga_data)[idx]
|
static inline attrentry_T * ATTR_ENTRY(int idx)
|
||||||
|
{
|
||||||
|
return &((attrentry_T *)attr_table.ga_data)[idx];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/// Return the attr number for a set of colors and font.
|
/// Return the attr number for a set of colors and font.
|
||||||
@ -6804,7 +6834,7 @@ int hl_combine_attr(int char_attr, int prim_attr)
|
|||||||
{
|
{
|
||||||
attrentry_T *char_aep = NULL;
|
attrentry_T *char_aep = NULL;
|
||||||
attrentry_T *spell_aep;
|
attrentry_T *spell_aep;
|
||||||
attrentry_T new_en;
|
attrentry_T new_en = ATTRENTRY_INIT;
|
||||||
|
|
||||||
if (char_attr == 0) {
|
if (char_attr == 0) {
|
||||||
return prim_attr;
|
return prim_attr;
|
||||||
@ -6820,8 +6850,6 @@ int hl_combine_attr(int char_attr, int prim_attr)
|
|||||||
if (char_aep != NULL) {
|
if (char_aep != NULL) {
|
||||||
// Copy all attributes from char_aep to the new entry
|
// Copy all attributes from char_aep to the new entry
|
||||||
new_en = *char_aep;
|
new_en = *char_aep;
|
||||||
} else {
|
|
||||||
memset(&new_en, 0, sizeof(new_en));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
spell_aep = syn_cterm_attr2entry(prim_attr);
|
spell_aep = syn_cterm_attr2entry(prim_attr);
|
||||||
@ -6852,17 +6880,25 @@ int hl_combine_attr(int char_attr, int prim_attr)
|
|||||||
return get_attr_entry(&new_en);
|
return get_attr_entry(&new_en);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// \note this function does not apply exclusively to cterm attr contrary
|
||||||
|
/// to what its name implies
|
||||||
|
/// \warn don't call it with attr 0 (i.e., the null attribute)
|
||||||
attrentry_T *syn_cterm_attr2entry(int attr)
|
attrentry_T *syn_cterm_attr2entry(int attr)
|
||||||
{
|
{
|
||||||
attr -= ATTR_OFF;
|
attr -= ATTR_OFF;
|
||||||
if (attr >= attr_table.ga_len) /* did ":syntax clear" */
|
if (attr >= attr_table.ga_len) {
|
||||||
|
// did ":syntax clear"
|
||||||
return NULL;
|
return NULL;
|
||||||
return &(ATTR_ENTRY(attr));
|
}
|
||||||
|
return ATTR_ENTRY(attr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// \addtogroup LIST_XXX
|
||||||
|
/// @{
|
||||||
#define LIST_ATTR 1
|
#define LIST_ATTR 1
|
||||||
#define LIST_STRING 2
|
#define LIST_STRING 2
|
||||||
#define LIST_INT 3
|
#define LIST_INT 3
|
||||||
|
/// @}
|
||||||
|
|
||||||
static void highlight_list_one(int id)
|
static void highlight_list_one(int id)
|
||||||
{
|
{
|
||||||
@ -6901,7 +6937,13 @@ static void highlight_list_one(int id)
|
|||||||
last_set_msg(sgp->sg_scriptID);
|
last_set_msg(sgp->sg_scriptID);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int highlight_list_arg(int id, int didh, int type, int iarg, char_u *sarg, char *name)
|
/// Outputs a highlight when doing ":hi MyHighlight"
|
||||||
|
///
|
||||||
|
/// @param type one of \ref LIST_XXX
|
||||||
|
/// @param iarg integer argument used if \p type == LIST_INT
|
||||||
|
/// @param sarg string used if \p type == LIST_STRING
|
||||||
|
static int highlight_list_arg(int id, int didh, int type, int iarg,
|
||||||
|
char_u *sarg, const char *name)
|
||||||
{
|
{
|
||||||
char_u buf[100];
|
char_u buf[100];
|
||||||
char_u *ts;
|
char_u *ts;
|
||||||
@ -7041,24 +7083,23 @@ const char *highlight_color(const int id, const char *const what,
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/// Output the syntax list header.
|
||||||
* Output the syntax list header.
|
///
|
||||||
* Return TRUE when started a new line.
|
/// @param did_header did header already
|
||||||
*/
|
/// @param outlen length of string that comes
|
||||||
static int
|
/// @param id highlight group id
|
||||||
syn_list_header (
|
/// @return true when started a new line.
|
||||||
int did_header, /* did header already */
|
static int
|
||||||
int outlen, /* length of string that comes */
|
syn_list_header(int did_header, int outlen, int id)
|
||||||
int id /* highlight group id */
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
int endcol = 19;
|
int endcol = 19;
|
||||||
int newline = TRUE;
|
int newline = TRUE;
|
||||||
|
|
||||||
if (!did_header) {
|
if (!did_header) {
|
||||||
msg_putchar('\n');
|
msg_putchar('\n');
|
||||||
if (got_int)
|
if (got_int) {
|
||||||
return TRUE;
|
return true;
|
||||||
|
}
|
||||||
msg_outtrans(HL_TABLE()[id - 1].sg_name);
|
msg_outtrans(HL_TABLE()[id - 1].sg_name);
|
||||||
endcol = 15;
|
endcol = 15;
|
||||||
} else if (msg_col + outlen + 1 >= Columns) {
|
} else if (msg_col + outlen + 1 >= Columns) {
|
||||||
@ -7086,21 +7127,14 @@ syn_list_header (
|
|||||||
return newline;
|
return newline;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/// Set the attribute numbers for a highlight group.
|
||||||
* Set the attribute numbers for a highlight group.
|
/// Called after one of the attributes has changed.
|
||||||
* Called after one of the attributes has changed.
|
/// @param idx corrected highlight index
|
||||||
*/
|
static void set_hl_attr(int idx)
|
||||||
static void
|
|
||||||
set_hl_attr (
|
|
||||||
int idx /* index in array */
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
attrentry_T at_en;
|
attrentry_T at_en = ATTRENTRY_INIT;
|
||||||
struct hl_group *sgp = HL_TABLE() + idx;
|
struct hl_group *sgp = HL_TABLE() + idx;
|
||||||
|
|
||||||
/* The "Normal" group doesn't need an attribute number */
|
|
||||||
if (sgp->sg_name_u != NULL && STRCMP(sgp->sg_name_u, "NORMAL") == 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
at_en.cterm_ae_attr = sgp->sg_cterm;
|
at_en.cterm_ae_attr = sgp->sg_cterm;
|
||||||
at_en.cterm_fg_color = sgp->sg_cterm_fg;
|
at_en.cterm_fg_color = sgp->sg_cterm_fg;
|
||||||
@ -7124,10 +7158,10 @@ set_hl_attr (
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/// Lookup a highlight group name and return its ID.
|
||||||
* Lookup a highlight group name and return it's ID.
|
///
|
||||||
* If it is not found, 0 is returned.
|
/// @param highlight name e.g. 'Cursor', 'Normal'
|
||||||
*/
|
/// @return the highlight id, else 0 if \p name does not exist
|
||||||
int syn_name2id(const char_u *name)
|
int syn_name2id(const char_u *name)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
@ -7176,7 +7210,7 @@ int syn_namen2id(char_u *linep, int len)
|
|||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Find highlight group name in the table and return it's ID.
|
/// Find highlight group name in the table and return its ID.
|
||||||
/// If it doesn't exist yet, a new entry is created.
|
/// If it doesn't exist yet, a new entry is created.
|
||||||
///
|
///
|
||||||
/// @param pp Highlight group name
|
/// @param pp Highlight group name
|
||||||
@ -7195,11 +7229,11 @@ int syn_check_group(char_u *pp, int len)
|
|||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/// Add new highlight group and return it's ID.
|
||||||
* Add new highlight group and return it's ID.
|
///
|
||||||
* "name" must be an allocated string, it will be consumed.
|
/// @param name must be an allocated string, it will be consumed.
|
||||||
* Return 0 for failure.
|
/// @return 0 for failure, else the allocated group id
|
||||||
*/
|
/// @see syn_check_group syn_unadd_group
|
||||||
static int syn_add_group(char_u *name)
|
static int syn_add_group(char_u *name)
|
||||||
{
|
{
|
||||||
char_u *p;
|
char_u *p;
|
||||||
@ -7237,25 +7271,26 @@ static int syn_add_group(char_u *name)
|
|||||||
struct hl_group* hlgp = GA_APPEND_VIA_PTR(struct hl_group, &highlight_ga);
|
struct hl_group* hlgp = GA_APPEND_VIA_PTR(struct hl_group, &highlight_ga);
|
||||||
memset(hlgp, 0, sizeof(*hlgp));
|
memset(hlgp, 0, sizeof(*hlgp));
|
||||||
hlgp->sg_name = name;
|
hlgp->sg_name = name;
|
||||||
|
hlgp->sg_rgb_bg = -1;
|
||||||
|
hlgp->sg_rgb_fg = -1;
|
||||||
|
hlgp->sg_rgb_sp = -1;
|
||||||
hlgp->sg_name_u = vim_strsave_up(name);
|
hlgp->sg_name_u = vim_strsave_up(name);
|
||||||
|
|
||||||
return highlight_ga.ga_len; /* ID is index plus one */
|
return highlight_ga.ga_len; /* ID is index plus one */
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/// When, just after calling syn_add_group(), an error is discovered, this
|
||||||
* When, just after calling syn_add_group(), an error is discovered, this
|
/// function deletes the new name.
|
||||||
* function deletes the new name.
|
|
||||||
*/
|
|
||||||
static void syn_unadd_group(void)
|
static void syn_unadd_group(void)
|
||||||
{
|
{
|
||||||
--highlight_ga.ga_len;
|
highlight_ga.ga_len--;
|
||||||
xfree(HL_TABLE()[highlight_ga.ga_len].sg_name);
|
xfree(HL_TABLE()[highlight_ga.ga_len].sg_name);
|
||||||
xfree(HL_TABLE()[highlight_ga.ga_len].sg_name_u);
|
xfree(HL_TABLE()[highlight_ga.ga_len].sg_name_u);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Translate a group ID to highlight attributes.
|
/// Translate a group ID to highlight attributes.
|
||||||
*/
|
/// @see syn_cterm_attr2entry
|
||||||
int syn_id2attr(int hl_id)
|
int syn_id2attr(int hl_id)
|
||||||
{
|
{
|
||||||
struct hl_group *sgp;
|
struct hl_group *sgp;
|
||||||
@ -8208,6 +8243,30 @@ RgbValue name_to_color(const uint8_t *name)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Gets highlight description for id `attr_id` as a map.
|
||||||
|
Dictionary hl_get_attr_by_id(Integer attr_id, Boolean rgb, Error *err)
|
||||||
|
{
|
||||||
|
HlAttrs attrs = HLATTRS_INIT;
|
||||||
|
Dictionary dic = ARRAY_DICT_INIT;
|
||||||
|
|
||||||
|
if (attr_id == 0) {
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
|
||||||
|
attrentry_T *aep = syn_cterm_attr2entry((int)attr_id);
|
||||||
|
if (!aep) {
|
||||||
|
api_set_error(err, kErrorTypeException,
|
||||||
|
"Invalid attribute id: %d", attr_id);
|
||||||
|
return dic;
|
||||||
|
}
|
||||||
|
|
||||||
|
attrs = attrentry2hlattrs(aep, rgb);
|
||||||
|
|
||||||
|
end:
|
||||||
|
return hlattrs2dict(attrs);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**************************************
|
/**************************************
|
||||||
* End of Highlighting stuff *
|
* End of Highlighting stuff *
|
||||||
**************************************/
|
**************************************/
|
||||||
|
@ -73,4 +73,14 @@ typedef struct attr_entry {
|
|||||||
int cterm_fg_color, cterm_bg_color;
|
int cterm_fg_color, cterm_bg_color;
|
||||||
} attrentry_T;
|
} attrentry_T;
|
||||||
|
|
||||||
|
#define ATTRENTRY_INIT { \
|
||||||
|
.rgb_ae_attr = 0, \
|
||||||
|
.cterm_ae_attr = 0, \
|
||||||
|
.rgb_fg_color = -1, \
|
||||||
|
.rgb_bg_color = -1, \
|
||||||
|
.rgb_sp_color = -1, \
|
||||||
|
.cterm_fg_color = 0, \
|
||||||
|
.cterm_bg_color = 0, \
|
||||||
|
}
|
||||||
|
|
||||||
#endif // NVIM_SYNTAX_DEFS_H
|
#endif // NVIM_SYNTAX_DEFS_H
|
||||||
|
@ -432,14 +432,6 @@ static int terminal_execute(VimState *state, int key)
|
|||||||
TerminalState *s = (TerminalState *)state;
|
TerminalState *s = (TerminalState *)state;
|
||||||
|
|
||||||
switch (key) {
|
switch (key) {
|
||||||
case K_FOCUSGAINED: // nvim has been given focus
|
|
||||||
apply_autocmds(EVENT_FOCUSGAINED, NULL, NULL, false, curbuf);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case K_FOCUSLOST: // nvim has lost focus
|
|
||||||
apply_autocmds(EVENT_FOCUSLOST, NULL, NULL, false, curbuf);
|
|
||||||
break;
|
|
||||||
|
|
||||||
// Temporary fix until paste events gets implemented
|
// Temporary fix until paste events gets implemented
|
||||||
case K_PASTE:
|
case K_PASTE:
|
||||||
break;
|
break;
|
||||||
@ -530,6 +522,12 @@ void terminal_send(Terminal *term, char *data, size_t size)
|
|||||||
void terminal_send_key(Terminal *term, int c)
|
void terminal_send_key(Terminal *term, int c)
|
||||||
{
|
{
|
||||||
VTermModifier mod = VTERM_MOD_NONE;
|
VTermModifier mod = VTERM_MOD_NONE;
|
||||||
|
|
||||||
|
// Convert K_ZERO back to ASCII
|
||||||
|
if (c == K_ZERO) {
|
||||||
|
c = Ctrl_AT;
|
||||||
|
}
|
||||||
|
|
||||||
VTermKey key = convert_key(c, &mod);
|
VTermKey key = convert_key(c, &mod);
|
||||||
|
|
||||||
if (key) {
|
if (key) {
|
||||||
@ -783,26 +781,60 @@ static int term_sb_pop(int cols, VTermScreenCell *cells, void *data)
|
|||||||
// }}}
|
// }}}
|
||||||
// input handling {{{
|
// input handling {{{
|
||||||
|
|
||||||
static void convert_modifiers(VTermModifier *statep)
|
static void convert_modifiers(int key, VTermModifier *statep)
|
||||||
{
|
{
|
||||||
if (mod_mask & MOD_MASK_SHIFT) { *statep |= VTERM_MOD_SHIFT; }
|
if (mod_mask & MOD_MASK_SHIFT) { *statep |= VTERM_MOD_SHIFT; }
|
||||||
if (mod_mask & MOD_MASK_CTRL) { *statep |= VTERM_MOD_CTRL; }
|
if (mod_mask & MOD_MASK_CTRL) { *statep |= VTERM_MOD_CTRL; }
|
||||||
if (mod_mask & MOD_MASK_ALT) { *statep |= VTERM_MOD_ALT; }
|
if (mod_mask & MOD_MASK_ALT) { *statep |= VTERM_MOD_ALT; }
|
||||||
|
|
||||||
|
switch (key) {
|
||||||
|
case K_S_TAB:
|
||||||
|
case K_S_UP:
|
||||||
|
case K_S_DOWN:
|
||||||
|
case K_S_LEFT:
|
||||||
|
case K_S_RIGHT:
|
||||||
|
case K_S_F1:
|
||||||
|
case K_S_F2:
|
||||||
|
case K_S_F3:
|
||||||
|
case K_S_F4:
|
||||||
|
case K_S_F5:
|
||||||
|
case K_S_F6:
|
||||||
|
case K_S_F7:
|
||||||
|
case K_S_F8:
|
||||||
|
case K_S_F9:
|
||||||
|
case K_S_F10:
|
||||||
|
case K_S_F11:
|
||||||
|
case K_S_F12:
|
||||||
|
*statep |= VTERM_MOD_SHIFT;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case K_C_LEFT:
|
||||||
|
case K_C_RIGHT:
|
||||||
|
*statep |= VTERM_MOD_CTRL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static VTermKey convert_key(int key, VTermModifier *statep)
|
static VTermKey convert_key(int key, VTermModifier *statep)
|
||||||
{
|
{
|
||||||
convert_modifiers(statep);
|
convert_modifiers(key, statep);
|
||||||
|
|
||||||
switch (key) {
|
switch (key) {
|
||||||
case K_BS: return VTERM_KEY_BACKSPACE;
|
case K_BS: return VTERM_KEY_BACKSPACE;
|
||||||
|
case K_S_TAB: // FALLTHROUGH
|
||||||
case TAB: return VTERM_KEY_TAB;
|
case TAB: return VTERM_KEY_TAB;
|
||||||
case Ctrl_M: return VTERM_KEY_ENTER;
|
case Ctrl_M: return VTERM_KEY_ENTER;
|
||||||
case ESC: return VTERM_KEY_ESCAPE;
|
case ESC: return VTERM_KEY_ESCAPE;
|
||||||
|
|
||||||
|
case K_S_UP: // FALLTHROUGH
|
||||||
case K_UP: return VTERM_KEY_UP;
|
case K_UP: return VTERM_KEY_UP;
|
||||||
|
case K_S_DOWN: // FALLTHROUGH
|
||||||
case K_DOWN: return VTERM_KEY_DOWN;
|
case K_DOWN: return VTERM_KEY_DOWN;
|
||||||
|
case K_S_LEFT: // FALLTHROUGH
|
||||||
|
case K_C_LEFT: // FALLTHROUGH
|
||||||
case K_LEFT: return VTERM_KEY_LEFT;
|
case K_LEFT: return VTERM_KEY_LEFT;
|
||||||
|
case K_S_RIGHT: // FALLTHROUGH
|
||||||
|
case K_C_RIGHT: // FALLTHROUGH
|
||||||
case K_RIGHT: return VTERM_KEY_RIGHT;
|
case K_RIGHT: return VTERM_KEY_RIGHT;
|
||||||
|
|
||||||
case K_INS: return VTERM_KEY_INS;
|
case K_INS: return VTERM_KEY_INS;
|
||||||
@ -812,22 +844,22 @@ static VTermKey convert_key(int key, VTermModifier *statep)
|
|||||||
case K_PAGEUP: return VTERM_KEY_PAGEUP;
|
case K_PAGEUP: return VTERM_KEY_PAGEUP;
|
||||||
case K_PAGEDOWN: return VTERM_KEY_PAGEDOWN;
|
case K_PAGEDOWN: return VTERM_KEY_PAGEDOWN;
|
||||||
|
|
||||||
case K_K0:
|
case K_K0: // FALLTHROUGH
|
||||||
case K_KINS: return VTERM_KEY_KP_0;
|
case K_KINS: return VTERM_KEY_KP_0;
|
||||||
case K_K1:
|
case K_K1: // FALLTHROUGH
|
||||||
case K_KEND: return VTERM_KEY_KP_1;
|
case K_KEND: return VTERM_KEY_KP_1;
|
||||||
case K_K2: return VTERM_KEY_KP_2;
|
case K_K2: return VTERM_KEY_KP_2;
|
||||||
case K_K3:
|
case K_K3: // FALLTHROUGH
|
||||||
case K_KPAGEDOWN: return VTERM_KEY_KP_3;
|
case K_KPAGEDOWN: return VTERM_KEY_KP_3;
|
||||||
case K_K4: return VTERM_KEY_KP_4;
|
case K_K4: return VTERM_KEY_KP_4;
|
||||||
case K_K5: return VTERM_KEY_KP_5;
|
case K_K5: return VTERM_KEY_KP_5;
|
||||||
case K_K6: return VTERM_KEY_KP_6;
|
case K_K6: return VTERM_KEY_KP_6;
|
||||||
case K_K7:
|
case K_K7: // FALLTHROUGH
|
||||||
case K_KHOME: return VTERM_KEY_KP_7;
|
case K_KHOME: return VTERM_KEY_KP_7;
|
||||||
case K_K8: return VTERM_KEY_KP_8;
|
case K_K8: return VTERM_KEY_KP_8;
|
||||||
case K_K9:
|
case K_K9: // FALLTHROUGH
|
||||||
case K_KPAGEUP: return VTERM_KEY_KP_9;
|
case K_KPAGEUP: return VTERM_KEY_KP_9;
|
||||||
case K_KDEL:
|
case K_KDEL: // FALLTHROUGH
|
||||||
case K_KPOINT: return VTERM_KEY_KP_PERIOD;
|
case K_KPOINT: return VTERM_KEY_KP_PERIOD;
|
||||||
case K_KENTER: return VTERM_KEY_KP_ENTER;
|
case K_KENTER: return VTERM_KEY_KP_ENTER;
|
||||||
case K_KPLUS: return VTERM_KEY_KP_PLUS;
|
case K_KPLUS: return VTERM_KEY_KP_PLUS;
|
||||||
@ -835,6 +867,57 @@ static VTermKey convert_key(int key, VTermModifier *statep)
|
|||||||
case K_KMULTIPLY: return VTERM_KEY_KP_MULT;
|
case K_KMULTIPLY: return VTERM_KEY_KP_MULT;
|
||||||
case K_KDIVIDE: return VTERM_KEY_KP_DIVIDE;
|
case K_KDIVIDE: return VTERM_KEY_KP_DIVIDE;
|
||||||
|
|
||||||
|
case K_S_F1: // FALLTHROUGH
|
||||||
|
case K_F1: return VTERM_KEY_FUNCTION(1);
|
||||||
|
case K_S_F2: // FALLTHROUGH
|
||||||
|
case K_F2: return VTERM_KEY_FUNCTION(2);
|
||||||
|
case K_S_F3: // FALLTHROUGH
|
||||||
|
case K_F3: return VTERM_KEY_FUNCTION(3);
|
||||||
|
case K_S_F4: // FALLTHROUGH
|
||||||
|
case K_F4: return VTERM_KEY_FUNCTION(4);
|
||||||
|
case K_S_F5: // FALLTHROUGH
|
||||||
|
case K_F5: return VTERM_KEY_FUNCTION(5);
|
||||||
|
case K_S_F6: // FALLTHROUGH
|
||||||
|
case K_F6: return VTERM_KEY_FUNCTION(6);
|
||||||
|
case K_S_F7: // FALLTHROUGH
|
||||||
|
case K_F7: return VTERM_KEY_FUNCTION(7);
|
||||||
|
case K_S_F8: // FALLTHROUGH
|
||||||
|
case K_F8: return VTERM_KEY_FUNCTION(8);
|
||||||
|
case K_S_F9: // FALLTHROUGH
|
||||||
|
case K_F9: return VTERM_KEY_FUNCTION(9);
|
||||||
|
case K_S_F10: // FALLTHROUGH
|
||||||
|
case K_F10: return VTERM_KEY_FUNCTION(10);
|
||||||
|
case K_S_F11: // FALLTHROUGH
|
||||||
|
case K_F11: return VTERM_KEY_FUNCTION(11);
|
||||||
|
case K_S_F12: // FALLTHROUGH
|
||||||
|
case K_F12: return VTERM_KEY_FUNCTION(12);
|
||||||
|
|
||||||
|
case K_F13: return VTERM_KEY_FUNCTION(13);
|
||||||
|
case K_F14: return VTERM_KEY_FUNCTION(14);
|
||||||
|
case K_F15: return VTERM_KEY_FUNCTION(15);
|
||||||
|
case K_F16: return VTERM_KEY_FUNCTION(16);
|
||||||
|
case K_F17: return VTERM_KEY_FUNCTION(17);
|
||||||
|
case K_F18: return VTERM_KEY_FUNCTION(18);
|
||||||
|
case K_F19: return VTERM_KEY_FUNCTION(19);
|
||||||
|
case K_F20: return VTERM_KEY_FUNCTION(20);
|
||||||
|
case K_F21: return VTERM_KEY_FUNCTION(21);
|
||||||
|
case K_F22: return VTERM_KEY_FUNCTION(22);
|
||||||
|
case K_F23: return VTERM_KEY_FUNCTION(23);
|
||||||
|
case K_F24: return VTERM_KEY_FUNCTION(24);
|
||||||
|
case K_F25: return VTERM_KEY_FUNCTION(25);
|
||||||
|
case K_F26: return VTERM_KEY_FUNCTION(26);
|
||||||
|
case K_F27: return VTERM_KEY_FUNCTION(27);
|
||||||
|
case K_F28: return VTERM_KEY_FUNCTION(28);
|
||||||
|
case K_F29: return VTERM_KEY_FUNCTION(29);
|
||||||
|
case K_F30: return VTERM_KEY_FUNCTION(30);
|
||||||
|
case K_F31: return VTERM_KEY_FUNCTION(31);
|
||||||
|
case K_F32: return VTERM_KEY_FUNCTION(32);
|
||||||
|
case K_F33: return VTERM_KEY_FUNCTION(33);
|
||||||
|
case K_F34: return VTERM_KEY_FUNCTION(34);
|
||||||
|
case K_F35: return VTERM_KEY_FUNCTION(35);
|
||||||
|
case K_F36: return VTERM_KEY_FUNCTION(36);
|
||||||
|
case K_F37: return VTERM_KEY_FUNCTION(37);
|
||||||
|
|
||||||
default: return VTERM_KEY_NONE;
|
default: return VTERM_KEY_NONE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1176,6 +1259,10 @@ static void redraw(bool restore_cursor)
|
|||||||
update_screen(0);
|
update_screen(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (need_maketitle) { // Update title in terminal-mode. #7248
|
||||||
|
maketitle();
|
||||||
|
}
|
||||||
|
|
||||||
if (restore_cursor) {
|
if (restore_cursor) {
|
||||||
ui_cursor_goto(save_row, save_col);
|
ui_cursor_goto(save_row, save_col);
|
||||||
} else if (term) {
|
} else if (term) {
|
||||||
|
@ -58,6 +58,8 @@ NEW_TESTS ?= \
|
|||||||
test_match.res \
|
test_match.res \
|
||||||
test_matchadd_conceal.res \
|
test_matchadd_conceal.res \
|
||||||
test_matchadd_conceal_utf8.res \
|
test_matchadd_conceal_utf8.res \
|
||||||
|
test_mksession.res \
|
||||||
|
test_mksession_utf8.res \
|
||||||
test_nested_function.res \
|
test_nested_function.res \
|
||||||
test_normal.res \
|
test_normal.res \
|
||||||
test_quickfix.res \
|
test_quickfix.res \
|
||||||
|
@ -230,12 +230,41 @@ func Test_paste_in_cmdline()
|
|||||||
|
|
||||||
call feedkeys("f;:aaa \<C-R>\<C-A> bbb\<C-B>\"\<CR>", 'tx')
|
call feedkeys("f;:aaa \<C-R>\<C-A> bbb\<C-B>\"\<CR>", 'tx')
|
||||||
call assert_equal('"aaa a;b-c*d bbb', @:)
|
call assert_equal('"aaa a;b-c*d bbb', @:)
|
||||||
|
|
||||||
|
call feedkeys(":\<C-\>etoupper(getline(1))\<CR>\<C-B>\"\<CR>", 'tx')
|
||||||
|
call assert_equal('"ASDF.X /TMP/SOME VERYLONGWORD A;B-C*D ', @:)
|
||||||
bwipe!
|
bwipe!
|
||||||
endfunc
|
endfunc
|
||||||
|
|
||||||
func Test_illegal_address()
|
func Test_remove_char_in_cmdline()
|
||||||
|
call feedkeys(":abc def\<S-Left>\<Del>\<C-B>\"\<CR>", 'tx')
|
||||||
|
call assert_equal('"abc ef', @:)
|
||||||
|
|
||||||
|
call feedkeys(":abc def\<S-Left>\<BS>\<C-B>\"\<CR>", 'tx')
|
||||||
|
call assert_equal('"abcdef', @:)
|
||||||
|
|
||||||
|
call feedkeys(":abc def ghi\<S-Left>\<C-W>\<C-B>\"\<CR>", 'tx')
|
||||||
|
call assert_equal('"abc ghi', @:)
|
||||||
|
|
||||||
|
call feedkeys(":abc def\<S-Left>\<C-U>\<C-B>\"\<CR>", 'tx')
|
||||||
|
call assert_equal('"def', @:)
|
||||||
|
endfunc
|
||||||
|
|
||||||
|
func Test_illegal_address1()
|
||||||
new
|
new
|
||||||
2;'(
|
2;'(
|
||||||
2;')
|
2;')
|
||||||
quit
|
quit
|
||||||
endfunc
|
endfunc
|
||||||
|
|
||||||
|
func Test_illegal_address2()
|
||||||
|
call writefile(['c', 'x', ' x', '.', '1;y'], 'Xtest.vim')
|
||||||
|
new
|
||||||
|
source Xtest.vim
|
||||||
|
" Trigger calling validate_cursor()
|
||||||
|
diffsp Xtest.vim
|
||||||
|
quit!
|
||||||
|
bwipe!
|
||||||
|
call delete('Xtest.vim')
|
||||||
|
endfunc
|
||||||
|
|
||||||
|
@ -212,6 +212,7 @@ func Test_diffoff()
|
|||||||
call setline(1, ['One', '', 'Two', 'Three'])
|
call setline(1, ['One', '', 'Two', 'Three'])
|
||||||
diffthis
|
diffthis
|
||||||
redraw
|
redraw
|
||||||
|
call assert_notequal(normattr, screenattr(1, 1))
|
||||||
diffoff!
|
diffoff!
|
||||||
redraw
|
redraw
|
||||||
call assert_equal(normattr, screenattr(1, 1))
|
call assert_equal(normattr, screenattr(1, 1))
|
||||||
@ -219,6 +220,42 @@ func Test_diffoff()
|
|||||||
bwipe!
|
bwipe!
|
||||||
endfunc
|
endfunc
|
||||||
|
|
||||||
|
func Test_diffoff_hidden()
|
||||||
|
set diffopt=filler,foldcolumn:0
|
||||||
|
e! one
|
||||||
|
call setline(1, ['Two', 'Three'])
|
||||||
|
let normattr = screenattr(1, 1)
|
||||||
|
diffthis
|
||||||
|
botright vert new two
|
||||||
|
call setline(1, ['One', 'Four'])
|
||||||
|
diffthis
|
||||||
|
redraw
|
||||||
|
call assert_notequal(normattr, screenattr(1, 1))
|
||||||
|
set hidden
|
||||||
|
close
|
||||||
|
redraw
|
||||||
|
" diffing with hidden buffer two
|
||||||
|
call assert_notequal(normattr, screenattr(1, 1))
|
||||||
|
diffoff
|
||||||
|
redraw
|
||||||
|
call assert_equal(normattr, screenattr(1, 1))
|
||||||
|
diffthis
|
||||||
|
redraw
|
||||||
|
" still diffing with hidden buffer two
|
||||||
|
call assert_notequal(normattr, screenattr(1, 1))
|
||||||
|
diffoff!
|
||||||
|
redraw
|
||||||
|
call assert_equal(normattr, screenattr(1, 1))
|
||||||
|
diffthis
|
||||||
|
redraw
|
||||||
|
" no longer diffing with hidden buffer two
|
||||||
|
call assert_equal(normattr, screenattr(1, 1))
|
||||||
|
|
||||||
|
bwipe!
|
||||||
|
bwipe!
|
||||||
|
set hidden& diffopt&
|
||||||
|
endfunc
|
||||||
|
|
||||||
func Test_setting_cursor()
|
func Test_setting_cursor()
|
||||||
new Xtest1
|
new Xtest1
|
||||||
put =range(1,90)
|
put =range(1,90)
|
||||||
|
@ -89,17 +89,8 @@ func s:doc_config_teardown()
|
|||||||
endif
|
endif
|
||||||
endfunc
|
endfunc
|
||||||
|
|
||||||
func s:get_cmd_compl_list(cmd)
|
func s:get_help_compl_list(cmd)
|
||||||
let list = []
|
return getcompletion(a:cmd, 'help')
|
||||||
let str = ''
|
|
||||||
for cnt in range(1, 999)
|
|
||||||
call feedkeys(a:cmd . repeat("\<Tab>", cnt) . "'\<C-B>let str='\<CR>", 'tx')
|
|
||||||
if str ==# a:cmd[1:]
|
|
||||||
break
|
|
||||||
endif
|
|
||||||
call add(list, str)
|
|
||||||
endfor
|
|
||||||
return list
|
|
||||||
endfunc
|
endfunc
|
||||||
|
|
||||||
func Test_help_complete()
|
func Test_help_complete()
|
||||||
@ -111,49 +102,49 @@ func Test_help_complete()
|
|||||||
if has('multi_lang')
|
if has('multi_lang')
|
||||||
set helplang=
|
set helplang=
|
||||||
endif
|
endif
|
||||||
let list = s:get_cmd_compl_list(":h test")
|
let list = s:get_help_compl_list("test")
|
||||||
call assert_equal(['h test-col', 'h test-char'], list)
|
call assert_equal(['test-col', 'test-char'], list)
|
||||||
|
|
||||||
if has('multi_lang')
|
if has('multi_lang')
|
||||||
" 'helplang=ab' and help file lang is 'en'
|
" 'helplang=ab' and help file lang is 'en'
|
||||||
set helplang=ab
|
set helplang=ab
|
||||||
let list = s:get_cmd_compl_list(":h test")
|
let list = s:get_help_compl_list("test")
|
||||||
call assert_equal(['h test-col', 'h test-char'], list)
|
call assert_equal(['test-col', 'test-char'], list)
|
||||||
|
|
||||||
" 'helplang=' and help file lang is 'en' and 'ab'
|
" 'helplang=' and help file lang is 'en' and 'ab'
|
||||||
set rtp+=Xdir1/doc-ab
|
set rtp+=Xdir1/doc-ab
|
||||||
set helplang=
|
set helplang=
|
||||||
let list = s:get_cmd_compl_list(":h test")
|
let list = s:get_help_compl_list("test")
|
||||||
call assert_equal(sort(['h test-col@en', 'h test-col@ab',
|
call assert_equal(sort(['test-col@en', 'test-col@ab',
|
||||||
\ 'h test-char@en', 'h test-char@ab']), sort(list))
|
\ 'test-char@en', 'test-char@ab']), sort(list))
|
||||||
|
|
||||||
" 'helplang=ab' and help file lang is 'en' and 'ab'
|
" 'helplang=ab' and help file lang is 'en' and 'ab'
|
||||||
set helplang=ab
|
set helplang=ab
|
||||||
let list = s:get_cmd_compl_list(":h test")
|
let list = s:get_help_compl_list("test")
|
||||||
call assert_equal(sort(['h test-col', 'h test-col@en',
|
call assert_equal(sort(['test-col', 'test-col@en',
|
||||||
\ 'h test-char', 'h test-char@en']), sort(list))
|
\ 'test-char', 'test-char@en']), sort(list))
|
||||||
|
|
||||||
" 'helplang=' and help file lang is 'en', 'ab' and 'ja'
|
" 'helplang=' and help file lang is 'en', 'ab' and 'ja'
|
||||||
set rtp+=Xdir1/doc-ja
|
set rtp+=Xdir1/doc-ja
|
||||||
set helplang=
|
set helplang=
|
||||||
let list = s:get_cmd_compl_list(":h test")
|
let list = s:get_help_compl_list("test")
|
||||||
call assert_equal(sort(['h test-col@en', 'h test-col@ab',
|
call assert_equal(sort(['test-col@en', 'test-col@ab',
|
||||||
\ 'h test-col@ja', 'h test-char@en',
|
\ 'test-col@ja', 'test-char@en',
|
||||||
\ 'h test-char@ab', 'h test-char@ja']), sort(list))
|
\ 'test-char@ab', 'test-char@ja']), sort(list))
|
||||||
|
|
||||||
" 'helplang=ab' and help file lang is 'en', 'ab' and 'ja'
|
" 'helplang=ab' and help file lang is 'en', 'ab' and 'ja'
|
||||||
set helplang=ab
|
set helplang=ab
|
||||||
let list = s:get_cmd_compl_list(":h test")
|
let list = s:get_help_compl_list("test")
|
||||||
call assert_equal(sort(['h test-col', 'h test-col@en',
|
call assert_equal(sort(['test-col', 'test-col@en',
|
||||||
\ 'h test-col@ja', 'h test-char',
|
\ 'test-col@ja', 'test-char',
|
||||||
\ 'h test-char@en', 'h test-char@ja']), sort(list))
|
\ 'test-char@en', 'test-char@ja']), sort(list))
|
||||||
|
|
||||||
" 'helplang=ab,ja' and help file lang is 'en', 'ab' and 'ja'
|
" 'helplang=ab,ja' and help file lang is 'en', 'ab' and 'ja'
|
||||||
set helplang=ab,ja
|
set helplang=ab,ja
|
||||||
let list = s:get_cmd_compl_list(":h test")
|
let list = s:get_help_compl_list("test")
|
||||||
call assert_equal(sort(['h test-col', 'h test-col@ja',
|
call assert_equal(sort(['test-col', 'test-col@ja',
|
||||||
\ 'h test-col@en', 'h test-char',
|
\ 'test-col@en', 'test-char',
|
||||||
\ 'h test-char@ja', 'h test-char@en']), sort(list))
|
\ 'test-char@ja', 'test-char@en']), sort(list))
|
||||||
endif
|
endif
|
||||||
catch
|
catch
|
||||||
call assert_exception('X')
|
call assert_exception('X')
|
||||||
|
155
src/nvim/testdir/test_mksession.vim
Normal file
155
src/nvim/testdir/test_mksession.vim
Normal file
@ -0,0 +1,155 @@
|
|||||||
|
" Test for :mksession, :mkview and :loadview in latin1 encoding
|
||||||
|
|
||||||
|
scriptencoding latin1
|
||||||
|
|
||||||
|
if !has('multi_byte') || !has('mksession')
|
||||||
|
finish
|
||||||
|
endif
|
||||||
|
|
||||||
|
func Test_mksession()
|
||||||
|
tabnew
|
||||||
|
let wrap_save = &wrap
|
||||||
|
set sessionoptions=buffers splitbelow fileencoding=latin1
|
||||||
|
call setline(1, [
|
||||||
|
\ 'start:',
|
||||||
|
\ 'no multibyte chAracter',
|
||||||
|
\ ' one leaDing tab',
|
||||||
|
\ ' four leadinG spaces',
|
||||||
|
\ 'two consecutive tabs',
|
||||||
|
\ 'two tabs in one line',
|
||||||
|
\ 'one ä multibyteCharacter',
|
||||||
|
\ 'aä Ä two multiByte characters',
|
||||||
|
\ 'Aäöü three mulTibyte characters'
|
||||||
|
\ ])
|
||||||
|
let tmpfile = 'Xtemp'
|
||||||
|
exec 'w! ' . tmpfile
|
||||||
|
/^start:
|
||||||
|
set wrap
|
||||||
|
vsplit
|
||||||
|
norm! j16|
|
||||||
|
split
|
||||||
|
norm! j16|
|
||||||
|
split
|
||||||
|
norm! j16|
|
||||||
|
split
|
||||||
|
norm! j8|
|
||||||
|
split
|
||||||
|
norm! j8|
|
||||||
|
split
|
||||||
|
norm! j16|
|
||||||
|
split
|
||||||
|
norm! j16|
|
||||||
|
split
|
||||||
|
norm! j16|
|
||||||
|
wincmd l
|
||||||
|
|
||||||
|
set nowrap
|
||||||
|
/^start:
|
||||||
|
norm! j16|3zl
|
||||||
|
split
|
||||||
|
norm! j016|3zl
|
||||||
|
split
|
||||||
|
norm! j016|3zl
|
||||||
|
split
|
||||||
|
norm! j08|3zl
|
||||||
|
split
|
||||||
|
norm! j08|3zl
|
||||||
|
split
|
||||||
|
norm! j016|3zl
|
||||||
|
split
|
||||||
|
norm! j016|3zl
|
||||||
|
split
|
||||||
|
norm! j016|3zl
|
||||||
|
split
|
||||||
|
call wincol()
|
||||||
|
mksession! Xtest_mks.out
|
||||||
|
let li = filter(readfile('Xtest_mks.out'), 'v:val =~# "\\(^ *normal! 0\\|^ *exe ''normal!\\)"')
|
||||||
|
let expected = [
|
||||||
|
\ 'normal! 016|',
|
||||||
|
\ 'normal! 016|',
|
||||||
|
\ 'normal! 016|',
|
||||||
|
\ 'normal! 08|',
|
||||||
|
\ 'normal! 08|',
|
||||||
|
\ 'normal! 016|',
|
||||||
|
\ 'normal! 016|',
|
||||||
|
\ 'normal! 016|',
|
||||||
|
\ " exe 'normal! ' . s:c . '|zs' . 16 . '|'",
|
||||||
|
\ " normal! 016|",
|
||||||
|
\ " exe 'normal! ' . s:c . '|zs' . 16 . '|'",
|
||||||
|
\ " normal! 016|",
|
||||||
|
\ " exe 'normal! ' . s:c . '|zs' . 16 . '|'",
|
||||||
|
\ " normal! 016|",
|
||||||
|
\ " exe 'normal! ' . s:c . '|zs' . 8 . '|'",
|
||||||
|
\ " normal! 08|",
|
||||||
|
\ " exe 'normal! ' . s:c . '|zs' . 8 . '|'",
|
||||||
|
\ " normal! 08|",
|
||||||
|
\ " exe 'normal! ' . s:c . '|zs' . 16 . '|'",
|
||||||
|
\ " normal! 016|",
|
||||||
|
\ " exe 'normal! ' . s:c . '|zs' . 16 . '|'",
|
||||||
|
\ " normal! 016|",
|
||||||
|
\ " exe 'normal! ' . s:c . '|zs' . 16 . '|'",
|
||||||
|
\ " normal! 016|",
|
||||||
|
\ " exe 'normal! ' . s:c . '|zs' . 16 . '|'",
|
||||||
|
\ " normal! 016|"
|
||||||
|
\ ]
|
||||||
|
call assert_equal(expected, li)
|
||||||
|
tabclose!
|
||||||
|
|
||||||
|
call delete('Xtest_mks.out')
|
||||||
|
call delete(tmpfile)
|
||||||
|
let &wrap = wrap_save
|
||||||
|
endfunc
|
||||||
|
|
||||||
|
func Test_mksession_winheight()
|
||||||
|
new
|
||||||
|
set winheight=10 winminheight=2
|
||||||
|
mksession! Xtest_mks.out
|
||||||
|
source Xtest_mks.out
|
||||||
|
|
||||||
|
call delete('Xtest_mks.out')
|
||||||
|
endfunc
|
||||||
|
|
||||||
|
" Verify that arglist is stored correctly to the session file.
|
||||||
|
func Test_mksession_arglist()
|
||||||
|
argdel *
|
||||||
|
next file1 file2 file3 file4
|
||||||
|
mksession! Xtest_mks.out
|
||||||
|
source Xtest_mks.out
|
||||||
|
call assert_equal(['file1', 'file2', 'file3', 'file4'], argv())
|
||||||
|
|
||||||
|
call delete('Xtest_mks.out')
|
||||||
|
argdel *
|
||||||
|
endfunc
|
||||||
|
|
||||||
|
|
||||||
|
func Test_mksession_one_buffer_two_windows()
|
||||||
|
edit Xtest1
|
||||||
|
new Xtest2
|
||||||
|
split
|
||||||
|
mksession! Xtest_mks.out
|
||||||
|
let lines = readfile('Xtest_mks.out')
|
||||||
|
let count1 = 0
|
||||||
|
let count2 = 0
|
||||||
|
let count2buf = 0
|
||||||
|
for line in lines
|
||||||
|
if line =~ 'edit \f*Xtest1$'
|
||||||
|
let count1 += 1
|
||||||
|
endif
|
||||||
|
if line =~ 'edit \f\{-}Xtest2'
|
||||||
|
let count2 += 1
|
||||||
|
endif
|
||||||
|
if line =~ 'buffer \f\{-}Xtest2'
|
||||||
|
let count2buf += 1
|
||||||
|
endif
|
||||||
|
endfor
|
||||||
|
call assert_equal(1, count1, 'Xtest1 count')
|
||||||
|
call assert_equal(2, count2, 'Xtest2 count')
|
||||||
|
call assert_equal(2, count2buf, 'Xtest2 buffer count')
|
||||||
|
|
||||||
|
close
|
||||||
|
bwipe!
|
||||||
|
call delete('Xtest_mks.out')
|
||||||
|
endfunc
|
||||||
|
|
||||||
|
|
||||||
|
" vim: shiftwidth=2 sts=2 expandtab
|
104
src/nvim/testdir/test_mksession_utf8.vim
Normal file
104
src/nvim/testdir/test_mksession_utf8.vim
Normal file
@ -0,0 +1,104 @@
|
|||||||
|
" Test for :mksession, :mkview and :loadview in utf-8 encoding
|
||||||
|
|
||||||
|
set encoding=utf-8
|
||||||
|
scriptencoding utf-8
|
||||||
|
|
||||||
|
if !has('multi_byte') || !has('mksession')
|
||||||
|
finish
|
||||||
|
endif
|
||||||
|
|
||||||
|
func Test_mksession_utf8()
|
||||||
|
tabnew
|
||||||
|
let wrap_save = &wrap
|
||||||
|
set sessionoptions=buffers splitbelow fileencoding=utf-8
|
||||||
|
call setline(1, [
|
||||||
|
\ 'start:',
|
||||||
|
\ 'no multibyte chAracter',
|
||||||
|
\ ' one leaDing tab',
|
||||||
|
\ ' four leadinG spaces',
|
||||||
|
\ 'two consecutive tabs',
|
||||||
|
\ 'two tabs in one line',
|
||||||
|
\ 'one … multibyteCharacter',
|
||||||
|
\ 'a “b” two multiByte characters',
|
||||||
|
\ '“c”1€ three mulTibyte characters'
|
||||||
|
\ ])
|
||||||
|
let tmpfile = tempname()
|
||||||
|
exec 'w! ' . tmpfile
|
||||||
|
/^start:
|
||||||
|
set wrap
|
||||||
|
vsplit
|
||||||
|
norm! j16|
|
||||||
|
split
|
||||||
|
norm! j16|
|
||||||
|
split
|
||||||
|
norm! j16|
|
||||||
|
split
|
||||||
|
norm! j8|
|
||||||
|
split
|
||||||
|
norm! j8|
|
||||||
|
split
|
||||||
|
norm! j16|
|
||||||
|
split
|
||||||
|
norm! j16|
|
||||||
|
split
|
||||||
|
norm! j16|
|
||||||
|
wincmd l
|
||||||
|
|
||||||
|
set nowrap
|
||||||
|
/^start:
|
||||||
|
norm! j16|3zl
|
||||||
|
split
|
||||||
|
norm! j016|3zl
|
||||||
|
split
|
||||||
|
norm! j016|3zl
|
||||||
|
split
|
||||||
|
norm! j08|3zl
|
||||||
|
split
|
||||||
|
norm! j08|3zl
|
||||||
|
split
|
||||||
|
norm! j016|3zl
|
||||||
|
split
|
||||||
|
norm! j016|3zl
|
||||||
|
split
|
||||||
|
norm! j016|3zl
|
||||||
|
split
|
||||||
|
call wincol()
|
||||||
|
mksession! test_mks.out
|
||||||
|
let li = filter(readfile('test_mks.out'), 'v:val =~# "\\(^ *normal! 0\\|^ *exe ''normal!\\)"')
|
||||||
|
let expected = [
|
||||||
|
\ 'normal! 016|',
|
||||||
|
\ 'normal! 016|',
|
||||||
|
\ 'normal! 016|',
|
||||||
|
\ 'normal! 08|',
|
||||||
|
\ 'normal! 08|',
|
||||||
|
\ 'normal! 016|',
|
||||||
|
\ 'normal! 016|',
|
||||||
|
\ 'normal! 016|',
|
||||||
|
\ " exe 'normal! ' . s:c . '|zs' . 16 . '|'",
|
||||||
|
\ " normal! 016|",
|
||||||
|
\ " exe 'normal! ' . s:c . '|zs' . 16 . '|'",
|
||||||
|
\ " normal! 016|",
|
||||||
|
\ " exe 'normal! ' . s:c . '|zs' . 16 . '|'",
|
||||||
|
\ " normal! 016|",
|
||||||
|
\ " exe 'normal! ' . s:c . '|zs' . 8 . '|'",
|
||||||
|
\ " normal! 08|",
|
||||||
|
\ " exe 'normal! ' . s:c . '|zs' . 8 . '|'",
|
||||||
|
\ " normal! 08|",
|
||||||
|
\ " exe 'normal! ' . s:c . '|zs' . 16 . '|'",
|
||||||
|
\ " normal! 016|",
|
||||||
|
\ " exe 'normal! ' . s:c . '|zs' . 16 . '|'",
|
||||||
|
\ " normal! 016|",
|
||||||
|
\ " exe 'normal! ' . s:c . '|zs' . 16 . '|'",
|
||||||
|
\ " normal! 016|",
|
||||||
|
\ " exe 'normal! ' . s:c . '|zs' . 16 . '|'",
|
||||||
|
\ " normal! 016|"
|
||||||
|
\ ]
|
||||||
|
call assert_equal(expected, li)
|
||||||
|
tabclose!
|
||||||
|
|
||||||
|
call delete('test_mks.out')
|
||||||
|
call delete(tmpfile)
|
||||||
|
let &wrap = wrap_save
|
||||||
|
endfunc
|
||||||
|
|
||||||
|
" vim: shiftwidth=2 sts=2 expandtab
|
@ -13,6 +13,12 @@ function! Test_whichwrap()
|
|||||||
set whichwrap+=h,l
|
set whichwrap+=h,l
|
||||||
call assert_equal('b,s,h,l', &whichwrap)
|
call assert_equal('b,s,h,l', &whichwrap)
|
||||||
|
|
||||||
|
set whichwrap=h,h
|
||||||
|
call assert_equal('h', &whichwrap)
|
||||||
|
|
||||||
|
set whichwrap=h,h,h
|
||||||
|
call assert_equal('h', &whichwrap)
|
||||||
|
|
||||||
set whichwrap&
|
set whichwrap&
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
@ -97,3 +103,13 @@ func Test_keymap_valid()
|
|||||||
call assert_fails(":set kmp=trunc\x00name", "E544:")
|
call assert_fails(":set kmp=trunc\x00name", "E544:")
|
||||||
call assert_fails(":set kmp=trunc\x00name", "trunc")
|
call assert_fails(":set kmp=trunc\x00name", "trunc")
|
||||||
endfunc
|
endfunc
|
||||||
|
|
||||||
|
func Test_complete()
|
||||||
|
" Trailing single backslash used to cause invalid memory access.
|
||||||
|
set complete=s\
|
||||||
|
new
|
||||||
|
call feedkeys("i\<C-N>\<Esc>", 'xt')
|
||||||
|
bwipe!
|
||||||
|
set complete&
|
||||||
|
endfun
|
||||||
|
|
||||||
|
@ -7,10 +7,10 @@ func! ListMonths()
|
|||||||
if g:setting != ''
|
if g:setting != ''
|
||||||
exe ":set" g:setting
|
exe ":set" g:setting
|
||||||
endif
|
endif
|
||||||
let mth=copy(g:months)
|
let mth = copy(g:months)
|
||||||
let entered = strcharpart(getline('.'),0,col('.'))
|
let entered = strcharpart(getline('.'),0,col('.'))
|
||||||
if !empty(entered)
|
if !empty(entered)
|
||||||
let mth=filter(mth, 'v:val=~"^".entered')
|
let mth = filter(mth, 'v:val=~"^".entered')
|
||||||
endif
|
endif
|
||||||
call complete(1, mth)
|
call complete(1, mth)
|
||||||
return ''
|
return ''
|
||||||
@ -468,7 +468,7 @@ endfunc
|
|||||||
" auto-wrap text.
|
" auto-wrap text.
|
||||||
func Test_completion_ctrl_e_without_autowrap()
|
func Test_completion_ctrl_e_without_autowrap()
|
||||||
new
|
new
|
||||||
let tw_save=&tw
|
let tw_save = &tw
|
||||||
set tw=78
|
set tw=78
|
||||||
let li = [
|
let li = [
|
||||||
\ '" zzz',
|
\ '" zzz',
|
||||||
@ -478,7 +478,7 @@ func Test_completion_ctrl_e_without_autowrap()
|
|||||||
call feedkeys("A\<C-X>\<C-N>\<C-E>\<Esc>", "tx")
|
call feedkeys("A\<C-X>\<C-N>\<C-E>\<Esc>", "tx")
|
||||||
call assert_equal(li, getline(1, '$'))
|
call assert_equal(li, getline(1, '$'))
|
||||||
|
|
||||||
let &tw=tw_save
|
let &tw = tw_save
|
||||||
q!
|
q!
|
||||||
endfunc
|
endfunc
|
||||||
|
|
||||||
@ -541,4 +541,33 @@ func Test_completion_comment_formatting()
|
|||||||
bwipe!
|
bwipe!
|
||||||
endfunc
|
endfunc
|
||||||
|
|
||||||
|
function! DummyCompleteSix()
|
||||||
|
call complete(1, ['Hello', 'World'])
|
||||||
|
return ''
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
" complete() correctly clears the list of autocomplete candidates
|
||||||
|
func Test_completion_clear_candidate_list()
|
||||||
|
new
|
||||||
|
%d
|
||||||
|
" select first entry from the completion popup
|
||||||
|
call feedkeys("a xxx\<C-N>\<C-R>=DummyCompleteSix()\<CR>", "tx")
|
||||||
|
call assert_equal('Hello', getline(1))
|
||||||
|
%d
|
||||||
|
" select second entry from the completion popup
|
||||||
|
call feedkeys("a xxx\<C-N>\<C-R>=DummyCompleteSix()\<CR>\<C-N>", "tx")
|
||||||
|
call assert_equal('World', getline(1))
|
||||||
|
%d
|
||||||
|
" select original text
|
||||||
|
call feedkeys("a xxx\<C-N>\<C-R>=DummyCompleteSix()\<CR>\<C-N>\<C-N>", "tx")
|
||||||
|
call assert_equal(' xxx', getline(1))
|
||||||
|
%d
|
||||||
|
" back at first entry from completion list
|
||||||
|
call feedkeys("a xxx\<C-N>\<C-R>=DummyCompleteSix()\<CR>\<C-N>\<C-N>\<C-N>", "tx")
|
||||||
|
call assert_equal('Hello', getline(1))
|
||||||
|
|
||||||
|
bw!
|
||||||
|
endfunc
|
||||||
|
|
||||||
|
|
||||||
" vim: shiftwidth=2 sts=2 expandtab
|
" vim: shiftwidth=2 sts=2 expandtab
|
||||||
|
@ -24,28 +24,34 @@ func Test_after_comes_later()
|
|||||||
\ 'set guioptions+=M',
|
\ 'set guioptions+=M',
|
||||||
\ 'let $HOME = "/does/not/exist"',
|
\ 'let $HOME = "/does/not/exist"',
|
||||||
\ 'set loadplugins',
|
\ 'set loadplugins',
|
||||||
\ 'set rtp=Xhere,Xafter',
|
\ 'set rtp=Xhere,Xafter,Xanother',
|
||||||
\ 'set packpath=Xhere,Xafter',
|
\ 'set packpath=Xhere,Xafter',
|
||||||
\ 'set nomore',
|
\ 'set nomore',
|
||||||
|
\ 'let g:sequence = ""',
|
||||||
\ ]
|
\ ]
|
||||||
let after = [
|
let after = [
|
||||||
\ 'redir! > Xtestout',
|
\ 'redir! > Xtestout',
|
||||||
\ 'scriptnames',
|
\ 'scriptnames',
|
||||||
\ 'redir END',
|
\ 'redir END',
|
||||||
|
\ 'redir! > Xsequence',
|
||||||
|
\ 'echo g:sequence',
|
||||||
|
\ 'redir END',
|
||||||
\ 'quit',
|
\ 'quit',
|
||||||
\ ]
|
\ ]
|
||||||
call mkdir('Xhere/plugin', 'p')
|
call mkdir('Xhere/plugin', 'p')
|
||||||
call writefile(['let done = 1'], 'Xhere/plugin/here.vim')
|
call writefile(['let g:sequence .= "here "'], 'Xhere/plugin/here.vim')
|
||||||
|
call mkdir('Xanother/plugin', 'p')
|
||||||
|
call writefile(['let g:sequence .= "another "'], 'Xanother/plugin/another.vim')
|
||||||
call mkdir('Xhere/pack/foo/start/foobar/plugin', 'p')
|
call mkdir('Xhere/pack/foo/start/foobar/plugin', 'p')
|
||||||
call writefile(['let done = 1'], 'Xhere/pack/foo/start/foobar/plugin/foo.vim')
|
call writefile(['let g:sequence .= "pack "'], 'Xhere/pack/foo/start/foobar/plugin/foo.vim')
|
||||||
|
|
||||||
call mkdir('Xafter/plugin', 'p')
|
call mkdir('Xafter/plugin', 'p')
|
||||||
call writefile(['let done = 1'], 'Xafter/plugin/later.vim')
|
call writefile(['let g:sequence .= "after "'], 'Xafter/plugin/later.vim')
|
||||||
|
|
||||||
if RunVim(before, after, '')
|
if RunVim(before, after, '')
|
||||||
|
|
||||||
let lines = readfile('Xtestout')
|
let lines = readfile('Xtestout')
|
||||||
let expected = ['Xbefore.vim', 'here.vim', 'foo.vim', 'later.vim', 'Xafter.vim']
|
let expected = ['Xbefore.vim', 'here.vim', 'another.vim', 'foo.vim', 'later.vim', 'Xafter.vim']
|
||||||
let found = []
|
let found = []
|
||||||
for line in lines
|
for line in lines
|
||||||
for one in expected
|
for one in expected
|
||||||
@ -57,9 +63,45 @@ func Test_after_comes_later()
|
|||||||
call assert_equal(expected, found)
|
call assert_equal(expected, found)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
call assert_equal('here another pack after', substitute(join(readfile('Xsequence', 1), ''), '\s\+$', '', ''))
|
||||||
|
|
||||||
|
call delete('Xtestout')
|
||||||
|
call delete('Xsequence')
|
||||||
|
call delete('Xhere', 'rf')
|
||||||
|
call delete('Xanother', 'rf')
|
||||||
|
call delete('Xafter', 'rf')
|
||||||
|
endfunc
|
||||||
|
|
||||||
|
func Test_pack_in_rtp_when_plugins_run()
|
||||||
|
if !has('packages')
|
||||||
|
return
|
||||||
|
endif
|
||||||
|
let before = [
|
||||||
|
\ 'set nocp viminfo+=nviminfo',
|
||||||
|
\ 'set guioptions+=M',
|
||||||
|
\ 'let $HOME = "/does/not/exist"',
|
||||||
|
\ 'set loadplugins',
|
||||||
|
\ 'set rtp=Xhere',
|
||||||
|
\ 'set packpath=Xhere',
|
||||||
|
\ 'set nomore',
|
||||||
|
\ ]
|
||||||
|
let after = [
|
||||||
|
\ 'quit',
|
||||||
|
\ ]
|
||||||
|
call mkdir('Xhere/plugin', 'p')
|
||||||
|
call writefile(['redir! > Xtestout', 'silent set runtimepath?', 'silent! call foo#Trigger()', 'redir END'], 'Xhere/plugin/here.vim')
|
||||||
|
call mkdir('Xhere/pack/foo/start/foobar/autoload', 'p')
|
||||||
|
call writefile(['function! foo#Trigger()', 'echo "autoloaded foo"', 'endfunction'], 'Xhere/pack/foo/start/foobar/autoload/foo.vim')
|
||||||
|
|
||||||
|
if RunVim(before, after, '')
|
||||||
|
|
||||||
|
let lines = filter(readfile('Xtestout'), '!empty(v:val)')
|
||||||
|
call assert_match('Xhere[/\\]pack[/\\]foo[/\\]start[/\\]foobar', get(lines, 0))
|
||||||
|
call assert_match('autoloaded foo', get(lines, 1))
|
||||||
|
endif
|
||||||
|
|
||||||
call delete('Xtestout')
|
call delete('Xtestout')
|
||||||
call delete('Xhere', 'rf')
|
call delete('Xhere', 'rf')
|
||||||
call delete('Xafter', 'rf')
|
|
||||||
endfunc
|
endfunc
|
||||||
|
|
||||||
func Test_help_arg()
|
func Test_help_arg()
|
||||||
@ -76,11 +118,11 @@ func Test_help_arg()
|
|||||||
let found = []
|
let found = []
|
||||||
for line in lines
|
for line in lines
|
||||||
if line =~ '-R.*Read-only mode'
|
if line =~ '-R.*Read-only mode'
|
||||||
call add(found, 'Readonly mode')
|
call add(found, 'Readonly mode')
|
||||||
endif
|
endif
|
||||||
" Watch out for a second --version line in the Gnome version.
|
" Watch out for a second --version line in the Gnome version.
|
||||||
if line =~ '--version.*Print version information and exit'
|
if line =~ '--version.*Print version information'
|
||||||
call add(found, "--version")
|
call add(found, "--version")
|
||||||
endif
|
endif
|
||||||
endfor
|
endfor
|
||||||
call assert_equal(['Readonly mode', '--version'], found)
|
call assert_equal(['Readonly mode', '--version'], found)
|
||||||
|
@ -50,7 +50,7 @@ func Test_syn_iskeyword()
|
|||||||
setlocal isk-=_
|
setlocal isk-=_
|
||||||
call assert_equal('DLTD_BY', GetSyntaxItem('DLTD'))
|
call assert_equal('DLTD_BY', GetSyntaxItem('DLTD'))
|
||||||
/\<D\k\+\>/:norm! ygn
|
/\<D\k\+\>/:norm! ygn
|
||||||
let b2=@0
|
let b2 = @0
|
||||||
call assert_equal('DLTD', @0)
|
call assert_equal('DLTD', @0)
|
||||||
|
|
||||||
syn iskeyword clear
|
syn iskeyword clear
|
||||||
@ -76,3 +76,85 @@ func Test_syntax_after_reload()
|
|||||||
call assert_true(exists('g:gotit'))
|
call assert_true(exists('g:gotit'))
|
||||||
call delete('Xsomefile')
|
call delete('Xsomefile')
|
||||||
endfunc
|
endfunc
|
||||||
|
|
||||||
|
func Test_syntime()
|
||||||
|
if !has('profile')
|
||||||
|
return
|
||||||
|
endif
|
||||||
|
|
||||||
|
syntax on
|
||||||
|
syntime on
|
||||||
|
let a = execute('syntime report')
|
||||||
|
call assert_equal("\nNo Syntax items defined for this buffer", a)
|
||||||
|
|
||||||
|
view ../memfile_test.c
|
||||||
|
setfiletype cpp
|
||||||
|
redraw
|
||||||
|
let a = execute('syntime report')
|
||||||
|
call assert_match('^ TOTAL *COUNT *MATCH *SLOWEST *AVERAGE *NAME *PATTERN', a)
|
||||||
|
call assert_match(' \d*\.\d* \+[^0]\d* .* cppRawString ', a)
|
||||||
|
call assert_match(' \d*\.\d* \+[^0]\d* .* cppNumber ', a)
|
||||||
|
|
||||||
|
syntime off
|
||||||
|
syntime clear
|
||||||
|
let a = execute('syntime report')
|
||||||
|
call assert_match('^ TOTAL *COUNT *MATCH *SLOWEST *AVERAGE *NAME *PATTERN', a)
|
||||||
|
call assert_notmatch('.* cppRawString *', a)
|
||||||
|
call assert_notmatch('.* cppNumber*', a)
|
||||||
|
call assert_notmatch('[1-9]', a)
|
||||||
|
|
||||||
|
call assert_fails('syntime abc', 'E475')
|
||||||
|
|
||||||
|
syntax clear
|
||||||
|
let a = execute('syntime report')
|
||||||
|
call assert_equal("\nNo Syntax items defined for this buffer", a)
|
||||||
|
|
||||||
|
bd
|
||||||
|
endfunc
|
||||||
|
|
||||||
|
func Test_syntax_list()
|
||||||
|
syntax on
|
||||||
|
let a = execute('syntax list')
|
||||||
|
call assert_equal("\nNo Syntax items defined for this buffer", a)
|
||||||
|
|
||||||
|
view ../memfile_test.c
|
||||||
|
setfiletype c
|
||||||
|
|
||||||
|
let a = execute('syntax list')
|
||||||
|
call assert_match('cInclude*', a)
|
||||||
|
call assert_match('cDefine', a)
|
||||||
|
|
||||||
|
let a = execute('syntax list cDefine')
|
||||||
|
call assert_notmatch('cInclude*', a)
|
||||||
|
call assert_match('cDefine', a)
|
||||||
|
call assert_match(' links to Macro$', a)
|
||||||
|
|
||||||
|
call assert_fails('syntax list ABCD', 'E28:')
|
||||||
|
call assert_fails('syntax list @ABCD', 'E392:')
|
||||||
|
|
||||||
|
syntax clear
|
||||||
|
let a = execute('syntax list')
|
||||||
|
call assert_equal("\nNo Syntax items defined for this buffer", a)
|
||||||
|
|
||||||
|
bd
|
||||||
|
endfunc
|
||||||
|
|
||||||
|
func Test_syntax_completion()
|
||||||
|
call feedkeys(":syn \<C-A>\<C-B>\"\<CR>", 'tx')
|
||||||
|
call assert_equal('"syn case clear cluster conceal enable include iskeyword keyword list manual match off on region reset spell sync', @:)
|
||||||
|
|
||||||
|
call feedkeys(":syn case \<C-A>\<C-B>\"\<CR>", 'tx')
|
||||||
|
call assert_equal('"syn case ignore match', @:)
|
||||||
|
|
||||||
|
call feedkeys(":syn spell \<C-A>\<C-B>\"\<CR>", 'tx')
|
||||||
|
call assert_equal('"syn spell default notoplevel toplevel', @:)
|
||||||
|
|
||||||
|
call feedkeys(":syn sync \<C-A>\<C-B>\"\<CR>", 'tx')
|
||||||
|
call assert_equal('"syn sync ccomment clear fromstart linebreaks= linecont lines= match maxlines= minlines= region', @:)
|
||||||
|
|
||||||
|
call feedkeys(":syn list \<C-A>\<C-B>\"\<CR>", 'tx')
|
||||||
|
call assert_match('^"syn list Boolean Character ', @:)
|
||||||
|
|
||||||
|
call feedkeys(":syn match \<C-A>\<C-B>\"\<CR>", 'tx')
|
||||||
|
call assert_match('^"syn match Boolean Character ', @:)
|
||||||
|
endfunc
|
@ -15,3 +15,23 @@ func Test_block_shift_multibyte()
|
|||||||
call assert_equal(' ヹxxx', getline(2))
|
call assert_equal(' ヹxxx', getline(2))
|
||||||
q!
|
q!
|
||||||
endfunc
|
endfunc
|
||||||
|
|
||||||
|
func Test_Visual_ctrl_o()
|
||||||
|
new
|
||||||
|
call setline(1, ['one', 'two', 'three'])
|
||||||
|
call cursor(1,2)
|
||||||
|
set noshowmode
|
||||||
|
set tw=0
|
||||||
|
call feedkeys("\<c-v>jjlIa\<c-\>\<c-o>:set tw=88\<cr>\<esc>", 'tx')
|
||||||
|
call assert_equal(['oane', 'tawo', 'tahree'], getline(1, 3))
|
||||||
|
call assert_equal(88, &tw)
|
||||||
|
set tw&
|
||||||
|
bw!
|
||||||
|
endfu
|
||||||
|
|
||||||
|
func Test_Visual_vapo()
|
||||||
|
new
|
||||||
|
normal oxx
|
||||||
|
normal vapo
|
||||||
|
bwipe!
|
||||||
|
endfunc
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
#include "nvim/api/private/helpers.h"
|
#include "nvim/api/private/helpers.h"
|
||||||
#include "nvim/ascii.h"
|
#include "nvim/ascii.h"
|
||||||
#include "nvim/main.h"
|
#include "nvim/main.h"
|
||||||
|
#include "nvim/aucmd.h"
|
||||||
#include "nvim/os/os.h"
|
#include "nvim/os/os.h"
|
||||||
#include "nvim/os/input.h"
|
#include "nvim/os/input.h"
|
||||||
#include "nvim/event/rstream.h"
|
#include "nvim/event/rstream.h"
|
||||||
@ -280,9 +281,9 @@ static void timer_cb(TimeWatcher *watcher, void *data)
|
|||||||
|
|
||||||
/// Handle focus events.
|
/// Handle focus events.
|
||||||
///
|
///
|
||||||
/// If the upcoming sequence of bytes in the input stream matches either the
|
/// If the upcoming sequence of bytes in the input stream matches the termcode
|
||||||
/// escape code for focus gained `<ESC>[I` or focus lost `<ESC>[O` then consume
|
/// for "focus gained" or "focus lost", consume that sequence and schedule an
|
||||||
/// that sequence and push the appropriate event into the input queue
|
/// event on the main loop.
|
||||||
///
|
///
|
||||||
/// @param input the input stream
|
/// @param input the input stream
|
||||||
/// @return true iff handle_focus_event consumed some input
|
/// @return true iff handle_focus_event consumed some input
|
||||||
@ -294,11 +295,7 @@ static bool handle_focus_event(TermInput *input)
|
|||||||
// Advance past the sequence
|
// Advance past the sequence
|
||||||
bool focus_gained = *rbuffer_get(input->read_stream.buffer, 2) == 'I';
|
bool focus_gained = *rbuffer_get(input->read_stream.buffer, 2) == 'I';
|
||||||
rbuffer_consumed(input->read_stream.buffer, 3);
|
rbuffer_consumed(input->read_stream.buffer, 3);
|
||||||
if (focus_gained) {
|
aucmd_schedule_focusgained(focus_gained);
|
||||||
enqueue_input(input, FOCUSGAINED_KEY, sizeof(FOCUSGAINED_KEY) - 1);
|
|
||||||
} else {
|
|
||||||
enqueue_input(input, FOCUSLOST_KEY, sizeof(FOCUSLOST_KEY) - 1);
|
|
||||||
}
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
@ -104,7 +104,9 @@ unibi_term *load_builtin_terminfo(const char * term)
|
|||||||
return unibi_from_mem((const char *)interix_8colour_terminfo,
|
return unibi_from_mem((const char *)interix_8colour_terminfo,
|
||||||
sizeof interix_8colour_terminfo);
|
sizeof interix_8colour_terminfo);
|
||||||
} else if (terminfo_is_term_family(term, "iterm")
|
} else if (terminfo_is_term_family(term, "iterm")
|
||||||
|| terminfo_is_term_family(term, "iTerm.app")) {
|
|| terminfo_is_term_family(term, "iterm2")
|
||||||
|
|| terminfo_is_term_family(term, "iTerm.app")
|
||||||
|
|| terminfo_is_term_family(term, "iTerm2.app")) {
|
||||||
return unibi_from_mem((const char *)iterm_256colour_terminfo,
|
return unibi_from_mem((const char *)iterm_256colour_terminfo,
|
||||||
sizeof iterm_256colour_terminfo);
|
sizeof iterm_256colour_terminfo);
|
||||||
} else if (terminfo_is_term_family(term, "st")) {
|
} else if (terminfo_is_term_family(term, "st")) {
|
||||||
|
@ -52,6 +52,15 @@
|
|||||||
#define LINUXSET0C "\x1b[?0c"
|
#define LINUXSET0C "\x1b[?0c"
|
||||||
#define LINUXSET1C "\x1b[?1c"
|
#define LINUXSET1C "\x1b[?1c"
|
||||||
|
|
||||||
|
#ifdef NVIM_UNIBI_HAS_VAR_FROM
|
||||||
|
#define UNIBI_SET_NUM_VAR(var, num) \
|
||||||
|
do { \
|
||||||
|
(var) = unibi_var_from_num((num)); \
|
||||||
|
} while (0)
|
||||||
|
#else
|
||||||
|
#define UNIBI_SET_NUM_VAR(var, num) (var).i = (num);
|
||||||
|
#endif
|
||||||
|
|
||||||
// Per the commentary in terminfo, only a minus sign is a true suffix
|
// Per the commentary in terminfo, only a minus sign is a true suffix
|
||||||
// separator.
|
// separator.
|
||||||
bool terminfo_is_term_family(const char *term, const char *family)
|
bool terminfo_is_term_family(const char *term, const char *family)
|
||||||
@ -234,9 +243,9 @@ static void terminfo_start(UI *ui)
|
|||||||
unibi_out(ui, unibi_keypad_xmit);
|
unibi_out(ui, unibi_keypad_xmit);
|
||||||
unibi_out(ui, unibi_clear_screen);
|
unibi_out(ui, unibi_clear_screen);
|
||||||
// Enable bracketed paste
|
// Enable bracketed paste
|
||||||
unibi_out(ui, data->unibi_ext.enable_bracketed_paste);
|
unibi_out_ext(ui, data->unibi_ext.enable_bracketed_paste);
|
||||||
// Enable focus reporting
|
// Enable focus reporting
|
||||||
unibi_out(ui, data->unibi_ext.enable_focus_reporting);
|
unibi_out_ext(ui, data->unibi_ext.enable_focus_reporting);
|
||||||
uv_loop_init(&data->write_loop);
|
uv_loop_init(&data->write_loop);
|
||||||
if (data->out_isatty) {
|
if (data->out_isatty) {
|
||||||
uv_tty_init(&data->write_loop, &data->output_handle.tty, data->out_fd, 0);
|
uv_tty_init(&data->write_loop, &data->output_handle.tty, data->out_fd, 0);
|
||||||
@ -263,9 +272,9 @@ static void terminfo_stop(UI *ui)
|
|||||||
unibi_out(ui, unibi_keypad_local);
|
unibi_out(ui, unibi_keypad_local);
|
||||||
unibi_out(ui, unibi_exit_ca_mode);
|
unibi_out(ui, unibi_exit_ca_mode);
|
||||||
// Disable bracketed paste
|
// Disable bracketed paste
|
||||||
unibi_out(ui, data->unibi_ext.disable_bracketed_paste);
|
unibi_out_ext(ui, data->unibi_ext.disable_bracketed_paste);
|
||||||
// Disable focus reporting
|
// Disable focus reporting
|
||||||
unibi_out(ui, data->unibi_ext.disable_focus_reporting);
|
unibi_out_ext(ui, data->unibi_ext.disable_focus_reporting);
|
||||||
flush_buf(ui, true);
|
flush_buf(ui, true);
|
||||||
uv_tty_reset_mode();
|
uv_tty_reset_mode();
|
||||||
uv_close((uv_handle_t *)&data->output_handle, NULL);
|
uv_close((uv_handle_t *)&data->output_handle, NULL);
|
||||||
@ -279,7 +288,7 @@ static void terminfo_stop(UI *ui)
|
|||||||
static void tui_terminal_start(UI *ui)
|
static void tui_terminal_start(UI *ui)
|
||||||
{
|
{
|
||||||
TUIData *data = ui->data;
|
TUIData *data = ui->data;
|
||||||
data->print_attrs = EMPTY_ATTRS;
|
data->print_attrs = HLATTRS_INIT;
|
||||||
ugrid_init(&data->grid);
|
ugrid_init(&data->grid);
|
||||||
terminfo_start(ui);
|
terminfo_start(ui);
|
||||||
update_size(ui);
|
update_size(ui);
|
||||||
@ -391,15 +400,15 @@ static void update_attrs(UI *ui, HlAttrs attrs)
|
|||||||
|
|
||||||
if (unibi_get_str(data->ut, unibi_set_attributes)) {
|
if (unibi_get_str(data->ut, unibi_set_attributes)) {
|
||||||
if (attrs.bold || attrs.reverse || attrs.underline || attrs.undercurl) {
|
if (attrs.bold || attrs.reverse || attrs.underline || attrs.undercurl) {
|
||||||
data->params[0].i = 0; // standout
|
UNIBI_SET_NUM_VAR(data->params[0], 0); // standout
|
||||||
data->params[1].i = attrs.underline || attrs.undercurl;
|
UNIBI_SET_NUM_VAR(data->params[1], attrs.underline || attrs.undercurl);
|
||||||
data->params[2].i = attrs.reverse;
|
UNIBI_SET_NUM_VAR(data->params[2], attrs.reverse);
|
||||||
data->params[3].i = 0; // blink
|
UNIBI_SET_NUM_VAR(data->params[3], 0); // blink
|
||||||
data->params[4].i = 0; // dim
|
UNIBI_SET_NUM_VAR(data->params[4], 0); // dim
|
||||||
data->params[5].i = attrs.bold;
|
UNIBI_SET_NUM_VAR(data->params[5], attrs.bold);
|
||||||
data->params[6].i = 0; // blank
|
UNIBI_SET_NUM_VAR(data->params[6], 0); // blank
|
||||||
data->params[7].i = 0; // protect
|
UNIBI_SET_NUM_VAR(data->params[7], 0); // protect
|
||||||
data->params[8].i = 0; // alternate character set
|
UNIBI_SET_NUM_VAR(data->params[8], 0); // alternate character set
|
||||||
unibi_out(ui, unibi_set_attributes);
|
unibi_out(ui, unibi_set_attributes);
|
||||||
} else if (!data->default_attr) {
|
} else if (!data->default_attr) {
|
||||||
unibi_out(ui, unibi_exit_attribute_mode);
|
unibi_out(ui, unibi_exit_attribute_mode);
|
||||||
@ -423,26 +432,26 @@ static void update_attrs(UI *ui, HlAttrs attrs)
|
|||||||
}
|
}
|
||||||
if (ui->rgb) {
|
if (ui->rgb) {
|
||||||
if (fg != -1) {
|
if (fg != -1) {
|
||||||
data->params[0].i = (fg >> 16) & 0xff; // red
|
UNIBI_SET_NUM_VAR(data->params[0], (fg >> 16) & 0xff); // red
|
||||||
data->params[1].i = (fg >> 8) & 0xff; // green
|
UNIBI_SET_NUM_VAR(data->params[1], (fg >> 8) & 0xff); // green
|
||||||
data->params[2].i = fg & 0xff; // blue
|
UNIBI_SET_NUM_VAR(data->params[2], fg & 0xff); // blue
|
||||||
unibi_out(ui, data->unibi_ext.set_rgb_foreground);
|
unibi_out_ext(ui, data->unibi_ext.set_rgb_foreground);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bg != -1) {
|
if (bg != -1) {
|
||||||
data->params[0].i = (bg >> 16) & 0xff; // red
|
UNIBI_SET_NUM_VAR(data->params[0], (bg >> 16) & 0xff); // red
|
||||||
data->params[1].i = (bg >> 8) & 0xff; // green
|
UNIBI_SET_NUM_VAR(data->params[1], (bg >> 8) & 0xff); // green
|
||||||
data->params[2].i = bg & 0xff; // blue
|
UNIBI_SET_NUM_VAR(data->params[2], bg & 0xff); // blue
|
||||||
unibi_out(ui, data->unibi_ext.set_rgb_background);
|
unibi_out_ext(ui, data->unibi_ext.set_rgb_background);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (fg != -1) {
|
if (fg != -1) {
|
||||||
data->params[0].i = fg;
|
UNIBI_SET_NUM_VAR(data->params[0], fg);
|
||||||
unibi_out(ui, unibi_set_a_foreground);
|
unibi_out(ui, unibi_set_a_foreground);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bg != -1) {
|
if (bg != -1) {
|
||||||
data->params[0].i = bg;
|
UNIBI_SET_NUM_VAR(data->params[0], bg);
|
||||||
unibi_out(ui, unibi_set_a_background);
|
unibi_out(ui, unibi_set_a_background);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -558,7 +567,7 @@ static void cursor_goto(UI *ui, int row, int col)
|
|||||||
unibi_out(ui, unibi_cursor_left);
|
unibi_out(ui, unibi_cursor_left);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
data->params[0].i = n;
|
UNIBI_SET_NUM_VAR(data->params[0], n);
|
||||||
unibi_out(ui, unibi_parm_left_cursor);
|
unibi_out(ui, unibi_parm_left_cursor);
|
||||||
}
|
}
|
||||||
ugrid_goto(grid, row, col);
|
ugrid_goto(grid, row, col);
|
||||||
@ -570,7 +579,7 @@ static void cursor_goto(UI *ui, int row, int col)
|
|||||||
unibi_out(ui, unibi_cursor_right);
|
unibi_out(ui, unibi_cursor_right);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
data->params[0].i = n;
|
UNIBI_SET_NUM_VAR(data->params[0], n);
|
||||||
unibi_out(ui, unibi_parm_right_cursor);
|
unibi_out(ui, unibi_parm_right_cursor);
|
||||||
}
|
}
|
||||||
ugrid_goto(grid, row, col);
|
ugrid_goto(grid, row, col);
|
||||||
@ -585,7 +594,7 @@ static void cursor_goto(UI *ui, int row, int col)
|
|||||||
unibi_out(ui, unibi_cursor_down);
|
unibi_out(ui, unibi_cursor_down);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
data->params[0].i = n;
|
UNIBI_SET_NUM_VAR(data->params[0], n);
|
||||||
unibi_out(ui, unibi_parm_down_cursor);
|
unibi_out(ui, unibi_parm_down_cursor);
|
||||||
}
|
}
|
||||||
ugrid_goto(grid, row, col);
|
ugrid_goto(grid, row, col);
|
||||||
@ -597,7 +606,7 @@ static void cursor_goto(UI *ui, int row, int col)
|
|||||||
unibi_out(ui, unibi_cursor_up);
|
unibi_out(ui, unibi_cursor_up);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
data->params[0].i = n;
|
UNIBI_SET_NUM_VAR(data->params[0], n);
|
||||||
unibi_out(ui, unibi_parm_up_cursor);
|
unibi_out(ui, unibi_parm_up_cursor);
|
||||||
}
|
}
|
||||||
ugrid_goto(grid, row, col);
|
ugrid_goto(grid, row, col);
|
||||||
@ -619,7 +628,7 @@ static void clear_region(UI *ui, int top, int bot, int left, int right)
|
|||||||
if (grid->bg == -1 && right == ui->width -1) {
|
if (grid->bg == -1 && right == ui->width -1) {
|
||||||
// Background is set to the default color and the right edge matches the
|
// Background is set to the default color and the right edge matches the
|
||||||
// screen end, try to use terminal codes for clearing the requested area.
|
// screen end, try to use terminal codes for clearing the requested area.
|
||||||
HlAttrs clear_attrs = EMPTY_ATTRS;
|
HlAttrs clear_attrs = HLATTRS_INIT;
|
||||||
clear_attrs.foreground = grid->fg;
|
clear_attrs.foreground = grid->fg;
|
||||||
clear_attrs.background = grid->bg;
|
clear_attrs.background = grid->bg;
|
||||||
update_attrs(ui, clear_attrs);
|
update_attrs(ui, clear_attrs);
|
||||||
@ -675,19 +684,19 @@ static void set_scroll_region(UI *ui)
|
|||||||
TUIData *data = ui->data;
|
TUIData *data = ui->data;
|
||||||
UGrid *grid = &data->grid;
|
UGrid *grid = &data->grid;
|
||||||
|
|
||||||
data->params[0].i = grid->top;
|
UNIBI_SET_NUM_VAR(data->params[0], grid->top);
|
||||||
data->params[1].i = grid->bot;
|
UNIBI_SET_NUM_VAR(data->params[1], grid->bot);
|
||||||
unibi_out(ui, unibi_change_scroll_region);
|
unibi_out(ui, unibi_change_scroll_region);
|
||||||
if (grid->left != 0 || grid->right != ui->width - 1) {
|
if (grid->left != 0 || grid->right != ui->width - 1) {
|
||||||
unibi_out(ui, data->unibi_ext.enable_lr_margin);
|
unibi_out_ext(ui, data->unibi_ext.enable_lr_margin);
|
||||||
if (data->can_set_lr_margin) {
|
if (data->can_set_lr_margin) {
|
||||||
data->params[0].i = grid->left;
|
UNIBI_SET_NUM_VAR(data->params[0], grid->left);
|
||||||
data->params[1].i = grid->right;
|
UNIBI_SET_NUM_VAR(data->params[1], grid->right);
|
||||||
unibi_out(ui, unibi_set_lr_margin);
|
unibi_out(ui, unibi_set_lr_margin);
|
||||||
} else {
|
} else {
|
||||||
data->params[0].i = grid->left;
|
UNIBI_SET_NUM_VAR(data->params[0], grid->left);
|
||||||
unibi_out(ui, unibi_set_left_margin_parm);
|
unibi_out(ui, unibi_set_left_margin_parm);
|
||||||
data->params[0].i = grid->right;
|
UNIBI_SET_NUM_VAR(data->params[0], grid->right);
|
||||||
unibi_out(ui, unibi_set_right_margin_parm);
|
unibi_out(ui, unibi_set_right_margin_parm);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -700,24 +709,24 @@ static void reset_scroll_region(UI *ui)
|
|||||||
UGrid *grid = &data->grid;
|
UGrid *grid = &data->grid;
|
||||||
|
|
||||||
if (0 <= data->unibi_ext.reset_scroll_region) {
|
if (0 <= data->unibi_ext.reset_scroll_region) {
|
||||||
unibi_out(ui, data->unibi_ext.reset_scroll_region);
|
unibi_out_ext(ui, data->unibi_ext.reset_scroll_region);
|
||||||
} else {
|
} else {
|
||||||
data->params[0].i = 0;
|
UNIBI_SET_NUM_VAR(data->params[0], 0);
|
||||||
data->params[1].i = ui->height - 1;
|
UNIBI_SET_NUM_VAR(data->params[1], ui->height - 1);
|
||||||
unibi_out(ui, unibi_change_scroll_region);
|
unibi_out(ui, unibi_change_scroll_region);
|
||||||
}
|
}
|
||||||
if (grid->left != 0 || grid->right != ui->width - 1) {
|
if (grid->left != 0 || grid->right != ui->width - 1) {
|
||||||
if (data->can_set_lr_margin) {
|
if (data->can_set_lr_margin) {
|
||||||
data->params[0].i = 0;
|
UNIBI_SET_NUM_VAR(data->params[0], 0);
|
||||||
data->params[1].i = ui->width - 1;
|
UNIBI_SET_NUM_VAR(data->params[1], ui->width - 1);
|
||||||
unibi_out(ui, unibi_set_lr_margin);
|
unibi_out(ui, unibi_set_lr_margin);
|
||||||
} else {
|
} else {
|
||||||
data->params[0].i = 0;
|
UNIBI_SET_NUM_VAR(data->params[0], 0);
|
||||||
unibi_out(ui, unibi_set_left_margin_parm);
|
unibi_out(ui, unibi_set_left_margin_parm);
|
||||||
data->params[0].i = ui->width - 1;
|
UNIBI_SET_NUM_VAR(data->params[0], ui->width - 1);
|
||||||
unibi_out(ui, unibi_set_right_margin_parm);
|
unibi_out(ui, unibi_set_right_margin_parm);
|
||||||
}
|
}
|
||||||
unibi_out(ui, data->unibi_ext.disable_lr_margin);
|
unibi_out_ext(ui, data->unibi_ext.disable_lr_margin);
|
||||||
}
|
}
|
||||||
unibi_goto(ui, grid->row, grid->col);
|
unibi_goto(ui, grid->row, grid->col);
|
||||||
}
|
}
|
||||||
@ -728,9 +737,9 @@ static void tui_resize(UI *ui, Integer width, Integer height)
|
|||||||
ugrid_resize(&data->grid, (int)width, (int)height);
|
ugrid_resize(&data->grid, (int)width, (int)height);
|
||||||
|
|
||||||
if (!got_winch) { // Try to resize the terminal window.
|
if (!got_winch) { // Try to resize the terminal window.
|
||||||
data->params[0].i = (int)height;
|
UNIBI_SET_NUM_VAR(data->params[0], (int)height);
|
||||||
data->params[1].i = (int)width;
|
UNIBI_SET_NUM_VAR(data->params[1], (int)width);
|
||||||
unibi_out(ui, data->unibi_ext.resize_screen);
|
unibi_out_ext(ui, data->unibi_ext.resize_screen);
|
||||||
// DECSLPP does not reset the scroll region.
|
// DECSLPP does not reset the scroll region.
|
||||||
if (data->scroll_region_is_full_screen) {
|
if (data->scroll_region_is_full_screen) {
|
||||||
reset_scroll_region(ui);
|
reset_scroll_region(ui);
|
||||||
@ -836,7 +845,7 @@ static void tui_mouse_on(UI *ui)
|
|||||||
{
|
{
|
||||||
TUIData *data = ui->data;
|
TUIData *data = ui->data;
|
||||||
if (!data->mouse_enabled) {
|
if (!data->mouse_enabled) {
|
||||||
unibi_out(ui, data->unibi_ext.enable_mouse);
|
unibi_out_ext(ui, data->unibi_ext.enable_mouse);
|
||||||
data->mouse_enabled = true;
|
data->mouse_enabled = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -845,7 +854,7 @@ static void tui_mouse_off(UI *ui)
|
|||||||
{
|
{
|
||||||
TUIData *data = ui->data;
|
TUIData *data = ui->data;
|
||||||
if (data->mouse_enabled) {
|
if (data->mouse_enabled) {
|
||||||
unibi_out(ui, data->unibi_ext.disable_mouse);
|
unibi_out_ext(ui, data->unibi_ext.disable_mouse);
|
||||||
data->mouse_enabled = false;
|
data->mouse_enabled = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -863,8 +872,8 @@ static void tui_set_mode(UI *ui, ModeShape mode)
|
|||||||
int attr = syn_id2attr(c.id);
|
int attr = syn_id2attr(c.id);
|
||||||
if (attr > 0) {
|
if (attr > 0) {
|
||||||
attrentry_T *aep = syn_cterm_attr2entry(attr);
|
attrentry_T *aep = syn_cterm_attr2entry(attr);
|
||||||
data->params[0].i = aep->rgb_bg_color;
|
UNIBI_SET_NUM_VAR(data->params[0], aep->rgb_bg_color);
|
||||||
unibi_out(ui, data->unibi_ext.set_cursor_color);
|
unibi_out_ext(ui, data->unibi_ext.set_cursor_color);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -874,8 +883,8 @@ static void tui_set_mode(UI *ui, ModeShape mode)
|
|||||||
case SHAPE_VER: shape = 5; break;
|
case SHAPE_VER: shape = 5; break;
|
||||||
default: WLOG("Unknown shape value %d", shape); break;
|
default: WLOG("Unknown shape value %d", shape); break;
|
||||||
}
|
}
|
||||||
data->params[0].i = shape + (int)(c.blinkon == 0);
|
UNIBI_SET_NUM_VAR(data->params[0], shape + (int)(c.blinkon == 0));
|
||||||
unibi_out(ui, data->unibi_ext.set_cursor_style);
|
unibi_out_ext(ui, data->unibi_ext.set_cursor_style);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @param mode editor mode
|
/// @param mode editor mode
|
||||||
@ -917,7 +926,7 @@ static void tui_scroll(UI *ui, Integer count)
|
|||||||
cursor_goto(ui, grid->top, grid->left);
|
cursor_goto(ui, grid->top, grid->left);
|
||||||
// also set default color attributes or some terminals can become funny
|
// also set default color attributes or some terminals can become funny
|
||||||
if (scroll_clears_to_current_colour) {
|
if (scroll_clears_to_current_colour) {
|
||||||
HlAttrs clear_attrs = EMPTY_ATTRS;
|
HlAttrs clear_attrs = HLATTRS_INIT;
|
||||||
clear_attrs.foreground = grid->fg;
|
clear_attrs.foreground = grid->fg;
|
||||||
clear_attrs.background = grid->bg;
|
clear_attrs.background = grid->bg;
|
||||||
update_attrs(ui, clear_attrs);
|
update_attrs(ui, clear_attrs);
|
||||||
@ -927,14 +936,14 @@ static void tui_scroll(UI *ui, Integer count)
|
|||||||
if (count == 1) {
|
if (count == 1) {
|
||||||
unibi_out(ui, unibi_delete_line);
|
unibi_out(ui, unibi_delete_line);
|
||||||
} else {
|
} else {
|
||||||
data->params[0].i = (int)count;
|
UNIBI_SET_NUM_VAR(data->params[0], (int)count);
|
||||||
unibi_out(ui, unibi_parm_delete_line);
|
unibi_out(ui, unibi_parm_delete_line);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (count == -1) {
|
if (count == -1) {
|
||||||
unibi_out(ui, unibi_insert_line);
|
unibi_out(ui, unibi_insert_line);
|
||||||
} else {
|
} else {
|
||||||
data->params[0].i = -(int)count;
|
UNIBI_SET_NUM_VAR(data->params[0], -(int)count);
|
||||||
unibi_out(ui, unibi_parm_insert_line);
|
unibi_out(ui, unibi_parm_insert_line);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1177,30 +1186,33 @@ end:
|
|||||||
static void unibi_goto(UI *ui, int row, int col)
|
static void unibi_goto(UI *ui, int row, int col)
|
||||||
{
|
{
|
||||||
TUIData *data = ui->data;
|
TUIData *data = ui->data;
|
||||||
data->params[0].i = row;
|
UNIBI_SET_NUM_VAR(data->params[0], row);
|
||||||
data->params[1].i = col;
|
UNIBI_SET_NUM_VAR(data->params[1], col);
|
||||||
unibi_out(ui, unibi_cursor_address);
|
unibi_out(ui, unibi_cursor_address);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define UNIBI_OUT(fn) \
|
||||||
|
do { \
|
||||||
|
TUIData *data = ui->data; \
|
||||||
|
const char *str = NULL; \
|
||||||
|
if (unibi_index >= 0) { \
|
||||||
|
str = fn(data->ut, (unsigned)unibi_index); \
|
||||||
|
} \
|
||||||
|
if (str) { \
|
||||||
|
unibi_var_t vars[26 + 26]; \
|
||||||
|
memset(&vars, 0, sizeof(vars)); \
|
||||||
|
unibi_format(vars, vars + 26, str, data->params, out, ui, NULL, NULL); \
|
||||||
|
} \
|
||||||
|
} while (0)
|
||||||
static void unibi_out(UI *ui, int unibi_index)
|
static void unibi_out(UI *ui, int unibi_index)
|
||||||
{
|
{
|
||||||
TUIData *data = ui->data;
|
UNIBI_OUT(unibi_get_str);
|
||||||
|
|
||||||
const char *str = NULL;
|
|
||||||
|
|
||||||
if (unibi_index >= 0) {
|
|
||||||
if (unibi_index < unibi_string_begin_) {
|
|
||||||
str = unibi_get_ext_str(data->ut, (unsigned)unibi_index);
|
|
||||||
} else {
|
|
||||||
str = unibi_get_str(data->ut, (unsigned)unibi_index);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (str) {
|
|
||||||
unibi_var_t vars[26 + 26] = {{0}};
|
|
||||||
unibi_format(vars, vars + 26, str, data->params, out, ui, NULL, NULL);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
static void unibi_out_ext(UI *ui, int unibi_index)
|
||||||
|
{
|
||||||
|
UNIBI_OUT(unibi_get_ext_str);
|
||||||
|
}
|
||||||
|
#undef UNIBI_OUT
|
||||||
|
|
||||||
static void out(void *ctx, const char *str, size_t len)
|
static void out(void *ctx, const char *str, size_t len)
|
||||||
{
|
{
|
||||||
@ -1261,7 +1273,9 @@ static void patch_terminfo_bugs(TUIData *data, const char *term,
|
|||||||
bool gnome = terminfo_is_term_family(term, "gnome")
|
bool gnome = terminfo_is_term_family(term, "gnome")
|
||||||
|| terminfo_is_term_family(term, "vte");
|
|| terminfo_is_term_family(term, "vte");
|
||||||
bool iterm = terminfo_is_term_family(term, "iterm")
|
bool iterm = terminfo_is_term_family(term, "iterm")
|
||||||
|| terminfo_is_term_family(term, "iTerm.app");
|
|| terminfo_is_term_family(term, "iterm2")
|
||||||
|
|| terminfo_is_term_family(term, "iTerm.app")
|
||||||
|
|| terminfo_is_term_family(term, "iTerm2.app");
|
||||||
// None of the following work over SSH; see :help TERM .
|
// None of the following work over SSH; see :help TERM .
|
||||||
bool iterm_pretending_xterm = xterm && iterm_env;
|
bool iterm_pretending_xterm = xterm && iterm_env;
|
||||||
bool konsole_pretending_xterm = xterm && konsole;
|
bool konsole_pretending_xterm = xterm && konsole;
|
||||||
@ -1444,7 +1458,7 @@ static void patch_terminfo_bugs(TUIData *data, const char *term,
|
|||||||
// teminfo entries. See
|
// teminfo entries. See
|
||||||
// https://github.com/gnachman/iTerm2/pull/92 for more.
|
// https://github.com/gnachman/iTerm2/pull/92 for more.
|
||||||
// xterm even has an extended version that has a vertical bar.
|
// xterm even has an extended version that has a vertical bar.
|
||||||
if (true_xterm // per xterm ctlseqs doco (since version 282)
|
if (!konsole && (true_xterm // per xterm ctlseqs doco (since version 282)
|
||||||
// per MinTTY 0.4.3-1 release notes from 2009
|
// per MinTTY 0.4.3-1 release notes from 2009
|
||||||
|| putty
|
|| putty
|
||||||
// per https://bugzilla.gnome.org/show_bug.cgi?id=720821
|
// per https://bugzilla.gnome.org/show_bug.cgi?id=720821
|
||||||
@ -1459,7 +1473,7 @@ static void patch_terminfo_bugs(TUIData *data, const char *term,
|
|||||||
// Allows forcing the use of DECSCUSR on linux type terminals, such as
|
// Allows forcing the use of DECSCUSR on linux type terminals, such as
|
||||||
// console-terminal-emulator from the nosh toolset, which does indeed
|
// console-terminal-emulator from the nosh toolset, which does indeed
|
||||||
// implement the xterm extension:
|
// implement the xterm extension:
|
||||||
|| (linuxvt && (xterm_version || (vte_version > 0) || colorterm))) {
|
|| (linuxvt && (xterm_version || (vte_version > 0) || colorterm)))) {
|
||||||
data->unibi_ext.set_cursor_style =
|
data->unibi_ext.set_cursor_style =
|
||||||
(int)unibi_add_ext_str(ut, "Ss", "\x1b[%p1%d q");
|
(int)unibi_add_ext_str(ut, "Ss", "\x1b[%p1%d q");
|
||||||
if (-1 == data->unibi_ext.reset_cursor_style) {
|
if (-1 == data->unibi_ext.reset_cursor_style) {
|
||||||
@ -1533,7 +1547,9 @@ static void augment_terminfo(TUIData *data, const char *term,
|
|||||||
bool screen = terminfo_is_term_family(term, "screen");
|
bool screen = terminfo_is_term_family(term, "screen");
|
||||||
bool tmux = terminfo_is_term_family(term, "tmux") || !!os_getenv("TMUX");
|
bool tmux = terminfo_is_term_family(term, "tmux") || !!os_getenv("TMUX");
|
||||||
bool iterm = terminfo_is_term_family(term, "iterm")
|
bool iterm = terminfo_is_term_family(term, "iterm")
|
||||||
|| terminfo_is_term_family(term, "iTerm.app");
|
|| terminfo_is_term_family(term, "iterm2")
|
||||||
|
|| terminfo_is_term_family(term, "iTerm.app")
|
||||||
|
|| terminfo_is_term_family(term, "iTerm2.app");
|
||||||
// None of the following work over SSH; see :help TERM .
|
// None of the following work over SSH; see :help TERM .
|
||||||
bool iterm_pretending_xterm = xterm && iterm_env;
|
bool iterm_pretending_xterm = xterm && iterm_env;
|
||||||
|
|
||||||
|
@ -16,7 +16,7 @@
|
|||||||
|
|
||||||
void ugrid_init(UGrid *grid)
|
void ugrid_init(UGrid *grid)
|
||||||
{
|
{
|
||||||
grid->attrs = EMPTY_ATTRS;
|
grid->attrs = HLATTRS_INIT;
|
||||||
grid->fg = grid->bg = -1;
|
grid->fg = grid->bg = -1;
|
||||||
grid->cells = NULL;
|
grid->cells = NULL;
|
||||||
}
|
}
|
||||||
@ -118,7 +118,7 @@ UCell *ugrid_put(UGrid *grid, uint8_t *text, size_t size)
|
|||||||
|
|
||||||
static void clear_region(UGrid *grid, int top, int bot, int left, int right)
|
static void clear_region(UGrid *grid, int top, int bot, int left, int right)
|
||||||
{
|
{
|
||||||
HlAttrs clear_attrs = EMPTY_ATTRS;
|
HlAttrs clear_attrs = HLATTRS_INIT;
|
||||||
clear_attrs.foreground = grid->fg;
|
clear_attrs.foreground = grid->fg;
|
||||||
clear_attrs.background = grid->bg;
|
clear_attrs.background = grid->bg;
|
||||||
UGRID_FOREACH_CELL(grid, top, bot, left, right, {
|
UGRID_FOREACH_CELL(grid, top, bot, left, right, {
|
||||||
|
@ -21,8 +21,6 @@ struct ugrid {
|
|||||||
UCell **cells;
|
UCell **cells;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define EMPTY_ATTRS ((HlAttrs){ false, false, false, false, false, -1, -1, -1 })
|
|
||||||
|
|
||||||
#define UGRID_FOREACH_CELL(grid, top, bot, left, right, code) \
|
#define UGRID_FOREACH_CELL(grid, top, bot, left, right, code) \
|
||||||
do { \
|
do { \
|
||||||
for (int row = top; row <= bot; row++) { \
|
for (int row = top; row <= bot; row++) { \
|
||||||
|
128
src/nvim/ui.c
128
src/nvim/ui.c
@ -71,10 +71,10 @@ static char uilog_last_event[1024] = { 0 };
|
|||||||
uilog_seen++; \
|
uilog_seen++; \
|
||||||
} else { \
|
} else { \
|
||||||
if (uilog_seen > 0) { \
|
if (uilog_seen > 0) { \
|
||||||
do_log(DEBUG_LOG_LEVEL, "ui", 0, true, \
|
do_log(DEBUG_LOG_LEVEL, "UI: ", NULL, -1, true, \
|
||||||
"%s (+%zu times...)", uilog_last_event, uilog_seen); \
|
"%s (+%zu times...)", uilog_last_event, uilog_seen); \
|
||||||
} \
|
} \
|
||||||
DLOG("ui: " STR(funname)); \
|
do_log(DEBUG_LOG_LEVEL, "UI: ", NULL, -1, true, STR(funname)); \
|
||||||
uilog_seen = 0; \
|
uilog_seen = 0; \
|
||||||
xstrlcpy(uilog_last_event, STR(funname), sizeof(uilog_last_event)); \
|
xstrlcpy(uilog_last_event, STR(funname), sizeof(uilog_last_event)); \
|
||||||
} \
|
} \
|
||||||
@ -166,6 +166,90 @@ void ui_event(char *name, Array args)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// Converts an attrentry_T into an HlAttrs
|
||||||
|
///
|
||||||
|
/// @param[in] aep data to convert
|
||||||
|
/// @param use_rgb use 'gui*' settings if true, else resorts to 'cterm*'
|
||||||
|
HlAttrs attrentry2hlattrs(const attrentry_T *aep, bool use_rgb)
|
||||||
|
{
|
||||||
|
assert(aep);
|
||||||
|
|
||||||
|
HlAttrs attrs = HLATTRS_INIT;
|
||||||
|
int mask = 0;
|
||||||
|
|
||||||
|
mask = use_rgb ? aep->rgb_ae_attr : aep->cterm_ae_attr;
|
||||||
|
|
||||||
|
attrs.bold = mask & HL_BOLD;
|
||||||
|
attrs.underline = mask & HL_UNDERLINE;
|
||||||
|
attrs.undercurl = mask & HL_UNDERCURL;
|
||||||
|
attrs.italic = mask & HL_ITALIC;
|
||||||
|
attrs.reverse = mask & (HL_INVERSE | HL_STANDOUT);
|
||||||
|
|
||||||
|
if (use_rgb) {
|
||||||
|
if (aep->rgb_fg_color != -1) {
|
||||||
|
attrs.foreground = aep->rgb_fg_color;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (aep->rgb_bg_color != -1) {
|
||||||
|
attrs.background = aep->rgb_bg_color;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (aep->rgb_sp_color != -1) {
|
||||||
|
attrs.special = aep->rgb_sp_color;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (cterm_normal_fg_color != aep->cterm_fg_color) {
|
||||||
|
attrs.foreground = aep->cterm_fg_color - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cterm_normal_bg_color != aep->cterm_bg_color) {
|
||||||
|
attrs.background = aep->cterm_bg_color - 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return attrs;
|
||||||
|
}
|
||||||
|
|
||||||
|
Dictionary hlattrs2dict(HlAttrs attrs)
|
||||||
|
{
|
||||||
|
Dictionary hl = ARRAY_DICT_INIT;
|
||||||
|
|
||||||
|
if (attrs.bold) {
|
||||||
|
PUT(hl, "bold", BOOLEAN_OBJ(true));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (attrs.underline) {
|
||||||
|
PUT(hl, "underline", BOOLEAN_OBJ(true));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (attrs.undercurl) {
|
||||||
|
PUT(hl, "undercurl", BOOLEAN_OBJ(true));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (attrs.italic) {
|
||||||
|
PUT(hl, "italic", BOOLEAN_OBJ(true));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (attrs.reverse) {
|
||||||
|
PUT(hl, "reverse", BOOLEAN_OBJ(true));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (attrs.foreground != -1) {
|
||||||
|
PUT(hl, "foreground", INTEGER_OBJ(attrs.foreground));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (attrs.background != -1) {
|
||||||
|
PUT(hl, "background", INTEGER_OBJ(attrs.background));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (attrs.special != -1) {
|
||||||
|
PUT(hl, "special", INTEGER_OBJ(attrs.special));
|
||||||
|
}
|
||||||
|
|
||||||
|
return hl;
|
||||||
|
}
|
||||||
|
|
||||||
void ui_refresh(void)
|
void ui_refresh(void)
|
||||||
{
|
{
|
||||||
if (!ui_active()) {
|
if (!ui_active()) {
|
||||||
@ -405,54 +489,20 @@ void ui_flush(void)
|
|||||||
|
|
||||||
static void set_highlight_args(int attr_code)
|
static void set_highlight_args(int attr_code)
|
||||||
{
|
{
|
||||||
HlAttrs rgb_attrs = { false, false, false, false, false, -1, -1, -1 };
|
HlAttrs rgb_attrs = HLATTRS_INIT;
|
||||||
HlAttrs cterm_attrs = rgb_attrs;
|
HlAttrs cterm_attrs = rgb_attrs;
|
||||||
|
|
||||||
if (attr_code == HL_NORMAL) {
|
if (attr_code == HL_NORMAL) {
|
||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
|
|
||||||
int rgb_mask = 0;
|
|
||||||
int cterm_mask = 0;
|
|
||||||
attrentry_T *aep = syn_cterm_attr2entry(attr_code);
|
attrentry_T *aep = syn_cterm_attr2entry(attr_code);
|
||||||
|
|
||||||
if (!aep) {
|
if (!aep) {
|
||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
|
|
||||||
rgb_mask = aep->rgb_ae_attr;
|
rgb_attrs = attrentry2hlattrs(aep, true);
|
||||||
cterm_mask = aep->cterm_ae_attr;
|
cterm_attrs = attrentry2hlattrs(aep, false);
|
||||||
|
|
||||||
rgb_attrs.bold = rgb_mask & HL_BOLD;
|
|
||||||
rgb_attrs.underline = rgb_mask & HL_UNDERLINE;
|
|
||||||
rgb_attrs.undercurl = rgb_mask & HL_UNDERCURL;
|
|
||||||
rgb_attrs.italic = rgb_mask & HL_ITALIC;
|
|
||||||
rgb_attrs.reverse = rgb_mask & (HL_INVERSE | HL_STANDOUT);
|
|
||||||
cterm_attrs.bold = cterm_mask & HL_BOLD;
|
|
||||||
cterm_attrs.underline = cterm_mask & HL_UNDERLINE;
|
|
||||||
cterm_attrs.undercurl = cterm_mask & HL_UNDERCURL;
|
|
||||||
cterm_attrs.italic = cterm_mask & HL_ITALIC;
|
|
||||||
cterm_attrs.reverse = cterm_mask & (HL_INVERSE | HL_STANDOUT);
|
|
||||||
|
|
||||||
if (aep->rgb_fg_color != normal_fg) {
|
|
||||||
rgb_attrs.foreground = aep->rgb_fg_color;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (aep->rgb_bg_color != normal_bg) {
|
|
||||||
rgb_attrs.background = aep->rgb_bg_color;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (aep->rgb_sp_color != normal_sp) {
|
|
||||||
rgb_attrs.special = aep->rgb_sp_color;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (cterm_normal_fg_color != aep->cterm_fg_color) {
|
|
||||||
cterm_attrs.foreground = aep->cterm_fg_color - 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (cterm_normal_bg_color != aep->cterm_bg_color) {
|
|
||||||
cterm_attrs.background = aep->cterm_bg_color - 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
end:
|
end:
|
||||||
UI_CALL(highlight_set, (ui->rgb ? rgb_attrs : cterm_attrs));
|
UI_CALL(highlight_set, (ui->rgb ? rgb_attrs : cterm_attrs));
|
||||||
|
@ -21,6 +21,9 @@ typedef struct {
|
|||||||
int foreground, background, special;
|
int foreground, background, special;
|
||||||
} HlAttrs;
|
} HlAttrs;
|
||||||
|
|
||||||
|
#define HLATTRS_INIT \
|
||||||
|
((HlAttrs){ false, false, false, false, false, -1, -1, -1 })
|
||||||
|
|
||||||
typedef struct ui_t UI;
|
typedef struct ui_t UI;
|
||||||
|
|
||||||
struct ui_t {
|
struct ui_t {
|
||||||
|
@ -77,6 +77,157 @@ static char *features[] = {
|
|||||||
|
|
||||||
// clang-format off
|
// clang-format off
|
||||||
static const int included_patches[] = {
|
static const int included_patches[] = {
|
||||||
|
// 1026,
|
||||||
|
1025,
|
||||||
|
1024,
|
||||||
|
// 1023,
|
||||||
|
// 1022,
|
||||||
|
// 1021,
|
||||||
|
// 1020,
|
||||||
|
// 1019,
|
||||||
|
// 1018,
|
||||||
|
// 1017,
|
||||||
|
// 1016,
|
||||||
|
// 1015,
|
||||||
|
// 1014,
|
||||||
|
// 1013,
|
||||||
|
// 1012,
|
||||||
|
// 1011,
|
||||||
|
// 1010,
|
||||||
|
// 1009,
|
||||||
|
// 1008,
|
||||||
|
// 1007,
|
||||||
|
// 1006,
|
||||||
|
// 1005,
|
||||||
|
// 1004,
|
||||||
|
// 1003,
|
||||||
|
// 1002,
|
||||||
|
// 1001,
|
||||||
|
// 1000,
|
||||||
|
// 999,
|
||||||
|
// 998,
|
||||||
|
// 997,
|
||||||
|
// 996,
|
||||||
|
// 995,
|
||||||
|
// 994,
|
||||||
|
// 993,
|
||||||
|
// 992,
|
||||||
|
// 991,
|
||||||
|
// 990,
|
||||||
|
// 989,
|
||||||
|
// 988,
|
||||||
|
// 987,
|
||||||
|
// 986,
|
||||||
|
// 985,
|
||||||
|
// 984,
|
||||||
|
// 983,
|
||||||
|
// 982,
|
||||||
|
// 981,
|
||||||
|
// 980,
|
||||||
|
// 979,
|
||||||
|
// 978,
|
||||||
|
// 977,
|
||||||
|
// 976,
|
||||||
|
// 975,
|
||||||
|
// 974,
|
||||||
|
// 973,
|
||||||
|
// 972,
|
||||||
|
// 971,
|
||||||
|
// 970,
|
||||||
|
// 969,
|
||||||
|
// 968,
|
||||||
|
// 967,
|
||||||
|
// 966,
|
||||||
|
// 965,
|
||||||
|
// 964,
|
||||||
|
// 963,
|
||||||
|
// 962,
|
||||||
|
// 961,
|
||||||
|
// 960,
|
||||||
|
// 959,
|
||||||
|
// 958,
|
||||||
|
// 957,
|
||||||
|
// 956,
|
||||||
|
// 955,
|
||||||
|
// 954,
|
||||||
|
// 953,
|
||||||
|
// 952,
|
||||||
|
// 951,
|
||||||
|
// 950,
|
||||||
|
// 949,
|
||||||
|
// 948,
|
||||||
|
// 947,
|
||||||
|
// 946,
|
||||||
|
// 945,
|
||||||
|
// 944,
|
||||||
|
// 943,
|
||||||
|
// 942,
|
||||||
|
// 941,
|
||||||
|
// 940,
|
||||||
|
// 939,
|
||||||
|
// 938,
|
||||||
|
// 937,
|
||||||
|
// 936,
|
||||||
|
// 935,
|
||||||
|
// 934,
|
||||||
|
// 933,
|
||||||
|
// 932,
|
||||||
|
// 931,
|
||||||
|
// 930,
|
||||||
|
// 929,
|
||||||
|
// 928,
|
||||||
|
// 927,
|
||||||
|
// 926,
|
||||||
|
// 925,
|
||||||
|
// 924,
|
||||||
|
// 923,
|
||||||
|
// 922,
|
||||||
|
// 921,
|
||||||
|
// 920,
|
||||||
|
// 919,
|
||||||
|
// 918,
|
||||||
|
// 917,
|
||||||
|
// 916,
|
||||||
|
// 915,
|
||||||
|
// 914,
|
||||||
|
// 913,
|
||||||
|
// 912,
|
||||||
|
// 911,
|
||||||
|
// 910,
|
||||||
|
// 909,
|
||||||
|
// 908,
|
||||||
|
// 907,
|
||||||
|
// 906,
|
||||||
|
// 905,
|
||||||
|
// 904,
|
||||||
|
// 903,
|
||||||
|
// 902,
|
||||||
|
// 901,
|
||||||
|
// 900,
|
||||||
|
// 899,
|
||||||
|
// 898,
|
||||||
|
// 897,
|
||||||
|
// 896,
|
||||||
|
// 895,
|
||||||
|
// 894,
|
||||||
|
// 893,
|
||||||
|
// 892,
|
||||||
|
// 891,
|
||||||
|
// 890,
|
||||||
|
// 889,
|
||||||
|
// 888,
|
||||||
|
// 887,
|
||||||
|
// 886,
|
||||||
|
// 885,
|
||||||
|
// 884,
|
||||||
|
// 883,
|
||||||
|
// 882,
|
||||||
|
// 881,
|
||||||
|
// 880,
|
||||||
|
// 879,
|
||||||
|
// 878,
|
||||||
|
// 877,
|
||||||
|
// 876,
|
||||||
// 875,
|
// 875,
|
||||||
// 874,
|
// 874,
|
||||||
// 873,
|
// 873,
|
||||||
@ -272,7 +423,7 @@ static const int included_patches[] = {
|
|||||||
// 683,
|
// 683,
|
||||||
// 682,
|
// 682,
|
||||||
// 681,
|
// 681,
|
||||||
// 680,
|
680,
|
||||||
679,
|
679,
|
||||||
678,
|
678,
|
||||||
// 677,
|
// 677,
|
||||||
@ -340,7 +491,7 @@ static const int included_patches[] = {
|
|||||||
// 615,
|
// 615,
|
||||||
614,
|
614,
|
||||||
// 613,
|
// 613,
|
||||||
// 612,
|
612,
|
||||||
// 611,
|
// 611,
|
||||||
// 610,
|
// 610,
|
||||||
// 609,
|
// 609,
|
||||||
@ -515,7 +666,7 @@ static const int included_patches[] = {
|
|||||||
// 440,
|
// 440,
|
||||||
// 439,
|
// 439,
|
||||||
// 438,
|
// 438,
|
||||||
// 437,
|
437,
|
||||||
// 436,
|
// 436,
|
||||||
// 435,
|
// 435,
|
||||||
// 434,
|
// 434,
|
||||||
@ -619,16 +770,16 @@ static const int included_patches[] = {
|
|||||||
// 336,
|
// 336,
|
||||||
// 335,
|
// 335,
|
||||||
// 334,
|
// 334,
|
||||||
// 333,
|
333,
|
||||||
// 332,
|
// 332,
|
||||||
331,
|
331,
|
||||||
// 330,
|
330,
|
||||||
// 329,
|
// 329,
|
||||||
// 328,
|
328,
|
||||||
// 327,
|
327,
|
||||||
// 326,
|
326,
|
||||||
// 325,
|
325,
|
||||||
// 324,
|
324,
|
||||||
// 323,
|
// 323,
|
||||||
322,
|
322,
|
||||||
// 321,
|
// 321,
|
||||||
@ -644,24 +795,24 @@ static const int included_patches[] = {
|
|||||||
311,
|
311,
|
||||||
// 310,
|
// 310,
|
||||||
// 309,
|
// 309,
|
||||||
// 308,
|
308,
|
||||||
307,
|
307,
|
||||||
// 306,
|
// 306,
|
||||||
// 305,
|
305,
|
||||||
// 304,
|
// 304,
|
||||||
// 303,
|
// 303,
|
||||||
// 302,
|
// 302, NA
|
||||||
// 301,
|
// 301,
|
||||||
// 300,
|
300,
|
||||||
// 299,
|
// 299,
|
||||||
// 298,
|
// 298,
|
||||||
297,
|
297,
|
||||||
// 296,
|
// 296,
|
||||||
// 295,
|
// 295,
|
||||||
// 294,
|
294,
|
||||||
// 293,
|
// 293,
|
||||||
// 292,
|
// 292,
|
||||||
// 291,
|
291,
|
||||||
290,
|
290,
|
||||||
// 289,
|
// 289,
|
||||||
// 288 NA
|
// 288 NA
|
||||||
@ -670,7 +821,7 @@ static const int included_patches[] = {
|
|||||||
// 285 NA
|
// 285 NA
|
||||||
// 284 NA
|
// 284 NA
|
||||||
// 283,
|
// 283,
|
||||||
// 282,
|
282,
|
||||||
// 281 NA
|
// 281 NA
|
||||||
280,
|
280,
|
||||||
// 279 NA
|
// 279 NA
|
||||||
@ -694,18 +845,18 @@ static const int included_patches[] = {
|
|||||||
// 261,
|
// 261,
|
||||||
// 260 NA
|
// 260 NA
|
||||||
259,
|
259,
|
||||||
// 258,
|
258,
|
||||||
// 257 NA
|
// 257 NA
|
||||||
// 256,
|
// 256,
|
||||||
// 255,
|
// 255,
|
||||||
// 254,
|
// 254,
|
||||||
// 253,
|
253,
|
||||||
// 252,
|
// 252,
|
||||||
// 251,
|
// 251,
|
||||||
250,
|
250,
|
||||||
// 249 NA
|
// 249 NA
|
||||||
// 248,
|
// 248,
|
||||||
// 247,
|
247,
|
||||||
// 246 NA
|
// 246 NA
|
||||||
// 245,
|
// 245,
|
||||||
// 244,
|
// 244,
|
||||||
@ -743,7 +894,7 @@ static const int included_patches[] = {
|
|||||||
// 212,
|
// 212,
|
||||||
// 211 NA
|
// 211 NA
|
||||||
// 210,
|
// 210,
|
||||||
// 209,
|
209,
|
||||||
208,
|
208,
|
||||||
// 207,
|
// 207,
|
||||||
// 206,
|
// 206,
|
||||||
@ -764,14 +915,14 @@ static const int included_patches[] = {
|
|||||||
// 191 NA
|
// 191 NA
|
||||||
190,
|
190,
|
||||||
// 189,
|
// 189,
|
||||||
// 188,
|
188,
|
||||||
// 187 NA
|
// 187 NA
|
||||||
// 186,
|
186,
|
||||||
// 185,
|
// 185,
|
||||||
// 184,
|
// 184,
|
||||||
// 183,
|
// 183,
|
||||||
// 182,
|
182,
|
||||||
// 181,
|
181,
|
||||||
// 180,
|
// 180,
|
||||||
179,
|
179,
|
||||||
178,
|
178,
|
||||||
@ -788,29 +939,29 @@ static const int included_patches[] = {
|
|||||||
167,
|
167,
|
||||||
// 166,
|
// 166,
|
||||||
165,
|
165,
|
||||||
// 164,
|
164,
|
||||||
// 163 NA
|
// 163 NA
|
||||||
// 162 NA
|
// 162 NA
|
||||||
// 161 NA
|
// 161 NA
|
||||||
// 160,
|
// 160,
|
||||||
159,
|
159,
|
||||||
158,
|
158,
|
||||||
// 157,
|
157,
|
||||||
156,
|
156,
|
||||||
// 155,
|
155,
|
||||||
// 154,
|
// 154,
|
||||||
// 153,
|
// 153,
|
||||||
// 152 NA
|
// 152 NA
|
||||||
// 151,
|
// 151,
|
||||||
150,
|
150,
|
||||||
149,
|
149,
|
||||||
// 148,
|
148,
|
||||||
147,
|
147,
|
||||||
146,
|
146,
|
||||||
// 145 NA
|
// 145 NA
|
||||||
// 144 NA
|
// 144 NA
|
||||||
143,
|
143,
|
||||||
// 142,
|
142,
|
||||||
// 141,
|
// 141,
|
||||||
// 140,
|
// 140,
|
||||||
// 139 NA
|
// 139 NA
|
||||||
@ -820,14 +971,14 @@ static const int included_patches[] = {
|
|||||||
135,
|
135,
|
||||||
134,
|
134,
|
||||||
133,
|
133,
|
||||||
// 132,
|
132,
|
||||||
// 131,
|
131,
|
||||||
// 130 NA
|
// 130 NA
|
||||||
// 129 NA
|
// 129 NA
|
||||||
128,
|
128,
|
||||||
127,
|
127,
|
||||||
126,
|
126,
|
||||||
// 125,
|
125,
|
||||||
124,
|
124,
|
||||||
// 123 NA
|
// 123 NA
|
||||||
// 122 NA
|
// 122 NA
|
||||||
@ -840,7 +991,7 @@ static const int included_patches[] = {
|
|||||||
// 115 NA
|
// 115 NA
|
||||||
// 114 NA
|
// 114 NA
|
||||||
// 113 NA
|
// 113 NA
|
||||||
// 112,
|
112,
|
||||||
111,
|
111,
|
||||||
110,
|
110,
|
||||||
// 109 NA
|
// 109 NA
|
||||||
@ -860,8 +1011,8 @@ static const int included_patches[] = {
|
|||||||
// 95 NA
|
// 95 NA
|
||||||
// 94 NA
|
// 94 NA
|
||||||
// 93 NA
|
// 93 NA
|
||||||
// 92,
|
92,
|
||||||
// 91,
|
91,
|
||||||
90,
|
90,
|
||||||
// 89 NA
|
// 89 NA
|
||||||
88,
|
88,
|
||||||
@ -1089,13 +1240,7 @@ static void list_features(void)
|
|||||||
msg_putchar('\n');
|
msg_putchar('\n');
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
while (msg_col % width) {
|
msg_putchar(' ');
|
||||||
int old_msg_col = msg_col;
|
|
||||||
msg_putchar(' ');
|
|
||||||
if (old_msg_col == msg_col) {
|
|
||||||
break; // XXX: Avoid infinite loop.
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (msg_col > 0) {
|
if (msg_col > 0) {
|
||||||
@ -1103,7 +1248,7 @@ static void list_features(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
MSG_PUTS("For differences from Vim, see :help vim-differences\n\n");
|
MSG_PUTS("See \":help feature-compile\"\n\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
void list_version(void)
|
void list_version(void)
|
||||||
@ -1144,7 +1289,7 @@ void list_version(void)
|
|||||||
}
|
}
|
||||||
#endif // ifdef HAVE_PATHDEF
|
#endif // ifdef HAVE_PATHDEF
|
||||||
|
|
||||||
version_msg(_("\n\nOptional features included (+) or not (-): "));
|
version_msg(_("\n\nFeatures: "));
|
||||||
|
|
||||||
list_features();
|
list_features();
|
||||||
|
|
||||||
@ -1216,7 +1361,6 @@ void intro_message(int colon)
|
|||||||
static char *(lines[]) = {
|
static char *(lines[]) = {
|
||||||
N_(NVIM_VERSION_LONG),
|
N_(NVIM_VERSION_LONG),
|
||||||
"",
|
"",
|
||||||
N_("by al."),
|
|
||||||
N_("Nvim is open source and freely distributable"),
|
N_("Nvim is open source and freely distributable"),
|
||||||
N_("https://neovim.io/community"),
|
N_("https://neovim.io/community"),
|
||||||
"",
|
"",
|
||||||
|
@ -5515,11 +5515,14 @@ void restore_buffer(bufref_T *save_curbuf)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Add match to the match list of window 'wp'. The pattern 'pat' will be
|
/// Add match to the match list of window 'wp'. The pattern 'pat' will be
|
||||||
// highlighted with the group 'grp' with priority 'prio'.
|
/// highlighted with the group 'grp' with priority 'prio'.
|
||||||
// Optionally, a desired ID 'id' can be specified (greater than or equal to 1).
|
/// Optionally, a desired ID 'id' can be specified (greater than or equal to 1).
|
||||||
// If no particular ID is desired, -1 must be specified for 'id'.
|
///
|
||||||
// Return ID of added match, -1 on failure.
|
/// @param[in] id a desired ID 'id' can be specified
|
||||||
|
/// (greater than or equal to 1). -1 must be specified if no
|
||||||
|
/// particular ID is desired
|
||||||
|
/// @return ID of added match, -1 on failure.
|
||||||
int match_add(win_T *wp, const char *const grp, const char *const pat,
|
int match_add(win_T *wp, const char *const grp, const char *const pat,
|
||||||
int prio, int id, list_T *pos_list,
|
int prio, int id, list_T *pos_list,
|
||||||
const char *const conceal_char)
|
const char *const conceal_char)
|
||||||
@ -5697,10 +5700,9 @@ fail:
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Delete match with ID 'id' in the match list of window 'wp'.
|
/// Delete match with ID 'id' in the match list of window 'wp'.
|
||||||
* Print error messages if 'perr' is TRUE.
|
/// Print error messages if 'perr' is TRUE.
|
||||||
*/
|
|
||||||
int match_delete(win_T *wp, int id, int perr)
|
int match_delete(win_T *wp, int id, int perr)
|
||||||
{
|
{
|
||||||
matchitem_T *cur = wp->w_match_head;
|
matchitem_T *cur = wp->w_match_head;
|
||||||
|
@ -17,4 +17,4 @@ ignore = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
-- Ignore whitespace issues in converted Vim legacy tests.
|
-- Ignore whitespace issues in converted Vim legacy tests.
|
||||||
files["functional/legacy"] = {ignore = { "611", "612", "613", "621" }}
|
--files["functional/legacy"] = {ignore = { "611", "612", "613", "621" }}
|
||||||
|
103
test/functional/api/highlight_spec.lua
Normal file
103
test/functional/api/highlight_spec.lua
Normal file
@ -0,0 +1,103 @@
|
|||||||
|
local helpers = require('test.functional.helpers')(after_each)
|
||||||
|
local clear, nvim = helpers.clear, helpers.nvim
|
||||||
|
local Screen = require('test.functional.ui.screen')
|
||||||
|
local eq, eval = helpers.eq, helpers.eval
|
||||||
|
local command = helpers.command
|
||||||
|
local meths = helpers.meths
|
||||||
|
|
||||||
|
describe('highlight api',function()
|
||||||
|
local expected_rgb = {
|
||||||
|
background = Screen.colors.Yellow,
|
||||||
|
foreground = Screen.colors.Red,
|
||||||
|
special = Screen.colors.Blue,
|
||||||
|
bold = true,
|
||||||
|
}
|
||||||
|
local expected_cterm = {
|
||||||
|
background = 10,
|
||||||
|
underline = true,
|
||||||
|
}
|
||||||
|
local expected_rgb2 = {
|
||||||
|
background = Screen.colors.Yellow,
|
||||||
|
foreground = Screen.colors.Red,
|
||||||
|
special = Screen.colors.Blue,
|
||||||
|
bold = true,
|
||||||
|
italic = true,
|
||||||
|
reverse = true,
|
||||||
|
undercurl = true,
|
||||||
|
underline = true,
|
||||||
|
}
|
||||||
|
|
||||||
|
before_each(function()
|
||||||
|
clear()
|
||||||
|
command("hi NewHighlight cterm=underline ctermbg=green guifg=red guibg=yellow guisp=blue gui=bold")
|
||||||
|
end)
|
||||||
|
|
||||||
|
it("nvim_get_hl_by_id", function()
|
||||||
|
local hl_id = eval("hlID('NewHighlight')")
|
||||||
|
eq(expected_cterm, nvim("get_hl_by_id", hl_id, false))
|
||||||
|
|
||||||
|
hl_id = eval("hlID('NewHighlight')")
|
||||||
|
-- Test valid id.
|
||||||
|
eq(expected_rgb, nvim("get_hl_by_id", hl_id, true))
|
||||||
|
|
||||||
|
-- Test invalid id.
|
||||||
|
local err, emsg = pcall(meths.get_hl_by_id, 30000, false)
|
||||||
|
eq(false, err)
|
||||||
|
eq('Invalid highlight id: 30000', string.match(emsg, 'Invalid.*'))
|
||||||
|
|
||||||
|
-- Test all highlight properties.
|
||||||
|
command('hi NewHighlight gui=underline,bold,undercurl,italic,reverse')
|
||||||
|
eq(expected_rgb2, nvim("get_hl_by_id", hl_id, true))
|
||||||
|
|
||||||
|
-- Test nil argument.
|
||||||
|
err, emsg = pcall(meths.get_hl_by_id, { nil }, false)
|
||||||
|
eq(false, err)
|
||||||
|
eq('Wrong type for argument 1, expecting Integer',
|
||||||
|
string.match(emsg, 'Wrong.*'))
|
||||||
|
|
||||||
|
-- Test 0 argument.
|
||||||
|
err, emsg = pcall(meths.get_hl_by_id, 0, false)
|
||||||
|
eq(false, err)
|
||||||
|
eq('Invalid highlight id: 0',
|
||||||
|
string.match(emsg, 'Invalid.*'))
|
||||||
|
|
||||||
|
-- Test -1 argument.
|
||||||
|
err, emsg = pcall(meths.get_hl_by_id, -1, false)
|
||||||
|
eq(false, err)
|
||||||
|
eq('Invalid highlight id: -1',
|
||||||
|
string.match(emsg, 'Invalid.*'))
|
||||||
|
end)
|
||||||
|
|
||||||
|
it("nvim_get_hl_by_name", function()
|
||||||
|
local expected_normal = { background = Screen.colors.Yellow,
|
||||||
|
foreground = Screen.colors.Red }
|
||||||
|
|
||||||
|
-- Test `Normal` default values.
|
||||||
|
eq({}, nvim("get_hl_by_name", 'Normal', true))
|
||||||
|
|
||||||
|
eq(expected_cterm, nvim("get_hl_by_name", 'NewHighlight', false))
|
||||||
|
eq(expected_rgb, nvim("get_hl_by_name", 'NewHighlight', true))
|
||||||
|
|
||||||
|
-- Test `Normal` modified values.
|
||||||
|
command('hi Normal guifg=red guibg=yellow')
|
||||||
|
eq(expected_normal, nvim("get_hl_by_name", 'Normal', true))
|
||||||
|
|
||||||
|
-- Test invalid name.
|
||||||
|
local err, emsg = pcall(meths.get_hl_by_name , 'unknown_highlight', false)
|
||||||
|
eq(false, err)
|
||||||
|
eq('Invalid highlight name: unknown_highlight',
|
||||||
|
string.match(emsg, 'Invalid.*'))
|
||||||
|
|
||||||
|
-- Test nil argument.
|
||||||
|
err, emsg = pcall(meths.get_hl_by_name , { nil }, false)
|
||||||
|
eq(false, err)
|
||||||
|
eq('Wrong type for argument 1, expecting String',
|
||||||
|
string.match(emsg, 'Wrong.*'))
|
||||||
|
|
||||||
|
-- Test empty string argument.
|
||||||
|
err, emsg = pcall(meths.get_hl_by_name , '', false)
|
||||||
|
eq(false, err)
|
||||||
|
eq('Invalid highlight name: ',
|
||||||
|
string.match(emsg, 'Invalid.*'))
|
||||||
|
end)
|
||||||
|
end)
|
@ -20,6 +20,22 @@ describe('server -> client', function()
|
|||||||
cid = nvim('get_api_info')[1]
|
cid = nvim('get_api_info')[1]
|
||||||
end)
|
end)
|
||||||
|
|
||||||
|
it('handles unexpected closed stream while preparing RPC response', function()
|
||||||
|
source([[
|
||||||
|
let g:_nvim_args = [v:progpath, '--embed', '-n', '-u', 'NONE', '-i', 'NONE', ]
|
||||||
|
let ch1 = jobstart(g:_nvim_args, {'rpc': v:true})
|
||||||
|
let child1_ch = rpcrequest(ch1, "nvim_get_api_info")[0]
|
||||||
|
call rpcnotify(ch1, 'nvim_eval', 'rpcrequest('.child1_ch.', "nvim_get_api_info")')
|
||||||
|
|
||||||
|
let ch2 = jobstart(g:_nvim_args, {'rpc': v:true})
|
||||||
|
let child2_ch = rpcrequest(ch2, "nvim_get_api_info")[0]
|
||||||
|
call rpcnotify(ch2, 'nvim_eval', 'rpcrequest('.child2_ch.', "nvim_get_api_info")')
|
||||||
|
|
||||||
|
call jobstop(ch1)
|
||||||
|
]])
|
||||||
|
eq(2, eval("1+1")) -- Still alive?
|
||||||
|
end)
|
||||||
|
|
||||||
describe('simple call', function()
|
describe('simple call', function()
|
||||||
it('works', function()
|
it('works', function()
|
||||||
local function on_setup()
|
local function on_setup()
|
||||||
@ -141,7 +157,7 @@ describe('server -> client', function()
|
|||||||
end)
|
end)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
describe('when the client is a recursive vim instance', function()
|
describe('recursive (child) nvim client', function()
|
||||||
if os.getenv("TRAVIS") and helpers.os_name() == "osx" then
|
if os.getenv("TRAVIS") and helpers.os_name() == "osx" then
|
||||||
-- XXX: Hangs Travis macOS since e9061117a5b8f195c3f26a5cb94e18ddd7752d86.
|
-- XXX: Hangs Travis macOS since e9061117a5b8f195c3f26a5cb94e18ddd7752d86.
|
||||||
pending("[Hangs on Travis macOS. #5002]", function() end)
|
pending("[Hangs on Travis macOS. #5002]", function() end)
|
||||||
@ -155,7 +171,7 @@ describe('server -> client', function()
|
|||||||
|
|
||||||
after_each(function() command('call rpcstop(vim)') end)
|
after_each(function() command('call rpcstop(vim)') end)
|
||||||
|
|
||||||
it('can send/recieve notifications and make requests', function()
|
it('can send/receive notifications and make requests', function()
|
||||||
nvim('command', "call rpcnotify(vim, 'vim_set_current_line', 'SOME TEXT')")
|
nvim('command', "call rpcnotify(vim, 'vim_set_current_line', 'SOME TEXT')")
|
||||||
|
|
||||||
-- Wait for the notification to complete.
|
-- Wait for the notification to complete.
|
||||||
@ -188,7 +204,7 @@ describe('server -> client', function()
|
|||||||
end)
|
end)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
describe('when using jobstart', function()
|
describe('jobstart()', function()
|
||||||
local jobid
|
local jobid
|
||||||
before_each(function()
|
before_each(function()
|
||||||
local channel = nvim('get_api_info')[1]
|
local channel = nvim('get_api_info')[1]
|
||||||
@ -227,7 +243,7 @@ describe('server -> client', function()
|
|||||||
end)
|
end)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
describe('when connecting to another nvim instance', function()
|
describe('connecting to another (peer) nvim', function()
|
||||||
local function connect_test(server, mode, address)
|
local function connect_test(server, mode, address)
|
||||||
local serverpid = funcs.getpid()
|
local serverpid = funcs.getpid()
|
||||||
local client = spawn(nvim_argv)
|
local client = spawn(nvim_argv)
|
||||||
@ -256,7 +272,7 @@ describe('server -> client', function()
|
|||||||
client:close()
|
client:close()
|
||||||
end
|
end
|
||||||
|
|
||||||
it('over a named pipe', function()
|
it('via named pipe', function()
|
||||||
local server = spawn(nvim_argv)
|
local server = spawn(nvim_argv)
|
||||||
set_session(server)
|
set_session(server)
|
||||||
local address = funcs.serverlist()[1]
|
local address = funcs.serverlist()[1]
|
||||||
@ -265,7 +281,7 @@ describe('server -> client', function()
|
|||||||
connect_test(server, 'pipe', address)
|
connect_test(server, 'pipe', address)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
it('to an ip adress', function()
|
it('via ip address', function()
|
||||||
local server = spawn(nvim_argv)
|
local server = spawn(nvim_argv)
|
||||||
set_session(server)
|
set_session(server)
|
||||||
local address = funcs.serverstart("127.0.0.1:")
|
local address = funcs.serverstart("127.0.0.1:")
|
||||||
@ -273,7 +289,7 @@ describe('server -> client', function()
|
|||||||
connect_test(server, 'tcp', address)
|
connect_test(server, 'tcp', address)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
it('to a hostname', function()
|
it('via hostname', function()
|
||||||
local server = spawn(nvim_argv)
|
local server = spawn(nvim_argv)
|
||||||
set_session(server)
|
set_session(server)
|
||||||
local address = funcs.serverstart("localhost:")
|
local address = funcs.serverstart("localhost:")
|
||||||
|
@ -329,24 +329,92 @@ describe('api', function()
|
|||||||
}
|
}
|
||||||
eq({ { {mode='n', blocking=false},
|
eq({ { {mode='n', blocking=false},
|
||||||
13,
|
13,
|
||||||
{mode='n', blocking=false}, -- TODO: should be blocked=true
|
{mode='n', blocking=false}, -- TODO: should be blocked=true ?
|
||||||
1 },
|
1 },
|
||||||
NIL}, meths.call_atomic(req))
|
NIL}, meths.call_atomic(req))
|
||||||
eq({mode='r', blocking=true}, nvim("get_mode"))
|
eq({mode='r', blocking=true}, nvim("get_mode"))
|
||||||
end)
|
end)
|
||||||
-- TODO: bug #6166
|
|
||||||
it("during insert-mode map-pending, returns blocking=true #6166", function()
|
it("during insert-mode map-pending, returns blocking=true #6166", function()
|
||||||
command("inoremap xx foo")
|
command("inoremap xx foo")
|
||||||
nvim("input", "ix")
|
nvim("input", "ix")
|
||||||
eq({mode='i', blocking=true}, nvim("get_mode"))
|
eq({mode='i', blocking=true}, nvim("get_mode"))
|
||||||
end)
|
end)
|
||||||
-- TODO: bug #6166
|
|
||||||
it("during normal-mode gU, returns blocking=false #6166", function()
|
it("during normal-mode gU, returns blocking=false #6166", function()
|
||||||
nvim("input", "gu")
|
nvim("input", "gu")
|
||||||
eq({mode='no', blocking=false}, nvim("get_mode"))
|
eq({mode='no', blocking=false}, nvim("get_mode"))
|
||||||
end)
|
end)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
|
describe('RPC (K_EVENT) #6166', function()
|
||||||
|
it('does not complete ("interrupt") normal-mode operator-pending', function()
|
||||||
|
helpers.insert([[
|
||||||
|
FIRST LINE
|
||||||
|
SECOND LINE]])
|
||||||
|
nvim('input', 'gg')
|
||||||
|
nvim('input', 'gu')
|
||||||
|
-- Make any RPC request (can be non-async: op-pending does not block).
|
||||||
|
nvim('get_current_buf')
|
||||||
|
-- Buffer should not change.
|
||||||
|
helpers.expect([[
|
||||||
|
FIRST LINE
|
||||||
|
SECOND LINE]])
|
||||||
|
-- Now send input to complete the operator.
|
||||||
|
nvim('input', 'j')
|
||||||
|
helpers.expect([[
|
||||||
|
first line
|
||||||
|
second line]])
|
||||||
|
end)
|
||||||
|
|
||||||
|
it('does not complete ("interrupt") `d` #3732', function()
|
||||||
|
local screen = Screen.new(20, 4)
|
||||||
|
screen:attach()
|
||||||
|
command('set listchars=eol:$')
|
||||||
|
command('set list')
|
||||||
|
feed('ia<cr>b<cr>c<cr><Esc>kkk')
|
||||||
|
feed('d')
|
||||||
|
-- Make any RPC request (can be non-async: op-pending does not block).
|
||||||
|
nvim('get_current_buf')
|
||||||
|
screen:expect([[
|
||||||
|
^a$ |
|
||||||
|
b$ |
|
||||||
|
c$ |
|
||||||
|
|
|
||||||
|
]])
|
||||||
|
end)
|
||||||
|
|
||||||
|
it('does not complete ("interrupt") normal-mode map-pending', function()
|
||||||
|
command("nnoremap dd :let g:foo='it worked...'<CR>")
|
||||||
|
helpers.insert([[
|
||||||
|
FIRST LINE
|
||||||
|
SECOND LINE]])
|
||||||
|
nvim('input', 'gg')
|
||||||
|
nvim('input', 'd')
|
||||||
|
-- Make any RPC request (must be async, because map-pending blocks).
|
||||||
|
nvim('get_api_info')
|
||||||
|
-- Send input to complete the mapping.
|
||||||
|
nvim('input', 'd')
|
||||||
|
helpers.expect([[
|
||||||
|
FIRST LINE
|
||||||
|
SECOND LINE]])
|
||||||
|
eq('it worked...', helpers.eval('g:foo'))
|
||||||
|
end)
|
||||||
|
it('does not complete ("interrupt") insert-mode map-pending', function()
|
||||||
|
command('inoremap xx foo')
|
||||||
|
command('set timeoutlen=9999')
|
||||||
|
helpers.insert([[
|
||||||
|
FIRST LINE
|
||||||
|
SECOND LINE]])
|
||||||
|
nvim('input', 'ix')
|
||||||
|
-- Make any RPC request (must be async, because map-pending blocks).
|
||||||
|
nvim('get_api_info')
|
||||||
|
-- Send input to complete the mapping.
|
||||||
|
nvim('input', 'x')
|
||||||
|
helpers.expect([[
|
||||||
|
FIRST LINE
|
||||||
|
SECOND LINfooE]])
|
||||||
|
end)
|
||||||
|
end)
|
||||||
|
|
||||||
describe('nvim_replace_termcodes', function()
|
describe('nvim_replace_termcodes', function()
|
||||||
it('escapes K_SPECIAL as K_SPECIAL KS_SPECIAL KE_FILLER', function()
|
it('escapes K_SPECIAL as K_SPECIAL KS_SPECIAL KE_FILLER', function()
|
||||||
eq('\128\254X', helpers.nvim('replace_termcodes', '\128', true, true, true))
|
eq('\128\254X', helpers.nvim('replace_termcodes', '\128', true, true, true))
|
||||||
|
@ -57,7 +57,9 @@ describe('TermClose event', function()
|
|||||||
command('call jobstop(g:test_job)')
|
command('call jobstop(g:test_job)')
|
||||||
retry(nil, nil, function() eq(1, eval('get(g:, "test_job_exited", 0)')) end)
|
retry(nil, nil, function() eq(1, eval('get(g:, "test_job_exited", 0)')) end)
|
||||||
local duration = os.time() - start
|
local duration = os.time() - start
|
||||||
eq(4, duration)
|
-- nvim starts sending kill after 2*KILL_TIMEOUT_MS
|
||||||
|
helpers.ok(4 <= duration)
|
||||||
|
helpers.ok(duration <= 7) -- <= 4 + delta because of slow CI
|
||||||
end)
|
end)
|
||||||
|
|
||||||
it('reports the correct <abuf>', function()
|
it('reports the correct <abuf>', function()
|
||||||
|
@ -4,6 +4,8 @@ local helpers = require('test.functional.helpers')(after_each)
|
|||||||
local Screen = require('test.functional.ui.screen')
|
local Screen = require('test.functional.ui.screen')
|
||||||
local clear, feed, insert = helpers.clear, helpers.feed, helpers.insert
|
local clear, feed, insert = helpers.clear, helpers.feed, helpers.insert
|
||||||
local feed_command, expect, eq, eval = helpers.feed_command, helpers.expect, helpers.eq, helpers.eval
|
local feed_command, expect, eq, eval = helpers.feed_command, helpers.expect, helpers.eq, helpers.eval
|
||||||
|
local command = helpers.command
|
||||||
|
local meths = helpers.meths
|
||||||
|
|
||||||
local function basic_register_test(noblock)
|
local function basic_register_test(noblock)
|
||||||
insert("some words")
|
insert("some words")
|
||||||
@ -80,15 +82,73 @@ local function basic_register_test(noblock)
|
|||||||
expect("two and three and one")
|
expect("two and three and one")
|
||||||
end
|
end
|
||||||
|
|
||||||
describe('the unnamed register', function()
|
describe('clipboard', function()
|
||||||
before_each(clear)
|
before_each(clear)
|
||||||
it('works without provider', function()
|
|
||||||
|
it('unnamed register works without provider', function()
|
||||||
eq('"', eval('v:register'))
|
eq('"', eval('v:register'))
|
||||||
basic_register_test()
|
basic_register_test()
|
||||||
end)
|
end)
|
||||||
|
|
||||||
|
it('`:redir @+>` with invalid g:clipboard shows exactly one error #7184',
|
||||||
|
function()
|
||||||
|
local screen = Screen.new(72, 4)
|
||||||
|
screen:attach()
|
||||||
|
command("let g:clipboard = 'bogus'")
|
||||||
|
feed_command('redir @+> | :silent echo system("cat CONTRIBUTING.md") | redir END')
|
||||||
|
screen:expect([[
|
||||||
|
^ |
|
||||||
|
~ |
|
||||||
|
~ |
|
||||||
|
clipboard: No provider. Try ":CheckHealth" or ":h clipboard". |
|
||||||
|
]], nil, {{bold = true, foreground = Screen.colors.Blue}})
|
||||||
|
end)
|
||||||
|
|
||||||
|
it('`:redir @+>|bogus_cmd|redir END` + invalid g:clipboard must not recurse #7184',
|
||||||
|
function()
|
||||||
|
local screen = Screen.new(72, 4)
|
||||||
|
screen:attach()
|
||||||
|
command("let g:clipboard = 'bogus'")
|
||||||
|
feed_command('redir @+> | bogus_cmd | redir END')
|
||||||
|
screen:expect([[
|
||||||
|
~ |
|
||||||
|
clipboard: No provider. Try ":CheckHealth" or ":h clipboard". |
|
||||||
|
E492: Not an editor command: bogus_cmd | redir END |
|
||||||
|
Press ENTER or type command to continue^ |
|
||||||
|
]], nil, {{bold = true, foreground = Screen.colors.Blue}})
|
||||||
|
end)
|
||||||
|
|
||||||
|
it('invalid g:clipboard shows hint if :redir is not active', function()
|
||||||
|
command("let g:clipboard = 'bogus'")
|
||||||
|
eq('', eval('provider#clipboard#Executable()'))
|
||||||
|
eq('clipboard: invalid g:clipboard', eval('provider#clipboard#Error()'))
|
||||||
|
|
||||||
|
local screen = Screen.new(72, 4)
|
||||||
|
screen:attach()
|
||||||
|
command("let g:clipboard = 'bogus'")
|
||||||
|
-- Explicit clipboard attempt, should show a hint message.
|
||||||
|
feed_command('let @+="foo"')
|
||||||
|
screen:expect([[
|
||||||
|
^ |
|
||||||
|
~ |
|
||||||
|
~ |
|
||||||
|
clipboard: No provider. Try ":CheckHealth" or ":h clipboard". |
|
||||||
|
]], nil, {{bold = true, foreground = Screen.colors.Blue}})
|
||||||
|
end)
|
||||||
|
|
||||||
|
it('valid g:clipboard', function()
|
||||||
|
-- provider#clipboard#Executable() only checks the structure.
|
||||||
|
meths.set_var('clipboard', {
|
||||||
|
['name'] = 'clippy!',
|
||||||
|
['copy'] = { ['+'] = 'any command', ['*'] = 'some other' },
|
||||||
|
['paste'] = { ['+'] = 'any command', ['*'] = 'some other' },
|
||||||
|
})
|
||||||
|
eq('clippy!', eval('provider#clipboard#Executable()'))
|
||||||
|
eq('', eval('provider#clipboard#Error()'))
|
||||||
|
end)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
describe('clipboard usage', function()
|
describe('clipboard', function()
|
||||||
local function reset(...)
|
local function reset(...)
|
||||||
clear('--cmd', 'let &rtp = "test/functional/fixtures,".&rtp', ...)
|
clear('--cmd', 'let &rtp = "test/functional/fixtures,".&rtp', ...)
|
||||||
end
|
end
|
||||||
@ -98,7 +158,36 @@ describe('clipboard usage', function()
|
|||||||
feed_command('call getreg("*")') -- force load of provider
|
feed_command('call getreg("*")') -- force load of provider
|
||||||
end)
|
end)
|
||||||
|
|
||||||
it('has independent "* and unnamed registers per default', function()
|
it('`:redir @+>` invokes clipboard once-per-message', function()
|
||||||
|
eq(0, eval("g:clip_called_set"))
|
||||||
|
feed_command('redir @+> | :silent echo system("cat CONTRIBUTING.md") | redir END')
|
||||||
|
-- Assuming CONTRIBUTING.md has >100 lines.
|
||||||
|
assert(eval("g:clip_called_set") > 100)
|
||||||
|
end)
|
||||||
|
|
||||||
|
it('`:redir @">` does NOT invoke clipboard', function()
|
||||||
|
-- :redir to a non-clipboard register, with `:set clipboard=unnamed` does
|
||||||
|
-- NOT propagate to the clipboard. This is consistent with Vim.
|
||||||
|
command("set clipboard=unnamedplus")
|
||||||
|
eq(0, eval("g:clip_called_set"))
|
||||||
|
feed_command('redir @"> | :silent echo system("cat CONTRIBUTING.md") | redir END')
|
||||||
|
eq(0, eval("g:clip_called_set"))
|
||||||
|
end)
|
||||||
|
|
||||||
|
it('`:redir @+>|bogus_cmd|redir END` must not recurse #7184',
|
||||||
|
function()
|
||||||
|
local screen = Screen.new(72, 4)
|
||||||
|
screen:attach()
|
||||||
|
feed_command('redir @+> | bogus_cmd | redir END')
|
||||||
|
screen:expect([[
|
||||||
|
^ |
|
||||||
|
~ |
|
||||||
|
~ |
|
||||||
|
E492: Not an editor command: bogus_cmd | redir END |
|
||||||
|
]], nil, {{bold = true, foreground = Screen.colors.Blue}})
|
||||||
|
end)
|
||||||
|
|
||||||
|
it('has independent "* and unnamed registers by default', function()
|
||||||
insert("some words")
|
insert("some words")
|
||||||
feed('^"*dwdw"*P')
|
feed('^"*dwdw"*P')
|
||||||
expect('some ')
|
expect('some ')
|
||||||
@ -139,7 +228,7 @@ describe('clipboard usage', function()
|
|||||||
eq({'some\ntext', '\nvery binary\n'}, eval("getreg('*', 1, 1)"))
|
eq({'some\ntext', '\nvery binary\n'}, eval("getreg('*', 1, 1)"))
|
||||||
end)
|
end)
|
||||||
|
|
||||||
it('support autodectection of regtype', function()
|
it('autodetects regtype', function()
|
||||||
feed_command("let g:test_clip['*'] = ['linewise stuff','']")
|
feed_command("let g:test_clip['*'] = ['linewise stuff','']")
|
||||||
feed_command("let g:test_clip['+'] = ['charwise','stuff']")
|
feed_command("let g:test_clip['+'] = ['charwise','stuff']")
|
||||||
eq("V", eval("getregtype('*')"))
|
eq("V", eval("getregtype('*')"))
|
||||||
@ -169,7 +258,7 @@ describe('clipboard usage', function()
|
|||||||
eq({{' much', 'ktext', ''}, 'b'}, eval("g:test_clip['+']"))
|
eq({{' much', 'ktext', ''}, 'b'}, eval("g:test_clip['+']"))
|
||||||
end)
|
end)
|
||||||
|
|
||||||
it('supports setreg', function()
|
it('supports setreg()', function()
|
||||||
feed_command('call setreg("*", "setted\\ntext", "c")')
|
feed_command('call setreg("*", "setted\\ntext", "c")')
|
||||||
feed_command('call setreg("+", "explicitly\\nlines", "l")')
|
feed_command('call setreg("+", "explicitly\\nlines", "l")')
|
||||||
feed('"+P"*p')
|
feed('"+P"*p')
|
||||||
@ -187,7 +276,7 @@ describe('clipboard usage', function()
|
|||||||
]])
|
]])
|
||||||
end)
|
end)
|
||||||
|
|
||||||
it('supports let @+ (issue #1427)', function()
|
it('supports :let @+ (issue #1427)', function()
|
||||||
feed_command("let @+ = 'some'")
|
feed_command("let @+ = 'some'")
|
||||||
feed_command("let @* = ' other stuff'")
|
feed_command("let @* = ' other stuff'")
|
||||||
eq({{'some'}, 'v'}, eval("g:test_clip['+']"))
|
eq({{'some'}, 'v'}, eval("g:test_clip['+']"))
|
||||||
@ -303,9 +392,16 @@ describe('clipboard usage', function()
|
|||||||
eq('---', eval('getreg("*")'))
|
eq('---', eval('getreg("*")'))
|
||||||
end)
|
end)
|
||||||
|
|
||||||
|
it('works in the cmdline window', function()
|
||||||
|
feed('q:itext<esc>yy')
|
||||||
|
eq({{'text', ''}, 'V'}, eval("g:test_clip['*']"))
|
||||||
|
command("let g:test_clip['*'] = [['star'], 'c']")
|
||||||
|
feed('p')
|
||||||
|
eq('textstar', meths.get_current_line())
|
||||||
|
end)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
describe('with clipboard=unnamedplus', function()
|
describe('clipboard=unnamedplus', function()
|
||||||
before_each(function()
|
before_each(function()
|
||||||
feed_command('set clipboard=unnamedplus')
|
feed_command('set clipboard=unnamedplus')
|
||||||
end)
|
end)
|
||||||
@ -349,6 +445,7 @@ describe('clipboard usage', function()
|
|||||||
really unnamed
|
really unnamed
|
||||||
the plus]])
|
the plus]])
|
||||||
end)
|
end)
|
||||||
|
|
||||||
it('is updated on global changes', function()
|
it('is updated on global changes', function()
|
||||||
insert([[
|
insert([[
|
||||||
text
|
text
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user