Merge branch 'master' into expression-parser

This commit is contained in:
ZyX
2017-10-30 00:49:12 +03:00
119 changed files with 2655 additions and 777 deletions

View File

@@ -113,15 +113,14 @@ else()
set(HAS_OG_FLAG 0) set(HAS_OG_FLAG 0)
endif() endif()
# Set custom build flags for RelWithDebInfo. #
# -DNDEBUG purposely omitted because we want assertions. # Build-type: RelWithDebInfo
#
if(HAS_OG_FLAG) if(HAS_OG_FLAG)
set(CMAKE_C_FLAGS_RELWITHDEBINFO "-Og -g" set(CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELWITHDEBINFO} -Og -g")
CACHE STRING "Flags used by the compiler during release-with-debug builds." FORCE) endif()
elseif(NOT MSVC) # We _want_ assertions in RelWithDebInfo build-type.
set(CMAKE_C_FLAGS_RELWITHDEBINFO "-O2 -g" if(CMAKE_C_FLAGS_RELWITHDEBINFO MATCHES DNDEBUG)
CACHE STRING "Flags used by the compiler during release-with-debug builds." FORCE)
elseif(CMAKE_C_FLAGS_RELWITHDEBINFO MATCHES DNDEBUG)
string(REPLACE "-DNDEBUG" "" CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELWITHDEBINFO}") string(REPLACE "-DNDEBUG" "" CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELWITHDEBINFO}")
endif() endif()
@@ -479,20 +478,19 @@ install_helper(
DESTINATION ${CMAKE_INSTALL_MANDIR}/man1) DESTINATION ${CMAKE_INSTALL_MANDIR}/man1)
# MIN_LOG_LEVEL for log.h # MIN_LOG_LEVEL for log.h
if(DEFINED MIN_LOG_LEVEL) if("${MIN_LOG_LEVEL}" MATCHES "^$")
message(STATUS "MIN_LOG_LEVEL not specified")
else()
if(NOT MIN_LOG_LEVEL MATCHES "^[0-3]$") if(NOT MIN_LOG_LEVEL MATCHES "^[0-3]$")
message(FATAL_ERROR "invalid MIN_LOG_LEVEL: " ${MIN_LOG_LEVEL}) message(FATAL_ERROR "invalid MIN_LOG_LEVEL: " ${MIN_LOG_LEVEL})
endif() endif()
message(STATUS "MIN_LOG_LEVEL set to ${MIN_LOG_LEVEL}") message(STATUS "MIN_LOG_LEVEL set to ${MIN_LOG_LEVEL}")
else()
message(STATUS "MIN_LOG_LEVEL not specified, defaulting to 1 (INFO)")
endif() endif()
# Go down the tree. # Go down the tree.
add_subdirectory(src/nvim) add_subdirectory(src/nvim)
# Read compilation flags from src/nvim, # Read compilation flags from src/nvim, used in config subdirectory below.
# used in config subdirectory below.
include(GetCompileFlags) include(GetCompileFlags)
get_compile_flags(NVIM_VERSION_CFLAGS) get_compile_flags(NVIM_VERSION_CFLAGS)

View File

@@ -13,7 +13,7 @@
[![Clang Scan Build](https://neovim.io/doc/reports/clang/badge.svg)](https://neovim.io/doc/reports/clang) [![Clang Scan Build](https://neovim.io/doc/reports/clang/badge.svg)](https://neovim.io/doc/reports/clang)
[![PVS-studio Check](https://neovim.io/doc/reports/pvs/badge.svg)](https://neovim.io/doc/reports/pvs) [![PVS-studio Check](https://neovim.io/doc/reports/pvs/badge.svg)](https://neovim.io/doc/reports/pvs)
<a href="https://buildd.debian.org/neovim"><img src="https://www.debian.org/logos/openlogo-nd-25.png" width="13" height="15">Debian</a> [![Debian CI](https://badges.debian.net/badges/debian/testing/neovim/version.svg)](https://buildd.debian.org/neovim)
[![Downloads](https://img.shields.io/github/downloads/neovim/neovim/total.svg?maxAge=2592000)](https://github.com/neovim/neovim/releases/) [![Downloads](https://img.shields.io/github/downloads/neovim/neovim/total.svg?maxAge=2592000)](https://github.com/neovim/neovim/releases/)
Neovim is a project that seeks to aggressively refactor Vim in order to: Neovim is a project that seeks to aggressively refactor Vim in order to:

View File

@@ -2,8 +2,8 @@
if(CMAKE_SYSTEM_NAME MATCHES "BSD" AND NOT DEFINED CMAKE_INSTALL_MANDIR) if(CMAKE_SYSTEM_NAME MATCHES "BSD" AND NOT DEFINED CMAKE_INSTALL_MANDIR)
if(DEFINED ENV{MANPREFIX}) if(DEFINED ENV{MANPREFIX})
set(CMAKE_INSTALL_MANDIR "$ENV{MANPREFIX}/man") set(CMAKE_INSTALL_MANDIR "$ENV{MANPREFIX}/man")
else() elseif(CMAKE_INSTALL_PREFIX MATCHES "^/usr/local$")
set(CMAKE_INSTALL_MANDIR "/usr/local/man") set(CMAKE_INSTALL_MANDIR "man")
endif() endif()
endif() endif()

View File

@@ -18,7 +18,7 @@ function! s:enhance_syntax() abort
syntax match healthBar "|" contained conceal syntax match healthBar "|" contained conceal
highlight link healthHelp Identifier highlight link healthHelp Identifier
" We do not care about markdown syntax errors in :CheckHealth output. " We do not care about markdown syntax errors in :checkhealth output.
highlight! link markdownError Normal highlight! link markdownError Normal
endfunction endfunction
@@ -159,7 +159,10 @@ endfunction
" Translates a list of plugin names to healthcheck function names. " Translates a list of plugin names to healthcheck function names.
function! s:to_fn_names(plugin_names) abort function! s:to_fn_names(plugin_names) abort
let healthchecks = [] let healthchecks = []
for p in a:plugin_names let plugin_names = type('') ==# type(a:plugin_names)
\ ? split(a:plugin_names, '', v:false)
\ : a:plugin_names
for p in plugin_names
call add(healthchecks, 'health#'.p.'#check') call add(healthchecks, 'health#'.p.'#check')
endfor endfor
return healthchecks return healthchecks

View File

@@ -4,12 +4,19 @@ function! s:check_config() abort
let ok = v:true let ok = v:true
call health#report_start('Configuration') call health#report_start('Configuration')
" If $VIM is empty we don't care. Else make sure it is valid.
if !empty($VIM) && !filereadable($VIM.'/runtime/doc/nvim.txt')
let ok = v:false
call health#report_error("$VIM is invalid: ".$VIM)
endif
if exists('$NVIM_TUI_ENABLE_CURSOR_SHAPE') if exists('$NVIM_TUI_ENABLE_CURSOR_SHAPE')
let ok = v:false let ok = v:false
call health#report_warn("$NVIM_TUI_ENABLE_CURSOR_SHAPE is ignored in Nvim 0.2+", call health#report_warn("$NVIM_TUI_ENABLE_CURSOR_SHAPE is ignored in Nvim 0.2+",
\ [ "Use the 'guicursor' option to configure cursor shape. :help 'guicursor'", \ [ "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 if &paste
let ok = v:false 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.", call health#report_error("'paste' is enabled. This option is only for pasting text.\nIt should not be set in your config.",

View File

@@ -75,7 +75,7 @@ let s:prog = provider#ruby#Detect()
let s:plugin_path = expand('<sfile>:p:h') . '/script_host.rb' let s:plugin_path = expand('<sfile>:p:h') . '/script_host.rb'
if empty(s:prog) if empty(s:prog)
let s:err = 'Cannot find the neovim RubyGem. Try :CheckHealth' let s:err = 'Cannot find the neovim RubyGem. Try :checkhealth'
endif endif
call remote#host#RegisterClone('legacy-ruby-provider', 'ruby') call remote#host#RegisterClone('legacy-ruby-provider', 'ruby')

View File

@@ -169,14 +169,40 @@ function! remote#define#FunctionOnChannel(channel, method, sync, name, opts)
exe function_def exe function_def
endfunction endfunction
let s:busy = {}
let s:pending_notifications = {}
function! s:GetRpcFunction(sync) function! s:GetRpcFunction(sync)
if a:sync if a:sync ==# 'urgent'
return 'rpcrequest'
endif
return 'rpcnotify' return 'rpcnotify'
elseif a:sync
return 'remote#define#request'
endif
return 'remote#define#notify'
endfunction endfunction
function! remote#define#notify(chan, ...)
if get(s:busy, a:chan, 0) > 0
let pending = get(s:pending_notifications, a:chan, [])
call add(pending, deepcopy(a:000))
let s:pending_notifications[a:chan] = pending
else
call call('rpcnotify', [a:chan] + a:000)
endif
endfunction
function! remote#define#request(chan, ...)
let s:busy[a:chan] = get(s:busy, a:chan, 0)+1
let val = call('rpcrequest', [a:chan]+a:000)
let s:busy[a:chan] -= 1
if s:busy[a:chan] == 0
for msg in get(s:pending_notifications, a:chan, [])
call call('rpcnotify', [a:chan] + msg)
endfor
let s:pending_notifications[a:chan] = []
endif
return val
endfunction
function! s:GetCommandPrefix(name, opts) function! s:GetCommandPrefix(name, opts)
return 'command!'.s:StringifyOpts(a:opts, ['nargs', 'complete', 'range', return 'command!'.s:StringifyOpts(a:opts, ['nargs', 'complete', 'range',

View File

@@ -11,7 +11,7 @@ via |msgpack-rpc|, Lua and VimL (|eval-api|).
Applications can also embed libnvim to work with the C API directly. Applications can also embed libnvim to work with the C API directly.
Type <M-]> to see the table of contents. Type |gO| to see the table of contents.
============================================================================== ==============================================================================
API Types *api-types* API Types *api-types*
@@ -48,7 +48,7 @@ version.api_compatible API is backwards-compatible with this level
version.api_prerelease Declares the current API level as unstable > version.api_prerelease Declares the current API level as unstable >
(version.api_prerelease && fn.since == version.api_level) (version.api_prerelease && fn.since == version.api_level)
functions API function signatures functions API function signatures
ui_events UI event signatures |rpc-remote-ui| ui_events UI event signatures |ui|
{fn}.since API level where function {fn} was introduced {fn}.since API level where function {fn} was introduced
{fn}.deprecated_since API level where function {fn} was deprecated {fn}.deprecated_since API level where function {fn} was deprecated
types Custom handle types defined by Nvim types Custom handle types defined by Nvim

View File

@@ -8,7 +8,7 @@ Automatic commands *autocommand*
For a basic explanation, see section |40.3| in the user manual. For a basic explanation, see section |40.3| in the user manual.
Type <M-]> to see the table of contents. Type |gO| to see the table of contents.
============================================================================== ==============================================================================
1. Introduction *autocmd-intro* 1. Introduction *autocmd-intro*

View File

@@ -11,7 +11,7 @@ commands with the "." command.
For inserting text see |insert.txt|. For inserting text see |insert.txt|.
Type <M-]> to see the table of contents. Type |gO| to see the table of contents.
============================================================================== ==============================================================================
1. Deleting text *deleting* *E470* 1. Deleting text *deleting* *E470*
@@ -648,6 +648,7 @@ g& Synonym for `:%s//~/&` (repeat last substitute with
*:s_flags* *:s_flags*
The flags that you can use for the substitute commands: The flags that you can use for the substitute commands:
*:&&*
[&] Must be the first one: Keep the flags from the previous substitute [&] Must be the first one: Keep the flags from the previous substitute
command. Examples: > command. Examples: >
:&& :&&

View File

@@ -13,7 +13,7 @@ Command-line mode is used to enter Ex commands (":"), search patterns
Basic command line editing is explained in chapter 20 of the user manual Basic command line editing is explained in chapter 20 of the user manual
|usr_20.txt|. |usr_20.txt|.
Type <M-]> to see the table of contents. Type |gO| to see the table of contents.
============================================================================== ==============================================================================
1. Command-line editing *cmdline-editing* 1. Command-line editing *cmdline-editing*

View File

@@ -9,7 +9,7 @@ Debugging Vim *debug-vim*
This is for debugging Vim itself, when it doesn't work properly. This is for debugging Vim itself, when it doesn't work properly.
For debugging Vim scripts, functions, etc. see |debug-scripts| For debugging Vim scripts, functions, etc. see |debug-scripts|
Type <M-]> to see the table of contents. Type |gO| to see the table of contents.
============================================================================== ==============================================================================

View File

@@ -11,7 +11,7 @@ Nvim is open source software. Everybody is encouraged to contribute.
See src/nvim/README.md for an overview of the source code. See src/nvim/README.md for an overview of the source code.
Type <M-]> to see the table of contents. Type |gO| to see the table of contents.
============================================================================== ==============================================================================
Design goals *design-goals* Design goals *design-goals*

View File

@@ -10,7 +10,7 @@ eight versions of the same file.
The basics are explained in section |08.7| of the user manual. The basics are explained in section |08.7| of the user manual.
Type <M-]> to see the table of contents. Type |gO| to see the table of contents.
============================================================================== ==============================================================================
1. Starting diff mode 1. Starting diff mode

View File

@@ -14,7 +14,7 @@ with CTRL-V (see |i_CTRL-V|).
There is a brief introduction on digraphs in the user manual: |24.9| There is a brief introduction on digraphs in the user manual: |24.9|
An alternative is using the 'keymap' option. An alternative is using the 'keymap' option.
Type <M-]> to see the table of contents. Type |gO| to see the table of contents.
============================================================================== ==============================================================================
1. Defining digraphs *digraphs-define* 1. Defining digraphs *digraphs-define*

View File

@@ -6,7 +6,7 @@
Editing files *edit-files* Editing files *edit-files*
Type <M-]> to see the table of contents. Type |gO| to see the table of contents.
============================================================================== ==============================================================================
1. Introduction *edit-intro* 1. Introduction *edit-intro*
@@ -901,11 +901,12 @@ WRITING WITH MULTIPLE BUFFERS *buffer-write*
*:wa* *:wall* *:wa* *:wall*
:wa[ll] Write all changed buffers. Buffers without a file :wa[ll] Write all changed buffers. Buffers without a file
name or which are readonly are not written. name cause an error message. Buffers which are
readonly are not written.
:wa[ll]! Write all changed buffers, even the ones that are :wa[ll]! Write all changed buffers, even the ones that are
readonly. Buffers without a file name are not readonly. Buffers without a file name are not
written. written and cause an error message.
Vim will warn you if you try to overwrite a file that has been changed Vim will warn you if you try to overwrite a file that has been changed

View File

@@ -12,7 +12,7 @@ Note: Expression evaluation can be disabled at compile time. If this has been
done, the features in this document are not available. See |+eval| and done, the features in this document are not available. See |+eval| and
|no-eval-feature|. |no-eval-feature|.
Type <M-]> to see the table of contents. Type |gO| to see the table of contents.
============================================================================== ==============================================================================
1. Variables *variables* 1. Variables *variables*

View File

@@ -8,7 +8,7 @@ Filetypes *filetype* *file-type*
Also see |autocmd.txt|. Also see |autocmd.txt|.
Type <M-]> to see the table of contents. Type |gO| to see the table of contents.
============================================================================== ==============================================================================
1. Filetypes *filetypes* *file-types* 1. Filetypes *filetypes* *file-types*
@@ -540,7 +540,7 @@ K or CTRL-] Jump to the manpage for the <cWORD> under the
cursor. Takes a count for the section. cursor. Takes a count for the section.
CTRL-T Jump back to the location that the manpage was CTRL-T Jump back to the location that the manpage was
opened from. opened from.
META-] Show the manpage outline in the |location-list|. gO Show the manpage outline. |gO|
q :quit if invoked as $MANPAGER, otherwise :close. q :quit if invoked as $MANPAGER, otherwise :close.
Variables: Variables:

View File

@@ -9,7 +9,7 @@ Folding *Folding* *folding* *folds*
You can find an introduction on folding in chapter 28 of the user manual. You can find an introduction on folding in chapter 28 of the user manual.
|usr_28.txt| |usr_28.txt|
Type <M-]> to see the table of contents. Type |gO| to see the table of contents.
============================================================================== ==============================================================================
1. Fold methods *fold-methods* 1. Fold methods *fold-methods*

View File

@@ -6,7 +6,7 @@
Vim's Graphical User Interface *gui* *GUI* Vim's Graphical User Interface *gui* *GUI*
Type <M-]> to see the table of contents. Type |gO| to see the table of contents.
============================================================================== ==============================================================================
1. Starting the GUI *gui-start* *E229* *E233* 1. Starting the GUI *gui-start* *E229* *E233*

View File

@@ -6,7 +6,7 @@
Help on help files *helphelp* Help on help files *helphelp*
Type <M-]> to see the table of contents. Type |gO| to see the table of contents.
============================================================================== ==============================================================================
1. Help commands *online-help* 1. Help commands *online-help*
@@ -23,7 +23,7 @@ Help on help files *helphelp*
The 'helplang' option is used to select a language, if The 'helplang' option is used to select a language, if
the main help file is available in several languages. the main help file is available in several languages.
Type <M-]> to see the table of contents. Type |gO| to see the table of contents.
*{subject}* *E149* *E661* *{subject}* *E149* *E661*
:h[elp] {subject} Like ":help", additionally jump to the tag {subject}. :h[elp] {subject} Like ":help", additionally jump to the tag {subject}.

View File

@@ -12,7 +12,7 @@ a cscope query is just like jumping to any tag; it is saved on the tag stack
so that with the right keyboard mappings, you can jump back and forth between so that with the right keyboard mappings, you can jump back and forth between
functions as you normally would with |tags|. functions as you normally would with |tags|.
Type <M-]> to see the table of contents. Type |gO| to see the table of contents.
============================================================================== ==============================================================================
1. Cscope introduction *cscope-intro* 1. Cscope introduction *cscope-intro*

View File

@@ -1,26 +1,26 @@
*if_lua.txt* Nvim *if_lua.txt* Nvim
VIM REFERENCE MANUAL by Luis Carvalho NVIM REFERENCE MANUAL
Lua Interface to Nvim *lua* *Lua* Lua Interface to Nvim *lua* *Lua*
Type <M-]> to see the table of contents. Type |gO| to see the table of contents.
============================================================================== ==============================================================================
1. Importing modules *lua-require* Importing modules *lua-require*
Neovim lua interface automatically adjusts `package.path` and `package.cpath` Nvim automatically adjusts `package.path` and `package.cpath` according to
according to effective &runtimepath value. Adjustment happens after effective 'runtimepath' value. Adjustment happens whenever 'runtimepath' is
'runtimepath' is changed. `package.path` is adjusted by simply appending changed. `package.path` is adjusted by simply appending `/lua/?.lua` and
`/lua/?.lua` and `/lua/?/init.lua` to each directory from 'runtimepath' (`/` `/lua/?/init.lua` to each directory from 'runtimepath' (`/` is actually the
is actually the first character of `package.config`). first character of `package.config`).
Similarly to `package.path`, modified directories from `runtimepath` are also Similarly to `package.path`, modified directories from 'runtimepath' are also
added to `package.cpath`. In this case, instead of appending `/lua/?.lua` and added to `package.cpath`. In this case, instead of appending `/lua/?.lua` and
`/lua/?/init.lua` to each runtimepath, all unique `?`-containing suffixes of `/lua/?/init.lua` to each runtimepath, all unique `?`-containing suffixes of
the existing `package.cpath` are used. Here is an example: the existing `package.cpath` are used. Example:
1. Given that 1. Given that
- 'runtimepath' contains `/foo/bar,/xxx;yyy/baz,/abc`; - 'runtimepath' contains `/foo/bar,/xxx;yyy/baz,/abc`;
@@ -61,7 +61,7 @@ paths when path is removed from 'runtimepath', adding paths when they are
added and reordering `package.path`/`package.cpath` content if 'runtimepath' added and reordering `package.path`/`package.cpath` content if 'runtimepath'
was reordered. was reordered.
Note 2: even though adjustments happens automatically Neovim does not track Note 2: even though adjustments happens automatically Nvim does not track
current values of `package.path` or `package.cpath`. If you happened to current values of `package.path` or `package.cpath`. If you happened to
delete some paths from there you need to reset 'runtimepath' to make them delete some paths from there you need to reset 'runtimepath' to make them
readded. Just running `let &runtimepath = &runtimepath` should work. readded. Just running `let &runtimepath = &runtimepath` should work.
@@ -72,7 +72,7 @@ badly written plugins using shell which will not work with paths containing
semicolons it is better to not have them in 'runtimepath' at all. semicolons it is better to not have them in 'runtimepath' at all.
------------------------------------------------------------------------------ ------------------------------------------------------------------------------
1.1. Example of the plugin which uses lua modules: *lua-require-example* Example of a plugin that uses lua modules *lua-require-example*
The following example plugin adds a command `:MakeCharBlob` which transforms The following example plugin adds a command `:MakeCharBlob` which transforms
current buffer into a long `unsigned char` array. Lua contains transformation current buffer into a long `unsigned char` array. Lua contains transformation
@@ -149,7 +149,7 @@ lua/charblob.lua: >
} }
============================================================================== ==============================================================================
2. Commands *lua-commands* Commands *lua-commands*
*:lua* *:lua*
:[range]lua {chunk} :[range]lua {chunk}
@@ -157,7 +157,7 @@ lua/charblob.lua: >
Examples: Examples:
> >
:lua vim.api.nvim_command('echo "Hello, Neovim!"') :lua vim.api.nvim_command('echo "Hello, Nvim!"')
< <
:[range]lua << {endmarker} :[range]lua << {endmarker}
@@ -230,27 +230,80 @@ All these commands execute a Lua chunk from either the command line (:lua and
:luado) or a file (:luafile) with the given line [range]. Similarly to the Lua :luado) or a file (:luafile) with the given line [range]. Similarly to the Lua
interpreter, each chunk has its own scope and so only global variables are interpreter, each chunk has its own scope and so only global variables are
shared between command calls. All Lua default libraries are available. In shared between command calls. All Lua default libraries are available. In
addition, Lua "print" function has its output redirected to the Vim message addition, Lua "print" function has its output redirected to the Nvim message
area, with arguments separated by a white space instead of a tab. area, with arguments separated by a white space instead of a tab.
Lua uses the "vim" module (see |lua-vim|) to issue commands to Neovim Lua uses the "vim" module (see |lua-vim|) to issue commands to Nvim
and manage buffers (|lua-buffer|) and windows (|lua-window|). However, and manage buffers (|lua-buffer|) and windows (|lua-window|). However,
procedures that alter buffer content, open new buffers, and change cursor procedures that alter buffer content, open new buffers, and change cursor
position are restricted when the command is executed in the |sandbox|. position are restricted when the command is executed in the |sandbox|.
============================================================================== ==============================================================================
2. The vim module *lua-vim* The vim module *lua-vim*
Lua interfaces Vim through the "vim" module. Currently it only has `api` Lua interfaces Nvim through the "vim" module. Currently it has the `api`
submodule which is a table with all API functions. Descriptions of these submodule and some Nvim-specific utilities.
functions may be found in |api.txt|.
------------------------------------------------------------------------------
vim.api.* functions
`vim.api` exposes the Nvim |API| as a table of Lua functions. All functions
are available.
For example, to use the "nvim_get_current_line()" API function, call
"vim.api.nvim_get_current_line()": >
print(tostring(vim.api.nvim_get_current_line()))
------------------------------------------------------------------------------
vim.* utility functions
vim.stricmp(a, b) *lua-vim.stricmp*
Function used for case-insensitive string comparison. Takes two
string arguments and returns 0, 1 or -1 if strings are equal, a is
greater then b or a is lesser then b respectively.
vim.type_idx *lua-vim.type_idx*
Type index for use in |lua-special-tables|. Specifying one of the
values from |lua-vim.types| allows typing the empty table (it is
unclear whether empty lua table represents empty list or empty array)
and forcing integral numbers to be |Float|. See |lua-special-tbl| for
more details.
vim.val_idx *lua-vim.val_idx*
Value index for tables representing |Float|s. A table representing
floating-point value 1.0 looks like this: >
{
[vim.type_idx] = vim.types.float,
[vim.val_idx] = 1.0,
}
< See also |lua-vim.type_idx| and |lua-special-tbl|.
vim.types *lua-vim.types*
Table with possible values for |lua-vim.type_idx|. Contains two sets
of key-value pairs: first maps possible values for |lua-vim.type_idx|
to human-readable strings, second maps human-readable type names to
values for |lua-vim.type_idx|. Currently contains pairs for `float`,
`array` and `dictionary` types.
Note: one must expect that values corresponding to `vim.types.float`,
`vim.types.array` and `vim.types.dictionary` fall under only two
following assumptions:
1. Value may serve both as a key and as a value in a table. Given the
properties of lua tables this basically means “value is not `nil`”.
2. For each value in `vim.types` table `vim.types[vim.types[value]]`
is the same as `value`.
No other restrictions are put on types, and it is not guaranteed that
values corresponding to `vim.types.float`, `vim.types.array` and
`vim.types.dictionary` will not change or that `vim.types` table will
only contain values for these three types.
============================================================================== ==============================================================================
3. The luaeval function *lua-luaeval* *lua-eval* The luaeval function *lua-luaeval* *lua-eval*
*luaeval()* *luaeval()*
The (dual) equivalent of "vim.eval" for passing Lua values to Vim is The (dual) equivalent of "vim.eval" for passing Lua values to Nvim is
"luaeval". "luaeval" takes an expression string and an optional argument used "luaeval". "luaeval" takes an expression string and an optional argument used
for _A inside expression and returns the result of the expression. It is for _A inside expression and returns the result of the expression. It is
semantically equivalent in Lua to: semantically equivalent in Lua to:
@@ -262,7 +315,7 @@ semantically equivalent in Lua to:
end end
Note that "_A" receives the argument to "luaeval". Lua nils, numbers, strings, Note that "_A" receives the argument to "luaeval". Lua nils, numbers, strings,
tables and booleans are converted to their Vim respective types. An error is tables and booleans are converted to their respective VimL types. An error is
thrown if conversion of any of the remaining Lua types is attempted. thrown if conversion of any of the remaining Lua types is attempted.
Note 2: lua tables are used as both dictionaries and lists, thus making it Note 2: lua tables are used as both dictionaries and lists, thus making it
@@ -278,6 +331,7 @@ between these cases there is the following agreement:
3. Table with string keys, at least one of which contains NUL byte, is also 3. Table with string keys, at least one of which contains NUL byte, is also
considered to be a dictionary, but this time it is converted to considered to be a dictionary, but this time it is converted to
a |msgpack-special-map|. a |msgpack-special-map|.
*lua-special-tbl*
4. Table with `vim.type_idx` key may be a dictionary, a list or floating-point 4. Table with `vim.type_idx` key may be a dictionary, a list or floating-point
value: value:
- `{[vim.type_idx]=vim.types.float, [vim.val_idx]=1}` is converted to - `{[vim.type_idx]=vim.types.float, [vim.val_idx]=1}` is converted to

View File

@@ -8,7 +8,7 @@ The Python Interface to Vim *python* *Python*
See |provider-python| for more information. {Nvim} See |provider-python| for more information. {Nvim}
Type <M-]> to see the table of contents. Type |gO| to see the table of contents.
============================================================================== ==============================================================================
1. Commands *python-commands* 1. Commands *python-commands*

View File

@@ -10,7 +10,7 @@ The Ruby Interface to Vim *ruby* *Ruby*
The home page for ruby is http://www.ruby-lang.org/. You can find links for The home page for ruby is http://www.ruby-lang.org/. You can find links for
downloading Ruby there. downloading Ruby there.
Type <M-]> to see the table of contents. Type |gO| to see the table of contents.
============================================================================== ==============================================================================
1. Commands *ruby-commands* 1. Commands *ruby-commands*

View File

@@ -6,7 +6,7 @@
This file is about indenting C programs and other files. This file is about indenting C programs and other files.
Type <M-]> to see the table of contents. Type |gO| to see the table of contents.
============================================================================== ==============================================================================
1. Indenting C style programs *C-indenting* 1. Indenting C style programs *C-indenting*

View File

@@ -15,7 +15,7 @@ For an overview of built-in functions see |functions|.
For a list of Vim variables see |vim-variable|. For a list of Vim variables see |vim-variable|.
For a complete listing of all help items see |help-tags|. For a complete listing of all help items see |help-tags|.
Type <M-]> to see the table of contents. Type |gO| to see the table of contents.
============================================================================== ==============================================================================
1. Insert mode *insert-index* 1. Insert mode *insert-index*

View File

@@ -16,7 +16,7 @@ user manual |usr_24.txt|.
Also see 'virtualedit', for moving the cursor to positions where there is no Also see 'virtualedit', for moving the cursor to positions where there is no
character. Useful for editing a table. character. Useful for editing a table.
Type <M-]> to see the table of contents. Type |gO| to see the table of contents.
============================================================================== ==============================================================================
1. Special keys *ins-special-keys* 1. Special keys *ins-special-keys*

View File

@@ -6,7 +6,7 @@
Introduction to Vim *ref* *reference* Introduction to Vim *ref* *reference*
Type <M-]> to see the table of contents. Type |gO| to see the table of contents.
============================================================================== ==============================================================================
1. Introduction *intro* 1. Introduction *intro*

View File

@@ -6,7 +6,7 @@
Nvim's facilities for job control *job-control* Nvim's facilities for job control *job-control*
Type <M-]> to see the table of contents. Type |gO| to see the table of contents.
============================================================================== ==============================================================================
1. Introduction *job-control-intro* 1. Introduction *job-control-intro*

View File

@@ -9,7 +9,7 @@ Key mapping, abbreviations and user-defined commands.
This subject is introduced in sections |05.3|, |24.7| and |40.1| of the user This subject is introduced in sections |05.3|, |24.7| and |40.1| of the user
manual. manual.
Type <M-]> to see the table of contents. Type |gO| to see the table of contents.
============================================================================== ==============================================================================
1. Key mapping *key-mapping* *mapping* *macro* 1. Key mapping *key-mapping* *mapping* *macro*

View File

@@ -14,7 +14,7 @@ For an introduction to the most common features, see |usr_45.txt| in the user
manual. manual.
For changing the language of messages and menus see |mlang.txt|. For changing the language of messages and menus see |mlang.txt|.
Type <M-]> to see the table of contents. Type |gO| to see the table of contents.
============================================================================== ==============================================================================
Getting started *mbyte-first* Getting started *mbyte-first*

View File

@@ -8,7 +8,7 @@ This file contains an alphabetical list of messages and error messages that
Vim produces. You can use this if you don't understand what the message Vim produces. You can use this if you don't understand what the message
means. It is not complete though. means. It is not complete though.
Type <M-]> to see the table of contents. Type |gO| to see the table of contents.
============================================================================== ==============================================================================
1. Old messages *:messages* *:mes* *message-history* 1. Old messages *:messages* *:mes* *message-history*

View File

@@ -11,7 +11,7 @@ multi-byte text see |multibyte|.
The basics are explained in the user manual: |usr_45.txt|. The basics are explained in the user manual: |usr_45.txt|.
Type <M-]> to see the table of contents. Type |gO| to see the table of contents.
============================================================================== ==============================================================================
1. Messages *multilang-messages* 1. Messages *multilang-messages*

View File

@@ -26,7 +26,7 @@ The 'virtualedit' option can be set to make it possible to move the cursor to
positions where there is no character or within a multi-column character (like positions where there is no character or within a multi-column character (like
a tab). a tab).
Type <M-]> to see the table of contents. Type |gO| to see the table of contents.
============================================================================== ==============================================================================
1. Motions and operators *operator* 1. Motions and operators *operator*
@@ -886,6 +886,7 @@ was made yet in the current file.
then the position can be near the end of what the then the position can be near the end of what the
command changed. For example when inserting a word, command changed. For example when inserting a word,
the position will be on the last character. the position will be on the last character.
To jump to older changes use |g;|.
*'(* *`(* *'(* *`(*
'( `( To the start of the current sentence, like the |(| '( `( To the start of the current sentence, like the |(|

View File

@@ -6,7 +6,7 @@
RPC API for Nvim *RPC* *rpc* *msgpack-rpc* RPC API for Nvim *RPC* *rpc* *msgpack-rpc*
Type <M-]> to see the table of contents. Type |gO| to see the table of contents.
============================================================================== ==============================================================================
1. Introduction *rpc-intro* 1. Introduction *rpc-intro*
@@ -243,203 +243,4 @@ Even for statically compiled clients it is good practice to avoid hardcoding
the type codes, because a client may be built against one Nvim version but the type codes, because a client may be built against one Nvim version but
connect to another with different type codes. connect to another with different type codes.
==============================================================================
6. Remote UIs *rpc-remote-ui*
GUIs can be implemented as external processes communicating with Nvim over the
RPC API. The UI model consists of a terminal-like grid with a single,
monospace font size. Some elements (UI "widgets") can be drawn separately from
the grid ("externalized").
After connecting to Nvim (usually a spawned, embedded instance) use the
|nvim_ui_attach| API method to tell Nvim that your program wants to draw the
Nvim screen on a grid of width × height cells. `options` must be
a dictionary with these (optional) keys:
`rgb` Controls what color format to use.
Set to true (default) to use 24-bit rgb
colors.
Set to false to use terminal color codes (at
most 256 different colors).
`ext_popupmenu` Externalize the popupmenu. |ui-ext-popupmenu|
`ext_tabline` Externalize the tabline. |ui-ext-tabline|
Externalized widgets will not be drawn by
Nvim; only high-level data will be published
in new UI event kinds.
Nvim will then send msgpack-rpc notifications, with the method name "redraw"
and a single argument, an array of screen updates (described below). These
should be processed in order. Preferably the user should only be able to see
the screen state after all updates in the same "redraw" event are processed
(not any intermediate state after processing only a part of the array).
Future versions of Nvim may add new update kinds and may append new parameters
to existing update kinds. Clients must be prepared to ignore such extensions
to be forward-compatible. |api-contract|
Screen updates are tuples whose first element is the string name of the update
kind.
["resize", width, height]
The grid is resized to `width` and `height` cells.
["clear"]
Clear the screen.
["eol_clear"]
Clear from the cursor position to the end of the current line.
["cursor_goto", row, col]
Move the cursor to position (row, col). Currently, the same cursor is
used to define the position for text insertion and the visible cursor.
However, only the last cursor position, after processing the entire
array in the "redraw" event, is intended to be a visible cursor
position.
["update_fg", color]
["update_bg", color]
["update_sp", color]
Set the default foreground, background and special colors
respectively.
["highlight_set", attrs]
Set the attributes that the next text put on the screen will have.
`attrs` is a dict with the keys below. Any absent key is reset
to its default value. Color defaults are set by the `update_fg` etc
updates. All boolean keys default to false.
`foreground`: foreground color.
`background`: backround color.
`special`: color to use for underline and undercurl, when present.
`reverse`: reverse video. Foreground and background colors are
switched.
`italic`: italic text.
`bold`: bold text.
`underline`: underlined text. The line has `special` color.
`undercurl`: undercurled text. The curl has `special` color.
["put", text]
The (utf-8 encoded) string `text` is put at the cursor position
(and the cursor is advanced), with the highlights as set by the
last `highlight_set` update.
["set_scroll_region", top, bot, left, right]
Define the scroll region used by `scroll` below.
["scroll", count]
Scroll the text in the scroll region. The diagrams below illustrate
what will happen, depending on the scroll direction. "=" is used to
represent the SR(scroll region) boundaries and "-" the moved rectangles.
Note that dst and src share a common region.
If count is bigger than 0, move a rectangle in the SR up, this can
happen while scrolling down.
>
+-------------------------+
| (clipped above SR) | ^
|=========================| dst_top |
| dst (still in SR) | |
+-------------------------+ src_top |
| src (moved up) and dst | |
|-------------------------| dst_bot |
| src (cleared) | |
+=========================+ src_bot
<
If count is less than zero, move a rectangle in the SR down, this can
happen while scrolling up.
>
+=========================+ src_top
| src (cleared) | |
|------------------------ | dst_top |
| src (moved down) and dst| |
+-------------------------+ src_bot |
| dst (still in SR) | |
|=========================| dst_bot |
| (clipped below SR) | v
+-------------------------+
<
["set_title", title]
["set_icon", icon]
Set the window title, and icon (minimized) window title, respectively.
In windowing systems not distinguishing between the two, "set_icon"
can be ignored.
["mouse_on"]
["mouse_off"]
Tells the client whether mouse support, as determined by |'mouse'|
option, is considered to be active in the current mode. This is mostly
useful for a terminal frontend, or other situations where nvim mouse
would conflict with other usages of the mouse. It is safe for a client
to ignore this and always send mouse events.
["busy_on"]
["busy_off"]
Nvim started or stopped being busy, and possibly not responsible to user
input. This could be indicated to the user by hiding the cursor.
["suspend"]
|:suspend| command or |Ctrl-Z| mapping is used. A terminal client (or other
client where it makes sense) could suspend itself. Other clients can
safely ignore it.
["bell"]
["visual_bell"]
Notify the user with an audible or visual bell, respectively.
["update_menu"]
The menu mappings changed.
["mode_info_set", cursor_style_enabled, mode_info]
`cursor_style_enabled` is a boolean indicating if the UI should set the cursor
style. `mode_info` is a list of mode property maps. The current mode is given
by the `mode_idx` field of the `mode_change` event.
Each mode property map may contain these keys:
KEY DESCRIPTION ~
`cursor_shape`: "block", "horizontal", "vertical"
`cell_percentage`: Cell % occupied by the cursor.
`blinkwait`, `blinkon`, `blinkoff`: See |cursor-blinking|.
`hl_id`: Cursor highlight group.
`hl_lm`: Cursor highlight group if 'langmap' is active.
`short_name`: Mode code name, see 'guicursor'.
`name`: Mode descriptive name.
`mouse_shape`: (To be implemented.)
Some keys are missing in some modes.
["mode_change", mode, mode_idx]
The mode changed. The first parameter `mode` is a string representing the
current mode. `mode_idx` is an index into the array received in the
`mode_info_set` event. UIs should change the cursor style according to the
properties specified in the corresponding item. The set of modes reported will
change in new versions of Nvim, for instance more submodes and temporary
states might be represented as separate modes.
*ui-ext-popupmenu*
["popupmenu_show", items, selected, row, col]
When `popupmenu_external` is set to true, nvim will not draw the
popupmenu on the grid, instead when the popupmenu is to be displayed
this update is sent. `items` is an array of the items to show, the
items are themselves arrays of the form [word, kind, menu, info]
as defined at |complete-items|, except that `word` is replaced by
`abbr` if present. `selected` is the initially selected item, either a
zero-based index into the array of items, or -1 if no item is
selected. `row` and `col` is the anchor position, where the first
character of the completed word will be.
["popupmenu_select", selected]
An item in the currently displayed popupmenu is selected. `selected`
is either a zero-based index into the array of items from the last
`popupmenu_show` event, or -1 if no item is selected.
["popupmenu_hide"]
The popupmenu is hidden.
*ui-ext-tabline*
["tabline_update", curtab, tabs]
Tabline was updated. UIs should present this data in a custom tabline
widget.
curtab: Current Tabpage
tabs: List of Dicts [{ "tab": Tabpage, "name": String }, ...]
==============================================================================
vim:tw=78:ts=8:noet:ft=help:norl:

View File

@@ -15,7 +15,7 @@ Nvim is emphatically a fork of Vim, not a clone: compatibility with Vim is
maintained where possible. See |vim_diff.txt| for the complete reference of maintained where possible. See |vim_diff.txt| for the complete reference of
differences from Vim. differences from Vim.
Type <M-]> to see the table of contents. Type |gO| to see the table of contents.
============================================================================== ==============================================================================
Transitioning from Vim *nvim-from-vim* Transitioning from Vim *nvim-from-vim*

View File

@@ -18,7 +18,7 @@ Terminal buffers behave like normal buffers, except:
closing the terminal buffer. closing the terminal buffer.
- 'bufhidden' defaults to "hide". - 'bufhidden' defaults to "hide".
Type <M-]> to see the table of contents. Type |gO| to see the table of contents.
============================================================================== ==============================================================================
Start *terminal-start* Start *terminal-start*

View File

@@ -14,7 +14,7 @@ achieve special effects. These options come in three forms:
number has a numeric value number has a numeric value
string has a string value string has a string value
Type <M-]> to see the table of contents. Type |gO| to see the table of contents.
============================================================================== ==============================================================================
1. Setting options *set-option* *E764* 1. Setting options *set-option* *E764*
@@ -187,7 +187,7 @@ opt+=val" the expansion is done before the adding or removing.
Handling of local options *local-options* Handling of local options *local-options*
Some of the options only apply to a window or buffer. Each window or buffer Some of the options only apply to a window or buffer. Each window or buffer
has its own copy of this option, thus can each have their own value. This has its own copy of this option, thus each can have its own value. This
allows you to set 'list' in one window but not in another. And set allows you to set 'list' in one window but not in another. And set
'shiftwidth' to 3 in one buffer and 4 in another. 'shiftwidth' to 3 in one buffer and 4 in another.
@@ -3017,6 +3017,8 @@ A jump table for the options with a short description can be found at |Q_op|.
The format of this option is like that of 'statusline'. The format of this option is like that of 'statusline'.
'guitabtooltip' is used for the tooltip, see below. 'guitabtooltip' is used for the tooltip, see below.
The expression will be evaluated in the |sandbox| when set from a
modeline, see |sandbox-option|.
Only used when the GUI tab pages line is displayed. 'e' must be Only used when the GUI tab pages line is displayed. 'e' must be
present in 'guioptions'. For the non-GUI tab pages line 'tabline' is present in 'guioptions'. For the non-GUI tab pages line 'tabline' is
@@ -4482,6 +4484,8 @@ A jump table for the options with a short description can be found at |Q_op|.
and |+postscript| features} and |+postscript| features}
Expression used to print the PostScript produced with |:hardcopy|. Expression used to print the PostScript produced with |:hardcopy|.
See |pexpr-option|. See |pexpr-option|.
This option cannot be set from a |modeline| or in the |sandbox|, for
security reasons.
*'printfont'* *'pfn'* *'printfont'* *'pfn'*
'printfont' 'pfn' string (default "courier") 'printfont' 'pfn' string (default "courier")

View File

@@ -9,7 +9,7 @@ Patterns and search commands *pattern-searches*
The very basics can be found in section |03.9| of the user manual. A few more The very basics can be found in section |03.9| of the user manual. A few more
explanations are in chapter 27 |usr_27.txt|. explanations are in chapter 27 |usr_27.txt|.
Type <M-]> to see the table of contents. Type |gO| to see the table of contents.
============================================================================== ==============================================================================
1. Search commands *search-commands* 1. Search commands *search-commands*

View File

@@ -2,53 +2,45 @@
Author: TJ DeVries <devries.timothyj@gmail.com> Author: TJ DeVries <devries.timothyj@gmail.com>
Type <M-]> to see the table of contents. Type |gO| to see the table of contents.
============================================================================== ==============================================================================
Introduction *healthcheck* *health.vim-intro* Introduction *health*
Troubleshooting user configuration problems is a time-consuming task that health.vim is a minimal framework to help with troubleshooting user
developers want to minimize. health.vim provides a simple framework for plugin configuration. Nvim ships with healthchecks for configuration, performance,
authors to hook into, and for users to invoke, to check and report the user's python support, ruby support, clipboard support, and more.
configuration and environment. Type this command to try it: >
:CheckHealth To run the healthchecks, use this command: >
:checkhealth
< <
For example, some users have broken or unusual Python setups, which breaks the Plugin authors are encouraged to write new healthchecks. |health-dev|
|:python| command. |:CheckHealth| detects several common Python configuration
problems and reports them. If the Neovim Python module is not installed, it
shows a warning: >
You have not installed the Neovim Python module
You might want to try `pip install Neovim`
<
Plugin authors are encouraged to add healthchecks, see |health.vim-dev|.
============================================================================== ==============================================================================
Commands and functions *health.vim-manual* Commands *health-commands*
Commands *:checkhealth* *:CheckHealth*
------------------------------------------------------------------------------ :checkhealth Run all healthchecks.
*:CheckHealth* *E5009*
:CheckHealth Run all healthchecks and show the output in a new Nvim depends on the |$VIMRUNTIME| environment variable
tabpage. These healthchecks are included by default: to find the standard "runtime files" for syntax
- python2 highlighting, filetype-specific behavior, and standard
- python3 plugins such as :checkhealth. If $VIMRUNTIME is invalid
- ruby then those features will not work.
- remote plugin
:CheckHealth {plugins} :checkhealth {plugins}
Run healthchecks for one or more plugins. E.g. to run Run healthcheck(s) for one or more plugins. E.g. to run
only the standard Nvim healthcheck: > only the standard Nvim healthcheck: >
:CheckHealth nvim :checkhealth nvim
< To run the healthchecks for the "foo" and "bar" plugins < To run the healthchecks for the "foo" and "bar" plugins
(assuming these plugins are on your 'runtimepath' and (assuming these plugins are on your 'runtimepath' and
they have implemented health#foo#check() and they have implemented health#foo#check() and
health#bar#check(), respectively): > health#bar#check(), respectively): >
:CheckHealth foo bar :checkhealth foo bar
< <
Functions ==============================================================================
------------------------------------------------------------------------------ Functions *health-functions*
health.vim functions are for creating new healthchecks. They mostly just do health.vim functions are for creating new healthchecks. They mostly just do
some layout and formatting, to give users a consistent presentation. some layout and formatting, to give users a consistent presentation.
@@ -59,51 +51,49 @@ health#report_start({name}) *health#report_start*
per section. per section.
health#report_info({msg}) *health#report_info* health#report_info({msg}) *health#report_info*
Displays an informational message. Reports an informational message.
health#report_ok({msg}) *health#report_ok* health#report_ok({msg}) *health#report_ok*
Displays a "success" message. Reports a "success" message.
health#report_warn({msg}, [{advice}]) *health#report_warn* health#report_warn({msg}, [{advice}]) *health#report_warn*
Displays a warning. {advice} is an optional List of suggestions. Reports a warning. {advice} is an optional List of suggestions.
health#report_error({msg}, [{advice}]) *health#report_error* health#report_error({msg}, [{advice}]) *health#report_error*
Displays an error. {advice} is an optional List of suggestions. Reports 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 Healthcheck function for {plugin}. Called by |:checkhealth|
from this function, then |:CheckHealth| does the rest. Example: > automatically. Example: >
function! health#my_plug#check() abort function! health#my_plug#check() abort
silent call s:check_environment_vars() silent call s:check_environment_vars()
silent call s:check_python_configuration() silent call s:check_python_configuration()
endfunction endfunction
< <
The function will be found and called automatically when the user
invokes |:CheckHealth|.
All output will be captured from the healthcheck. Use the All output will be captured from the healthcheck. Use the
health#report_* functions so that your healthcheck has a format health#report_* functions so that your healthcheck has a format
consistent with the standard healthchecks. consistent with the standard healthchecks.
============================================================================== ==============================================================================
Create a healthcheck *health.vim-dev* Create a healthcheck *health-dev*
Healthchecks are functions that check the health of the system. Neovim has Healthchecks are functions that check the user environment, configuration,
built-in checkers, found in $VIMRUNTIME/autoload/health/. etc. Nvim has built-in healthchecks in $VIMRUNTIME/autoload/health/.
To add a new checker for your own plugin, simply define a To add a new healthcheck for your own plugin, simply define a
health#{plugin}#check() function in autoload/health/{plugin}.vim. health#{plugin}#check() function in autoload/health/{plugin}.vim.
|:CheckHealth| automatically finds and invokes such functions. |:checkhealth| automatically finds and invokes such functions.
If your plugin is named "jslint", then its healthcheck function must be > If your plugin is named "foo", then its healthcheck function must be >
health#jslint#check() health#foo#check()
defined in this file on 'runtimepath': > defined in this file on 'runtimepath': >
autoload/health/jslint.vim autoload/health/foo.vim
Here's a sample to get started: > Copy this sample code into autoload/health/foo.vim and replace "foo" with your
function! health#jslint#check() abort plugin name: >
function! health#foo#check() abort
call health#report_start('sanity checks') call health#report_start('sanity checks')
" perform arbitrary checks " perform arbitrary checks
" ... " ...
@@ -111,8 +101,8 @@ Here's a sample to get started: >
if looks_good if looks_good
call health#report_ok('found required dependencies') call health#report_ok('found required dependencies')
else else
call health#report_error('cannot find jslint', call health#report_error('cannot find foo',
\ ['npm install --save jslint']) \ ['npm install --save foo'])
endif endif
endfunction endfunction

View File

@@ -6,7 +6,7 @@
Printing *printing* Printing *printing*
Type <M-]> to see the table of contents. Type |gO| to see the table of contents.
============================================================================== ==============================================================================
1. Introduction *print-intro* 1. Introduction *print-intro*

View File

@@ -8,7 +8,7 @@ Providers *provider*
Nvim delegates some features to dynamic "providers". Nvim delegates some features to dynamic "providers".
Type <M-]> to see the table of contents. Type |gO| to see the table of contents.
============================================================================== ==============================================================================
Python integration *provider-python* Python integration *provider-python*
@@ -20,7 +20,7 @@ Note: Only the Vim 7.3 API is supported; bindeval (Vim 7.4) is not.
PYTHON QUICKSTART ~ PYTHON QUICKSTART ~
If you used a package manager to install Nvim, you might already have the If you used a package manager to install Nvim, you might already have the
required `neovim` Python package. Run |:CheckHealth| to see if your system is required `neovim` Python package. Run |:checkhealth| to see if your system is
up-to-date. up-to-date.
Following are steps to install the package with Python's `pip` tool. Following are steps to install the package with Python's `pip` tool.
@@ -88,7 +88,7 @@ Ruby integration *provider-ruby*
Nvim supports the Vim legacy |ruby-vim| interface via external Ruby Nvim supports the Vim legacy |ruby-vim| interface via external Ruby
interpreters connected via |RPC|. interpreters connected via |RPC|.
Run |:CheckHealth| to see if your system is up-to-date. Run |:checkhealth| to see if your system is up-to-date.
RUBY QUICKSTART ~ RUBY QUICKSTART ~

View File

@@ -6,7 +6,7 @@
This subject is introduced in section |30.1| of the user manual. This subject is introduced in section |30.1| of the user manual.
Type <M-]> to see the table of contents. Type |gO| to see the table of contents.
============================================================================= =============================================================================
1. Using QuickFix commands *quickfix* *Quickfix* *E42* 1. Using QuickFix commands *quickfix* *Quickfix* *E42*
@@ -138,11 +138,15 @@ processing a quickfix or location list command, it will be aborted.
current window is used instead of the quickfix list. current window is used instead of the quickfix list.
*:cq* *:cquit* *:cq* *:cquit*
:cq[uit][!] Quit Vim with an error code, so that the compiler :[count]cq[uit] Quit Nvim with an error code, or the code specified in
will not compile the same file again. [count]. Useful when Nvim is called from another
WARNING: All changes in files are lost! Also when the program: e.g. `git commit` will abort the comitting
[!] is not used. It works like ":qall!" |:qall|, process, `fc` (built-in for shells like bash and zsh)
except that Vim returns a non-zero exit code. will not execute the command.
WARNING: All changes in files are lost. It works like
":qall!" |:qall|, except that Nvim exits non-zero or
[count].
*:cf* *:cfile* *:cf* *:cfile*
:cf[ile][!] [errorfile] Read the error file and jump to the first error. :cf[ile][!] [errorfile] Read the error file and jump to the first error.
@@ -1534,4 +1538,4 @@ by Vim.
vim:tw=78:ts=8:ft=help:norl: vim:noet:tw=78:ts=8:ft=help:norl:

View File

@@ -15,7 +15,7 @@ You can recover most of your changes from the files that Vim uses to store
the contents of the file. Mostly you can recover your work with one command: the contents of the file. Mostly you can recover your work with one command:
vim -r filename vim -r filename
Type <M-]> to see the table of contents. Type |gO| to see the table of contents.
============================================================================== ==============================================================================
1. The swap file *swap-file* 1. The swap file *swap-file*

View File

@@ -6,7 +6,7 @@
Vim client-server communication *client-server* Vim client-server communication *client-server*
Type <M-]> to see the table of contents. Type |gO| to see the table of contents.
============================================================================== ==============================================================================
1. Common functionality *clientserver* 1. Common functionality *clientserver*

View File

@@ -6,7 +6,7 @@
Nvim support for remote plugins *remote-plugin* Nvim support for remote plugins *remote-plugin*
Type <M-]> to see the table of contents. Type |gO| to see the table of contents.
============================================================================== ==============================================================================
1. Introduction *remote-plugin-intro* 1. Introduction *remote-plugin-intro*

View File

@@ -8,7 +8,7 @@ Repeating commands, Vim scripts and debugging *repeating*
Chapter 26 of the user manual introduces repeating |usr_26.txt|. Chapter 26 of the user manual introduces repeating |usr_26.txt|.
Type <M-]> to see the table of contents. Type |gO| to see the table of contents.
============================================================================== ==============================================================================
1. Single repeats *single-repeat* 1. Single repeats *single-repeat*

View File

@@ -6,7 +6,7 @@
Russian language localization and support in Vim *russian* *Russian* Russian language localization and support in Vim *russian* *Russian*
Type <M-]> to see the table of contents. Type |gO| to see the table of contents.
=============================================================================== ===============================================================================
1. Introduction *russian-intro* 1. Introduction *russian-intro*

View File

@@ -16,7 +16,7 @@ upwards in the buffer, the text in the window moves downwards on your screen.
See section |03.7| of the user manual for an introduction. See section |03.7| of the user manual for an introduction.
Type <M-]> to see the table of contents. Type |gO| to see the table of contents.
============================================================================== ==============================================================================
1. Scrolling downwards *scroll-down* 1. Scrolling downwards *scroll-down*

View File

@@ -7,7 +7,7 @@
Sign Support Features *sign-support* Sign Support Features *sign-support*
Type <M-]> to see the table of contents. Type |gO| to see the table of contents.
============================================================================== ==============================================================================
1. Introduction *sign-intro* *signs* 1. Introduction *sign-intro* *signs*

View File

@@ -6,7 +6,7 @@
Spell checking *spell* Spell checking *spell*
Type <M-]> to see the table of contents. Type |gO| to see the table of contents.
============================================================================== ==============================================================================
1. Quick start *spell-quickstart* *E756* 1. Quick start *spell-quickstart* *E756*

View File

@@ -6,7 +6,7 @@
Starting Vim *starting* Starting Vim *starting*
Type <M-]> to see the table of contents. Type |gO| to see the table of contents.
============================================================================== ==============================================================================
1. Vim arguments *vim-arguments* 1. Vim arguments *vim-arguments*
@@ -633,54 +633,40 @@ though.
============================================================================== ==============================================================================
3. $VIM and $VIMRUNTIME 3. $VIM and $VIMRUNTIME
*$VIM* *$VIM*
The environment variable "$VIM" is used to locate various user files for Vim, The environment variable "$VIM" is used to locate various user files for Nvim,
such as the user startup script |init.vim|. This depends on the system, see such as the user startup script |init.vim|. This depends on the system, see
|startup|. |startup|.
To avoid the need for every user to set the $VIM environment variable, Vim Nvim will try to get the value for $VIM in this order:
will try to get the value for $VIM in this order:
1. The value defined by the $VIM environment variable. You can use this to 1. Environment variable $VIM, if it is set.
make Vim look in a specific directory for its support files. Example: > 2. Path derived from the 'helpfile' option, unless it contains some
setenv VIM /home/paul/vim environment variable too (default is "$VIMRUNTIME/doc/help.txt"). File
2. The path from 'helpfile' is used, unless it contains some environment name ("help.txt", etc.) is removed. Trailing directory names are removed,
variable too (the default is "$VIMRUNTIME/doc/help.txt": chicken-egg in this order: "doc", "runtime".
problem). The file name ("help.txt" or any other) is removed. Then 3. Path derived from the location of the `nvim` executable.
trailing directory names are removed, in this order: "doc", "runtime" and 4. Compile-time defined installation directory (see output of ":version").
"vim{version}" (e.g., "vim54").
3. For MSDOS and Win32 Vim tries to use the directory name of the After doing this once, Nvim sets the $VIM environment variable.
executable. If it ends in "/src", this is removed. This is useful if you
unpacked the .zip file in some directory, and adjusted the search path to
find the vim executable. Trailing directory names are removed, in this
order: "runtime" and "vim{version}" (e.g., "vim54").
4. For Unix the compile-time defined installation directory is used (see the
output of ":version").
Once Vim has done this once, it will set the $VIM environment variable. To
change it later, use a ":let" command like this: >
:let $VIM = "/home/paul/vim/"
<
*$VIMRUNTIME* *$VIMRUNTIME*
The environment variable "$VIMRUNTIME" is used to locate various support The environment variable "$VIMRUNTIME" is used to locate various support
files, such as the on-line documentation and files used for syntax files, such as the documentation and syntax-highlighting files. For example,
highlighting. For example, the main help file is normally the main help file is normally "$VIMRUNTIME/doc/help.txt".
"$VIMRUNTIME/doc/help.txt".
You don't normally set $VIMRUNTIME yourself, but let Vim figure it out. This
is the order used to find the value of $VIMRUNTIME:
1. If the environment variable $VIMRUNTIME is set, it is used. You can use
this when the runtime files are in an unusual location.
2. If "$VIM/vim{version}" exists, it is used. {version} is the version
number of Vim, without any '-' or '.'. For example: "$VIM/vim54". This is
the normal value for $VIMRUNTIME.
3. If "$VIM/runtime" exists, it is used.
4. The value of $VIM is used. This is for backwards compatibility with older
versions.
5. If "../share/nvim/runtime" exists relative to |v:progpath|, it is used.
6. When the 'helpfile' option is set and doesn't contain a '$', its value is
used, with "doc/help.txt" removed from the end.
Once Vim has done this once, it will set the $VIMRUNTIME environment variable. Nvim will try to get the value for $VIMRUNTIME in this order:
To change it later, use a ":let" command like this: >
:let $VIMRUNTIME = "/home/piet/vim/vim54" 1. Environment variable $VIMRUNTIME, if it is set.
2. Directory path "$VIM/vim{version}", if it exists, where {version} is the
Vim version number without '-' or '.'. For example: "$VIM/vim54".
3. Directory path "$VIM/runtime", if it exists.
4. Value of $VIM environment variable. This is for backwards compatibility
with older Vim versions.
5. If "../share/nvim/runtime" exists relative to |v:progpath|, it is used.
6. Path derived from the 'helpfile' option (if it doesn't contain '$') with
"doc/help.txt" removed from the end.
After doing this once, Nvim sets the $VIMRUNTIME environment variable.
In case you need the value of $VIMRUNTIME in a shell (e.g., for a script that In case you need the value of $VIMRUNTIME in a shell (e.g., for a script that
greps in the help files) you might be able to use this: > greps in the help files) you might be able to use this: >

View File

@@ -20,7 +20,7 @@ In the User Manual:
|usr_06.txt| introduces syntax highlighting. |usr_06.txt| introduces syntax highlighting.
|usr_44.txt| introduces writing a syntax file. |usr_44.txt| introduces writing a syntax file.
Type <M-]> to see the table of contents. Type |gO| to see the table of contents.
============================================================================== ==============================================================================
1. Quick start *:syn-qstart* 1. Quick start *:syn-qstart*

View File

@@ -10,7 +10,7 @@ The commands which have been added to use multiple tab pages are explained
here. Additionally, there are explanations for commands that work differently here. Additionally, there are explanations for commands that work differently
when used in combination with more than one tab page. when used in combination with more than one tab page.
Type <M-]> to see the table of contents. Type |gO| to see the table of contents.
============================================================================== ==============================================================================
1. Introduction *tab-page-intro* 1. Introduction *tab-page-intro*

View File

@@ -8,7 +8,7 @@ Tags and special searches *tags-and-searches*
See section |29.1| of the user manual for an introduction. See section |29.1| of the user manual for an introduction.
Type <M-]> to see the table of contents. Type |gO| to see the table of contents.
============================================================================== ==============================================================================
1. Jump to a tag *tag-commands* 1. Jump to a tag *tag-commands*

View File

@@ -10,7 +10,7 @@ Nvim (except in |--headless| mode) uses information about the terminal you are
using to present a built-in UI. If that information is not correct, the using to present a built-in UI. If that information is not correct, the
screen may be messed up or keys may not be recognized. screen may be messed up or keys may not be recognized.
Type <M-]> to see the table of contents. Type |gO| to see the table of contents.
============================================================================== ==============================================================================
Startup *startup-terminal* Startup *startup-terminal*

View File

@@ -13,7 +13,7 @@ http://www.vim.org
Don't forget to browse the user manual, it also contains lots of useful tips Don't forget to browse the user manual, it also contains lots of useful tips
|usr_toc.txt|. |usr_toc.txt|.
Type <M-]> to see the table of contents. Type |gO| to see the table of contents.
============================================================================== ==============================================================================
Editing C programs *C-editing* Editing C programs *C-editing*

290
runtime/doc/ui.txt Normal file
View File

@@ -0,0 +1,290 @@
*ui.txt* Nvim
NVIM REFERENCE MANUAL
Nvim UI protocol *ui*
Type |gO| to see the table of contents.
==============================================================================
Introduction *ui-intro*
GUIs can be implemented as external processes communicating with Nvim over the
RPC API. The UI model consists of a terminal-like grid with a single,
monospace font size. Some elements (UI "widgets") can be drawn separately from
the grid ("externalized").
*ui-options*
After connecting to Nvim (usually a spawned, embedded instance) use the
|nvim_ui_attach| API method to tell Nvim that your program wants to draw the
Nvim screen grid with a size of width × height cells. `options` must be
a dictionary with these (optional) keys:
`rgb` Decides the color format.
Set true (default) for 24-bit RGB colors.
Set false for terminal colors (max of 256).
*ui-ext-options*
`ext_popupmenu` Externalize the popupmenu. |ui-popupmenu|
`ext_tabline` Externalize the tabline. |ui-tabline|
`ext_cmdline` Externalize the cmdline. |ui-cmdline|
Nvim will then send msgpack-rpc notifications, with the method name "redraw"
and a single argument, an array of screen update events.
Update events are tuples whose first element is the event name and remaining
elements the event parameters.
Events must be handled in order. The user should only see the updated screen
state after all events in the same "redraw" batch are processed (not any
intermediate state after processing only part of the array).
Nvim sends |ui-global| and |ui-grid| events unconditionally; these suffice to
implement a terminal-like interface.
Nvim optionally sends screen elements "semantically" as structured events
instead of raw grid-lines. Then the UI must decide how to present those
elements itself; Nvim will not draw those elements on the grid. This is
controlled by the |ui-ext-options|.
Future versions of Nvim may add new update kinds and may append new parameters
to existing update kinds. Clients must be prepared to ignore such extensions
to be forward-compatible. |api-contract|
==============================================================================
Global Events *ui-global*
["set_title", title]
["set_icon", icon]
Set the window title, and icon (minimized) window title, respectively.
In windowing systems not distinguishing between the two, "set_icon"
can be ignored.
["mode_info_set", cursor_style_enabled, mode_info]
`cursor_style_enabled` is a boolean indicating if the UI should set
the cursor style. `mode_info` is a list of mode property maps. The
current mode is given by the `mode_idx` field of the `mode_change`
event.
Each mode property map may contain these keys:
KEY DESCRIPTION ~
`cursor_shape`: "block", "horizontal", "vertical"
`cell_percentage`: Cell % occupied by the cursor.
`blinkwait`, `blinkon`, `blinkoff`: See |cursor-blinking|.
`hl_id`: Cursor highlight group.
`hl_lm`: Cursor highlight group if 'langmap' is active.
`short_name`: Mode code name, see 'guicursor'.
`name`: Mode descriptive name.
`mouse_shape`: (To be implemented.)
Some keys are missing in some modes.
["mode_change", mode, mode_idx]
The mode changed. The first parameter `mode` is a string representing
the current mode. `mode_idx` is an index into the array received in
the `mode_info_set` event. UIs should change the cursor style
according to the properties specified in the corresponding item. The
set of modes reported will change in new versions of Nvim, for
instance more submodes and temporary states might be represented as
separate modes.
["mouse_on"]
["mouse_off"]
Tells the client whether mouse support, as determined by |'mouse'|
option, is considered to be active in the current mode. This is mostly
useful for a terminal frontend, or other situations where nvim mouse
would conflict with other usages of the mouse. It is safe for a client
to ignore this and always send mouse events.
["busy_on"]
["busy_off"]
Nvim started or stopped being busy, and possibly not responsive to
user input. This could be indicated to the user by hiding the cursor.
["suspend"]
|:suspend| command or |Ctrl-Z| mapping is used. A terminal client (or other
client where it makes sense) could suspend itself. Other clients can
safely ignore it.
["update_menu"]
The menu mappings changed.
["bell"]
["visual_bell"]
Notify the user with an audible or visual bell, respectively.
==============================================================================
Grid Events *ui-grid*
["resize", width, height]
The grid is resized to `width` and `height` cells.
["clear"]
Clear the grid.
["eol_clear"]
Clear from the cursor position to the end of the current line.
["cursor_goto", row, col]
Move the cursor to position (row, col). Currently, the same cursor is
used to define the position for text insertion and the visible cursor.
However, only the last cursor position, after processing the entire
array in the "redraw" event, is intended to be a visible cursor
position.
["update_fg", color]
["update_bg", color]
["update_sp", color]
Set the default foreground, background and special colors
respectively.
*ui-event-highlight_set*
["highlight_set", attrs]
Set the attributes that the next text put on the grid will have.
`attrs` is a dict with the keys below. Any absent key is reset
to its default value. Color defaults are set by the `update_fg` etc
updates. All boolean keys default to false.
`foreground`: foreground color.
`background`: backround color.
`special`: color to use for underline and undercurl, when present.
`reverse`: reverse video. Foreground and background colors are
switched.
`italic`: italic text.
`bold`: bold text.
`underline`: underlined text. The line has `special` color.
`undercurl`: undercurled text. The curl has `special` color.
["put", text]
The (utf-8 encoded) string `text` is put at the cursor position
(and the cursor is advanced), with the highlights as set by the
last `highlight_set` update.
["set_scroll_region", top, bot, left, right]
Define the scroll region used by `scroll` below.
["scroll", count]
Scroll the text in the scroll region. The diagrams below illustrate
what will happen, depending on the scroll direction. "=" is used to
represent the SR(scroll region) boundaries and "-" the moved rectangles.
Note that dst and src share a common region.
If count is bigger than 0, move a rectangle in the SR up, this can
happen while scrolling down.
>
+-------------------------+
| (clipped above SR) | ^
|=========================| dst_top |
| dst (still in SR) | |
+-------------------------+ src_top |
| src (moved up) and dst | |
|-------------------------| dst_bot |
| src (cleared) | |
+=========================+ src_bot
<
If count is less than zero, move a rectangle in the SR down, this can
happen while scrolling up.
>
+=========================+ src_top
| src (cleared) | |
|------------------------ | dst_top |
| src (moved down) and dst| |
+-------------------------+ src_bot |
| dst (still in SR) | |
|=========================| dst_bot |
| (clipped below SR) | v
+-------------------------+
<
==============================================================================
Popupmenu Events *ui-popupmenu*
Only sent if `ext_popupmenu` option is set in |ui-options|
["popupmenu_show", items, selected, row, col]
`items` is an array of the items to show, the
items are themselves arrays of the form [word, kind, menu, info]
as defined at |complete-items|, except that `word` is replaced by
`abbr` if present. `selected` is the initially selected item, either a
zero-based index into the array of items, or -1 if no item is
selected. `row` and `col` is the anchor position, where the first
character of the completed word will be.
["popupmenu_select", selected]
An item in the currently displayed popupmenu is selected. `selected`
is either a zero-based index into the array of items from the last
`popupmenu_show` event, or -1 if no item is selected.
["popupmenu_hide"]
The popupmenu is hidden.
==============================================================================
Tabline Events *ui-tabline*
Only sent if `ext_tabline` option is set in |ui-options|
["tabline_update", curtab, tabs]
Tabline was updated. UIs should present this data in a custom tabline
widget.
curtab: Current Tabpage
tabs: List of Dicts [{ "tab": Tabpage, "name": String }, ...]
==============================================================================
Cmdline Events *ui-cmdline*
Only sent if `ext_cmdline` option is set in |ui-options|
["cmdline_show", content, pos, firstc, prompt, indent, level]
content: List of [attrs, string]
[[{}, "t"], [attrs, "est"], ...]
Triggered when the user types in the cmdline.
The `content` is the full content that should be displayed in the
cmdline, and the `pos` is the position of the cursor that in the
cmdline. The content is divided into chunks with different highlight
attributes represented as a dict (see |ui-event-highlight_set|).
`firstc` and `prompt` are text, that if non-empty should be
displayed in front of the command line. `firstc` always indicates
built-in command lines such as `:` (ex command) and `/` `?` (search),
while `prompt` is an |input()| prompt. `indent` tells how many spaces
the content should be indented.
The Nvim command line can be invoked recursively, for instance by
typing `<c-r>=` at the command line prompt. The `level` field is used
to distinguish different command lines active at the same time. The
first invoked command line has level 1, the next recursively-invoked
prompt has level 2. A command line invoked from the |cmd-line-window|
has a higher level than than the edited command line.
["cmdline_pos", pos, level]
Change the cursor position in the cmdline.
["cmdline_special_char", c, shift, level]
Display a special char in the cmdline at the cursor position. This is
typically used to indicate a pending state, e.g. after |c_CTRL-V|. If
`shift` is true the text after the cursor should be shifted, otherwise
it should overwrite the char at the cursor.
Should be hidden at next cmdline_pos.
["cmdline_hide"]
Hide the cmdline.
["cmdline_block_show", lines]
Show a block of context to the current command line. For example if
the user defines a |:function| interactively: >
:function Foo()
: echo "foo"
:
<
`lines` is a list of lines of highlighted chunks, in the same form as
the "cmdline_show" `contents` parameter.
["cmdline_block_append", line]
Append a line at the end of the currently shown block.
["cmdline_block_hide"]
Hide the block.
==============================================================================
vim:tw=78:ts=8:noet:ft=help:norl:

View File

@@ -8,7 +8,7 @@ Undo and redo *undo-redo*
The basics are explained in section |02.5| of the user manual. The basics are explained in section |02.5| of the user manual.
Type <M-]> to see the table of contents. Type |gO| to see the table of contents.
============================================================================== ==============================================================================
1. Undo and redo commands *undo-commands* 1. Undo and redo commands *undo-commands*

View File

@@ -6,7 +6,7 @@
Various commands *various* Various commands *various*
Type <M-]> to see the table of contents. Type |gO| to see the table of contents.
============================================================================== ==============================================================================
1. Various commands *various-cmds* 1. Various commands *various-cmds*
@@ -608,6 +608,13 @@ which it was defined is reported.
the keyword. Only works when the highlighted text is the keyword. Only works when the highlighted text is
not more than one line. not more than one line.
*gO*
gO Show a filetype-specific, navigable "outline" of the
current buffer. For example, in a |help| buffer this
shows the table of contents.
Currently works in |help| and |:Man| buffers.
[N]gs *gs* *:sl* *:sleep* [N]gs *gs* *:sl* *:sleep*
:[N]sl[eep] [N] [m] Do nothing for [N] seconds. When [m] is included, :[N]sl[eep] [N] [m] Do nothing for [N] seconds. When [m] is included,
sleep for [N] milliseconds. The count for "gs" always sleep for [N] milliseconds. The count for "gs" always
@@ -646,4 +653,4 @@ LessInitFunc in your vimrc, for example: >
endfunc endfunc
< <
vim:tw=78:ts=8:ft=help:norl: vim:noet:tw=78:ts=8:ft=help:norl:

View File

@@ -6,7 +6,7 @@
Differences between Vim and Vi *vi-differences* Differences between Vim and Vi *vi-differences*
Type <M-]> to see the table of contents. Type |gO| to see the table of contents.
============================================================================== ==============================================================================
1. Limits *limits* 1. Limits *limits*

View File

@@ -9,7 +9,7 @@ Differences between Nvim and Vim *vim-differences*
Nvim differs from Vim in many ways, big and small. This document is Nvim differs from Vim in many ways, big and small. This document is
a complete and centralized reference of those differences. a complete and centralized reference of those differences.
Type <M-]> to see the table of contents. Type |gO| to see the table of contents.
============================================================================== ==============================================================================
1. Configuration *nvim-configuration* 1. Configuration *nvim-configuration*
@@ -100,7 +100,7 @@ by Nvim developers.
FEATURES ~ FEATURES ~
"Outline": Type <M-]> in |:Man| and |:help| pages to see a document outline. "Outline": Type |gO| in |:Man| and |:help| pages to see a document outline.
|META| (ALT) chords are recognized, even in the terminal. Any |<M-| mapping |META| (ALT) chords are recognized, even in the terminal. Any |<M-| mapping
will work. Some examples: <M-1>, <M-2>, <M-BS>, <M-Del>, <M-Ins>, <M-/>, will work. Some examples: <M-1>, <M-2>, <M-BS>, <M-Del>, <M-Ins>, <M-/>,
@@ -127,7 +127,7 @@ Variables:
|v:windowid| is always available (for use by external UIs) |v:windowid| is always available (for use by external UIs)
Commands: Commands:
|:CheckHealth| |:checkhealth|
|:drop| is available on all platforms |:drop| is available on all platforms
|:Man| is available by default, with many improvements such as completion |:Man| is available by default, with many improvements such as completion
@@ -281,8 +281,8 @@ other arguments if used).
|input()| and |inputdialog()| support user-defined cmdline highlighting. |input()| and |inputdialog()| support user-defined cmdline highlighting.
Highlight groups: Highlight groups:
|hl-ColorColumn|, |hl-CursorColumn|, |hl-CursorLine| are lower priority than |hl-ColorColumn|, |hl-CursorColumn| are lower priority than most other
(overridden by) most other highlight groups. groups
============================================================================== ==============================================================================
5. Missing legacy features *nvim-features-missing* 5. Missing legacy features *nvim-features-missing*

View File

@@ -11,7 +11,7 @@ operator. It is the only way to select a block of text.
This is introduced in section |04.4| of the user manual. This is introduced in section |04.4| of the user manual.
Type <M-]> to see the table of contents. Type |gO| to see the table of contents.
============================================================================== ==============================================================================
1. Using Visual mode *visual-use* 1. Using Visual mode *visual-use*

View File

@@ -13,7 +13,7 @@ differently when used in combination with more than one window.
The basics are explained in chapter 7 and 8 of the user manual |usr_07.txt| The basics are explained in chapter 7 and 8 of the user manual |usr_07.txt|
|usr_08.txt|. |usr_08.txt|.
Type <M-]> to see the table of contents. Type |gO| to see the table of contents.
============================================================================== ==============================================================================
1. Introduction *windows-intro* *window* 1. Introduction *windows-intro* *window*
@@ -677,6 +677,8 @@ can also get to them with the buffer list commands, like ":bnext".
- If the file is not open in a window edit the file in the - If the file is not open in a window edit the file in the
current window. If the current buffer can't be |abandon|ed, current window. If the current buffer can't be |abandon|ed,
the window is split first. the window is split first.
- Windows that are not in the argument list or are not full
width will be closed if possible.
The |argument-list| is set, like with the |:next| command. The |argument-list| is set, like with the |:next| command.
The purpose of this command is that it can be used from a The purpose of this command is that it can be used from a
program that wants Vim to edit another file, e.g., a debugger. program that wants Vim to edit another file, e.g., a debugger.

View File

@@ -90,7 +90,7 @@ if !exists('g:no_plugin_maps')
let w:qf_toc = bufname let w:qf_toc = bufname
endfunction endfunction
nnoremap <silent><buffer> <M-]> :call <sid>show_toc()<cr> nnoremap <silent><buffer> gO :call <sid>show_toc()<cr>
endif endif
let &cpo = s:cpo_save let &cpo = s:cpo_save

View File

@@ -31,7 +31,7 @@ setlocal nolist
setlocal nofoldenable setlocal nofoldenable
if !exists('g:no_plugin_maps') && !exists('g:no_man_maps') if !exists('g:no_plugin_maps') && !exists('g:no_man_maps')
nnoremap <silent> <buffer> <M-]> :call man#show_toc()<CR> nnoremap <silent> <buffer> gO :call man#show_toc()<CR>
nnoremap <silent> <buffer> <C-]> :Man<CR> nnoremap <silent> <buffer> <C-]> :Man<CR>
nnoremap <silent> <buffer> K :Man<CR> nnoremap <silent> <buffer> K :Man<CR>
nnoremap <silent> <buffer> <C-T> :call man#pop_tag()<CR> nnoremap <silent> <buffer> <C-T> :call man#pop_tag()<CR>

View File

@@ -1,7 +1,7 @@
" Vim syntax file " Vim syntax file
" Language: C " Language: C
" Maintainer: Bram Moolenaar <Bram@vim.org> " Maintainer: Bram Moolenaar <Bram@vim.org>
" Last Change: 2016 Nov 17 " Last Change: 2016 Nov 18
" Quit when a (custom) syntax file was already loaded " Quit when a (custom) syntax file was already loaded
if exists("b:current_syntax") if exists("b:current_syntax")
@@ -363,23 +363,23 @@ syn match cPreConditMatch display "^\s*\zs\(%:\|#\)\s*\(else\|endif\)\>"
if !exists("c_no_if0") if !exists("c_no_if0")
syn cluster cCppOutInGroup contains=cCppInIf,cCppInElse,cCppInElse2,cCppOutIf,cCppOutIf2,cCppOutElse,cCppInSkip,cCppOutSkip syn cluster cCppOutInGroup contains=cCppInIf,cCppInElse,cCppInElse2,cCppOutIf,cCppOutIf2,cCppOutElse,cCppInSkip,cCppOutSkip
syn region cCppOutWrapper start="^\s*\zs\(%:\|#\)\s*if\s\+0\+\s*\($\|//\|/\*\|&\)" end=".\@=\|$" contains=cCppOutIf,cCppOutElse,@NoSpell fold syn region cCppOutWrapper start="^\s*\zs\(%:\|#\)\s*if\s\+0\+\s*\($\|//\|/\*\|&\)" end=".\@=\|$" contains=cCppOutIf,cCppOutElse,@NoSpell fold
syn region cCppOutIf contained start="0\+" matchgroup=cCppOutWrapper end="^\s*\zs\(%:\|#\)\s*endif\>" contains=cCppOutIf2,cCppOutElse syn region cCppOutIf contained start="0\+" matchgroup=cCppOutWrapper end="^\s*\(%:\|#\)\s*endif\>" contains=cCppOutIf2,cCppOutElse
if !exists("c_no_if0_fold") if !exists("c_no_if0_fold")
syn region cCppOutIf2 contained matchgroup=cCppOutWrapper start="0\+" end="^\s*\(%:\|#\)\s*\(else\>\|elif\s\+\(0\+\s*\($\|//\|/\*\|&\)\)\@!\|endif\>\)"me=s-1 contains=cSpaceError,cCppOutSkip,@Spell fold syn region cCppOutIf2 contained matchgroup=cCppOutWrapper start="0\+" end="^\s*\(%:\|#\)\s*\(else\>\|elif\s\+\(0\+\s*\($\|//\|/\*\|&\)\)\@!\|endif\>\)"me=s-1 contains=cSpaceError,cCppOutSkip,@Spell fold
else else
syn region cCppOutIf2 contained matchgroup=cCppOutWrapper start="0\+" end="^\s*\(%:\|#\)\s*\(else\>\|elif\s\+\(0\+\s*\($\|//\|/\*\|&\)\)\@!\|endif\>\)"me=s-1 contains=cSpaceError,cCppOutSkip,@Spell syn region cCppOutIf2 contained matchgroup=cCppOutWrapper start="0\+" end="^\s*\(%:\|#\)\s*\(else\>\|elif\s\+\(0\+\s*\($\|//\|/\*\|&\)\)\@!\|endif\>\)"me=s-1 contains=cSpaceError,cCppOutSkip,@Spell
endif endif
syn region cCppOutElse contained matchgroup=cCppOutWrapper start="^\s*\zs\(%:\|#\)\s*\(else\|elif\)" end="^\s*\zs\(%:\|#\)\s*endif\>"me=s-1 contains=TOP,cPreCondit syn region cCppOutElse contained matchgroup=cCppOutWrapper start="^\s*\(%:\|#\)\s*\(else\|elif\)" end="^\s*\(%:\|#\)\s*endif\>"me=s-1 contains=TOP,cPreCondit
syn region cCppInWrapper start="^\s*\zs\(%:\|#\)\s*if\s\+0*[1-9]\d*\s*\($\|//\|/\*\||\)" end=".\@=\|$" contains=cCppInIf,cCppInElse fold syn region cCppInWrapper start="^\s*\zs\(%:\|#\)\s*if\s\+0*[1-9]\d*\s*\($\|//\|/\*\||\)" end=".\@=\|$" contains=cCppInIf,cCppInElse fold
syn region cCppInIf contained matchgroup=cCppInWrapper start="\d\+" end="^\s*\zs\(%:\|#\)\s*endif\>" contains=TOP,cPreCondit syn region cCppInIf contained matchgroup=cCppInWrapper start="\d\+" end="^\s*\(%:\|#\)\s*endif\>" contains=TOP,cPreCondit
if !exists("c_no_if0_fold") if !exists("c_no_if0_fold")
syn region cCppInElse contained start="^\s*\zs\(%:\|#\)\s*\(else\>\|elif\s\+\(0*[1-9]\d*\s*\($\|//\|/\*\||\)\)\@!\)" end=".\@=\|$" containedin=cCppInIf contains=cCppInElse2 fold syn region cCppInElse contained start="^\s*\(%:\|#\)\s*\(else\>\|elif\s\+\(0*[1-9]\d*\s*\($\|//\|/\*\||\)\)\@!\)" end=".\@=\|$" containedin=cCppInIf contains=cCppInElse2 fold
else else
syn region cCppInElse contained start="^\s*\zs\(%:\|#\)\s*\(else\>\|elif\s\+\(0*[1-9]\d*\s*\($\|//\|/\*\||\)\)\@!\)" end=".\@=\|$" containedin=cCppInIf contains=cCppInElse2 syn region cCppInElse contained start="^\s*\(%:\|#\)\s*\(else\>\|elif\s\+\(0*[1-9]\d*\s*\($\|//\|/\*\||\)\)\@!\)" end=".\@=\|$" containedin=cCppInIf contains=cCppInElse2
endif endif
syn region cCppInElse2 contained matchgroup=cCppInWrapper start="^\s*\zs\(%:\|#\)\s*\(else\|elif\)\([^/]\|/[^/*]\)*" end="^\s*\zs\(%:\|#\)\s*endif\>"me=s-1 contains=cSpaceError,cCppOutSkip,@Spell syn region cCppInElse2 contained matchgroup=cCppInWrapper start="^\s*\(%:\|#\)\s*\(else\|elif\)\([^/]\|/[^/*]\)*" end="^\s*\(%:\|#\)\s*endif\>"me=s-1 contains=cSpaceError,cCppOutSkip,@Spell
syn region cCppOutSkip contained start="^\s*\zs\(%:\|#\)\s*\(if\>\|ifdef\>\|ifndef\>\)" skip="\\$" end="^\s*\zs\(%:\|#\)\s*endif\>" contains=cSpaceError,cCppOutSkip syn region cCppOutSkip contained start="^\s*\(%:\|#\)\s*\(if\>\|ifdef\>\|ifndef\>\)" skip="\\$" end="^\s*\(%:\|#\)\s*endif\>" contains=cSpaceError,cCppOutSkip
syn region cCppInSkip contained matchgroup=cCppInWrapper start="^\s*\zs\(%:\|#\)\s*\(if\s\+\(\d\+\s*\($\|//\|/\*\||\|&\)\)\@!\|ifdef\>\|ifndef\>\)" skip="\\$" end="^\s*\zs\(%:\|#\)\s*endif\>" containedin=cCppOutElse,cCppInIf,cCppInSkip contains=TOP,cPreProc syn region cCppInSkip contained matchgroup=cCppInWrapper start="^\s*\(%:\|#\)\s*\(if\s\+\(\d\+\s*\($\|//\|/\*\||\|&\)\)\@!\|ifdef\>\|ifndef\>\)" skip="\\$" end="^\s*\(%:\|#\)\s*endif\>" containedin=cCppOutElse,cCppInIf,cCppInSkip contains=TOP,cPreProc
endif endif
syn region cIncluded display contained start=+"+ skip=+\\\\\|\\"+ end=+"+ syn region cIncluded display contained start=+"+ skip=+\\\\\|\\"+ end=+"+
syn match cIncluded display contained "<[^>]*>" syn match cIncluded display contained "<[^>]*>"

View File

@@ -2531,6 +2531,7 @@ def CheckSpacing(filename, clean_lines, linenum, nesting_state, error):
r'(?<!\bkhash_t)' r'(?<!\bkhash_t)'
r'(?<!\bkbtree_t)' r'(?<!\bkbtree_t)'
r'(?<!\bkbitr_t)' r'(?<!\bkbitr_t)'
r'(?<!\bPMap)'
r'\((?:const )?(?:struct )?[a-zA-Z_]\w*(?: *\*(?:const)?)*\)' r'\((?:const )?(?:struct )?[a-zA-Z_]\w*(?: *\*(?:const)?)*\)'
r' +' r' +'
r'-?(?:\*+|&)?(?:\w+|\+\+|--|\()', cast_line) r'-?(?:\*+|&)?(?:\w+|\+\+|--|\()', cast_line)

View File

@@ -166,7 +166,7 @@ if(NOT MSVC)
endif() endif()
endif() endif()
if(DEFINED MIN_LOG_LEVEL) if(NOT "${MIN_LOG_LEVEL}" MATCHES "^$")
add_definitions(-DMIN_LOG_LEVEL=${MIN_LOG_LEVEL}) add_definitions(-DMIN_LOG_LEVEL=${MIN_LOG_LEVEL})
endif() endif()
@@ -543,11 +543,6 @@ endfunction()
set(NO_SINGLE_CHECK_HEADERS set(NO_SINGLE_CHECK_HEADERS
os/win_defs.h os/win_defs.h
os/pty_process_win.h os/pty_process_win.h
regexp_defs.h
syntax_defs.h
terminal.h
undo.h
undo_defs.h
) )
foreach(hfile ${NVIM_HEADERS}) foreach(hfile ${NVIM_HEADERS})
get_test_target(test-includes "${hfile}" relative_path texe) get_test_target(test-includes "${hfile}" relative_path texe)

View File

@@ -793,7 +793,11 @@ Integer nvim_buf_add_highlight(Buffer buffer,
col_end = MAXCOL; col_end = MAXCOL;
} }
int hlg_id = syn_name2id((char_u *)(hl_group.data ? hl_group.data : "")); int hlg_id = 0;
if (hl_group.size > 0) {
hlg_id = syn_check_group((char_u *)hl_group.data, (int)hl_group.size);
}
src_id = bufhl_add_hl(buf, (int)src_id, hlg_id, (linenr_T)line+1, src_id = bufhl_add_hl(buf, (int)src_id, hlg_id, (linenr_T)line+1,
(colnr_T)col_start+1, (colnr_T)col_end); (colnr_T)col_start+1, (colnr_T)col_end);
return src_id; return src_id;

View File

@@ -667,6 +667,22 @@ tabpage_T *find_tab_by_handle(Tabpage tabpage, Error *err)
return rv; return rv;
} }
/// Allocates a String consisting of a single char. Does not support multibyte
/// characters. The resulting string is also NUL-terminated, to facilitate
/// interoperating with code using C strings.
///
/// @param char the char to convert
/// @return the resulting String, if the input char was NUL, an
/// empty String is returned
String cchar_to_string(char c)
{
char buf[] = { c, NUL };
return (String) {
.data = xmemdupz(buf, 1),
.size = (c != NUL) ? 1 : 0
};
}
/// Copies a C string into a String (binary safe string, characters + length). /// Copies a C string into a String (binary safe string, characters + length).
/// The resulting string is also NUL-terminated, to facilitate interoperating /// The resulting string is also NUL-terminated, to facilitate interoperating
/// with code using C strings. /// with code using C strings.
@@ -687,6 +703,23 @@ String cstr_to_string(const char *str)
}; };
} }
/// Copies buffer to an allocated String.
/// The resulting string is also NUL-terminated, to facilitate interoperating
/// with code using C strings.
///
/// @param buf the buffer to copy
/// @param size length of the buffer
/// @return the resulting String, if the input string was NULL, an
/// empty String is returned
String cbuf_to_string(const char *buf, size_t size)
FUNC_ATTR_NONNULL_ALL
{
return (String) {
.data = xmemdupz(buf, size),
.size = size
};
}
/// Creates a String using the given C string. Unlike /// Creates a String using the given C string. Unlike
/// cstr_to_string this function DOES NOT copy the C string. /// cstr_to_string this function DOES NOT copy the C string.
/// ///

View File

@@ -68,4 +68,20 @@ void popupmenu_select(Integer selected)
void tabline_update(Tabpage current, Array tabs) void tabline_update(Tabpage current, Array tabs)
FUNC_API_SINCE(3) FUNC_API_REMOTE_ONLY; FUNC_API_SINCE(3) FUNC_API_REMOTE_ONLY;
void cmdline_show(Array content, Integer pos, String firstc, String prompt,
Integer indent, Integer level)
FUNC_API_SINCE(3) FUNC_API_REMOTE_ONLY;
void cmdline_pos(Integer pos, Integer level)
FUNC_API_SINCE(3) FUNC_API_REMOTE_ONLY;
void cmdline_special_char(String c, Boolean shift, Integer level)
FUNC_API_SINCE(3) FUNC_API_REMOTE_ONLY;
void cmdline_hide(Integer level)
FUNC_API_SINCE(3) FUNC_API_REMOTE_ONLY;
void cmdline_block_show(Array lines)
FUNC_API_SINCE(3) FUNC_API_REMOTE_ONLY;
void cmdline_block_append(Array lines)
FUNC_API_SINCE(3) FUNC_API_REMOTE_ONLY;
void cmdline_block_hide(void)
FUNC_API_SINCE(3) FUNC_API_REMOTE_ONLY;
#endif // NVIM_API_UI_EVENTS_IN_H #endif // NVIM_API_UI_EVENTS_IN_H

View File

@@ -1466,7 +1466,7 @@ void enter_buffer(buf_T *buf)
if (buf->terminal) { if (buf->terminal) {
terminal_resize(buf->terminal, terminal_resize(buf->terminal,
(uint16_t)curwin->w_width, (uint16_t)(MAX(0, curwin->w_width - win_col_off(curwin))),
(uint16_t)curwin->w_height); (uint16_t)curwin->w_height);
} }

View File

@@ -375,18 +375,31 @@ void check_cursor_col_win(win_T *win)
win->w_cursor.col = 0; win->w_cursor.col = 0;
} }
/* If virtual editing is on, we can leave the cursor on the old position, // If virtual editing is on, we can leave the cursor on the old position,
* only we must set it to virtual. But don't do it when at the end of the // only we must set it to virtual. But don't do it when at the end of the
* line. */ // line.
if (oldcol == MAXCOL) if (oldcol == MAXCOL) {
win->w_cursor.coladd = 0; win->w_cursor.coladd = 0;
else if (ve_flags == VE_ALL) { } else if (ve_flags == VE_ALL) {
if (oldcoladd > win->w_cursor.col) if (oldcoladd > win->w_cursor.col) {
win->w_cursor.coladd = oldcoladd - win->w_cursor.col; win->w_cursor.coladd = oldcoladd - win->w_cursor.col;
else
/* avoid weird number when there is a miscalculation or overflow */ // Make sure that coladd is not more than the char width.
// Not for the last character, coladd is then used when the cursor
// is actually after the last character.
if (win->w_cursor.col + 1 < len && win->w_cursor.coladd > 0) {
int cs, ce;
getvcol(win, &win->w_cursor, &cs, NULL, &ce);
if (win->w_cursor.coladd > ce - cs) {
win->w_cursor.coladd = ce - cs;
}
}
} else {
// avoid weird number when there is a miscalculation or overflow
win->w_cursor.coladd = 0; win->w_cursor.coladd = 0;
} }
}
} }
/* /*

View File

@@ -11147,18 +11147,19 @@ void get_user_input(const typval_T *const argvars,
cmd_silent = false; // Want to see the prompt. cmd_silent = false; // Want to see the prompt.
// Only the part of the message after the last NL is considered as // Only the part of the message after the last NL is considered as
// prompt for the command line. // prompt for the command line, unlsess cmdline is externalized
const char *p = strrchr(prompt, '\n'); const char *p = prompt;
if (p == NULL) { if (!ui_is_external(kUICmdline)) {
p = prompt; const char *lastnl = strrchr(prompt, '\n');
} else { if (lastnl != NULL) {
p++; p = lastnl+1;
msg_start(); msg_start();
msg_clr_eos(); msg_clr_eos();
msg_puts_attr_len(prompt, p - prompt, echo_attr); msg_puts_attr_len(prompt, p - prompt, echo_attr);
msg_didout = false; msg_didout = false;
msg_starthere(); msg_starthere();
} }
}
cmdline_row = msg_row; cmdline_row = msg_row;
stuffReadbuffSpec(defstr); stuffReadbuffSpec(defstr);
@@ -16723,9 +16724,10 @@ static void f_termopen(typval_T *argvars, typval_T *rettv, FunPtr fptr)
} }
} }
uint16_t term_width = MAX(0, curwin->w_width - win_col_off(curwin));
TerminalJobData *data = common_job_init(argv, on_stdout, on_stderr, on_exit, TerminalJobData *data = common_job_init(argv, on_stdout, on_stderr, on_exit,
true, false, false, cwd); true, false, false, cwd);
data->proc.pty.width = curwin->w_width; data->proc.pty.width = term_width;
data->proc.pty.height = curwin->w_height; data->proc.pty.height = curwin->w_height;
data->proc.pty.term_name = xstrdup("xterm-256color"); data->proc.pty.term_name = xstrdup("xterm-256color");
if (!common_job_start(data, rettv)) { if (!common_job_start(data, rettv)) {
@@ -16733,7 +16735,7 @@ static void f_termopen(typval_T *argvars, typval_T *rettv, FunPtr fptr)
} }
TerminalOptions topts; TerminalOptions topts;
topts.data = data; topts.data = data;
topts.width = curwin->w_width; topts.width = term_width;
topts.height = curwin->w_height; topts.height = curwin->w_height;
topts.write_cb = term_write; topts.write_cb = term_write;
topts.resize_cb = term_resize; topts.resize_cb = term_resize;
@@ -19642,6 +19644,7 @@ void ex_function(exarg_T *eap)
int todo; int todo;
hashitem_T *hi; hashitem_T *hi;
int sourcing_lnum_off; int sourcing_lnum_off;
bool show_block = false;
/* /*
* ":function" without argument: list functions. * ":function" without argument: list functions.
@@ -19815,6 +19818,11 @@ void ex_function(exarg_T *eap)
goto errret_2; goto errret_2;
} }
if (KeyTyped && ui_is_external(kUICmdline)) {
show_block = true;
ui_ext_cmdline_block_append(0, (const char *)eap->cmd);
}
// find extra arguments "range", "dict", "abort" and "closure" // find extra arguments "range", "dict", "abort" and "closure"
for (;; ) { for (;; ) {
p = skipwhite(p); p = skipwhite(p);
@@ -19867,7 +19875,9 @@ void ex_function(exarg_T *eap)
if (!eap->skip && did_emsg) if (!eap->skip && did_emsg)
goto erret; goto erret;
msg_putchar('\n'); /* don't overwrite the function name */ if (!ui_is_external(kUICmdline)) {
msg_putchar('\n'); // don't overwrite the function name
}
cmdline_row = msg_row; cmdline_row = msg_row;
} }
@@ -19901,6 +19911,9 @@ void ex_function(exarg_T *eap)
EMSG(_("E126: Missing :endfunction")); EMSG(_("E126: Missing :endfunction"));
goto erret; goto erret;
} }
if (show_block) {
ui_ext_cmdline_block_append(indent, (const char *)theline);
}
/* Detect line continuation: sourcing_lnum increased more than one. */ /* Detect line continuation: sourcing_lnum increased more than one. */
if (sourcing_lnum > sourcing_lnum_off + 1) if (sourcing_lnum > sourcing_lnum_off + 1)
@@ -20193,6 +20206,9 @@ ret_free:
xfree(name); xfree(name);
did_emsg |= saved_did_emsg; did_emsg |= saved_did_emsg;
need_wait_return |= saved_wait_return; need_wait_return |= saved_wait_return;
if (show_block) {
ui_ext_cmdline_block_leave();
}
} }
/// Get a function name, translating "<SID>" and "<SNR>". /// Get a function name, translating "<SID>" and "<SNR>".
@@ -22850,3 +22866,32 @@ void eval_format_source_name_line(char *buf, size_t bufsize)
(sourcing_name ? sourcing_name : (char_u *)"?"), (sourcing_name ? sourcing_name : (char_u *)"?"),
(sourcing_name ? sourcing_lnum : 0)); (sourcing_name ? sourcing_lnum : 0));
} }
/// ":checkhealth [plugins]"
void ex_checkhealth(exarg_T *eap)
{
bool found = !!find_func((char_u *)"health#check");
if (!found
&& script_autoload("health#check", sizeof("health#check") - 1, false)) {
found = !!find_func((char_u *)"health#check");
}
if (!found) {
const char *vimruntime_env = os_getenv("VIMRUNTIME");
if (vimruntime_env == NULL) {
EMSG(_("E5009: $VIMRUNTIME is empty or unset"));
return;
} else {
EMSG2(_("E5009: Invalid $VIMRUNTIME: %s"), os_getenv("VIMRUNTIME"));
return;
}
}
size_t bufsize = STRLEN(eap->arg) + sizeof("call health#check('')");
char *buf = xmalloc(bufsize);
snprintf(buf, bufsize, "call health#check('%s')", eap->arg);
do_cmdline_cmd(buf);
xfree(buf);
}

View File

@@ -450,6 +450,12 @@ return {
addr_type=ADDR_LINES, addr_type=ADDR_LINES,
func='ex_changes', func='ex_changes',
}, },
{
command='checkhealth',
flags=bit.bor(EXTRA, TRLBAR),
addr_type=ADDR_LINES,
func='ex_checkhealth',
},
{ {
command='checkpath', command='checkpath',
flags=bit.bor(TRLBAR, BANG, CMDWIN), flags=bit.bor(TRLBAR, BANG, CMDWIN),
@@ -614,7 +620,7 @@ return {
}, },
{ {
command='cquit', command='cquit',
flags=bit.bor(TRLBAR, BANG), flags=bit.bor(RANGE, NOTADR, COUNT, ZEROR, TRLBAR, BANG),
addr_type=ADDR_LINES, addr_type=ADDR_LINES,
func='ex_cquit', func='ex_cquit',
}, },

View File

@@ -9,6 +9,7 @@
#include <string.h> #include <string.h>
#include <stdbool.h> #include <stdbool.h>
#include <stdint.h> #include <stdint.h>
#include <stdlib.h>
#include <inttypes.h> #include <inttypes.h>
#include "nvim/vim.h" #include "nvim/vim.h"
@@ -5996,7 +5997,7 @@ static void ex_quit(exarg_T *eap)
*/ */
static void ex_cquit(exarg_T *eap) static void ex_cquit(exarg_T *eap)
{ {
getout(1); getout(eap->addr_count > 0 ? (int)eap->line2 : EXIT_FAILURE);
} }
/* /*
@@ -9883,7 +9884,7 @@ static void ex_terminal(exarg_T *eap)
/// Checks if `cmd` is "previewable" (i.e. supported by 'inccommand'). /// Checks if `cmd` is "previewable" (i.e. supported by 'inccommand').
/// ///
/// @param[in] cmd Commandline to check. May start with a range. /// @param[in] cmd Commandline to check. May start with a range or modifier.
/// ///
/// @return true if `cmd` is previewable /// @return true if `cmd` is previewable
bool cmd_can_preview(char_u *cmd) bool cmd_can_preview(char_u *cmd)
@@ -9892,6 +9893,12 @@ bool cmd_can_preview(char_u *cmd)
return false; return false;
} }
// Ignore any leading modifiers (:keeppatterns, :verbose, etc.)
for (int len = modifier_len(cmd); len != 0; len = modifier_len(cmd)) {
cmd += len;
cmd = skipwhite(cmd);
}
exarg_T ea; exarg_T ea;
// parse the command line // parse the command line
ea.cmd = skip_range(cmd, NULL); ea.cmd = skip_range(cmd, NULL);

View File

@@ -69,6 +69,30 @@
#include "nvim/viml/parser/parser.h" #include "nvim/viml/parser/parser.h"
#include "nvim/viml/parser/expressions.h" #include "nvim/viml/parser/expressions.h"
/// Command-line colors: one chunk
///
/// Defines a region which has the same highlighting.
typedef struct {
int start; ///< Colored chunk start.
int end; ///< Colored chunk end (exclusive, > start).
int attr; ///< Highlight attr.
} CmdlineColorChunk;
/// Command-line colors
///
/// Holds data about all colors.
typedef kvec_t(CmdlineColorChunk) CmdlineColors;
/// Command-line coloring
///
/// Holds both what are the colors and what have been colored. Latter is used to
/// suppress unnecessary calls to coloring callbacks.
typedef struct {
unsigned prompt_id; ///< ID of the prompt which was colored last.
char *cmdbuff; ///< What exactly was colored last time or NULL.
CmdlineColors colors; ///< Last colors.
} ColoredCmdline;
/* /*
* Variables shared between getcmdline(), redrawcmdline() and others. * Variables shared between getcmdline(), redrawcmdline() and others.
* These need to be saved when using CTRL-R |, that's why they are in a * These need to be saved when using CTRL-R |, that's why they are in a
@@ -93,6 +117,11 @@ struct cmdline_info {
int input_fn; // when TRUE Invoked for input() function int input_fn; // when TRUE Invoked for input() function
unsigned prompt_id; ///< Prompt number, used to disable coloring on errors. unsigned prompt_id; ///< Prompt number, used to disable coloring on errors.
Callback highlight_callback; ///< Callback used for coloring user input. Callback highlight_callback; ///< Callback used for coloring user input.
ColoredCmdline last_colors; ///< Last cmdline colors
int level; // current cmdline level
struct cmdline_info *prev_ccline; ///< pointer to saved cmdline state
char special_char; ///< last putcmdline char (used for redraws)
bool special_shift; ///< shift of last putcmdline char
}; };
/// Last value of prompt_id, incremented when doing new prompt /// Last value of prompt_id, incremented when doing new prompt
static unsigned last_prompt_id = 0; static unsigned last_prompt_id = 0;
@@ -145,36 +174,6 @@ typedef struct command_line_state {
struct cmdline_info save_ccline; struct cmdline_info save_ccline;
} CommandLineState; } CommandLineState;
/// Command-line colors: one chunk
///
/// Defines a region which has the same highlighting.
typedef struct {
int start; ///< Colored chunk start.
int end; ///< Colored chunk end (exclusive, > start).
int attr; ///< Highlight attr.
} CmdlineColorChunk;
/// Command-line colors
///
/// Holds data about all colors.
typedef kvec_t(CmdlineColorChunk) CmdlineColors;
/// Command-line coloring
///
/// Holds both what are the colors and what have been colored. Latter is used to
/// suppress unnecessary calls to coloring callbacks.
typedef struct {
unsigned prompt_id; ///< ID of the prompt which was colored last.
char *cmdbuff; ///< What exactly was colored last time or NULL.
CmdlineColors colors; ///< Last colors.
} ColoredCmdline;
/// Last command-line colors.
ColoredCmdline last_ccline_colors = {
.cmdbuff = NULL,
.colors = KV_INITIAL_VALUE
};
typedef struct cmdline_info CmdlineInfo; typedef struct cmdline_info CmdlineInfo;
/* The current cmdline_info. It is initialized in getcmdline() and after that /* The current cmdline_info. It is initialized in getcmdline() and after that
@@ -187,6 +186,8 @@ static int cmd_showtail; /* Only show path tail in lists ? */
static int new_cmdpos; /* position set by set_cmdline_pos() */ static int new_cmdpos; /* position set by set_cmdline_pos() */
static Array cmdline_block; ///< currently displayed block of context
/* /*
* Type used by call_user_expand_func * Type used by call_user_expand_func
*/ */
@@ -241,6 +242,7 @@ static uint8_t *command_line_enter(int firstc, long count, int indent)
} }
ccline.prompt_id = last_prompt_id++; ccline.prompt_id = last_prompt_id++;
ccline.level++;
ccline.overstrike = false; // always start in insert mode ccline.overstrike = false; // always start in insert mode
clearpos(&s->match_end); clearpos(&s->match_end);
s->save_cursor = curwin->w_cursor; // may be restored later s->save_cursor = curwin->w_cursor; // may be restored later
@@ -260,6 +262,9 @@ static uint8_t *command_line_enter(int firstc, long count, int indent)
ccline.cmdlen = ccline.cmdpos = 0; ccline.cmdlen = ccline.cmdpos = 0;
ccline.cmdbuff[0] = NUL; ccline.cmdbuff[0] = NUL;
ccline.last_colors = (ColoredCmdline){ .cmdbuff = NULL,
.colors = KV_INITIAL_VALUE };
// autoindent for :insert and :append // autoindent for :insert and :append
if (s->firstc <= 0) { if (s->firstc <= 0) {
memset(ccline.cmdbuff, ' ', s->indent); memset(ccline.cmdbuff, ' ', s->indent);
@@ -410,12 +415,19 @@ static uint8_t *command_line_enter(int firstc, long count, int indent)
setmouse(); setmouse();
ui_cursor_shape(); // may show different cursor shape ui_cursor_shape(); // may show different cursor shape
xfree(s->save_p_icm); xfree(s->save_p_icm);
xfree(ccline.last_colors.cmdbuff);
kv_destroy(ccline.last_colors.colors);
{ {
char_u *p = ccline.cmdbuff; char_u *p = ccline.cmdbuff;
// Make ccline empty, getcmdline() may try to use it. // Make ccline empty, getcmdline() may try to use it.
ccline.cmdbuff = NULL; ccline.cmdbuff = NULL;
if (ui_is_external(kUICmdline)) {
ui_call_cmdline_hide(ccline.level);
}
ccline.level--;
return p; return p;
} }
} }
@@ -806,7 +818,9 @@ static int command_line_execute(VimState *state, int key)
} }
if (!cmd_silent) { if (!cmd_silent) {
if (!ui_is_external(kUICmdline)) {
ui_cursor_goto(msg_row, 0); ui_cursor_goto(msg_row, 0);
}
ui_flush(); ui_flush();
} }
return 0; return 0;
@@ -1136,7 +1150,7 @@ static int command_line_handle_key(CommandLineState *s)
xfree(ccline.cmdbuff); // no commandline to return xfree(ccline.cmdbuff); // no commandline to return
ccline.cmdbuff = NULL; ccline.cmdbuff = NULL;
if (!cmd_silent) { if (!cmd_silent && !ui_is_external(kUICmdline)) {
if (cmdmsg_rl) { if (cmdmsg_rl) {
msg_col = Columns; msg_col = Columns;
} else { } else {
@@ -1588,10 +1602,15 @@ static int command_line_handle_key(CommandLineState *s)
s->do_abbr = false; // don't do abbreviation now s->do_abbr = false; // don't do abbreviation now
// may need to remove ^ when composing char was typed // may need to remove ^ when composing char was typed
if (enc_utf8 && utf_iscomposing(s->c) && !cmd_silent) { if (enc_utf8 && utf_iscomposing(s->c) && !cmd_silent) {
if (ui_is_external(kUICmdline)) {
// TODO(bfredl): why not make unputcmdline also work with true?
unputcmdline();
} else {
draw_cmdline(ccline.cmdpos, ccline.cmdlen - ccline.cmdpos); draw_cmdline(ccline.cmdpos, ccline.cmdlen - ccline.cmdpos);
msg_putchar(' '); msg_putchar(' ');
cursorcmd(); cursorcmd();
} }
}
break; break;
case Ctrl_K: case Ctrl_K:
@@ -2404,8 +2423,7 @@ static void color_expr_cmdline(const CmdlineInfo *const colored_ccline,
/// Should use built-in command parser or user-specified one. Currently only the /// Should use built-in command parser or user-specified one. Currently only the
/// latter is supported. /// latter is supported.
/// ///
/// @param[in] colored_ccline Command-line to color. /// @param[in,out] colored_ccline Command-line to color. Also holds a cache:
/// @param[out] ret_ccline_colors What should be colored. Also holds a cache:
/// if ->prompt_id and ->cmdbuff values happen /// if ->prompt_id and ->cmdbuff values happen
/// to be equal to those from colored_cmdline it /// to be equal to those from colored_cmdline it
/// will just do nothing, assuming that ->colors /// will just do nothing, assuming that ->colors
@@ -2415,11 +2433,11 @@ static void color_expr_cmdline(const CmdlineInfo *const colored_ccline,
/// ///
/// @return true if draw_cmdline may proceed, false if it does not need anything /// @return true if draw_cmdline may proceed, false if it does not need anything
/// to do. /// to do.
static bool color_cmdline(const CmdlineInfo *const colored_ccline, static bool color_cmdline(CmdlineInfo *colored_ccline)
ColoredCmdline *const ret_ccline_colors)
FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT
{ {
bool printed_errmsg = false; bool printed_errmsg = false;
#define PRINT_ERRMSG(...) \ #define PRINT_ERRMSG(...) \
do { \ do { \
msg_putchar('\n'); \ msg_putchar('\n'); \
@@ -2428,19 +2446,21 @@ static bool color_cmdline(const CmdlineInfo *const colored_ccline,
} while (0) } while (0)
bool ret = true; bool ret = true;
ColoredCmdline *ccline_colors = &colored_ccline->last_colors;
// Check whether result of the previous call is still valid. // Check whether result of the previous call is still valid.
if (ret_ccline_colors->prompt_id == colored_ccline->prompt_id if (ccline_colors->prompt_id == colored_ccline->prompt_id
&& ret_ccline_colors->cmdbuff != NULL && ccline_colors->cmdbuff != NULL
&& STRCMP(ret_ccline_colors->cmdbuff, colored_ccline->cmdbuff) == 0) { && STRCMP(ccline_colors->cmdbuff, colored_ccline->cmdbuff) == 0) {
return ret; return ret;
} }
kv_size(ret_ccline_colors->colors) = 0; kv_size(ccline_colors->colors) = 0;
if (colored_ccline->cmdbuff == NULL || *colored_ccline->cmdbuff == NUL) { if (colored_ccline->cmdbuff == NULL || *colored_ccline->cmdbuff == NUL) {
// Nothing to do, exiting. // Nothing to do, exiting.
xfree(ret_ccline_colors->cmdbuff); xfree(ccline_colors->cmdbuff);
ret_ccline_colors->cmdbuff = NULL; ccline_colors->cmdbuff = NULL;
return ret; return ret;
} }
@@ -2453,7 +2473,7 @@ static bool color_cmdline(const CmdlineInfo *const colored_ccline,
static unsigned prev_prompt_id = UINT_MAX; static unsigned prev_prompt_id = UINT_MAX;
static int prev_prompt_errors = 0; static int prev_prompt_errors = 0;
Callback color_cb = { .type = kCallbackNone }; Callback color_cb = CALLBACK_NONE;
bool can_free_cb = false; bool can_free_cb = false;
TryState tstate; TryState tstate;
Error err = ERROR_INIT; Error err = ERROR_INIT;
@@ -2557,7 +2577,7 @@ static bool color_cmdline(const CmdlineInfo *const colored_ccline,
goto color_cmdline_error; goto color_cmdline_error;
} }
if (start != prev_end) { if (start != prev_end) {
kv_push(ret_ccline_colors->colors, ((CmdlineColorChunk) { kv_push(ccline_colors->colors, ((CmdlineColorChunk) {
.start = prev_end, .start = prev_end,
.end = start, .end = start,
.attr = 0, .attr = 0,
@@ -2586,14 +2606,14 @@ static bool color_cmdline(const CmdlineInfo *const colored_ccline,
} }
const int id = syn_name2id((char_u *)group); const int id = syn_name2id((char_u *)group);
const int attr = (id == 0 ? 0 : syn_id2attr(id)); const int attr = (id == 0 ? 0 : syn_id2attr(id));
kv_push(ret_ccline_colors->colors, ((CmdlineColorChunk) { kv_push(ccline_colors->colors, ((CmdlineColorChunk) {
.start = start, .start = start,
.end = end, .end = end,
.attr = attr, .attr = attr,
})); }));
} }
if (prev_end < colored_ccline->cmdlen) { if (prev_end < colored_ccline->cmdlen) {
kv_push(ret_ccline_colors->colors, ((CmdlineColorChunk) { kv_push(ccline_colors->colors, ((CmdlineColorChunk) {
.start = prev_end, .start = prev_end,
.end = colored_ccline->cmdlen, .end = colored_ccline->cmdlen,
.attr = 0, .attr = 0,
@@ -2605,13 +2625,13 @@ color_cmdline_end:
if (can_free_cb) { if (can_free_cb) {
callback_free(&color_cb); callback_free(&color_cb);
} }
xfree(ret_ccline_colors->cmdbuff); xfree(ccline_colors->cmdbuff);
// Note: errors “output” is cached just as well as regular results. // Note: errors “output” is cached just as well as regular results.
ret_ccline_colors->prompt_id = colored_ccline->prompt_id; ccline_colors->prompt_id = colored_ccline->prompt_id;
if (arg_allocated) { if (arg_allocated) {
ret_ccline_colors->cmdbuff = (char *)arg.vval.v_string; ccline_colors->cmdbuff = (char *)arg.vval.v_string;
} else { } else {
ret_ccline_colors->cmdbuff = xmemdupz((const char *)colored_ccline->cmdbuff, ccline_colors->cmdbuff = xmemdupz((const char *)colored_ccline->cmdbuff,
(size_t)colored_ccline->cmdlen); (size_t)colored_ccline->cmdlen);
} }
tv_clear(&tv); tv_clear(&tv);
@@ -2625,7 +2645,7 @@ color_cmdline_error:
(void)printed_errmsg; (void)printed_errmsg;
prev_prompt_errors++; prev_prompt_errors++;
kv_size(ret_ccline_colors->colors) = 0; kv_size(ccline_colors->colors) = 0;
redrawcmdline(); redrawcmdline();
ret = false; ret = false;
goto color_cmdline_end; goto color_cmdline_end;
@@ -2638,7 +2658,13 @@ color_cmdline_error:
*/ */
static void draw_cmdline(int start, int len) static void draw_cmdline(int start, int len)
{ {
if (!color_cmdline(&ccline, &last_ccline_colors)) { if (!color_cmdline(&ccline)) {
return;
}
if (ui_is_external(kUICmdline)) {
ccline.special_char = NUL;
ui_ext_cmdline_show(&ccline);
return; return;
} }
@@ -2740,9 +2766,9 @@ static void draw_cmdline(int start, int len)
msg_outtrans_len(arshape_buf, newlen); msg_outtrans_len(arshape_buf, newlen);
} else { } else {
draw_cmdline_no_arabicshape: draw_cmdline_no_arabicshape:
if (kv_size(last_ccline_colors.colors)) { if (kv_size(ccline.last_colors.colors)) {
for (size_t i = 0; i < kv_size(last_ccline_colors.colors); i++) { for (size_t i = 0; i < kv_size(ccline.last_colors.colors); i++) {
CmdlineColorChunk chunk = kv_A(last_ccline_colors.colors, i); CmdlineColorChunk chunk = kv_A(ccline.last_colors.colors, i);
if (chunk.end <= start) { if (chunk.end <= start) {
continue; continue;
} }
@@ -2757,6 +2783,107 @@ draw_cmdline_no_arabicshape:
} }
} }
static void ui_ext_cmdline_show(CmdlineInfo *line)
{
Array content = ARRAY_DICT_INIT;
if (cmdline_star) {
size_t len = 0;
for (char_u *p = ccline.cmdbuff; *p; mb_ptr_adv(p)) {
len++;
}
char *buf = xmallocz(len);
memset(buf, '*', len);
Array item = ARRAY_DICT_INIT;
ADD(item, DICTIONARY_OBJ((Dictionary)ARRAY_DICT_INIT));
ADD(item, STRING_OBJ(((String) { .data = buf, .size = len })));
ADD(content, ARRAY_OBJ(item));
} else if (kv_size(line->last_colors.colors)) {
for (size_t i = 0; i < kv_size(line->last_colors.colors); i++) {
CmdlineColorChunk chunk = kv_A(line->last_colors.colors, i);
Array item = ARRAY_DICT_INIT;
if (chunk.attr) {
attrentry_T *aep = syn_cterm_attr2entry(chunk.attr);
// TODO(bfredl): this desicion could be delayed by making attr_code a
// recognized type
HlAttrs rgb_attrs = attrentry2hlattrs(aep, true);
ADD(item, DICTIONARY_OBJ(hlattrs2dict(rgb_attrs)));
} else {
ADD(item, DICTIONARY_OBJ((Dictionary)ARRAY_DICT_INIT));
}
ADD(item, STRING_OBJ(cbuf_to_string((char *)line->cmdbuff + chunk.start,
chunk.end-chunk.start)));
ADD(content, ARRAY_OBJ(item));
}
} else {
Array item = ARRAY_DICT_INIT;
ADD(item, DICTIONARY_OBJ((Dictionary)ARRAY_DICT_INIT));
ADD(item, STRING_OBJ(cstr_to_string((char *)(line->cmdbuff))));
ADD(content, ARRAY_OBJ(item));
}
ui_call_cmdline_show(content, line->cmdpos,
cchar_to_string((char)line->cmdfirstc),
cstr_to_string((char *)(line->cmdprompt)),
line->cmdindent,
line->level);
if (line->special_char) {
ui_call_cmdline_special_char(cchar_to_string((char)(line->special_char)),
line->special_shift,
line->level);
}
}
void ui_ext_cmdline_block_append(int indent, const char *line)
{
char *buf = xmallocz(indent + strlen(line));
memset(buf, ' ', indent);
memcpy(buf+indent, line, strlen(line));
Array item = ARRAY_DICT_INIT;
ADD(item, DICTIONARY_OBJ((Dictionary)ARRAY_DICT_INIT));
ADD(item, STRING_OBJ(cstr_as_string(buf)));
Array content = ARRAY_DICT_INIT;
ADD(content, ARRAY_OBJ(item));
ADD(cmdline_block, ARRAY_OBJ(content));
if (cmdline_block.size > 1) {
ui_call_cmdline_block_append(copy_array(content));
} else {
ui_call_cmdline_block_show(copy_array(cmdline_block));
}
}
void ui_ext_cmdline_block_leave(void)
{
api_free_array(cmdline_block);
ui_call_cmdline_block_hide();
}
/// Extra redrawing needed for redraw! and on ui_attach
/// assumes "redrawcmdline()" will already be invoked
void cmdline_screen_cleared(void)
{
if (!ui_is_external(kUICmdline)) {
return;
}
if (cmdline_block.size) {
ui_call_cmdline_block_show(copy_array(cmdline_block));
}
int prev_level = ccline.level-1;
CmdlineInfo *prev_ccline = ccline.prev_ccline;
while (prev_level > 0 && prev_ccline) {
if (prev_ccline->level == prev_level) {
// don't redraw a cmdline already shown in the cmdline window
if (prev_level != cmdwin_level) {
ui_ext_cmdline_show(prev_ccline);
}
prev_level--;
}
prev_ccline = prev_ccline->prev_ccline;
}
}
/* /*
* Put a character on the command line. Shifts the following text to the * Put a character on the command line. Shifts the following text to the
* right when "shift" is TRUE. Used for CTRL-V, CTRL-K, etc. * right when "shift" is TRUE. Used for CTRL-V, CTRL-K, etc.
@@ -2764,33 +2891,39 @@ draw_cmdline_no_arabicshape:
*/ */
void putcmdline(int c, int shift) void putcmdline(int c, int shift)
{ {
if (cmd_silent) if (cmd_silent) {
return; return;
msg_no_more = TRUE; }
if (!ui_is_external(kUICmdline)) {
msg_no_more = true;
msg_putchar(c); msg_putchar(c);
if (shift) if (shift) {
draw_cmdline(ccline.cmdpos, ccline.cmdlen - ccline.cmdpos); draw_cmdline(ccline.cmdpos, ccline.cmdlen - ccline.cmdpos);
msg_no_more = FALSE; }
msg_no_more = false;
} else {
ccline.special_char = c;
ccline.special_shift = shift;
ui_call_cmdline_special_char(cchar_to_string((char)(c)), shift,
ccline.level);
}
cursorcmd(); cursorcmd();
ui_cursor_shape(); ui_cursor_shape();
} }
/* /// Undo a putcmdline(c, FALSE).
* Undo a putcmdline(c, FALSE).
*/
void unputcmdline(void) void unputcmdline(void)
{ {
if (cmd_silent) if (cmd_silent) {
return; return;
msg_no_more = TRUE; }
if (ccline.cmdlen == ccline.cmdpos) msg_no_more = true;
if (ccline.cmdlen == ccline.cmdpos && !ui_is_external(kUICmdline)) {
msg_putchar(' '); msg_putchar(' ');
else if (has_mbyte) } else {
draw_cmdline(ccline.cmdpos, draw_cmdline(ccline.cmdpos, mb_ptr2len(ccline.cmdbuff + ccline.cmdpos));
(*mb_ptr2len)(ccline.cmdbuff + ccline.cmdpos)); }
else msg_no_more = false;
draw_cmdline(ccline.cmdpos, 1);
msg_no_more = FALSE;
cursorcmd(); cursorcmd();
ui_cursor_shape(); ui_cursor_shape();
} }
@@ -2924,9 +3057,6 @@ void put_on_cmdline(char_u *str, int len, int redraw)
msg_check(); msg_check();
} }
static struct cmdline_info prev_ccline;
static int prev_ccline_used = FALSE;
/* /*
* Save ccline, because obtaining the "=" register may execute "normal :cmd" * Save ccline, because obtaining the "=" register may execute "normal :cmd"
* and overwrite it. But get_cmdline_str() may need it, thus make it * and overwrite it. But get_cmdline_str() may need it, thus make it
@@ -2934,15 +3064,12 @@ static int prev_ccline_used = FALSE;
*/ */
static void save_cmdline(struct cmdline_info *ccp) static void save_cmdline(struct cmdline_info *ccp)
{ {
if (!prev_ccline_used) { *ccp = ccline;
memset(&prev_ccline, 0, sizeof(struct cmdline_info)); ccline.prev_ccline = ccp;
prev_ccline_used = TRUE;
}
*ccp = prev_ccline;
prev_ccline = ccline;
ccline.cmdbuff = NULL; ccline.cmdbuff = NULL;
ccline.cmdprompt = NULL; ccline.cmdprompt = NULL;
ccline.xpc = NULL; ccline.xpc = NULL;
ccline.special_char = NUL;
} }
/* /*
@@ -2950,8 +3077,7 @@ static void save_cmdline(struct cmdline_info *ccp)
*/ */
static void restore_cmdline(struct cmdline_info *ccp) static void restore_cmdline(struct cmdline_info *ccp)
{ {
ccline = prev_ccline; ccline = *ccp;
prev_ccline = *ccp;
} }
/* /*
@@ -3119,17 +3245,25 @@ static void redrawcmdprompt(void)
if (cmd_silent) if (cmd_silent)
return; return;
if (ccline.cmdfirstc != NUL) if (ui_is_external(kUICmdline)) {
ui_ext_cmdline_show(&ccline);
return;
}
if (ccline.cmdfirstc != NUL) {
msg_putchar(ccline.cmdfirstc); msg_putchar(ccline.cmdfirstc);
}
if (ccline.cmdprompt != NULL) { if (ccline.cmdprompt != NULL) {
msg_puts_attr((const char *)ccline.cmdprompt, ccline.cmdattr); msg_puts_attr((const char *)ccline.cmdprompt, ccline.cmdattr);
ccline.cmdindent = msg_col + (msg_row - cmdline_row) * Columns; ccline.cmdindent = msg_col + (msg_row - cmdline_row) * Columns;
/* do the reverse of set_cmdspos() */ // do the reverse of set_cmdspos()
if (ccline.cmdfirstc != NUL) if (ccline.cmdfirstc != NUL) {
--ccline.cmdindent; ccline.cmdindent--;
} else }
for (i = ccline.cmdindent; i > 0; --i) } else {
for (i = ccline.cmdindent; i > 0; i--) {
msg_putchar(' '); msg_putchar(' ');
}
}
} }
/* /*
@@ -3140,6 +3274,11 @@ void redrawcmd(void)
if (cmd_silent) if (cmd_silent)
return; return;
if (ui_is_external(kUICmdline)) {
draw_cmdline(0, ccline.cmdlen);
return;
}
/* when 'incsearch' is set there may be no command line while redrawing */ /* when 'incsearch' is set there may be no command line while redrawing */
if (ccline.cmdbuff == NULL) { if (ccline.cmdbuff == NULL) {
ui_cursor_goto(cmdline_row, 0); ui_cursor_goto(cmdline_row, 0);
@@ -3183,6 +3322,11 @@ static void cursorcmd(void)
if (cmd_silent) if (cmd_silent)
return; return;
if (ui_is_external(kUICmdline)) {
ui_call_cmdline_pos(ccline.cmdpos, ccline.level);
return;
}
if (cmdmsg_rl) { if (cmdmsg_rl) {
msg_row = cmdline_row + (ccline.cmdspos / (int)(Columns - 1)); msg_row = cmdline_row + (ccline.cmdspos / (int)(Columns - 1));
msg_col = (int)Columns - (ccline.cmdspos % (int)(Columns - 1)) - 1; msg_col = (int)Columns - (ccline.cmdspos % (int)(Columns - 1)) - 1;
@@ -3200,6 +3344,9 @@ static void cursorcmd(void)
void gotocmdline(int clr) void gotocmdline(int clr)
{ {
if (ui_is_external(kUICmdline)) {
return;
}
msg_start(); msg_start();
if (cmdmsg_rl) if (cmdmsg_rl)
msg_col = Columns - 1; msg_col = Columns - 1;
@@ -5257,13 +5404,15 @@ int get_history_idx(int histype)
*/ */
static struct cmdline_info *get_ccline_ptr(void) static struct cmdline_info *get_ccline_ptr(void)
{ {
if ((State & CMDLINE) == 0) if ((State & CMDLINE) == 0) {
return NULL; return NULL;
if (ccline.cmdbuff != NULL) } else if (ccline.cmdbuff != NULL) {
return &ccline; return &ccline;
if (prev_ccline_used && prev_ccline.cmdbuff != NULL) } else if (ccline.prev_ccline && ccline.prev_ccline->cmdbuff != NULL) {
return &prev_ccline; return ccline.prev_ccline;
} else {
return NULL; return NULL;
}
} }
/* /*
@@ -5699,6 +5848,7 @@ static int ex_window(void)
return K_IGNORE; return K_IGNORE;
} }
cmdwin_type = get_cmdline_type(); cmdwin_type = get_cmdline_type();
cmdwin_level = ccline.level;
// Create empty command-line buffer. // Create empty command-line buffer.
buf_open_scratch(0, "[Command Line]"); buf_open_scratch(0, "[Command Line]");
@@ -5751,6 +5901,9 @@ static int ex_window(void)
curwin->w_cursor.col = ccline.cmdpos; curwin->w_cursor.col = ccline.cmdpos;
changed_line_abv_curs(); changed_line_abv_curs();
invalidate_botline(); invalidate_botline();
if (ui_is_external(kUICmdline)) {
ui_call_cmdline_hide(ccline.level);
}
redraw_later(SOME_VALID); redraw_later(SOME_VALID);
// Save the command line info, can be used recursively. // Save the command line info, can be used recursively.
@@ -5793,6 +5946,7 @@ static int ex_window(void)
// Restore the command line info. // Restore the command line info.
restore_cmdline(&save_ccline); restore_cmdline(&save_ccline);
cmdwin_type = 0; cmdwin_type = 0;
cmdwin_level = 0;
exmode_active = save_exmode; exmode_active = save_exmode;
@@ -6027,3 +6181,4 @@ static void set_search_match(pos_T *t)
coladvance((colnr_T)MAXCOL); coladvance((colnr_T)MAXCOL);
} }
} }

View File

@@ -74,6 +74,7 @@ local get_flags = function(o)
{'gettext'}, {'gettext'},
{'noglob'}, {'noglob'},
{'normal_fname_chars', 'P_NFNAME'}, {'normal_fname_chars', 'P_NFNAME'},
{'normal_dname_chars', 'P_NDNAME'},
{'pri_mkrc'}, {'pri_mkrc'},
{'deny_in_modelines', 'P_NO_ML'}, {'deny_in_modelines', 'P_NO_ML'},
{'deny_duplicates', 'P_NODUP'}, {'deny_duplicates', 'P_NODUP'},

View File

@@ -958,9 +958,10 @@ EXTERN int fill_diff INIT(= '-');
EXTERN int km_stopsel INIT(= FALSE); EXTERN int km_stopsel INIT(= FALSE);
EXTERN int km_startsel INIT(= FALSE); EXTERN int km_startsel INIT(= FALSE);
EXTERN int cedit_key INIT(= -1); /* key value of 'cedit' option */ EXTERN int cedit_key INIT(= -1); ///< key value of 'cedit' option
EXTERN int cmdwin_type INIT(= 0); /* type of cmdline window or 0 */ EXTERN int cmdwin_type INIT(= 0); ///< type of cmdline window or 0
EXTERN int cmdwin_result INIT(= 0); /* result of cmdline window or 0 */ EXTERN int cmdwin_result INIT(= 0); ///< result of cmdline window or 0
EXTERN int cmdwin_level INIT(= 0); ///< cmdline recursion level
EXTERN char_u no_lines_msg[] INIT(= N_("--No lines in buffer--")); EXTERN char_u no_lines_msg[] INIT(= N_("--No lines in buffer--"));

View File

@@ -124,9 +124,40 @@ static void nlua_error(lua_State *const lstate, const char *const msg)
/// omitted. /// omitted.
static int nlua_stricmp(lua_State *const lstate) FUNC_ATTR_NONNULL_ALL static int nlua_stricmp(lua_State *const lstate) FUNC_ATTR_NONNULL_ALL
{ {
const char *s1 = luaL_checklstring(lstate, 1, NULL); size_t s1_len;
const char *s2 = luaL_checklstring(lstate, 2, NULL); size_t s2_len;
const int ret = STRICMP(s1, s2); const char *s1 = luaL_checklstring(lstate, 1, &s1_len);
const char *s2 = luaL_checklstring(lstate, 2, &s2_len);
char *nul1;
char *nul2;
int ret = 0;
assert(s1[s1_len] == NUL);
assert(s2[s2_len] == NUL);
do {
nul1 = memchr(s1, NUL, s1_len);
nul2 = memchr(s2, NUL, s2_len);
ret = STRICMP(s1, s2);
if (ret == 0) {
// Compare "a\0" greater then "a".
if ((nul1 == NULL) != (nul2 == NULL)) {
ret = ((nul1 != NULL) - (nul2 != NULL));
break;
}
if (nul1 != NULL) {
assert(nul2 != NULL);
// Can't shift both strings by the same amount of bytes: lowercase
// letter may have different byte-length than uppercase.
s1_len -= (size_t)(nul1 - s1) + 1;
s2_len -= (size_t)(nul2 - s2) + 1;
s1 = nul1 + 1;
s2 = nul2 + 1;
} else {
break;
}
} else {
break;
}
} while (true);
lua_pop(lstate, 2); lua_pop(lstate, 2);
lua_pushnumber(lstate, (lua_Number)((ret > 0) - (ret < 0))); lua_pushnumber(lstate, (lua_Number)((ret > 0) - (ret < 0)));
return 1; return 1;
@@ -254,10 +285,6 @@ static int nlua_exec_lua_file(lua_State *const lstate) FUNC_ATTR_NONNULL_ALL
/// Called by lua interpreter itself to initialize state. /// Called by lua interpreter itself to initialize state.
static int nlua_state_init(lua_State *const lstate) FUNC_ATTR_NONNULL_ALL static int nlua_state_init(lua_State *const lstate) FUNC_ATTR_NONNULL_ALL
{ {
// stricmp
lua_pushcfunction(lstate, &nlua_stricmp);
lua_setglobal(lstate, "stricmp");
// print // print
lua_pushcfunction(lstate, &nlua_print); lua_pushcfunction(lstate, &nlua_print);
lua_setglobal(lstate, "print"); lua_setglobal(lstate, "print");
@@ -277,13 +304,17 @@ static int nlua_state_init(lua_State *const lstate) FUNC_ATTR_NONNULL_ALL
nlua_add_api_functions(lstate); nlua_add_api_functions(lstate);
// vim.types, vim.type_idx, vim.val_idx // vim.types, vim.type_idx, vim.val_idx
nlua_init_types(lstate); nlua_init_types(lstate);
// stricmp
lua_pushcfunction(lstate, &nlua_stricmp);
lua_setfield(lstate, -2, "stricmp");
lua_setglobal(lstate, "vim"); lua_setglobal(lstate, "vim");
return 0; return 0;
} }
/// Initialize lua interpreter /// Initialize lua interpreter
/// ///
/// Crashes NeoVim if initialization fails. Should be called once per lua /// Crashes Nvim if initialization fails. Should be called once per lua
/// interpreter instance. /// interpreter instance.
/// ///
/// @return New lua interpreter instance. /// @return New lua interpreter instance.

View File

@@ -682,6 +682,10 @@ static dict_T *menu_get_recursive(const vimmenu_T *menu, int modes)
tv_dict_add_str(dict, S_LEN("shortcut"), buf); tv_dict_add_str(dict, S_LEN("shortcut"), buf);
} }
if (menu->actext) {
tv_dict_add_str(dict, S_LEN("actext"), (char *)menu->actext);
}
if (menu->modes & MENU_TIP_MODE && menu->strings[MENU_INDEX_TIP]) { if (menu->modes & MENU_TIP_MODE && menu->strings[MENU_INDEX_TIP]) {
tv_dict_add_str(dict, S_LEN("tooltip"), tv_dict_add_str(dict, S_LEN("tooltip"),
(char *)menu->strings[MENU_INDEX_TIP]); (char *)menu->strings[MENU_INDEX_TIP]);
@@ -695,11 +699,9 @@ static dict_T *menu_get_recursive(const vimmenu_T *menu, int modes)
for (int bit = 0; bit < MENU_MODES; bit++) { for (int bit = 0; bit < MENU_MODES; bit++) {
if ((menu->modes & modes & (1 << bit)) != 0) { if ((menu->modes & modes & (1 << bit)) != 0) {
dict_T *impl = tv_dict_alloc(); dict_T *impl = tv_dict_alloc();
if (*menu->strings[bit] == NUL) { tv_dict_add_allocated_str(impl, S_LEN("rhs"),
tv_dict_add_str(impl, S_LEN("rhs"), (char *)"<Nop>"); str2special_save((char *)menu->strings[bit],
} else { false, false));
tv_dict_add_str(impl, S_LEN("rhs"), (char *)menu->strings[bit]);
}
tv_dict_add_nr(impl, S_LEN("silent"), menu->silent[bit]); tv_dict_add_nr(impl, S_LEN("silent"), menu->silent[bit]);
tv_dict_add_nr(impl, S_LEN("enabled"), tv_dict_add_nr(impl, S_LEN("enabled"),
(menu->enabled & (1 << bit)) ? 1 : 0); (menu->enabled & (1 << bit)) ? 1 : 0);

View File

@@ -1273,8 +1273,8 @@ int plines_win_nofold(win_T *wp, linenr_T lnum)
* Add column offset for 'number', 'relativenumber' and 'foldcolumn'. * Add column offset for 'number', 'relativenumber' and 'foldcolumn'.
*/ */
width = wp->w_width - win_col_off(wp); width = wp->w_width - win_col_off(wp);
if (width <= 0) { if (width <= 0 || col > 32000) {
return 32000; // bigger than the number of lines of the screen return 32000; // bigger than the number of screen columns
} }
if (col <= (unsigned int)width) { if (col <= (unsigned int)width) {
return 1; return 1;

View File

@@ -56,7 +56,6 @@ typedef struct {
typedef struct { typedef struct {
uint64_t id; uint64_t id;
size_t refcount; size_t refcount;
size_t pending_requests;
PMap(cstr_t) *subscribed_events; PMap(cstr_t) *subscribed_events;
bool closed; bool closed;
ChannelType type; ChannelType type;
@@ -71,7 +70,6 @@ typedef struct {
} data; } data;
uint64_t next_request_id; uint64_t next_request_id;
kvec_t(ChannelCallFrame *) call_stack; kvec_t(ChannelCallFrame *) call_stack;
kvec_t(WBuffer *) delayed_notifications;
MultiQueue *events; MultiQueue *events;
} Channel; } Channel;
@@ -205,14 +203,7 @@ bool channel_send_event(uint64_t id, const char *name, Array args)
} }
if (channel) { if (channel) {
if (channel->pending_requests) {
// Pending request, queue the notification for later sending.
const String method = cstr_as_string((char *)name);
WBuffer *buffer = serialize_request(id, 0, method, args, &out_buffer, 1);
kv_push(channel->delayed_notifications, buffer);
} else {
send_event(channel, name, args); send_event(channel, name, args);
}
} else { } else {
broadcast_event(name, args); broadcast_event(name, args);
} }
@@ -248,10 +239,8 @@ Object channel_send_call(uint64_t id,
// Push the frame // Push the frame
ChannelCallFrame frame = { request_id, false, false, NIL }; ChannelCallFrame frame = { request_id, false, false, NIL };
kv_push(channel->call_stack, &frame); kv_push(channel->call_stack, &frame);
channel->pending_requests++;
LOOP_PROCESS_EVENTS_UNTIL(&main_loop, channel->events, -1, frame.returned); LOOP_PROCESS_EVENTS_UNTIL(&main_loop, channel->events, -1, frame.returned);
(void)kv_pop(channel->call_stack); (void)kv_pop(channel->call_stack);
channel->pending_requests--;
if (frame.errored) { if (frame.errored) {
if (frame.result.type == kObjectTypeString) { if (frame.result.type == kObjectTypeString) {
@@ -276,10 +265,6 @@ Object channel_send_call(uint64_t id,
api_free_object(frame.result); api_free_object(frame.result);
} }
if (!channel->pending_requests) {
send_delayed_notifications(channel);
}
decref(channel); decref(channel);
return frame.errored ? NIL : frame.result; return frame.errored ? NIL : frame.result;
@@ -704,12 +689,8 @@ static void broadcast_event(const char *name, Array args)
for (size_t i = 0; i < kv_size(subscribed); i++) { for (size_t i = 0; i < kv_size(subscribed); i++) {
Channel *channel = kv_A(subscribed, i); Channel *channel = kv_A(subscribed, i);
if (channel->pending_requests) {
kv_push(channel->delayed_notifications, buffer);
} else {
channel_write(channel, buffer); channel_write(channel, buffer);
} }
}
end: end:
kv_destroy(subscribed); kv_destroy(subscribed);
@@ -786,7 +767,6 @@ static void free_channel(Channel *channel)
pmap_free(cstr_t)(channel->subscribed_events); pmap_free(cstr_t)(channel->subscribed_events);
kv_destroy(channel->call_stack); kv_destroy(channel->call_stack);
kv_destroy(channel->delayed_notifications);
if (channel->type != kChannelTypeProc) { if (channel->type != kChannelTypeProc) {
multiqueue_free(channel->events); multiqueue_free(channel->events);
} }
@@ -811,11 +791,9 @@ static Channel *register_channel(ChannelType type, uint64_t id,
rv->closed = false; rv->closed = false;
rv->unpacker = msgpack_unpacker_new(MSGPACK_UNPACKER_INIT_BUFFER_SIZE); rv->unpacker = msgpack_unpacker_new(MSGPACK_UNPACKER_INIT_BUFFER_SIZE);
rv->id = id > 0 ? id : next_chan_id++; rv->id = id > 0 ? id : next_chan_id++;
rv->pending_requests = 0;
rv->subscribed_events = pmap_new(cstr_t)(); rv->subscribed_events = pmap_new(cstr_t)();
rv->next_request_id = 1; rv->next_request_id = 1;
kv_init(rv->call_stack); kv_init(rv->call_stack);
kv_init(rv->delayed_notifications);
pmap_put(uint64_t)(channels, rv->id, rv); pmap_put(uint64_t)(channels, rv->id, rv);
ILOG("new channel %" PRIu64 " (%s): %s", rv->id, ILOG("new channel %" PRIu64 " (%s): %s", rv->id,
@@ -912,16 +890,6 @@ static WBuffer *serialize_response(uint64_t channel_id,
return rv; return rv;
} }
static void send_delayed_notifications(Channel* channel)
{
for (size_t i = 0; i < kv_size(channel->delayed_notifications); i++) {
WBuffer *buffer = kv_A(channel->delayed_notifications, i);
channel_write(channel, buffer);
}
kv_size(channel->delayed_notifications) = 0;
}
static void incref(Channel *channel) static void incref(Channel *channel)
{ {
channel->refcount++; channel->refcount++;

View File

@@ -1548,8 +1548,10 @@ void do_pending_operator(cmdarg_T *cap, int old_col, bool gui_yank)
} }
oap->start = VIsual; oap->start = VIsual;
if (VIsual_mode == 'V') if (VIsual_mode == 'V') {
oap->start.col = 0; oap->start.col = 0;
oap->start.coladd = 0;
}
} }
/* /*
@@ -6260,15 +6262,18 @@ static void nv_gomark(cmdarg_T *cap)
} else } else
nv_cursormark(cap, cap->arg, pos); nv_cursormark(cap, cap->arg, pos);
/* May need to clear the coladd that a mark includes. */ // May need to clear the coladd that a mark includes.
if (!virtual_active()) if (!virtual_active()) {
curwin->w_cursor.coladd = 0; curwin->w_cursor.coladd = 0;
}
check_cursor_col();
if (cap->oap->op_type == OP_NOP if (cap->oap->op_type == OP_NOP
&& pos != NULL && pos != NULL
&& (pos == (pos_T *)-1 || !equalpos(old_cursor, *pos)) && (pos == (pos_T *)-1 || !equalpos(old_cursor, *pos))
&& (fdo_flags & FDO_MARK) && (fdo_flags & FDO_MARK)
&& old_KeyTyped) && old_KeyTyped) {
foldOpenCursor(); foldOpenCursor();
}
} }
/* /*

View File

@@ -5535,7 +5535,7 @@ int get_default_register_name(void)
static yankreg_T *adjust_clipboard_name(int *name, bool quiet, bool writing) static yankreg_T *adjust_clipboard_name(int *name, bool quiet, bool writing)
{ {
#define MSG_NO_CLIP "clipboard: No provider. " \ #define MSG_NO_CLIP "clipboard: No provider. " \
"Try \":CheckHealth\" or \":h clipboard\"." "Try \":checkhealth\" or \":h clipboard\"."
yankreg_T *target = NULL; yankreg_T *target = NULL;
bool explicit_cb_reg = (*name == '*' || *name == '+'); bool explicit_cb_reg = (*name == '*' || *name == '+');

View File

@@ -242,6 +242,7 @@ typedef struct vimoption {
#define P_NO_DEF_EXP 0x8000000U ///< Do not expand default value. #define P_NO_DEF_EXP 0x8000000U ///< Do not expand default value.
#define P_RWINONLY 0x10000000U ///< only redraw current window #define P_RWINONLY 0x10000000U ///< only redraw current window
#define P_NDNAME 0x20000000U ///< only normal dir name chars allowed
#define HIGHLIGHT_INIT \ #define HIGHLIGHT_INIT \
"8:SpecialKey,~:EndOfBuffer,z:TermCursor,Z:TermCursorNC,@:NonText," \ "8:SpecialKey,~:EndOfBuffer,z:TermCursor,Z:TermCursorNC,@:NonText," \
@@ -2454,11 +2455,14 @@ did_set_string_option (
if ((secure || sandbox != 0) if ((secure || sandbox != 0)
&& (options[opt_idx].flags & P_SECURE)) { && (options[opt_idx].flags & P_SECURE)) {
errmsg = e_secure; errmsg = e_secure;
} else if ((options[opt_idx].flags & P_NFNAME) } else if (((options[opt_idx].flags & P_NFNAME)
&& vim_strpbrk(*varp, (char_u *)"/\\*?[|;&<>\r\n") != NULL) { && vim_strpbrk(*varp, (char_u *)(secure ? "/\\*?[|;&<>\r\n"
// Check for a "normal" file name in some options. Disallow a path : "/\\*?[<>\r\n")) != NULL)
// separator (slash and/or backslash), wildcards and characters that are || ((options[opt_idx].flags & P_NDNAME)
// often illegal in a file name. && vim_strpbrk(*varp, (char_u *)"*?[|;&<>\r\n") != NULL)) {
// Check for a "normal" directory or file name in some options. Disallow a
// path separator (slash and/or backslash), wildcards and characters that
// are often illegal in a file name. Be more permissive if "secure" is off.
errmsg = e_invarg; errmsg = e_invarg;
} }
/* 'backupcopy' */ /* 'backupcopy' */
@@ -3173,17 +3177,18 @@ did_set_string_option (
} else { } else {
// Options that are a list of flags. // Options that are a list of flags.
p = NULL; p = NULL;
if (varp == &p_ww) if (varp == &p_ww) { // 'whichwrap'
p = (char_u *)WW_ALL; p = (char_u *)WW_ALL;
if (varp == &p_shm) }
if (varp == &p_shm) { // 'shortmess'
p = (char_u *)SHM_ALL; p = (char_u *)SHM_ALL;
else if (varp == &(p_cpo)) } else if (varp == &(p_cpo)) { // 'cpoptions'
p = (char_u *)CPO_VI; p = (char_u *)CPO_VI;
else if (varp == &(curbuf->b_p_fo)) } else if (varp == &(curbuf->b_p_fo)) { // 'formatoptions'
p = (char_u *)FO_ALL; p = (char_u *)FO_ALL;
else if (varp == &curwin->w_p_cocu) } else if (varp == &curwin->w_p_cocu) { // 'concealcursor'
p = (char_u *)COCU_ALL; p = (char_u *)COCU_ALL;
else if (varp == &p_mouse) { } else if (varp == &p_mouse) { // 'mouse'
p = (char_u *)MOUSE_ALL; p = (char_u *)MOUSE_ALL;
} }
if (p != NULL) { if (p != NULL) {

View File

@@ -7,7 +7,7 @@
-- enable_if=nil, -- enable_if=nil,
-- defaults={condition=nil, if_true={vi=224, vim=0}, if_false=nil}, -- defaults={condition=nil, if_true={vi=224, vim=0}, if_false=nil},
-- secure=nil, gettext=nil, noglob=nil, normal_fname_chars=nil, -- secure=nil, gettext=nil, noglob=nil, normal_fname_chars=nil,
-- pri_mkrc=nil, deny_in_modelines=nil, -- pri_mkrc=nil, deny_in_modelines=nil, normal_dname_chars=nil,
-- expand=nil, nodefault=nil, no_mkrc=nil, vi_def=true, vim=true, -- expand=nil, nodefault=nil, no_mkrc=nil, vi_def=true, vim=true,
-- alloced=nil, -- alloced=nil,
-- save_pv_indir=nil, -- save_pv_indir=nil,
@@ -575,6 +575,7 @@ return {
full_name='dictionary', abbreviation='dict', full_name='dictionary', abbreviation='dict',
type='string', list='onecomma', scope={'global', 'buffer'}, type='string', list='onecomma', scope={'global', 'buffer'},
deny_duplicates=true, deny_duplicates=true,
normal_dname_chars=true,
vi_def=true, vi_def=true,
expand=true, expand=true,
varname='p_dict', varname='p_dict',
@@ -1750,6 +1751,7 @@ return {
{ {
full_name='printexpr', abbreviation='pexpr', full_name='printexpr', abbreviation='pexpr',
type='string', scope={'global'}, type='string', scope={'global'},
secure=true,
vi_def=true, vi_def=true,
varname='p_pexpr', varname='p_pexpr',
defaults={if_true={vi=""}} defaults={if_true={vi=""}}
@@ -2449,6 +2451,7 @@ return {
full_name='thesaurus', abbreviation='tsr', full_name='thesaurus', abbreviation='tsr',
type='string', list='onecomma', scope={'global', 'buffer'}, type='string', list='onecomma', scope={'global', 'buffer'},
deny_duplicates=true, deny_duplicates=true,
normal_dname_chars=true,
vi_def=true, vi_def=true,
expand=true, expand=true,
varname='p_tsr', varname='p_tsr',

View File

@@ -15,6 +15,8 @@
#include <stdbool.h> #include <stdbool.h>
#include "nvim/pos.h" #include "nvim/pos.h"
#include "nvim/types.h"
#include "nvim/profile.h"
/* /*
* The number of sub-matches is limited to 10. * The number of sub-matches is limited to 10.
@@ -41,18 +43,36 @@
#define NFA_ENGINE 2 #define NFA_ENGINE 2
typedef struct regengine regengine_T; typedef struct regengine regengine_T;
typedef struct regprog regprog_T;
typedef struct reg_extmatch reg_extmatch_T;
/// Structure to be used for multi-line matching.
/// Sub-match "no" starts in line "startpos[no].lnum" column "startpos[no].col"
/// and ends in line "endpos[no].lnum" just before column "endpos[no].col".
/// The line numbers are relative to the first line, thus startpos[0].lnum is
/// always 0.
/// When there is no match, the line number is -1.
typedef struct {
regprog_T *regprog;
lpos_T startpos[NSUBEXP];
lpos_T endpos[NSUBEXP];
int rmm_ic;
colnr_T rmm_maxcol; /// when not zero: maximum column
} regmmatch_T;
#include "nvim/buffer_defs.h"
/* /*
* Structure returned by vim_regcomp() to pass on to vim_regexec(). * Structure returned by vim_regcomp() to pass on to vim_regexec().
* This is the general structure. For the actual matcher, two specific * This is the general structure. For the actual matcher, two specific
* structures are used. See code below. * structures are used. See code below.
*/ */
typedef struct regprog { struct regprog {
regengine_T *engine; regengine_T *engine;
unsigned regflags; unsigned regflags;
unsigned re_engine; ///< Automatic, backtracking or NFA engine. unsigned re_engine; ///< Automatic, backtracking or NFA engine.
unsigned re_flags; ///< Second argument for vim_regcomp(). unsigned re_flags; ///< Second argument for vim_regcomp().
} regprog_T; };
/* /*
* Structure used by the back track matcher. * Structure used by the back track matcher.
@@ -125,31 +145,15 @@ typedef struct {
bool rm_ic; bool rm_ic;
} regmatch_T; } regmatch_T;
/*
* Structure to be used for multi-line matching.
* Sub-match "no" starts in line "startpos[no].lnum" column "startpos[no].col"
* and ends in line "endpos[no].lnum" just before column "endpos[no].col".
* The line numbers are relative to the first line, thus startpos[0].lnum is
* always 0.
* When there is no match, the line number is -1.
*/
typedef struct {
regprog_T *regprog;
lpos_T startpos[NSUBEXP];
lpos_T endpos[NSUBEXP];
int rmm_ic;
colnr_T rmm_maxcol; /* when not zero: maximum column */
} regmmatch_T;
/* /*
* Structure used to store external references: "\z\(\)" to "\z\1". * Structure used to store external references: "\z\(\)" to "\z\1".
* Use a reference count to avoid the need to copy this around. When it goes * Use a reference count to avoid the need to copy this around. When it goes
* from 1 to zero the matches need to be freed. * from 1 to zero the matches need to be freed.
*/ */
typedef struct { struct reg_extmatch {
short refcnt; int16_t refcnt;
char_u *matches[NSUBEXP]; char_u *matches[NSUBEXP];
} reg_extmatch_T; };
struct regengine { struct regengine {
regprog_T *(*regcomp)(char_u*, int); regprog_T *(*regcomp)(char_u*, int);

View File

@@ -345,8 +345,9 @@ void update_screen(int type)
if (need_highlight_changed) if (need_highlight_changed)
highlight_changed(); highlight_changed();
if (type == CLEAR) { /* first clear screen */ if (type == CLEAR) { // first clear screen
screenclear(); /* will reset clear_cmdline */ screenclear(); // will reset clear_cmdline
cmdline_screen_cleared(); // clear external cmdline state
type = NOT_VALID; type = NOT_VALID;
} }
@@ -692,12 +693,18 @@ static void win_update(win_T *wp)
if (wp->w_nrwidth != i) { if (wp->w_nrwidth != i) {
type = NOT_VALID; type = NOT_VALID;
wp->w_nrwidth = i; wp->w_nrwidth = i;
} else if (buf->b_mod_set && buf->b_mod_xlines != 0 && wp->w_redraw_top != 0) {
/* if (buf->terminal) {
* When there are both inserted/deleted lines and specific lines to be terminal_resize(buf->terminal,
* redrawn, w_redraw_top and w_redraw_bot may be invalid, just redraw (uint16_t)(MAX(0, curwin->w_width - win_col_off(curwin))),
* everything (only happens when redrawing is off for while). (uint16_t)curwin->w_height);
*/ }
} else if (buf->b_mod_set
&& buf->b_mod_xlines != 0
&& wp->w_redraw_top != 0) {
// When there are both inserted/deleted lines and specific lines to be
// redrawn, w_redraw_top and w_redraw_bot may be invalid, just redraw
// everything (only happens when redrawing is off for while).
type = NOT_VALID; type = NOT_VALID;
} else { } else {
/* /*
@@ -2202,7 +2209,6 @@ win_line (
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
int line_attr_low_priority = 0; // current line, lowest priority
matchitem_T *cur; // points to the match list matchitem_T *cur; // points to the match list
match_T *shl; // points to search_hl or a match match_T *shl; // points to search_hl or a match
int shl_flag; // flag to indicate whether search_hl int shl_flag; // flag to indicate whether search_hl
@@ -2428,13 +2434,7 @@ win_line (
filler_lines = wp->w_topfill; filler_lines = wp->w_topfill;
filler_todo = filler_lines; filler_todo = filler_lines;
// 'cursorline' highlighting for the current window. Not when Visual mode is // If this line has a sign with line highlighting set line_attr.
// 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);
@@ -2449,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_low_priority || line_attr) { if (line_attr != 0) {
area_highlighting = true; area_highlighting = true;
} }
@@ -2671,6 +2671,20 @@ 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) {
@@ -3589,9 +3603,7 @@ win_line (
// 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
&& line_attr_low_priority == 0) {
// In virtualedit, visual selections may extend 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) {
@@ -3655,7 +3667,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_low_priority || line_attr) } else if ((diff_hlf != (hlf_T)0 || line_attr != 0)
&& (wp->w_p_rl && (wp->w_p_rl
? (col >= 0) ? (col >= 0)
: (col - boguscols < wp->w_width))) { : (col - boguscols < wp->w_width))) {
@@ -3667,8 +3679,7 @@ 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_low_priority || line_attr) if (line_attr != 0 && char_attr == search_attr && col > 0) {
&& char_attr == search_attr && col > 0) {
char_attr = line_attr; char_attr = line_attr;
} }
if (diff_hlf == HLF_TXD) { if (diff_hlf == HLF_TXD) {
@@ -4037,9 +4048,6 @@ win_line (
} }
} }
// 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'.

View File

@@ -2,7 +2,6 @@
#define NVIM_SYNTAX_DEFS_H #define NVIM_SYNTAX_DEFS_H
#include "nvim/highlight_defs.h" #include "nvim/highlight_defs.h"
#include "nvim/regexp_defs.h"
# define SST_MIN_ENTRIES 150 /* minimal size for state stack array */ # define SST_MIN_ENTRIES 150 /* minimal size for state stack array */
# define SST_MAX_ENTRIES 1000 /* maximal size for state stack array */ # define SST_MAX_ENTRIES 1000 /* maximal size for state stack array */
@@ -10,6 +9,11 @@
# define SST_DIST 16 /* normal distance between entries */ # define SST_DIST 16 /* normal distance between entries */
# define SST_INVALID (synstate_T *)-1 /* invalid syn_state pointer */ # define SST_INVALID (synstate_T *)-1 /* invalid syn_state pointer */
typedef struct syn_state synstate_T;
#include "nvim/buffer_defs.h"
#include "nvim/regexp_defs.h"
typedef unsigned short disptick_T; /* display tick type */ typedef unsigned short disptick_T; /* display tick type */
/* struct passed to in_id_list() */ /* struct passed to in_id_list() */
@@ -48,8 +52,6 @@ typedef struct buf_state {
* syn_state contains the syntax state stack for the start of one line. * syn_state contains the syntax state stack for the start of one line.
* Used by b_sst_array[]. * Used by b_sst_array[].
*/ */
typedef struct syn_state synstate_T;
struct syn_state { struct syn_state {
synstate_T *sst_next; /* next entry in used or free list */ synstate_T *sst_next; /* next entry in used or free list */
linenr_T sst_lnum; /* line number for this state */ linenr_T sst_lnum; /* line number for this state */

View File

@@ -10,6 +10,8 @@ typedef void (*terminal_write_cb)(char *buffer, size_t size, void *data);
typedef void (*terminal_resize_cb)(uint16_t width, uint16_t height, void *data); typedef void (*terminal_resize_cb)(uint16_t width, uint16_t height, void *data);
typedef void (*terminal_close_cb)(void *data); typedef void (*terminal_close_cb)(void *data);
#include "nvim/buffer_defs.h"
typedef struct { typedef struct {
void *data; void *data;
uint16_t width, height; uint16_t width, height;

View File

@@ -62,7 +62,9 @@ NEW_TESTS ?= \
test_mksession_utf8.res \ test_mksession_utf8.res \
test_nested_function.res \ test_nested_function.res \
test_normal.res \ test_normal.res \
test_profile.res \
test_quickfix.res \ test_quickfix.res \
test_retab.res \
test_search.res \ test_search.res \
test_signs.res \ test_signs.res \
test_smartindent.res \ test_smartindent.res \

View File

@@ -34,4 +34,5 @@ source test_taglist.vim
source test_true_false.vim source test_true_false.vim
source test_unlet.vim source test_unlet.vim
source test_utf8.vim source test_utf8.vim
source test_virtualedit.vim
source test_window_cmd.vim source test_window_cmd.vim

View File

@@ -104,6 +104,29 @@ func Test_keymap_valid()
call assert_fails(":set kmp=trunc\x00name", "trunc") call assert_fails(":set kmp=trunc\x00name", "trunc")
endfunc endfunc
func Check_dir_option(name)
" Check that it's possible to set the option.
exe 'set ' . a:name . '=/usr/share/dict/words'
call assert_equal('/usr/share/dict/words', eval('&' . a:name))
exe 'set ' . a:name . '=/usr/share/dict/words,/and/there'
call assert_equal('/usr/share/dict/words,/and/there', eval('&' . a:name))
exe 'set ' . a:name . '=/usr/share/dict\ words'
call assert_equal('/usr/share/dict words', eval('&' . a:name))
" Check rejecting weird characters.
call assert_fails("set " . a:name . "=/not&there", "E474:")
call assert_fails("set " . a:name . "=/not>there", "E474:")
call assert_fails("set " . a:name . "=/not.*there", "E474:")
endfunc
func Test_dictionary()
call Check_dir_option('dictionary')
endfunc
func Test_thesaurus()
call Check_dir_option('thesaurus')
endfunc
func Test_complete() func Test_complete()
" Trailing single backslash used to cause invalid memory access. " Trailing single backslash used to cause invalid memory access.
set complete=s\ set complete=s\

View File

@@ -0,0 +1,147 @@
" Test Vim profiler
if !has('profile')
finish
endif
func Test_profile_func()
let lines = [
\ "func! Foo1()",
\ "endfunc",
\ "func! Foo2()",
\ " let l:count = 100",
\ " while l:count > 0",
\ " let l:count = l:count - 1",
\ " endwhile",
\ "endfunc",
\ "func! Foo3()",
\ "endfunc",
\ "func! Bar()",
\ "endfunc",
\ "call Foo1()",
\ "call Foo1()",
\ "profile pause",
\ "call Foo1()",
\ "profile continue",
\ "call Foo2()",
\ "call Foo3()",
\ "call Bar()",
\ "if !v:profiling",
\ " delfunc Foo2",
\ "endif",
\ "delfunc Foo3",
\ ]
call writefile(lines, 'Xprofile_func.vim')
call system(v:progpath
\ . ' -es -u NONE -U NONE -i NONE --noplugin'
\ . ' -c "profile start Xprofile_func.log"'
\ . ' -c "profile func Foo*"'
\ . ' -c "so Xprofile_func.vim"'
\ . ' -c "qall!"')
call assert_equal(0, v:shell_error)
let lines = readfile('Xprofile_func.log')
" - Foo1() is called 3 times but should be reported as called twice
" since one call is in between "profile pause" .. "profile continue".
" - Foo2() should come before Foo1() since Foo1() does much more work.
" - Foo3() is not reported because function is deleted.
" - Unlike Foo3(), Foo2() should not be deleted since there is a check
" for v:profiling.
" - Bar() is not reported since it does not match "profile func Foo*".
call assert_equal(28, len(lines))
call assert_equal('FUNCTION Foo1()', lines[0])
call assert_equal('Called 2 times', lines[1])
call assert_match('^Total time:\s\+\d\+\.\d\+$', lines[2])
call assert_match('^ Self time:\s\+\d\+\.\d\+$', lines[3])
call assert_equal('', lines[4])
call assert_equal('count total (s) self (s)', lines[5])
call assert_equal('', lines[6])
call assert_equal('FUNCTION Foo2()', lines[7])
call assert_equal('Called 1 time', lines[8])
call assert_match('^Total time:\s\+\d\+\.\d\+$', lines[9])
call assert_match('^ Self time:\s\+\d\+\.\d\+$', lines[10])
call assert_equal('', lines[11])
call assert_equal('count total (s) self (s)', lines[12])
call assert_match('^\s*1\s\+.*\slet l:count = 100$', lines[13])
call assert_match('^\s*101\s\+.*\swhile l:count > 0$', lines[14])
call assert_match('^\s*100\s\+.*\s let l:count = l:count - 1$', lines[15])
call assert_match('^\s*100\s\+.*\sendwhile$', lines[16])
call assert_equal('', lines[17])
call assert_equal('FUNCTIONS SORTED ON TOTAL TIME', lines[18])
call assert_equal('count total (s) self (s) function', lines[19])
call assert_match('^\s*1\s\+\d\+\.\d\+\s\+Foo2()$', lines[20])
call assert_match('^\s*2\s\+\d\+\.\d\+\s\+Foo1()$', lines[21])
call assert_equal('', lines[22])
call assert_equal('FUNCTIONS SORTED ON SELF TIME', lines[23])
call assert_equal('count total (s) self (s) function', lines[24])
call assert_match('^\s*1\s\+\d\+\.\d\+\s\+Foo2()$', lines[25])
call assert_match('^\s*2\s\+\d\+\.\d\+\s\+Foo1()$', lines[26])
call assert_equal('', lines[27])
call delete('Xprofile_func.vim')
call delete('Xprofile_func.log')
endfunc
func Test_profile_file()
let lines = [
\ 'func! Foo()',
\ 'endfunc',
\ 'for i in range(10)',
\ ' " a comment',
\ ' call Foo()',
\ 'endfor',
\ 'call Foo()',
\ ]
call writefile(lines, 'Xprofile_file.vim')
call system(v:progpath
\ . ' -es -u NONE -U NONE -i NONE --noplugin'
\ . ' -c "profile start Xprofile_file.log"'
\ . ' -c "profile file Xprofile_file.vim"'
\ . ' -c "so Xprofile_file.vim"'
\ . ' -c "so Xprofile_file.vim"'
\ . ' -c "qall!"')
call assert_equal(0, v:shell_error)
let lines = readfile('Xprofile_file.log')
call assert_equal(14, len(lines))
call assert_match('^SCRIPT .*Xprofile_file.vim$', lines[0])
call assert_equal('Sourced 2 times', lines[1])
call assert_match('^Total time:\s\+\d\+\.\d\+$', lines[2])
call assert_match('^ Self time:\s\+\d\+\.\d\+$', lines[3])
call assert_equal('', lines[4])
call assert_equal('count total (s) self (s)', lines[5])
call assert_equal(' func! Foo()', lines[6])
call assert_equal(' endfunc', lines[7])
" Loop iterates 10 times. Since script runs twice, body executes 20 times.
" First line of loop executes one more time than body to detect end of loop.
call assert_match('^\s*22\s\+\d\+\.\d\+\s\+for i in range(10)$', lines[8])
call assert_equal(' " a comment', lines[9])
" if self and total are equal we only get one number
call assert_match('^\s*20\s\+\(\d\+\.\d\+\s\+\)\=\d\+\.\d\+\s\+call Foo()$', lines[10])
call assert_match('^\s*20\s\+\d\+\.\d\+\s\+endfor$', lines[11])
" if self and total are equal we only get one number
call assert_match('^\s*2\s\+\(\d\+\.\d\+\s\+\)\=\d\+\.\d\+\s\+call Foo()$', lines[12])
call assert_equal('', lines[13])
call delete('Xprofile_file.vim')
call delete('Xprofile_file.log')
endfunc
func Test_profile_completion()
call feedkeys(":profile \<C-A>\<C-B>\"\<CR>", 'tx')
call assert_equal('"profile continue dump file func pause start stop', @:)
call feedkeys(":profile start test_prof\<C-A>\<C-B>\"\<CR>", 'tx')
call assert_match('^"profile start.* test_profile\.vim', @:)
endfunc
func Test_profile_errors()
call assert_fails("profile func Foo", 'E750:')
call assert_fails("profile pause", 'E750:')
call assert_fails("profile continue", 'E750:')
endfunc

View File

@@ -0,0 +1,77 @@
" Test :retab
func SetUp()
new
call setline(1, "\ta \t b c ")
endfunc
func TearDown()
bwipe!
endfunc
func Retab(bang, n)
let l:old_tabstop = &tabstop
let l:old_line = getline(1)
exe "retab" . a:bang . a:n
let l:line = getline(1)
call setline(1, l:old_line)
if a:n > 0
" :retab changes 'tabstop' to n with argument n > 0.
call assert_equal(a:n, &tabstop)
exe 'set tabstop=' . l:old_tabstop
else
" :retab does not change 'tabstop' with empty or n <= 0.
call assert_equal(l:old_tabstop, &tabstop)
endif
return l:line
endfunc
func Test_retab()
set tabstop=8 noexpandtab
call assert_equal("\ta\t b c ", Retab('', ''))
call assert_equal("\ta\t b c ", Retab('', 0))
call assert_equal("\ta\t b c ", Retab('', 8))
call assert_equal("\ta\t b\t c\t ", Retab('!', ''))
call assert_equal("\ta\t b\t c\t ", Retab('!', 0))
call assert_equal("\ta\t b\t c\t ", Retab('!', 8))
call assert_equal("\t\ta\t\t\tb c ", Retab('', 4))
call assert_equal("\t\ta\t\t\tb\t\t c\t ", Retab('!', 4))
call assert_equal(" a\t\tb c ", Retab('', 10))
call assert_equal(" a\t\tb c ", Retab('!', 10))
set tabstop=8 expandtab
call assert_equal(" a b c ", Retab('', ''))
call assert_equal(" a b c ", Retab('', 0))
call assert_equal(" a b c ", Retab('', 8))
call assert_equal(" a b c ", Retab('!', ''))
call assert_equal(" a b c ", Retab('!', 0))
call assert_equal(" a b c ", Retab('!', 8))
call assert_equal(" a b c ", Retab(' ', 4))
call assert_equal(" a b c ", Retab('!', 4))
call assert_equal(" a b c ", Retab(' ', 10))
call assert_equal(" a b c ", Retab('!', 10))
set tabstop=4 noexpandtab
call assert_equal("\ta\t\tb c ", Retab('', ''))
call assert_equal("\ta\t\tb\t\t c\t ", Retab('!', ''))
call assert_equal("\t a\t\t\tb c ", Retab('', 3))
call assert_equal("\t a\t\t\tb\t\t\tc\t ", Retab('!', 3))
call assert_equal(" a\t b c ", Retab('', 5))
call assert_equal(" a\t b\t\t c\t ", Retab('!', 5))
set tabstop=4 expandtab
call assert_equal(" a b c ", Retab('', ''))
call assert_equal(" a b c ", Retab('!', ''))
call assert_equal(" a b c ", Retab('', 3))
call assert_equal(" a b c ", Retab('!', 3))
call assert_equal(" a b c ", Retab('', 5))
call assert_equal(" a b c ", Retab('!', 5))
endfunc
func Test_retab_error()
call assert_fails('retab -1', 'E487:')
call assert_fails('retab! -1', 'E487:')
endfunc

View File

@@ -0,0 +1,43 @@
" Tests for 'virtualedit'.
func Test_yank_move_change()
new
call setline(1, [
\ "func foo() error {",
\ "\tif n, err := bar();",
\ "\terr != nil {",
\ "\t\treturn err",
\ "\t}",
\ "\tn = n * n",
\ ])
set virtualedit=all
set ts=4
function! MoveSelectionDown(count) abort
normal! m`
silent! exe "'<,'>move'>+".a:count
norm! ``
endfunction
xmap ]e :<C-U>call MoveSelectionDown(v:count1)<CR>
2
normal 2gg
normal J
normal jVj
normal ]e
normal ce
bwipe!
set virtualedit=
set ts=8
endfunc
func Test_paste_end_of_line()
new
set virtualedit=all
call setline(1, ['456', '123'])
normal! gg0"ay$
exe "normal! 2G$lllA\<C-O>:normal! \"agP\r"
call assert_equal('123456', getline(2))
bwipe!
set virtualedit=
endfunc

View File

@@ -1,13 +1,13 @@
" Tests for Visual mode " Tests for various Visual mode.
if !has('multi_byte')
finish
endif
if !has('visual') if !has('visual')
finish finish
endif endif
func Test_block_shift_multibyte() func Test_block_shift_multibyte()
" Uses double-wide character.
if !has('multi_byte')
return
endif
split split
call setline(1, ['xヹxxx', 'ヹxxx']) call setline(1, ['xヹxxx', 'ヹxxx'])
exe "normal 1G0l\<C-V>jl>" exe "normal 1G0l\<C-V>jl>"
@@ -35,3 +35,11 @@ func Test_Visual_vapo()
normal vapo normal vapo
bwipe! bwipe!
endfunc endfunc
func Test_dotregister_paste()
new
exe "norm! ihello world\<esc>"
norm! 0ve".p
call assert_equal('hello world world', getline(1))
q!
endfunc

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