aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CMakeLists.txt4
-rwxr-xr-xci/snap/deploy.sh2
-rw-r--r--config/CMakeLists.txt2
-rw-r--r--contrib/local.mk.example2
-rw-r--r--man/nvim.13
-rw-r--r--runtime/CMakeLists.txt2
-rw-r--r--runtime/autoload/dist/ft.vim21
-rw-r--r--runtime/doc/api.txt977
-rw-r--r--runtime/doc/autocmd.txt4
-rw-r--r--runtime/doc/diagnostic.txt67
-rw-r--r--runtime/doc/eval.txt35
-rw-r--r--runtime/doc/filetype.txt12
-rw-r--r--runtime/doc/helphelp.txt4
-rw-r--r--runtime/doc/lsp.txt270
-rw-r--r--runtime/doc/lua.txt70
-rw-r--r--runtime/doc/map.txt5
-rw-r--r--runtime/doc/pi_msgpack.txt2
-rw-r--r--runtime/doc/syntax.txt8
-rw-r--r--runtime/doc/treesitter.txt11
-rw-r--r--runtime/doc/usr_20.txt2
-rw-r--r--runtime/doc/vim_diff.txt2
-rw-r--r--runtime/doc/visual.txt3
-rw-r--r--runtime/filetype.vim23
-rw-r--r--runtime/ftplugin/indent.vim7
-rw-r--r--runtime/ftplugin/jsonc.vim10
-rw-r--r--runtime/ftplugin/vb.vim82
-rw-r--r--runtime/lua/vim/F.lua2
-rw-r--r--runtime/lua/vim/_meta.lua2
-rw-r--r--runtime/lua/vim/diagnostic.lua294
-rw-r--r--runtime/lua/vim/lsp.lua205
-rw-r--r--runtime/lua/vim/lsp/buf.lua31
-rw-r--r--runtime/lua/vim/lsp/diagnostic.lua27
-rw-r--r--runtime/lua/vim/lsp/handlers.lua3
-rw-r--r--runtime/lua/vim/lsp/log.lua1
-rw-r--r--runtime/lua/vim/lsp/rpc.lua13
-rw-r--r--runtime/lua/vim/lsp/sync.lua79
-rw-r--r--runtime/lua/vim/lsp/tagfunc.lua76
-rw-r--r--runtime/lua/vim/lsp/util.lua258
-rw-r--r--runtime/lua/vim/shared.lua20
-rw-r--r--runtime/lua/vim/treesitter.lua2
-rw-r--r--runtime/lua/vim/treesitter/language.lua2
-rw-r--r--runtime/lua/vim/treesitter/languagetree.lua4
-rw-r--r--runtime/lua/vim/treesitter/query.lua6
-rw-r--r--runtime/lua/vim/uri.lua28
-rw-r--r--runtime/nvim.appdata.xml1
-rw-r--r--runtime/pack/dist/opt/termdebug/plugin/termdebug.vim317
-rw-r--r--runtime/rgb.txt753
-rw-r--r--runtime/scripts.vim4
-rw-r--r--runtime/syntax/indent.vim9
-rw-r--r--runtime/syntax/vim.vim8
-rw-r--r--runtime/tools/check_colors.vim14
-rwxr-xr-xscripts/gen_vimdoc.py1
-rw-r--r--scripts/lintcommit.lua2
-rw-r--r--src/mpack/object.h2
-rw-r--r--src/nvim/api/buffer.c4
-rw-r--r--src/nvim/api/extmark.c2
-rw-r--r--src/nvim/api/vimscript.c4
-rw-r--r--src/nvim/auevents.lua2
-rw-r--r--src/nvim/buffer.c20
-rw-r--r--src/nvim/buffer_defs.h16
-rw-r--r--src/nvim/change.c6
-rw-r--r--src/nvim/cursor_shape.c2
-rw-r--r--src/nvim/debugger.c2
-rw-r--r--src/nvim/diff.c2
-rw-r--r--src/nvim/edit.c16
-rw-r--r--src/nvim/eval.c22
-rw-r--r--src/nvim/eval/funcs.c40
-rw-r--r--src/nvim/eval/typval.h2
-rw-r--r--src/nvim/eval/userfunc.c4
-rw-r--r--src/nvim/ex_cmds.c16
-rw-r--r--src/nvim/ex_cmds2.c4
-rw-r--r--src/nvim/ex_cmds_defs.h6
-rw-r--r--src/nvim/ex_docmd.c39
-rw-r--r--src/nvim/ex_eval.c4
-rw-r--r--src/nvim/ex_getln.c12
-rw-r--r--src/nvim/ex_session.c8
-rw-r--r--src/nvim/file_search.c10
-rw-r--r--src/nvim/fileio.c22
-rw-r--r--src/nvim/fold.c16
-rw-r--r--src/nvim/getchar.c16
-rw-r--r--src/nvim/globals.h44
-rw-r--r--src/nvim/hardcopy.c7
-rw-r--r--src/nvim/if_cscope.c4
-rw-r--r--src/nvim/lib/kbtree.h2
-rw-r--r--src/nvim/lib/khash.h4
-rw-r--r--src/nvim/lua/stdlib.c6
-rw-r--r--src/nvim/lua/vim.lua13
-rw-r--r--src/nvim/lua/xdiff.c2
-rw-r--r--src/nvim/mark.c2
-rw-r--r--src/nvim/mbyte.c8
-rw-r--r--src/nvim/memfile.c2
-rw-r--r--src/nvim/memline.c18
-rw-r--r--src/nvim/memory.c5
-rw-r--r--src/nvim/menu.c6
-rw-r--r--src/nvim/message.c10
-rw-r--r--src/nvim/misc1.c12
-rw-r--r--src/nvim/mouse.c6
-rw-r--r--src/nvim/move.c6
-rw-r--r--src/nvim/normal.c20
-rw-r--r--src/nvim/ops.c70
-rw-r--r--src/nvim/option.c48
-rw-r--r--src/nvim/os/fs.c2
-rw-r--r--src/nvim/os/stdpaths.c2
-rw-r--r--src/nvim/path.c30
-rw-r--r--src/nvim/quickfix.c6
-rw-r--r--src/nvim/runtime.c6
-rw-r--r--src/nvim/screen.c18
-rw-r--r--src/nvim/search.c66
-rw-r--r--src/nvim/shada.c2
-rw-r--r--src/nvim/sign.c6
-rw-r--r--src/nvim/spell.c52
-rw-r--r--src/nvim/spellfile.c72
-rw-r--r--src/nvim/strings.c4
-rw-r--r--src/nvim/syntax.c73
-rw-r--r--src/nvim/tag.c10
-rw-r--r--src/nvim/testdir/test_arglist.vim16
-rw-r--r--src/nvim/testdir/test_autochdir.vim38
-rw-r--r--src/nvim/testdir/test_autocmd.vim35
-rw-r--r--src/nvim/testdir/test_blockedit.vim52
-rw-r--r--src/nvim/testdir/test_bufwintabinfo.vim204
-rw-r--r--src/nvim/testdir/test_cd.vim39
-rw-r--r--src/nvim/testdir/test_cmdline.vim3
-rw-r--r--src/nvim/testdir/test_filetype.vim73
-rw-r--r--src/nvim/testdir/test_functions.vim4
-rw-r--r--src/nvim/testdir/test_highlight.vim10
-rw-r--r--src/nvim/testdir/test_listchars.vim141
-rw-r--r--src/nvim/testdir/test_listlbr.vim2
-rw-r--r--src/nvim/testdir/test_put.vim13
-rw-r--r--src/nvim/testdir/test_quickfix.vim3
-rw-r--r--src/nvim/testdir/test_registers.vim5
-rw-r--r--src/nvim/testdir/test_textobjects.vim32
-rw-r--r--src/nvim/undo.c4
-rw-r--r--src/nvim/version.c8
-rw-r--r--src/nvim/viml/parser/expressions.c2
-rw-r--r--src/nvim/window.c41
-rw-r--r--src/uncrustify.cfg44
-rw-r--r--test/functional/core/fileio_spec.lua9
-rw-r--r--test/functional/core/startup_spec.lua2
-rw-r--r--test/functional/ex_cmds/cd_spec.lua13
-rw-r--r--test/functional/fixtures/api_level_8.mpackbin0 -> 28544 bytes
-rw-r--r--test/functional/legacy/autochdir_spec.lua38
-rw-r--r--test/functional/legacy/fnamemodify_spec.lua2
-rw-r--r--test/functional/legacy/packadd_spec.lua3
-rw-r--r--test/functional/lua/diagnostic_spec.lua71
-rw-r--r--test/functional/lua/uri_spec.lua6
-rw-r--r--test/functional/lua/vim_spec.lua14
-rw-r--r--test/functional/options/chars_spec.lua92
-rw-r--r--test/functional/plugin/lsp/incremental_sync_spec.lua26
-rw-r--r--test/functional/plugin/lsp_spec.lua10
-rw-r--r--test/functional/treesitter/parser_spec.lua12
-rw-r--r--test/unit/path_spec.lua14
-rw-r--r--third-party/CMakeLists.txt14
152 files changed, 3029 insertions, 2801 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index f44937b5ae..87223b9d4e 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -136,14 +136,14 @@ set_property(CACHE CMAKE_BUILD_TYPE PROPERTY
# If not in a git repo (e.g., a tarball) these tokens define the complete
# version string, else they are combined with the result of `git describe`.
set(NVIM_VERSION_MAJOR 0)
-set(NVIM_VERSION_MINOR 6)
+set(NVIM_VERSION_MINOR 7)
set(NVIM_VERSION_PATCH 0)
set(NVIM_VERSION_PRERELEASE "-dev") # for package maintainers
# API level
set(NVIM_API_LEVEL 8) # Bump this after any API change.
set(NVIM_API_LEVEL_COMPAT 0) # Adjust this after a _breaking_ API change.
-set(NVIM_API_PRERELEASE true)
+set(NVIM_API_PRERELEASE false)
set(NVIM_VERSION_BUILD_TYPE "${CMAKE_BUILD_TYPE}")
# NVIM_VERSION_CFLAGS set further below.
diff --git a/ci/snap/deploy.sh b/ci/snap/deploy.sh
index 579c48e933..8429059e22 100755
--- a/ci/snap/deploy.sh
+++ b/ci/snap/deploy.sh
@@ -24,7 +24,7 @@ snap_realease_needed() {
trigger_snapcraft_webhook() {
[[ -n "${PAYLOAD_SIG}" ]] || exit
- echo "Triggering new snap relase via webhook..."
+ echo "Triggering new snap release via webhook..."
curl -X POST \
-H "Content-Type: application/json" \
-H "X-Hub-Signature: sha1=${PAYLOAD_SIG}" \
diff --git a/config/CMakeLists.txt b/config/CMakeLists.txt
index 581f25857b..613475b00d 100644
--- a/config/CMakeLists.txt
+++ b/config/CMakeLists.txt
@@ -92,7 +92,7 @@ if (NOT "${HAVE_BE64TOH}")
# any case and ORDER_BIG_ENDIAN will not be examined.
# - CMAKE_CROSSCOMPILING *and* HAVE_BE64TOH are both false. In this case
# be64toh function which uses cycle and arithmetic operations is used which
- # will work regardless of endianess. Function is sub-optimal though.
+ # will work regardless of endianness. Function is sub-optimal though.
check_c_source_runs("
${SI}
${MS}
diff --git a/contrib/local.mk.example b/contrib/local.mk.example
index 778e848d60..20396e86ae 100644
--- a/contrib/local.mk.example
+++ b/contrib/local.mk.example
@@ -27,7 +27,7 @@
# With non-Debug builds interprocedural optimization (IPO) (which includes
# link-time optimization (LTO)) is enabled by default, which causes the link
-# step to take a significant amout of time, which is relevant when building
+# step to take a significant amount of time, which is relevant when building
# often. You can disable it explicitly:
# CMAKE_EXTRA_FLAGS += -DENABLE_LTO=OFF
diff --git a/man/nvim.1 b/man/nvim.1
index b206b62343..43dfc21dc7 100644
--- a/man/nvim.1
+++ b/man/nvim.1
@@ -177,8 +177,7 @@ If
.Ar vimrc
is
.Cm NORC ,
-do not load any initialization files (except plugins),
-and do not attempt to parse environment variables.
+do not load any initialization files (except plugins).
If
.Ar vimrc
is
diff --git a/runtime/CMakeLists.txt b/runtime/CMakeLists.txt
index 37029874f2..f656f1cbc3 100644
--- a/runtime/CMakeLists.txt
+++ b/runtime/CMakeLists.txt
@@ -123,7 +123,7 @@ foreach(PROG ${RUNTIME_PROGRAMS})
endforeach()
globrecurse_wrapper(RUNTIME_FILES ${CMAKE_CURRENT_SOURCE_DIR}
- rgb.txt *.vim *.lua *.dict *.py *.rb *.ps *.spl *.tutor *.tutor.json)
+ *.vim *.lua *.dict *.py *.rb *.ps *.spl *.tutor *.tutor.json)
foreach(F ${RUNTIME_FILES})
get_filename_component(BASEDIR ${F} PATH)
diff --git a/runtime/autoload/dist/ft.vim b/runtime/autoload/dist/ft.vim
index 7484149a26..74df871544 100644
--- a/runtime/autoload/dist/ft.vim
+++ b/runtime/autoload/dist/ft.vim
@@ -219,6 +219,23 @@ func dist#ft#FTe()
endif
endfunc
+" Distinguish between Forth and F#.
+" Provided by Doug Kearns.
+func dist#ft#FTfs()
+ if exists("g:filetype_fs")
+ exe "setf " . g:filetype_fs
+ else
+ let line = getline(nextnonblank(1))
+ " comments and colon definitions
+ if line =~ '^\s*\.\=( ' || line =~ '^\s*\\G\= ' || line =~ '^\\$'
+ \ || line =~ '^\s*: \S'
+ setf forth
+ else
+ setf fsharp
+ endif
+ endif
+endfunc
+
" Distinguish between HTML, XHTML and Django
func dist#ft#FThtml()
let n = 1
@@ -272,6 +289,8 @@ func dist#ft#FTm()
" excluding end(for|function|if|switch|while) common to Murphi
let octave_block_terminators = '\<end\%(_try_catch\|classdef\|enumeration\|events\|methods\|parfor\|properties\)\>'
+ let objc_preprocessor = '^\s*#\s*\%(import\|include\|define\|if\|ifn\=def\|undef\|line\|error\|pragma\)\>'
+
let n = 1
let saw_comment = 0 " Whether we've seen a multiline comment leader.
while n < 100
@@ -282,7 +301,7 @@ func dist#ft#FTm()
" anything more definitive.
let saw_comment = 1
endif
- if line =~ '^\s*\(#\s*\(include\|import\)\>\|@import\>\|//\)'
+ if line =~ '^\s*//' || line =~ '^\s*@import\>' || line =~ objc_preprocessor
setf objc
return
endif
diff --git a/runtime/doc/api.txt b/runtime/doc/api.txt
index bb8e83f84a..482d8c198d 100644
--- a/runtime/doc/api.txt
+++ b/runtime/doc/api.txt
@@ -652,35 +652,6 @@ nvim_call_atomic({calls}) *nvim_call_atomic()*
occurred, the values from all preceding calls will still
be returned.
- *nvim_call_dict_function()*
-nvim_call_dict_function({dict}, {fn}, {args})
- Calls a VimL |Dictionary-function| with the given arguments.
-
- On execution error: fails with VimL error, does not update
- v:errmsg.
-
- Parameters: ~
- {dict} Dictionary, or String evaluating to a VimL |self|
- dict
- {fn} Name of the function defined on the VimL dict
- {args} Function arguments packed in an Array
-
- Return: ~
- Result of the function call
-
-nvim_call_function({fn}, {args}) *nvim_call_function()*
- Calls a VimL function with the given arguments.
-
- On execution error: fails with VimL error, does not update
- v:errmsg.
-
- Parameters: ~
- {fn} Function to call
- {args} Function arguments packed in an Array
-
- Return: ~
- Result of the function call
-
nvim_chan_send({chan}, {data}) *nvim_chan_send()*
Send data to channel `id` . For a job, it writes it to the
stdin of the process. For the stdio channel |channel-stdio|,
@@ -697,18 +668,6 @@ nvim_chan_send({chan}, {data}) *nvim_chan_send()*
{chan} id of the channel
{data} data to write. 8-bit clean: can contain NUL bytes.
-nvim_command({command}) *nvim_command()*
- Executes an ex-command.
-
- On execution error: fails with VimL error, does not update
- v:errmsg.
-
- Parameters: ~
- {command} Ex-command string
-
- See also: ~
- |nvim_exec()|
-
nvim_create_buf({listed}, {scratch}) *nvim_create_buf()*
Creates a new, empty, unnamed buffer.
@@ -724,22 +683,6 @@ nvim_create_buf({listed}, {scratch}) *nvim_create_buf()*
See also: ~
buf_open_scratch
-nvim_create_namespace({name}) *nvim_create_namespace()*
- Creates a new *namespace* or gets an existing one.
-
- Namespaces are used for buffer highlights and virtual text,
- see |nvim_buf_add_highlight()| and |nvim_buf_set_extmark()|.
-
- Namespaces can be named or anonymous. If `name` matches an
- existing namespace, the associated id is returned. If `name`
- is an empty string a new, anonymous namespace is created.
-
- Parameters: ~
- {name} Namespace name or empty string
-
- Return: ~
- Namespace id
-
nvim_del_current_line() *nvim_del_current_line()*
Deletes the current line.
@@ -806,19 +749,6 @@ nvim_err_writeln({str}) *nvim_err_writeln()*
See also: ~
nvim_err_write()
-nvim_eval({expr}) *nvim_eval()*
- Evaluates a VimL |expression|. Dictionaries and Lists are
- recursively expanded.
-
- On execution error: fails with VimL error, does not update
- v:errmsg.
-
- Parameters: ~
- {expr} VimL expression string
-
- Return: ~
- Evaluation result or expanded object
-
nvim_eval_statusline({str}, {*opts}) *nvim_eval_statusline()*
Evaluates statusline string.
@@ -852,29 +782,6 @@ nvim_eval_statusline({str}, {*opts}) *nvim_eval_statusline()*
character that uses the highlight.
• group: (string) Name of highlight group.
-nvim_exec({src}, {output}) *nvim_exec()*
- Executes Vimscript (multiline block of Ex-commands), like
- anonymous |:source|.
-
- Unlike |nvim_command()| this function supports heredocs,
- script-scope (s:), etc.
-
- On execution error: fails with VimL error, does not update
- v:errmsg.
-
- Parameters: ~
- {src} Vimscript code
- {output} Capture and return all (non-error, non-shell
- |:!|) output
-
- Return: ~
- Output (non-error, non-shell |:!|) if `output` is true,
- else empty string.
-
- See also: ~
- |execute()|
- |nvim_command()|
-
nvim_exec_lua({code}, {args}) *nvim_exec_lua()*
Execute Lua code. Parameters (if any) are available as `...`
inside the chunk. The chunk can return a value.
@@ -1110,12 +1017,6 @@ nvim_get_mode() *nvim_get_mode()*
Attributes: ~
{fast}
-nvim_get_namespaces() *nvim_get_namespaces()*
- Gets existing, non-anonymous namespaces.
-
- Return: ~
- dict that maps from names to namespace ids.
-
nvim_get_option({name}) *nvim_get_option()*
Gets an option value string.
@@ -1344,7 +1245,15 @@ nvim_open_term({buffer}, {opts}) *nvim_open_term()*
Parameters: ~
{buffer} the buffer to use (expected to be empty)
- {opts} Optional parameters. Reserved for future use.
+ {opts} Optional parameters.
+ • on_input: lua callback for input sent, i e
+ keypresses in terminal mode. Note: keypresses
+ are sent raw as they would be to the pty
+ master end. For instance, a carriage return is
+ sent as a "\r", not as a "\n". |textlock|
+ applies. It is possible to call
+ |nvim_chan_send| directly in the callback
+ however. ["input", term, bufnr, data]
Return: ~
Channel id, or 0 on error
@@ -1357,104 +1266,6 @@ nvim_out_write({str}) *nvim_out_write()*
Parameters: ~
{str} Message
- *nvim_parse_expression()*
-nvim_parse_expression({expr}, {flags}, {highlight})
- Parse a VimL expression.
-
- Attributes: ~
- {fast}
-
- Parameters: ~
- {expr} Expression to parse. Always treated as a
- single line.
- {flags} Flags:
- • "m" if multiple expressions in a row are
- allowed (only the first one will be
- parsed),
- • "E" if EOC tokens are not allowed
- (determines whether they will stop parsing
- process or be recognized as an
- operator/space, though also yielding an
- error).
- • "l" when needing to start parsing with
- lvalues for ":let" or ":for". Common flag
- sets:
- • "m" to parse like for ":echo".
- • "E" to parse like for "<C-r>=".
- • empty string for ":call".
- • "lm" to parse for ":let".
- {highlight} If true, return value will also include
- "highlight" key containing array of 4-tuples
- (arrays) (Integer, Integer, Integer, String),
- where first three numbers define the
- highlighted region and represent line,
- starting column and ending column (latter
- exclusive: one should highlight region
- [start_col, end_col)).
-
- Return: ~
-
- • AST: top-level dictionary with these keys:
- • "error": Dictionary with error, present only if parser
- saw some error. Contains the following keys:
- • "message": String, error message in printf format,
- translated. Must contain exactly one "%.*s".
- • "arg": String, error message argument.
-
- • "len": Amount of bytes successfully parsed. With flags
- equal to "" that should be equal to the length of expr
- string. (“Successfully parsed” here means
- “participated in AST creation”, not “till the first
- error”.)
- • "ast": AST, either nil or a dictionary with these
- keys:
- • "type": node type, one of the value names from
- ExprASTNodeType stringified without "kExprNode"
- prefix.
- • "start": a pair [line, column] describing where node
- is "started" where "line" is always 0 (will not be 0
- if you will be using nvim_parse_viml() on e.g.
- ":let", but that is not present yet). Both elements
- are Integers.
- • "len": “length” of the node. This and "start" are
- there for debugging purposes primary (debugging
- parser and providing debug information).
- • "children": a list of nodes described in top/"ast".
- There always is zero, one or two children, key will
- not be present if node has no children. Maximum
- number of children may be found in node_maxchildren
- array.
-
- • Local values (present only for certain nodes):
- • "scope": a single Integer, specifies scope for
- "Option" and "PlainIdentifier" nodes. For "Option" it
- is one of ExprOptScope values, for "PlainIdentifier"
- it is one of ExprVarScope values.
- • "ident": identifier (without scope, if any), present
- for "Option", "PlainIdentifier", "PlainKey" and
- "Environment" nodes.
- • "name": Integer, register name (one character) or -1.
- Only present for "Register" nodes.
- • "cmp_type": String, comparison type, one of the value
- names from ExprComparisonType, stringified without
- "kExprCmp" prefix. Only present for "Comparison"
- nodes.
- • "ccs_strategy": String, case comparison strategy, one
- of the value names from ExprCaseCompareStrategy,
- stringified without "kCCStrategy" prefix. Only present
- for "Comparison" nodes.
- • "augmentation": String, augmentation type for
- "Assignment" nodes. Is either an empty string, "Add",
- "Subtract" or "Concat" for "=", "+=", "-=" or ".="
- respectively.
- • "invert": Boolean, true if result of comparison needs
- to be inverted. Only present for "Comparison" nodes.
- • "ivalue": Integer, integer value for "Integer" nodes.
- • "fvalue": Float, floating-point value for "Float"
- nodes.
- • "svalue": String, value for "SingleQuotedString" and
- "DoubleQuotedString" nodes.
-
nvim_paste({data}, {crlf}, {phase}) *nvim_paste()*
Pastes at cursor, in any mode.
@@ -1650,53 +1461,6 @@ nvim_set_current_win({window}) *nvim_set_current_win()*
Parameters: ~
{window} Window handle
- *nvim_set_decoration_provider()*
-nvim_set_decoration_provider({ns_id}, {opts})
- Set or change decoration provider for a namespace
-
- This is a very general purpose interface for having lua
- callbacks being triggered during the redraw code.
-
- The expected usage is to set extmarks for the currently
- redrawn buffer. |nvim_buf_set_extmark| can be called to add
- marks on a per-window or per-lines basis. Use the `ephemeral`
- key to only use the mark for the current screen redraw (the
- callback will be called again for the next redraw ).
-
- Note: this function should not be called often. Rather, the
- callbacks themselves can be used to throttle unneeded
- callbacks. the `on_start` callback can return `false` to
- disable the provider until the next redraw. Similarly, return
- `false` in `on_win` will skip the `on_lines` calls for that
- window (but any extmarks set in `on_win` will still be used).
- A plugin managing multiple sources of decoration should
- ideally only set one provider, and merge the sources
- internally. You can use multiple `ns_id` for the extmarks
- set/modified inside the callback anyway.
-
- Note: doing anything other than setting extmarks is considered
- experimental. Doing things like changing options are not
- expliticly forbidden, but is likely to have unexpected
- consequences (such as 100% CPU consumption). doing
- `vim.rpcnotify` should be OK, but `vim.rpcrequest` is quite
- dubious for the moment.
-
- Parameters: ~
- {ns_id} Namespace id from |nvim_create_namespace()|
- {opts} Callbacks invoked during redraw:
- • on_start: called first on each screen redraw
- ["start", tick]
- • on_buf: called for each buffer being redrawn
- (before window callbacks) ["buf", bufnr, tick]
- • on_win: called when starting to redraw a
- specific window. ["win", winid, bufnr, topline,
- botline_guess]
- • on_line: called for each buffer line being
- redrawn. (The interation with fold lines is
- subject to change) ["win", winid, bufnr, row]
- • on_end: called at the end of a redraw cycle
- ["end", tick]
-
nvim_set_hl({ns_id}, {name}, {val}) *nvim_set_hl()*
Set a highlight group.
@@ -1790,6 +1554,185 @@ nvim_unsubscribe({event}) *nvim_unsubscribe()*
==============================================================================
+Vimscript Functions *api-vimscript*
+
+ *nvim_call_dict_function()*
+nvim_call_dict_function({dict}, {fn}, {args})
+ Calls a VimL |Dictionary-function| with the given arguments.
+
+ On execution error: fails with VimL error, does not update
+ v:errmsg.
+
+ Parameters: ~
+ {dict} Dictionary, or String evaluating to a VimL |self|
+ dict
+ {fn} Name of the function defined on the VimL dict
+ {args} Function arguments packed in an Array
+
+ Return: ~
+ Result of the function call
+
+nvim_call_function({fn}, {args}) *nvim_call_function()*
+ Calls a VimL function with the given arguments.
+
+ On execution error: fails with VimL error, does not update
+ v:errmsg.
+
+ Parameters: ~
+ {fn} Function to call
+ {args} Function arguments packed in an Array
+
+ Return: ~
+ Result of the function call
+
+nvim_command({command}) *nvim_command()*
+ Executes an ex-command.
+
+ On execution error: fails with VimL error, does not update
+ v:errmsg.
+
+ Parameters: ~
+ {command} Ex-command string
+
+ See also: ~
+ |nvim_exec()|
+
+nvim_eval({expr}) *nvim_eval()*
+ Evaluates a VimL |expression|. Dictionaries and Lists are
+ recursively expanded.
+
+ On execution error: fails with VimL error, does not update
+ v:errmsg.
+
+ Parameters: ~
+ {expr} VimL expression string
+
+ Return: ~
+ Evaluation result or expanded object
+
+nvim_exec({src}, {output}) *nvim_exec()*
+ Executes Vimscript (multiline block of Ex-commands), like
+ anonymous |:source|.
+
+ Unlike |nvim_command()| this function supports heredocs,
+ script-scope (s:), etc.
+
+ On execution error: fails with VimL error, does not update
+ v:errmsg.
+
+ Parameters: ~
+ {src} Vimscript code
+ {output} Capture and return all (non-error, non-shell
+ |:!|) output
+
+ Return: ~
+ Output (non-error, non-shell |:!|) if `output` is true,
+ else empty string.
+
+ See also: ~
+ |execute()|
+ |nvim_command()|
+
+ *nvim_parse_expression()*
+nvim_parse_expression({expr}, {flags}, {highlight})
+ Parse a VimL expression.
+
+ Attributes: ~
+ {fast}
+
+ Parameters: ~
+ {expr} Expression to parse. Always treated as a
+ single line.
+ {flags} Flags:
+ • "m" if multiple expressions in a row are
+ allowed (only the first one will be
+ parsed),
+ • "E" if EOC tokens are not allowed
+ (determines whether they will stop parsing
+ process or be recognized as an
+ operator/space, though also yielding an
+ error).
+ • "l" when needing to start parsing with
+ lvalues for ":let" or ":for". Common flag
+ sets:
+ • "m" to parse like for ":echo".
+ • "E" to parse like for "<C-r>=".
+ • empty string for ":call".
+ • "lm" to parse for ":let".
+ {highlight} If true, return value will also include
+ "highlight" key containing array of 4-tuples
+ (arrays) (Integer, Integer, Integer, String),
+ where first three numbers define the
+ highlighted region and represent line,
+ starting column and ending column (latter
+ exclusive: one should highlight region
+ [start_col, end_col)).
+
+ Return: ~
+
+ • AST: top-level dictionary with these keys:
+ • "error": Dictionary with error, present only if parser
+ saw some error. Contains the following keys:
+ • "message": String, error message in printf format,
+ translated. Must contain exactly one "%.*s".
+ • "arg": String, error message argument.
+
+ • "len": Amount of bytes successfully parsed. With flags
+ equal to "" that should be equal to the length of expr
+ string. (“Successfully parsed” here means
+ “participated in AST creation”, not “till the first
+ error”.)
+ • "ast": AST, either nil or a dictionary with these
+ keys:
+ • "type": node type, one of the value names from
+ ExprASTNodeType stringified without "kExprNode"
+ prefix.
+ • "start": a pair [line, column] describing where node
+ is "started" where "line" is always 0 (will not be 0
+ if you will be using nvim_parse_viml() on e.g.
+ ":let", but that is not present yet). Both elements
+ are Integers.
+ • "len": “length” of the node. This and "start" are
+ there for debugging purposes primary (debugging
+ parser and providing debug information).
+ • "children": a list of nodes described in top/"ast".
+ There always is zero, one or two children, key will
+ not be present if node has no children. Maximum
+ number of children may be found in node_maxchildren
+ array.
+
+ • Local values (present only for certain nodes):
+ • "scope": a single Integer, specifies scope for
+ "Option" and "PlainIdentifier" nodes. For "Option" it
+ is one of ExprOptScope values, for "PlainIdentifier"
+ it is one of ExprVarScope values.
+ • "ident": identifier (without scope, if any), present
+ for "Option", "PlainIdentifier", "PlainKey" and
+ "Environment" nodes.
+ • "name": Integer, register name (one character) or -1.
+ Only present for "Register" nodes.
+ • "cmp_type": String, comparison type, one of the value
+ names from ExprComparisonType, stringified without
+ "kExprCmp" prefix. Only present for "Comparison"
+ nodes.
+ • "ccs_strategy": String, case comparison strategy, one
+ of the value names from ExprCaseCompareStrategy,
+ stringified without "kCCStrategy" prefix. Only present
+ for "Comparison" nodes.
+ • "augmentation": String, augmentation type for
+ "Assignment" nodes. Is either an empty string, "Add",
+ "Subtract" or "Concat" for "=", "+=", "-=" or ".="
+ respectively.
+ • "invert": Boolean, true if result of comparison needs
+ to be inverted. Only present for "Comparison" nodes.
+ • "ivalue": Integer, integer value for "Integer" nodes.
+ • "fvalue": Float, floating-point value for "Float"
+ nodes.
+ • "svalue": String, value for "SingleQuotedString" and
+ "DoubleQuotedString" nodes.
+
+
+==============================================================================
Buffer Functions *api-buffer*
@@ -1815,48 +1758,6 @@ nvim__buf_redraw_range({buffer}, {first}, {last})
nvim__buf_stats({buffer}) *nvim__buf_stats()*
TODO: Documentation
- *nvim_buf_add_highlight()*
-nvim_buf_add_highlight({buffer}, {ns_id}, {hl_group}, {line}, {col_start},
- {col_end})
- Adds a highlight to buffer.
-
- Useful for plugins that dynamically generate highlights to a
- buffer (like a semantic highlighter or linter). The function
- adds a single highlight to a buffer. Unlike |matchaddpos()|
- highlights follow changes to line numbering (as lines are
- inserted/removed above the highlighted line), like signs and
- marks do.
-
- Namespaces are used for batch deletion/updating of a set of
- highlights. To create a namespace, use
- |nvim_create_namespace()| which returns a namespace id. Pass
- it in to this function as `ns_id` to add highlights to the
- namespace. All highlights in the same namespace can then be
- cleared with single call to |nvim_buf_clear_namespace()|. If
- the highlight never will be deleted by an API call, pass
- `ns_id = -1` .
-
- As a shorthand, `ns_id = 0` can be used to create a new
- namespace for the highlight, the allocated id is then
- returned. If `hl_group` is the empty string no highlight is
- added, but a new `ns_id` is still returned. This is supported
- for backwards compatibility, new code should use
- |nvim_create_namespace()| to create a new empty namespace.
-
- Parameters: ~
- {buffer} Buffer handle, or 0 for current buffer
- {ns_id} namespace to use or -1 for ungrouped
- highlight
- {hl_group} Name of the highlight group to use
- {line} Line to highlight (zero-indexed)
- {col_start} Start of (byte-indexed) column range to
- highlight
- {col_end} End of (byte-indexed) column range to
- highlight, or -1 to highlight to end of line
-
- Return: ~
- The ns_id that was used
-
nvim_buf_attach({buffer}, {send_buffer}, {opts}) *nvim_buf_attach()*
Activates buffer-update events on a channel, or as Lua
callbacks.
@@ -1950,7 +1851,7 @@ nvim_buf_call({buffer}, {fun}) *nvim_buf_call()*
switched If a window inside the current tabpage (including a
float) already shows the buffer One of these windows will be
set as current window temporarily. Otherwise a temporary
- scratch window (calleed the "autocmd window" for historical
+ scratch window (called the "autocmd window" for historical
reasons) will be used.
This is useful e.g. to call vimL functions that only work with
@@ -1965,33 +1866,6 @@ nvim_buf_call({buffer}, {fun}) *nvim_buf_call()*
Return value of function. NB: will deepcopy lua values
currently, use upvalues to send lua references in and out.
- *nvim_buf_clear_namespace()*
-nvim_buf_clear_namespace({buffer}, {ns_id}, {line_start}, {line_end})
- Clears namespaced objects (highlights, extmarks, virtual text)
- from a region.
-
- Lines are 0-indexed. |api-indexing| To clear the namespace in
- the entire buffer, specify line_start=0 and line_end=-1.
-
- Parameters: ~
- {buffer} Buffer handle, or 0 for current buffer
- {ns_id} Namespace to clear, or -1 to clear all
- namespaces.
- {line_start} Start of range of lines to clear
- {line_end} End of range of lines to clear (exclusive)
- or -1 to clear to end of buffer.
-
-nvim_buf_del_extmark({buffer}, {ns_id}, {id}) *nvim_buf_del_extmark()*
- Removes an extmark.
-
- Parameters: ~
- {buffer} Buffer handle, or 0 for current buffer
- {ns_id} Namespace id from |nvim_create_namespace()|
- {id} Extmark id
-
- Return: ~
- true if the extmark was found, else false
-
nvim_buf_del_keymap({buffer}, {mode}, {lhs}) *nvim_buf_del_keymap()*
Unmaps a buffer-local |mapping| for the given mode.
@@ -2073,73 +1947,6 @@ nvim_buf_get_commands({buffer}, {*opts}) *nvim_buf_get_commands()*
Return: ~
Map of maps describing commands.
- *nvim_buf_get_extmark_by_id()*
-nvim_buf_get_extmark_by_id({buffer}, {ns_id}, {id}, {opts})
- Gets the position (0-indexed) of an extmark.
-
- Parameters: ~
- {buffer} Buffer handle, or 0 for current buffer
- {ns_id} Namespace id from |nvim_create_namespace()|
- {id} Extmark id
- {opts} Optional parameters. Keys:
- • details: Whether to include the details dict
-
- Return: ~
- 0-indexed (row, col) tuple or empty list () if extmark id
- was absent
-
- *nvim_buf_get_extmarks()*
-nvim_buf_get_extmarks({buffer}, {ns_id}, {start}, {end}, {opts})
- Gets extmarks in "traversal order" from a |charwise| region
- defined by buffer positions (inclusive, 0-indexed
- |api-indexing|).
-
- Region can be given as (row,col) tuples, or valid extmark ids
- (whose positions define the bounds). 0 and -1 are understood
- as (0,0) and (-1,-1) respectively, thus the following are
- equivalent:
->
- nvim_buf_get_extmarks(0, my_ns, 0, -1, {})
- nvim_buf_get_extmarks(0, my_ns, [0,0], [-1,-1], {})
-<
-
- If `end` is less than `start` , traversal works backwards.
- (Useful with `limit` , to get the first marks prior to a given
- position.)
-
- Example:
->
- local a = vim.api
- local pos = a.nvim_win_get_cursor(0)
- local ns = a.nvim_create_namespace('my-plugin')
- -- Create new extmark at line 1, column 1.
- local m1 = a.nvim_buf_set_extmark(0, ns, 0, 0, 0, {})
- -- Create new extmark at line 3, column 1.
- local m2 = a.nvim_buf_set_extmark(0, ns, 0, 2, 0, {})
- -- Get extmarks only from line 3.
- local ms = a.nvim_buf_get_extmarks(0, ns, {2,0}, {2,0}, {})
- -- Get all marks in this buffer + namespace.
- local all = a.nvim_buf_get_extmarks(0, ns, 0, -1, {})
- print(vim.inspect(ms))
-<
-
- Parameters: ~
- {buffer} Buffer handle, or 0 for current buffer
- {ns_id} Namespace id from |nvim_create_namespace()|
- {start} Start of range: a 0-indexed (row, col) or valid
- extmark id (whose position defines the bound).
- |api-indexing|
- {end} End of range (inclusive): a 0-indexed (row, col)
- or valid extmark id (whose position defines the
- bound). |api-indexing|
- {opts} Optional parameters. Keys:
- • limit: Maximum number of marks to return
- • details Whether to include the details dict
-
- Return: ~
- List of [extmark_id, row, col] tuples in "traversal
- order".
-
nvim_buf_get_keymap({buffer}, {mode}) *nvim_buf_get_keymap()*
Gets a list of buffer-local |mapping| definitions.
@@ -2270,6 +2077,257 @@ nvim_buf_line_count({buffer}) *nvim_buf_line_count()*
Return: ~
Line count, or 0 for unloaded buffer. |api-buffer|
+ *nvim_buf_set_keymap()*
+nvim_buf_set_keymap({buffer}, {mode}, {lhs}, {rhs}, {*opts})
+ Sets a buffer-local |mapping| for the given mode.
+
+ Parameters: ~
+ {buffer} Buffer handle, or 0 for current buffer
+
+ See also: ~
+ |nvim_set_keymap()|
+
+ *nvim_buf_set_lines()*
+nvim_buf_set_lines({buffer}, {start}, {end}, {strict_indexing}, {replacement})
+ Sets (replaces) a line-range in the buffer.
+
+ Indexing is zero-based, end-exclusive. Negative indices are
+ interpreted as length+1+index: -1 refers to the index past the
+ end. So to change or delete the last element use start=-2 and
+ end=-1.
+
+ To insert lines at a given index, set `start` and `end` to the
+ same index. To delete a range of lines, set `replacement` to
+ an empty array.
+
+ Out-of-bounds indices are clamped to the nearest valid value,
+ unless `strict_indexing` is set.
+
+ Attributes: ~
+ not allowed when |textlock| is active
+
+ Parameters: ~
+ {buffer} Buffer handle, or 0 for current buffer
+ {start} First line index
+ {end} Last line index (exclusive)
+ {strict_indexing} Whether out-of-bounds should be an
+ error.
+ {replacement} Array of lines to use as replacement
+
+ *nvim_buf_set_mark()*
+nvim_buf_set_mark({buffer}, {name}, {line}, {col}, {opts})
+ Sets a named mark in the given buffer, all marks are allowed
+ file/uppercase, visual, last change, etc. See |mark-motions|.
+
+ Marks are (1,0)-indexed. |api-indexing|
+
+ Note:
+ Passing 0 as line deletes the mark
+
+ Parameters: ~
+ {buffer} Buffer to set the mark on
+ {name} Mark name
+ {line} Line number
+ {col} Column/row number
+ {opts} Optional parameters. Reserved for future use.
+
+ Return: ~
+ true if the mark was set, else false.
+
+ See also: ~
+ |nvim_buf_del_mark()|
+ |nvim_buf_get_mark()|
+
+nvim_buf_set_name({buffer}, {name}) *nvim_buf_set_name()*
+ Sets the full file name for a buffer
+
+ Parameters: ~
+ {buffer} Buffer handle, or 0 for current buffer
+ {name} Buffer name
+
+nvim_buf_set_option({buffer}, {name}, {value}) *nvim_buf_set_option()*
+ Sets a buffer option value. Passing 'nil' as value deletes the
+ option (only works if there's a global fallback)
+
+ Parameters: ~
+ {buffer} Buffer handle, or 0 for current buffer
+ {name} Option name
+ {value} Option value
+
+ *nvim_buf_set_text()*
+nvim_buf_set_text({buffer}, {start_row}, {start_col}, {end_row}, {end_col},
+ {replacement})
+ Sets (replaces) a range in the buffer
+
+ This is recommended over nvim_buf_set_lines when only
+ modifying parts of a line, as extmarks will be preserved on
+ non-modified parts of the touched lines.
+
+ Indexing is zero-based and end-exclusive.
+
+ To insert text at a given index, set `start` and `end` ranges
+ to the same index. To delete a range, set `replacement` to an
+ array containing an empty string, or simply an empty array.
+
+ Prefer nvim_buf_set_lines when adding or deleting entire lines
+ only.
+
+ Parameters: ~
+ {buffer} Buffer handle, or 0 for current buffer
+ {start_row} First line index
+ {start_column} First column
+ {end_row} Last line index
+ {end_column} Last column
+ {replacement} Array of lines to use as replacement
+
+nvim_buf_set_var({buffer}, {name}, {value}) *nvim_buf_set_var()*
+ Sets a buffer-scoped (b:) variable
+
+ Parameters: ~
+ {buffer} Buffer handle, or 0 for current buffer
+ {name} Variable name
+ {value} Variable value
+
+
+==============================================================================
+Extmark Functions *api-extmark*
+
+ *nvim_buf_add_highlight()*
+nvim_buf_add_highlight({buffer}, {ns_id}, {hl_group}, {line}, {col_start},
+ {col_end})
+ Adds a highlight to buffer.
+
+ Useful for plugins that dynamically generate highlights to a
+ buffer (like a semantic highlighter or linter). The function
+ adds a single highlight to a buffer. Unlike |matchaddpos()|
+ highlights follow changes to line numbering (as lines are
+ inserted/removed above the highlighted line), like signs and
+ marks do.
+
+ Namespaces are used for batch deletion/updating of a set of
+ highlights. To create a namespace, use
+ |nvim_create_namespace()| which returns a namespace id. Pass
+ it in to this function as `ns_id` to add highlights to the
+ namespace. All highlights in the same namespace can then be
+ cleared with single call to |nvim_buf_clear_namespace()|. If
+ the highlight never will be deleted by an API call, pass
+ `ns_id = -1` .
+
+ As a shorthand, `ns_id = 0` can be used to create a new
+ namespace for the highlight, the allocated id is then
+ returned. If `hl_group` is the empty string no highlight is
+ added, but a new `ns_id` is still returned. This is supported
+ for backwards compatibility, new code should use
+ |nvim_create_namespace()| to create a new empty namespace.
+
+ Parameters: ~
+ {buffer} Buffer handle, or 0 for current buffer
+ {ns_id} namespace to use or -1 for ungrouped
+ highlight
+ {hl_group} Name of the highlight group to use
+ {line} Line to highlight (zero-indexed)
+ {col_start} Start of (byte-indexed) column range to
+ highlight
+ {col_end} End of (byte-indexed) column range to
+ highlight, or -1 to highlight to end of line
+
+ Return: ~
+ The ns_id that was used
+
+ *nvim_buf_clear_namespace()*
+nvim_buf_clear_namespace({buffer}, {ns_id}, {line_start}, {line_end})
+ Clears namespaced objects (highlights, extmarks, virtual text)
+ from a region.
+
+ Lines are 0-indexed. |api-indexing| To clear the namespace in
+ the entire buffer, specify line_start=0 and line_end=-1.
+
+ Parameters: ~
+ {buffer} Buffer handle, or 0 for current buffer
+ {ns_id} Namespace to clear, or -1 to clear all
+ namespaces.
+ {line_start} Start of range of lines to clear
+ {line_end} End of range of lines to clear (exclusive)
+ or -1 to clear to end of buffer.
+
+nvim_buf_del_extmark({buffer}, {ns_id}, {id}) *nvim_buf_del_extmark()*
+ Removes an extmark.
+
+ Parameters: ~
+ {buffer} Buffer handle, or 0 for current buffer
+ {ns_id} Namespace id from |nvim_create_namespace()|
+ {id} Extmark id
+
+ Return: ~
+ true if the extmark was found, else false
+
+ *nvim_buf_get_extmark_by_id()*
+nvim_buf_get_extmark_by_id({buffer}, {ns_id}, {id}, {opts})
+ Gets the position (0-indexed) of an extmark.
+
+ Parameters: ~
+ {buffer} Buffer handle, or 0 for current buffer
+ {ns_id} Namespace id from |nvim_create_namespace()|
+ {id} Extmark id
+ {opts} Optional parameters. Keys:
+ • details: Whether to include the details dict
+
+ Return: ~
+ 0-indexed (row, col) tuple or empty list () if extmark id
+ was absent
+
+ *nvim_buf_get_extmarks()*
+nvim_buf_get_extmarks({buffer}, {ns_id}, {start}, {end}, {opts})
+ Gets extmarks in "traversal order" from a |charwise| region
+ defined by buffer positions (inclusive, 0-indexed
+ |api-indexing|).
+
+ Region can be given as (row,col) tuples, or valid extmark ids
+ (whose positions define the bounds). 0 and -1 are understood
+ as (0,0) and (-1,-1) respectively, thus the following are
+ equivalent:
+>
+ nvim_buf_get_extmarks(0, my_ns, 0, -1, {})
+ nvim_buf_get_extmarks(0, my_ns, [0,0], [-1,-1], {})
+<
+
+ If `end` is less than `start` , traversal works backwards.
+ (Useful with `limit` , to get the first marks prior to a given
+ position.)
+
+ Example:
+>
+ local a = vim.api
+ local pos = a.nvim_win_get_cursor(0)
+ local ns = a.nvim_create_namespace('my-plugin')
+ -- Create new extmark at line 1, column 1.
+ local m1 = a.nvim_buf_set_extmark(0, ns, 0, 0, 0, {})
+ -- Create new extmark at line 3, column 1.
+ local m2 = a.nvim_buf_set_extmark(0, ns, 0, 2, 0, {})
+ -- Get extmarks only from line 3.
+ local ms = a.nvim_buf_get_extmarks(0, ns, {2,0}, {2,0}, {})
+ -- Get all marks in this buffer + namespace.
+ local all = a.nvim_buf_get_extmarks(0, ns, 0, -1, {})
+ print(vim.inspect(ms))
+<
+
+ Parameters: ~
+ {buffer} Buffer handle, or 0 for current buffer
+ {ns_id} Namespace id from |nvim_create_namespace()|
+ {start} Start of range: a 0-indexed (row, col) or valid
+ extmark id (whose position defines the bound).
+ |api-indexing|
+ {end} End of range (inclusive): a 0-indexed (row, col)
+ or valid extmark id (whose position defines the
+ bound). |api-indexing|
+ {opts} Optional parameters. Keys:
+ • limit: Maximum number of marks to return
+ • details Whether to include the details dict
+
+ Return: ~
+ List of [extmark_id, row, col] tuples in "traversal
+ order".
+
*nvim_buf_set_extmark()*
nvim_buf_set_extmark({buffer}, {ns_id}, {line}, {col}, {*opts})
Creates or updates an extmark.
@@ -2351,12 +2409,7 @@ nvim_buf_set_extmark({buffer}, {ns_id}, {line}, {col}, {*opts})
of the array. However the 'tabstop' buffer
option is still used for hard tabs. By default
lines are placed below the buffer line
- containing the mark. • Note: currently virtual lines are limited to
- one block per buffer. Thus setting a new mark
- disables any previous `virt_lines` decoration.
- However plugins should not rely on this
- behaviour, as this limitation is planned to be
- removed.
+ containing the mark.
• virt_lines_above: place virtual lines above
instead.
• virt_lines_leftcol: Place extmarks in the
@@ -2383,116 +2436,74 @@ nvim_buf_set_extmark({buffer}, {ns_id}, {line}, {col}, {*opts})
Return: ~
Id of the created/updated extmark
- *nvim_buf_set_keymap()*
-nvim_buf_set_keymap({buffer}, {mode}, {lhs}, {rhs}, {*opts})
- Sets a buffer-local |mapping| for the given mode.
-
- Parameters: ~
- {buffer} Buffer handle, or 0 for current buffer
-
- See also: ~
- |nvim_set_keymap()|
-
- *nvim_buf_set_lines()*
-nvim_buf_set_lines({buffer}, {start}, {end}, {strict_indexing}, {replacement})
- Sets (replaces) a line-range in the buffer.
-
- Indexing is zero-based, end-exclusive. Negative indices are
- interpreted as length+1+index: -1 refers to the index past the
- end. So to change or delete the last element use start=-2 and
- end=-1.
-
- To insert lines at a given index, set `start` and `end` to the
- same index. To delete a range of lines, set `replacement` to
- an empty array.
-
- Out-of-bounds indices are clamped to the nearest valid value,
- unless `strict_indexing` is set.
-
- Attributes: ~
- not allowed when |textlock| is active
-
- Parameters: ~
- {buffer} Buffer handle, or 0 for current buffer
- {start} First line index
- {end} Last line index (exclusive)
- {strict_indexing} Whether out-of-bounds should be an
- error.
- {replacement} Array of lines to use as replacement
-
- *nvim_buf_set_mark()*
-nvim_buf_set_mark({buffer}, {name}, {line}, {col}, {opts})
- Sets a named mark in the given buffer, all marks are allowed
- file/uppercase, visual, last change, etc. See |mark-motions|.
+nvim_create_namespace({name}) *nvim_create_namespace()*
+ Creates a new *namespace* or gets an existing one.
- Marks are (1,0)-indexed. |api-indexing|
+ Namespaces are used for buffer highlights and virtual text,
+ see |nvim_buf_add_highlight()| and |nvim_buf_set_extmark()|.
- Note:
- Passing 0 as line deletes the mark
+ Namespaces can be named or anonymous. If `name` matches an
+ existing namespace, the associated id is returned. If `name`
+ is an empty string a new, anonymous namespace is created.
Parameters: ~
- {buffer} Buffer to set the mark on
- {name} Mark name
- {line} Line number
- {col} Column/row number
- {opts} Optional parameters. Reserved for future use.
+ {name} Namespace name or empty string
Return: ~
- true if the mark was set, else false.
-
- See also: ~
- |nvim_buf_del_mark()|
- |nvim_buf_get_mark()|
-
-nvim_buf_set_name({buffer}, {name}) *nvim_buf_set_name()*
- Sets the full file name for a buffer
-
- Parameters: ~
- {buffer} Buffer handle, or 0 for current buffer
- {name} Buffer name
-
-nvim_buf_set_option({buffer}, {name}, {value}) *nvim_buf_set_option()*
- Sets a buffer option value. Passing 'nil' as value deletes the
- option (only works if there's a global fallback)
-
- Parameters: ~
- {buffer} Buffer handle, or 0 for current buffer
- {name} Option name
- {value} Option value
+ Namespace id
- *nvim_buf_set_text()*
-nvim_buf_set_text({buffer}, {start_row}, {start_col}, {end_row}, {end_col},
- {replacement})
- Sets (replaces) a range in the buffer
+nvim_get_namespaces() *nvim_get_namespaces()*
+ Gets existing, non-anonymous namespaces.
- This is recommended over nvim_buf_set_lines when only
- modifying parts of a line, as extmarks will be preserved on
- non-modified parts of the touched lines.
+ Return: ~
+ dict that maps from names to namespace ids.
- Indexing is zero-based and end-exclusive.
+ *nvim_set_decoration_provider()*
+nvim_set_decoration_provider({ns_id}, {opts})
+ Set or change decoration provider for a namespace
- To insert text at a given index, set `start` and `end` ranges
- to the same index. To delete a range, set `replacement` to an
- array containing an empty string, or simply an empty array.
+ This is a very general purpose interface for having lua
+ callbacks being triggered during the redraw code.
- Prefer nvim_buf_set_lines when adding or deleting entire lines
- only.
+ The expected usage is to set extmarks for the currently
+ redrawn buffer. |nvim_buf_set_extmark| can be called to add
+ marks on a per-window or per-lines basis. Use the `ephemeral`
+ key to only use the mark for the current screen redraw (the
+ callback will be called again for the next redraw ).
- Parameters: ~
- {buffer} Buffer handle, or 0 for current buffer
- {start_row} First line index
- {start_column} Last column
- {end_row} Last line index
- {end_column} Last column
- {replacement} Array of lines to use as replacement
+ Note: this function should not be called often. Rather, the
+ callbacks themselves can be used to throttle unneeded
+ callbacks. the `on_start` callback can return `false` to
+ disable the provider until the next redraw. Similarly, return
+ `false` in `on_win` will skip the `on_lines` calls for that
+ window (but any extmarks set in `on_win` will still be used).
+ A plugin managing multiple sources of decoration should
+ ideally only set one provider, and merge the sources
+ internally. You can use multiple `ns_id` for the extmarks
+ set/modified inside the callback anyway.
-nvim_buf_set_var({buffer}, {name}, {value}) *nvim_buf_set_var()*
- Sets a buffer-scoped (b:) variable
+ Note: doing anything other than setting extmarks is considered
+ experimental. Doing things like changing options are not
+ expliticly forbidden, but is likely to have unexpected
+ consequences (such as 100% CPU consumption). doing
+ `vim.rpcnotify` should be OK, but `vim.rpcrequest` is quite
+ dubious for the moment.
Parameters: ~
- {buffer} Buffer handle, or 0 for current buffer
- {name} Variable name
- {value} Variable value
+ {ns_id} Namespace id from |nvim_create_namespace()|
+ {opts} Callbacks invoked during redraw:
+ • on_start: called first on each screen redraw
+ ["start", tick]
+ • on_buf: called for each buffer being redrawn
+ (before window callbacks) ["buf", bufnr, tick]
+ • on_win: called when starting to redraw a
+ specific window. ["win", winid, bufnr, topline,
+ botline_guess]
+ • on_line: called for each buffer line being
+ redrawn. (The interaction with fold lines is
+ subject to change) ["win", winid, bufnr, row]
+ • on_end: called at the end of a redraw cycle
+ ["end", tick]
==============================================================================
diff --git a/runtime/doc/autocmd.txt b/runtime/doc/autocmd.txt
index d196167319..879a34bcaa 100644
--- a/runtime/doc/autocmd.txt
+++ b/runtime/doc/autocmd.txt
@@ -57,7 +57,7 @@ The special pattern <buffer> or <buffer=N> defines a buffer-local autocommand.
See |autocmd-buflocal|.
Note: The ":autocmd" command can only be followed by another command when the
-'|' appears before {cmd}. This works: >
+'|' appears where the pattern is expected. This works: >
:augroup mine | au! BufRead | augroup END
But this sees "augroup" as part of the defined command: >
:augroup mine | au! BufRead * | augroup END
@@ -813,7 +813,7 @@ QuitPre When using `:quit`, `:wq` or `:qall`, before
before QuitPre is triggered. Can be used to
close any non-essential window if the current
window is the last ordinary window.
- See also |ExitPre|, ||WinClosed|.
+ See also |ExitPre|, |WinClosed|.
*RemoteReply*
RemoteReply When a reply from a Vim that functions as
server was received |server2client()|. The
diff --git a/runtime/doc/diagnostic.txt b/runtime/doc/diagnostic.txt
index 1dd9c4f301..9a65737dae 100644
--- a/runtime/doc/diagnostic.txt
+++ b/runtime/doc/diagnostic.txt
@@ -239,7 +239,7 @@ DiagnosticUnderlineHint
*hl-DiagnosticFloatingError*
DiagnosticFloatingError
Used to color "Error" diagnostic messages in diagnostics float.
- See |vim.diagnostic.show_line_diagnostics()|
+ See |vim.diagnostic.open_float()|
*hl-DiagnosticFloatingWarn*
DiagnosticFloatingWarn
@@ -289,11 +289,11 @@ option in the "signs" table of |vim.diagnostic.config()| or 10 if unset).
==============================================================================
EVENTS *diagnostic-events*
- *DiagnosticsChanged*
-DiagnosticsChanged After diagnostics have changed.
+ *DiagnosticChanged*
+DiagnosticChanged After diagnostics have changed.
Example: >
- autocmd User DiagnosticsChanged lua vim.diagnostic.setqflist({open = false })
+ autocmd DiagnosticChanged * lua vim.diagnostic.setqflist({open = false })
<
==============================================================================
==============================================================================
@@ -373,39 +373,8 @@ config({opts}, {namespace}) *vim.diagnostic.config()*
Otherwise, all signs use the same
priority.
- • float: Options for floating windows:
- • severity: See |diagnostic-severity|.
- • header: (string or table) String to use
- as the header for the floating window. If
- a table, it is interpreted as a [text,
- hl_group] tuple. Defaults to
- "Diagnostics:".
- • source: (string) Include the diagnostic
- source in the message. One of "always" or
- "if_many".
- • format: (function) A function that takes
- a diagnostic as input and returns a
- string. The return value is the text used
- to display the diagnostic.
- • prefix: (function, string, or table)
- Prefix each diagnostic in the floating
- window. If a function, it must have the
- signature (diagnostic, i, total) ->
- (string, string), where {i} is the index
- of the diagnostic being evaluated and
- {total} is the total number of
- diagnostics displayed in the window. The
- function should return a string which is
- prepended to each diagnostic in the
- window as well as an (optional) highlight
- group which will be used to highlight the
- prefix. If {prefix} is a table, it is
- interpreted as a [text, hl_group] tuple
- as in |nvim_echo()|; otherwise, if
- {prefix} is a string, it is prepended to
- each diagnostic in the window with no
- highlight.
-
+ • float: Options for floating windows. See
+ |vim.diagnostic.open_float()|.
• update_in_insert: (default false) Update
diagnostics in Insert mode (if false,
diagnostics are updated on InsertLeave)
@@ -470,7 +439,7 @@ get_namespace({namespace}) *vim.diagnostic.get_namespace()*
Get namespace metadata.
Parameters: ~
- {ns} number Diagnostic namespace
+ {namespace} number Diagnostic namespace
Return: ~
table Namespace metadata
@@ -539,6 +508,9 @@ goto_next({opts}) *vim.diagnostic.goto_next()*
"true", call |vim.diagnostic.open_float()| after
moving. If a table, pass the table as the {opts}
parameter to |vim.diagnostic.open_float()|.
+ Unless overridden, the float will show
+ diagnostics at the new cursor position (as if
+ "cursor" were passed to the "scope" option).
• win_id: (number, default 0) Window ID
goto_prev({opts}) *vim.diagnostic.goto_prev()*
@@ -613,7 +585,7 @@ open_float({bufnr}, {opts}) *vim.diagnostic.open_float()*
addition to the following:
• namespace: (number) Limit diagnostics to the
given namespace
- • scope: (string, default "buffer") Show
+ • scope: (string, default "line") Show
diagnostics from the whole buffer ("buffer"),
the current cursor line ("line"), or the
current cursor position ("cursor").
@@ -641,8 +613,21 @@ open_float({bufnr}, {opts}) *vim.diagnostic.open_float()*
diagnostic. Overrides the setting from
|vim.diagnostic.config()|.
• prefix: (function, string, or table) Prefix
- each diagnostic in the floating window.
- Overrides the setting from
+ each diagnostic in the floating window. If a
+ function, it must have the signature
+ (diagnostic, i, total) -> (string, string),
+ where {i} is the index of the diagnostic being
+ evaluated and {total} is the total number of
+ diagnostics displayed in the window. The
+ function should return a string which is
+ prepended to each diagnostic in the window as
+ well as an (optional) highlight group which
+ will be used to highlight the prefix. If
+ {prefix} is a table, it is interpreted as a
+ [text, hl_group] tuple as in |nvim_echo()|;
+ otherwise, if {prefix} is a string, it is
+ prepended to each diagnostic in the window with
+ no highlight. Overrides the setting from
|vim.diagnostic.config()|.
Return: ~
diff --git a/runtime/doc/eval.txt b/runtime/doc/eval.txt
index eb3dbd9b70..4d4e011c08 100644
--- a/runtime/doc/eval.txt
+++ b/runtime/doc/eval.txt
@@ -3081,7 +3081,7 @@ bufname([{buf}]) *bufname()*
bufname(3) name of buffer 3
bufname("%") name of current buffer
bufname("file2") name of buffer where "file2" matches.
-
+<
*bufnr()*
bufnr([{buf} [, {create}]])
The result is the number of a buffer, as it is displayed by
@@ -3584,7 +3584,7 @@ count({comp}, {expr} [, {ic} [, {start}]]) *count()*
Can also be used as a |method|: >
mylist->count(val)
-
+<
*cscope_connection()*
cscope_connection([{num} , {dbpath} [, {prepend}]])
Checks for the existence of a |cscope| connection. If no
@@ -3937,7 +3937,7 @@ exepath({expr}) *exepath()*
Can also be used as a |method|: >
GetCommand()->exepath()
-
+<
*exists()*
exists({expr}) The result is a Number, which is |TRUE| if {expr} is
defined, zero otherwise.
@@ -4483,7 +4483,7 @@ foldlevel({lnum}) *foldlevel()*
Can also be used as a |method|: >
GetLnum()->foldlevel()
-
+<
*foldtext()*
foldtext() Returns a String, to be displayed for a closed fold. This is
the default function used for the 'foldtext' option and should
@@ -5001,11 +5001,11 @@ getcurpos() Get the position of the cursor. This is like getpos('.'), but
getcwd([{winnr}[, {tabnr}]]) *getcwd()*
With no arguments, returns the name of the effective
|current-directory|. With {winnr} or {tabnr} the working
- directory of that scope is returned.
+ directory of that scope is returned, and 'autochdir' is
+ ignored.
Tabs and windows are identified by their respective numbers,
- 0 means current tab or window. Missing argument implies 0.
+ 0 means current tab or window. Missing tab number implies 0.
Thus the following are equivalent: >
- getcwd()
getcwd(0)
getcwd(0, 0)
< If {winnr} is -1 it is ignored, only the tab is resolved.
@@ -5136,8 +5136,8 @@ getline({lnum} [, {end}])
digit, |line()| is called to translate the String into a Number.
To get the line under the cursor: >
getline(".")
-< When {lnum} is smaller than 1 or bigger than the number of
- lines in the buffer, an empty string is returned.
+< When {lnum} is a number smaller than 1 or bigger than the
+ number of lines in the buffer, an empty string is returned.
When {end} is given the result is a |List| where each item is
a line from the current buffer in the range {lnum} to {end},
@@ -5562,6 +5562,9 @@ getwininfo([{winid}]) *getwininfo()*
otherwise
wincol leftmost screen column of the window;
"col" from |win_screenpos()|
+ textoff number of columns occupied by any
+ 'foldcolumn', 'signcolumn' and line
+ number in front of the text
winid |window-ID|
winnr window number
winrow topmost screen line of the window;
@@ -7461,15 +7464,18 @@ printf({fmt}, {expr1} ...) *printf()*
field width. If the converted value has fewer bytes
than the field width, it will be padded with spaces on
the left (or right, if the left-adjustment flag has
- been given) to fill out the field width.
+ been given) to fill out the field width. For the S
+ conversion the count is in cells.
.precision
An optional precision, in the form of a period '.'
followed by an optional digit string. If the digit
string is omitted, the precision is taken as zero.
This gives the minimum number of digits to appear for
- d, o, x, and X conversions, or the maximum number of
- bytes to be printed from a string for s conversions.
+ d, o, x, and X conversions, the maximum number of
+ bytes to be printed from a string for s conversions,
+ or the maximum number of cells to be printed from a
+ string for S conversions.
For floating point it is the number of digits after
the decimal point.
@@ -8546,6 +8552,7 @@ setbufline({buf}, {lnum}, {text}) *setbufline()*
For the use of {buf}, see |bufname()| above.
{lnum} is used like with |setline()|.
+ Use "$" to refer to the last line in buffer {buf}.
When {lnum} is just below the last line the {text} will be
added below the last line.
On success 0 is returned, on failure 1 is returned.
@@ -8970,7 +8977,7 @@ shellescape({string} [, {special}]) *shellescape()*
Otherwise encloses {string} in single-quotes and replaces all
"'" with "'\''".
- If {special} is a ||non-zero-arg|:
+ If {special} is a |non-zero-arg|:
- Special items such as "!", "%", "#" and "<cword>" will be
preceded by a backslash. The backslash will be removed again
by the |:!| command.
@@ -8980,7 +8987,7 @@ shellescape({string} [, {special}]) *shellescape()*
- The "!" character will be escaped. This is because csh and
tcsh use "!" for history replacement even in single-quotes.
- The <NL> character is escaped (twice if {special} is
- a ||non-zero-arg|).
+ a |non-zero-arg|).
If 'shell' contains "fish" in the tail, the "\" character will
be escaped because in fish it is used as an escape character
diff --git a/runtime/doc/filetype.txt b/runtime/doc/filetype.txt
index 42a9993c8c..bbbe71ec3a 100644
--- a/runtime/doc/filetype.txt
+++ b/runtime/doc/filetype.txt
@@ -128,18 +128,19 @@ can be used to overrule the filetype used for certain extensions:
file name variable ~
*.asa g:filetype_asa |ft-aspvbs-syntax| |ft-aspperl-syntax|
- *.asp g:filetype_asp |ft-aspvbs-syntax| |ft-aspperl-syntax|
*.asm g:asmsyntax |ft-asm-syntax|
- *.prg g:filetype_prg
- *.pl g:filetype_pl
- *.inc g:filetype_inc
- *.w g:filetype_w |ft-cweb-syntax|
+ *.asp g:filetype_asp |ft-aspvbs-syntax| |ft-aspperl-syntax|
+ *.fs g:filetype_fs |ft-forth-syntax|
*.i g:filetype_i |ft-progress-syntax|
+ *.inc g:filetype_inc
*.m g:filetype_m |ft-mathematica-syntax|
*.p g:filetype_p |ft-pascal-syntax|
+ *.pl g:filetype_pl
*.pp g:filetype_pp |ft-pascal-syntax|
+ *.prg g:filetype_prg
*.sh g:bash_is_sh |ft-sh-syntax|
*.tex g:tex_flavor |ft-tex-plugin|
+ *.w g:filetype_w |ft-cweb-syntax|
*filetype-ignore*
To avoid that certain files are being inspected, the g:ft_ignore_pat variable
@@ -494,7 +495,6 @@ Options:
For further discussion of fortran_have_tabs and the method used for the
detection of source format see |ft-fortran-syntax|.
-
GIT COMMIT *ft-gitcommit-plugin*
One command, :DiffGitCached, is provided to show a diff of the current commit
diff --git a/runtime/doc/helphelp.txt b/runtime/doc/helphelp.txt
index c884eea54f..e7b489d6e1 100644
--- a/runtime/doc/helphelp.txt
+++ b/runtime/doc/helphelp.txt
@@ -319,7 +319,7 @@ Hints for translators:
3. Writing help files *help-writing*
For ease of use, a Vim help file for a plugin should follow the format of the
-standard Vim help files, except fot the fist line. If you are writing a new
+standard Vim help files, except for the first line. If you are writing a new
help file it's best to copy one of the existing files and use it as a
template.
@@ -332,7 +332,7 @@ remainder of the line, after a Tab, describes the plugin purpose in a short
way. This will show up in the "LOCAL ADDITIONS" section of the main help
file. Check there that it shows up properly: |local-additions|.
-If you want to add a version number of last modification date, put it in the
+If you want to add a version number or last modification date, put it in the
second line, right aligned.
At the bottom of the help file, place a Vim modeline to set the 'textwidth'
diff --git a/runtime/doc/lsp.txt b/runtime/doc/lsp.txt
index 83d201c23a..9bd304cbb4 100644
--- a/runtime/doc/lsp.txt
+++ b/runtime/doc/lsp.txt
@@ -521,7 +521,9 @@ buf_request({bufnr}, {method}, {params}, {handler})
{method} (string) LSP method name
{params} (optional, table) Parameters to send to the
server
- {handler} (optional, function) See |lsp-handler|
+ {handler} (optional, function) See |lsp-handler| If nil,
+ follows resolution strategy defined in
+ |lsp-handler-configuration|
Return: ~
2-tuple:
@@ -628,11 +630,6 @@ client() *vim.lsp.client*
server.
• {handlers} (table): The handlers used by the client as
described in |lsp-handler|.
- • {requests} (table): The current pending requests in flight
- to the server. Entries are key-value pairs with the key
- being the request ID while the value is a table with `type`,
- `bufnr`, and `method` key-value pairs. `type` is either "pending"
- for an active request, or "cancel" for a cancel request.
• {config} (table): copy of the table that was passed by the
user to |vim.lsp.start_client()|.
• {server_capabilities} (table): Response from the server
@@ -650,12 +647,34 @@ client_is_stopped({client_id}) *vim.lsp.client_is_stopped()*
Return: ~
true if client is stopped, false otherwise.
-flush({client}) *vim.lsp.flush()*
- TODO: Documentation
-
*vim.lsp.for_each_buffer_client()*
for_each_buffer_client({bufnr}, {fn})
- TODO: Documentation
+ Invokes a function for each LSP client attached to a buffer.
+
+ Parameters: ~
+ {bufnr} number Buffer number
+ {fn} function Function to run on each client attached
+ to buffer {bufnr}. The function takes the client,
+ client ID, and buffer number as arguments.
+ Example: >
+
+ vim.lsp.for_each_buffer_client(0, function(client, client_id, bufnr)
+ print(vim.inspect(client))
+ end)
+<
+
+formatexpr({opts}) *vim.lsp.formatexpr()*
+ Provides an interface between the built-in client and a
+ `formatexpr` function.
+
+ Currently only supports a single client. This can be set via `setlocal formatexpr=v:lua.vim.lsp.formatexpr()` but will typically or in `on_attach` via vim.api.nvim_buf_set_option(bufnr, 'formatexpr , 'v:lua.vim.lsp.formatexpr(#{timeout_ms:250})')`.
+
+ Parameters: ~
+ {opts} table options for customizing the formatting
+ expression which takes the following optional
+ keys:
+ • timeout_ms (default 500ms). The timeout period
+ for the formatting request.
get_active_clients() *vim.lsp.get_active_clients()*
Gets all active clients.
@@ -665,8 +684,10 @@ get_active_clients() *vim.lsp.get_active_clients()*
*vim.lsp.get_buffers_by_client_id()*
get_buffers_by_client_id({client_id})
+ Returns list of buffers attached to client_id.
+
Parameters: ~
- {client_id} client id
+ {client_id} number client id
Return: ~
list of buffer ids
@@ -676,7 +697,7 @@ get_client_by_id({client_id}) *vim.lsp.get_client_by_id()*
client may not yet be fully initialized.
Parameters: ~
- {client_id} client id number
+ {client_id} number client id
Return: ~
|vim.lsp.client| object, or nil
@@ -706,16 +727,6 @@ omnifunc({findstart}, {base}) *vim.lsp.omnifunc()*
|complete-items|
|CompleteDone|
- *vim.lsp.prepare()*
-prepare({bufnr}, {firstline}, {new_lastline}, {changedtick})
- TODO: Documentation
-
-reset({client_id}) *vim.lsp.reset()*
- TODO: Documentation
-
-reset_buf({client}, {bufnr}) *vim.lsp.reset_buf()*
- TODO: Documentation
-
set_log_level({level}) *vim.lsp.set_log_level()*
Sets the global log level for LSP logging.
@@ -734,15 +745,12 @@ set_log_level({level}) *vim.lsp.set_log_level()*
start_client({config}) *vim.lsp.start_client()*
Starts and initializes a client with the given configuration.
- Parameters `cmd` and `root_dir` are required.
+ Parameter `cmd` is required.
The following parameters describe fields in the {config}
table.
Parameters: ~
- {root_dir} (string) Directory where the LSP
- server will base its rootUri on
- initialization.
{cmd} (required, string or list treated
like |jobstart()|) Base command that
initiates the LSP client.
@@ -757,6 +765,13 @@ start_client({config}) *vim.lsp.start_client()*
{ "PRODUCTION=true"; "TEST=123"; PORT = 8080; HOST = "0.0.0.0"; }
<
+ {workspace_folders} (table) List of workspace folders
+ passed to the language server. For
+ backwards compatibility rootUri and
+ rootPath will be derived from the
+ first workspace folder in this list.
+ See `workspaceFolders` in the LSP
+ spec.
{capabilities} Map overriding the default
capabilities defined by
|vim.lsp.protocol.make_client_capabilities()|,
@@ -776,15 +791,21 @@ start_client({config}) *vim.lsp.start_client()*
language server if requested via
`workspace/configuration` . Keys are
case-sensitive.
+ {commands} table Table that maps string of
+ clientside commands to user-defined
+ functions. Commands passed to
+ start_client take precedence over the
+ global command registry. Each key
+ must be a unique command name, and
+ the value is a function which is
+ called if any LSP action (code
+ action, code lenses, ...) triggers
+ the command.
{init_options} Values to pass in the initialization
request as `initializationOptions` .
See `initialize` in the LSP spec.
{name} (string, default=client-id) Name in
log messages.
- {workspace_folders} (table) List of workspace folders
- passed to the language server.
- Defaults to root_dir if not set. See
- `workspaceFolders` in the LSP spec
{get_language_id} function(bufnr, filetype) -> language
ID as string. Defaults to the
filetype.
@@ -851,6 +872,17 @@ start_client({config}) *vim.lsp.start_client()*
notifications to the server by the
given number in milliseconds. No
debounce occurs if nil
+ • exit_timeout (number, default 500):
+ Milliseconds to wait for server to
+ exit cleanly after sending the
+ 'shutdown' request before sending
+ kill -15. If set to false, nvim
+ exits immediately after sending the
+ 'shutdown' request to the server.
+ {root_dir} string Directory where the LSP server
+ will base its workspaceFolders,
+ rootUri, and rootPath on
+ initialization.
Return: ~
Client id. |vim.lsp.get_client_by_id()| Note: client may
@@ -876,6 +908,23 @@ stop_client({client_id}, {force}) *vim.lsp.stop_client()*
thereof
{force} boolean (optional) shutdown forcefully
+tagfunc({...}) *vim.lsp.tagfunc()*
+ Provides an interface between the built-in client and
+ 'tagfunc'.
+
+ When used with normal mode commands (e.g. |CTRL-]|) this will
+ invoke the "textDocument/definition" LSP method to find the
+ tag under the cursor. Otherwise, uses "workspace/symbol". If
+ no results are returned from any LSP servers, falls back to
+ using built-in tags.
+
+ Parameters: ~
+ {pattern} Pattern used to find a workspace symbol
+ {flags} See |tag-function|
+
+ Return: ~
+ A list of matching tags
+
with({handler}, {override_config}) *vim.lsp.with()*
Function to manage overriding defaults for LSP handlers.
@@ -942,9 +991,9 @@ document_highlight() *vim.lsp.buf.document_highlight()*
triggered by a key mapping or by events such as `CursorHold` ,
eg:
>
- vim.api.nvim_command [[autocmd CursorHold <buffer> lua vim.lsp.buf.document_highlight()]]
- vim.api.nvim_command [[autocmd CursorHoldI <buffer> lua vim.lsp.buf.document_highlight()]]
- vim.api.nvim_command [[autocmd CursorMoved <buffer> lua vim.lsp.buf.clear_references()]]
+ autocmd CursorHold <buffer> lua vim.lsp.buf.document_highlight()
+ autocmd CursorHoldI <buffer> lua vim.lsp.buf.document_highlight()
+ autocmd CursorMoved <buffer> lua vim.lsp.buf.clear_references()
<
Note: Usage of |vim.lsp.buf.document_highlight()| requires the
@@ -1012,7 +1061,7 @@ formatting_sync({options}, {timeout_ms})
|vim.lsp.buf_request_sync()|. Example:
>
- vim.api.nvim_command[[autocmd BufWritePre <buffer> lua vim.lsp.buf.formatting_sync()]]
+ autocmd BufWritePre <buffer> lua vim.lsp.buf.formatting_sync()
<
Parameters: ~
@@ -1044,9 +1093,6 @@ outgoing_calls() *vim.lsp.buf.outgoing_calls()*
cursor in the |quickfix| window. If the symbol can resolve to
multiple items, the user can pick one in the |inputlist|.
-prepare_rename({err}, {result}) *vim.lsp.buf.prepare_rename()*
- TODO: Documentation
-
*vim.lsp.buf.range_code_action()*
range_code_action({context}, {start_pos}, {end_pos})
Performs |vim.lsp.buf.code_action()| for a given range.
@@ -1301,23 +1347,22 @@ buf_clear_references({bufnr}) *vim.lsp.util.buf_clear_references()*
Removes document highlights from a buffer.
Parameters: ~
- {bufnr} buffer id
+ {bufnr} number Buffer id
*vim.lsp.util.buf_highlight_references()*
-buf_highlight_references({bufnr}, {references})
+buf_highlight_references({bufnr}, {references}, {offset_encoding})
Shows a list of document highlights for a certain buffer.
Parameters: ~
- {bufnr} buffer id
- {references} List of `DocumentHighlight` objects to
- highlight
+ {bufnr} number Buffer id
+ {references} table List of `DocumentHighlight`
+ objects to highlight
+ {offset_encoding} string One of "utf-8", "utf-16",
+ "utf-32", or nil. Defaults to utf-16
See also: ~
https://microsoft.github.io/language-server-protocol/specifications/specification-3-17/#documentHighlight
-buf_lines({bufnr}) *vim.lsp.util.buf_lines()*
- TODO: Documentation
-
*vim.lsp.util.character_offset()*
character_offset({bufnr}, {row}, {col})
Returns the UTF-32 and UTF-16 offsets for a position in a
@@ -1344,25 +1389,6 @@ close_preview_autocmd({events}, {winnr})
See also: ~
|autocmd-events|
- *vim.lsp.util.compute_diff()*
-compute_diff({old_lines}, {new_lines}, {start_line_idx}, {end_line_idx},
- {offset_encoding})
- Returns the range table for the difference between old and new
- lines
-
- Parameters: ~
- {old_lines} table list of lines
- {new_lines} table list of lines
- {start_line_idx} int line to begin search for first
- difference
- {end_line_idx} int line to begin search for last
- difference
- {offset_encoding} string encoding requested by language
- server
-
- Return: ~
- table start_line_idx and start_col_idx of range
-
*vim.lsp.util.convert_input_to_markdown_lines()*
convert_input_to_markdown_lines({input}, {contents})
Converts any of `MarkedString` | `MarkedString[]` |
@@ -1403,12 +1429,6 @@ convert_signature_help_to_markdown_lines({signature_help}, {ft}, {triggers})
See also: ~
https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_signatureHelp
-create_file({change}) *vim.lsp.util.create_file()*
- TODO: Documentation
-
-delete_file({change}) *vim.lsp.util.delete_file()*
- TODO: Documentation
-
*vim.lsp.util.extract_completion_items()*
extract_completion_items({result})
Can be used to extract the completion items from a `textDocument/completion` request, which may return one of `CompletionItem[]` , `CompletionList` or null.
@@ -1436,29 +1456,6 @@ get_effective_tabstop({bufnr}) *vim.lsp.util.get_effective_tabstop()*
See also: ~
|softtabstop|
-get_line({uri}, {row}) *vim.lsp.util.get_line()*
- Gets the zero-indexed line from the given uri.
-
- Parameters: ~
- {uri} string uri of the resource to get the line from
- {row} number zero-indexed line number
-
- Return: ~
- string the line at row in filename
-
-get_lines({uri}, {rows}) *vim.lsp.util.get_lines()*
- Gets the zero-indexed lines from the given uri.
-
- Parameters: ~
- {uri} string uri of the resource to get the lines from
- {rows} number[] zero-indexed line numbers
-
- Return: ~
- table<number string> a table mapping rows to lines
-
-get_progress_messages() *vim.lsp.util.get_progress_messages()*
- TODO: Documentation
-
jump_to_location({location}) *vim.lsp.util.jump_to_location()*
Jumps to a location.
@@ -1593,25 +1590,32 @@ open_floating_preview({contents}, {syntax}, {opts})
Parameters: ~
{contents} table of lines to show in window
{syntax} string of syntax to set for opened buffer
- {opts} dictionary with optional fields
- • height of floating window
- • width of floating window
- • wrap boolean enable wrapping of long lines
- (defaults to true)
- • wrap_at character to wrap at for computing
- height when wrap is enabled
- • max_width maximal width of floating window
- • max_height maximal height of floating window
- • pad_top number of lines to pad contents at
- top
- • pad_bottom number of lines to pad contents
- at bottom
- • focus_id if a popup with this id is opened,
- then focus it
- • close_events list of events that closes the
+ {opts} table with optional fields (additional keys
+ are passed on to |vim.api.nvim_open_win()|)
+ • height: (number) height of floating window
+ • width: (number) width of floating window
+ • wrap: (boolean, default true) wrap long
+ lines
+ • wrap_at: (string) character to wrap at for
+ computing height when wrap is enabled
+ • max_width: (number) maximal width of
floating window
- • focusable (boolean, default true): Make
+ • max_height: (number) maximal height of
+ floating window
+ • pad_top: (number) number of lines to pad
+ contents at top
+ • pad_bottom: (number) number of lines to pad
+ contents at bottom
+ • focus_id: (string) if a popup with this id
+ is opened, then focus it
+ • close_events: (table) list of events that
+ closes the floating window
+ • focusable: (boolean, default true) Make
float focusable
+ • focus: (boolean, default true) If `true` ,
+ and if {focusable} is also `true` , focus an
+ existing floating window with the same
+ {focus_id}
Return: ~
bufnr,winnr buffer and window number of the newly created
@@ -1752,7 +1756,10 @@ get_filename() *vim.lsp.log.get_filename()*
(string) log filename
get_level() *vim.lsp.log.get_level()*
- TODO: Documentation
+ Gets the current log level.
+
+ Return: ~
+ string current log level
set_format_func({handle}) *vim.lsp.log.set_format_func()*
Sets formatting function used to format logs
@@ -1800,14 +1807,19 @@ notify({method}, {params}) *vim.lsp.rpc.notify()*
(bool) `true` if notification could be sent, `false` if
not
-request({method}, {params}, {callback}) *vim.lsp.rpc.request()*
+ *vim.lsp.rpc.request()*
+request({method}, {params}, {callback}, {notify_reply_callback})
Sends a request to the LSP server and runs {callback} upon
response.
Parameters: ~
- {method} (string) The invoked LSP method
- {params} (table) Parameters for the invoked LSP method
- {callback} (function) Callback to invoke
+ {method} (string) The invoked LSP method
+ {params} (table) Parameters for the
+ invoked LSP method
+ {callback} (function) Callback to invoke
+ {notify_reply_callback} (function) Callback to invoke as
+ soon as a request is no longer
+ pending
Return: ~
(bool, number) `(true, message_id)` if request could be
@@ -1826,7 +1838,8 @@ rpc_response_error({code}, {message}, {data})
*vim.lsp.rpc.start()*
start({cmd}, {cmd_args}, {dispatchers}, {extra_spawn_params})
Starts an LSP server process and create an LSP RPC client
- object to interact with it.
+ object to interact with it. Communication with the server is
+ currently limited to stdio.
Parameters: ~
{cmd} (string) Command to start the LSP
@@ -1862,6 +1875,31 @@ start({cmd}, {cmd_args}, {dispatchers}, {extra_spawn_params})
==============================================================================
+Lua module: vim.lsp.sync *lsp-sync*
+
+ *vim.lsp.sync.compute_diff()*
+compute_diff({prev_lines}, {curr_lines}, {firstline}, {lastline},
+ {new_lastline}, {offset_encoding}, {line_ending})
+ Returns the range table for the difference between prev and
+ curr lines
+
+ Parameters: ~
+ {prev_lines} table list of lines
+ {curr_lines} table list of lines
+ {firstline} number line to begin search for first
+ difference
+ {lastline} number line to begin search in
+ old_lines for last difference
+ {new_lastline} number line to begin search in
+ new_lines for last difference
+ {offset_encoding} string encoding requested by language
+ server
+
+ Return: ~
+ table TextDocumentContentChangeEvent see https://microsoft.github.io/language-server-protocol/specifications/specification-3-17/#textDocumentContentChangeEvent
+
+
+==============================================================================
Lua module: vim.lsp.protocol *lsp-protocol*
*vim.lsp.protocol.make_client_capabilities()*
diff --git a/runtime/doc/lua.txt b/runtime/doc/lua.txt
index ef2d87949d..630df16e79 100644
--- a/runtime/doc/lua.txt
+++ b/runtime/doc/lua.txt
@@ -362,8 +362,8 @@ cases there is the following agreement:
converted to a dictionary `{'a': 42}`: non-string keys are ignored.
Without `vim.type_idx` key tables with keys not fitting in 1., 2. or 3.
are errors.
- - `{[vim.type_idx]=vim.types.list}` is converted to an empty list. As well
- as `{[vim.type_idx]=vim.types.list, [42]=1}`: integral keys that do not
+ - `{[vim.type_idx]=vim.types.array}` is converted to an empty list. As well
+ as `{[vim.type_idx]=vim.types.array, [42]=1}`: integral keys that do not
form a 1-step sequence from 1 to N are ignored, as well as all
non-integral keys.
@@ -1190,9 +1190,6 @@ defer_fn({fn}, {timeout}) *vim.defer_fn()*
Return: ~
timer luv timer object
-insert_keys({obj}) *vim.insert_keys()*
- TODO: Documentation
-
inspect({object}, {options}) *vim.inspect()*
Return a human-readable representation of the given object.
@@ -1200,20 +1197,16 @@ inspect({object}, {options}) *vim.inspect()*
https://github.com/kikito/inspect.lua
https://github.com/mpeterv/vinspect
-make_dict_accessor({scope}) *vim.make_dict_accessor()*
- TODO: Documentation
-
-notify({msg}, {log_level}, {_opts}) *vim.notify()*
+notify({msg}, {log_level}, {opts}) *vim.notify()*
Notification provider
Without a runtime, writes to :Messages
Parameters: ~
- {msg} Content of the notification to show to the
- user
- {log_level} Optional log level
- {opts} Dictionary with optional options (timeout,
- etc)
+ {msg} string Content of the notification to show to
+ the user
+ {log_level} number|nil enum from vim.log.levels
+ {opts} table|nil additional options (timeout, etc)
See also: ~
:help nvim_notify
@@ -1239,7 +1232,7 @@ on_key({fn}, {ns_id}) *vim.on_key()*
it removes the callback for the associated
{ns_id}
{ns_id} number? Namespace ID. If nil or 0, generates and
- returns a new |nvim_create_namesapce()| id.
+ returns a new |nvim_create_namespace()| id.
Return: ~
number Namespace id associated with {fn}. Or count of all
@@ -1328,7 +1321,7 @@ deepcopy({orig}) *vim.deepcopy()*
and will throw an error.
Parameters: ~
- {orig} Table to copy
+ {orig} table Table to copy
Return: ~
New table of copied keys and (nested) values.
@@ -1369,9 +1362,6 @@ is_callable({f}) *vim.is_callable()*
Return: ~
true if `f` is callable, else false
-is_valid({opt}) *vim.is_valid()*
- TODO: Documentation
-
list_extend({dst}, {src}, {start}, {finish}) *vim.list_extend()*
Extends a list-like table with the values of another list-like
table.
@@ -1617,14 +1607,12 @@ validate({opt}) *vim.validate()*
vim.validate{arg1={{'foo'}, 'table'}, arg2={'foo', 'string'}}
=> NOP (success)
-<
->
- vim.validate{arg1={1, 'table'}}
- => error('arg1: expected table, got number')
-<
->
- vim.validate{arg1={3, function(a) return (a % 2) == 0 end, 'even number'}}
- => error('arg1: expected even number, got 3')
+
+ vim.validate{arg1={1, 'table'}}
+ => error('arg1: expected table, got number')
+
+ vim.validate{arg1={3, function(a) return (a % 2) == 0 end, 'even number'}}
+ => error('arg1: expected even number, got 3')
<
Parameters: ~
@@ -1658,40 +1646,38 @@ uri_from_bufnr({bufnr}) *vim.uri_from_bufnr()*
Get a URI from a bufnr
Parameters: ~
- {bufnr} (number): Buffer number
+ {bufnr} number
Return: ~
- URI
+ string URI
uri_from_fname({path}) *vim.uri_from_fname()*
Get a URI from a file path.
Parameters: ~
- {path} (string): Path to file
+ {path} string Path to file
Return: ~
- URI
+ string URI
uri_to_bufnr({uri}) *vim.uri_to_bufnr()*
- Return or create a buffer for a uri.
+ Get the buffer for a uri. Creates a new unloaded buffer if no
+ buffer for the uri already exists.
Parameters: ~
- {uri} (string): The URI
+ {uri} string
Return: ~
- bufnr.
-
- Note:
- Creates buffer but does not load it
+ number bufnr
uri_to_fname({uri}) *vim.uri_to_fname()*
Get a filename from a URI
Parameters: ~
- {uri} (string): The URI
+ {uri} string
Return: ~
- Filename
+ string filename or unchanged URI for non-file URIs
==============================================================================
@@ -1731,6 +1717,12 @@ select({items}, {opts}, {on_choice}) *vim.ui.select()*
• format_item (function item -> text)
Function to format an individual item from
`items` . Defaults to `tostring` .
+ • kind (string|nil) Arbitrary hint string
+ indicating the item shape. Plugins
+ reimplementing `vim.ui.select` may wish to
+ use this to infer the structure or
+ semantics of `items` , or the context in
+ which select() was called.
{on_choice} function ((item|nil, idx|nil) -> ()) Called
once the user made a choice. `idx` is the
1-based index of `item` within `item` . `nil`
diff --git a/runtime/doc/map.txt b/runtime/doc/map.txt
index 0b9ac42898..0ea2565694 100644
--- a/runtime/doc/map.txt
+++ b/runtime/doc/map.txt
@@ -81,6 +81,9 @@ modes.
Remove the mapping of {lhs} for the modes where the
map command applies. The mapping may remain defined
for other modes where it applies.
+ It also works when {lhs} matches the {rhs} of a
+ mapping. This is for when when an abbreviation
+ applied.
Note: Trailing spaces are included in the {lhs}. This
unmap does NOT work: >
:map @@ foo
@@ -320,6 +323,8 @@ Note:
- For the same reason, |keycodes| like <C-R><C-W> are interpreted as plain,
unmapped keys.
- The command is not echo'ed, no need for <silent>.
+- The {rhs} is not subject to abbreviations nor to other mappings, even if the
+ mapping is recursive.
- In Visual mode you can use `line('v')` and `col('v')` to get one end of the
Visual area, the cursor is at the other end.
- In select-mode, |:map| and |:vmap| command mappings are executed in
diff --git a/runtime/doc/pi_msgpack.txt b/runtime/doc/pi_msgpack.txt
index 951b897f55..1dbd268038 100644
--- a/runtime/doc/pi_msgpack.txt
+++ b/runtime/doc/pi_msgpack.txt
@@ -68,7 +68,7 @@ msgpack#strftime({format}, {msgpack-integer}) *msgpack#strftime()*
*msgpack#strptime*
msgpack#strptime({format}, {time}) *msgpack#strptime()*
- Reverse of |msgpack#strptime()|: for any time and format
+ Reverse of |msgpack#strftime()|: for any time and format
|msgpack#equal|( |msgpack#strptime|(format, |msgpack#strftime|(format,
time)), time) be true. Requires |+python| or |+python3|, without it
only supports non-|msgpack-special-dict| nonnegative times and format
diff --git a/runtime/doc/syntax.txt b/runtime/doc/syntax.txt
index e423c59efe..72f08c37ca 100644
--- a/runtime/doc/syntax.txt
+++ b/runtime/doc/syntax.txt
@@ -1497,6 +1497,14 @@ gvim display. Here, statements are colored LightYellow instead of Yellow, and
conditionals are LightBlue for better distinction.
+FORTH *forth.vim* *ft-forth-syntax*
+
+Files matching "*.fs" could be F# or Forth. If the automatic detection
+doesn't work for you, or you don't edit F# at all, use this in your
+startup vimrc: >
+ :let filetype_fs = "forth"
+
+
FORTRAN *fortran.vim* *ft-fortran-syntax*
Default highlighting and dialect ~
diff --git a/runtime/doc/treesitter.txt b/runtime/doc/treesitter.txt
index 441ae13df4..08dc0583ac 100644
--- a/runtime/doc/treesitter.txt
+++ b/runtime/doc/treesitter.txt
@@ -353,7 +353,7 @@ Lua module: vim.treesitter *lua-treesitter-core*
get_parser({bufnr}, {lang}, {opts}) *get_parser()*
Gets the parser for this bufnr / ft combination.
- If needed this will create the parser. Unconditionnally attach
+ If needed this will create the parser. Unconditionally attach
the provided callback
Parameters: ~
@@ -380,7 +380,7 @@ Lua module: vim.treesitter.language *treesitter-language*
inspect_language({lang}) *inspect_language()*
Inspects the provided language.
- Inspecting provides some useful informations on the language
+ Inspecting provides some useful information on the language
like node names, ...
Parameters: ~
@@ -479,7 +479,7 @@ Query:iter_captures({self}, {node}, {source}, {start}, {stop})
{source} is needed if the query contains predicates, then the
caller must ensure to use a freshly parsed tree consistent
- with the current text of the buffer (if relevent). {start_row}
+ with the current text of the buffer (if relevant). {start_row}
and {end_row} can be used to limit matches inside a row range
(this is typically used with root node as the node, i e to get
syntax highlight matches in the current viewport). When
@@ -503,8 +503,7 @@ Query:iter_captures({self}, {node}, {source}, {start}, {stop})
Parameters: ~
{node} The node under which the search will occur
- {source} The source buffer or string to exctract text
- from
+ {source} The source buffer or string to extract text from
{start} The starting line of the search
{stop} The stopping line of the search (end-exclusive)
{self}
@@ -611,7 +610,7 @@ LanguageTree:children({self}) *LanguageTree:children()*
{self}
LanguageTree:contains({self}, {range}) *LanguageTree:contains()*
- Determines wether This goes down the tree to recursively check childs.
+ Determines whether This goes down the tree to recursively check children.
Parameters: ~
{range} is contained in this language tree
diff --git a/runtime/doc/usr_20.txt b/runtime/doc/usr_20.txt
index cff5c7d2f2..6a8836c8e8 100644
--- a/runtime/doc/usr_20.txt
+++ b/runtime/doc/usr_20.txt
@@ -292,7 +292,7 @@ to newer commands.
There are actually five histories. The ones we will mention here are for ":"
commands and for "/" and "?" search commands. The "/" and "?" commands share
the same history, because they are both search commands. The three other
-histories are for expressions, debug more commands and input lines for the
+histories are for expressions, debug mode commands and input lines for the
input() function. |cmdline-history|
Suppose you have done a ":set" command, typed ten more colon commands and then
diff --git a/runtime/doc/vim_diff.txt b/runtime/doc/vim_diff.txt
index d88f4f42e8..956cb3e624 100644
--- a/runtime/doc/vim_diff.txt
+++ b/runtime/doc/vim_diff.txt
@@ -428,7 +428,7 @@ Working directory (Vim implemented some of these later than Nvim):
- |DirChanged| can be triggered when switching to another window.
- |getcwd()| and |haslocaldir()| may throw errors if the tab page or window
cannot be found. *E5000* *E5001* *E5002*
-- |haslocaldir()| only checks for tab-local directory when -1 is passed as
+- |haslocaldir()| checks for tab-local directory if and only if -1 is passed as
window number, and its only possible returns values are 0 and 1.
- `getcwd(-1)` is equivalent to `getcwd(-1, 0)` instead of returning the global
working directory. Use `getcwd(-1, -1)` to get the global working directory.
diff --git a/runtime/doc/visual.txt b/runtime/doc/visual.txt
index 111588e43a..4a69fc989b 100644
--- a/runtime/doc/visual.txt
+++ b/runtime/doc/visual.txt
@@ -360,7 +360,8 @@ same amount of text as the last time:
last line the same number of characters as in the last line the last time.
The start of the text is the Cursor position. If the "$" command was used as
one of the last commands to extend the highlighted text, the repeating will
-be applied up to the rightmost column of the longest line.
+be applied up to the rightmost column of the longest line. Any count passed
+to the `.` command is not used.
==============================================================================
diff --git a/runtime/filetype.vim b/runtime/filetype.vim
index 1b48070128..cc28dba1d0 100644
--- a/runtime/filetype.vim
+++ b/runtime/filetype.vim
@@ -484,7 +484,7 @@ au BufNewFile,BufRead *.desktop,*.directory setf desktop
au BufNewFile,BufRead dict.conf,.dictrc setf dictconf
" Dictd config
-au BufNewFile,BufRead dictd.conf setf dictdconf
+au BufNewFile,BufRead dictd*.conf setf dictdconf
" Diff files
au BufNewFile,BufRead *.diff,*.rej setf diff
@@ -628,7 +628,7 @@ au BufNewFile,BufRead auto.master setf conf
au BufNewFile,BufRead *.mas,*.master setf master
" Forth
-au BufNewFile,BufRead *.fs,*.ft,*.fth setf forth
+au BufNewFile,BufRead *.ft,*.fth setf forth
" Reva Forth
au BufNewFile,BufRead *.frt setf reva
@@ -645,6 +645,12 @@ au BufNewFile,BufRead *.fsl setf framescript
" FStab
au BufNewFile,BufRead fstab,mtab setf fstab
+" F# or Forth
+au BufNewFile,BufRead *.fs call dist#ft#FTfs()
+
+" F#
+au BufNewFile,BufRead *.fsi,*.fsx setf fsharp
+
" GDB command files
au BufNewFile,BufRead .gdbinit,gdbinit setf gdb
@@ -1095,6 +1101,9 @@ au BufNewFile,BufRead *.moo setf moo
" Modconf
au BufNewFile,BufRead */etc/modules.conf,*/etc/modules,*/etc/conf.modules setf modconf
+" MPD is based on XML
+au BufNewFile,BufRead *.mpd setf xml
+
" Mplayer config
au BufNewFile,BufRead mplayer.conf,*/.mplayer/config setf mplayerconf
@@ -2055,9 +2064,15 @@ au BufNewFile,BufRead *.xml call dist#ft#FTxml()
" XMI (holding UML models) is also XML
au BufNewFile,BufRead *.xmi setf xml
-" CSPROJ files are Visual Studio.NET's XML-based project config files
+" CSPROJ files are Visual Studio.NET's XML-based C# project config files
au BufNewFile,BufRead *.csproj,*.csproj.user setf xml
+" FSPROJ files are Visual Studio.NET's XML-based F# project config files
+au BufNewFile,BufRead *.fsproj,*.fsproj.user setf xml
+
+" VBPROJ files are Visual Studio.NET's XML-based Visual Basic project config files
+au BufNewFile,BufRead *.vbproj,*.vbproj.user setf xml
+
" Qt Linguist translation source and Qt User Interface Files are XML
" However, for .ts Typescript is more common.
au BufNewFile,BufRead *.ui setf xml
@@ -2155,7 +2170,7 @@ au BufNewFile,BufRead proftpd.conf* call s:StarSetf('apachestyle')
" More Apache config files
au BufNewFile,BufRead access.conf*,apache.conf*,apache2.conf*,httpd.conf*,srm.conf* call s:StarSetf('apache')
-au BufNewFile,BufRead */etc/apache2/*.conf*,*/etc/apache2/conf.*/*,*/etc/apache2/mods-*/*,*/etc/apache2/sites-*/*,*/etc/httpd/conf.d/*.conf* call s:StarSetf('apache')
+au BufNewFile,BufRead */etc/apache2/*.conf*,*/etc/apache2/conf.*/*,*/etc/apache2/mods-*/*,*/etc/apache2/sites-*/*,*/etc/httpd/conf.*/*,*/etc/httpd/mods-*/*,*/etc/httpd/sites-*/*,*/etc/httpd/conf.d/*.conf* call s:StarSetf('apache')
" Asterisk config file
au BufNewFile,BufRead *asterisk/*.conf* call s:StarSetf('asterisk')
diff --git a/runtime/ftplugin/indent.vim b/runtime/ftplugin/indent.vim
index e6d928a073..64a650ad7b 100644
--- a/runtime/ftplugin/indent.vim
+++ b/runtime/ftplugin/indent.vim
@@ -1,7 +1,8 @@
" Vim filetype plugin file
-" Language: indent(1) configuration file
-" Previous Maintainer: Nikolai Weibull <now@bitwi.se>
-" Latest Revision: 2008-07-09
+" Language: indent(1) configuration file
+" Maintainer: Doug Kearns <dougkearns@gmail.com>
+" Previous Maintainer: Nikolai Weibull <now@bitwi.se>
+" Latest Revision: 2008-07-09
if exists("b:did_ftplugin")
finish
diff --git a/runtime/ftplugin/jsonc.vim b/runtime/ftplugin/jsonc.vim
index 90d52cd0d3..e47a75f574 100644
--- a/runtime/ftplugin/jsonc.vim
+++ b/runtime/ftplugin/jsonc.vim
@@ -4,7 +4,7 @@
" Acknowledgement: Based off of vim-jsonc maintained by Kevin Locke <kevin@kevinlocke.name>
" https://github.com/kevinoid/vim-jsonc
" License: MIT
-" Last Change: 2021-07-01
+" Last Change: 2021 Nov 22
runtime! ftplugin/json.vim
@@ -14,14 +14,8 @@ else
let b:did_ftplugin_jsonc = 1
endif
-" A list of commands that undo buffer local changes made below.
-let s:undo_ftplugin = []
-
" Set comment (formatting) related options. {{{1
setlocal commentstring=//%s comments=sO:*\ -,mO:*\ \ ,exO:*/,s1:/*,mb:*,ex:*/,://
-call add(s:undo_ftplugin, 'commentstring< comments<')
" Let Vim know how to disable the plug-in.
-call map(s:undo_ftplugin, "'execute ' . string(v:val)")
-let b:undo_ftplugin = join(s:undo_ftplugin, ' | ')
-unlet s:undo_ftplugin
+let b:undo_ftplugin = 'setlocal commentstring< comments<'
diff --git a/runtime/ftplugin/vb.vim b/runtime/ftplugin/vb.vim
index d70db89273..5a9548115b 100644
--- a/runtime/ftplugin/vb.vim
+++ b/runtime/ftplugin/vb.vim
@@ -1,44 +1,70 @@
" Vim filetype plugin file
-" Language: VisualBasic (ft=vb)
-" Maintainer: Johannes Zellner <johannes@zellner.org>
-" Last Change: Thu, 22 Nov 2001 12:56:14 W. Europe Standard Time
+" Language: Visual Basic (ft=vb)
+" Maintainer: Doug Kearns <dougkearns@gmail.com>
+" Previous Maintainer: Johannes Zellner <johannes@zellner.org>
+" Last Change: 2021 Nov 17
-if exists("b:did_ftplugin") | finish | endif
+if exists("b:did_ftplugin")
+ finish
+endif
let b:did_ftplugin = 1
-setlocal com=sr:'\ -,mb:'\ \ ,el:'\ \ ,:'
+let s:cpo_save = &cpo
+set cpo&vim
+
+setlocal comments=sr:'\ -,mb:'\ \ ,el:'\ \ ,:'
+setlocal commentstring='\ %s
+setlocal formatoptions-=t formatoptions+=croql
+
+let b:undo_ftplugin = "setlocal com< cms< fo<"
" we need this wrapper, as call doesn't allow a count
-fun! <SID>VbSearch(pattern, flags)
+function! s:VbSearch(pattern, flags)
let cnt = v:count1
while cnt > 0
call search(a:pattern, a:flags)
let cnt = cnt - 1
endwhile
-endfun
+endfunction
-let s:cpo_save = &cpo
-set cpo&vim
+if !exists("no_plugin_maps") && !exists("no_vb_maps")
+ nnoremap <buffer> <silent> [[ <Cmd>call <SID>VbSearch('^\s*\%(\%(private\<Bar>public\)\s\+\)\=\%(function\<Bar>sub\)', 'sbW')<CR>
+ vnoremap <buffer> <silent> [[ <Cmd>call <SID>VbSearch('^\s*\%(\%(private\<Bar>public\)\s\+\)\=\%(function\<Bar>sub\)', 'sbW')<CR>
+ nnoremap <buffer> <silent> ]] <Cmd>call <SID>VbSearch('^\s*\%(\%(private\<Bar>public\)\s\+\)\=\%(function\<Bar>sub\)', 'sW')<CR>
+ vnoremap <buffer> <silent> ]] <Cmd>call <SID>VbSearch('^\s*\%(\%(private\<Bar>public\)\s\+\)\=\%(function\<Bar>sub\)', 'sW')<CR>
+ nnoremap <buffer> <silent> [] <Cmd>call <SID>VbSearch('^\s*end\s\+\%(function\<Bar>sub\)', 'sbW')<CR>
+ vnoremap <buffer> <silent> [] <Cmd>call <SID>VbSearch('^\s*end\s\+\%(function\<Bar>sub\)', 'sbW')<CR>
+ nnoremap <buffer> <silent> ][ <Cmd>call <SID>VbSearch('^\s*end\s\+\%(function\<Bar>sub\)', 'sW')<CR>
+ vnoremap <buffer> <silent> ][ <Cmd>call <SID>VbSearch('^\s*end\s\+\%(function\<Bar>sub\)', 'sW')<CR>
+ let b:undo_ftplugin .= " | sil! exe 'nunmap <buffer> [[' | sil! exe 'vunmap <buffer> [['" .
+ \ " | sil! exe 'nunmap <buffer> ]]' | sil! exe 'vunmap <buffer> ]]'" .
+ \ " | sil! exe 'nunmap <buffer> []' | sil! exe 'vunmap <buffer> []'" .
+ \ " | sil! exe 'nunmap <buffer> ][' | sil! exe 'vunmap <buffer> ]['"
+endif
+
+" TODO: line start anchors are almost certainly overly restrictive - allow
+" after statement separators. Even in QuickBasic only block IF statements
+" were required to be at the start of a line.
+if exists("loaded_matchit") && !exists("b:match_words")
+ let b:match_ignorecase = 1
+ let b:match_words =
+ \ '\%(^\s*\)\@<=\<if\>.*\<then\>\s*\%($\|''\):\%(^\s*\)\@<=\<else\>:\%(^\s*\)\@<=\<elseif\>:\%(^\s*\)\@<=\<end\>\s\+\<if\>,' .
+ \ '\%(^\s*\)\@<=\<for\>:\%(^\s*\)\@<=\<next\>,' .
+ \ '\%(^\s*\)\@<=\<while\>:\%(^\s*\)\@<=\<wend\>,' .
+ \ '\%(^\s*\)\@<=\<do\>:\%(^\s*\)\@<=\<loop\>\s\+\<while\>,' .
+ \ '\%(^\s*\)\@<=\<select\>\s\+\<case\>:\%(^\s*\)\@<=\<case\>:\%(^\s*\)\@<=\<end\>\s\+\<select\>,' .
+ \ '\%(^\s*\)\@<=\<enum\>:\%(^\s*\)\@<=\<end\>\s\<enum\>,' .
+ \ '\%(^\s*\)\@<=\<with\>:\%(^\s*\)\@<=\<end\>\s\<with\>,' .
+ \ '\%(^\s*\)\@<=\%(\<\%(private\|public\)\>\s\+\)\=\<function\>\s\+\([^ \t(]\+\):\%(^\s*\)\@<=\<\1\>\s*=:\%(^\s*\)\@<=\<end\>\s\+\<function\>,' .
+ \ '\%(^\s*\)\@<=\%(\<\%(private\|public\)\>\s\+\)\=\<sub\>\s\+:\%(^\s*\)\@<=\<end\>\s\+\<sub\>'
+ let b:undo_ftplugin .= " | unlet! b:match_words b:match_ignorecase"
+endif
-" NOTE the double escaping \\|
-nnoremap <buffer> <silent> [[ :call <SID>VbSearch('^\s*\(\(private\|public\)\s\+\)\=\(function\\|sub\)', 'bW')<cr>
-nnoremap <buffer> <silent> ]] :call <SID>VbSearch('^\s*\(\(private\|public\)\s\+\)\=\(function\\|sub\)', 'W')<cr>
-nnoremap <buffer> <silent> [] :call <SID>VbSearch('^\s*\<end\>\s\+\(function\\|sub\)', 'bW')<cr>
-nnoremap <buffer> <silent> ][ :call <SID>VbSearch('^\s*\<end\>\s\+\(function\\|sub\)', 'W')<cr>
-
-" matchit support
-if exists("loaded_matchit")
- let b:match_ignorecase=1
- let b:match_words=
- \ '\%(^\s*\)\@<=\<if\>.*\<then\>\s*$:\%(^\s*\)\@<=\<else\>:\%(^\s*\)\@<=\<elseif\>:\%(^\s*\)\@<=\<end\>\s\+\<if\>,' .
- \ '\%(^\s*\)\@<=\<for\>:\%(^\s*\)\@<=\<next\>,' .
- \ '\%(^\s*\)\@<=\<while\>:\%(^\s*\)\@<=\<wend\>,' .
- \ '\%(^\s*\)\@<=\<do\>:\%(^\s*\)\@<=\<loop\>\s\+\<while\>,' .
- \ '\%(^\s*\)\@<=\<select\>\s\+\<case\>:\%(^\s*\)\@<=\<case\>:\%(^\s*\)\@<=\<end\>\s\+\<select\>,' .
- \ '\%(^\s*\)\@<=\<enum\>:\%(^\s*\)\@<=\<end\>\s\<enum\>,' .
- \ '\%(^\s*\)\@<=\<with\>:\%(^\s*\)\@<=\<end\>\s\<with\>,' .
- \ '\%(^\s*\)\@<=\%(\<\%(private\|public\)\>\s\+\)\=\<function\>\s\+\([^ \t(]\+\):\%(^\s*\)\@<=\<\1\>\s*=:\%(^\s*\)\@<=\<end\>\s\+\<function\>,' .
- \ '\%(^\s*\)\@<=\%(\<\%(private\|public\)\>\s\+\)\=\<sub\>\s\+:\%(^\s*\)\@<=\<end\>\s\+\<sub\>'
+if (has("gui_win32") || has("gui_gtk")) && !exists("b:browsefilter")
+ let b:browsefilter = "Visual Basic Source Files (*.bas)\t*.bas\n" .
+ \ "Visual Basic Form Files (*.frm)\t*.frm\n" .
+ \ "All Files (*.*)\t*.*\n"
+ let b:undo_ftplugin .= " | unlet! b:browsefilter"
endif
let &cpo = s:cpo_save
diff --git a/runtime/lua/vim/F.lua b/runtime/lua/vim/F.lua
index 1a258546a5..9327c652db 100644
--- a/runtime/lua/vim/F.lua
+++ b/runtime/lua/vim/F.lua
@@ -27,7 +27,7 @@ function F.nil_wrap(fn)
end
end
---- like {...} except preserve the lenght explicitly
+--- like {...} except preserve the length explicitly
function F.pack_len(...)
return {n=select('#', ...), ...}
end
diff --git a/runtime/lua/vim/_meta.lua b/runtime/lua/vim/_meta.lua
index f7d47c1030..a3d5f64630 100644
--- a/runtime/lua/vim/_meta.lua
+++ b/runtime/lua/vim/_meta.lua
@@ -398,7 +398,7 @@ end)()
--- Converts a vimoption_T style value to a Lua value
local convert_value_to_lua = (function()
- -- Map of OptionType to functions that take vimoption_T values and conver to lua values.
+ -- Map of OptionType to functions that take vimoption_T values and convert to lua values.
-- Each function takes (info, vim_value) -> lua_value
local to_lua_value = {
[OptionTypes.BOOLEAN] = function(_, value) return value end,
diff --git a/runtime/lua/vim/diagnostic.lua b/runtime/lua/vim/diagnostic.lua
index 191b9b9145..5c5631af98 100644
--- a/runtime/lua/vim/diagnostic.lua
+++ b/runtime/lua/vim/diagnostic.lua
@@ -36,7 +36,34 @@ M.handlers = setmetatable({}, {
end,
})
--- Local functions {{{
+-- Metatable that automatically creates an empty table when assigning to a missing key
+local bufnr_and_namespace_cacher_mt = {
+ __index = function(t, bufnr)
+ assert(bufnr > 0, "Invalid buffer number")
+ t[bufnr] = {}
+ return t[bufnr]
+ end,
+}
+
+local diagnostic_cache = setmetatable({}, {
+ __index = function(t, bufnr)
+ assert(bufnr > 0, "Invalid buffer number")
+ vim.api.nvim_buf_attach(bufnr, false, {
+ on_detach = function()
+ rawset(t, bufnr, nil) -- clear cache
+ end
+ })
+ t[bufnr] = {}
+ return t[bufnr]
+ end,
+})
+
+local diagnostic_cache_extmarks = setmetatable({}, bufnr_and_namespace_cacher_mt)
+local diagnostic_attached_buffers = {}
+local diagnostic_disabled = {}
+local bufs_waiting_to_update = setmetatable({}, bufnr_and_namespace_cacher_mt)
+
+local all_namespaces = {}
---@private
local function to_severity(severity)
@@ -106,8 +133,6 @@ local function reformat_diagnostics(format, diagnostics)
return formatted
end
-local all_namespaces = {}
-
---@private
local function enabled_value(option, namespace)
local ns = namespace and M.get_namespace(namespace) or {}
@@ -213,36 +238,6 @@ local function get_bufnr(bufnr)
return bufnr
end
--- Metatable that automatically creates an empty table when assigning to a missing key
-local bufnr_and_namespace_cacher_mt = {
- __index = function(t, bufnr)
- if not bufnr or bufnr == 0 then
- bufnr = vim.api.nvim_get_current_buf()
- end
-
- if rawget(t, bufnr) == nil then
- rawset(t, bufnr, {})
- end
-
- return rawget(t, bufnr)
- end,
-
- __newindex = function(t, bufnr, v)
- if not bufnr or bufnr == 0 then
- bufnr = vim.api.nvim_get_current_buf()
- end
-
- rawset(t, bufnr, v)
- end,
-}
-
-local diagnostic_cleanup = setmetatable({}, bufnr_and_namespace_cacher_mt)
-local diagnostic_cache = setmetatable({}, bufnr_and_namespace_cacher_mt)
-local diagnostic_cache_extmarks = setmetatable({}, bufnr_and_namespace_cacher_mt)
-local diagnostic_attached_buffers = {}
-local diagnostic_disabled = {}
-local bufs_waiting_to_update = setmetatable({}, bufnr_and_namespace_cacher_mt)
-
---@private
local function is_disabled(namespace, bufnr)
local ns = M.get_namespace(namespace)
@@ -287,11 +282,6 @@ local function set_diagnostic_cache(namespace, bufnr, diagnostics)
end
---@private
-local function clear_diagnostic_cache(namespace, bufnr)
- diagnostic_cache[bufnr][namespace] = nil
-end
-
----@private
local function restore_extmarks(bufnr, last)
for ns, extmarks in pairs(diagnostic_cache_extmarks[bufnr]) do
local extmarks_current = vim.api.nvim_buf_get_extmarks(bufnr, ns, 0, -1, {details = true})
@@ -377,6 +367,71 @@ local function clear_scheduled_display(namespace, bufnr)
end
---@private
+local function get_diagnostics(bufnr, opts, clamp)
+ opts = opts or {}
+
+ local namespace = opts.namespace
+ local diagnostics = {}
+
+ -- Memoized results of buf_line_count per bufnr
+ local buf_line_count = setmetatable({}, {
+ __index = function(t, k)
+ t[k] = vim.api.nvim_buf_line_count(k)
+ return rawget(t, k)
+ end,
+ })
+
+ ---@private
+ local function add(b, d)
+ if not opts.lnum or d.lnum == opts.lnum then
+ if clamp and vim.api.nvim_buf_is_loaded(b) then
+ local line_count = buf_line_count[b] - 1
+ if (d.lnum > line_count or d.end_lnum > line_count) then
+ d = vim.deepcopy(d)
+ d.lnum = math.max(math.min(d.lnum, line_count), 0)
+ d.end_lnum = math.max(math.min(d.end_lnum, line_count), 0)
+ end
+ end
+ table.insert(diagnostics, d)
+ end
+ end
+
+ if namespace == nil and bufnr == nil then
+ for b, t in pairs(diagnostic_cache) do
+ for _, v in pairs(t) do
+ for _, diagnostic in pairs(v) do
+ add(b, diagnostic)
+ end
+ end
+ end
+ elseif namespace == nil then
+ bufnr = get_bufnr(bufnr)
+ for iter_namespace in pairs(diagnostic_cache[bufnr]) do
+ for _, diagnostic in pairs(diagnostic_cache[bufnr][iter_namespace]) do
+ add(bufnr, diagnostic)
+ end
+ end
+ elseif bufnr == nil then
+ for b, t in pairs(diagnostic_cache) do
+ for _, diagnostic in pairs(t[namespace] or {}) do
+ add(b, diagnostic)
+ end
+ end
+ else
+ bufnr = get_bufnr(bufnr)
+ for _, diagnostic in pairs(diagnostic_cache[bufnr][namespace] or {}) do
+ add(bufnr, diagnostic)
+ end
+ end
+
+ if opts.severity then
+ diagnostics = filter_by_severity(opts.severity, diagnostics)
+ end
+
+ return diagnostics
+end
+
+---@private
local function set_list(loclist, opts)
opts = opts or {}
local open = vim.F.if_nil(opts.open, true)
@@ -386,7 +441,9 @@ local function set_list(loclist, opts)
if loclist then
bufnr = vim.api.nvim_win_get_buf(winnr)
end
- local diagnostics = M.get(bufnr, opts)
+ -- Don't clamp line numbers since the quickfix list can already handle line
+ -- numbers beyond the end of the buffer
+ local diagnostics = get_diagnostics(bufnr, opts, false)
local items = M.toqflist(diagnostics)
if loclist then
vim.fn.setloclist(winnr, {}, ' ', { title = title, items = items })
@@ -399,27 +456,12 @@ local function set_list(loclist, opts)
end
---@private
---- To (slightly) improve performance, modifies diagnostics in place.
-local function clamp_line_numbers(bufnr, diagnostics)
- local buf_line_count = vim.api.nvim_buf_line_count(bufnr)
- if buf_line_count == 0 then
- return
- end
-
- for _, diagnostic in ipairs(diagnostics) do
- diagnostic.lnum = math.max(math.min(diagnostic.lnum, buf_line_count - 1), 0)
- diagnostic.end_lnum = math.max(math.min(diagnostic.end_lnum, buf_line_count - 1), 0)
- end
-end
-
----@private
local function next_diagnostic(position, search_forward, bufnr, opts, namespace)
position[1] = position[1] - 1
bufnr = get_bufnr(bufnr)
local wrap = vim.F.if_nil(opts.wrap, true)
local line_count = vim.api.nvim_buf_line_count(bufnr)
- local diagnostics = M.get(bufnr, vim.tbl_extend("keep", opts, {namespace = namespace}))
- clamp_line_numbers(bufnr, diagnostics)
+ local diagnostics = get_diagnostics(bufnr, vim.tbl_extend("keep", opts, {namespace = namespace}), true)
local line_diagnostics = diagnostic_lines(diagnostics)
for i = 0, line_count do
local offset = i * (search_forward and 1 or -1)
@@ -431,13 +473,14 @@ local function next_diagnostic(position, search_forward, bufnr, opts, namespace)
lnum = (lnum + line_count) % line_count
end
if line_diagnostics[lnum] and not vim.tbl_isempty(line_diagnostics[lnum]) then
+ local line_length = #vim.api.nvim_buf_get_lines(bufnr, lnum, lnum + 1, true)[1]
local sort_diagnostics, is_next
if search_forward then
sort_diagnostics = function(a, b) return a.col < b.col end
- is_next = function(diagnostic) return diagnostic.col > position[2] end
+ is_next = function(d) return math.min(d.col, line_length - 1) > position[2] end
else
sort_diagnostics = function(a, b) return a.col > b.col end
- is_next = function(diagnostic) return diagnostic.col < position[2] end
+ is_next = function(d) return math.min(d.col, line_length - 1) < position[2] end
end
table.sort(line_diagnostics[lnum], sort_diagnostics)
if i == 0 then
@@ -475,16 +518,15 @@ local function diagnostic_move_pos(opts, pos)
vim.schedule(function()
M.open_float(
vim.api.nvim_win_get_buf(win_id),
- vim.tbl_extend("keep", float_opts, {scope="cursor"})
+ vim.tbl_extend("keep", float_opts, {
+ scope = "cursor",
+ focus = false,
+ })
)
end)
end
end
--- }}}
-
--- Public API {{{
-
--- Configure diagnostic options globally or for a specific diagnostic
--- namespace.
---
@@ -537,26 +579,7 @@ end
--- * priority: (number, default 10) Base priority to use for signs. When
--- {severity_sort} is used, the priority of a sign is adjusted based on
--- its severity. Otherwise, all signs use the same priority.
---- - float: Options for floating windows:
---- * severity: See |diagnostic-severity|.
---- * header: (string or table) String to use as the header for the floating
---- window. If a table, it is interpreted as a [text, hl_group] tuple.
---- Defaults to "Diagnostics:".
---- * source: (string) Include the diagnostic source in
---- the message. One of "always" or "if_many".
---- * format: (function) A function that takes a diagnostic as input and returns a
---- string. The return value is the text used to display the diagnostic.
---- * prefix: (function, string, or table) Prefix each diagnostic in the floating
---- window. If a function, it must have the signature (diagnostic, i,
---- total) -> (string, string), where {i} is the index of the diagnostic
---- being evaluated and {total} is the total number of diagnostics
---- displayed in the window. The function should return a string which
---- is prepended to each diagnostic in the window as well as an
---- (optional) highlight group which will be used to highlight the
---- prefix. If {prefix} is a table, it is interpreted as a [text,
---- hl_group] tuple as in |nvim_echo()|; otherwise, if {prefix} is a
---- string, it is prepended to each diagnostic in the window with no
---- highlight.
+--- - float: Options for floating windows. See |vim.diagnostic.open_float()|.
--- - update_in_insert: (default false) Update diagnostics in Insert mode (if false,
--- diagnostics are updated on InsertLeave)
--- - severity_sort: (default false) Sort diagnostics by severity. This affects the order in
@@ -564,6 +587,7 @@ end
--- are displayed before lower severities (e.g. ERROR is displayed before WARN).
--- Options:
--- * reverse: (boolean) Reverse sort order
+---
---@param namespace number|nil Update the options for the given namespace. When omitted, update the
--- global diagnostic options.
function M.config(opts, namespace)
@@ -617,33 +641,26 @@ function M.set(namespace, bufnr, diagnostics, opts)
opts = {opts, 't', true},
}
+ bufnr = get_bufnr(bufnr)
+
if vim.tbl_isempty(diagnostics) then
- clear_diagnostic_cache(namespace, bufnr)
+ diagnostic_cache[bufnr][namespace] = nil
else
- if not diagnostic_cleanup[bufnr][namespace] then
- diagnostic_cleanup[bufnr][namespace] = true
-
- -- Clean up our data when the buffer unloads.
- vim.api.nvim_buf_attach(bufnr, false, {
- on_detach = function(_, b)
- clear_diagnostic_cache(namespace, b)
- diagnostic_cleanup[b][namespace] = nil
- end
- })
- end
set_diagnostic_cache(namespace, bufnr, diagnostics)
end
if vim.api.nvim_buf_is_loaded(bufnr) then
- M.show(namespace, bufnr, diagnostics, opts)
+ M.show(namespace, bufnr, nil, opts)
end
- vim.api.nvim_command("doautocmd <nomodeline> User DiagnosticsChanged")
+ vim.api.nvim_command(
+ string.format("doautocmd <nomodeline> DiagnosticChanged %s", vim.api.nvim_buf_get_name(bufnr))
+ )
end
--- Get namespace metadata.
---
----@param ns number Diagnostic namespace
+---@param namespace number Diagnostic namespace
---@return table Namespace metadata
function M.get_namespace(namespace)
vim.validate { namespace = { namespace, 'n' } }
@@ -689,49 +706,7 @@ function M.get(bufnr, opts)
opts = { opts, 't', true },
}
- opts = opts or {}
-
- local namespace = opts.namespace
- local diagnostics = {}
-
- ---@private
- local function add(d)
- if not opts.lnum or d.lnum == opts.lnum then
- table.insert(diagnostics, d)
- end
- end
-
- if namespace == nil and bufnr == nil then
- for _, t in pairs(diagnostic_cache) do
- for _, v in pairs(t) do
- for _, diagnostic in pairs(v) do
- add(diagnostic)
- end
- end
- end
- elseif namespace == nil then
- for iter_namespace in pairs(diagnostic_cache[bufnr]) do
- for _, diagnostic in pairs(diagnostic_cache[bufnr][iter_namespace]) do
- add(diagnostic)
- end
- end
- elseif bufnr == nil then
- for _, t in pairs(diagnostic_cache) do
- for _, diagnostic in pairs(t[namespace] or {}) do
- add(diagnostic)
- end
- end
- else
- for _, diagnostic in pairs(diagnostic_cache[bufnr][namespace] or {}) do
- add(diagnostic)
- end
- end
-
- if opts.severity then
- diagnostics = filter_by_severity(opts.severity, diagnostics)
- end
-
- return diagnostics
+ return get_diagnostics(bufnr, opts, false)
end
--- Get the previous diagnostic closest to the cursor position.
@@ -807,7 +782,9 @@ end
--- - severity: See |diagnostic-severity|.
--- - float: (boolean or table, default true) If "true", call |vim.diagnostic.open_float()|
--- after moving. If a table, pass the table as the {opts} parameter to
---- |vim.diagnostic.open_float()|.
+--- |vim.diagnostic.open_float()|. Unless overridden, the float will show
+--- diagnostics at the new cursor position (as if "cursor" were passed to
+--- the "scope" option).
--- - win_id: (number, default 0) Window ID
function M.goto_next(opts)
return diagnostic_move_pos(
@@ -1115,7 +1092,7 @@ function M.show(namespace, bufnr, diagnostics, opts)
M.hide(namespace, bufnr)
- diagnostics = diagnostics or M.get(bufnr, {namespace=namespace})
+ diagnostics = diagnostics or get_diagnostics(bufnr, {namespace=namespace}, true)
if not diagnostics or vim.tbl_isempty(diagnostics) then
return
@@ -1141,8 +1118,6 @@ function M.show(namespace, bufnr, diagnostics, opts)
end
end
- clamp_line_numbers(bufnr, diagnostics)
-
for handler_name, handler in pairs(M.handlers) do
if handler.show and opts[handler_name] then
handler.show(namespace, bufnr, diagnostics, opts)
@@ -1156,7 +1131,7 @@ end
---@param opts table|nil Configuration table with the same keys as
--- |vim.lsp.util.open_floating_preview()| in addition to the following:
--- - namespace: (number) Limit diagnostics to the given namespace
---- - scope: (string, default "buffer") Show diagnostics from the whole buffer ("buffer"),
+--- - scope: (string, default "line") Show diagnostics from the whole buffer ("buffer"),
--- the current cursor line ("line"), or the current cursor position ("cursor").
--- - pos: (number or table) If {scope} is "line" or "cursor", use this position rather
--- than the cursor position. If a number, interpreted as a line number;
@@ -1173,7 +1148,17 @@ end
--- - format: (function) A function that takes a diagnostic as input and returns a
--- string. The return value is the text used to display the diagnostic.
--- Overrides the setting from |vim.diagnostic.config()|.
---- - prefix: (function, string, or table) Prefix each diagnostic in the floating window.
+--- - prefix: (function, string, or table) Prefix each diagnostic in the floating
+--- window. If a function, it must have the signature (diagnostic, i,
+--- total) -> (string, string), where {i} is the index of the diagnostic
+--- being evaluated and {total} is the total number of diagnostics
+--- displayed in the window. The function should return a string which
+--- is prepended to each diagnostic in the window as well as an
+--- (optional) highlight group which will be used to highlight the
+--- prefix. If {prefix} is a table, it is interpreted as a [text,
+--- hl_group] tuple as in |nvim_echo()|; otherwise, if {prefix} is a
+--- string, it is prepended to each diagnostic in the window with no
+--- highlight.
--- Overrides the setting from |vim.diagnostic.config()|.
---@return tuple ({float_bufnr}, {win_id})
function M.open_float(bufnr, opts)
@@ -1184,7 +1169,7 @@ function M.open_float(bufnr, opts)
opts = opts or {}
bufnr = get_bufnr(bufnr)
- local scope = opts.scope or "buffer"
+ local scope = opts.scope or "line"
local lnum, col
if scope == "line" or scope == "cursor" then
if not opts.pos then
@@ -1213,8 +1198,7 @@ function M.open_float(bufnr, opts)
opts = get_resolved_options({ float = float_opts }, nil, bufnr).float
end
- local diagnostics = M.get(bufnr, opts)
- clamp_line_numbers(bufnr, diagnostics)
+ local diagnostics = get_diagnostics(bufnr, opts, true)
if scope == "line" then
diagnostics = vim.tbl_filter(function(d)
@@ -1334,16 +1318,18 @@ function M.reset(namespace, bufnr)
bufnr = {bufnr, 'n', true},
}
- local buffers = bufnr and {bufnr} or vim.tbl_keys(diagnostic_cache)
+ local buffers = bufnr and {get_bufnr(bufnr)} or vim.tbl_keys(diagnostic_cache)
for _, iter_bufnr in ipairs(buffers) do
local namespaces = namespace and {namespace} or vim.tbl_keys(diagnostic_cache[iter_bufnr])
for _, iter_namespace in ipairs(namespaces) do
- clear_diagnostic_cache(iter_namespace, iter_bufnr)
+ diagnostic_cache[iter_bufnr][iter_namespace] = nil
M.hide(iter_namespace, iter_bufnr)
end
end
- vim.api.nvim_command("doautocmd <nomodeline> User DiagnosticsChanged")
+ vim.api.nvim_command(
+ string.format("doautocmd <nomodeline> DiagnosticChanged %s", vim.api.nvim_buf_get_name(bufnr))
+ )
end
--- Add all diagnostics to the quickfix list.
@@ -1545,7 +1531,7 @@ function M.fromqflist(list)
for _, item in ipairs(list) do
if item.valid == 1 then
local lnum = math.max(0, item.lnum - 1)
- local col = item.col > 0 and (item.col - 1) or nil
+ local col = math.max(0, item.col - 1)
local end_lnum = item.end_lnum > 0 and (item.end_lnum - 1) or lnum
local end_col = item.end_col > 0 and (item.end_col - 1) or col
local severity = item.type ~= "" and M.severity[item.type] or M.severity.ERROR
@@ -1563,6 +1549,4 @@ function M.fromqflist(list)
return diagnostics
end
--- }}}
-
return M
diff --git a/runtime/lua/vim/lsp.lua b/runtime/lua/vim/lsp.lua
index 0fc0a7a7aa..61a700bd15 100644
--- a/runtime/lua/vim/lsp.lua
+++ b/runtime/lua/vim/lsp.lua
@@ -115,6 +115,13 @@ local format_line_ending = {
["mac"] = '\r',
}
+---@private
+---@param bufnr (number)
+---@returns (string)
+local function buf_get_line_ending(bufnr)
+ return format_line_ending[nvim_buf_get_option(bufnr, 'fileformat')] or '\n'
+end
+
local client_index = 0
---@private
--- Returns a new, unused client id.
@@ -130,12 +137,6 @@ local all_buffer_active_clients = {}
local uninitialized_clients = {}
---@private
---- Invokes a function for each LSP client attached to the buffer {bufnr}.
----
----@param bufnr (Number) of buffer
----@param fn (function({client}, {client_id}, {bufnr}) Function to run on
----each client attached to that buffer.
----@param restrict_client_ids table list of client ids on which to restrict function application.
local function for_each_buffer_client(bufnr, fn, restrict_client_ids)
validate {
fn = { fn, 'f' };
@@ -236,7 +237,6 @@ local function validate_client_config(config)
config = { config, 't' };
}
validate {
- root_dir = { config.root_dir, optional_validator(is_dir), "directory" };
handlers = { config.handlers, "t", true };
capabilities = { config.capabilities, "t", true };
cmd_cwd = { config.cmd_cwd, optional_validator(is_dir), "directory" };
@@ -278,9 +278,10 @@ end
---@param bufnr (number) Buffer handle, or 0 for current.
---@returns Buffer text as string.
local function buf_get_full_text(bufnr)
- local text = table.concat(nvim_buf_get_lines(bufnr, 0, -1, true), '\n')
+ local line_ending = buf_get_line_ending(bufnr)
+ local text = table.concat(nvim_buf_get_lines(bufnr, 0, -1, true), line_ending)
if nvim_buf_get_option(bufnr, 'eol') then
- text = text .. '\n'
+ text = text .. line_ending
end
return text
end
@@ -313,12 +314,14 @@ do
---
--- state
--- pending_change?: function that the timer starts to trigger didChange
- --- pending_changes: list of tables with the pending changesets; for incremental_sync only
+ --- pending_changes: table (uri -> list of pending changeset tables));
+ -- Only set if incremental_sync is used
--- use_incremental_sync: bool
--- buffers?: table (bufnr → lines); for incremental sync only
--- timer?: uv_timer
local state_by_client = {}
+ ---@private
function changetracking.init(client, bufnr)
local state = state_by_client[client.id]
if not state then
@@ -340,16 +343,16 @@ do
state.buffers[bufnr] = nvim_buf_get_lines(bufnr, 0, -1, true)
end
+ ---@private
function changetracking.reset_buf(client, bufnr)
+ changetracking.flush(client)
local state = state_by_client[client.id]
- if state then
- changetracking._reset_timer(state)
- if state.buffers then
- state.buffers[bufnr] = nil
- end
+ if state and state.buffers then
+ state.buffers[bufnr] = nil
end
end
+ ---@private
function changetracking.reset(client_id)
local state = state_by_client[client_id]
if state then
@@ -358,13 +361,14 @@ do
end
end
- function changetracking.prepare(bufnr, firstline, lastline, new_lastline, changedtick)
+ ---@private
+ function changetracking.prepare(bufnr, firstline, lastline, new_lastline)
local incremental_changes = function(client)
local cached_buffers = state_by_client[client.id].buffers
local curr_lines = nvim_buf_get_lines(bufnr, 0, -1, true)
- local line_ending = format_line_ending[vim.api.nvim_buf_get_option(0, 'fileformat')]
+ local line_ending = buf_get_line_ending(bufnr)
local incremental_change = sync.compute_diff(
- cached_buffers[bufnr], curr_lines, firstline, lastline, new_lastline, client.offset_encoding or 'utf-16', line_ending or '\n')
+ cached_buffers[bufnr], curr_lines, firstline, lastline, new_lastline, client.offset_encoding or 'utf-16', line_ending)
cached_buffers[bufnr] = curr_lines
return incremental_change
end
@@ -385,7 +389,7 @@ do
client.notify("textDocument/didChange", {
textDocument = {
uri = uri;
- version = changedtick;
+ version = util.buf_versions[bufnr];
};
contentChanges = { changes, }
})
@@ -395,27 +399,36 @@ do
if state.use_incremental_sync then
-- This must be done immediately and cannot be delayed
-- The contents would further change and startline/endline may no longer fit
- table.insert(state.pending_changes, incremental_changes(client))
+ if not state.pending_changes[uri] then
+ state.pending_changes[uri] = {}
+ end
+ table.insert(state.pending_changes[uri], incremental_changes(client))
end
state.pending_change = function()
state.pending_change = nil
if client.is_stopped() or not vim.api.nvim_buf_is_valid(bufnr) then
return
end
- local contentChanges
if state.use_incremental_sync then
- contentChanges = state.pending_changes
+ for change_uri, content_changes in pairs(state.pending_changes) do
+ client.notify("textDocument/didChange", {
+ textDocument = {
+ uri = change_uri;
+ version = util.buf_versions[vim.uri_to_bufnr(change_uri)];
+ };
+ contentChanges = content_changes,
+ })
+ end
state.pending_changes = {}
else
- contentChanges = { full_changes(), }
+ client.notify("textDocument/didChange", {
+ textDocument = {
+ uri = uri;
+ version = util.buf_versions[bufnr];
+ };
+ contentChanges = { full_changes() },
+ })
end
- client.notify("textDocument/didChange", {
- textDocument = {
- uri = uri;
- version = changedtick;
- };
- contentChanges = contentChanges
- })
end
state.timer = vim.loop.new_timer()
-- Must use schedule_wrap because `full_changes()` calls nvim_buf_get_lines
@@ -432,6 +445,7 @@ do
end
--- Flushes any outstanding change notification.
+ ---@private
function changetracking.flush(client)
local state = state_by_client[client.id]
if state then
@@ -566,12 +580,10 @@ end
--
--- Starts and initializes a client with the given configuration.
---
---- Parameters `cmd` and `root_dir` are required.
+--- Parameter `cmd` is required.
---
--- The following parameters describe fields in the {config} table.
---
----@param root_dir: (string) Directory where the LSP server will base
---- its rootUri on initialization.
---
---@param cmd: (required, string or list treated like |jobstart()|) Base command
--- that initiates the LSP client.
@@ -587,6 +599,11 @@ end
--- { "PRODUCTION=true"; "TEST=123"; PORT = 8080; HOST = "0.0.0.0"; }
--- </pre>
---
+---@param workspace_folders (table) List of workspace folders passed to the
+--- language server. For backwards compatibility rootUri and rootPath will be
+--- derived from the first workspace folder in this list. See `workspaceFolders` in
+--- the LSP spec.
+---
---@param capabilities Map overriding the default capabilities defined by
--- |vim.lsp.protocol.make_client_capabilities()|, passed to the language
--- server on initialization. Hint: use make_client_capabilities() and modify
@@ -603,17 +620,13 @@ end
---
---@param commands table Table that maps string of clientside commands to user-defined functions.
--- Commands passed to start_client take precedence over the global command registry. Each key
---- must be a unique comand name, and the value is a function which is called if any LSP action
+--- must be a unique command name, and the value is a function which is called if any LSP action
--- (code action, code lenses, ...) triggers the command.
---
---@param init_options Values to pass in the initialization request
--- as `initializationOptions`. See `initialize` in the LSP spec.
---
---@param name (string, default=client-id) Name in log messages.
---
----@param workspace_folders (table) List of workspace folders passed to the
---- language server. Defaults to root_dir if not set. See `workspaceFolders` in
---- the LSP spec
---
---@param get_language_id function(bufnr, filetype) -> language ID as string.
--- Defaults to the filetype.
@@ -661,8 +674,13 @@ end
--- notifications to the server by the given number in milliseconds. No debounce
--- occurs if nil
--- - exit_timeout (number, default 500): Milliseconds to wait for server to
--- exit cleanly after sending the 'shutdown' request before sending kill -15.
--- If set to false, nvim exits immediately after sending the 'shutdown' request to the server.
+--- exit cleanly after sending the 'shutdown' request before sending kill -15.
+--- If set to false, nvim exits immediately after sending the 'shutdown' request to the server.
+---
+---@param root_dir string Directory where the LSP
+--- server will base its workspaceFolders, rootUri, and rootPath
+--- on initialization.
+---
---@returns Client id. |vim.lsp.get_client_by_id()| Note: client may not be
--- fully initialized. Use `on_init` to do any actions once
--- the client has been initialized.
@@ -779,6 +797,9 @@ function lsp.start_client(config)
env = config.cmd_env;
})
+ -- Return nil if client fails to start
+ if not rpc then return end
+
local client = {
id = client_id;
name = name;
@@ -805,11 +826,24 @@ function lsp.start_client(config)
}
local version = vim.version()
- if config.root_dir and not config.workspace_folders then
- config.workspace_folders = {{
- uri = vim.uri_from_fname(config.root_dir);
- name = string.format("%s", config.root_dir);
- }};
+ local workspace_folders
+ local root_uri
+ local root_path
+ if config.workspace_folders or config.root_dir then
+ if config.root_dir and not config.workspace_folders then
+ workspace_folders = {{
+ uri = vim.uri_from_fname(config.root_dir);
+ name = string.format("%s", config.root_dir);
+ }};
+ else
+ workspace_folders = config.workspace_folders
+ end
+ root_uri = workspace_folders[1].uri
+ root_path = vim.uri_to_fname(root_uri)
+ else
+ workspace_folders = nil
+ root_uri = nil
+ root_path = nil
end
local initialize_params = {
@@ -827,10 +861,15 @@ function lsp.start_client(config)
-- The rootPath of the workspace. Is null if no folder is open.
--
-- @deprecated in favour of rootUri.
- rootPath = config.root_dir;
+ rootPath = root_path or vim.NIL;
-- The rootUri of the workspace. Is null if no folder is open. If both
-- `rootPath` and `rootUri` are set `rootUri` wins.
- rootUri = config.root_dir and vim.uri_from_fname(config.root_dir);
+ rootUri = root_uri or vim.NIL;
+ -- The workspace folders configured in the client when the server starts.
+ -- This property is only available if the client supports workspace folders.
+ -- It can be `null` if the client supports workspace folders but none are
+ -- configured.
+ workspaceFolders = workspace_folders or vim.NIL;
-- User provided initialization options.
initializationOptions = config.init_options;
-- The capabilities provided by the client (editor or tool)
@@ -838,21 +877,6 @@ function lsp.start_client(config)
-- The initial trace setting. If omitted trace is disabled ("off").
-- trace = "off" | "messages" | "verbose";
trace = valid_traces[config.trace] or 'off';
- -- The workspace folders configured in the client when the server starts.
- -- This property is only available if the client supports workspace folders.
- -- It can be `null` if the client supports workspace folders but none are
- -- configured.
- --
- -- Since 3.6.0
- -- workspaceFolders?: WorkspaceFolder[] | null;
- -- export interface WorkspaceFolder {
- -- -- The associated URI for this workspace folder.
- -- uri
- -- -- The name of the workspace folder. Used to refer to this
- -- -- workspace folder in the user interface.
- -- name
- -- }
- workspaceFolders = config.workspace_folders,
}
if config.before_init then
-- TODO(ashkan) handle errors here.
@@ -865,7 +889,9 @@ function lsp.start_client(config)
rpc.notify('initialized', vim.empty_dict())
client.initialized = true
uninitialized_clients[client_id] = nil
- client.workspaceFolders = initialize_params.workspaceFolders
+ client.workspace_folders = workspace_folders
+ -- TODO(mjlbach): Backwards compatbility, to be removed in 0.7
+ client.workspaceFolders = client.workspace_folders
client.server_capabilities = assert(result.capabilities, "initialize result doesn't contain capabilities")
-- These are the cleaned up capabilities we use for dynamically deciding
-- when to send certain events to clients.
@@ -1007,7 +1033,7 @@ function lsp.start_client(config)
return rpc.notify("$/cancelRequest", { id = id })
end
- -- Track this so that we can escalate automatically if we've alredy tried a
+ -- Track this so that we can escalate automatically if we've already tried a
-- graceful shutdown
local graceful_shutdown_failed = false
---@private
@@ -1084,7 +1110,7 @@ do
return
end
util.buf_versions[bufnr] = changedtick
- local compute_change_and_notify = changetracking.prepare(bufnr, firstline, lastline, new_lastline, changedtick)
+ local compute_change_and_notify = changetracking.prepare(bufnr, firstline, lastline, new_lastline)
for_each_buffer_client(bufnr, compute_change_and_notify)
end
end
@@ -1143,6 +1169,7 @@ function lsp.buf_attach_client(bufnr, client_id)
on_reload = function()
local params = { textDocument = { uri = uri; } }
for_each_buffer_client(bufnr, function(client, _)
+ changetracking.reset_buf(client, bufnr)
if client.resolved_capabilities.text_document_open_close then
client.notify('textDocument/didClose', params)
end
@@ -1152,10 +1179,10 @@ function lsp.buf_attach_client(bufnr, client_id)
on_detach = function()
local params = { textDocument = { uri = uri; } }
for_each_buffer_client(bufnr, function(client, _)
+ changetracking.reset_buf(client, bufnr)
if client.resolved_capabilities.text_document_open_close then
client.notify('textDocument/didClose', params)
end
- changetracking.reset_buf(client, bufnr)
end)
util.buf_versions[bufnr] = nil
all_buffer_active_clients[bufnr] = nil
@@ -1190,7 +1217,7 @@ end
--- Gets a client by id, or nil if the id is invalid.
--- The returned client may not yet be fully initialized.
---
+---
---@param client_id number client id
---
---@returns |vim.lsp.client| object, or nil
@@ -1199,7 +1226,7 @@ function lsp.get_client_by_id(client_id)
end
--- Returns list of buffers attached to client_id.
---
+---
---@param client_id number client id
---@returns list of buffer ids
function lsp.get_buffers_by_client_id(client_id)
@@ -1269,6 +1296,7 @@ function lsp._vim_exit_handler()
local poll_time = 50
+ ---@private
local function check_clients_closed()
for client_id, timeout in pairs(timeouts) do
timeouts[client_id] = timeout - poll_time
@@ -1303,8 +1331,8 @@ nvim_command("autocmd VimLeavePre * lua vim.lsp._vim_exit_handler()")
---@param method (string) LSP method name
---@param params (optional, table) Parameters to send to the server
---@param handler (optional, function) See |lsp-handler|
--- If nil, follows resolution strategy defined in |lsp-handler-configuration|
---
+--- If nil, follows resolution strategy defined in |lsp-handler-configuration|
+---
---@returns 2-tuple:
--- - Map of client-id:request-id pairs for all successful requests.
--- - Function which can be used to cancel all the requests. You could instead
@@ -1587,6 +1615,21 @@ function lsp.formatexpr(opts)
return 0
end
+--- Provides an interface between the built-in client and 'tagfunc'.
+---
+--- When used with normal mode commands (e.g. |CTRL-]|) this will invoke
+--- the "textDocument/definition" LSP method to find the tag under the cursor.
+--- Otherwise, uses "workspace/symbol". If no results are returned from
+--- any LSP servers, falls back to using built-in tags.
+---
+---@param pattern Pattern used to find a workspace symbol
+---@param flags See |tag-function|
+---
+---@returns A list of matching tags
+function lsp.tagfunc(...)
+ return require('vim.lsp.tagfunc')(...)
+end
+
---Checks whether a client is stopped.
---
---@param client_id (Number)
@@ -1640,7 +1683,17 @@ function lsp.get_log_path()
return log.get_filename()
end
---- Call {fn} for every client attached to {bufnr}
+--- Invokes a function for each LSP client attached to a buffer.
+---
+---@param bufnr number Buffer number
+---@param fn function Function to run on each client attached to buffer
+--- {bufnr}. The function takes the client, client ID, and
+--- buffer number as arguments. Example:
+--- <pre>
+--- vim.lsp.for_each_buffer_client(0, function(client, client_id, bufnr)
+--- print(vim.inspect(client))
+--- end)
+--- </pre>
function lsp.for_each_buffer_client(bufnr, fn)
return for_each_buffer_client(bufnr, fn)
end
@@ -1699,11 +1752,11 @@ end
--- using `workspace/executeCommand`.
---
--- The first argument to the function will be the `Command`:
--- Command
--- title: String
--- command: String
--- arguments?: any[]
---
+--- Command
+--- title: String
+--- command: String
+--- arguments?: any[]
+---
--- The second argument is the `ctx` of |lsp-handler|
lsp.commands = setmetatable({}, {
__newindex = function(tbl, key, value)
diff --git a/runtime/lua/vim/lsp/buf.lua b/runtime/lua/vim/lsp/buf.lua
index 747d761730..f02ebfb9dc 100644
--- a/runtime/lua/vim/lsp/buf.lua
+++ b/runtime/lua/vim/lsp/buf.lua
@@ -165,7 +165,7 @@ end
--- saved. {timeout_ms} is passed on to |vim.lsp.buf_request_sync()|. Example:
---
--- <pre>
---- vim.api.nvim_command[[autocmd BufWritePre <buffer> lua vim.lsp.buf.formatting_sync()]]
+--- autocmd BufWritePre <buffer> lua vim.lsp.buf.formatting_sync()
--- </pre>
---
---@param options Table with valid `FormattingOptions` entries
@@ -176,9 +176,10 @@ function M.formatting_sync(options, timeout_ms)
if client == nil then return end
local params = util.make_formatting_params(options)
- local result, err = client.request_sync("textDocument/formatting", params, timeout_ms, vim.api.nvim_get_current_buf())
+ local bufnr = vim.api.nvim_get_current_buf()
+ local result, err = client.request_sync("textDocument/formatting", params, timeout_ms, bufnr)
if result and result.result then
- util.apply_text_edits(result.result)
+ util.apply_text_edits(result.result, bufnr)
elseif err then
vim.notify("vim.lsp.buf.formatting_sync: " .. err, vim.log.levels.WARN)
end
@@ -202,6 +203,7 @@ end
---the remaining clients in the order as they occur in the `order` list.
function M.formatting_seq_sync(options, timeout_ms, order)
local clients = vim.tbl_values(vim.lsp.buf_get_clients());
+ local bufnr = vim.api.nvim_get_current_buf()
-- sort the clients according to `order`
for _, client_name in pairs(order or {}) do
@@ -220,7 +222,7 @@ function M.formatting_seq_sync(options, timeout_ms, order)
local params = util.make_formatting_params(options)
local result, err = client.request_sync("textDocument/formatting", params, timeout_ms, vim.api.nvim_get_current_buf())
if result and result.result then
- util.apply_text_edits(result.result)
+ util.apply_text_edits(result.result, bufnr)
elseif err then
vim.notify(string.format("vim.lsp.buf.formatting_seq_sync: (%s) %s", client.name, err), vim.log.levels.WARN)
end
@@ -261,6 +263,7 @@ function M.rename(new_name)
request('textDocument/rename', params)
end
+ ---@private
local function prepare_rename(err, result)
if err == nil and result == nil then
vim.notify('nothing to rename', vim.log.levels.INFO)
@@ -369,7 +372,7 @@ end
function M.list_workspace_folders()
local workspace_folders = {}
for _, client in pairs(vim.lsp.buf_get_clients()) do
- for _, folder in pairs(client.workspaceFolders or {}) do
+ for _, folder in pairs(client.workspace_folders or {}) do
table.insert(workspace_folders, folder.name)
end
end
@@ -389,7 +392,7 @@ function M.add_workspace_folder(workspace_folder)
local params = util.make_workspace_params({{uri = vim.uri_from_fname(workspace_folder); name = workspace_folder}}, {{}})
for _, client in pairs(vim.lsp.buf_get_clients()) do
local found = false
- for _, folder in pairs(client.workspaceFolders or {}) do
+ for _, folder in pairs(client.workspace_folders or {}) do
if folder.name == workspace_folder then
found = true
print(workspace_folder, "is already part of this workspace")
@@ -398,10 +401,10 @@ function M.add_workspace_folder(workspace_folder)
end
if not found then
vim.lsp.buf_notify(0, 'workspace/didChangeWorkspaceFolders', params)
- if not client.workspaceFolders then
- client.workspaceFolders = {}
+ if not client.workspace_folders then
+ client.workspace_folders = {}
end
- table.insert(client.workspaceFolders, params.event.added[1])
+ table.insert(client.workspace_folders, params.event.added[1])
end
end
end
@@ -415,10 +418,10 @@ function M.remove_workspace_folder(workspace_folder)
if not (workspace_folder and #workspace_folder > 0) then return end
local params = util.make_workspace_params({{}}, {{uri = vim.uri_from_fname(workspace_folder); name = workspace_folder}})
for _, client in pairs(vim.lsp.buf_get_clients()) do
- for idx, folder in pairs(client.workspaceFolders) do
+ for idx, folder in pairs(client.workspace_folders) do
if folder.name == workspace_folder then
vim.lsp.buf_notify(0, 'workspace/didChangeWorkspaceFolders', params)
- client.workspaceFolders[idx] = nil
+ client.workspace_folders[idx] = nil
return
end
end
@@ -444,9 +447,9 @@ end
--- by events such as `CursorHold`, eg:
---
--- <pre>
---- vim.api.nvim_command [[autocmd CursorHold <buffer> lua vim.lsp.buf.document_highlight()]]
---- vim.api.nvim_command [[autocmd CursorHoldI <buffer> lua vim.lsp.buf.document_highlight()]]
---- vim.api.nvim_command [[autocmd CursorMoved <buffer> lua vim.lsp.buf.clear_references()]]
+--- autocmd CursorHold <buffer> lua vim.lsp.buf.document_highlight()
+--- autocmd CursorHoldI <buffer> lua vim.lsp.buf.document_highlight()
+--- autocmd CursorMoved <buffer> lua vim.lsp.buf.clear_references()
--- </pre>
---
--- Note: Usage of |vim.lsp.buf.document_highlight()| requires the following highlight groups
diff --git a/runtime/lua/vim/lsp/diagnostic.lua b/runtime/lua/vim/lsp/diagnostic.lua
index 1e6f83c1ba..075da41b23 100644
--- a/runtime/lua/vim/lsp/diagnostic.lua
+++ b/runtime/lua/vim/lsp/diagnostic.lua
@@ -220,12 +220,9 @@ function M.on_publish_diagnostics(_, result, ctx, config)
end
vim.diagnostic.set(namespace, bufnr, diagnostic_lsp_to_vim(diagnostics, bufnr, client_id))
-
- -- Keep old autocmd for back compat. This should eventually be removed.
- vim.api.nvim_command("doautocmd <nomodeline> User LspDiagnosticsChanged")
end
---- Clear diagnotics and diagnostic cache.
+--- Clear diagnostics and diagnostic cache.
---
--- Diagnostic producers should prefer |vim.diagnostic.reset()|. However,
--- this method signature is still used internally in some parts of the LSP
@@ -434,24 +431,6 @@ end
--- Move to the next diagnostic
---
---@deprecated Prefer |vim.diagnostic.goto_next()|
----
----@param opts table|nil Configuration table. Keys:
---- - {client_id}: (number)
---- - If nil, will consider all clients attached to buffer.
---- - {cursor_position}: (Position, default current position)
---- - See |nvim_win_get_cursor()|
---- - {wrap}: (boolean, default true)
---- - Whether to loop around file or not. Similar to 'wrapscan'
---- - {severity}: (DiagnosticSeverity)
---- - Exclusive severity to consider. Overrides {severity_limit}
---- - {severity_limit}: (DiagnosticSeverity)
---- - Limit severity of diagnostics found. E.g. "Warning" means { "Error", "Warning" } will be valid.
---- - {enable_popup}: (boolean, default true)
---- - Call |vim.lsp.diagnostic.show_line_diagnostics()| on jump
---- - {popup_opts}: (table)
---- - Table to pass as {opts} parameter to |vim.lsp.diagnostic.show_line_diagnostics()|
---- - {win_id}: (number, default 0)
---- - Window ID
function M.goto_next(opts)
if opts then
if opts.severity then
@@ -565,7 +544,7 @@ end
--- Open a floating window with the diagnostics from {line_nr}
---
----@deprecated Prefer |vim.diagnostic.show_line_diagnostics()|
+---@deprecated Prefer |vim.diagnostic.open_float()|
---
---@param opts table Configuration table
--- - all opts for |vim.lsp.diagnostic.get_line_diagnostics()| and
@@ -717,5 +696,3 @@ end
-- }}}
return M
-
--- vim: fdm=marker
diff --git a/runtime/lua/vim/lsp/handlers.lua b/runtime/lua/vim/lsp/handlers.lua
index fa4f2b22a5..22089aaaa6 100644
--- a/runtime/lua/vim/lsp/handlers.lua
+++ b/runtime/lua/vim/lsp/handlers.lua
@@ -28,7 +28,7 @@ local function progress_handler(_, result, ctx, _)
local client_name = client and client.name or string.format("id=%d", client_id)
if not client then
err_message("LSP[", client_name, "] client has shut down after sending the message")
- return
+ return vim.NIL
end
local val = result.value -- unspecified yet
local token = result.token -- string or number
@@ -70,6 +70,7 @@ M['window/workDoneProgress/create'] = function(_, result, ctx)
local client_name = client and client.name or string.format("id=%d", client_id)
if not client then
err_message("LSP[", client_name, "] client has shut down after sending the message")
+ return vim.NIL
end
client.messages.progress[token] = {}
return vim.NIL
diff --git a/runtime/lua/vim/lsp/log.lua b/runtime/lua/vim/lsp/log.lua
index 4597f1919a..dbc473b52c 100644
--- a/runtime/lua/vim/lsp/log.lua
+++ b/runtime/lua/vim/lsp/log.lua
@@ -101,6 +101,7 @@ function log.set_level(level)
end
--- Gets the current log level.
+---@return string current log level
function log.get_level()
return current_log_level
end
diff --git a/runtime/lua/vim/lsp/rpc.lua b/runtime/lua/vim/lsp/rpc.lua
index bce1e9f35d..1fb75ddeb7 100644
--- a/runtime/lua/vim/lsp/rpc.lua
+++ b/runtime/lua/vim/lsp/rpc.lua
@@ -230,7 +230,7 @@ function default_dispatchers.on_error(code, err)
end
--- Starts an LSP server process and create an LSP RPC client object to
---- interact with it.
+--- interact with it. Communication with the server is currently limited to stdio.
---
---@param cmd (string) Command to start the LSP server.
---@param cmd_args (table) List of additional string arguments to pass to {cmd}.
@@ -264,8 +264,6 @@ local function start(cmd, cmd_args, dispatchers, extra_spawn_params)
if extra_spawn_params and extra_spawn_params.cwd then
assert(is_dir(extra_spawn_params.cwd), "cwd must be a directory")
- elseif not (vim.fn.executable(cmd) == 1) then
- error(string.format("The given command %q is not executable.", cmd))
end
if dispatchers then
local user_dispatchers = dispatchers
@@ -325,7 +323,14 @@ local function start(cmd, cmd_args, dispatchers, extra_spawn_params)
end
handle, pid = uv.spawn(cmd, spawn_params, onexit)
if handle == nil then
- error(string.format("start `%s` failed: %s", cmd, pid))
+ local msg = string.format("Spawning language server with cmd: `%s` failed", cmd)
+ if string.match(pid, "ENOENT") then
+ msg = msg .. ". The language server is either not installed, missing from PATH, or not executable."
+ else
+ msg = msg .. string.format(" with error message: %s", pid)
+ end
+ vim.notify(msg, vim.log.levels.WARN)
+ return
end
end
diff --git a/runtime/lua/vim/lsp/sync.lua b/runtime/lua/vim/lsp/sync.lua
index 585c14a00f..5df2a4d144 100644
--- a/runtime/lua/vim/lsp/sync.lua
+++ b/runtime/lua/vim/lsp/sync.lua
@@ -75,42 +75,45 @@ local function byte_to_utf(line, byte, offset_encoding)
end
---@private
+local function compute_line_length(line, offset_encoding)
+ local length
+ local _
+ if offset_encoding == 'utf-16' then
+ _, length = str_utfindex(line)
+ elseif offset_encoding == 'utf-32' then
+ length, _ = str_utfindex(line)
+ else
+ length = #line
+ end
+ return length
+end
+
+---@private
-- Given a line, byte idx, alignment, and offset_encoding convert to the aligned
-- utf-8 index and either the utf-16, or utf-32 index.
---@param line string the line to index into
---@param byte integer the byte idx
----@param align string when dealing with multibyte characters,
--- to choose the start of the current character or the beginning of the next.
--- Used for incremental sync for start/end range respectively
---@param offset_encoding string utf-8|utf-16|utf-32|nil (default: utf-8)
---@returns table<string, int> byte_idx and char_idx of first change position
-local function align_position(line, byte, align, offset_encoding)
+local function align_end_position(line, byte, offset_encoding)
local char
-- If on the first byte, or an empty string: the trivial case
if byte == 1 or #line == 0 then
char = byte
-- Called in the case of extending an empty line "" -> "a"
elseif byte == #line + 1 then
- byte = byte + str_utf_end(line, #line)
- char = byte_to_utf(line, byte, offset_encoding)
+ char = compute_line_length(line, offset_encoding) + 1
else
-- Modifying line, find the nearest utf codepoint
- if align == 'start' then
- byte = byte + str_utf_start(line, byte)
- char = byte_to_utf(line, byte, offset_encoding)
- elseif align == 'end' then
- local offset = str_utf_end(line, byte)
- -- If the byte does not fall on the start of the character, then
- -- align to the start of the next character.
- if offset > 0 then
- char = byte_to_utf(line, byte, offset_encoding) + 1
- byte = byte + offset
- else
- char = byte_to_utf(line, byte, offset_encoding)
- byte = byte + offset
- end
+ local offset = str_utf_end(line, byte)
+ -- If the byte does not fall on the start of the character, then
+ -- align to the start of the next character.
+ if offset > 0 then
+ char = byte_to_utf(line, byte, offset_encoding) + 1
+ byte = byte + offset
else
- error('`align` must be start or end.')
+ char = byte_to_utf(line, byte, offset_encoding)
+ byte = byte + offset
end
-- Extending line, find the nearest utf codepoint for the last valid character
end
@@ -131,7 +134,7 @@ local function compute_start_range(prev_lines, curr_lines, firstline, lastline,
-- occur on a new line pointed to by lastline. This occurs during insertion of
-- new lines(O), the new newline is inserted at the line indicated by
-- new_lastline.
- -- If firstline == new_lastline, the first change occured on a line that was deleted.
+ -- If firstline == new_lastline, the first change occurred on a line that was deleted.
-- In this case, the first byte change is also at the first byte of firstline
if firstline == new_lastline or firstline == lastline then
return { line_idx = firstline, byte_idx = 1, char_idx = 1 }
@@ -154,7 +157,18 @@ local function compute_start_range(prev_lines, curr_lines, firstline, lastline,
end
-- Convert byte to codepoint if applicable
- local byte_idx, char_idx = align_position(prev_line, start_byte_idx, 'start', offset_encoding)
+ local char_idx
+ local byte_idx
+ if start_byte_idx == 1 or (#prev_line == 0 and start_byte_idx == 1)then
+ byte_idx = start_byte_idx
+ char_idx = 1
+ elseif start_byte_idx == #prev_line + 1 then
+ byte_idx = start_byte_idx
+ char_idx = compute_line_length(prev_line, offset_encoding) + 1
+ else
+ byte_idx = start_byte_idx + str_utf_start(prev_line, start_byte_idx)
+ char_idx = byte_to_utf(prev_line, start_byte_idx, offset_encoding)
+ end
-- Return the start difference (shared for new and prev lines)
return { line_idx = firstline, byte_idx = byte_idx, char_idx = char_idx }
@@ -174,7 +188,7 @@ end
---@param offset_encoding string
---@returns (int, int) end_line_idx and end_col_idx of range
local function compute_end_range(prev_lines, curr_lines, start_range, firstline, lastline, new_lastline, offset_encoding)
- -- If firstline == new_lastline, the first change occured on a line that was deleted.
+ -- If firstline == new_lastline, the first change occurred on a line that was deleted.
-- In this case, the last_byte...
if firstline == new_lastline then
return { line_idx = (lastline - new_lastline + firstline), byte_idx = 1, char_idx = 1 }, { line_idx = firstline, byte_idx = 1, char_idx = 1 }
@@ -219,11 +233,12 @@ local function compute_end_range(prev_lines, curr_lines, start_range, firstline,
-- Iterate from end to beginning of shortest line
local prev_end_byte_idx = prev_line_length - byte_offset + 1
+
-- Handle case where lines match
if prev_end_byte_idx == 0 then
prev_end_byte_idx = 1
end
- local prev_byte_idx, prev_char_idx = align_position(prev_line, prev_end_byte_idx, 'start', offset_encoding)
+ local prev_byte_idx, prev_char_idx = align_end_position(prev_line, prev_end_byte_idx, offset_encoding)
local prev_end_range = { line_idx = prev_line_idx, byte_idx = prev_byte_idx, char_idx = prev_char_idx }
local curr_end_range
@@ -236,7 +251,7 @@ local function compute_end_range(prev_lines, curr_lines, start_range, firstline,
if curr_end_byte_idx == 0 then
curr_end_byte_idx = 1
end
- local curr_byte_idx, curr_char_idx = align_position(curr_line, curr_end_byte_idx, 'start', offset_encoding)
+ local curr_byte_idx, curr_char_idx = align_end_position(curr_line, curr_end_byte_idx, offset_encoding)
curr_end_range = { line_idx = curr_line_idx, byte_idx = curr_byte_idx, char_idx = curr_char_idx }
end
@@ -280,18 +295,6 @@ local function extract_text(lines, start_range, end_range, line_ending)
end
end
-local function compute_line_length(line, offset_encoding)
- local length
- local _
- if offset_encoding == 'utf-16' then
- _, length = str_utfindex(line)
- elseif offset_encoding == 'utf-32' then
- length, _ = str_utfindex(line)
- else
- length = #line
- end
- return length
-end
---@private
-- rangelength depends on the offset encoding
-- bytes for utf-8 (clangd with extenion)
diff --git a/runtime/lua/vim/lsp/tagfunc.lua b/runtime/lua/vim/lsp/tagfunc.lua
new file mode 100644
index 0000000000..5c55e8559f
--- /dev/null
+++ b/runtime/lua/vim/lsp/tagfunc.lua
@@ -0,0 +1,76 @@
+local lsp = vim.lsp
+local util = vim.lsp.util
+
+---@private
+local function mk_tag_item(name, range, uri, offset_encoding)
+ local bufnr = vim.uri_to_bufnr(uri)
+ -- This is get_line_byte_from_position is 0-indexed, call cursor expects a 1-indexed position
+ local byte = util._get_line_byte_from_position(bufnr, range.start, offset_encoding) + 1
+ return {
+ name = name,
+ filename = vim.uri_to_fname(uri),
+ cmd = string.format('call cursor(%d, %d)|', range.start.line + 1, byte),
+ }
+end
+
+---@private
+local function query_definition(pattern)
+ local params = lsp.util.make_position_params()
+ local results_by_client, err = lsp.buf_request_sync(0, 'textDocument/definition', params, 1000)
+ if err then
+ return {}
+ end
+ local results = {}
+ local add = function(range, uri, offset_encoding)
+ table.insert(results, mk_tag_item(pattern, range, uri, offset_encoding))
+ end
+ for client_id, lsp_results in pairs(results_by_client) do
+ local client = lsp.get_client_by_id(client_id)
+ local result = lsp_results.result or {}
+ if result.range then -- Location
+ add(result.range, result.uri)
+ else -- Location[] or LocationLink[]
+ for _, item in pairs(result) do
+ if item.range then -- Location
+ add(item.range, item.uri, client.offset_encoding)
+ else -- LocationLink
+ add(item.targetSelectionRange, item.targetUri, client.offset_encoding)
+ end
+ end
+ end
+ end
+ return results
+end
+
+---@private
+local function query_workspace_symbols(pattern)
+ local results_by_client, err = lsp.buf_request_sync(0, 'workspace/symbol', { query = pattern }, 1000)
+ if err then
+ return {}
+ end
+ local results = {}
+ for client_id, symbols in pairs(results_by_client) do
+ local client = lsp.get_client_by_id(client_id)
+ for _, symbol in pairs(symbols.result or {}) do
+ local loc = symbol.location
+ local item = mk_tag_item(symbol.name, loc.range, loc.uri, client.offset_encoding)
+ item.kind = lsp.protocol.SymbolKind[symbol.kind] or 'Unknown'
+ table.insert(results, item)
+ end
+ end
+ return results
+end
+
+---@private
+local function tagfunc(pattern, flags)
+ local matches
+ if string.match(flags, 'c') then
+ matches = query_definition(pattern)
+ else
+ matches = query_workspace_symbols(pattern)
+ end
+ -- fall back to tags if no matches
+ return #matches > 0 and matches or vim.NIL
+end
+
+return tagfunc
diff --git a/runtime/lua/vim/lsp/util.lua b/runtime/lua/vim/lsp/util.lua
index ba5c20ef9f..fad2b962b5 100644
--- a/runtime/lua/vim/lsp/util.lua
+++ b/runtime/lua/vim/lsp/util.lua
@@ -148,6 +148,93 @@ local function sort_by_key(fn)
end
---@private
+--- Gets the zero-indexed lines from the given buffer.
+--- Works on unloaded buffers by reading the file using libuv to bypass buf reading events.
+--- Falls back to loading the buffer and nvim_buf_get_lines for buffers with non-file URI.
+---
+---@param bufnr number bufnr to get the lines from
+---@param rows number[] zero-indexed line numbers
+---@return table<number string> a table mapping rows to lines
+local function get_lines(bufnr, rows)
+ rows = type(rows) == "table" and rows or { rows }
+
+ ---@private
+ local function buf_lines()
+ local lines = {}
+ for _, row in pairs(rows) do
+ lines[row] = (vim.api.nvim_buf_get_lines(bufnr, row, row + 1, false) or { "" })[1]
+ end
+ return lines
+ end
+
+ local uri = vim.uri_from_bufnr(bufnr)
+
+ -- load the buffer if this is not a file uri
+ -- Custom language server protocol extensions can result in servers sending URIs with custom schemes. Plugins are able to load these via `BufReadCmd` autocmds.
+ if uri:sub(1, 4) ~= "file" then
+ vim.fn.bufload(bufnr)
+ return buf_lines()
+ end
+
+ -- use loaded buffers if available
+ if vim.fn.bufloaded(bufnr) == 1 then
+ return buf_lines()
+ end
+
+ local filename = api.nvim_buf_get_name(bufnr)
+
+ -- get the data from the file
+ local fd = uv.fs_open(filename, "r", 438)
+ if not fd then return "" end
+ local stat = uv.fs_fstat(fd)
+ local data = uv.fs_read(fd, stat.size, 0)
+ uv.fs_close(fd)
+
+ local lines = {} -- rows we need to retrieve
+ local need = 0 -- keep track of how many unique rows we need
+ for _, row in pairs(rows) do
+ if not lines[row] then
+ need = need + 1
+ end
+ lines[row] = true
+ end
+
+ local found = 0
+ local lnum = 0
+
+ for line in string.gmatch(data, "([^\n]*)\n?") do
+ if lines[lnum] == true then
+ lines[lnum] = line
+ found = found + 1
+ if found == need then break end
+ end
+ lnum = lnum + 1
+ end
+
+ -- change any lines we didn't find to the empty string
+ for i, line in pairs(lines) do
+ if line == true then
+ lines[i] = ""
+ end
+ end
+ return lines
+end
+
+
+---@private
+--- Gets the zero-indexed line from the given buffer.
+--- Works on unloaded buffers by reading the file using libuv to bypass buf reading events.
+--- Falls back to loading the buffer and nvim_buf_get_lines for buffers with non-file URI.
+---
+---@param bufnr number
+---@param row number zero-indexed line number
+---@return string the line at row in filename
+local function get_line(bufnr, row)
+ return get_lines(bufnr, { row })[row]
+end
+
+
+---@private
--- Position is a https://microsoft.github.io/language-server-protocol/specifications/specification-current/#position
--- Returns a zero-indexed column, since set_lines() does the conversion to
--- 1-indexed
@@ -158,31 +245,25 @@ local function get_line_byte_from_position(bufnr, position, offset_encoding)
-- When on the first character, we can ignore the difference between byte and
-- character
if col > 0 then
- if not api.nvim_buf_is_loaded(bufnr) then
- vim.fn.bufload(bufnr)
- end
+ local line = get_line(bufnr, position.line)
+ local ok, result
- local line = position.line
- local lines = api.nvim_buf_get_lines(bufnr, line, line + 1, false)
- if #lines > 0 then
- local ok, result
-
- if offset_encoding == "utf-16" or not offset_encoding then
- ok, result = pcall(vim.str_byteindex, lines[1], col, true)
- elseif offset_encoding == "utf-32" then
- ok, result = pcall(vim.str_byteindex, lines[1], col, false)
- end
+ if offset_encoding == "utf-16" or not offset_encoding then
+ ok, result = pcall(vim.str_byteindex, line, col, true)
+ elseif offset_encoding == "utf-32" then
+ ok, result = pcall(vim.str_byteindex, line, col, false)
+ end
- if ok then
- return result
- end
- return math.min(#lines[1], col)
+ if ok then
+ return result
end
+ return math.min(#line, col)
end
return col
end
--- Process and return progress reports from lsp server
+---@private
function M.get_progress_messages()
local new_messages = {}
@@ -246,6 +327,10 @@ end
---@param bufnr number Buffer id
---@see https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textEdit
function M.apply_text_edits(text_edits, bufnr)
+ validate {
+ text_edits = { text_edits, 't', false };
+ bufnr = { bufnr, 'number', false };
+ }
if not next(text_edits) then return end
if not api.nvim_buf_is_loaded(bufnr) then
vim.fn.bufload(bufnr)
@@ -474,7 +559,7 @@ local function remove_unmatch_completion_items(items, prefix)
end, items)
end
---- Acording to LSP spec, if the client set `completionItemKind.valueSet`,
+--- According to LSP spec, if the client set `completionItemKind.valueSet`,
--- the client must handle it properly even if it receives a value outside the
--- specification.
---
@@ -574,7 +659,7 @@ function M.rename(old_fname, new_fname, opts)
api.nvim_buf_delete(oldbuf, { force = true })
end
-
+---@private
local function create_file(change)
local opts = change.options or {}
-- from spec: Overwrite wins over `ignoreIfExists`
@@ -586,7 +671,7 @@ local function create_file(change)
vim.fn.bufadd(fname)
end
-
+---@private
local function delete_file(change)
local opts = change.options or {}
local fname = vim.uri_to_fname(change.uri)
@@ -1054,7 +1139,7 @@ function M.stylize_markdown(bufnr, contents, opts)
markdown_lines[#stripped] = true
end
else
- -- strip any emty lines or separators prior to this separator in actual markdown
+ -- strip any empty lines or separators prior to this separator in actual markdown
if line:match("^---+$") then
while markdown_lines[#stripped] and (stripped[#stripped]:match("^%s*$") or stripped[#stripped]:match("^---+$")) do
markdown_lines[#stripped] = false
@@ -1087,7 +1172,7 @@ function M.stylize_markdown(bufnr, contents, opts)
local idx = 1
---@private
- -- keep track of syntaxes we already inlcuded.
+ -- keep track of syntaxes we already included.
-- no need to include the same syntax more than once
local langs = {}
local fences = get_markdown_fences()
@@ -1223,18 +1308,21 @@ end
---
---@param contents table of lines to show in window
---@param syntax string of syntax to set for opened buffer
----@param opts dictionary with optional fields
---- - height of floating window
---- - width of floating window
---- - wrap boolean enable wrapping of long lines (defaults to true)
---- - wrap_at character to wrap at for computing height when wrap is enabled
---- - max_width maximal width of floating window
---- - max_height maximal height of floating window
---- - pad_top number of lines to pad contents at top
---- - pad_bottom number of lines to pad contents at bottom
---- - focus_id if a popup with this id is opened, then focus it
---- - close_events list of events that closes the floating window
---- - focusable (boolean, default true): Make float focusable
+---@param opts table with optional fields (additional keys are passed on to |vim.api.nvim_open_win()|)
+--- - height: (number) height of floating window
+--- - width: (number) width of floating window
+--- - wrap: (boolean, default true) wrap long lines
+--- - wrap_at: (string) character to wrap at for computing height when wrap is enabled
+--- - max_width: (number) maximal width of floating window
+--- - max_height: (number) maximal height of floating window
+--- - pad_top: (number) number of lines to pad contents at top
+--- - pad_bottom: (number) number of lines to pad contents at bottom
+--- - focus_id: (string) if a popup with this id is opened, then focus it
+--- - close_events: (table) list of events that closes the floating window
+--- - focusable: (boolean, default true) Make float focusable
+--- - focus: (boolean, default true) If `true`, and if {focusable}
+--- is also `true`, focus an existing floating window with the same
+--- {focus_id}
---@returns bufnr,winnr buffer and window number of the newly created floating
---preview window
function M.open_floating_preview(contents, syntax, opts)
@@ -1246,12 +1334,13 @@ function M.open_floating_preview(contents, syntax, opts)
opts = opts or {}
opts.wrap = opts.wrap ~= false -- wrapping by default
opts.stylize_markdown = opts.stylize_markdown ~= false
+ opts.focus = opts.focus ~= false
opts.close_events = opts.close_events or {"CursorMoved", "CursorMovedI", "BufHidden", "InsertCharPre"}
local bufnr = api.nvim_get_current_buf()
-- check if this popup is focusable and we need to focus
- if opts.focus_id and opts.focusable ~= false then
+ if opts.focus_id and opts.focusable ~= false and opts.focus then
-- Go back to previous window if we are in a focusable one
local current_winnr = api.nvim_get_current_win()
if npcall(api.nvim_win_get_var, current_winnr, opts.focus_id) then
@@ -1314,7 +1403,7 @@ function M.open_floating_preview(contents, syntax, opts)
api.nvim_buf_set_option(floating_bufnr, 'modifiable', false)
api.nvim_buf_set_option(floating_bufnr, 'bufhidden', 'wipe')
- api.nvim_buf_set_keymap(floating_bufnr, "n", "q", "<cmd>bdelete<cr>", {silent = true, noremap = true})
+ api.nvim_buf_set_keymap(floating_bufnr, "n", "q", "<cmd>bdelete<cr>", {silent = true, noremap = true, nowait = true})
M.close_preview_autocmd(opts.close_events, floating_winnr)
-- save focus_id
@@ -1331,7 +1420,7 @@ do --[[ References ]]
--- Removes document highlights from a buffer.
---
- ---@param bufnr buffer id
+ ---@param bufnr number Buffer id
function M.buf_clear_references(bufnr)
validate { bufnr = {bufnr, 'n', true} }
api.nvim_buf_clear_namespace(bufnr, reference_ns, 0, -1)
@@ -1339,9 +1428,9 @@ do --[[ References ]]
--- Shows a list of document highlights for a certain buffer.
---
- ---@param bufnr buffer id
- ---@param references List of `DocumentHighlight` objects to highlight
- ---@param offset_encoding string utf-8|utf-16|utf-32|nil defaults to utf-16
+ ---@param bufnr number Buffer id
+ ---@param references table List of `DocumentHighlight` objects to highlight
+ ---@param offset_encoding string One of "utf-8", "utf-16", "utf-32", or nil. Defaults to utf-16
---@see https://microsoft.github.io/language-server-protocol/specifications/specification-3-17/#documentHighlight
function M.buf_highlight_references(bufnr, references, offset_encoding)
validate { bufnr = {bufnr, 'n', true} }
@@ -1372,88 +1461,6 @@ local position_sort = sort_by_key(function(v)
return {v.start.line, v.start.character}
end)
---- Gets the zero-indexed line from the given uri.
----@param uri string uri of the resource to get the line from
----@param row number zero-indexed line number
----@return string the line at row in filename
--- For non-file uris, we load the buffer and get the line.
--- If a loaded buffer exists, then that is used.
--- Otherwise we get the line using libuv which is a lot faster than loading the buffer.
-function M.get_line(uri, row)
- return M.get_lines(uri, { row })[row]
-end
-
---- Gets the zero-indexed lines from the given uri.
----@param uri string uri of the resource to get the lines from
----@param rows number[] zero-indexed line numbers
----@return table<number string> a table mapping rows to lines
--- For non-file uris, we load the buffer and get the lines.
--- If a loaded buffer exists, then that is used.
--- Otherwise we get the lines using libuv which is a lot faster than loading the buffer.
-function M.get_lines(uri, rows)
- rows = type(rows) == "table" and rows or { rows }
-
- local function buf_lines(bufnr)
- local lines = {}
- for _, row in pairs(rows) do
- lines[row] = (vim.api.nvim_buf_get_lines(bufnr, row, row + 1, false) or { "" })[1]
- end
- return lines
- end
-
- -- load the buffer if this is not a file uri
- -- Custom language server protocol extensions can result in servers sending URIs with custom schemes. Plugins are able to load these via `BufReadCmd` autocmds.
- if uri:sub(1, 4) ~= "file" then
- local bufnr = vim.uri_to_bufnr(uri)
- vim.fn.bufload(bufnr)
- return buf_lines(bufnr)
- end
-
- local filename = vim.uri_to_fname(uri)
-
- -- use loaded buffers if available
- if vim.fn.bufloaded(filename) == 1 then
- local bufnr = vim.fn.bufnr(filename, false)
- return buf_lines(bufnr)
- end
-
- -- get the data from the file
- local fd = uv.fs_open(filename, "r", 438)
- if not fd then return "" end
- local stat = uv.fs_fstat(fd)
- local data = uv.fs_read(fd, stat.size, 0)
- uv.fs_close(fd)
-
- local lines = {} -- rows we need to retrieve
- local need = 0 -- keep track of how many unique rows we need
- for _, row in pairs(rows) do
- if not lines[row] then
- need = need + 1
- end
- lines[row] = true
- end
-
- local found = 0
- local lnum = 0
-
- for line in string.gmatch(data, "([^\n]*)\n?") do
- if lines[lnum] == true then
- lines[lnum] = line
- found = found + 1
- if found == need then break end
- end
- lnum = lnum + 1
- end
-
- -- change any lines we didn't find to the empty string
- for i, line in pairs(lines) do
- if line == true then
- lines[i] = ""
- end
- end
- return lines
-end
-
--- Returns the items with the byte position calculated correctly and in sorted
--- order, for display in quickfix and location lists.
---
@@ -1496,7 +1503,7 @@ function M.locations_to_items(locations)
end
-- get all the lines for this uri
- local lines = M.get_lines(uri, uri_rows)
+ local lines = get_lines(vim.uri_to_bufnr(uri), uri_rows)
for _, temp in ipairs(rows) do
local pos = temp.start
@@ -1541,7 +1548,7 @@ function M.set_qflist(items)
})
end
--- Acording to LSP spec, if the client set "symbolKind.valueSet",
+-- According to LSP spec, if the client set "symbolKind.valueSet",
-- the client must handle it properly even if it receives a value outside the specification.
-- https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_documentSymbol
function M._get_symbol_kind_name(symbol_kind)
@@ -1773,8 +1780,7 @@ end
---@param col 0-indexed byte offset in line
---@returns (number, number) UTF-32 and UTF-16 index of the character in line {row} column {col} in buffer {buf}
function M.character_offset(bufnr, row, col)
- local uri = vim.uri_from_bufnr(bufnr)
- local line = M.get_line(uri, row)
+ local line = get_line(bufnr, row)
-- If the col is past the EOL, use the line length.
if col > #line then
return str_utfindex(line)
diff --git a/runtime/lua/vim/shared.lua b/runtime/lua/vim/shared.lua
index 6e40b6ca52..1cf618725d 100644
--- a/runtime/lua/vim/shared.lua
+++ b/runtime/lua/vim/shared.lua
@@ -12,7 +12,7 @@ local vim = vim or {}
--- same functions as those in the input table. Userdata and threads are not
--- copied and will throw an error.
---
----@param orig Table to copy
+---@param orig table Table to copy
---@returns New table of copied keys and (nested) values.
function vim.deepcopy(orig) end -- luacheck: no unused
vim.deepcopy = (function()
@@ -21,17 +21,16 @@ vim.deepcopy = (function()
end
local deepcopy_funcs = {
- table = function(orig)
+ table = function(orig, cache)
+ if cache[orig] then return cache[orig] end
local copy = {}
- if vim._empty_dict_mt ~= nil and getmetatable(orig) == vim._empty_dict_mt then
- copy = vim.empty_dict()
- end
-
+ cache[orig] = copy
+ local mt = getmetatable(orig)
for k, v in pairs(orig) do
- copy[vim.deepcopy(k)] = vim.deepcopy(v)
+ copy[vim.deepcopy(k, cache)] = vim.deepcopy(v, cache)
end
- return copy
+ return setmetatable(copy, mt)
end,
number = _id,
string = _id,
@@ -40,10 +39,10 @@ vim.deepcopy = (function()
['function'] = _id,
}
- return function(orig)
+ return function(orig, cache)
local f = deepcopy_funcs[type(orig)]
if f then
- return f(orig)
+ return f(orig, cache or {})
else
error("Cannot deepcopy object of type "..type(orig))
end
@@ -560,6 +559,7 @@ do
return type(val) == t or (t == 'callable' and vim.is_callable(val))
end
+ ---@private
local function is_valid(opt)
if type(opt) ~= 'table' then
return false, string.format('opt: expected table, got %s', type(opt))
diff --git a/runtime/lua/vim/treesitter.lua b/runtime/lua/vim/treesitter.lua
index 66999c5f7f..07f6418c0c 100644
--- a/runtime/lua/vim/treesitter.lua
+++ b/runtime/lua/vim/treesitter.lua
@@ -72,7 +72,7 @@ end
--- Gets the parser for this bufnr / ft combination.
---
--- If needed this will create the parser.
---- Unconditionnally attach the provided callback
+--- Unconditionally attach the provided callback
---
---@param bufnr The buffer the parser should be tied to
---@param lang The filetype of this parser
diff --git a/runtime/lua/vim/treesitter/language.lua b/runtime/lua/vim/treesitter/language.lua
index 89ddd6cd5a..6f347ff25f 100644
--- a/runtime/lua/vim/treesitter/language.lua
+++ b/runtime/lua/vim/treesitter/language.lua
@@ -38,7 +38,7 @@ end
--- Inspects the provided language.
---
---- Inspecting provides some useful informations on the language like node names, ...
+--- Inspecting provides some useful information on the language like node names, ...
---
---@param lang The language.
function M.inspect_language(lang)
diff --git a/runtime/lua/vim/treesitter/languagetree.lua b/runtime/lua/vim/treesitter/languagetree.lua
index 7e392f72a4..594765761d 100644
--- a/runtime/lua/vim/treesitter/languagetree.lua
+++ b/runtime/lua/vim/treesitter/languagetree.lua
@@ -493,9 +493,9 @@ local function tree_contains(tree, range)
return false
end
---- Determines wether @param range is contained in this language tree
+--- Determines whether @param range is contained in this language tree
---
---- This goes down the tree to recursively check childs.
+--- This goes down the tree to recursively check children.
---
---@param range A range, that is a `{ start_line, start_col, end_line, end_col }` table.
function LanguageTree:contains(range)
diff --git a/runtime/lua/vim/treesitter/query.lua b/runtime/lua/vim/treesitter/query.lua
index 66da179ea3..b8255e61ed 100644
--- a/runtime/lua/vim/treesitter/query.lua
+++ b/runtime/lua/vim/treesitter/query.lua
@@ -48,7 +48,7 @@ function M.get_query_files(lang, query_name, is_included)
local base_langs = {}
-- Now get the base languages by looking at the first line of every file
- -- The syntax is the folowing :
+ -- The syntax is the following :
-- ;+ inherits: ({language},)*{language}
--
-- {language} ::= {lang} | ({lang})
@@ -446,7 +446,7 @@ end
---
--- {source} is needed if the query contains predicates, then the caller
--- must ensure to use a freshly parsed tree consistent with the current
---- text of the buffer (if relevent). {start_row} and {end_row} can be used to limit
+--- text of the buffer (if relevant). {start_row} and {end_row} can be used to limit
--- matches inside a row range (this is typically used with root node
--- as the node, i e to get syntax highlight matches in the current
--- viewport). When omitted the start and end row values are used from the given node.
@@ -466,7 +466,7 @@ end
--- </pre>
---
---@param node The node under which the search will occur
----@param source The source buffer or string to exctract text from
+---@param source The source buffer or string to extract text from
---@param start The starting line of the search
---@param stop The stopping line of the search (end-exclusive)
---
diff --git a/runtime/lua/vim/uri.lua b/runtime/lua/vim/uri.lua
index 5d8d4fa169..d08d2a3ee3 100644
--- a/runtime/lua/vim/uri.lua
+++ b/runtime/lua/vim/uri.lua
@@ -56,8 +56,8 @@ local function is_windows_file_uri(uri)
end
--- Get a URI from a file path.
----@param path (string): Path to file
----@return URI
+---@param path string Path to file
+---@return string URI
local function uri_from_fname(path)
local volume_path, fname = path:match("^([a-zA-Z]:)(.*)")
local is_windows = volume_path ~= nil
@@ -78,8 +78,8 @@ local URI_SCHEME_PATTERN = '^([a-zA-Z]+[a-zA-Z0-9+-.]*):.*'
local WINDOWS_URI_SCHEME_PATTERN = '^([a-zA-Z]+[a-zA-Z0-9+-.]*):[a-zA-Z]:.*'
--- Get a URI from a bufnr
----@param bufnr (number): Buffer number
----@return URI
+---@param bufnr number
+---@return string URI
local function uri_from_bufnr(bufnr)
local fname = vim.api.nvim_buf_get_name(bufnr)
local volume_path = fname:match("^([a-zA-Z]:).*")
@@ -99,8 +99,8 @@ local function uri_from_bufnr(bufnr)
end
--- Get a filename from a URI
----@param uri (string): The URI
----@return Filename
+---@param uri string
+---@return string filename or unchanged URI for non-file URIs
local function uri_to_fname(uri)
local scheme = assert(uri:match(URI_SCHEME_PATTERN), 'URI must contain a scheme: ' .. uri)
if scheme ~= 'file' then
@@ -117,17 +117,13 @@ local function uri_to_fname(uri)
return uri
end
---- Return or create a buffer for a uri.
----@param uri (string): The URI
----@return bufnr.
----@note Creates buffer but does not load it
+--- Get the buffer for a uri.
+--- Creates a new unloaded buffer if no buffer for the uri already exists.
+--
+---@param uri string
+---@return number bufnr
local function uri_to_bufnr(uri)
- local scheme = assert(uri:match(URI_SCHEME_PATTERN), 'URI must contain a scheme: ' .. uri)
- if scheme == 'file' then
- return vim.fn.bufadd(uri_to_fname(uri))
- else
- return vim.fn.bufadd(uri)
- end
+ return vim.fn.bufadd(uri_to_fname(uri))
end
return {
diff --git a/runtime/nvim.appdata.xml b/runtime/nvim.appdata.xml
index 099c9a57c0..225dd79878 100644
--- a/runtime/nvim.appdata.xml
+++ b/runtime/nvim.appdata.xml
@@ -26,6 +26,7 @@
</screenshots>
<releases>
+ <release date="2021-11-30" version="0.6.0"/>
<release date="2021-07-02" version="0.5.0"/>
<release date="2020-08-04" version="0.4.4"/>
<release date="2019-11-06" version="0.4.3"/>
diff --git a/runtime/pack/dist/opt/termdebug/plugin/termdebug.vim b/runtime/pack/dist/opt/termdebug/plugin/termdebug.vim
index ae0242a312..4a58bee8ce 100644
--- a/runtime/pack/dist/opt/termdebug/plugin/termdebug.vim
+++ b/runtime/pack/dist/opt/termdebug/plugin/termdebug.vim
@@ -2,7 +2,7 @@
"
" Author: Bram Moolenaar
" Copyright: Vim license applies, see ":help license"
-" Last Change: 2021 Nov 14
+" Last Change: 2021 Nov 27
"
" WORK IN PROGRESS - Only the basics work
" Note: On MS-Windows you need a recent version of gdb. The one included with
@@ -102,6 +102,7 @@ endfunc
call s:Highlight(1, '', &background)
hi default debugBreakpoint term=reverse ctermbg=red guibg=red
+hi default debugBreakpointDisabled term=reverse ctermbg=gray guibg=gray
func s:StartDebug(bang, ...)
" First argument is the command to debug, second core file or process ID.
@@ -241,15 +242,29 @@ func s:StartDebug_term(dict)
let comm_job_info = nvim_get_chan_info(s:comm_job_id)
let commpty = comm_job_info['pty']
- " Open a terminal window to run the debugger.
- " Add -quiet to avoid the intro message causing a hit-enter prompt.
let gdb_args = get(a:dict, 'gdb_args', [])
let proc_args = get(a:dict, 'proc_args', [])
- let cmd = [g:termdebugger, '-quiet', '-tty', pty, '--eval-command', 'echo startupdone\n'] + gdb_args
- "call ch_log('executing "' . join(cmd) . '"')
+ let gdb_cmd = [g:termdebugger]
+ " Add -quiet to avoid the intro message causing a hit-enter prompt.
+ let gdb_cmd += ['-quiet']
+ " Disable pagination, it causes everything to stop at the gdb
+ let gdb_cmd += ['-iex', 'set pagination off']
+ " Interpret commands while the target is running. This should usually only
+ " be exec-interrupt, since many commands don't work properly while the
+ " target is running (so execute during startup).
+ let gdb_cmd += ['-iex', 'set mi-async on']
+ " Open a terminal window to run the debugger.
+ let gdb_cmd += ['-tty', pty]
+ " Command executed _after_ startup is done, provides us with the necessary feedback
+ let gdb_cmd += ['-ex', 'echo startupdone\n']
+
+ " Adding arguments requested by the user
+ let gdb_cmd += gdb_args
+
execute 'new'
- let s:gdb_job_id = termopen(cmd, {'on_exit': function('s:EndTermDebug')})
+ " call ch_log('executing "' . join(gdb_cmd) . '"')
+ let s:gdb_job_id = termopen(gdb_cmd, {'on_exit': function('s:EndTermDebug')})
if s:gdb_job_id == 0
echoerr 'invalid argument (or job table is full) while opening gdb terminal window'
exe 'bwipe! ' . s:ptybuf
@@ -272,8 +287,8 @@ func s:StartDebug_term(dict)
for lnum in range(1, 200)
if get(getbufline(s:gdbbuf, lnum), 0, '') =~ 'startupdone'
- let try_count = 9999
- break
+ let try_count = 9999
+ break
endif
endfor
let try_count += 1
@@ -286,11 +301,12 @@ func s:StartDebug_term(dict)
" Set arguments to be run.
if len(proc_args)
- call chansend(s:gdb_job_id, 'set args ' . join(proc_args) . "\r")
+ call chansend(s:gdb_job_id, 'server set args ' . join(proc_args) . "\r")
endif
- " Connect gdb to the communication pty, using the GDB/MI interface
- call chansend(s:gdb_job_id, 'new-ui mi ' . commpty . "\r")
+ " Connect gdb to the communication pty, using the GDB/MI interface.
+ " Prefix "server" to avoid adding this to the history.
+ call chansend(s:gdb_job_id, 'server new-ui mi ' . commpty . "\r")
" Wait for the response to show up, users may not notice the error and wonder
" why the debugger doesn't work.
@@ -309,7 +325,8 @@ func s:StartDebug_term(dict)
let response = line1 . line2
if response =~ 'Undefined command'
echoerr 'Sorry, your gdb is too old, gdb 7.12 is required'
- call s:CloseBuffers()
+ " CHECKME: possibly send a "server show version" here
+ call s:CloseBuffers()
return
endif
if response =~ 'New UI allocated'
@@ -332,17 +349,6 @@ func s:StartDebug_term(dict)
sleep 10m
endwhile
- " Interpret commands while the target is running. This should usually only be
- " exec-interrupt, since many commands don't work properly while the target is
- " running.
- call s:SendCommand('-gdb-set mi-async on')
- " Older gdb uses a different command.
- call s:SendCommand('-gdb-set target-async on')
-
- " Disable pagination, it causes everything to stop at the gdb
- " "Type <return> to continue" prompt.
- call s:SendCommand('set pagination off')
-
" Set the filetype, this can be used to add mappings.
set filetype=termdebug
@@ -370,14 +376,26 @@ func s:StartDebug_prompt(dict)
exe (&columns / 2 - 1) . "wincmd |"
endif
- " Add -quiet to avoid the intro message causing a hit-enter prompt.
let gdb_args = get(a:dict, 'gdb_args', [])
let proc_args = get(a:dict, 'proc_args', [])
- let cmd = [g:termdebugger, '-quiet', '--interpreter=mi2'] + gdb_args
- "call ch_log('executing "' . join(cmd) . '"')
+ let gdb_cmd = [g:termdebugger]
+ " Add -quiet to avoid the intro message causing a hit-enter prompt.
+ let gdb_cmd += ['-quiet']
+ " Disable pagination, it causes everything to stop at the gdb, needs to be run early
+ let gdb_cmd += ['-iex', 'set pagination off']
+ " Interpret commands while the target is running. This should usually only
+ " be exec-interrupt, since many commands don't work properly while the
+ " target is running (so execute during startup).
+ let gdb_cmd += ['-iex', 'set mi-async on']
+ " directly communicate via mi2
+ let gdb_cmd += ['--interpreter=mi2']
- let s:gdbjob = jobstart(cmd, {
+ " Adding arguments requested by the user
+ let gdb_cmd += gdb_args
+
+ " call ch_log('executing "' . join(gdb_cmd) . '"')
+ let s:gdbjob = jobstart(gdb_cmd, {
\ 'on_exit': function('s:EndPromptDebug'),
\ 'on_stdout': function('s:GdbOutCallback'),
\ })
@@ -391,13 +409,6 @@ func s:StartDebug_prompt(dict)
return
endif
- " Interpret commands while the target is running. This should usually only
- " be exec-interrupt, since many commands don't work properly while the
- " target is running.
- call s:SendCommand('-gdb-set mi-async on')
- " Older gdb uses a different command.
- call s:SendCommand('-gdb-set target-async on')
-
let s:ptybuf = 0
if has('win32')
" MS-Windows: run in a new console window for maximum compatibility
@@ -432,8 +443,6 @@ func s:StartDebug_prompt(dict)
endif
call s:SendCommand('set print pretty on')
call s:SendCommand('set breakpoint pending on')
- " Disable pagination, it causes everything to stop at the gdb
- call s:SendCommand('set pagination off')
" Set arguments to be run
if len(proc_args)
@@ -504,7 +513,7 @@ func TermDebugSendCommand(cmd)
" needed once.
call jobstop(s:gdbjob)
else
- call s:SendCommand('-exec-interrupt')
+ Stop
endif
sleep 10m
endif
@@ -515,6 +524,15 @@ func TermDebugSendCommand(cmd)
endif
endfunc
+" Send a command only when stopped. Used for :Next and :Step.
+func s:SendCommandIfStopped(cmd)
+ if s:stopped
+ call s:SendCommand(a:cmd)
+ " else
+ " call ch_log('dropping command, program is running: ' . a:cmd)
+ endif
+endfunc
+
" Function called when entering a line in the prompt buffer.
func s:PromptCallback(text)
call s:SendCommand(a:text)
@@ -583,32 +601,23 @@ func s:GdbOutCallback(job_id, msgs, event)
endfunc
" Decode a message from gdb. quotedText starts with a ", return the text up
-" to the next ", unescaping characters.
+" to the next ", unescaping characters:
+" - remove line breaks
+" - change \\t to \t
+" - change \0xhh to \xhh
+" - change \ooo to octal
+" - change \\ to \
func s:DecodeMessage(quotedText)
if a:quotedText[0] != '"'
echoerr 'DecodeMessage(): missing quote in ' . a:quotedText
return
endif
- let result = ''
- let i = 1
- while a:quotedText[i] != '"' && i < len(a:quotedText)
- if a:quotedText[i] == '\'
- let i += 1
- if a:quotedText[i] == 'n'
- " drop \n
- let i += 1
- continue
- elseif a:quotedText[i] == 't'
- " append \t
- let i += 1
- let result .= "\t"
- continue
- endif
- endif
- let result .= a:quotedText[i]
- let i += 1
- endwhile
- return result
+ return a:quotedText
+ \->substitute('^"\|".*\|\\n', '', 'g')
+ \->substitute('\\t', "\t", 'g')
+ \->substitute('\\0x\(\x\x\)', {-> eval('"\x' .. submatch(1) .. '"')}, 'g')
+ \->substitute('\\\o\o\o', {-> eval('"' .. submatch(0) .. '"')}, 'g')
+ \->substitute('\\\\', '\', 'g')
endfunc
" Extract the "name" value from a gdb message with fullname="name".
@@ -657,8 +666,8 @@ func s:EndDebugCommon()
if bufexists(bufnr)
exe bufnr .. "buf"
if exists('b:save_signcolumn')
- let &signcolumn = b:save_signcolumn
- unlet b:save_signcolumn
+ let &signcolumn = b:save_signcolumn
+ unlet b:save_signcolumn
endif
endif
endfor
@@ -770,7 +779,9 @@ func s:CommOutput(job_id, msgs, event)
if msg =~ '^\(\*stopped\|\*running\|=thread-selected\)'
call s:HandleCursor(msg)
elseif msg =~ '^\^done,bkpt=' || msg =~ '^=breakpoint-created,'
- call s:HandleNewBreakpoint(msg)
+ call s:HandleNewBreakpoint(msg, 0)
+ elseif msg =~ '^=breakpoint-modified,'
+ call s:HandleNewBreakpoint(msg, 1)
elseif msg =~ '^=breakpoint-deleted,'
call s:HandleBreakpointDelete(msg)
elseif msg =~ '^=thread-group-started'
@@ -804,17 +815,20 @@ func s:InstallCommands()
command -nargs=? Break call s:SetBreakpoint(<q-args>)
command Clear call s:ClearBreakpoint()
- command Step call s:SendCommand('-exec-step')
- command Over call s:SendCommand('-exec-next')
- command Finish call s:SendCommand('-exec-finish')
+ command Step call s:SendCommandIfStopped('-exec-step')
+ command Over call s:SendCommandIfStopped('-exec-next')
+ command Finish call s:SendCommandIfStopped('-exec-finish')
command -nargs=* Run call s:Run(<q-args>)
command -nargs=* Arguments call s:SendCommand('-exec-arguments ' . <q-args>)
- command Stop call s:SendCommand('-exec-interrupt')
- " using -exec-continue results in CTRL-C in gdb window not working
if s:way == 'prompt'
+ command Stop call s:PromptInterrupt()
command Continue call s:SendCommand('continue')
else
+ command Stop call s:SendCommand('-exec-interrupt')
+ " using -exec-continue results in CTRL-C in the gdb window not working,
+ " communicating via commbuf (= use of SendCommand) has the same result
+ "command Continue call s:SendCommand('-exec-continue')
command Continue call chansend(s:gdb_job_id, "continue\r")
endif
@@ -913,20 +927,16 @@ func s:SetBreakpoint(at)
let do_continue = 0
if !s:stopped
let do_continue = 1
- if s:way == 'prompt'
- call s:PromptInterrupt()
- else
- call s:SendCommand('-exec-interrupt')
- endif
+ Stop
sleep 10m
endif
" Use the fname:lnum format, older gdb can't handle --source.
let at = empty(a:at) ?
- \ fnameescape(expand('%:p')) . ':' . line('.') : a:at
+ \ fnameescape(expand('%:p')) . ':' . line('.') : a:at
call s:SendCommand('-break-insert ' . at)
if do_continue
- call s:SendCommand('-exec-continue')
+ Continue
endif
endfunc
@@ -937,23 +947,32 @@ func s:ClearBreakpoint()
let bploc = printf('%s:%d', fname, lnum)
if has_key(s:breakpoint_locations, bploc)
let idx = 0
+ let nr = 0
for id in s:breakpoint_locations[bploc]
if has_key(s:breakpoints, id)
- " Assume this always works, the reply is simply "^done".
- call s:SendCommand('-break-delete ' . id)
- for subid in keys(s:breakpoints[id])
- exe 'sign unplace ' . s:Breakpoint2SignNumber(id, subid)
- endfor
- unlet s:breakpoints[id]
- unlet s:breakpoint_locations[bploc][idx]
- break
+ " Assume this always works, the reply is simply "^done".
+ call s:SendCommand('-break-delete ' . id)
+ for subid in keys(s:breakpoints[id])
+ exe 'sign unplace ' . s:Breakpoint2SignNumber(id, subid)
+ endfor
+ unlet s:breakpoints[id]
+ unlet s:breakpoint_locations[bploc][idx]
+ let nr = id
+ break
else
- let idx += 1
+ let idx += 1
endif
endfor
- if empty(s:breakpoint_locations[bploc])
- unlet s:breakpoint_locations[bploc]
+ if nr != 0
+ if empty(s:breakpoint_locations[bploc])
+ unlet s:breakpoint_locations[bploc]
+ endif
+ echomsg 'Breakpoint ' . id . ' cleared from line ' . lnum . '.'
+ else
+ echoerr 'Internal error trying to remove breakpoint at line ' . lnum . '!'
endif
+ else
+ echomsg 'No breakpoint to remove at line ' . lnum . '.'
endif
endfunc
@@ -965,44 +984,75 @@ func s:Run(args)
endfunc
func s:SendEval(expr)
- " clean up expression that may got in because of range
- " (newlines and surrounding spaces)
- let expr = a:expr
- if &filetype ==# 'cobol'
- " extra cleanup for COBOL: _every: expression ends with a period,
- " a trailing comma is ignored as it commonly separates multiple expr.
- let expr = substitute(expr, '\..*', '', '')
- let expr = substitute(expr, '[;\n]', ' ', 'g')
- let expr = substitute(expr, ',*$', '', '')
+ " check for "likely" boolean expressions, in which case we take it as lhs
+ if a:expr =~ "[=!<>]="
+ let exprLHS = a:expr
else
- let expr = substitute(expr, '\n', ' ', 'g')
+ " remove text that is likely an assignment
+ let exprLHS = substitute(a:expr, ' *=.*', '', '')
endif
- let expr = substitute(expr, '^ *\(.*\) *', '\1', '')
+ " encoding expression to prevent bad errors
+ let expr = a:expr
+ let expr = substitute(expr, '\\', '\\\\', 'g')
+ let expr = substitute(expr, '"', '\\"', 'g')
call s:SendCommand('-data-evaluate-expression "' . expr . '"')
- let s:evalexpr = expr
+ let s:evalexpr = exprLHS
endfunc
-" :Evaluate - evaluate what is under the cursor
+" :Evaluate - evaluate what is specified / under the cursor
func s:Evaluate(range, arg)
+ let expr = s:GetEvaluationExpression(a:range, a:arg)
+ let s:ignoreEvalError = 0
+ call s:SendEval(expr)
+endfunc
+
+" get what is specified / under the cursor
+func s:GetEvaluationExpression(range, arg)
if a:arg != ''
- let expr = a:arg
- let s:evalFromBalloonExpr = 0
+ " user supplied evaluation
+ let expr = s:CleanupExpr(a:arg)
+ " DSW: replace "likely copy + paste" assignment
+ let expr = substitute(expr, '"\([^"]*\)": *', '\1=', 'g')
elseif a:range == 2
let pos = getcurpos()
let reg = getreg('v', 1, 1)
let regt = getregtype('v')
normal! gv"vy
- let expr = @v
+ let expr = s:CleanupExpr(@v)
call setpos('.', pos)
call setreg('v', reg, regt)
let s:evalFromBalloonExpr = 1
else
+ " no evaluation provided: get from C-expression under cursor
+ " TODO: allow filetype specific lookup #9057
let expr = expand('<cexpr>')
let s:evalFromBalloonExpr = 1
endif
- let s:ignoreEvalError = 0
- call s:SendEval(expr)
+ return expr
+endfunc
+
+" clean up expression that may got in because of range
+" (newlines and surrounding whitespace)
+" As it can also be specified via ex-command for assignments this function
+" may not change the "content" parts (like replacing contained spaces
+func s:CleanupExpr(expr)
+ " replace all embedded newlines/tabs/...
+ let expr = substitute(a:expr, '\_s', ' ', 'g')
+
+ if &filetype ==# 'cobol'
+ " extra cleanup for COBOL:
+ " - a semicolon nmay be used instead of a space
+ " - a trailing comma or period is ignored as it commonly separates/ends
+ " multiple expr
+ let expr = substitute(expr, ';', ' ', 'g')
+ let expr = substitute(expr, '[,.]\+ *$', '', '')
+ endif
+
+ " get rid of leading and trailing spaces
+ let expr = substitute(expr, '^ *', '', '')
+ let expr = substitute(expr, ' *$', '', '')
+ return expr
endfunc
let s:ignoreEvalError = 0
@@ -1013,6 +1063,8 @@ let s:evalFromBalloonExprResult = ''
func s:HandleEvaluate(msg)
let value = substitute(a:msg, '.*value="\(.*\)"', '\1', '')
let value = substitute(value, '\\"', '"', 'g')
+ " multi-byte characters arrive in octal form
+ let value = substitute(value, '\\\o\o\o', {-> eval('"' .. submatch(0) .. '"')}, 'g')
let value = substitute(value, ' ', '\1', '')
if s:evalFromBalloonExpr
if s:evalFromBalloonExprResult == ''
@@ -1246,15 +1298,15 @@ func s:HandleCursor(msg)
let curwinid = win_getid(winnr())
if win_gotoid(s:asmwin)
- let lnum = search('^' . s:asm_addr)
- if lnum == 0
- call s:SendCommand('disassemble $pc')
- else
- exe 'sign unplace ' . s:asm_id
- exe 'sign place ' . s:asm_id . ' line=' . lnum . ' name=debugPC'
- endif
+ let lnum = search('^' . s:asm_addr)
+ if lnum == 0
+ call s:SendCommand('disassemble $pc')
+ else
+ exe 'sign unplace ' . s:asm_id
+ exe 'sign place ' . s:asm_id . ' line=' . lnum . ' name=debugPC'
+ endif
- call win_gotoid(curwinid)
+ call win_gotoid(curwinid)
endif
endif
endif
@@ -1278,8 +1330,8 @@ func s:HandleCursor(msg)
exe 'sign unplace ' . s:pc_id
exe 'sign place ' . s:pc_id . ' line=' . lnum . ' name=debugPC file=' . fname
if !exists('b:save_signcolumn')
- let b:save_signcolumn = &signcolumn
- call add(s:signcolumn_buflist, bufnr())
+ let b:save_signcolumn = &signcolumn
+ call add(s:signcolumn_buflist, bufnr())
endif
setlocal signcolumn=yes
endif
@@ -1292,11 +1344,16 @@ endfunc
let s:BreakpointSigns = []
-func s:CreateBreakpoint(id, subid)
+func s:CreateBreakpoint(id, subid, enabled)
let nr = printf('%d.%d', a:id, a:subid)
if index(s:BreakpointSigns, nr) == -1
call add(s:BreakpointSigns, nr)
- exe "sign define debugBreakpoint" . nr . " text=" . substitute(nr, '\..*', '', '') . " texthl=debugBreakpoint"
+ if a:enabled == "n"
+ let hiName = "debugBreakpointDisabled"
+ else
+ let hiName = "debugBreakpoint"
+ endif
+ exe "sign define debugBreakpoint" . nr . " text=" . substitute(nr, '\..*', '', '') . " texthl=" . hiName
endif
endfunc
@@ -1306,9 +1363,14 @@ endfunction
" Handle setting a breakpoint
" Will update the sign that shows the breakpoint
-func s:HandleNewBreakpoint(msg)
+func s:HandleNewBreakpoint(msg, modifiedFlag)
if a:msg !~ 'fullname='
- " a watch does not have a file name
+ " a watch or a pending breakpoint does not have a file name
+ if a:msg =~ 'pending='
+ let nr = substitute(a:msg, '.*number=\"\([0-9.]*\)\".*', '\1', '')
+ let target = substitute(a:msg, '.*pending=\"\([^"]*\)\".*', '\1', '')
+ echomsg 'Breakpoint ' . nr . ' (' . target . ') pending.'
+ endif
return
endif
for msg in s:SplitMsg(a:msg)
@@ -1324,7 +1386,8 @@ func s:HandleNewBreakpoint(msg)
" If "nr" is 123 it becomes "123.0" and subid is "0".
" If "nr" is 123.4 it becomes "123.4.0" and subid is "4"; "0" is discarded.
let [id, subid; _] = map(split(nr . '.0', '\.'), 'v:val + 0')
- call s:CreateBreakpoint(id, subid)
+ let enabled = substitute(msg, '.*enabled="\([yn]\)".*', '\1', '')
+ call s:CreateBreakpoint(id, subid, enabled)
if has_key(s:breakpoints, id)
let entries = s:breakpoints[id]
@@ -1351,7 +1414,18 @@ func s:HandleNewBreakpoint(msg)
if bufloaded(fname)
call s:PlaceSign(id, subid, entry)
+ let posMsg = ' at line ' . lnum . '.'
+ else
+ let posMsg = ' in ' . fname . ' at line ' . lnum . '.'
+ endif
+ if !a:modifiedFlag
+ let actionTaken = 'created'
+ elseif enabled == 'n'
+ let actionTaken = 'disabled'
+ else
+ let actionTaken = 'enabled'
endif
+ echomsg 'Breakpoint ' . nr . ' ' . actionTaken . posMsg
endfor
endfunc
@@ -1371,11 +1445,12 @@ func s:HandleBreakpointDelete(msg)
if has_key(s:breakpoints, id)
for [subid, entry] in items(s:breakpoints[id])
if has_key(entry, 'placed')
- exe 'sign unplace ' . s:Breakpoint2SignNumber(id, subid)
- unlet entry['placed']
+ exe 'sign unplace ' . s:Breakpoint2SignNumber(id, subid)
+ unlet entry['placed']
endif
endfor
unlet s:breakpoints[id]
+ echomsg 'Breakpoint ' . id . ' cleared.'
endif
endfunc
@@ -1396,7 +1471,7 @@ func s:BufRead()
for [id, entries] in items(s:breakpoints)
for [subid, entry] in items(entries)
if entry['fname'] == fname
- call s:PlaceSign(id, subid, entry)
+ call s:PlaceSign(id, subid, entry)
endif
endfor
endfor
@@ -1408,7 +1483,7 @@ func s:BufUnloaded()
for [id, entries] in items(s:breakpoints)
for [subid, entry] in items(entries)
if entry['fname'] == fname
- let entry['placed'] = 0
+ let entry['placed'] = 0
endif
endfor
endfor
diff --git a/runtime/rgb.txt b/runtime/rgb.txt
deleted file mode 100644
index 5bc2baa3d6..0000000000
--- a/runtime/rgb.txt
+++ /dev/null
@@ -1,753 +0,0 @@
-! $XConsortium: rgb.txt,v 10.41 94/02/20 18:39:36 rws Exp $
-255 250 250 snow
-248 248 255 ghost white
-248 248 255 GhostWhite
-245 245 245 white smoke
-245 245 245 WhiteSmoke
-220 220 220 gainsboro
-255 250 240 floral white
-255 250 240 FloralWhite
-253 245 230 old lace
-253 245 230 OldLace
-250 240 230 linen
-250 235 215 antique white
-250 235 215 AntiqueWhite
-255 239 213 papaya whip
-255 239 213 PapayaWhip
-255 235 205 blanched almond
-255 235 205 BlanchedAlmond
-255 228 196 bisque
-255 218 185 peach puff
-255 218 185 PeachPuff
-255 222 173 navajo white
-255 222 173 NavajoWhite
-255 228 181 moccasin
-255 248 220 cornsilk
-255 255 240 ivory
-255 250 205 lemon chiffon
-255 250 205 LemonChiffon
-255 245 238 seashell
-240 255 240 honeydew
-245 255 250 mint cream
-245 255 250 MintCream
-240 255 255 azure
-240 248 255 alice blue
-240 248 255 AliceBlue
-230 230 250 lavender
-255 240 245 lavender blush
-255 240 245 LavenderBlush
-255 228 225 misty rose
-255 228 225 MistyRose
-255 255 255 white
- 0 0 0 black
- 47 79 79 dark slate gray
- 47 79 79 DarkSlateGray
- 47 79 79 dark slate grey
- 47 79 79 DarkSlateGrey
-105 105 105 dim gray
-105 105 105 DimGray
-105 105 105 dim grey
-105 105 105 DimGrey
-112 128 144 slate gray
-112 128 144 SlateGray
-112 128 144 slate grey
-112 128 144 SlateGrey
-119 136 153 light slate gray
-119 136 153 LightSlateGray
-119 136 153 light slate grey
-119 136 153 LightSlateGrey
-190 190 190 gray
-190 190 190 grey
-211 211 211 light grey
-211 211 211 LightGrey
-211 211 211 light gray
-211 211 211 LightGray
- 25 25 112 midnight blue
- 25 25 112 MidnightBlue
- 0 0 128 navy
- 0 0 128 navy blue
- 0 0 128 NavyBlue
-100 149 237 cornflower blue
-100 149 237 CornflowerBlue
- 72 61 139 dark slate blue
- 72 61 139 DarkSlateBlue
-106 90 205 slate blue
-106 90 205 SlateBlue
-123 104 238 medium slate blue
-123 104 238 MediumSlateBlue
-132 112 255 light slate blue
-132 112 255 LightSlateBlue
- 0 0 205 medium blue
- 0 0 205 MediumBlue
- 65 105 225 royal blue
- 65 105 225 RoyalBlue
- 0 0 255 blue
- 30 144 255 dodger blue
- 30 144 255 DodgerBlue
- 0 191 255 deep sky blue
- 0 191 255 DeepSkyBlue
-135 206 235 sky blue
-135 206 235 SkyBlue
-135 206 250 light sky blue
-135 206 250 LightSkyBlue
- 70 130 180 steel blue
- 70 130 180 SteelBlue
-176 196 222 light steel blue
-176 196 222 LightSteelBlue
-173 216 230 light blue
-173 216 230 LightBlue
-176 224 230 powder blue
-176 224 230 PowderBlue
-175 238 238 pale turquoise
-175 238 238 PaleTurquoise
- 0 206 209 dark turquoise
- 0 206 209 DarkTurquoise
- 72 209 204 medium turquoise
- 72 209 204 MediumTurquoise
- 64 224 208 turquoise
- 0 255 255 cyan
-224 255 255 light cyan
-224 255 255 LightCyan
- 95 158 160 cadet blue
- 95 158 160 CadetBlue
-102 205 170 medium aquamarine
-102 205 170 MediumAquamarine
-127 255 212 aquamarine
- 0 100 0 dark green
- 0 100 0 DarkGreen
- 85 107 47 dark olive green
- 85 107 47 DarkOliveGreen
-143 188 143 dark sea green
-143 188 143 DarkSeaGreen
- 46 139 87 sea green
- 46 139 87 SeaGreen
- 60 179 113 medium sea green
- 60 179 113 MediumSeaGreen
- 32 178 170 light sea green
- 32 178 170 LightSeaGreen
-152 251 152 pale green
-152 251 152 PaleGreen
- 0 255 127 spring green
- 0 255 127 SpringGreen
-124 252 0 lawn green
-124 252 0 LawnGreen
- 0 255 0 green
-127 255 0 chartreuse
- 0 250 154 medium spring green
- 0 250 154 MediumSpringGreen
-173 255 47 green yellow
-173 255 47 GreenYellow
- 50 205 50 lime green
- 50 205 50 LimeGreen
-154 205 50 yellow green
-154 205 50 YellowGreen
- 34 139 34 forest green
- 34 139 34 ForestGreen
-107 142 35 olive drab
-107 142 35 OliveDrab
-189 183 107 dark khaki
-189 183 107 DarkKhaki
-240 230 140 khaki
-238 232 170 pale goldenrod
-238 232 170 PaleGoldenrod
-250 250 210 light goldenrod yellow
-250 250 210 LightGoldenrodYellow
-255 255 224 light yellow
-255 255 224 LightYellow
-255 255 0 yellow
-255 215 0 gold
-238 221 130 light goldenrod
-238 221 130 LightGoldenrod
-218 165 32 goldenrod
-184 134 11 dark goldenrod
-184 134 11 DarkGoldenrod
-188 143 143 rosy brown
-188 143 143 RosyBrown
-205 92 92 indian red
-205 92 92 IndianRed
-139 69 19 saddle brown
-139 69 19 SaddleBrown
-160 82 45 sienna
-205 133 63 peru
-222 184 135 burlywood
-245 245 220 beige
-245 222 179 wheat
-244 164 96 sandy brown
-244 164 96 SandyBrown
-210 180 140 tan
-210 105 30 chocolate
-178 34 34 firebrick
-165 42 42 brown
-233 150 122 dark salmon
-233 150 122 DarkSalmon
-250 128 114 salmon
-255 160 122 light salmon
-255 160 122 LightSalmon
-255 165 0 orange
-255 140 0 dark orange
-255 140 0 DarkOrange
-255 127 80 coral
-240 128 128 light coral
-240 128 128 LightCoral
-255 99 71 tomato
-255 69 0 orange red
-255 69 0 OrangeRed
-255 0 0 red
-255 105 180 hot pink
-255 105 180 HotPink
-255 20 147 deep pink
-255 20 147 DeepPink
-255 192 203 pink
-255 182 193 light pink
-255 182 193 LightPink
-219 112 147 pale violet red
-219 112 147 PaleVioletRed
-176 48 96 maroon
-199 21 133 medium violet red
-199 21 133 MediumVioletRed
-208 32 144 violet red
-208 32 144 VioletRed
-255 0 255 magenta
-238 130 238 violet
-221 160 221 plum
-218 112 214 orchid
-186 85 211 medium orchid
-186 85 211 MediumOrchid
-153 50 204 dark orchid
-153 50 204 DarkOrchid
-148 0 211 dark violet
-148 0 211 DarkViolet
-138 43 226 blue violet
-138 43 226 BlueViolet
-160 32 240 purple
-147 112 219 medium purple
-147 112 219 MediumPurple
-216 191 216 thistle
-255 250 250 snow1
-238 233 233 snow2
-205 201 201 snow3
-139 137 137 snow4
-255 245 238 seashell1
-238 229 222 seashell2
-205 197 191 seashell3
-139 134 130 seashell4
-255 239 219 AntiqueWhite1
-238 223 204 AntiqueWhite2
-205 192 176 AntiqueWhite3
-139 131 120 AntiqueWhite4
-255 228 196 bisque1
-238 213 183 bisque2
-205 183 158 bisque3
-139 125 107 bisque4
-255 218 185 PeachPuff1
-238 203 173 PeachPuff2
-205 175 149 PeachPuff3
-139 119 101 PeachPuff4
-255 222 173 NavajoWhite1
-238 207 161 NavajoWhite2
-205 179 139 NavajoWhite3
-139 121 94 NavajoWhite4
-255 250 205 LemonChiffon1
-238 233 191 LemonChiffon2
-205 201 165 LemonChiffon3
-139 137 112 LemonChiffon4
-255 248 220 cornsilk1
-238 232 205 cornsilk2
-205 200 177 cornsilk3
-139 136 120 cornsilk4
-255 255 240 ivory1
-238 238 224 ivory2
-205 205 193 ivory3
-139 139 131 ivory4
-240 255 240 honeydew1
-224 238 224 honeydew2
-193 205 193 honeydew3
-131 139 131 honeydew4
-255 240 245 LavenderBlush1
-238 224 229 LavenderBlush2
-205 193 197 LavenderBlush3
-139 131 134 LavenderBlush4
-255 228 225 MistyRose1
-238 213 210 MistyRose2
-205 183 181 MistyRose3
-139 125 123 MistyRose4
-240 255 255 azure1
-224 238 238 azure2
-193 205 205 azure3
-131 139 139 azure4
-131 111 255 SlateBlue1
-122 103 238 SlateBlue2
-105 89 205 SlateBlue3
- 71 60 139 SlateBlue4
- 72 118 255 RoyalBlue1
- 67 110 238 RoyalBlue2
- 58 95 205 RoyalBlue3
- 39 64 139 RoyalBlue4
- 0 0 255 blue1
- 0 0 238 blue2
- 0 0 205 blue3
- 0 0 139 blue4
- 30 144 255 DodgerBlue1
- 28 134 238 DodgerBlue2
- 24 116 205 DodgerBlue3
- 16 78 139 DodgerBlue4
- 99 184 255 SteelBlue1
- 92 172 238 SteelBlue2
- 79 148 205 SteelBlue3
- 54 100 139 SteelBlue4
- 0 191 255 DeepSkyBlue1
- 0 178 238 DeepSkyBlue2
- 0 154 205 DeepSkyBlue3
- 0 104 139 DeepSkyBlue4
-135 206 255 SkyBlue1
-126 192 238 SkyBlue2
-108 166 205 SkyBlue3
- 74 112 139 SkyBlue4
-176 226 255 LightSkyBlue1
-164 211 238 LightSkyBlue2
-141 182 205 LightSkyBlue3
- 96 123 139 LightSkyBlue4
-198 226 255 SlateGray1
-185 211 238 SlateGray2
-159 182 205 SlateGray3
-108 123 139 SlateGray4
-202 225 255 LightSteelBlue1
-188 210 238 LightSteelBlue2
-162 181 205 LightSteelBlue3
-110 123 139 LightSteelBlue4
-191 239 255 LightBlue1
-178 223 238 LightBlue2
-154 192 205 LightBlue3
-104 131 139 LightBlue4
-224 255 255 LightCyan1
-209 238 238 LightCyan2
-180 205 205 LightCyan3
-122 139 139 LightCyan4
-187 255 255 PaleTurquoise1
-174 238 238 PaleTurquoise2
-150 205 205 PaleTurquoise3
-102 139 139 PaleTurquoise4
-152 245 255 CadetBlue1
-142 229 238 CadetBlue2
-122 197 205 CadetBlue3
- 83 134 139 CadetBlue4
- 0 245 255 turquoise1
- 0 229 238 turquoise2
- 0 197 205 turquoise3
- 0 134 139 turquoise4
- 0 255 255 cyan1
- 0 238 238 cyan2
- 0 205 205 cyan3
- 0 139 139 cyan4
-151 255 255 DarkSlateGray1
-141 238 238 DarkSlateGray2
-121 205 205 DarkSlateGray3
- 82 139 139 DarkSlateGray4
-127 255 212 aquamarine1
-118 238 198 aquamarine2
-102 205 170 aquamarine3
- 69 139 116 aquamarine4
-193 255 193 DarkSeaGreen1
-180 238 180 DarkSeaGreen2
-155 205 155 DarkSeaGreen3
-105 139 105 DarkSeaGreen4
- 84 255 159 SeaGreen1
- 78 238 148 SeaGreen2
- 67 205 128 SeaGreen3
- 46 139 87 SeaGreen4
-154 255 154 PaleGreen1
-144 238 144 PaleGreen2
-124 205 124 PaleGreen3
- 84 139 84 PaleGreen4
- 0 255 127 SpringGreen1
- 0 238 118 SpringGreen2
- 0 205 102 SpringGreen3
- 0 139 69 SpringGreen4
- 0 255 0 green1
- 0 238 0 green2
- 0 205 0 green3
- 0 139 0 green4
-127 255 0 chartreuse1
-118 238 0 chartreuse2
-102 205 0 chartreuse3
- 69 139 0 chartreuse4
-192 255 62 OliveDrab1
-179 238 58 OliveDrab2
-154 205 50 OliveDrab3
-105 139 34 OliveDrab4
-202 255 112 DarkOliveGreen1
-188 238 104 DarkOliveGreen2
-162 205 90 DarkOliveGreen3
-110 139 61 DarkOliveGreen4
-255 246 143 khaki1
-238 230 133 khaki2
-205 198 115 khaki3
-139 134 78 khaki4
-255 236 139 LightGoldenrod1
-238 220 130 LightGoldenrod2
-205 190 112 LightGoldenrod3
-139 129 76 LightGoldenrod4
-255 255 224 LightYellow1
-238 238 209 LightYellow2
-205 205 180 LightYellow3
-139 139 122 LightYellow4
-255 255 0 yellow1
-238 238 0 yellow2
-205 205 0 yellow3
-139 139 0 yellow4
-255 215 0 gold1
-238 201 0 gold2
-205 173 0 gold3
-139 117 0 gold4
-255 193 37 goldenrod1
-238 180 34 goldenrod2
-205 155 29 goldenrod3
-139 105 20 goldenrod4
-255 185 15 DarkGoldenrod1
-238 173 14 DarkGoldenrod2
-205 149 12 DarkGoldenrod3
-139 101 8 DarkGoldenrod4
-255 193 193 RosyBrown1
-238 180 180 RosyBrown2
-205 155 155 RosyBrown3
-139 105 105 RosyBrown4
-255 106 106 IndianRed1
-238 99 99 IndianRed2
-205 85 85 IndianRed3
-139 58 58 IndianRed4
-255 130 71 sienna1
-238 121 66 sienna2
-205 104 57 sienna3
-139 71 38 sienna4
-255 211 155 burlywood1
-238 197 145 burlywood2
-205 170 125 burlywood3
-139 115 85 burlywood4
-255 231 186 wheat1
-238 216 174 wheat2
-205 186 150 wheat3
-139 126 102 wheat4
-255 165 79 tan1
-238 154 73 tan2
-205 133 63 tan3
-139 90 43 tan4
-255 127 36 chocolate1
-238 118 33 chocolate2
-205 102 29 chocolate3
-139 69 19 chocolate4
-255 48 48 firebrick1
-238 44 44 firebrick2
-205 38 38 firebrick3
-139 26 26 firebrick4
-255 64 64 brown1
-238 59 59 brown2
-205 51 51 brown3
-139 35 35 brown4
-255 140 105 salmon1
-238 130 98 salmon2
-205 112 84 salmon3
-139 76 57 salmon4
-255 160 122 LightSalmon1
-238 149 114 LightSalmon2
-205 129 98 LightSalmon3
-139 87 66 LightSalmon4
-255 165 0 orange1
-238 154 0 orange2
-205 133 0 orange3
-139 90 0 orange4
-255 127 0 DarkOrange1
-238 118 0 DarkOrange2
-205 102 0 DarkOrange3
-139 69 0 DarkOrange4
-255 114 86 coral1
-238 106 80 coral2
-205 91 69 coral3
-139 62 47 coral4
-255 99 71 tomato1
-238 92 66 tomato2
-205 79 57 tomato3
-139 54 38 tomato4
-255 69 0 OrangeRed1
-238 64 0 OrangeRed2
-205 55 0 OrangeRed3
-139 37 0 OrangeRed4
-255 0 0 red1
-238 0 0 red2
-205 0 0 red3
-139 0 0 red4
-255 20 147 DeepPink1
-238 18 137 DeepPink2
-205 16 118 DeepPink3
-139 10 80 DeepPink4
-255 110 180 HotPink1
-238 106 167 HotPink2
-205 96 144 HotPink3
-139 58 98 HotPink4
-255 181 197 pink1
-238 169 184 pink2
-205 145 158 pink3
-139 99 108 pink4
-255 174 185 LightPink1
-238 162 173 LightPink2
-205 140 149 LightPink3
-139 95 101 LightPink4
-255 130 171 PaleVioletRed1
-238 121 159 PaleVioletRed2
-205 104 137 PaleVioletRed3
-139 71 93 PaleVioletRed4
-255 52 179 maroon1
-238 48 167 maroon2
-205 41 144 maroon3
-139 28 98 maroon4
-255 62 150 VioletRed1
-238 58 140 VioletRed2
-205 50 120 VioletRed3
-139 34 82 VioletRed4
-255 0 255 magenta1
-238 0 238 magenta2
-205 0 205 magenta3
-139 0 139 magenta4
-255 131 250 orchid1
-238 122 233 orchid2
-205 105 201 orchid3
-139 71 137 orchid4
-255 187 255 plum1
-238 174 238 plum2
-205 150 205 plum3
-139 102 139 plum4
-224 102 255 MediumOrchid1
-209 95 238 MediumOrchid2
-180 82 205 MediumOrchid3
-122 55 139 MediumOrchid4
-191 62 255 DarkOrchid1
-178 58 238 DarkOrchid2
-154 50 205 DarkOrchid3
-104 34 139 DarkOrchid4
-155 48 255 purple1
-145 44 238 purple2
-125 38 205 purple3
- 85 26 139 purple4
-171 130 255 MediumPurple1
-159 121 238 MediumPurple2
-137 104 205 MediumPurple3
- 93 71 139 MediumPurple4
-255 225 255 thistle1
-238 210 238 thistle2
-205 181 205 thistle3
-139 123 139 thistle4
- 0 0 0 gray0
- 0 0 0 grey0
- 3 3 3 gray1
- 3 3 3 grey1
- 5 5 5 gray2
- 5 5 5 grey2
- 8 8 8 gray3
- 8 8 8 grey3
- 10 10 10 gray4
- 10 10 10 grey4
- 13 13 13 gray5
- 13 13 13 grey5
- 15 15 15 gray6
- 15 15 15 grey6
- 18 18 18 gray7
- 18 18 18 grey7
- 20 20 20 gray8
- 20 20 20 grey8
- 23 23 23 gray9
- 23 23 23 grey9
- 26 26 26 gray10
- 26 26 26 grey10
- 28 28 28 gray11
- 28 28 28 grey11
- 31 31 31 gray12
- 31 31 31 grey12
- 33 33 33 gray13
- 33 33 33 grey13
- 36 36 36 gray14
- 36 36 36 grey14
- 38 38 38 gray15
- 38 38 38 grey15
- 41 41 41 gray16
- 41 41 41 grey16
- 43 43 43 gray17
- 43 43 43 grey17
- 46 46 46 gray18
- 46 46 46 grey18
- 48 48 48 gray19
- 48 48 48 grey19
- 51 51 51 gray20
- 51 51 51 grey20
- 54 54 54 gray21
- 54 54 54 grey21
- 56 56 56 gray22
- 56 56 56 grey22
- 59 59 59 gray23
- 59 59 59 grey23
- 61 61 61 gray24
- 61 61 61 grey24
- 64 64 64 gray25
- 64 64 64 grey25
- 66 66 66 gray26
- 66 66 66 grey26
- 69 69 69 gray27
- 69 69 69 grey27
- 71 71 71 gray28
- 71 71 71 grey28
- 74 74 74 gray29
- 74 74 74 grey29
- 77 77 77 gray30
- 77 77 77 grey30
- 79 79 79 gray31
- 79 79 79 grey31
- 82 82 82 gray32
- 82 82 82 grey32
- 84 84 84 gray33
- 84 84 84 grey33
- 87 87 87 gray34
- 87 87 87 grey34
- 89 89 89 gray35
- 89 89 89 grey35
- 92 92 92 gray36
- 92 92 92 grey36
- 94 94 94 gray37
- 94 94 94 grey37
- 97 97 97 gray38
- 97 97 97 grey38
- 99 99 99 gray39
- 99 99 99 grey39
-102 102 102 gray40
-102 102 102 grey40
-105 105 105 gray41
-105 105 105 grey41
-107 107 107 gray42
-107 107 107 grey42
-110 110 110 gray43
-110 110 110 grey43
-112 112 112 gray44
-112 112 112 grey44
-115 115 115 gray45
-115 115 115 grey45
-117 117 117 gray46
-117 117 117 grey46
-120 120 120 gray47
-120 120 120 grey47
-122 122 122 gray48
-122 122 122 grey48
-125 125 125 gray49
-125 125 125 grey49
-127 127 127 gray50
-127 127 127 grey50
-130 130 130 gray51
-130 130 130 grey51
-133 133 133 gray52
-133 133 133 grey52
-135 135 135 gray53
-135 135 135 grey53
-138 138 138 gray54
-138 138 138 grey54
-140 140 140 gray55
-140 140 140 grey55
-143 143 143 gray56
-143 143 143 grey56
-145 145 145 gray57
-145 145 145 grey57
-148 148 148 gray58
-148 148 148 grey58
-150 150 150 gray59
-150 150 150 grey59
-153 153 153 gray60
-153 153 153 grey60
-156 156 156 gray61
-156 156 156 grey61
-158 158 158 gray62
-158 158 158 grey62
-161 161 161 gray63
-161 161 161 grey63
-163 163 163 gray64
-163 163 163 grey64
-166 166 166 gray65
-166 166 166 grey65
-168 168 168 gray66
-168 168 168 grey66
-171 171 171 gray67
-171 171 171 grey67
-173 173 173 gray68
-173 173 173 grey68
-176 176 176 gray69
-176 176 176 grey69
-179 179 179 gray70
-179 179 179 grey70
-181 181 181 gray71
-181 181 181 grey71
-184 184 184 gray72
-184 184 184 grey72
-186 186 186 gray73
-186 186 186 grey73
-189 189 189 gray74
-189 189 189 grey74
-191 191 191 gray75
-191 191 191 grey75
-194 194 194 gray76
-194 194 194 grey76
-196 196 196 gray77
-196 196 196 grey77
-199 199 199 gray78
-199 199 199 grey78
-201 201 201 gray79
-201 201 201 grey79
-204 204 204 gray80
-204 204 204 grey80
-207 207 207 gray81
-207 207 207 grey81
-209 209 209 gray82
-209 209 209 grey82
-212 212 212 gray83
-212 212 212 grey83
-214 214 214 gray84
-214 214 214 grey84
-217 217 217 gray85
-217 217 217 grey85
-219 219 219 gray86
-219 219 219 grey86
-222 222 222 gray87
-222 222 222 grey87
-224 224 224 gray88
-224 224 224 grey88
-227 227 227 gray89
-227 227 227 grey89
-229 229 229 gray90
-229 229 229 grey90
-232 232 232 gray91
-232 232 232 grey91
-235 235 235 gray92
-235 235 235 grey92
-237 237 237 gray93
-237 237 237 grey93
-240 240 240 gray94
-240 240 240 grey94
-242 242 242 gray95
-242 242 242 grey95
-245 245 245 gray96
-245 245 245 grey96
-247 247 247 gray97
-247 247 247 grey97
-250 250 250 gray98
-250 250 250 grey98
-252 252 252 gray99
-252 252 252 grey99
-255 255 255 gray100
-255 255 255 grey100
-169 169 169 dark grey
-169 169 169 DarkGrey
-169 169 169 dark gray
-169 169 169 DarkGray
-0 0 139 dark blue
-0 0 139 DarkBlue
-0 139 139 dark cyan
-0 139 139 DarkCyan
-139 0 139 dark magenta
-139 0 139 DarkMagenta
-139 0 0 dark red
-139 0 0 DarkRed
-144 238 144 light green
-144 238 144 LightGreen
diff --git a/runtime/scripts.vim b/runtime/scripts.vim
index 0ff8e49088..3790b1c10f 100644
--- a/runtime/scripts.vim
+++ b/runtime/scripts.vim
@@ -198,6 +198,10 @@ if s:line1 =~# "^#!"
elseif s:name =~# 'fish\>'
set ft=fish
+ " Gforth
+ elseif s:name =~# 'gforth\>'
+ set ft=forth
+
endif
unlet s:name
diff --git a/runtime/syntax/indent.vim b/runtime/syntax/indent.vim
index ddeae67e0d..b2a1a0c85f 100644
--- a/runtime/syntax/indent.vim
+++ b/runtime/syntax/indent.vim
@@ -1,7 +1,8 @@
" Vim syntax file
-" Language: indent(1) configuration file
-" Previous Maintainer: Nikolai Weibull <now@bitwi.se>
-" Latest Revision: 2010-01-23
+" Language: indent(1) configuration file
+" Maintainer: Doug Kearns <dougkearns@gmail.com>
+" Previous Maintainer: Nikolai Weibull <now@bitwi.se>
+" Last Change: 2021 Nov 17
" indent_is_bsd: If exists, will change somewhat to match BSD implementation
"
" TODO: is the deny-all (a la lilo.vim nice or no?)...
@@ -27,7 +28,7 @@ syn region indentComment start='//' skip='\\$' end='$'
\ contains=indentTodo,@Spell
if !exists("indent_is_bsd")
- syn match indentOptions '-i\|--indentation-level\|-il\|--indent-level'
+ syn match indentOptions '-i\|--indent-level\|-il\|--indent-label'
\ nextgroup=indentNumber skipwhite skipempty
endif
syn match indentOptions '-\%(bli\|c\%([bl]i\|[dip]\)\=\|di\=\|ip\=\|lc\=\|pp\=i\|sbi\|ts\|-\%(brace-indent\|comment-indentation\|case-brace-indentation\|declaration-comment-column\|continuation-indentation\|case-indentation\|else-endif-column\|line-comments-indentation\|declaration-indentation\|indent-level\|parameter-indentation\|line-length\|comment-line-length\|paren-indentation\|preprocessor-indentation\|struct-brace-indentation\|tab-size\)\)'
diff --git a/runtime/syntax/vim.vim b/runtime/syntax/vim.vim
index f7b5ce0f63..d0272916b9 100644
--- a/runtime/syntax/vim.vim
+++ b/runtime/syntax/vim.vim
@@ -741,10 +741,10 @@ if g:vimsyn_embed =~# 'P' && filereadable(s:pythonpath)
unlet! b:current_syntax
syn cluster vimFuncBodyList add=vimPythonRegion
exe "syn include @vimPythonScript ".s:pythonpath
- VimFoldP syn region vimPythonRegion matchgroup=vimScriptDelim start=+py\%[thon][3x]\=\s*<<\s*\z(\S*\)\ze\(\s*#.*\)\=$+ end=+^\z1\ze\(\s*".*\)\=$+ contains=@vimPythonScript
- VimFoldP syn region vimPythonRegion matchgroup=vimScriptDelim start=+py\%[thon][3x]\=\s*<<\s*$+ end=+\.$+ contains=@vimPythonScript
- VimFoldP syn region vimPythonRegion matchgroup=vimScriptDelim start=+Py\%[thon]2or3\s*<<\s*\z(\S*\)\ze\(\s*#.*\)\=$+ end=+^\z1\ze\(\s*".*\)\=$+ contains=@vimPythonScript
- VimFoldP syn region vimPythonRegion matchgroup=vimScriptDelim start=+Py\%[thon]2or3\=\s*<<\s*$+ end=+\.$+ contains=@vimPythonScript
+ VimFoldP syn region vimPythonRegion matchgroup=vimScriptDelim start=+py\%[thon][3x]\=\s*<<\s*\%(trim\s*\)\=\z(\S*\)\ze\(\s*#.*\)\=$+ end=+^\z1\ze\(\s*".*\)\=$+ contains=@vimPythonScript
+ VimFoldP syn region vimPythonRegion matchgroup=vimScriptDelim start=+py\%[thon][3x]\=\s*<<\s*\%(trim\s*\)\=$+ end=+\.$+ contains=@vimPythonScript
+ VimFoldP syn region vimPythonRegion matchgroup=vimScriptDelim start=+Py\%[thon]2or3\s*<<\s*\%(trim\s*\)\=\z(\S*\)\ze\(\s*#.*\)\=$+ end=+^\z1\ze\(\s*".*\)\=$+ contains=@vimPythonScript
+ VimFoldP syn region vimPythonRegion matchgroup=vimScriptDelim start=+Py\%[thon]2or3\=\s*<<\s*\%(trim\s*\)\=$+ end=+\.$+ contains=@vimPythonScript
syn cluster vimFuncBodyList add=vimPythonRegion
else
syn region vimEmbedError start=+py\%[thon]3\=\s*<<\s*\z(.*\)$+ end=+^\z1$+
diff --git a/runtime/tools/check_colors.vim b/runtime/tools/check_colors.vim
index 966072c706..85df882d1e 100644
--- a/runtime/tools/check_colors.vim
+++ b/runtime/tools/check_colors.vim
@@ -226,7 +226,13 @@ fu! Result(err)
endif
endfu
-call Test_check_colors()
-
-let &cpo = s:save_cpo
-unlet s:save_cpo
+try
+ call Test_check_colors()
+catch
+ echohl ErrorMsg
+ echomsg v:exception
+ echohl NONE
+finally
+ let &cpo = s:save_cpo
+ unlet s:save_cpo
+endtry
diff --git a/scripts/gen_vimdoc.py b/scripts/gen_vimdoc.py
index 2d2d46d1bd..89fc14121e 100755
--- a/scripts/gen_vimdoc.py
+++ b/scripts/gen_vimdoc.py
@@ -162,6 +162,7 @@ CONFIG = {
'buf.lua',
'diagnostic.lua',
'codelens.lua',
+ 'tagfunc.lua',
'handlers.lua',
'util.lua',
'log.lua',
diff --git a/scripts/lintcommit.lua b/scripts/lintcommit.lua
index c30a1b10da..0a7da4d4ef 100644
--- a/scripts/lintcommit.lua
+++ b/scripts/lintcommit.lua
@@ -47,7 +47,7 @@ end
local function validate_commit(commit_message)
local commit_split = vim.split(commit_message, ":")
- -- Return true if the type is vim-patch since most of the normal rules don't
+ -- Return nil if the type is vim-patch since most of the normal rules don't
-- apply.
if commit_split[1] == "vim-patch" then
return nil
diff --git a/src/mpack/object.h b/src/mpack/object.h
index 5327e56e18..e69821f9de 100644
--- a/src/mpack/object.h
+++ b/src/mpack/object.h
@@ -22,7 +22,7 @@ enum {
};
/* Storing integer in pointers in undefined behavior according to the C
- * standard. Define a union type to accomodate arbitrary user data associated
+ * standard. Define a union type to accommodate arbitrary user data associated
* with nodes(and with requests in rpc.h). */
typedef union {
void *p;
diff --git a/src/nvim/api/buffer.c b/src/nvim/api/buffer.c
index 4076a0d220..718743ed9c 100644
--- a/src/nvim/api/buffer.c
+++ b/src/nvim/api/buffer.c
@@ -535,7 +535,7 @@ end:
/// @param channel_id
/// @param buffer Buffer handle, or 0 for current buffer
/// @param start_row First line index
-/// @param start_column Last column
+/// @param start_column First column
/// @param end_row Last line index
/// @param end_column Last column
/// @param replacement Array of lines to use as replacement
@@ -1246,7 +1246,7 @@ ArrayOf(Integer, 2) nvim_buf_get_mark(Buffer buffer, String name, Error *err)
/// If the current window already shows "buffer", the window is not switched
/// If a window inside the current tabpage (including a float) already shows the
/// buffer One of these windows will be set as current window temporarily.
-/// Otherwise a temporary scratch window (calleed the "autocmd window" for
+/// Otherwise a temporary scratch window (called the "autocmd window" for
/// historical reasons) will be used.
///
/// This is useful e.g. to call vimL functions that only work with the current
diff --git a/src/nvim/api/extmark.c b/src/nvim/api/extmark.c
index 6f1fb15dac..6e25e627b9 100644
--- a/src/nvim/api/extmark.c
+++ b/src/nvim/api/extmark.c
@@ -839,7 +839,7 @@ void nvim_buf_clear_namespace(Buffer buffer, Integer ns_id, Integer line_start,
/// - on_win: called when starting to redraw a specific window.
/// ["win", winid, bufnr, topline, botline_guess]
/// - on_line: called for each buffer line being redrawn. (The
-/// interation with fold lines is subject to change)
+/// interaction with fold lines is subject to change)
/// ["win", winid, bufnr, row]
/// - on_end: called at the end of a redraw cycle
/// ["end", tick]
diff --git a/src/nvim/api/vimscript.c b/src/nvim/api/vimscript.c
index c516cedaf4..640144b234 100644
--- a/src/nvim/api/vimscript.c
+++ b/src/nvim/api/vimscript.c
@@ -390,7 +390,7 @@ Dictionary nvim_parse_expression(String expr, String flags, Boolean highlight, E
FUNC_API_SINCE(4) FUNC_API_FAST
{
int pflags = 0;
- for (size_t i = 0 ; i < flags.size ; i++) {
+ for (size_t i = 0; i < flags.size; i++) {
switch (flags.data[i]) {
case 'm':
pflags |= kExprFlagsMulti; break;
@@ -478,7 +478,7 @@ Dictionary nvim_parse_expression(String expr, String flags, Boolean highlight, E
.capacity = kv_size(colors),
.size = kv_size(colors),
};
- for (size_t i = 0 ; i < kv_size(colors) ; i++) {
+ for (size_t i = 0; i < kv_size(colors); i++) {
const ParserHighlightChunk chunk = kv_A(colors, i);
Array chunk_arr = (Array) {
.items = xmalloc(4 * sizeof(chunk_arr.items[0])),
diff --git a/src/nvim/auevents.lua b/src/nvim/auevents.lua
index bd30966acf..1daae85c5e 100644
--- a/src/nvim/auevents.lua
+++ b/src/nvim/auevents.lua
@@ -37,6 +37,7 @@ return {
'CursorHoldI', -- idem, in Insert mode
'CursorMoved', -- cursor was moved
'CursorMovedI', -- cursor was moved in Insert mode
+ 'DiagnosticChanged', -- diagnostics in a buffer were modified
'DiffUpdated', -- diffs have been updated
'DirChanged', -- directory changed
'EncodingChanged', -- after changing the 'encoding' option
@@ -127,6 +128,7 @@ return {
-- syntax file
nvim_specific = {
BufModifiedSet=true,
+ DiagnosticChanged=true,
DirChanged=true,
Signal=true,
TabClosed=true,
diff --git a/src/nvim/buffer.c b/src/nvim/buffer.c
index 88938d5099..f2f4950e58 100644
--- a/src/nvim/buffer.c
+++ b/src/nvim/buffer.c
@@ -1305,7 +1305,7 @@ int do_buffer(int action, int start, int dir, int count, int forceit)
if (buf == NULL) { // No previous buffer, Try 2'nd approach
forward = true;
buf = curbuf->b_next;
- for (;; ) {
+ for (;;) {
if (buf == NULL) {
if (!forward) { // tried both directions
break;
@@ -1587,7 +1587,7 @@ void do_autochdir(void)
if (starting == 0
&& curbuf->b_ffname != NULL
&& vim_chdirfile(curbuf->b_ffname, kCdCauseAuto) == OK) {
- post_chdir(kCdScopeGlobal, false);
+ last_chdir_reason = "autochdir";
shorten_fnames(true);
}
}
@@ -2163,7 +2163,7 @@ int buflist_findpat(const char_u *pattern, const char_u *pattern_end, bool unlis
// First try finding a listed buffer. If not found and "unlisted"
// is true, try finding an unlisted buffer.
find_listed = true;
- for (;; ) {
+ for (;;) {
for (attempt = 0; attempt <= 3; attempt++) {
// may add '^' and '$'
if (toggledollar) {
@@ -3511,7 +3511,7 @@ int build_stl_str_hl(win_T *wp, char_u *out, size_t outlen, char_u *fmt, int use
// Proceed character by character through the statusline format string
// fmt_p is the current position in the input buffer
- for (char_u *fmt_p = usefmt; *fmt_p; ) {
+ for (char_u *fmt_p = usefmt; *fmt_p;) {
if (curitem == (int)stl_items_len) {
size_t new_len = stl_items_len * 3 / 2;
@@ -4407,7 +4407,7 @@ int build_stl_str_hl(win_T *wp, char_u *out, size_t outlen, char_u *fmt, int use
// string to find the last character that will fit.
trunc_p = out;
width = 0;
- for (;; ) {
+ for (;;) {
width += ptr2cells(trunc_p);
if (width >= maxwidth) {
break;
@@ -4758,7 +4758,7 @@ void do_arg_all(int count, int forceit, int keep_tabs)
if (had_tab > 0) {
goto_tabpage_tp(first_tabpage, true, true);
}
- for (;; ) {
+ for (;;) {
win_T *wpnext = NULL;
tpnext = curtab->tp_next;
for (win_T *wp = firstwin; wp != NULL; wp = wpnext) {
@@ -5009,7 +5009,7 @@ void ex_buffer_all(exarg_T *eap)
if (had_tab > 0) {
goto_tabpage_tp(first_tabpage, true, true);
}
- for (;; ) {
+ for (;;) {
tpnext = curtab->tp_next;
for (wp = firstwin; wp != NULL; wp = wpnext) {
wpnext = wp->w_next;
@@ -5020,8 +5020,8 @@ void ex_buffer_all(exarg_T *eap)
: wp->w_width != Columns)
|| (had_tab > 0 && wp != firstwin))
&& !ONE_WINDOW
- && !(wp->w_closing ||
- wp->w_buffer->b_locked > 0)) {
+ && !(wp->w_closing
+ || wp->w_buffer->b_locked > 0)) {
win_close(wp, false);
wpnext = firstwin; // just in case an autocommand does
// something strange with windows
@@ -5138,7 +5138,7 @@ void ex_buffer_all(exarg_T *eap)
/*
* Close superfluous windows.
*/
- for (wp = lastwin; open_wins > count; ) {
+ for (wp = lastwin; open_wins > count;) {
r = (buf_hide(wp->w_buffer) || !bufIsChanged(wp->w_buffer)
|| autowrite(wp->w_buffer, false) == OK);
if (!win_valid(wp)) {
diff --git a/src/nvim/buffer_defs.h b/src/nvim/buffer_defs.h
index 3d7b03d921..e53b2d1dfa 100644
--- a/src/nvim/buffer_defs.h
+++ b/src/nvim/buffer_defs.h
@@ -1127,14 +1127,14 @@ typedef struct {
/// @{
enum {
MENU_INDEX_INVALID = -1,
- MENU_INDEX_NORMAL = 0,
- MENU_INDEX_VISUAL = 1,
- MENU_INDEX_SELECT = 2,
- MENU_INDEX_OP_PENDING = 3,
- MENU_INDEX_INSERT = 4,
- MENU_INDEX_CMDLINE = 5,
- MENU_INDEX_TIP = 6,
- MENU_MODES = 7,
+ MENU_INDEX_NORMAL = 0,
+ MENU_INDEX_VISUAL = 1,
+ MENU_INDEX_SELECT = 2,
+ MENU_INDEX_OP_PENDING = 3,
+ MENU_INDEX_INSERT = 4,
+ MENU_INDEX_CMDLINE = 5,
+ MENU_INDEX_TIP = 6,
+ MENU_MODES = 7,
};
typedef struct VimMenu vimmenu_T;
diff --git a/src/nvim/change.c b/src/nvim/change.c
index 6ec4979dac..ef771125f1 100644
--- a/src/nvim/change.c
+++ b/src/nvim/change.c
@@ -625,7 +625,7 @@ void ins_char_bytes(char_u *buf, size_t charlen)
}
}
- char_u *newp = xmalloc((size_t)(linelen + newlen - oldlen));
+ char_u *newp = xmalloc(linelen + newlen - oldlen);
// Copy bytes before the cursor.
if (col > 0) {
@@ -1355,7 +1355,7 @@ int open_line(int dir, int flags, int second_line_indent)
int c = 0;
int off = 0;
- for (p = lead_flags; *p != NUL && *p != ':'; ) {
+ for (p = lead_flags; *p != NUL && *p != ':';) {
if (*p == COM_RIGHT || *p == COM_LEFT) {
c = *p++;
} else if (ascii_isdigit(*p) || *p == '-') {
@@ -1841,7 +1841,7 @@ void del_lines(long nlines, bool undo)
return;
}
- for (n = 0; n < nlines; ) {
+ for (n = 0; n < nlines;) {
if (curbuf->b_ml.ml_flags & ML_EMPTY) { // nothing to delete
break;
}
diff --git a/src/nvim/cursor_shape.c b/src/nvim/cursor_shape.c
index 644bb2c324..6b0a5dfe12 100644
--- a/src/nvim/cursor_shape.c
+++ b/src/nvim/cursor_shape.c
@@ -168,7 +168,7 @@ char *parse_shape_opt(int what)
}
// Parse the part after the colon
- for (p = colonp + 1; *p && *p != ','; ) {
+ for (p = colonp + 1; *p && *p != ',';) {
{
/*
* First handle the ones with a number argument.
diff --git a/src/nvim/debugger.c b/src/nvim/debugger.c
index 3ac128a20f..b6e35f3047 100644
--- a/src/nvim/debugger.c
+++ b/src/nvim/debugger.c
@@ -109,7 +109,7 @@ void do_debug(char_u *cmd)
smsg(_("cmd: %s"), cmd);
}
// Repeat getting a command and executing it.
- for (;; ) {
+ for (;;) {
msg_scroll = true;
need_wait_return = false;
// Save the current typeahead buffer and replace it with an empty one.
diff --git a/src/nvim/diff.c b/src/nvim/diff.c
index 4e03f4761c..1f8acd8c79 100644
--- a/src/nvim/diff.c
+++ b/src/nvim/diff.c
@@ -739,7 +739,7 @@ static int diff_write_buffer(buf_T *buf, diffin_T *din)
len = 0;
for (lnum = 1; lnum <= buf->b_ml.ml_line_count; lnum++) {
- for (s = ml_get_buf(buf, lnum, false); *s != NUL; ) {
+ for (s = ml_get_buf(buf, lnum, false); *s != NUL;) {
if (diff_flags & DIFF_ICASE) {
char_u cbuf[MB_MAXBYTES + 1];
diff --git a/src/nvim/edit.c b/src/nvim/edit.c
index cccb33b792..f171897606 100644
--- a/src/nvim/edit.c
+++ b/src/nvim/edit.c
@@ -4173,7 +4173,7 @@ static int ins_compl_get_exp(pos_T *ini)
pos = (compl_direction == FORWARD) ? &last_match_pos : &first_match_pos;
// For ^N/^P loop over all the flags/windows/buffers in 'complete'
- for (;; ) {
+ for (;;) {
found_new_match = FAIL;
set_match_pos = false;
@@ -4391,7 +4391,7 @@ static int ins_compl_get_exp(pos_T *ini)
p_ws = true;
}
bool looped_around = false;
- for (;; ) {
+ for (;;) {
bool cont_s_ipos = false;
msg_silent++; // Don't want messages for wrapscan.
@@ -5579,7 +5579,7 @@ int get_literal(void)
no_mapping++; // don't map the next key hits
cc = 0;
i = 0;
- for (;; ) {
+ for (;;) {
nc = plain_vgetc();
if (!(State & CMDLINE)
&& MB_BYTE2LEN_CHECK(nc) == 1) {
@@ -6686,7 +6686,7 @@ static void stop_insert(pos_T *end_insert_pos, int esc, int nomove)
curwin->w_cursor = *end_insert_pos;
check_cursor_col(); // make sure it is not past the line
- for (;; ) {
+ for (;;) {
if (gchar_cursor() == NUL && curwin->w_cursor.col > 0) {
--curwin->w_cursor.col;
}
@@ -6877,7 +6877,7 @@ int oneleft(void)
// We might get stuck on 'showbreak', skip over it.
width = 1;
- for (;; ) {
+ for (;;) {
coladvance(v - width);
// getviscol() is slow, skip it when 'showbreak' is empty,
// 'breakindent' is not set and there are no multi-byte
@@ -7211,7 +7211,7 @@ static void replace_join(int off)
{
int i;
- for (i = replace_stack_nr; --i >= 0; ) {
+ for (i = replace_stack_nr; --i >= 0;) {
if (replace_stack[i] == NUL && off-- <= 0) {
--replace_stack_nr;
memmove(replace_stack + i, replace_stack + i + 1,
@@ -7260,7 +7260,7 @@ static void mb_replace_pop_ins(int cc)
}
// Handle composing chars.
- for (;; ) {
+ for (;;) {
c = replace_pop();
if (c == -1) { // stack empty
break;
@@ -9023,7 +9023,7 @@ static bool ins_tab(void)
// correct replace stack.
if ((State & REPLACE_FLAG)
&& !(State & VREPLACE_FLAG)) {
- for (temp = i; --temp >= 0; ) {
+ for (temp = i; --temp >= 0;) {
replace_join(repl_off);
}
}
diff --git a/src/nvim/eval.c b/src/nvim/eval.c
index 0123c7265b..d3d0121632 100644
--- a/src/nvim/eval.c
+++ b/src/nvim/eval.c
@@ -1551,7 +1551,7 @@ static const char_u *skip_var_list(const char_u *arg, int *var_count, int *semic
if (*arg == '[') {
// "[var, var]": find the matching ']'.
p = arg;
- for (;; ) {
+ for (;;) {
p = skipwhite(p + 1); // skip whites after '[', ';' or ','
s = skip_var_one(p);
if (s == p) {
@@ -2448,7 +2448,7 @@ static void set_var_lval(lval_T *lp, char_u *endp, typval_T *rettv, int copy, co
// Check whether any of the list items is locked
for (ri = tv_list_first(rettv->vval.v_list);
- ri != NULL && ll_li != NULL; ) {
+ ri != NULL && ll_li != NULL;) {
if (var_check_lock(TV_LIST_ITEM_TV(ll_li)->v_lock, lp->ll_name,
TV_CSTRING)) {
return;
@@ -2464,7 +2464,7 @@ static void set_var_lval(lval_T *lp, char_u *endp, typval_T *rettv, int copy, co
/*
* Assign the List values to the list items.
*/
- for (ri = tv_list_first(rettv->vval.v_list); ri != NULL; ) {
+ for (ri = tv_list_first(rettv->vval.v_list); ri != NULL;) {
if (op != NULL && *op != '=') {
eexe_mod_op(TV_LIST_ITEM_TV(lp->ll_li), TV_LIST_ITEM_TV(ri), op);
} else {
@@ -2691,7 +2691,7 @@ void set_context_for_expression(expand_T *xp, char_u *arg, cmdidx_T cmdidx)
xp->xp_context = EXPAND_USER_VARS;
if (vim_strpbrk(arg, (char_u *)"\"'+-*/%.=!?~|&$([<>,#") == NULL) {
// ":let var1 var2 ...": find last space.
- for (p = arg + STRLEN(arg); p >= arg; ) {
+ for (p = arg + STRLEN(arg); p >= arg;) {
xp->xp_pattern = p;
MB_PTR_BACK(arg, p);
if (ascii_iswhite(*p)) {
@@ -3732,7 +3732,7 @@ static int eval5(char_u **arg, typval_T *rettv, int evaluate)
/*
* Repeat computing, until no '+', '-' or '.' is following.
*/
- for (;; ) {
+ for (;;) {
op = **arg;
if (op != '+' && op != '-' && op != '.') {
break;
@@ -3907,7 +3907,7 @@ static int eval6(char_u **arg, typval_T *rettv, int evaluate, int want_string)
/*
* Repeat computing, until no '*', '/' or '%' is following.
*/
- for (;; ) {
+ for (;;) {
op = **arg;
if (op != '*' && op != '/' && op != '%') {
break;
@@ -4890,7 +4890,7 @@ static int get_string_tv(char_u **arg, typval_T *rettv, int evaluate)
rettv->v_type = VAR_STRING;
rettv->vval.v_string = name;
- for (p = *arg + 1; *p != NUL && *p != '"'; ) {
+ for (p = *arg + 1; *p != NUL && *p != '"';) {
if (*p == '\\') {
switch (*++p) {
case 'b':
@@ -5026,7 +5026,7 @@ static int get_lit_string_tv(char_u **arg, typval_T *rettv, int evaluate)
rettv->v_type = VAR_STRING;
rettv->vval.v_string = str;
- for (p = *arg + 1; *p != NUL; ) {
+ for (p = *arg + 1; *p != NUL;) {
if (*p == '\'') {
if (p[1] != '\'') {
break;
@@ -6086,7 +6086,7 @@ int assert_equalfile(typval_T *argvars)
snprintf((char *)IObuff, IOSIZE, (char *)e_notread, fname2);
} else {
int64_t linecount = 1;
- for (int64_t count = 0; ; count++) {
+ for (int64_t count = 0;; count++) {
const int c1 = fgetc(fd1);
const int c2 = fgetc(fd2);
if (c1 == EOF) {
@@ -6851,7 +6851,7 @@ dict_T *get_win_info(win_T *wp, int16_t tpnr, int16_t winnr)
tv_dict_add_nr(dict, S_LEN("width"), wp->w_width);
tv_dict_add_nr(dict, S_LEN("bufnr"), wp->w_buffer->b_fnum);
tv_dict_add_nr(dict, S_LEN("wincol"), wp->w_wincol + 1);
-
+ tv_dict_add_nr(dict, S_LEN("textoff"), win_col_off(wp));
tv_dict_add_nr(dict, S_LEN("terminal"), bt_terminal(wp->w_buffer));
tv_dict_add_nr(dict, S_LEN("quickfix"), bt_quickfix(wp->w_buffer));
tv_dict_add_nr(dict, S_LEN("loclist"),
@@ -7382,7 +7382,7 @@ void set_buffer_lines(buf_T *buf, linenr_T lnum_arg, bool append, const typval_T
}
// Default result is zero == OK.
- for (;; ) {
+ for (;;) {
if (lines->v_type == VAR_LIST) {
// List argument, get next string.
if (li == NULL) {
diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c
index 7549ec7ac8..dfadd28ebe 100644
--- a/src/nvim/eval/funcs.c
+++ b/src/nvim/eval/funcs.c
@@ -2663,12 +2663,12 @@ static void f_fnamemodify(typval_T *argvars, typval_T *rettv, FunPtr fptr)
char buf[NUMBUFLEN];
const char *fname = tv_get_string_chk(&argvars[0]);
const char *const mods = tv_get_string_buf_chk(&argvars[1], buf);
- if (fname == NULL) {
+ if (mods == NULL || fname == NULL) {
fname = NULL;
- } else if (mods != NULL && *mods != NUL) {
+ } else {
len = strlen(fname);
- size_t usedlen = 0;
if (*mods != NUL) {
+ size_t usedlen = 0;
(void)modify_fname((char_u *)mods, false, &usedlen,
(char_u **)&fname, &fbuf, &len);
}
@@ -3174,7 +3174,7 @@ static void getchar_common(typval_T *argvars, typval_T *rettv)
bool error = false;
no_mapping++;
- for (;; ) {
+ for (;;) {
// Position the cursor. Needed after a message that ends in a space,
// or if event processing caused a redraw.
ui_cursor_goto(msg_row, msg_col);
@@ -3386,15 +3386,17 @@ static void f_getcompletion(typval_T *argvars, typval_T *rettv, FunPtr fptr)
emsg(_(e_invarg));
return;
}
+ const char *pattern = tv_get_string(&argvars[0]);
if (strcmp(type, "cmdline") == 0) {
- set_one_cmd_context(&xpc, tv_get_string(&argvars[0]));
+ set_one_cmd_context(&xpc, pattern);
xpc.xp_pattern_len = STRLEN(xpc.xp_pattern);
+ xpc.xp_col = STRLEN(pattern);
goto theend;
}
ExpandInit(&xpc);
- xpc.xp_pattern = (char_u *)tv_get_string(&argvars[0]);
+ xpc.xp_pattern = (char_u *)pattern;
xpc.xp_pattern_len = STRLEN(xpc.xp_pattern);
xpc.xp_context = cmdcomplete_str_to_type(type);
if (xpc.xp_context == EXPAND_NOTHING) {
@@ -3447,7 +3449,7 @@ static void f_getcwd(typval_T *argvars, typval_T *rettv, FunPtr fptr)
// Numbers of the scope objects (window, tab) we want the working directory
// of. A `-1` means to skip this scope, a `0` means the current object.
int scope_number[] = {
- [kCdScopeWindow ] = 0, // Number of window to look at.
+ [kCdScopeWindow] = 0, // Number of window to look at.
[kCdScopeTabpage] = 0, // Number of tab to look at.
};
@@ -3485,11 +3487,6 @@ static void f_getcwd(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
}
- // If the user didn't specify anything, default to window scope
- if (scope == kCdScopeInvalid) {
- scope = MIN_CD_SCOPE;
- }
-
// Find the tabpage by number
if (scope_number[kCdScopeTabpage] > 0) {
tp = find_tabpage(scope_number[kCdScopeTabpage]);
@@ -3535,12 +3532,13 @@ static void f_getcwd(typval_T *argvars, typval_T *rettv, FunPtr fptr)
case kCdScopeGlobal:
if (globaldir) { // `globaldir` is not always set.
from = globaldir;
- } else if (os_dirname(cwd, MAXPATHL) == FAIL) { // Get the OS CWD.
+ break;
+ }
+ FALLTHROUGH; // In global directory, just need to get OS CWD.
+ case kCdScopeInvalid: // If called without any arguments, get OS CWD.
+ if (os_dirname(cwd, MAXPATHL) == FAIL) {
from = (char_u *)""; // Return empty string on failure.
}
- break;
- case kCdScopeInvalid: // We should never get here
- abort();
}
if (from) {
@@ -4667,7 +4665,7 @@ static void f_haslocaldir(typval_T *argvars, typval_T *rettv, FunPtr fptr)
// Numbers of the scope objects (window, tab) we want the working directory
// of. A `-1` means to skip this scope, a `0` means the current object.
int scope_number[] = {
- [kCdScopeWindow ] = 0, // Number of window to look at.
+ [kCdScopeWindow] = 0, // Number of window to look at.
[kCdScopeTabpage] = 0, // Number of tab to look at.
};
@@ -6182,7 +6180,7 @@ static void find_some_match(typval_T *const argvars, typval_T *const rettv,
if (regmatch.regprog != NULL) {
regmatch.rm_ic = p_ic;
- for (;; ) {
+ for (;;) {
if (l != NULL) {
if (li == NULL) {
match = false;
@@ -7727,8 +7725,8 @@ static void f_resolve(typval_T *argvars, typval_T *rettv, FunPtr fptr)
char *const buf = xmallocz(MAXPATHL);
char *cpy;
- for (;; ) {
- for (;; ) {
+ for (;;) {
+ for (;;) {
len = readlink(p, buf, MAXPATHL);
if (len <= 0) {
break;
@@ -8603,7 +8601,7 @@ long do_searchpair(const char *spat, const char *mpat, const char *epat, int dir
clearpos(&firstpos);
clearpos(&foundpos);
pat = pat3;
- for (;; ) {
+ for (;;) {
searchit_arg_T sia;
memset(&sia, 0, sizeof(sia));
sia.sa_stop_lnum = lnum_stop;
diff --git a/src/nvim/eval/typval.h b/src/nvim/eval/typval.h
index 69732f1a7d..d1275d6512 100644
--- a/src/nvim/eval/typval.h
+++ b/src/nvim/eval/typval.h
@@ -141,7 +141,7 @@ typedef struct {
dict_T *v_dict; ///< Dictionary for VAR_DICT, can be NULL.
partial_T *v_partial; ///< Closure: function with args.
blob_T *v_blob; ///< Blob for VAR_BLOB, can be NULL.
- } vval; ///< Actual value.
+ } vval; ///< Actual value.
} typval_T;
/// Values for (struct dictvar_S).dv_scope
diff --git a/src/nvim/eval/userfunc.c b/src/nvim/eval/userfunc.c
index 80a22f6f9d..9478a8441b 100644
--- a/src/nvim/eval/userfunc.c
+++ b/src/nvim/eval/userfunc.c
@@ -2141,7 +2141,7 @@ void ex_function(exarg_T *eap)
}
// find extra arguments "range", "dict", "abort" and "closure"
- for (;; ) {
+ for (;;) {
p = skipwhite(p);
if (STRNCMP(p, "range", 5) == 0) {
flags |= FC_RANGE;
@@ -2204,7 +2204,7 @@ void ex_function(exarg_T *eap)
indent = 2;
nesting = 0;
- for (;; ) {
+ for (;;) {
if (KeyTyped) {
msg_scroll = true;
saved_wait_return = false;
diff --git a/src/nvim/ex_cmds.c b/src/nvim/ex_cmds.c
index 66e30bdf2b..77944851d2 100644
--- a/src/nvim/ex_cmds.c
+++ b/src/nvim/ex_cmds.c
@@ -303,7 +303,7 @@ void ex_align(exarg_T *eap)
* Now try to move the line as much as possible to
* the right. Stop when it moves too far.
*/
- do{
+ do {
(void)set_indent(++new_indent, 0);
}
while (linelen(NULL) <= width);
@@ -774,7 +774,7 @@ void ex_retab(exarg_T *eap)
col = 0;
vcol = 0;
did_undo = false;
- for (;; ) {
+ for (;;) {
if (ascii_iswhite(ptr[col])) {
if (!got_tab && num_spaces == 0) {
// First consecutive white-space
@@ -2150,7 +2150,7 @@ static int check_readonly(int *forceit, buf_T *buf)
if (buf->b_p_ro) {
dialog_msg(buff,
- _( "'readonly' option is set for \"%s\".\nDo you wish to write anyway?"),
+ _("'readonly' option is set for \"%s\".\nDo you wish to write anyway?"),
buf->b_fname);
} else {
dialog_msg(buff,
@@ -2944,7 +2944,7 @@ void ex_append(exarg_T *eap)
State |= LANGMAP;
}
- for (;; ) {
+ for (;;) {
msg_scroll = TRUE;
need_wait_return = false;
if (curbuf->b_p_ai) {
@@ -3719,7 +3719,7 @@ static buf_T *do_sub(exarg_T *eap, proftime_T timeout, bool do_buf_event, handle
* 4. if subflags.do_all is set, find next match
* 5. break if there isn't another match in this line
*/
- for (;; ) {
+ for (;;) {
SubResult current_match = {
.start = { 0, 0 },
.end = { 0, 0 },
@@ -5030,9 +5030,9 @@ int find_help_tags(const char_u *arg, int *num_matches, char_u ***matches, bool
// When the string starting with "expr-" and containing '?' and matches
// the table, it is taken literally (but ~ is escaped). Otherwise '?'
// is recognized as a wildcard.
- for (i = (int)ARRAY_SIZE(expr_table); --i >= 0; ) {
+ for (i = (int)ARRAY_SIZE(expr_table); --i >= 0;) {
if (STRCMP(arg + 5, expr_table[i]) == 0) {
- for (int si = 0, di = 0; ; si++) {
+ for (int si = 0, di = 0;; si++) {
if (arg[si] == '~') {
d[di++] = '\\';
}
@@ -5047,7 +5047,7 @@ int find_help_tags(const char_u *arg, int *num_matches, char_u ***matches, bool
} else {
// Recognize a few exceptions to the rule. Some strings that contain
// '*' with "star". Otherwise '*' is recognized as a wildcard.
- for (i = (int)ARRAY_SIZE(mtable); --i >= 0; ) {
+ for (i = (int)ARRAY_SIZE(mtable); --i >= 0;) {
if (STRCMP(arg, mtable[i]) == 0) {
STRCPY(d, rtable[i]);
break;
diff --git a/src/nvim/ex_cmds2.c b/src/nvim/ex_cmds2.c
index 787b3f07b2..449e6f7bf5 100644
--- a/src/nvim/ex_cmds2.c
+++ b/src/nvim/ex_cmds2.c
@@ -410,7 +410,7 @@ static void script_dump_profile(FILE *fd)
} else {
// Keep going till the end of file, so that trailing
// continuation lines are listed.
- for (int i = 0; ; i++) {
+ for (int i = 0;; i++) {
if (vim_fgets(IObuff, IOSIZE, sfd)) {
break;
}
@@ -2505,7 +2505,7 @@ static char_u *get_one_sourceline(struct source_cookie *sp)
// Loop until there is a finished line (or end-of-file).
sp->sourcing_lnum++;
- for (;; ) {
+ for (;;) {
// make room to read at least 120 (more) characters
ga_grow(&ga, 120);
buf = (char_u *)ga.ga_data;
diff --git a/src/nvim/ex_cmds_defs.h b/src/nvim/ex_cmds_defs.h
index 6e5dd144ad..ea899b660b 100644
--- a/src/nvim/ex_cmds_defs.h
+++ b/src/nvim/ex_cmds_defs.h
@@ -135,10 +135,10 @@ typedef struct {
// Flags for the cs_lflags item in cstack_T.
enum {
- CSL_HAD_LOOP = 1, // just found ":while" or ":for"
+ CSL_HAD_LOOP = 1, // just found ":while" or ":for"
CSL_HAD_ENDLOOP = 2, // just found ":endwhile" or ":endfor"
- CSL_HAD_CONT = 4, // just found ":continue"
- CSL_HAD_FINA = 8, // just found ":finally"
+ CSL_HAD_CONT = 4, // just found ":continue"
+ CSL_HAD_FINA = 8, // just found ":finally"
};
/// Arguments used for Ex commands.
diff --git a/src/nvim/ex_docmd.c b/src/nvim/ex_docmd.c
index 03d85ea888..024eb0a904 100644
--- a/src/nvim/ex_docmd.c
+++ b/src/nvim/ex_docmd.c
@@ -433,8 +433,8 @@ int do_cmdline(char_u *cmdline, LineGetter fgetline, void *cookie, int flags)
if (next_cmdline == NULL
&& !force_abort
&& cstack.cs_idx < 0
- && !(getline_is_func &&
- func_has_abort(real_cookie))) {
+ && !(getline_is_func
+ && func_has_abort(real_cookie))) {
did_emsg = FALSE;
}
@@ -819,7 +819,7 @@ int do_cmdline(char_u *cmdline, LineGetter fgetline, void *cookie, int flags)
// of interrupts or errors to exceptions, and ensure that no more
// commands are executed.
if (current_exception) {
- void *p = NULL;
+ char *p = NULL;
char_u *saved_sourcing_name;
int saved_sourcing_lnum;
struct msglist *messages = NULL;
@@ -836,7 +836,7 @@ int do_cmdline(char_u *cmdline, LineGetter fgetline, void *cookie, int flags)
vim_snprintf((char *)IObuff, IOSIZE,
_("E605: Exception not caught: %s"),
current_exception->value);
- p = vim_strsave(IObuff);
+ p = (char *)vim_strsave(IObuff);
break;
case ET_ERROR:
messages = current_exception->messages;
@@ -2066,7 +2066,7 @@ int parse_command_modifiers(exarg_T *eap, char **errormsg, bool skip_only)
eap->save_msg_silent = -1;
// Repeat until no more command modifiers are found.
- for (;; ) {
+ for (;;) {
while (*eap->cmd == ' '
|| *eap->cmd == '\t'
|| *eap->cmd == ':') {
@@ -2716,7 +2716,7 @@ static char_u *find_ucmd(exarg_T *eap, char_u *p, int *full, expand_T *xp, int *
* Look for buffer-local user commands first, then global ones.
*/
gap = &curbuf->b_ucmds;
- for (;; ) {
+ for (;;) {
for (j = 0; j < gap->ga_len; ++j) {
uc = USER_CMD_GA(gap, j);
cp = eap->cmd;
@@ -4072,7 +4072,7 @@ static linenr_T get_address(exarg_T *eap, char_u **ptr, cmd_addr_T addr_type, in
}
}
- for (;; ) {
+ for (;;) {
cmd = skipwhite(cmd);
if (*cmd != '-' && *cmd != '+' && !ascii_isdigit(*cmd)) {
break;
@@ -5327,7 +5327,7 @@ static void uc_list(char_u *name, size_t name_len)
garray_T *gap = (cmdwin_type != 0 && get_cmdline_type() == NUL)
? &prevwin->w_buffer->b_ucmds
: &curbuf->b_ucmds;
- for (;; ) {
+ for (;;) {
for (i = 0; i < gap->ga_len; ++i) {
cmd = USER_CMD_GA(gap, i);
a = cmd->uc_argt;
@@ -5714,7 +5714,7 @@ static void ex_delcommand(exarg_T *eap)
garray_T *gap;
gap = &curbuf->b_ucmds;
- for (;; ) {
+ for (;;) {
for (i = 0; i < gap->ga_len; ++i) {
cmd = USER_CMD_GA(gap, i);
cmp = STRCMP(eap->arg, cmd->uc_name);
@@ -6154,12 +6154,12 @@ static void do_ucmd(exarg_T *eap)
* Second round: copy result into "buf".
*/
buf = NULL;
- for (;; ) {
+ for (;;) {
p = cmd->uc_rep; // source
q = buf; // destination
totlen = 0;
- for (;; ) {
+ for (;;) {
start = vim_strchr(p, '<');
if (start != NULL) {
end = vim_strchr(start + 1, '>');
@@ -6185,7 +6185,7 @@ static void do_ucmd(exarg_T *eap)
}
}
- // break if there no <item> is found
+ // break if no <item> is found
if (start == NULL || end == NULL) {
break;
}
@@ -7754,6 +7754,7 @@ void post_chdir(CdScope scope, bool trigger_dirchanged)
abort();
}
+ last_chdir_reason = NULL;
shorten_fnames(true);
if (trigger_dirchanged) {
@@ -7871,7 +7872,9 @@ static void ex_pwd(exarg_T *eap)
#endif
if (p_verbose > 0) {
char *context = "global";
- if (curwin->w_localdir != NULL) {
+ if (last_chdir_reason != NULL) {
+ context = last_chdir_reason;
+ } else if (curwin->w_localdir != NULL) {
context = "window";
} else if (curtab->tp_localdir != NULL) {
context = "tabpage";
@@ -8984,8 +8987,8 @@ ssize_t find_cmdline_var(const char_u *src, size_t *usedlen)
/// @return an allocated string if a valid match was found.
/// Returns NULL if no match was found. "usedlen" then still contains the
/// number of characters to skip.
-char_u *eval_vars(char_u *src, char_u *srcstart, size_t *usedlen, linenr_T *lnump,
- char **errormsg, int *escaped)
+char_u *eval_vars(char_u *src, char_u *srcstart, size_t *usedlen, linenr_T *lnump, char **errormsg,
+ int *escaped)
{
int i;
char_u *s;
@@ -9253,7 +9256,7 @@ static char_u *arg_all(void)
* first time: compute the total length
* second time: concatenate the names
*/
- for (;; ) {
+ for (;;) {
len = 0;
for (idx = 0; idx < ARGCOUNT; ++idx) {
p = alist_name(&ARGLIST[idx]);
@@ -9316,7 +9319,7 @@ char_u *expand_sfile(char_u *arg)
result = vim_strsave(arg);
- for (p = result; *p; ) {
+ for (p = result; *p;) {
if (STRNCMP(p, "<sfile>", 7) != 0) {
++p;
} else {
@@ -9462,7 +9465,7 @@ static void ex_filetype(exarg_T *eap)
}
// Accept "plugin" and "indent" in any order.
- for (;; ) {
+ for (;;) {
if (STRNCMP(arg, "plugin", 6) == 0) {
plugin = true;
arg = skipwhite(arg + 6);
diff --git a/src/nvim/ex_eval.c b/src/nvim/ex_eval.c
index 348a26d723..f60f0ebe98 100644
--- a/src/nvim/ex_eval.c
+++ b/src/nvim/ex_eval.c
@@ -1628,7 +1628,7 @@ void ex_endtry(exarg_T *eap)
eap->errmsg = get_end_emsg(cstack);
// Find the matching ":try" and report what's missing.
idx = cstack->cs_idx;
- do{
+ do {
--idx;
}
while (idx > 0 && !(cstack->cs_flags[idx] & CSF_TRY));
@@ -2091,7 +2091,7 @@ int has_loop_cmd(char_u *p)
int len;
// skip modifiers, white space and ':'
- for (;; ) {
+ for (;;) {
while (*p == ' ' || *p == '\t' || *p == ':') {
++p;
}
diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c
index 2823cb7567..9cf39802de 100644
--- a/src/nvim/ex_getln.c
+++ b/src/nvim/ex_getln.c
@@ -1667,7 +1667,7 @@ static int may_do_command_line_next_incsearch(int firstc, long count, incsearch_
static void command_line_next_histidx(CommandLineState *s, bool next_match)
{
int j = (int)STRLEN(s->lookfor);
- for (;; ) {
+ for (;;) {
// one step backwards
if (!next_match) {
if (s->hiscnt == hislen) {
@@ -2689,7 +2689,7 @@ static void color_expr_cmdline(const CmdlineInfo *const colored_ccline,
viml_parser_destroy(&pstate);
kv_resize(ret_ccline_colors->colors, kv_size(colors));
size_t prev_end = 0;
- for (size_t i = 0 ; i < kv_size(colors) ; i++) {
+ for (size_t i = 0; i < kv_size(colors); i++) {
const ParserHighlightChunk chunk = kv_A(colors, i);
assert(chunk.start.col < INT_MAX);
assert(chunk.end_col < INT_MAX);
@@ -3469,7 +3469,7 @@ static bool cmdline_paste(int regname, bool literally, bool remcr)
int len;
// Locate start of last word in the cmd buffer.
- for (w = ccline.cmdbuff + ccline.cmdpos; w > ccline.cmdbuff; ) {
+ for (w = ccline.cmdbuff + ccline.cmdpos; w > ccline.cmdbuff;) {
len = utf_head_off(ccline.cmdbuff, w - 1) + 1;
if (!vim_iswordc(utf_ptr2char(w - len))) {
break;
@@ -4389,7 +4389,7 @@ static int showmatches(expand_T *xp, int wildmenu)
msg_outtrans_long_attr(p + 2, HL_ATTR(HLF_D));
break;
}
- for (j = maxlen - lastlen; --j >= 0; ) {
+ for (j = maxlen - lastlen; --j >= 0;) {
msg_putchar(' ');
}
if (xp->xp_context == EXPAND_FILES
@@ -4460,7 +4460,7 @@ char_u *sm_gettail(char_u *s, bool eager)
char_u *t = s;
int had_sep = FALSE;
- for (p = s; *p != NUL; ) {
+ for (p = s; *p != NUL;) {
if (vim_ispathsep(*p)
#ifdef BACKSLASH_IN_FILENAME
&& !rem_backslash(p)
@@ -5222,7 +5222,7 @@ static void expand_shellcmd(char_u *filepat, int *num_file, char_u ***file, int
ga_init(&ga, (int)sizeof(char *), 10);
hashtab_T found_ht;
hash_init(&found_ht);
- for (s = path; ; s = e) {
+ for (s = path;; s = e) {
e = vim_strchr(s, ENV_SEPCHAR);
if (e == NULL) {
e = s + STRLEN(s);
diff --git a/src/nvim/ex_session.c b/src/nvim/ex_session.c
index 9aa8cc0107..f80a63560c 100644
--- a/src/nvim/ex_session.c
+++ b/src/nvim/ex_session.c
@@ -345,8 +345,8 @@ static int put_view(FILE *fd, win_T *wp, int add_edit, unsigned *flagp, int curr
// Load the file.
//
if (wp->w_buffer->b_ffname != NULL
- && (!bt_nofile(wp->w_buffer) ||
- wp->w_buffer->terminal)) {
+ && (!bt_nofile(wp->w_buffer)
+ || wp->w_buffer->terminal)) {
// Editing a file in this buffer: use ":edit file".
// This may have side effects! (e.g., compressed or network file).
//
@@ -431,8 +431,8 @@ static int put_view(FILE *fd, win_T *wp, int add_edit, unsigned *flagp, int curr
//
if ((*flagp & SSOP_FOLDS)
&& wp->w_buffer->b_ffname != NULL
- && (bt_normal(wp->w_buffer) ||
- bt_help(wp->w_buffer))) {
+ && (bt_normal(wp->w_buffer)
+ || bt_help(wp->w_buffer))) {
if (put_folds(fd, wp) == FAIL) {
return FAIL;
}
diff --git a/src/nvim/file_search.c b/src/nvim/file_search.c
index fe991963a0..5953a574f3 100644
--- a/src/nvim/file_search.c
+++ b/src/nvim/file_search.c
@@ -605,9 +605,9 @@ char_u *vim_findfile(void *search_ctx_arg)
}
// upward search loop
- for (;; ) {
+ for (;;) {
// downward search loop
- for (;; ) {
+ for (;;) {
// check if user user wants to stop the search
os_breakcheck();
if (got_int) {
@@ -829,7 +829,7 @@ char_u *vim_findfile(void *search_ctx_arg)
} else {
suf = curbuf->b_p_sua;
}
- for (;; ) {
+ for (;;) {
// if file exists and we didn't already find it
if ((path_with_url((char *)file_path)
|| (os_path_exists(file_path)
@@ -1500,7 +1500,7 @@ char_u *find_file_in_path_option(char_u *ptr, size_t len, int options, int first
/* When the file doesn't exist, try adding parts of
* 'suffixesadd'. */
buf = suffixes;
- for (;; ) {
+ for (;;) {
if (
(os_path_exists(NameBuff)
&& (find_what == FINDFILE_BOTH
@@ -1530,7 +1530,7 @@ char_u *find_file_in_path_option(char_u *ptr, size_t len, int options, int first
did_findfile_init = FALSE;
}
- for (;; ) {
+ for (;;) {
if (did_findfile_init) {
file_name = vim_findfile(fdip_search_ctx);
if (file_name != NULL) {
diff --git a/src/nvim/fileio.c b/src/nvim/fileio.c
index 321d884d9c..c90115d796 100644
--- a/src/nvim/fileio.c
+++ b/src/nvim/fileio.c
@@ -100,8 +100,8 @@ struct bw_info {
char_u bw_rest[CONV_RESTLEN]; // not converted bytes
int bw_restlen; // nr of bytes in bw_rest[]
int bw_first; // first write call
- char_u *bw_conv_buf; // buffer for writing converted chars
- int bw_conv_buflen; // size of bw_conv_buf
+ char_u *bw_conv_buf; // buffer for writing converted chars
+ size_t bw_conv_buflen; // size of bw_conv_buf
int bw_conv_error; // set for conversion error
linenr_T bw_conv_error_lnum; // first line with error or zero
linenr_T bw_start_lnum; // line number at start of buffer
@@ -995,7 +995,7 @@ retry:
long tlen;
tlen = 0;
- for (;; ) {
+ for (;;) {
p = ml_get(read_buf_lnum) + read_buf_col;
n = (int)STRLEN(p);
if ((int)tlen + n + 1 > size) {
@@ -1360,6 +1360,10 @@ retry:
u8c += (unsigned)(*--p) << 16;
u8c += (unsigned)(*--p) << 24;
}
+ // Replace characters over INT_MAX with Unicode replacement character
+ if (u8c > INT_MAX) {
+ u8c = 0xfffd;
+ }
} else { // UTF-8
if (*--p < 0x80) {
u8c = *p;
@@ -3125,7 +3129,7 @@ nobackup:
// If conversion is taking place, we may first pretend to write and check
// for conversion errors. Then loop again to write for real.
// When not doing conversion this writes for real right away.
- for (checking_conversion = true; ; checking_conversion = false) {
+ for (checking_conversion = true;; checking_conversion = false) {
// There is no need to check conversion when:
// - there is no conversion
// - we make a backup file, that can be restored in case of conversion
@@ -4265,8 +4269,8 @@ static char_u *check_for_bom(char_u *p, long size, int *lenp, int flags)
len = 4;
} else if (flags == (FIO_UCS2 | FIO_ENDIAN_L)) {
name = "ucs-2le"; // FF FE
- } else if (flags == FIO_ALL ||
- flags == (FIO_UTF16 | FIO_ENDIAN_L)) {
+ } else if (flags == FIO_ALL
+ || flags == (FIO_UTF16 | FIO_ENDIAN_L)) {
// utf-16le is preferred, it also works for ucs-2le text
name = "utf-16le"; // FF FE
}
@@ -4811,8 +4815,8 @@ int check_timestamps(int focus)
}
if (!stuff_empty() || global_busy || !typebuf_typed()
- || autocmd_busy || curbuf->b_ro_locked > 0 ||
- allbuf_lock > 0) {
+ || autocmd_busy || curbuf->b_ro_locked > 0
+ || allbuf_lock > 0) {
need_check_timestamps = true; // check later
} else {
no_wait_return++;
@@ -5727,7 +5731,7 @@ long read_eintr(int fd, void *buf, size_t bufsize)
{
long ret;
- for (;; ) {
+ for (;;) {
ret = read(fd, buf, bufsize);
if (ret >= 0 || errno != EINTR) {
break;
diff --git a/src/nvim/fold.c b/src/nvim/fold.c
index daf0df9326..4a8be7a31b 100644
--- a/src/nvim/fold.c
+++ b/src/nvim/fold.c
@@ -202,7 +202,7 @@ bool hasFoldingWin(win_T *const win, const linenr_T lnum, linenr_T *const firstp
* Recursively search for a fold that contains "lnum".
*/
garray_T *gap = &win->w_folds;
- for (;; ) {
+ for (;;) {
if (!foldFind(gap, lnum_rel, &fp)) {
break;
}
@@ -455,7 +455,7 @@ void foldOpenCursor(void)
checkupdate(curwin);
if (hasAnyFolding(curwin)) {
- for (;; ) {
+ for (;;) {
done = DONE_NOTHING;
(void)setManualFold(curwin->w_cursor, true, false, &done);
if (!(done & DONE_ACTION)) {
@@ -716,7 +716,7 @@ void deleteFold(win_T *const wp, const linenr_T start, const linenr_T end, const
garray_T *found_ga = NULL;
linenr_T lnum_off = 0;
bool use_level = false;
- for (;; ) {
+ for (;;) {
if (!foldFind(gap, lnum - lnum_off, &fp)) {
break;
}
@@ -897,7 +897,7 @@ int foldMoveTo(const bool updown, const int dir, const long count)
linenr_T lnum_found = curwin->w_cursor.lnum;
int level = 0;
bool last = false;
- for (;; ) {
+ for (;;) {
if (!foldFind(gap, curwin->w_cursor.lnum - lnum_off, &fp)) {
if (!updown || gap->ga_len == 0) {
break;
@@ -1155,7 +1155,7 @@ static int foldLevelWin(win_T *wp, linenr_T lnum)
// Recursively search for a fold that contains "lnum".
gap = &wp->w_folds;
- for (;; ) {
+ for (;;) {
if (!foldFind(gap, lnum_rel, &fp)) {
break;
}
@@ -1265,7 +1265,7 @@ static linenr_T setManualFoldWin(win_T *wp, linenr_T lnum, int opening, int recu
* Find the fold, open or close it.
*/
gap = &wp->w_folds;
- for (;; ) {
+ for (;;) {
if (!foldFind(gap, lnum, &fp)) {
// If there is a following fold, continue there next time.
if (fp != NULL && fp < (fold_T *)gap->ga_data + gap->ga_len) {
@@ -1928,7 +1928,7 @@ void foldtext_cleanup(char_u *str)
}
parseMarker(curwin);
- for (s = str; *s != NUL; ) {
+ for (s = str; *s != NUL;) {
size_t len = 0;
if (STRNCMP(s, curwin->w_p_fmr, foldstartmarkerlen) == 0) {
len = foldstartmarkerlen;
@@ -2603,7 +2603,7 @@ static linenr_T foldUpdateIEMSRecurse(garray_T *const gap, const int level,
}
// delete following folds that end before the current line
- for (;; ) {
+ for (;;) {
fp2 = fp + 1;
if (fp2 >= (fold_T *)gap->ga_data + gap->ga_len
|| fp2->fd_top > flp->lnum) {
diff --git a/src/nvim/getchar.c b/src/nvim/getchar.c
index 5267b313c7..2f4b59837a 100644
--- a/src/nvim/getchar.c
+++ b/src/nvim/getchar.c
@@ -1453,7 +1453,7 @@ int vgetc(void)
} else {
mod_mask = 0x0;
last_recorded_len = 0;
- for (;; ) { // this is done twice if there are modifiers
+ for (;;) { // this is done twice if there are modifiers
bool did_inc = false;
if (mod_mask) { // no mapping after modifier has been read
no_mapping++;
@@ -1793,7 +1793,7 @@ static int vgetorpeek(bool advance)
* If a mapped key sequence is found we go back to the start to
* try re-mapping.
*/
- for (;; ) {
+ for (;;) {
/*
* os_breakcheck() is slow, don't use it too often when
* inside a mapping. But call it each time for typed
@@ -1861,8 +1861,8 @@ static int vgetorpeek(bool advance)
&& State != CONFIRM
&& !((ctrl_x_mode_not_default() && vim_is_ctrl_x_key(c1))
|| ((compl_cont_status & CONT_LOCAL)
- && (c1 == Ctrl_N ||
- c1 == Ctrl_P)))) {
+ && (c1 == Ctrl_N
+ || c1 == Ctrl_P)))) {
if (c1 == K_SPECIAL) {
nolmaplen = 2;
} else {
@@ -1951,7 +1951,7 @@ static int vgetorpeek(bool advance)
* If one of the typed keys cannot be
* remapped, skip the entry.
*/
- for (n = mlen; --n >= 0; ) {
+ for (n = mlen; --n >= 0;) {
if (*s++ & (RM_NONE|RM_ABBR)) {
break;
}
@@ -2550,7 +2550,7 @@ int inchar(char_u *buf, int maxlen, long wait_time)
#define DUM_LEN MAXMAPLEN * 3 + 3
char_u dum[DUM_LEN + 1];
- for (;; ) {
+ for (;;) {
len = os_inchar(dum, DUM_LEN, 0L, 0, NULL);
if (len == 0 || (len == 1 && dum[0] == 3)) {
break;
@@ -3599,7 +3599,7 @@ char_u *set_context_in_map_cmd(expand_T *xp, char_u *cmd, char_u *arg, bool forc
expand_isabbrev = isabbrev;
xp->xp_context = EXPAND_MAPPINGS;
expand_buffer = false;
- for (;; ) {
+ for (;;) {
if (STRNCMP(arg, "<buffer>", 8) == 0) {
expand_buffer = true;
arg = skipwhite(arg + 8);
@@ -3987,7 +3987,7 @@ char_u *vim_strsave_escape_csi(char_u *p)
// 0xc0 -> 0xc3 - 0x80 -> 0xc3 K_SPECIAL KS_SPECIAL KE_FILLER
char_u *res = xmalloc(STRLEN(p) * 4 + 1);
char_u *d = res;
- for (char_u *s = p; *s != NUL; ) {
+ for (char_u *s = p; *s != NUL;) {
if (s[0] == K_SPECIAL && s[1] != NUL && s[2] != NUL) {
// Copy special key unmodified.
*d++ = *s++;
diff --git a/src/nvim/globals.h b/src/nvim/globals.h
index 9f0f19024b..7ae7b65702 100644
--- a/src/nvim/globals.h
+++ b/src/nvim/globals.h
@@ -790,6 +790,8 @@ extern char_u *compiled_sys;
// directory is not a local directory, globaldir is NULL.
EXTERN char_u *globaldir INIT(= NULL);
+EXTERN char *last_chdir_reason INIT(= NULL);
+
// Whether 'keymodel' contains "stopsel" and "startsel".
EXTERN bool km_stopsel INIT(= false);
EXTERN bool km_startsel INIT(= false);
@@ -843,6 +845,7 @@ EXTERN disptick_T display_tick INIT(= 0);
// cursor position in Insert mode.
EXTERN linenr_T spell_redraw_lnum INIT(= 0);
+// uncrustify:off
// The error messages that can be shared are included here.
// Excluded are errors that are only used once and debugging messages.
@@ -851,12 +854,8 @@ EXTERN char e_afterinit[] INIT(= N_("E905: Cannot set this option after startup"
EXTERN char e_api_spawn_failed[] INIT(= N_("E903: Could not spawn API job"));
EXTERN char e_argreq[] INIT(= N_("E471: Argument required"));
EXTERN char e_backslash[] INIT(= N_("E10: \\ should be followed by /, ? or &"));
-EXTERN char e_cmdwin[] INIT(=
- N_(
- "E11: Invalid in command-line window; <CR> executes, CTRL-C quits"));
-EXTERN char e_curdir[] INIT(=
- N_(
- "E12: Command not allowed from exrc/vimrc in current dir or tag search"));
+EXTERN char e_cmdwin[] INIT(= N_("E11: Invalid in command-line window; <CR> executes, CTRL-C quits"));
+EXTERN char e_curdir[] INIT(= N_( "E12: Command not allowed from exrc/vimrc in current dir or tag search"));
EXTERN char e_endif[] INIT(= N_("E171: Missing :endif"));
EXTERN char e_endtry[] INIT(= N_("E600: Missing :endtry"));
EXTERN char e_endwhile[] INIT(= N_("E170: Missing :endwhile"));
@@ -886,10 +885,7 @@ EXTERN char e_channotpty[] INIT(= N_("E904: channel is not a pty"));
EXTERN char e_stdiochan2[] INIT(= N_("E905: Couldn't open stdio channel: %s"));
EXTERN char e_invstream[] INIT(= N_("E906: invalid stream for channel"));
EXTERN char e_invstreamrpc[] INIT(= N_("E906: invalid stream for rpc channel, use 'rpc'"));
-EXTERN char e_streamkey[] INIT(=
- N_(
- "E5210: dict key '%s' already set for buffered stream in channel %"
- PRIu64));
+EXTERN char e_streamkey[] INIT(= N_("E5210: dict key '%s' already set for buffered stream in channel %" PRIu64));
EXTERN char e_libcall[] INIT(= N_("E364: Library call failed for \"%s()\""));
EXTERN char e_fsync[] INIT(= N_("E667: Fsync failed: %s"));
EXTERN char e_mkdir[] INIT(= N_("E739: Cannot create directory %s: %s"));
@@ -940,9 +936,7 @@ EXTERN char e_dictkey[] INIT(= N_("E716: Key not present in Dictionary: \"%s\"")
EXTERN char e_listreq[] INIT(= N_("E714: List required"));
EXTERN char e_listblobreq[] INIT(= N_("E897: List or Blob required"));
EXTERN char e_listdictarg[] INIT(= N_("E712: Argument of %s must be a List or Dictionary"));
-EXTERN char e_listdictblobarg[] INIT(=
- N_(
- "E896: Argument of %s must be a List, Dictionary or Blob"));
+EXTERN char e_listdictblobarg[] INIT(= N_("E896: Argument of %s must be a List, Dictionary or Blob"));
EXTERN char e_readerrf[] INIT(= N_("E47: Error while reading errorfile"));
EXTERN char e_sandbox[] INIT(= N_("E48: Not allowed in sandbox"));
EXTERN char e_secure[] INIT(= N_("E523: Not allowed here"));
@@ -981,25 +975,21 @@ EXTERN char e_unsupportedoption[] INIT(= N_("E519: Option not supported"));
EXTERN char e_fnametoolong[] INIT(= N_("E856: Filename too long"));
EXTERN char e_float_as_string[] INIT(= N_("E806: using Float as a String"));
-EXTERN char e_autocmd_err[] INIT(=N_("E5500: autocmd has thrown an exception: %s"));
-EXTERN char e_cmdmap_err[] INIT(=N_("E5520: <Cmd> mapping must end with <CR>"));
-EXTERN char
-e_cmdmap_repeated[] INIT(=N_("E5521: <Cmd> mapping must end with <CR> before second <Cmd>"));
-EXTERN char e_cmdmap_key[] INIT(=N_("E5522: <Cmd> mapping must not include %s key"));
+EXTERN char e_autocmd_err[] INIT(= N_("E5500: autocmd has thrown an exception: %s"));
+EXTERN char e_cmdmap_err[] INIT(= N_("E5520: <Cmd> mapping must end with <CR>"));
+EXTERN char e_cmdmap_repeated[] INIT(= N_("E5521: <Cmd> mapping must end with <CR> before second <Cmd>"));
+EXTERN char e_cmdmap_key[] INIT(= N_("E5522: <Cmd> mapping must not include %s key"));
-EXTERN char e_api_error[] INIT(=N_("E5555: API call: %s"));
+EXTERN char e_api_error[] INIT(= N_("E5555: API call: %s"));
-EXTERN char e_luv_api_disabled[] INIT(=N_("E5560: %s must not be called in a lua loop callback"));
+EXTERN char e_luv_api_disabled[] INIT(= N_("E5560: %s must not be called in a lua loop callback"));
-EXTERN char e_floatonly[] INIT(=N_(
- "E5601: Cannot close window, only floating window would remain"));
-EXTERN char e_floatexchange[] INIT(=N_("E5602: Cannot exchange or rotate float"));
+EXTERN char e_floatonly[] INIT(= N_("E5601: Cannot close window, only floating window would remain"));
+EXTERN char e_floatexchange[] INIT(= N_("E5602: Cannot exchange or rotate float"));
EXTERN char e_non_empty_string_required[] INIT(= N_("E1142: Non-empty string required"));
-EXTERN char e_cannot_define_autocommands_for_all_events[] INIT(=
- N_(
- "E1155: Cannot define autocommands for ALL events"));
+EXTERN char e_cannot_define_autocommands_for_all_events[] INIT(= N_("E1155: Cannot define autocommands for ALL events"));
EXTERN char top_bot_msg[] INIT(= N_("search hit TOP, continuing at BOTTOM"));
EXTERN char bot_top_msg[] INIT(= N_("search hit BOTTOM, continuing at TOP"));
@@ -1021,6 +1011,8 @@ EXTERN bool embedded_mode INIT(= false);
// Do not start a UI nor read/write to stdio (unless embedding).
EXTERN bool headless_mode INIT(= false);
+// uncrustify:on
+
/// Used to track the status of external functions.
/// Currently only used for iconv().
typedef enum {
diff --git a/src/nvim/hardcopy.c b/src/nvim/hardcopy.c
index ab3f63c93e..93fcdc55a6 100644
--- a/src/nvim/hardcopy.c
+++ b/src/nvim/hardcopy.c
@@ -571,7 +571,7 @@ static void prt_header(prt_settings_T *const psettings, const int pagenum, const
// Use a negative line number to indicate printing in the top margin.
int page_line = 0 - prt_header_height();
mch_print_start_line(true, page_line);
- for (char_u *p = tbuf; *p != NUL; ) {
+ for (char_u *p = tbuf; *p != NUL;) {
const int l = utfc_ptr2len(p);
assert(l >= 0);
if (mch_print_text_out(p, (size_t)l)) {
@@ -986,8 +986,7 @@ static colnr_T hardcopy_line(prt_settings_T *psettings, int page_line, prt_pos_T
#define PRT_PS_DEFAULT_DPI (72) // Default user space resolution
#define PRT_PS_DEFAULT_FONTSIZE (10)
-#define PRT_MEDIASIZE_LEN (sizeof(prt_mediasize) / \
- sizeof(struct prt_mediasize_S))
+#define PRT_MEDIASIZE_LEN ARRAY_SIZE(prt_mediasize)
static struct prt_mediasize_S prt_mediasize[] =
{
@@ -2455,7 +2454,7 @@ static int prt_add_resource(struct prt_ps_resource_S *resource)
prt_dsc_textline("BeginDocument", (char *)resource->filename);
- for (;; ) {
+ for (;;) {
bytes_read = fread((char *)resource_buffer, sizeof(char_u),
sizeof(resource_buffer), fd_resource);
if (ferror(fd_resource)) {
diff --git a/src/nvim/if_cscope.c b/src/nvim/if_cscope.c
index 2c44ce380d..6f02ebfb48 100644
--- a/src/nvim/if_cscope.c
+++ b/src/nvim/if_cscope.c
@@ -557,7 +557,7 @@ static int cs_cnt_matches(size_t idx)
int nlines = 0;
char *buf = xmalloc(CSREAD_BUFSIZE);
- for (;; ) {
+ for (;;) {
errno = 0;
if (!fgets(buf, CSREAD_BUFSIZE, csinfo[idx].fr_fp)) {
if (errno == EINTR) {
@@ -966,7 +966,7 @@ static int cs_find_common(char *opt, char *pat, int forceit, int verbose, int us
qfpos++;
// next symbol must be + or -
if (strchr(CSQF_FLAGS, *qfpos) == NULL) {
- (void)semsg(_("E469: invalid cscopequickfix flag %c for %c"), *qfpos, *(qfpos - 1));;
+ (void)semsg(_("E469: invalid cscopequickfix flag %c for %c"), *qfpos, *(qfpos - 1));
return FALSE;
}
diff --git a/src/nvim/lib/kbtree.h b/src/nvim/lib/kbtree.h
index 5d9c1095bc..617773a79a 100644
--- a/src/nvim/lib/kbtree.h
+++ b/src/nvim/lib/kbtree.h
@@ -53,7 +53,7 @@
bool is_internal; \
key_t key[2*T-1]; \
kbnode_##name##_t *ptr[]; \
- } ; \
+ }; \
typedef struct { \
kbnode_##name##_t *root; \
int n_keys, n_nodes; \
diff --git a/src/nvim/lib/khash.h b/src/nvim/lib/khash.h
index e0faf94db9..e81db43038 100644
--- a/src/nvim/lib/khash.h
+++ b/src/nvim/lib/khash.h
@@ -459,7 +459,7 @@ static kh_inline khint_t __ac_X31_hash_string(const char *s)
{
khint_t h = (khint_t)*s;
if (h) {
- for (++s ; *s; ++s) { h = (h << 5) - h + (uint8_t)*s; }
+ for (++s; *s; ++s) { h = (h << 5) - h + (uint8_t)*s; }
}
return h;
}
@@ -666,7 +666,7 @@ static kh_inline khint_t __ac_Wang_hash(khint_t key)
} \
}
-// More conenient interfaces
+// More convenient interfaces
/*! @function
@abstract Instantiate a hash set containing integer keys
diff --git a/src/nvim/lua/stdlib.c b/src/nvim/lua/stdlib.c
index db79e9e7e9..b5553060a1 100644
--- a/src/nvim/lua/stdlib.c
+++ b/src/nvim/lua/stdlib.c
@@ -175,13 +175,13 @@ int nlua_str_utfindex(lua_State *const lstate) FUNC_ATTR_NONNULL_ALL
size_t s1_len;
const char *s1 = luaL_checklstring(lstate, 1, &s1_len);
intptr_t idx;
- if (lua_gettop(lstate) >= 2) {
+ if (lua_isnoneornil(lstate, 2)) {
+ idx = (intptr_t)s1_len;
+ } else {
idx = luaL_checkinteger(lstate, 2);
if (idx < 0 || idx > (intptr_t)s1_len) {
return luaL_error(lstate, "index out of range");
}
- } else {
- idx = (intptr_t)s1_len;
}
size_t codepoints = 0, codeunits = 0;
diff --git a/src/nvim/lua/vim.lua b/src/nvim/lua/vim.lua
index 30c7034209..c1a1e7f162 100644
--- a/src/nvim/lua/vim.lua
+++ b/src/nvim/lua/vim.lua
@@ -323,6 +323,7 @@ end
do
local validate = vim.validate
+ --@private
local function make_dict_accessor(scope, handle)
validate {
scope = {scope, 's'};
@@ -422,11 +423,10 @@ end
---
--- Without a runtime, writes to :Messages
---@see :help nvim_notify
----@param msg Content of the notification to show to the user
----@param log_level Optional log level
----@param opts Dictionary with optional options (timeout, etc)
-function vim.notify(msg, log_level, _opts)
-
+---@param msg string Content of the notification to show to the user
+---@param log_level number|nil enum from vim.log.levels
+---@param opts table|nil additional options (timeout, etc)
+function vim.notify(msg, log_level, opts) -- luacheck: no unused
if log_level == vim.log.levels.ERROR then
vim.api.nvim_err_writeln(msg)
elseif log_level == vim.log.levels.WARN then
@@ -454,7 +454,7 @@ local on_key_cbs = {}
--- On each key press, Nvim passes the key char to fn(). |i_CTRL-V|
--- If {fn} is nil, it removes the callback for the associated {ns_id}
---@param ns_id number? Namespace ID. If nil or 0, generates and returns a new
---- |nvim_create_namesapce()| id.
+--- |nvim_create_namespace()| id.
---
---@return number Namespace id associated with {fn}. Or count of all callbacks
---if on_key() is called without arguments.
@@ -580,6 +580,7 @@ function vim._expand_pat(pat, env)
end
local keys = {}
+ ---@private
local function insert_keys(obj)
for k,_ in pairs(obj) do
if type(k) == "string" and string.sub(k,1,string.len(match_part)) == match_part then
diff --git a/src/nvim/lua/xdiff.c b/src/nvim/lua/xdiff.c
index 7eda9b6270..b2e971f9f3 100644
--- a/src/nvim/lua/xdiff.c
+++ b/src/nvim/lua/xdiff.c
@@ -17,7 +17,7 @@
#include "xdiff/xdiff.h"
typedef enum {
- kNluaXdiffModeUnified = 0,
+ kNluaXdiffModeUnified = 0,
kNluaXdiffModeOnHunkCB,
kNluaXdiffModeLocations,
} NluaXdiffMode;
diff --git a/src/nvim/mark.c b/src/nvim/mark.c
index 51f4ba635f..39f18b333d 100644
--- a/src/nvim/mark.c
+++ b/src/nvim/mark.c
@@ -235,7 +235,7 @@ pos_T *movemark(int count)
return (pos_T *)NULL;
}
- for (;; ) {
+ for (;;) {
if (curwin->w_jumplistidx + count < 0
|| curwin->w_jumplistidx + count >= curwin->w_jumplistlen) {
return (pos_T *)NULL;
diff --git a/src/nvim/mbyte.c b/src/nvim/mbyte.c
index 12460646ed..42117bc762 100644
--- a/src/nvim/mbyte.c
+++ b/src/nvim/mbyte.c
@@ -764,7 +764,7 @@ int utfc_ptr2char(const char_u *p, int *pcc)
&& p[len] >= 0x80
&& utf_composinglike(p, p + len)) {
cc = utf_ptr2char(p + len);
- for (;; ) {
+ for (;;) {
pcc[i++] = cc;
if (i == MAX_MCO) {
break;
@@ -1322,7 +1322,7 @@ static int utf_strnicmp(const char_u *s1, const char_u *s2, size_t n1, size_t n2
int c1, c2, cdiff;
char_u buffer[6];
- for (;; ) {
+ for (;;) {
c1 = utf_safe_read_char_adv(&s1, &n1);
c2 = utf_safe_read_char_adv(&s2, &n2);
@@ -1933,7 +1933,7 @@ void utf_find_illegal(void)
}
curwin->w_cursor.coladd = 0;
- for (;; ) {
+ for (;;) {
p = get_cursor_pos_ptr();
if (vimconv.vc_type != CONV_NONE) {
xfree(tofree);
@@ -2363,7 +2363,7 @@ static char_u *iconv_string(const vimconv_T *const vcp, char_u *str, size_t slen
from = (char *)str;
fromlen = slen;
- for (;; ) {
+ for (;;) {
if (len == 0 || ICONV_ERRNO == ICONV_E2BIG) {
// Allocate enough room for most conversions. When re-allocating
// increase the buffer size.
diff --git a/src/nvim/memfile.c b/src/nvim/memfile.c
index 2a0ea9a269..3397296b3a 100644
--- a/src/nvim/memfile.c
+++ b/src/nvim/memfile.c
@@ -505,7 +505,7 @@ bool mf_release_all(void)
// Flush as many blocks as possible, only if there is a swapfile.
if (mfp->mf_fd >= 0) {
- for (bhdr_T *hp = mfp->mf_used_last; hp != NULL; ) {
+ for (bhdr_T *hp = mfp->mf_used_last; hp != NULL;) {
if (!(hp->bh_flags & BH_LOCKED)
&& (!(hp->bh_flags & BH_DIRTY)
|| mf_write(mfp, hp) != FAIL)) {
diff --git a/src/nvim/memline.c b/src/nvim/memline.c
index edab367f02..08202a6d5c 100644
--- a/src/nvim/memline.c
+++ b/src/nvim/memline.c
@@ -407,7 +407,7 @@ void ml_setname(buf_T *buf)
*/
dirp = p_dir;
bool found_existing_dir = false;
- for (;; ) {
+ for (;;) {
if (*dirp == NUL) { // tried all directories, fail
break;
}
@@ -504,7 +504,7 @@ void ml_open_file(buf_T *buf)
*/
dirp = p_dir;
bool found_existing_dir = false;
- for (;; ) {
+ for (;;) {
if (*dirp == NUL) {
break;
}
@@ -1236,7 +1236,7 @@ void ml_recover(bool checkext)
} else if (error) {
++no_wait_return;
msg(">>>>>>>>>>>>>");
- emsg(_( "E312: Errors detected while recovering; look for lines starting with ???"));
+ emsg(_("E312: Errors detected while recovering; look for lines starting with ???"));
--no_wait_return;
msg(_("See \":help E312\" for more information."));
msg(">>>>>>>>>>>>>");
@@ -2349,7 +2349,7 @@ static int ml_append_int(buf_T *buf, linenr_T lnum, char_u *line, colnr_T len, b
* move some of the pointer into the new block
* prepare for updating the parent block
*/
- for (;; ) { // do this twice when splitting block 1
+ for (;;) { // do this twice when splitting block 1
hp_new = ml_new_ptr(mfp);
if (hp_new == NULL) { // TODO: try to fix tree
return FAIL;
@@ -2733,7 +2733,7 @@ linenr_T ml_firstmarked(void)
* The search starts with lowest_marked line. This is the last line where
* a mark was found, adjusted by inserting/deleting lines.
*/
- for (lnum = lowest_marked; lnum <= curbuf->b_ml.ml_line_count; ) {
+ for (lnum = lowest_marked; lnum <= curbuf->b_ml.ml_line_count;) {
/*
* Find the data block containing the line.
* This also fills the stack with the blocks from the root to the data
@@ -2775,7 +2775,7 @@ void ml_clearmarked(void)
/*
* The search starts with line lowest_marked.
*/
- for (lnum = lowest_marked; lnum <= curbuf->b_ml.ml_line_count; ) {
+ for (lnum = lowest_marked; lnum <= curbuf->b_ml.ml_line_count;) {
/*
* Find the data block containing the line.
* This also fills the stack with the blocks from the root to the data
@@ -3034,7 +3034,7 @@ static bhdr_T *ml_find_line(buf_T *buf, linenr_T lnum, int action)
/*
* search downwards in the tree until a data block is found
*/
- for (;; ) {
+ for (;;) {
if ((hp = mf_get(mfp, bnum, page_count)) == NULL) {
goto error_noblock;
}
@@ -3211,7 +3211,7 @@ int resolve_symlink(const char_u *fname, char_u *buf)
// Put the result so far in tmp[], starting with the original name.
STRLCPY(tmp, fname, MAXPATHL);
- for (;; ) {
+ for (;;) {
// Limit symlink depth to 100, catch recursive loops.
if (++depth == 100) {
semsg(_("E773: Symlink loop for \"%s\""), fname);
@@ -3481,7 +3481,7 @@ static char *findswapname(buf_T *buf, char **dirp, char *old_fname, bool *found_
fname = (char *)makeswapname((char_u *)buf_fname, buf->b_ffname, buf,
(char_u *)dir_name);
- for (;; ) {
+ for (;;) {
if (fname == NULL) { // must be out of memory
break;
}
diff --git a/src/nvim/memory.c b/src/nvim/memory.c
index 85140e4c64..3d621ebbb7 100644
--- a/src/nvim/memory.c
+++ b/src/nvim/memory.c
@@ -573,7 +573,6 @@ void free_all_mem(void)
return;
}
entered_free_all_mem = true;
-
// Don't want to trigger autocommands from here on.
block_autocmds();
@@ -673,7 +672,7 @@ void free_all_mem(void)
first_tabpage = NULL;
// message history
- for (;; ) {
+ for (;;) {
if (delete_first_msg() == FAIL) {
break;
}
@@ -688,7 +687,7 @@ void free_all_mem(void)
// Must be after eval_clear to avoid it trying to access b:changedtick after
// freeing it.
p_acd = false;
- for (buf = firstbuf; buf != NULL; ) {
+ for (buf = firstbuf; buf != NULL;) {
bufref_T bufref;
set_bufref(&bufref, buf);
nextbuf = buf->b_next;
diff --git a/src/nvim/menu.c b/src/nvim/menu.c
index c2b6a5e402..d596b31062 100644
--- a/src/nvim/menu.c
+++ b/src/nvim/menu.c
@@ -80,7 +80,7 @@ void ex_menu(exarg_T *eap)
modes = get_menu_cmd_modes((char *)eap->cmd, eap->forceit, &noremap, &unmenu);
arg = eap->arg;
- for (;; ) {
+ for (;;) {
if (STRNCMP(arg, "<script>", 8) == 0) {
noremap = REMAP_SCRIPT;
arg = skipwhite(arg + 8);
@@ -449,7 +449,7 @@ static int add_menu_path(const char_u *const menu_path, vimmenu_T *menuarg,
}
if (c != 0) {
- menu->strings[i] = xmalloc(STRLEN(call_data) + 5 );
+ menu->strings[i] = xmalloc(STRLEN(call_data) + 5);
menu->strings[i][0] = c;
if (d == 0) {
STRCPY(menu->strings[i] + 1, call_data);
@@ -1315,7 +1315,7 @@ static char_u *menu_text(const char_u *str, int *mnemonic, char_u **actext)
}
// Find mnemonic characters "&a" and reduce "&&" to "&".
- for (p = text; p != NULL; ) {
+ for (p = text; p != NULL;) {
p = vim_strchr(p, '&');
if (p != NULL) {
if (p[1] == NUL) { // trailing "&"
diff --git a/src/nvim/message.c b/src/nvim/message.c
index 8223e6c188..6fcd4cef8a 100644
--- a/src/nvim/message.c
+++ b/src/nvim/message.c
@@ -401,7 +401,7 @@ void trunc_string(char_u *s, char_u *buf, int room_in, int buflen)
}
len += n;
buf[e] = s[e];
- for (n = utfc_ptr2len(s + e); --n > 0; ) {
+ for (n = utfc_ptr2len(s + e); --n > 0;) {
if (++e == buflen) {
break;
}
@@ -883,7 +883,7 @@ char_u *msg_may_trunc(int force, char_u *s)
return s;
}
int n;
- for (n = 0; size >= room; ) {
+ for (n = 0; size >= room;) {
size -= utf_ptr2cells(s + n);
n += utfc_ptr2len(s + n);
}
@@ -2549,7 +2549,7 @@ static msgchunk_T *disp_sb_line(int row, msgchunk_T *smp)
msgchunk_T *mp = smp;
char_u *p;
- for (;; ) {
+ for (;;) {
msg_row = row;
msg_col = mp->sb_msg_col;
p = mp->sb_text;
@@ -2688,7 +2688,7 @@ static int do_more_prompt(int typed_char)
if (typed_char == NUL) {
msg_moremsg(FALSE);
}
- for (;; ) {
+ for (;;) {
/*
* Get a typed character directly from the user.
*/
@@ -3436,7 +3436,7 @@ int do_dialog(int type, char_u *title, char_u *message, char_u *buttons, int dfl
++no_wait_return;
hotkeys = msg_show_console_dialog(message, buttons, dfltbutton);
- for (;; ) {
+ for (;;) {
// Get a typed character directly from the user.
c = get_keystroke(NULL);
switch (c) {
diff --git a/src/nvim/misc1.c b/src/nvim/misc1.c
index 9900a68fac..872a2c58e3 100644
--- a/src/nvim/misc1.c
+++ b/src/nvim/misc1.c
@@ -99,7 +99,7 @@ int get_leader_len(char_u *line, char_u **flags, bool backward, bool include_spa
* scan through the 'comments' option for a match
*/
found_one = FALSE;
- for (list = curbuf->b_p_com; *list; ) {
+ for (list = curbuf->b_p_com; *list;) {
// Get one option part into part_buf[]. Advance "list" to next
// one. Put "string" at start of string.
if (!got_com && flags != NULL) {
@@ -244,7 +244,7 @@ int get_last_leader_offset(char_u *line, char_u **flags)
* scan through the 'comments' option for a match
*/
found_one = FALSE;
- for (list = curbuf->b_p_com; *list; ) {
+ for (list = curbuf->b_p_com; *list;) {
char_u *flags_save = list;
/*
@@ -340,7 +340,7 @@ int get_last_leader_offset(char_u *line, char_u **flags)
}
len1 = (int)STRLEN(com_leader);
- for (list = curbuf->b_p_com; *list; ) {
+ for (list = curbuf->b_p_com; *list;) {
char_u *flags_save = list;
(void)copy_option_part(&list, part_buf2, COM_MAX_LEN, ",");
@@ -359,7 +359,7 @@ int get_last_leader_offset(char_u *line, char_u **flags)
// Now we have to verify whether string ends with a substring
// beginning the com_leader.
- for (off = (len2 > i ? i : len2); off > 0 && off + len1 > len2; ) {
+ for (off = (len2 > i ? i : len2); off > 0 && off + len1 > len2;) {
--off;
if (!STRNCMP(string + off, com_leader, len2 - off)) {
if (i - off < lower_check_bound) {
@@ -492,7 +492,7 @@ int get_keystroke(MultiQueue *events)
int waited = 0;
mapped_ctrl_c = 0; // mappings are not used here
- for (;; ) {
+ for (;;) {
// flush output before waiting
ui_flush();
// Leave some room for check_termcode() to insert a key code into (max
@@ -580,7 +580,7 @@ int get_number(int colon, int *mouse_used)
}
no_mapping++;
- for (;; ) {
+ for (;;) {
ui_cursor_goto(msg_row, msg_col);
c = safe_vgetc();
if (ascii_isdigit(c)) {
diff --git a/src/nvim/mouse.c b/src/nvim/mouse.c
index f02c000e82..386094e509 100644
--- a/src/nvim/mouse.c
+++ b/src/nvim/mouse.c
@@ -245,7 +245,7 @@ retnomove:
// Scroll by however many rows outside the window we are.
if (row < 0) {
count = 0;
- for (first = true; curwin->w_topline > 1; ) {
+ for (first = true; curwin->w_topline > 1;) {
if (curwin->w_topfill < win_get_fill(curwin, curwin->w_topline)) {
count++;
} else {
@@ -270,7 +270,7 @@ retnomove:
row = 0;
} else if (row >= curwin->w_height_inner) {
count = 0;
- for (first = true; curwin->w_topline < curbuf->b_ml.ml_line_count; ) {
+ for (first = true; curwin->w_topline < curbuf->b_ml.ml_line_count;) {
if (curwin->w_topfill > 0) {
++count;
} else {
@@ -448,7 +448,7 @@ win_T *mouse_find_win(int *gridp, int *rowp, int *colp)
fp = topframe;
*rowp -= firstwin->w_winrow;
- for (;; ) {
+ for (;;) {
if (fp->fr_layout == FR_LEAF) {
break;
}
diff --git a/src/nvim/move.c b/src/nvim/move.c
index 5114cd6d8a..d80e63e79d 100644
--- a/src/nvim/move.c
+++ b/src/nvim/move.c
@@ -382,8 +382,8 @@ static bool check_top_offset(void)
topline_back(curwin, &loff);
// Stop when included a line above the window.
if (loff.lnum < curwin->w_topline
- || (loff.lnum == curwin->w_topline &&
- loff.fill > 0)) {
+ || (loff.lnum == curwin->w_topline
+ && loff.fill > 0)) {
break;
}
n += loff.height;
@@ -1661,7 +1661,7 @@ void scroll_cursor_bot(int min_scroll, int set_topbot)
boff.fill = curwin->w_topfill;
boff.lnum = curwin->w_topline - 1;
int i;
- for (i = 0; i < scrolled && boff.lnum < curwin->w_botline; ) {
+ for (i = 0; i < scrolled && boff.lnum < curwin->w_botline;) {
botline_forw(curwin, &boff);
i += boff.height;
++line_count;
diff --git a/src/nvim/normal.c b/src/nvim/normal.c
index 2ef15bde9b..f2b272a13f 100644
--- a/src/nvim/normal.c
+++ b/src/nvim/normal.c
@@ -571,8 +571,8 @@ static bool normal_need_additional_char(NormalState *s)
//
// TODO(tarruda): Visual state needs to be refactored into a
// separate state that "inherits" from normal state.
- || ((cmdchar == 'a' || cmdchar == 'i') &&
- (pending_op || VIsual_active)));
+ || ((cmdchar == 'a' || cmdchar == 'i')
+ && (pending_op || VIsual_active)));
}
static bool normal_need_redraw_mode_message(NormalState *s)
@@ -2286,7 +2286,7 @@ bool do_mouse(oparg_T *oap, int c, int dir, long count, bool fixindent)
save_cursor = curwin->w_cursor;
- for (;; ) {
+ for (;;) {
which_button = get_mouse_button(KEY2TERMCAP1(c), &is_click, &is_drag);
if (is_drag) {
/* If the next character is the same mouse event then use that
@@ -3932,7 +3932,7 @@ bool find_decl(char_u *ptr, size_t len, bool locally, bool thisblock, int flags_
// Search forward for the identifier, ignore comment lines.
clearpos(&found_pos);
- for (;; ) {
+ for (;;) {
t = searchit(curwin, curbuf, &curwin->w_cursor, NULL, FORWARD,
pat, 1L, searchflags, RE_LAST, NULL);
if (curwin->w_cursor.lnum >= old_pos.lnum) {
@@ -4311,7 +4311,7 @@ static void nv_zet(cmdarg_T *cap)
return;
}
n = nchar - '0';
- for (;; ) {
+ for (;;) {
no_mapping++;
nchar = plain_vgetc();
LANGMAP_ADJUST(nchar, true);
@@ -5347,8 +5347,8 @@ static void nv_right(cmdarg_T *cap)
for (n = cap->count1; n > 0; --n) {
if ((!PAST_LINE && oneright() == false)
- || (PAST_LINE &&
- *get_cursor_pos_ptr() == NUL)) {
+ || (PAST_LINE
+ && *get_cursor_pos_ptr() == NUL)) {
// <Space> wraps to next line if 'whichwrap' has 's'.
// 'l' wraps to next line if 'whichwrap' has 'l'.
// CURS_RIGHT wraps to next line if 'whichwrap' has '>'.
@@ -5844,7 +5844,7 @@ static void nv_brackets(cmdarg_T *cap)
pos = NULL;
}
while (n > 0) {
- for (;; ) {
+ for (;;) {
if ((findc == '{' ? dec_cursor() : inc_cursor()) < 0) {
// if not found anything, that's an error
if (pos == NULL) {
@@ -7696,8 +7696,8 @@ static void adjust_cursor(oparg_T *oap)
// - 'virtualedit' is not "all" and not "onemore".
if (curwin->w_cursor.col > 0 && gchar_cursor() == NUL
&& (!VIsual_active || *p_sel == 'o')
- && !virtual_active() &&
- (ve_flags & VE_ONEMORE) == 0) {
+ && !virtual_active()
+ && (ve_flags & VE_ONEMORE) == 0) {
curwin->w_cursor.col--;
// prevent cursor from moving on the trail byte
mb_adjust_cursor();
diff --git a/src/nvim/ops.c b/src/nvim/ops.c
index c2555add50..38de24b8ad 100644
--- a/src/nvim/ops.c
+++ b/src/nvim/ops.c
@@ -378,7 +378,7 @@ static void shift_block(oparg_T *oap, int amount)
bd.startspaces = 0;
}
}
- for (; ascii_iswhite(*bd.textstart); ) {
+ for (; ascii_iswhite(*bd.textstart);) {
// TODO: is passing bd.textstart for start of the line OK?
incr = lbr_chartabsize_adv(bd.textstart, &bd.textstart, (bd.start_vcol));
total += incr;
@@ -2037,7 +2037,7 @@ void op_tilde(oparg_T *oap)
did_change = swapchars(oap->op_type, &pos,
oap->end.col - pos.col + 1);
} else {
- for (;; ) {
+ for (;;) {
did_change |= swapchars(oap->op_type, &pos,
pos.lnum == oap->end.lnum ? oap->end.col + 1 :
(int)STRLEN(ml_get_pos(&pos)));
@@ -2162,7 +2162,8 @@ void op_insert(oparg_T *oap, long count1)
{
long ins_len, pre_textlen = 0;
char_u *firstline, *ins_text;
- colnr_T ind_pre = 0;
+ colnr_T ind_pre_col = 0, ind_post_col;
+ int ind_pre_vcol = 0, ind_post_vcol = 0;
struct block_def bd;
int i;
pos_T t1;
@@ -2196,7 +2197,8 @@ void op_insert(oparg_T *oap, long count1)
// Get the info about the block before entering the text
block_prep(oap, &bd, oap->start.lnum, true);
// Get indent information
- ind_pre = (colnr_T)getwhitecols_curline();
+ ind_pre_col = (colnr_T)getwhitecols_curline();
+ ind_pre_vcol = get_indent();
firstline = ml_get(oap->start.lnum) + bd.textcol;
if (oap->op_type == OP_APPEND) {
@@ -2261,10 +2263,11 @@ void op_insert(oparg_T *oap, long count1)
// if indent kicked in, the firstline might have changed
// but only do that, if the indent actually increased
- const colnr_T ind_post = (colnr_T)getwhitecols_curline();
- if (curbuf->b_op_start.col > ind_pre && ind_post > ind_pre) {
- bd.textcol += ind_post - ind_pre;
- bd.start_vcol += ind_post - ind_pre;
+ ind_post_col = (colnr_T)getwhitecols_curline();
+ if (curbuf->b_op_start.col > ind_pre_col && ind_post_col > ind_pre_col) {
+ bd.textcol += ind_post_col - ind_pre_col;
+ ind_post_vcol = get_indent();
+ bd.start_vcol += ind_post_vcol - ind_pre_vcol;
did_indent = true;
}
@@ -2297,12 +2300,26 @@ void op_insert(oparg_T *oap, long count1)
}
}
- /*
- * Spaces and tabs in the indent may have changed to other spaces and
- * tabs. Get the starting column again and correct the length.
- * Don't do this when "$" used, end-of-line will have changed.
- */
+ // Spaces and tabs in the indent may have changed to other spaces and
+ // tabs. Get the starting column again and correct the length.
+ // Don't do this when "$" used, end-of-line will have changed.
+ //
+ // if indent was added and the inserted text was after the indent,
+ // correct the selection for the new indent.
+ if (did_indent && bd.textcol - ind_post_col > 0) {
+ oap->start.col += ind_post_col - ind_pre_col;
+ oap->start_vcol += ind_post_vcol - ind_pre_vcol;
+ oap->end.col += ind_post_col - ind_pre_col;
+ oap->end_vcol += ind_post_vcol - ind_pre_vcol;
+ }
block_prep(oap, &bd2, oap->start.lnum, true);
+ if (did_indent && bd.textcol - ind_post_col > 0) {
+ // undo for where "oap" is used below
+ oap->start.col -= ind_post_col - ind_pre_col;
+ oap->start_vcol -= ind_post_vcol - ind_pre_vcol;
+ oap->end.col -= ind_post_col - ind_pre_col;
+ oap->end_vcol -= ind_post_vcol - ind_pre_vcol;
+ }
if (!bd.is_MAX || bd2.textlen < bd.textlen) {
if (oap->op_type == OP_APPEND) {
pre_textlen += bd2.textlen - bd.textlen;
@@ -2988,7 +3005,7 @@ void do_put(int regname, yankreg_T *reg, int dir, long count, int flags)
/* For the = register we need to split the string at NL
* characters.
* Loop twice: count the number of lines and save them. */
- for (;; ) {
+ for (;;) {
y_size = 0;
ptr = insert_string;
while (ptr != NULL) {
@@ -3205,7 +3222,7 @@ void do_put(int regname, yankreg_T *reg, int dir, long count, int flags)
// get the old line and advance to the position to insert at
oldp = get_cursor_line_ptr();
oldlen = STRLEN(oldp);
- for (ptr = oldp; vcol < col && *ptr; ) {
+ for (ptr = oldp; vcol < col && *ptr;) {
// Count a tab for what it's worth (if list mode not on)
incr = lbr_chartabsize_adv(oldp, &ptr, vcol);
vcol += incr;
@@ -3341,6 +3358,7 @@ void do_put(int regname, yankreg_T *reg, int dir, long count, int flags)
if (y_type == kMTCharWise && y_size == 1) {
linenr_T end_lnum = 0; // init for gcc
linenr_T start_lnum = lnum;
+ int first_byte_off = 0;
if (VIsual_active) {
end_lnum = curbuf->b_visual.vi_end.lnum;
@@ -3387,6 +3405,10 @@ void do_put(int regname, yankreg_T *reg, int dir, long count, int flags)
}
STRMOVE(ptr, oldp + col);
ml_replace(lnum, newp, false);
+
+ // compute the byte offset for the last character
+ first_byte_off = utf_head_off(newp, ptr - 1);
+
// Place cursor on last putted char.
if (lnum == curwin->w_cursor.lnum) {
// make sure curwin->w_virtcol is updated
@@ -3406,10 +3428,15 @@ void do_put(int regname, yankreg_T *reg, int dir, long count, int flags)
lnum--;
}
+ // put '] at the first byte of the last character
curbuf->b_op_end = curwin->w_cursor;
+ curbuf->b_op_end.col -= first_byte_off;
+
// For "CTRL-O p" in Insert mode, put cursor after last char
if (totlen && (restart_edit != 0 || (flags & PUT_CURSEND))) {
curwin->w_cursor.col++;
+ } else {
+ curwin->w_cursor.col -= first_byte_off;
}
} else {
// Insert at least one line. When y_type is kMTCharWise, break the first
@@ -3521,12 +3548,13 @@ error:
curbuf->b_op_start.lnum, nr_lines, true);
}
- // put '] mark at last inserted character
+ // Put the '] mark on the first byte of the last inserted character.
+ // Correct the length for change in indent.
curbuf->b_op_end.lnum = lnum;
- // correct length for change in indent
col = (colnr_T)STRLEN(y_array[y_size - 1]) - lendiff;
if (col > 1) {
- curbuf->b_op_end.col = col - 1;
+ curbuf->b_op_end.col = col - 1 - utf_head_off(y_array[y_size - 1],
+ y_array[y_size - 1] + col - 1);
} else {
curbuf->b_op_end.col = 0;
}
@@ -3937,8 +3965,8 @@ int do_join(size_t count, int insert_space, int save_undo, int use_formatoptions
|| (utf_ptr2char(curr) < 0x100 && endcurr1 < 0x100))
&& (!has_format_option(FO_MBYTE_JOIN2)
|| (utf_ptr2char(curr) < 0x100 && !utf_eat_space(endcurr1))
- || (endcurr1 < 0x100 &&
- !utf_eat_space(utf_ptr2char(curr))))) {
+ || (endcurr1 < 0x100
+ && !utf_eat_space(utf_ptr2char(curr))))) {
// don't add a space if the line is ending in a space
if (endcurr1 == ' ') {
endcurr1 = endcurr2;
@@ -5632,7 +5660,7 @@ static varnumber_T line_count_info(char_u *line, varnumber_T *wc, varnumber_T *c
varnumber_T chars = 0;
int is_word = 0;
- for (i = 0; i < limit && line[i] != NUL; ) {
+ for (i = 0; i < limit && line[i] != NUL;) {
if (is_word) {
if (ascii_isspace(line[i])) {
words++;
diff --git a/src/nvim/option.c b/src/nvim/option.c
index b85649a5cc..45e2032b35 100644
--- a/src/nvim/option.c
+++ b/src/nvim/option.c
@@ -1233,7 +1233,7 @@ int do_set(char_u *arg, int opt_flags)
}
errmsg = set_bool_option(opt_idx, varp, (int)value,
- opt_flags);
+ opt_flags);
} else { // Numeric or string.
if (vim_strchr((const char_u *)"=:&<", nextchar) == NULL
|| prefix != 1) {
@@ -2315,8 +2315,8 @@ static bool valid_spellfile(const char_u *val)
/// @param opt_flags OPT_LOCAL and/or OPT_GLOBAL
/// @param value_checked value was checked to be safe, no need to set P_INSECURE
static char *did_set_string_option(int opt_idx, char_u **varp, bool new_value_alloced,
- char_u *oldval, char *errbuf, size_t errbuflen,
- int opt_flags, int *value_checked)
+ char_u *oldval, char *errbuf, size_t errbuflen, int opt_flags,
+ int *value_checked)
{
char *errmsg = NULL;
char_u *s, *p;
@@ -2625,7 +2625,7 @@ ambw_end:
}
}
} else if (gvarp == &p_com) { // 'comments'
- for (s = *varp; *s; ) {
+ for (s = *varp; *s;) {
while (*s && *s != ':') {
if (vim_strchr((char_u *)COM_ALL, *s) == NULL
&& !ascii_isdigit(*s) && *s != '-') {
@@ -2650,24 +2650,38 @@ ambw_end:
}
s = skip_to_option_part(s);
}
- } else if (varp == &p_lcs) { // 'listchars'
+ } else if (varp == &p_lcs) { // global 'listchars'
errmsg = set_chars_option(curwin, varp, false);
- if (!errmsg) {
+ if (errmsg == NULL) {
+ // The current window is set to use the global 'listchars' value.
+ // So clear the window-local value.
+ if (!(opt_flags & OPT_GLOBAL)) {
+ clear_string_option(&curwin->w_p_lcs);
+ }
FOR_ALL_TAB_WINDOWS(tp, wp) {
- set_chars_option(wp, &wp->w_p_lcs, true);
+ // If no error was returned above, we don't expect an error
+ // here, so ignore the return value.
+ (void)set_chars_option(wp, &wp->w_p_lcs, true);
}
+ redraw_all_later(NOT_VALID);
}
- redraw_all_later(NOT_VALID);
} else if (varp == &curwin->w_p_lcs) { // local 'listchars'
errmsg = set_chars_option(curwin, varp, true);
- } else if (varp == &p_fcs) { // 'fillchars'
+ } else if (varp == &p_fcs) { // global 'fillchars'
errmsg = set_chars_option(curwin, varp, false);
- if (!errmsg) {
+ if (errmsg == NULL) {
+ // The current window is set to use the global 'fillchars' value.
+ // So clear the window-local value.
+ if (!(opt_flags & OPT_GLOBAL)) {
+ clear_string_option(&curwin->w_p_fcs);
+ }
FOR_ALL_TAB_WINDOWS(tp, wp) {
- set_chars_option(wp, &wp->w_p_fcs, true);
+ // If no error was returned above, we don't expect an error
+ // here, so ignore the return value.
+ (void)set_chars_option(wp, &wp->w_p_fcs, true);
}
+ redraw_all_later(NOT_VALID);
}
- redraw_all_later(NOT_VALID);
} else if (varp == &curwin->w_p_fcs) { // local 'fillchars'
errmsg = set_chars_option(curwin, varp, true);
} else if (varp == &p_cedit) { // 'cedit'
@@ -2690,7 +2704,7 @@ ambw_end:
// there would be a disconnect between the check for P_ALLOCED at the start
// of the function and the set of P_ALLOCED at the end of the function.
free_oldval = (options[opt_idx].flags & P_ALLOCED);
- for (s = p_shada; *s; ) {
+ for (s = p_shada; *s;) {
// Check it's a valid character
if (vim_strchr((char_u *)"!\"%'/:<@cfhnrs", *s) == NULL) {
errmsg = illegal_char(errbuf, errbuflen, *s);
@@ -2735,7 +2749,7 @@ ambw_end:
errmsg = N_("E528: Must specify a ' value");
}
} else if (gvarp == &p_sbr) { // 'showbreak'
- for (s = *varp; *s; ) {
+ for (s = *varp; *s;) {
if (ptr2cells(s) != 1) {
errmsg = N_("E595: 'showbreak' contains unprintable or wide character");
}
@@ -2879,7 +2893,7 @@ ambw_end:
}
} else if (gvarp == &p_cpt) {
// check if it is a valid value for 'complete' -- Acevedo
- for (s = *varp; *s; ) {
+ for (s = *varp; *s;) {
while (*s == ',' || *s == ' ') {
s++;
}
@@ -3355,7 +3369,7 @@ char *check_colorcolumn(win_T *wp)
return NULL; // buffer was closed
}
- for (s = wp->w_p_cc; *s != NUL && count < 255; ) {
+ for (s = wp->w_p_cc; *s != NUL && count < 255;) {
if (*s == '-' || *s == '+') {
// -N and +N: add to 'textwidth'
col = (*s == '-') ? -1 : 1;
@@ -6804,7 +6818,7 @@ static void langmap_set(void)
ga_clear(&langmap_mapga); // clear the previous map first
langmap_init(); // back to one-to-one map
- for (p = p_langmap; p[0] != NUL; ) {
+ for (p = p_langmap; p[0] != NUL;) {
for (p2 = p; p2[0] != NUL && p2[0] != ',' && p2[0] != ';';
MB_PTR_ADV(p2)) {
if (p2[0] == '\\' && p2[1] != NUL) {
diff --git a/src/nvim/os/fs.c b/src/nvim/os/fs.c
index 3ff13c2b3f..e9963516fc 100644
--- a/src/nvim/os/fs.c
+++ b/src/nvim/os/fs.c
@@ -369,7 +369,7 @@ static bool is_executable_in_path(const char *name, char **abspath)
// is an executable file.
char *p = path;
bool rv = false;
- for (;; ) {
+ for (;;) {
char *e = xstrchrnul(p, ENV_SEPCHAR);
// Combine the $PATH segment with `name`.
diff --git a/src/nvim/os/stdpaths.c b/src/nvim/os/stdpaths.c
index 10b0d391bf..5b824d23f4 100644
--- a/src/nvim/os/stdpaths.c
+++ b/src/nvim/os/stdpaths.c
@@ -146,7 +146,7 @@ char *stdpaths_user_data_subpath(const char *fname, const size_t trailing_pathse
const size_t numcommas = (escape_commas ? memcnt(ret, ',', len) : 0);
if (numcommas || trailing_pathseps) {
ret = xrealloc(ret, len + trailing_pathseps + numcommas + 1);
- for (size_t i = 0 ; i < len + numcommas ; i++) {
+ for (size_t i = 0; i < len + numcommas; i++) {
if (ret[i] == ',') {
memmove(ret + i + 1, ret + i, len - i + numcommas);
ret[i] = '\\';
diff --git a/src/nvim/path.c b/src/nvim/path.c
index c28d848683..7b9081eafa 100644
--- a/src/nvim/path.c
+++ b/src/nvim/path.c
@@ -1079,7 +1079,7 @@ const char *gettail_dir(const char *const fname)
const char *next_dir_end = fname;
bool look_for_sep = true;
- for (const char *p = fname; *p != NUL; ) {
+ for (const char *p = fname; *p != NUL;) {
if (vim_ispathsep(*p)) {
if (look_for_sep) {
next_dir_end = p;
@@ -1289,8 +1289,8 @@ int gen_expand_wildcards(int num_pat, char_u **pat, int *num_file, char_u ***fil
&& !path_is_absolute(p)
&& !(p[0] == '.'
&& (vim_ispathsep(p[1])
- || (p[1] == '.' &&
- vim_ispathsep(p[2]))))) {
+ || (p[1] == '.'
+ && vim_ispathsep(p[2]))))) {
/* :find completion where 'path' is used.
* Recursiveness is OK here. */
recursive = false;
@@ -1505,7 +1505,7 @@ void simplify_filename(char_u *filename)
if (vim_ispathsep(*p)) {
relative = false;
- do{
+ do {
++p;
}
while (vim_ispathsep(*p));
@@ -1517,8 +1517,8 @@ void simplify_filename(char_u *filename)
* or "p" is at the "start" of the (absolute or relative) path name. */
if (vim_ispathsep(*p)) {
STRMOVE(p, p + 1); // remove duplicate "/"
- } else if (p[0] == '.' &&
- (vim_ispathsep(p[1]) || p[1] == NUL)) {
+ } else if (p[0] == '.'
+ && (vim_ispathsep(p[1]) || p[1] == NUL)) {
if (p == start && relative) {
p += 1 + (p[1] != NUL); // keep single "." or leading "./"
} else {
@@ -2198,7 +2198,7 @@ int match_suffix(char_u *fname)
size_t fnamelen = STRLEN(fname);
size_t setsuflen = 0;
- for (char_u *setsuf = p_su; *setsuf; ) {
+ for (char_u *setsuf = p_su; *setsuf;) {
setsuflen = copy_option_part(&setsuf, suf_buf, MAXSUFLEN, ".,");
if (setsuflen == 0) {
char_u *tail = path_tail(fname);
@@ -2245,11 +2245,17 @@ int path_full_dir_name(char *directory, char *buffer, size_t len)
}
if (os_chdir(directory) != SUCCESS) {
- // Do not return immediately since we may be in the wrong directory.
- retval = FAIL;
- }
-
- if (retval == FAIL || os_dirname((char_u *)buffer, len) == FAIL) {
+ // Path does not exist (yet). For a full path fail,
+ // will use the path as-is. For a relative path use
+ // the current directory and append the file name.
+ if (path_is_absolute((const char_u *)directory)) {
+ // Do not return immediately since we may be in the wrong directory.
+ retval = FAIL;
+ } else {
+ xstrlcpy(buffer, old_dir, len);
+ append_path(buffer, directory, len);
+ }
+ } else if (os_dirname((char_u *)buffer, len) == FAIL) {
// Do not return immediately since we are in the wrong directory.
retval = FAIL;
}
diff --git a/src/nvim/quickfix.c b/src/nvim/quickfix.c
index bf9052de6f..6a192d148f 100644
--- a/src/nvim/quickfix.c
+++ b/src/nvim/quickfix.c
@@ -539,7 +539,7 @@ static size_t efm_regpat_bufsz(char_u *efm)
size_t sz;
sz = (FMT_PATTERNS * 3) + (STRLEN(efm) << 2);
- for (int i = FMT_PATTERNS - 1; i >= 0; ) {
+ for (int i = FMT_PATTERNS - 1; i >= 0;) {
sz += STRLEN(fmt_pat[i--].pattern);
}
#ifdef BACKSLASH_IN_FILENAME
@@ -2028,7 +2028,7 @@ void copy_loclist_stack(win_T *from, win_T *to)
/// Get buffer number for file "directory/fname".
/// Also sets the b_has_qf_entry flag.
-static int qf_get_fnum(qf_list_T *qfl, char_u *directory, char_u *fname )
+static int qf_get_fnum(qf_list_T *qfl, char_u *directory, char_u *fname)
{
char_u *ptr = NULL;
char_u *bufname;
@@ -4380,7 +4380,7 @@ static char_u *get_mef_name(void)
}
// Keep trying until the name doesn't exist yet.
- for (;; ) {
+ for (;;) {
if (start == -1) {
start = (int)os_get_pid();
} else {
diff --git a/src/nvim/runtime.c b/src/nvim/runtime.c
index 14f49d05d5..be365d4ab8 100644
--- a/src/nvim/runtime.c
+++ b/src/nvim/runtime.c
@@ -479,7 +479,7 @@ RuntimeSearchPath runtime_search_path_build(void)
CharVec after_path = KV_INITIAL_VALUE;
static char_u buf[MAXPATHL];
- for (char *entry = (char *)p_pp; *entry != NUL; ) {
+ for (char *entry = (char *)p_pp; *entry != NUL;) {
char *cur_entry = entry;
copy_option_part((char_u **)&entry, buf, MAXPATHL, ",");
@@ -491,7 +491,7 @@ RuntimeSearchPath runtime_search_path_build(void)
char *rtp_entry;
- for (rtp_entry = (char *)p_rtp; *rtp_entry != NUL; ) {
+ for (rtp_entry = (char *)p_rtp; *rtp_entry != NUL;) {
char *cur_entry = rtp_entry;
copy_option_part((char_u **)&rtp_entry, buf, MAXPATHL, ",");
size_t buflen = STRLEN(buf);
@@ -663,7 +663,7 @@ static int add_pack_dir_to_rtp(char_u *fname, bool is_pack)
}
const char *insp = NULL;
const char *after_insp = NULL;
- for (const char *entry = (const char *)p_rtp; *entry != NUL; ) {
+ for (const char *entry = (const char *)p_rtp; *entry != NUL;) {
const char *cur_entry = entry;
copy_option_part((char_u **)&entry, buf, MAXPATHL, ",");
diff --git a/src/nvim/screen.c b/src/nvim/screen.c
index cc3fab3503..2ce2be0bfd 100644
--- a/src/nvim/screen.c
+++ b/src/nvim/screen.c
@@ -1084,7 +1084,7 @@ static void win_update(win_T *wp, Providers *providers)
*/
bot_start = 0;
idx = 0;
- for (;; ) {
+ for (;;) {
wp->w_lines[idx] = wp->w_lines[j];
/* stop at line that didn't fit, unless it is still
* valid (no lines deleted) */
@@ -1359,7 +1359,7 @@ static void win_update(win_T *wp, Providers *providers)
win_check_ns_hl(wp);
- for (;; ) {
+ for (;;) {
/* stop updating when reached the end of the window (check for _past_
* the end of the window is at the end of the loop) */
if (row == wp->w_grid.Rows) {
@@ -1508,7 +1508,7 @@ static void win_update(win_T *wp, Providers *providers)
int x = row + new_rows;
// move entries in w_lines[] upwards
- for (;; ) {
+ for (;;) {
// stop at last valid entry in w_lines[]
if (i >= wp->w_lines_valid) {
wp->w_lines_valid = j;
@@ -2707,7 +2707,7 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool noc
int sign_idx = 0;
// Repeat for the whole displayed line.
- for (;; ) {
+ for (;;) {
int has_match_conc = 0; ///< match wants to conceal
bool did_decrement_ptr = false;
@@ -4413,8 +4413,8 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool noc
|| filler_todo > 0
|| (wp->w_p_list && wp->w_p_lcs_chars.eol != NUL
&& p_extra != at_end_str)
- || (n_extra != 0 &&
- (c_extra != NUL || *p_extra != NUL)))) {
+ || (n_extra != 0
+ && (c_extra != NUL || *p_extra != NUL)))) {
bool wrap = wp->w_p_wrap // Wrapping enabled.
&& filler_todo <= 0 // Not drawing diff filler lines.
&& lcs_eol_one != -1 // Haven't printed the lcs_eol character.
@@ -5011,8 +5011,8 @@ static int skip_status_match_char(expand_T *xp, char_u *s)
if ((rem_backslash(s) && xp->xp_context != EXPAND_HELP)
|| ((xp->xp_context == EXPAND_MENUS
|| xp->xp_context == EXPAND_MENUNAMES)
- && (s[0] == '\t' ||
- (s[0] == '\\' && s[1] != NUL)))) {
+ && (s[0] == '\t'
+ || (s[0] == '\\' && s[1] != NUL)))) {
#ifndef BACKSLASH_IN_FILENAME
if (xp->xp_shell && csh_like_shell() && s[1] == '\\' && s[2] == '!') {
return 2;
@@ -6144,7 +6144,7 @@ static void next_search_hl(win_T *win, match_T *shl, linenr_T lnum, colnr_T minc
* or none is found in this line.
*/
called_emsg = FALSE;
- for (;; ) {
+ for (;;) {
// Stop searching after passing the time limit.
if (profile_passed_limit(shl->tm)) {
shl->lnum = 0; // no match found in time
diff --git a/src/nvim/search.c b/src/nvim/search.c
index 0756fbf37d..f47315705c 100644
--- a/src/nvim/search.c
+++ b/src/nvim/search.c
@@ -370,8 +370,8 @@ int ignorecase_opt(char_u *pat, int ic_in, int scs)
{
int ic = ic_in;
if (ic && !no_smartcase && scs
- && !(ctrl_x_mode_not_default() &&
- curbuf->b_p_inf)) {
+ && !(ctrl_x_mode_not_default()
+ && curbuf->b_p_inf)) {
ic = !pat_has_uppercase(pat);
}
no_smartcase = false;
@@ -757,7 +757,7 @@ int searchit(win_T *win, buf_T *buf, pos_T *pos, pos_T *end_pos, Direction dir,
* relative to the end of the match.
*/
match_ok = false;
- for (;; ) {
+ for (;;) {
// Remember a position that is before the start
// position, we use it if it's the last match in
// the line. Always accept a position after
@@ -1105,7 +1105,7 @@ int do_search(oparg_T *oap, int dirc, int search_delim, char_u *pat, long count,
/*
* Repeat the search when pattern followed by ';', e.g. "/foo/;?bar".
*/
- for (;; ) {
+ for (;;) {
bool show_top_bot_msg = false;
searchstr = pat;
@@ -1465,7 +1465,7 @@ int search_for_exact_line(buf_T *buf, pos_T *pos, Direction dir, char_u *pat)
if (buf->b_ml.ml_line_count == 0) {
return FAIL;
}
- for (;; ) {
+ for (;;) {
pos->lnum += dir;
if (pos->lnum < 1) {
if (p_ws) {
@@ -1585,7 +1585,7 @@ int searchc(cmdarg_T *cap, int t_cmd)
len = (int)STRLEN(p);
while (count--) {
- for (;; ) {
+ for (;;) {
if (dir > 0) {
col += utfc_ptr2len(p + col);
if (col >= len) {
@@ -1808,6 +1808,9 @@ pos_T *findmatchlimit(oparg_T *oap, int initc, int flags, int64_t maxtravel)
initc = NUL;
} else if (initc != '#' && initc != NUL) {
find_mps_values(&initc, &findc, &backwards, true);
+ if (dir) {
+ backwards = (dir == FORWARD) ? false : true;
+ }
if (findc == NUL) {
return NULL;
}
@@ -1870,7 +1873,7 @@ pos_T *findmatchlimit(oparg_T *oap, int initc, int flags, int64_t maxtravel)
if (linep[pos.col] == NUL && pos.col) {
--pos.col;
}
- for (;; ) {
+ for (;;) {
initc = utf_ptr2char(linep + pos.col);
if (initc == NUL) {
break;
@@ -1894,7 +1897,7 @@ pos_T *findmatchlimit(oparg_T *oap, int initc, int flags, int64_t maxtravel)
// Set "match_escaped" if there are an odd number of
// backslashes.
- for (col = pos.col; check_prevcol(linep, col, '\\', &col); ) {
+ for (col = pos.col; check_prevcol(linep, col, '\\', &col);) {
bslcnt++;
}
match_escaped = (bslcnt & 1);
@@ -2278,7 +2281,7 @@ pos_T *findmatchlimit(oparg_T *oap, int initc, int flags, int64_t maxtravel)
int col, bslcnt = 0;
if (!cpo_bsl) {
- for (col = pos.col; check_prevcol(linep, col, '\\', &col); ) {
+ for (col = pos.col; check_prevcol(linep, col, '\\', &col);) {
bslcnt++;
}
}
@@ -2520,7 +2523,7 @@ int findsent(Direction dir, long count)
const int startlnum = pos.lnum;
const bool cpo_J = vim_strchr(p_cpo, CPO_ENDOFSENT) != NULL;
- for (;; ) { // find end of sentence
+ for (;;) { // find end of sentence
c = gchar_pos(&pos);
if (c == NUL || (pos.col == 0 && startPS(pos.lnum, NUL, FALSE))) {
if (dir == BACKWARD && pos.lnum != startlnum) {
@@ -2530,7 +2533,7 @@ int findsent(Direction dir, long count)
}
if (c == '.' || c == '!' || c == '?') {
tpos = pos;
- do{
+ do {
if ((c = inc(&tpos)) == -1) {
break;
}
@@ -3004,7 +3007,7 @@ static void back_in_line(void)
int sclass; // starting class
sclass = cls();
- for (;; ) {
+ for (;;) {
if (curwin->w_cursor.col == 0) { // stop at start of line
break;
}
@@ -3427,12 +3430,22 @@ int current_block(oparg_T *oap, long count, int include, int what, int other)
// user wants.
save_cpo = p_cpo;
p_cpo = (char_u *)(vim_strchr(p_cpo, CPO_MATCHBSL) != NULL ? "%M" : "%");
- while (count-- > 0) {
- if ((pos = findmatch(NULL, what)) == NULL) {
- break;
+ if ((pos = findmatch(NULL, what)) != NULL) {
+ while (count-- > 0) {
+ if ((pos = findmatch(NULL, what)) == NULL) {
+ break;
+ }
+ curwin->w_cursor = *pos;
+ start_pos = *pos; // the findmatch for end_pos will overwrite *pos
+ }
+ } else {
+ while (count-- > 0) {
+ if ((pos = findmatchlimit(NULL, what, FM_FORWARD, 0)) == NULL) {
+ break;
+ }
+ curwin->w_cursor = *pos;
+ start_pos = *pos; // the findmatch for end_pos will overwrite *pos
}
- curwin->w_cursor = *pos;
- start_pos = *pos; // the findmatch for end_pos will overwrite *pos
}
p_cpo = save_cpo;
@@ -3527,7 +3540,7 @@ static bool in_html_tag(bool end_tag)
int lc = NUL;
pos_T pos;
- for (p = line + curwin->w_cursor.col; p > line; ) {
+ for (p = line + curwin->w_cursor.col; p > line;) {
if (*p == '<') { // find '<' under/before cursor
break;
}
@@ -3555,7 +3568,7 @@ static bool in_html_tag(bool end_tag)
}
// check that the matching '>' is not preceded by '/'
- for (;; ) {
+ for (;;) {
if (inc(&pos) < 0) {
return false;
}
@@ -3791,7 +3804,7 @@ extend:
} else {
dir = FORWARD;
}
- for (i = count; --i >= 0; ) {
+ for (i = count; --i >= 0;) {
if (start_lnum ==
(dir == BACKWARD ? 1 : curbuf->b_ml.ml_line_count)) {
retval = FAIL;
@@ -3806,7 +3819,7 @@ extend:
start_lnum -= dir;
break;
}
- for (;; ) {
+ for (;;) {
if (start_lnum == (dir == BACKWARD
? 1 : curbuf->b_ml.ml_line_count)) {
break;
@@ -3946,7 +3959,7 @@ static int find_next_quote(char_u *line, int col, int quotechar, char_u *escape)
{
int c;
- for (;; ) {
+ for (;;) {
c = line[col];
if (c == NUL) {
return -1;
@@ -4118,7 +4131,7 @@ bool current_quote(oparg_T *oap, long count, bool include, int quotechar)
// Also do this when there is a Visual area, a' may leave the cursor
// in between two strings.
col_start = 0;
- for (;; ) {
+ for (;;) {
// Find open quote character.
col_start = find_next_quote(line, col_start, quotechar, NULL);
if (col_start < 0 || col_start > first_col) {
@@ -4842,7 +4855,7 @@ void find_pattern_in_path(char_u *ptr, Direction dir, size_t len, bool whole, bo
}
line = ml_get(lnum);
- for (;; ) {
+ for (;;) {
if (incl_regmatch.regprog != NULL
&& vim_regexec(&incl_regmatch, line, (colnr_T)0)) {
char_u *p_fname = (curr_fname == curbuf->b_fname)
@@ -5235,6 +5248,9 @@ search_line:
if (depth == -1) {
// match in current file
if (l_g_do_tagpreview != 0) {
+ if (!win_valid(curwin_save)) {
+ break;
+ }
if (!GETFILE_SUCCESS(getfile(curwin_save->w_buffer->b_fnum, NULL,
NULL, true, lnum, false))) {
break; // failed to jump to file
@@ -5379,7 +5395,7 @@ static void show_pat_in_path(char_u *line, int type, bool did_show, int action,
if (got_int) { // 'q' typed at "--more--" message
return;
}
- for (;; ) {
+ for (;;) {
p = line + STRLEN(line) - 1;
if (fp != NULL) {
// We used fgets(), so get rid of newline at end
diff --git a/src/nvim/shada.c b/src/nvim/shada.c
index 89f9d3a719..e75a244031 100644
--- a/src/nvim/shada.c
+++ b/src/nvim/shada.c
@@ -3977,7 +3977,7 @@ static bool shada_removable(const char *name)
bool retval = false;
char *new_name = (char *)home_replace_save(NULL, (char_u *)name);
- for (p = (char *)p_shada; *p; ) {
+ for (p = (char *)p_shada; *p;) {
(void)copy_option_part((char_u **)&p, (char_u *)part, ARRAY_SIZE(part), ", ");
if (part[0] == 'r') {
home_replace(NULL, (char_u *)(part + 1), (char_u *)NameBuff, MAXPATHL, true);
diff --git a/src/nvim/sign.c b/src/nvim/sign.c
index dfa863d0ff..fca73dc9f2 100644
--- a/src/nvim/sign.c
+++ b/src/nvim/sign.c
@@ -80,7 +80,7 @@ static signgroup_T *sign_group_ref(const char_u *groupname)
hi = hash_lookup(&sg_table, (char *)groupname, STRLEN(groupname), hash);
if (HASHITEM_EMPTY(hi)) {
// new group
- group = xmalloc((unsigned)(sizeof(signgroup_T) + STRLEN(groupname)));
+ group = xmalloc(sizeof(signgroup_T) + STRLEN(groupname));
STRCPY(group->sg_name, groupname);
group->sg_refcount = 1;
@@ -774,7 +774,7 @@ static int sign_cmd_idx(char_u *begin_cmd, char_u *end_cmd)
char_u save = *end_cmd;
*end_cmd = (char_u)NUL;
- for (idx = 0; ; idx++) {
+ for (idx = 0;; idx++) {
if (cmds[idx] == NULL || STRCMP(begin_cmd, cmds[idx]) == 0) {
break;
}
@@ -816,7 +816,7 @@ static sign_T *alloc_new_sign(char_u *name)
// Check that next_sign_typenr is not already being used.
// This only happens after wrapping around. Hopefully
// another one got deleted and we can use its number.
- for (lp = first_sign; lp != NULL; ) {
+ for (lp = first_sign; lp != NULL;) {
if (lp->sn_typenr == next_sign_typenr) {
next_sign_typenr++;
if (next_sign_typenr == MAX_TYPENR) {
diff --git a/src/nvim/spell.c b/src/nvim/spell.c
index 20081bce4f..85d1e139bf 100644
--- a/src/nvim/spell.c
+++ b/src/nvim/spell.c
@@ -622,7 +622,7 @@ static void find_word(matchinf_T *mip, int mode)
// - there is a byte that doesn't match,
// - we reach the end of the tree,
// - or we reach the end of the line.
- for (;; ) {
+ for (;;) {
if (flen <= 0 && *mip->mi_fend != NUL) {
flen = fold_more(mip);
}
@@ -689,7 +689,7 @@ static void find_word(matchinf_T *mip, int mode)
// One space in the good word may stand for several spaces in the
// checked word.
if (c == ' ') {
- for (;; ) {
+ for (;;) {
if (flen <= 0 && *mip->mi_fend != NUL) {
flen = fold_more(mip);
}
@@ -1269,7 +1269,7 @@ static void find_prefix(matchinf_T *mip, int mode)
// - there is a byte that doesn't match,
// - we reach the end of the tree,
// - or we reach the end of the line.
- for (;; ) {
+ for (;;) {
if (flen == 0 && *mip->mi_fend != NUL) {
flen = fold_more(mip);
}
@@ -2083,7 +2083,7 @@ char *did_set_spelllang(win_T *wp)
wp->w_s->b_cjk = 0;
// Loop over comma separated language names.
- for (splp = spl_copy; *splp != NUL; ) {
+ for (splp = spl_copy; *splp != NUL;) {
// Get one language name.
copy_option_part(&splp, lang, MAXWLEN, ",");
region = NULL;
@@ -2354,7 +2354,7 @@ static void use_midword(slang_T *lp, win_T *wp)
return;
}
- for (char_u *p = lp->sl_midword; *p != NUL; ) {
+ for (char_u *p = lp->sl_midword; *p != NUL;) {
const int c = utf_ptr2char(p);
const int l = utfc_ptr2len(p);
if (c < 256 && l <= 2) {
@@ -2759,7 +2759,7 @@ int spell_casefold(const win_T *wp, char_u *str, int len, char_u *buf, int bufle
int outi = 0;
// Fold one character at a time.
- for (char_u *p = str; p < str + len; ) {
+ for (char_u *p = str; p < str + len;) {
if (outi + MB_MAXBYTES > buflen) {
buf[outi] = NUL;
return FAIL;
@@ -2806,7 +2806,7 @@ int spell_check_sps(void)
sps_flags = 0;
sps_limit = 9999;
- for (p = p_sps; *p != NUL; ) {
+ for (p = p_sps; *p != NUL;) {
copy_option_part(&p, buf, MAXPATHL, ",");
f = 0;
@@ -3118,7 +3118,7 @@ static bool check_need_cap(linenr_T lnum, colnr_T col)
regmatch.regprog = curwin->w_s->b_cap_prog;
regmatch.rm_ic = FALSE;
p = line + endcol;
- for (;; ) {
+ for (;;) {
MB_PTR_BACK(line, p);
if (p == line || spell_iswordp_nmw(p, curwin)) {
break;
@@ -3330,7 +3330,7 @@ static void spell_find_suggest(char_u *badptr, int badlen, suginfo_T *su, int ma
sps_copy = vim_strsave(p_sps);
// Loop over the items in 'spellsuggest'.
- for (p = sps_copy; *p != NUL; ) {
+ for (p = sps_copy; *p != NUL;) {
copy_option_part(&p, buf, MAXPATHL, ",");
if (STRNCMP(buf, "expr:", 5) == 0) {
@@ -3557,7 +3557,7 @@ void onecap_copy(char_u *word, char_u *wcopy, bool upper)
static void allcap_copy(char_u *word, char_u *wcopy)
{
char_u *d = wcopy;
- for (char_u *s = word; *s != NUL; ) {
+ for (char_u *s = word; *s != NUL;) {
int c = mb_cptr2char_adv((const char_u **)&s);
if (c == 0xdf) {
@@ -4352,8 +4352,8 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char_u *fword, bool so
// just deleted this byte, accepting it is always cheaper than
// delete + substitute.
if (c == fword[sp->ts_fidx]
- || (sp->ts_tcharlen > 0 &&
- sp->ts_isdiff != DIFF_NONE)) {
+ || (sp->ts_tcharlen > 0
+ && sp->ts_isdiff != DIFF_NONE)) {
newscore = 0;
} else {
newscore = SCORE_SUBST;
@@ -4513,7 +4513,7 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char_u *fword, bool so
// skip over NUL bytes
n = sp->ts_arridx;
- for (;; ) {
+ for (;;) {
if (sp->ts_curi > byts[n]) {
// Only NUL bytes at this node, go to next state.
PROF_STORE(sp->ts_state)
@@ -5257,7 +5257,7 @@ static int stp_sal_score(suggest_T *stp, suginfo_T *su, slang_T *slang, char_u *
// space.
if (ascii_iswhite(su->su_badptr[su->su_badlen])
&& *skiptowhite(stp->st_word) == NUL) {
- for (p = fword; *(p = skiptowhite(p)) != NUL; ) {
+ for (p = fword; *(p = skiptowhite(p)) != NUL;) {
STRMOVE(p, p + 1);
}
}
@@ -5568,7 +5568,7 @@ static int soundfold_find(slang_T *slang, char_u *word)
byts = slang->sl_sbyts;
idxs = slang->sl_sidxs;
- for (;; ) {
+ for (;;) {
// First byte is the number of possible bytes.
len = byts[arridx++];
@@ -5701,7 +5701,7 @@ static void add_suggestion(suginfo_T *su, garray_T *gap, const char_u *goodword,
// "thee the" is added next to changing the first "the" the "thee".
const char_u *pgood = goodword + STRLEN(goodword);
char_u *pbad = su->su_badptr + badlenarg;
- for (;; ) {
+ for (;;) {
goodlen = (int)(pgood - goodword);
badlen = (int)(pbad - su->su_badptr);
if (goodlen <= 0 || badlen <= 0) {
@@ -6004,7 +6004,7 @@ static void spell_soundfold_sofo(slang_T *slang, char_u *inword, char_u *res)
// The sl_sal_first[] table contains the translation for chars up to
// 255, sl_sal the rest.
- for (char_u *s = inword; *s != NUL; ) {
+ for (char_u *s = inword; *s != NUL;) {
int c = mb_cptr2char_adv((const char_u **)&s);
if (utf_class(c) == 0) {
c = ' ';
@@ -6015,7 +6015,7 @@ static void spell_soundfold_sofo(slang_T *slang, char_u *inword, char_u *res)
if (ip == NULL) { // empty list, can't match
c = NUL;
} else {
- for (;; ) { // find "c" in the list
+ for (;;) { // find "c" in the list
if (*ip == 0) { // not found
c = NUL;
break;
@@ -6069,7 +6069,7 @@ static void spell_soundfold_wsal(slang_T *slang, char_u *inword, char_u *res)
// Remove accents, if wanted. We actually remove all non-word characters.
// But keep white space.
wordlen = 0;
- for (const char_u *s = inword; *s != NUL; ) {
+ for (const char_u *s = inword; *s != NUL;) {
const char_u *t = s;
c = mb_cptr2char_adv(&s);
if (slang->sl_rem_accents) {
@@ -6591,12 +6591,12 @@ static int spell_edit_score(slang_T *slang, char_u *badword, char_u *goodword)
// Get the characters from the multi-byte strings and put them in an
// int array for easy access.
badlen = 0;
- for (const char_u *p = badword; *p != NUL; ) {
+ for (const char_u *p = badword; *p != NUL;) {
wbadword[badlen++] = mb_cptr2char_adv(&p);
}
wbadword[badlen++] = 0;
goodlen = 0;
- for (const char_u *p = goodword; *p != NUL; ) {
+ for (const char_u *p = goodword; *p != NUL;) {
wgoodword[goodlen++] = mb_cptr2char_adv(&p);
}
wgoodword[goodlen++] = 0;
@@ -6690,12 +6690,12 @@ static int spell_edit_score_limit_w(slang_T *slang, char_u *badword, char_u *goo
// Get the characters from the multi-byte strings and put them in an
// int array for easy access.
bi = 0;
- for (const char_u *p = badword; *p != NUL; ) {
+ for (const char_u *p = badword; *p != NUL;) {
wbadword[bi++] = mb_cptr2char_adv(&p);
}
wbadword[bi++] = 0;
gi = 0;
- for (const char_u *p = goodword; *p != NUL; ) {
+ for (const char_u *p = goodword; *p != NUL;) {
wgoodword[gi++] = mb_cptr2char_adv(&p);
}
wgoodword[gi++] = 0;
@@ -6713,9 +6713,9 @@ static int spell_edit_score_limit_w(slang_T *slang, char_u *badword, char_u *goo
score = 0;
minscore = limit + 1;
- for (;; ) {
+ for (;;) {
// Skip over an equal part, score remains the same.
- for (;; ) {
+ for (;;) {
bc = wbadword[bi];
gc = wgoodword[gi];
@@ -7289,7 +7289,7 @@ int spell_word_start(int startcol)
// Find a word character before "startcol".
line = get_cursor_line_ptr();
- for (p = line + startcol; p > line; ) {
+ for (p = line + startcol; p > line;) {
MB_PTR_BACK(line, p);
if (spell_iswordp_nmw(p, curwin)) {
break;
diff --git a/src/nvim/spellfile.c b/src/nvim/spellfile.c
index 0fc9012f27..ae4514dd30 100644
--- a/src/nvim/spellfile.c
+++ b/src/nvim/spellfile.c
@@ -549,7 +549,7 @@ static inline int spell_check_magic_string(FILE *const fd)
FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_ALWAYS_INLINE
{
char buf[VIMSPELLMAGICL];
- SPELL_READ_BYTES(buf, VIMSPELLMAGICL, fd, ; );
+ SPELL_READ_BYTES(buf, VIMSPELLMAGICL, fd,; );
if (memcmp(buf, VIMSPELLMAGIC, VIMSPELLMAGICL) != 0) {
return SP_FORMERROR;
}
@@ -640,7 +640,7 @@ slang_T *spell_load_file(char_u *fname, char_u *lang, slang_T *old_lp, bool sile
// <SECTIONS>: <section> ... <sectionend>
// <section>: <sectionID> <sectionflags> <sectionlen> (section contents)
- for (;; ) {
+ for (;;) {
n = getc(fd); // <sectionID> or <sectionend>
if (n == SN_END) {
break;
@@ -960,7 +960,7 @@ someerror:
ga_init(&ga, 1, 100);
for (wordnr = 0; wordnr < wcount; ++wordnr) {
ga.ga_len = 0;
- for (;; ) {
+ for (;;) {
c = getc(fd); // <sugline>
if (c < 0) {
goto someerror;
@@ -1030,7 +1030,7 @@ static int read_region_section(FILE *fd, slang_T *lp, int len)
if (len > MAXREGIONS * 2) {
return SP_FORMERROR;
}
- SPELL_READ_NONNUL_BYTES((char *)lp->sl_regions, (size_t)len, fd, ; );
+ SPELL_READ_NONNUL_BYTES((char *)lp->sl_regions, (size_t)len, fd,; );
lp->sl_regions[len] = NUL;
return 0;
}
@@ -1097,7 +1097,7 @@ static int read_prefcond_section(FILE *fd, slang_T *lp)
if (n > 0) {
char buf[MAXWLEN + 1];
buf[0] = '^'; // always match at one position only
- SPELL_READ_NONNUL_BYTES(buf + 1, (size_t)n, fd, ; );
+ SPELL_READ_NONNUL_BYTES(buf + 1, (size_t)n, fd,; );
buf[n + 1] = NUL;
lp->sl_prefprog[i] = vim_regcomp((char_u *)buf, RE_MAGIC | RE_STRING);
}
@@ -1548,7 +1548,7 @@ static int set_sofo(slang_T *lp, char_u *from, char_u *to)
// First count the number of items for each list. Temporarily use
// sl_sal_first[] for this.
- for (p = from, s = to; *p != NUL && *s != NUL; ) {
+ for (p = from, s = to; *p != NUL && *s != NUL;) {
const int c = mb_cptr2char_adv((const char_u **)&p);
MB_CPTR_ADV(s);
if (c >= 256) {
@@ -1571,7 +1571,7 @@ static int set_sofo(slang_T *lp, char_u *from, char_u *to)
// Put the characters up to 255 in sl_sal_first[] the rest in a sl_sal
// list.
memset(lp->sl_sal_first, 0, sizeof(salfirst_T) * 256);
- for (p = from, s = to; *p != NUL && *s != NUL; ) {
+ for (p = from, s = to; *p != NUL && *s != NUL;) {
const int c = mb_cptr2char_adv((const char_u **)&p);
const int i = mb_cptr2char_adv((const char_u **)&s);
if (c >= 256) {
@@ -1647,7 +1647,7 @@ static int *mb_str2wide(char_u *s)
int i = 0;
int *res = xmalloc((mb_charlen(s) + 1) * sizeof(int));
- for (char_u *p = s; *p != NUL; ) {
+ for (char_u *p = s; *p != NUL;) {
res[i++] = mb_ptr2char_adv((const char_u **)&p);
}
res[i] = NUL;
@@ -2095,7 +2095,7 @@ static afffile_T *spell_read_aff(spellinfo_T *spin, char_u *fname)
// Split the line up in white separated items. Put a NUL after each
// item.
itemcnt = 0;
- for (p = line;; ) {
+ for (p = line;;) {
while (*p != NUL && *p <= ' ') { // skip white space and CR/NL
++p;
}
@@ -2646,7 +2646,7 @@ static afffile_T *spell_read_aff(spellinfo_T *spin, char_u *fname)
int c;
// Check that every character appears only once.
- for (p = items[1]; *p != NUL; ) {
+ for (p = items[1]; *p != NUL;) {
c = mb_ptr2char_adv((const char_u **)&p);
if ((!GA_EMPTY(&spin->si_map)
&& vim_strchr(spin->si_map.ga_data, c)
@@ -2804,7 +2804,7 @@ static void aff_process_flags(afffile_T *affile, affentry_T *entry)
if (entry->ae_flags != NULL
&& (affile->af_compforbid != 0 || affile->af_comppermit != 0)) {
- for (p = entry->ae_flags; *p != NUL; ) {
+ for (p = entry->ae_flags; *p != NUL;) {
prevp = p;
flag = get_affitem(affile->af_flagtype, &p);
if (flag == affile->af_comppermit || flag == affile->af_compforbid) {
@@ -2922,7 +2922,7 @@ static void process_compflags(spellinfo_T *spin, afffile_T *aff, char_u *compfla
spin->si_compflags = p;
tp = p + STRLEN(p);
- for (p = compflags; *p != NUL; ) {
+ for (p = compflags; *p != NUL;) {
if (vim_strchr((char_u *)"/?*+[]", *p) != NULL) {
// Copy non-flag characters directly.
*tp++ = *p++;
@@ -2985,7 +2985,7 @@ static bool flag_in_afflist(int flagtype, char_u *afflist, unsigned flag)
case AFT_CAPLONG:
case AFT_LONG:
- for (p = afflist; *p != NUL; ) {
+ for (p = afflist; *p != NUL;) {
n = mb_ptr2char_adv((const char_u **)&p);
if ((flagtype == AFT_LONG || (n >= 'A' && n <= 'Z'))
&& *p != NUL) {
@@ -2998,7 +2998,7 @@ static bool flag_in_afflist(int flagtype, char_u *afflist, unsigned flag)
break;
case AFT_NUM:
- for (p = afflist; *p != NUL; ) {
+ for (p = afflist; *p != NUL;) {
int digits = getdigits_int(&p, true, 0);
assert(digits >= 0);
n = (unsigned int)digits;
@@ -3248,9 +3248,9 @@ static int spell_read_dic(spellinfo_T *spin, char_u *fname, afffile_T *affile)
// Extract flags from the affix list.
flags |= get_affix_flags(affile, afflist);
- if (affile->af_needaffix != 0 &&
- flag_in_afflist(affile->af_flagtype, afflist,
- affile->af_needaffix)) {
+ if (affile->af_needaffix != 0
+ && flag_in_afflist(affile->af_flagtype, afflist,
+ affile->af_needaffix)) {
need_affix = true;
}
@@ -3311,32 +3311,32 @@ static int get_affix_flags(afffile_T *affile, char_u *afflist)
{
int flags = 0;
- if (affile->af_keepcase != 0 &&
- flag_in_afflist(affile->af_flagtype, afflist,
- affile->af_keepcase)) {
+ if (affile->af_keepcase != 0
+ && flag_in_afflist(affile->af_flagtype, afflist,
+ affile->af_keepcase)) {
flags |= WF_KEEPCAP | WF_FIXCAP;
}
- if (affile->af_rare != 0 &&
- flag_in_afflist(affile->af_flagtype, afflist, affile->af_rare)) {
+ if (affile->af_rare != 0
+ && flag_in_afflist(affile->af_flagtype, afflist, affile->af_rare)) {
flags |= WF_RARE;
}
- if (affile->af_bad != 0 &&
- flag_in_afflist(affile->af_flagtype, afflist, affile->af_bad)) {
+ if (affile->af_bad != 0
+ && flag_in_afflist(affile->af_flagtype, afflist, affile->af_bad)) {
flags |= WF_BANNED;
}
- if (affile->af_needcomp != 0 &&
- flag_in_afflist(affile->af_flagtype, afflist,
- affile->af_needcomp)) {
+ if (affile->af_needcomp != 0
+ && flag_in_afflist(affile->af_flagtype, afflist,
+ affile->af_needcomp)) {
flags |= WF_NEEDCOMP;
}
- if (affile->af_comproot != 0 &&
- flag_in_afflist(affile->af_flagtype, afflist,
- affile->af_comproot)) {
+ if (affile->af_comproot != 0
+ && flag_in_afflist(affile->af_flagtype, afflist,
+ affile->af_comproot)) {
flags |= WF_COMPROOT;
}
- if (affile->af_nosuggest != 0 &&
- flag_in_afflist(affile->af_flagtype, afflist,
- affile->af_nosuggest)) {
+ if (affile->af_nosuggest != 0
+ && flag_in_afflist(affile->af_flagtype, afflist,
+ affile->af_nosuggest)) {
flags |= WF_NOSUGGEST;
}
return flags;
@@ -3355,7 +3355,7 @@ static int get_pfxlist(afffile_T *affile, char_u *afflist, char_u *store_afflist
char_u key[AH_KEY_LEN];
hashitem_T *hi;
- for (p = afflist; *p != NUL; ) {
+ for (p = afflist; *p != NUL;) {
prevp = p;
if (get_affitem(affile->af_flagtype, &p) != 0) {
// A flag is a postponed prefix flag if it appears in "af_pref"
@@ -3389,7 +3389,7 @@ static void get_compflags(afffile_T *affile, char_u *afflist, char_u *store_affl
char_u key[AH_KEY_LEN];
hashitem_T *hi;
- for (p = afflist; *p != NUL; ) {
+ for (p = afflist; *p != NUL;) {
prevp = p;
if (get_affitem(affile->af_flagtype, &p) != 0) {
// A flag is a compound flag if it appears in "af_comp".
@@ -5845,7 +5845,7 @@ static void set_map_str(slang_T *lp, char_u *map)
// The similar characters are stored separated with slashes:
// "aaa/bbb/ccc/". Fill sl_map_array[c] with the character before c and
// before the same slash. For characters above 255 sl_map_hash is used.
- for (p = map; *p != NUL; ) {
+ for (p = map; *p != NUL;) {
c = mb_cptr2char_adv((const char_u **)&p);
if (c == '/') {
headc = 0;
diff --git a/src/nvim/strings.c b/src/nvim/strings.c
index 47cbf01996..c58e052ae9 100644
--- a/src/nvim/strings.c
+++ b/src/nvim/strings.c
@@ -242,7 +242,7 @@ char_u *vim_strsave_shellescape(const char_u *string, bool do_special, bool do_n
#endif
*d++ = '\'';
- for (const char_u *p = string; *p != NUL; ) {
+ for (const char_u *p = string; *p != NUL;) {
#ifdef WIN32
if (!p_ssl) {
if (*p == '"') {
@@ -405,7 +405,7 @@ int vim_stricmp(const char *s1, const char *s2)
{
int i;
- for (;; ) {
+ for (;;) {
i = (int)TOLOWER_LOC(*s1) - (int)TOLOWER_LOC(*s2);
if (i != 0) {
return i; // this character different
diff --git a/src/nvim/syntax.c b/src/nvim/syntax.c
index 8347f1bff1..49f8bbab37 100644
--- a/src/nvim/syntax.c
+++ b/src/nvim/syntax.c
@@ -691,7 +691,7 @@ static void syn_sync(win_T *wp, linenr_T start_lnum, synstate_T *last_valid)
* Restrict the search for the end of a comment to b_syn_sync_maxlines.
*/
if (find_start_comment((int)syn_block->b_syn_sync_maxlines) != NULL) {
- for (idx = syn_block->b_syn_patterns.ga_len; --idx >= 0; ) {
+ for (idx = syn_block->b_syn_patterns.ga_len; --idx >= 0;) {
if (SYN_ITEMS(syn_block)[idx].sp_syn.id
== syn_block->b_syn_sync_id
&& SYN_ITEMS(syn_block)[idx].sp_type == SPTYPE_START) {
@@ -752,7 +752,7 @@ static void syn_sync(win_T *wp, linenr_T start_lnum, synstate_T *last_valid)
for (current_lnum = lnum; current_lnum < end_lnum; ++current_lnum) {
syn_start_line();
- for (;; ) {
+ for (;;) {
had_sync_point = syn_finish_line(true);
// When a sync point has been found, remember where, and
// continue to look for another one, further on in the line.
@@ -1146,7 +1146,7 @@ static void syn_stack_apply_changes_block(synblock_T *block, buf_T *buf)
linenr_T n;
prev = NULL;
- for (p = block->b_sst_first; p != NULL; ) {
+ for (p = block->b_sst_first; p != NULL;) {
if (p->sst_lnum + block->b_syn_sync_linebreaks > buf->b_mod_top) {
n = p->sst_lnum + buf->b_mod_xlines;
if (n <= buf->b_mod_bot) {
@@ -1449,7 +1449,7 @@ static bool syn_stack_equal(synstate_T *sp)
}
int i;
- for (i = current_state.ga_len; --i >= 0; ) {
+ for (i = current_state.ga_len; --i >= 0;) {
// If the item has another index the state is different.
if (bp[i].bs_idx != CUR_STATE(i).si_idx) {
break;
@@ -1788,9 +1788,9 @@ static int syn_current_attr(const bool syncing, const bool displaying, bool *con
line = syn_getcurline();
const char_u *cur_pos = line + current_col;
if (vim_iswordp_buf(cur_pos, syn_buf)
- && (current_col == 0 ||
- !vim_iswordp_buf(cur_pos - 1 - utf_head_off(line, cur_pos - 1),
- syn_buf))) {
+ && (current_col == 0
+ || !vim_iswordp_buf(cur_pos - 1 - utf_head_off(line, cur_pos - 1),
+ syn_buf))) {
syn_id = check_keyword_id(line, (int)current_col, &endcol, &flags,
&next_list, cur_si, &cchar);
if (syn_id != 0) {
@@ -1852,7 +1852,7 @@ static int syn_current_attr(const bool syncing, const bool displaying, bool *con
*/
next_match_idx = 0; // no match in this line yet
next_match_col = MAXCOL;
- for (int idx = syn_block->b_syn_patterns.ga_len; --idx >= 0; ) {
+ for (int idx = syn_block->b_syn_patterns.ga_len; --idx >= 0;) {
synpat_T *const spp = &(SYN_ITEMS(syn_block)[idx]);
if (spp->sp_syncing == syncing
&& (displaying || !(spp->sp_flags & HL_DISPLAY))
@@ -2207,7 +2207,7 @@ static int syn_current_attr(const bool syncing, const bool displaying, bool *con
/// @return true if we already matched pattern "idx" at the current column.
static bool did_match_already(int idx, garray_T *gap)
{
- for (int i = current_state.ga_len; --i >= 0; ) {
+ for (int i = current_state.ga_len; --i >= 0;) {
if (CUR_STATE(i).si_m_startcol == (int)current_col
&& CUR_STATE(i).si_m_lnum == (int)current_lnum
&& CUR_STATE(i).si_idx == idx) {
@@ -2217,7 +2217,7 @@ static bool did_match_already(int idx, garray_T *gap)
// Zero-width matches with a nextgroup argument are not put on the syntax
// stack, and can only be matched once anyway.
- for (int i = gap->ga_len; --i >= 0; ) {
+ for (int i = gap->ga_len; --i >= 0;) {
if (((int *)(gap->ga_data))[i] == idx) {
return true;
}
@@ -2318,7 +2318,7 @@ static void check_state_ends(void)
int had_extend;
cur_si = &CUR_STATE(current_state.ga_len - 1);
- for (;; ) {
+ for (;;) {
if (cur_si->si_ends
&& (cur_si->si_m_endpos.lnum < current_lnum
|| (cur_si->si_m_endpos.lnum == current_lnum
@@ -2658,7 +2658,7 @@ static void find_endpos(int idx, lpos_T *startpos, lpos_T *m_endpos, lpos_T *hl_
/*
* Find the SKIP or first END pattern after the last START pattern.
*/
- for (;; ) {
+ for (;;) {
spp = &(SYN_ITEMS(syn_block)[idx]);
if (spp->sp_type != SPTYPE_START) {
break;
@@ -2687,7 +2687,7 @@ static void find_endpos(int idx, lpos_T *startpos, lpos_T *m_endpos, lpos_T *hl_
// use syntax iskeyword option
save_chartab(buf_chartab);
- for (;; ) {
+ for (;;) {
/*
* Find end pattern that matches first after "matchcol".
*/
@@ -3286,13 +3286,13 @@ void syntax_clear(synblock_T *block)
clear_keywtab(&block->b_keywtab_ic);
// free the syntax patterns
- for (int i = block->b_syn_patterns.ga_len; --i >= 0; ) {
+ for (int i = block->b_syn_patterns.ga_len; --i >= 0;) {
syn_clear_pattern(block, i);
}
ga_clear(&block->b_syn_patterns);
// free the syntax clusters
- for (int i = block->b_syn_clusters.ga_len; --i >= 0; ) {
+ for (int i = block->b_syn_clusters.ga_len; --i >= 0;) {
syn_clear_cluster(block, i);
}
ga_clear(&block->b_syn_clusters);
@@ -3336,7 +3336,7 @@ void reset_synblock(win_T *wp)
static void syntax_sync_clear(void)
{
// free the syntax patterns
- for (int i = curwin->w_s->b_syn_patterns.ga_len; --i >= 0; ) {
+ for (int i = curwin->w_s->b_syn_patterns.ga_len; --i >= 0;) {
if (SYN_ITEMS(curwin->w_s)[i].sp_syncing) {
syn_remove_pattern(curwin->w_s, i);
}
@@ -3484,7 +3484,7 @@ static void syn_clear_one(const int id, const bool syncing)
}
// clear the patterns for "id"
- for (int idx = curwin->w_s->b_syn_patterns.ga_len; --idx >= 0; ) {
+ for (int idx = curwin->w_s->b_syn_patterns.ga_len; --idx >= 0;) {
spp = &(SYN_ITEMS(curwin->w_s)[idx]);
if (spp->sp_syn.id != id || spp->sp_syncing != syncing) {
continue;
@@ -3874,7 +3874,7 @@ static void put_pattern(const char *const s, const int c, const synpat_T *const
msg_putchar(c);
// output the pattern, in between a char that is not in the pattern
- for (i = 0; vim_strchr(spp->sp_pattern, sepchars[i]) != NULL; ) {
+ for (i = 0; vim_strchr(spp->sp_pattern, sepchars[i]) != NULL;) {
if (sepchars[++i] == NUL) {
i = 0; // no good char found, just use the first one
break;
@@ -4015,7 +4015,7 @@ static void syn_clear_keyword(int id, hashtab_T *ht)
}
--todo;
kp_prev = NULL;
- for (kp = HI2KE(hi); kp != NULL; ) {
+ for (kp = HI2KE(hi); kp != NULL;) {
if (kp->k_syn.id == id) {
kp_next = kp->ke_next;
if (kp_prev == NULL) {
@@ -4191,7 +4191,7 @@ static char_u *get_syn_options(char_u *arg, syn_opt_arg_T *opt, int *conceal_cha
opt->flags |= HL_CONCEAL;
}
- for (;; ) {
+ for (;;) {
/*
* This is used very often when a large number of keywords is defined.
* Need to skip quickly when no option name is found.
@@ -4201,7 +4201,7 @@ static char_u *get_syn_options(char_u *arg, syn_opt_arg_T *opt, int *conceal_cha
break;
}
- for (fidx = ARRAY_SIZE(flagtab); --fidx >= 0; ) {
+ for (fidx = ARRAY_SIZE(flagtab); --fidx >= 0;) {
p = flagtab[fidx].name;
int i;
for (i = 0, len = 0; p[i] != NUL; i += 2, ++len) {
@@ -4273,7 +4273,7 @@ static char_u *get_syn_options(char_u *arg, syn_opt_arg_T *opt, int *conceal_cha
} else {
syn_id = syn_name2id((char *)gname);
int i;
- for (i = curwin->w_s->b_syn_patterns.ga_len; --i >= 0; ) {
+ for (i = curwin->w_s->b_syn_patterns.ga_len; --i >= 0;) {
if (SYN_ITEMS(curwin->w_s)[i].sp_syn.id == syn_id
&& SYN_ITEMS(curwin->w_s)[i].sp_type == SPTYPE_START) {
*opt->sync_idx = i;
@@ -4460,7 +4460,7 @@ static void syn_cmd_keyword(exarg_T *eap, int syncing)
// 2: Add an entry for each keyword.
for (kw = keyword_copy; --cnt >= 0; kw += STRLEN(kw) + 1) {
- for (p = vim_strchr(kw, '[');; ) {
+ for (p = vim_strchr(kw, '[');;) {
if (p != NULL) {
*p = NUL;
}
@@ -4972,7 +4972,7 @@ static int syn_scl_name2id(char_u *name)
// Avoid using stricmp() too much, it's slow on some systems
char_u *name_u = vim_strsave_up(name);
int i;
- for (i = curwin->w_s->b_syn_clusters.ga_len; --i >= 0; ) {
+ for (i = curwin->w_s->b_syn_clusters.ga_len; --i >= 0;) {
if (SYN_CLSTR(curwin->w_s)[i].scl_name_u != NULL
&& STRCMP(name_u, SYN_CLSTR(curwin->w_s)[i].scl_name_u) == 0) {
break;
@@ -5078,7 +5078,7 @@ static void syn_cmd_cluster(exarg_T *eap, int syncing)
}
scl_id -= SYNID_CLUSTER;
- for (;; ) {
+ for (;;) {
if (STRNICMP(rest, "add", 3) == 0
&& (ascii_iswhite(rest[3]) || rest[3] == '=')) {
opt_len = 3;
@@ -5174,7 +5174,7 @@ static char_u *get_syn_pattern(char_u *arg, synpat_T *ci)
*/
++end;
do {
- for (idx = SPO_COUNT; --idx >= 0; ) {
+ for (idx = SPO_COUNT; --idx >= 0;) {
if (STRNCMP(end, spo_name_tab[idx], 3) == 0) {
break;
}
@@ -5401,7 +5401,7 @@ static int get_id_list(char_u **const arg, const int keylen, int16_t **const lis
do {
for (end = p; *end && !ascii_iswhite(*end) && *end != ','; end++) {
}
- char_u *const name = xmalloc((int)(end - p + 3)); // leave room for "^$"
+ char_u *const name = xmalloc(end - p + 3); // leave room for "^$"
STRLCPY(name + 1, p, end - p + 1);
if (STRCMP(name + 1, "ALLBUT") == 0
|| STRCMP(name + 1, "ALL") == 0
@@ -5456,7 +5456,7 @@ static int get_id_list(char_u **const arg, const int keylen, int16_t **const lis
regmatch.rm_ic = TRUE;
id = 0;
- for (int i = highlight_ga.ga_len; --i >= 0; ) {
+ for (int i = highlight_ga.ga_len; --i >= 0;) {
if (vim_regexec(&regmatch, HL_TABLE()[i].sg_name, (colnr_T)0)) {
if (round == 2) {
// Got more items than expected; can happen
@@ -6520,7 +6520,7 @@ const char *const highlight_init_cmdline[] = {
/// Create default links for Nvim* highlight groups used for cmdline coloring
void syn_init_cmdline_highlight(bool reset, bool init)
{
- for (size_t i = 0 ; highlight_init_cmdline[i] != NULL ; i++) {
+ for (size_t i = 0; highlight_init_cmdline[i] != NULL; i++) {
do_highlight(highlight_init_cmdline[i], reset, init);
}
}
@@ -6968,7 +6968,7 @@ void do_highlight(const char *line, const bool forceit, const bool init)
attr = 0;
off = 0;
while (arg[off] != NUL) {
- for (i = ARRAY_SIZE(hl_attr_table); --i >= 0; ) {
+ for (i = ARRAY_SIZE(hl_attr_table); --i >= 0;) {
len = (int)STRLEN(hl_name_table[i]);
if (STRNICMP(arg + off, hl_name_table[i], len) == 0) {
attr |= hl_attr_table[i];
@@ -7040,7 +7040,7 @@ void do_highlight(const char *line, const bool forceit, const bool init)
} else {
// Reduce calls to STRICMP a bit, it can be slow.
off = TOUPPER_ASC(*arg);
- for (i = ARRAY_SIZE(color_names); --i >= 0; ) {
+ for (i = ARRAY_SIZE(color_names); --i >= 0;) {
if (off == color_names[i][0]
&& STRICMP(arg + 1, color_names[i] + 1) == 0) {
break;
@@ -7536,6 +7536,7 @@ static bool syn_list_header(const bool did_header, const int outlen, const int i
{
int endcol = 19;
bool newline = true;
+ int name_col = 0;
bool adjust = true;
if (!did_header) {
@@ -7544,6 +7545,7 @@ static bool syn_list_header(const bool did_header, const int outlen, const int i
return true;
}
msg_outtrans(HL_TABLE()[id - 1].sg_name);
+ name_col = msg_col;
endcol = 15;
} else if ((ui_has(kUIMessages) || msg_silent) && !force_newline) {
msg_putchar(' ');
@@ -7570,6 +7572,9 @@ static bool syn_list_header(const bool did_header, const int outlen, const int i
// Show "xxx" with the attributes.
if (!did_header) {
+ if (endcol == Columns - 1 && endcol <= name_col) {
+ msg_putchar(' ');
+ }
msg_puts_attr("xxx", syn_id2attr(id));
msg_putchar(' ');
}
@@ -7784,7 +7789,7 @@ int syn_get_final_id(int hl_id)
* Follow links until there is no more.
* Look out for loops! Break after 100 links.
*/
- for (count = 100; --count >= 0; ) {
+ for (count = 100; --count >= 0;) {
struct hl_group *sgp = &HL_TABLE()[hl_id - 1]; // index is ID minus one
// ACHTUNG: when using "tmp" attribute (no link) the function might be
@@ -7983,10 +7988,10 @@ static void highlight_list(void)
{
int i;
- for (i = 10; --i >= 0; ) {
+ for (i = 10; --i >= 0;) {
highlight_list_two(i, HL_ATTR(HLF_D));
}
- for (i = 40; --i >= 0; ) {
+ for (i = 40; --i >= 0;) {
highlight_list_two(99, 0);
}
}
diff --git a/src/nvim/tag.c b/src/nvim/tag.c
index 673ebc2668..1f4d3adc92 100644
--- a/src/nvim/tag.c
+++ b/src/nvim/tag.c
@@ -431,7 +431,7 @@ int do_tag(char_u *tag, int type, int count, int forceit, int verbose)
/*
* Repeat searching for tags, when a file has not been found.
*/
- for (;; ) {
+ for (;;) {
int other_name;
char_u *name;
@@ -1638,7 +1638,7 @@ int find_tags(char_u *pat, int *num_matches, char_u ***matchesp, int flags, int
/*
* Read and parse the lines in the file one by one
*/
- for (;; ) {
+ for (;;) {
// check for CTRL-C typed, more often when jumping around
if (state == TS_BINARY || state == TS_SKIP_BACK) {
line_breakcheck();
@@ -2403,7 +2403,7 @@ int get_tagfname(tagname_T *tnp, int first, char_u *buf)
* tnp->tn_did_filefind_init == FALSE: setup for next part in 'tags'.
* tnp->tn_did_filefind_init == TRUE: find next file in this part.
*/
- for (;; ) {
+ for (;;) {
if (tnp->tn_did_filefind_init) {
fname = vim_findfile(tnp->tn_search_ctx);
if (fname != NULL) {
@@ -2687,7 +2687,7 @@ static int jumpto_tag(const char_u *lbuf_arg, int forceit, int keep_help)
// copy the command to pbuf[], remove trailing CR/NL
str = tagp.command;
- for (pbuf_end = pbuf; *str && *str != '\n' && *str != '\r'; ) {
+ for (pbuf_end = pbuf; *str && *str != '\n' && *str != '\r';) {
*pbuf_end++ = *str++;
if (pbuf_end - pbuf + 1 >= LSIZE) {
break;
@@ -3056,7 +3056,7 @@ static int find_extra(char_u **pp)
char_u first_char = **pp;
// Repeat for addresses separated with ';'
- for (;; ) {
+ for (;;) {
if (ascii_isdigit(*str)) {
str = skipdigits(str + 1);
} else if (*str == '/' || *str == '?') {
diff --git a/src/nvim/testdir/test_arglist.vim b/src/nvim/testdir/test_arglist.vim
index 8fd60d6a5a..164149476f 100644
--- a/src/nvim/testdir/test_arglist.vim
+++ b/src/nvim/testdir/test_arglist.vim
@@ -1,5 +1,9 @@
" Test argument list commands
+func Reset_arglist()
+ args a | %argd
+endfunc
+
func Test_argidx()
args a b c
last
@@ -26,6 +30,8 @@ func Test_argidx()
endfunc
func Test_argadd()
+ call Reset_arglist()
+
%argdelete
argadd a b c
call assert_equal(0, argidx())
@@ -115,8 +121,7 @@ endfunc
" Test for [count]argument and [count]argdelete commands
" Ported from the test_argument_count.in test script
func Test_argument()
- " Clean the argument list
- arga a | %argd
+ call Reset_arglist()
let save_hidden = &hidden
set hidden
@@ -244,8 +249,7 @@ endfunc
" Test for 0argadd and 0argedit
" Ported from the test_argument_0count.in test script
func Test_zero_argadd()
- " Clean the argument list
- arga a | %argd
+ call Reset_arglist()
arga a b c d
2argu
@@ -272,10 +276,6 @@ func Test_zero_argadd()
call assert_equal('file with spaces', expand('%'))
endfunc
-func Reset_arglist()
- args a | %argd
-endfunc
-
" Test for argc()
func Test_argc()
call Reset_arglist()
diff --git a/src/nvim/testdir/test_autochdir.vim b/src/nvim/testdir/test_autochdir.vim
index 0b76828dd7..9ad727241e 100644
--- a/src/nvim/testdir/test_autochdir.vim
+++ b/src/nvim/testdir/test_autochdir.vim
@@ -26,4 +26,42 @@ func Test_set_filename()
call delete('samples/Xtest')
endfunc
+func Test_verbose_pwd()
+ CheckFunction test_autochdir
+ let cwd = getcwd()
+ call test_autochdir()
+
+ edit global.txt
+ call assert_match('\[global\].*testdir$', execute('verbose pwd'))
+
+ call mkdir('Xautodir')
+ split Xautodir/local.txt
+ lcd Xautodir
+ call assert_match('\[window\].*testdir[/\\]Xautodir', execute('verbose pwd'))
+
+ set acd
+ wincmd w
+ call assert_match('\[autochdir\].*testdir$', execute('verbose pwd'))
+ execute 'lcd' cwd
+ call assert_match('\[window\].*testdir$', execute('verbose pwd'))
+ execute 'tcd' cwd
+ call assert_match('\[tabpage\].*testdir$', execute('verbose pwd'))
+ execute 'cd' cwd
+ call assert_match('\[global\].*testdir$', execute('verbose pwd'))
+ edit
+ call assert_match('\[autochdir\].*testdir$', execute('verbose pwd'))
+ wincmd w
+ call assert_match('\[autochdir\].*testdir[/\\]Xautodir', execute('verbose pwd'))
+ set noacd
+ call assert_match('\[autochdir\].*testdir[/\\]Xautodir', execute('verbose pwd'))
+ wincmd w
+ call assert_match('\[global\].*testdir', execute('verbose pwd'))
+ wincmd w
+ call assert_match('\[window\].*testdir[/\\]Xautodir', execute('verbose pwd'))
+
+ bwipe!
+ call chdir(cwd)
+ call delete('Xautodir', 'rf')
+endfunc
+
" vim: shiftwidth=2 sts=2 expandtab
diff --git a/src/nvim/testdir/test_autocmd.vim b/src/nvim/testdir/test_autocmd.vim
index 0c8b8a45d9..49d56349a5 100644
--- a/src/nvim/testdir/test_autocmd.vim
+++ b/src/nvim/testdir/test_autocmd.vim
@@ -33,7 +33,7 @@ if has('timers')
let g:triggered = 0
au CursorHoldI * let g:triggered += 1
set updatetime=20
- call timer_start(LoadAdjust(100), 'ExitInsertMode')
+ call timer_start(LoadAdjust(200), 'ExitInsertMode')
call feedkeys('a', 'x!')
call assert_equal(1, g:triggered)
unlet g:triggered
@@ -1897,6 +1897,26 @@ func Test_autocmd_CmdWinEnter()
call delete(filename)
endfunc
+func Test_autocmd_was_using_freed_memory()
+ pedit xx
+ n x
+ augroup winenter
+ au WinEnter * if winnr('$') > 2 | quit | endif
+ augroup END
+ " Nvim needs large 'winwidth' and 'nowinfixwidth' to crash
+ set winwidth=99999 nowinfixwidth
+ split
+
+ augroup winenter
+ au! WinEnter
+ augroup END
+
+ set winwidth& winfixwidth&
+ bwipe xx
+ bwipe x
+ pclose
+endfunc
+
func Test_FileChangedShell_reload()
if !has('unix')
return
@@ -2125,6 +2145,19 @@ func Test_autocmd_closes_window()
au! BufWinLeave
endfunc
+func Test_autocmd_quit_psearch()
+ sn aa bb
+ augroup aucmd_win_test
+ au!
+ au BufEnter,BufLeave,BufNew,WinEnter,WinLeave,WinNew * if winnr('$') > 1 | q | endif
+ augroup END
+ ps /
+
+ augroup aucmd_win_test
+ au!
+ augroup END
+endfunc
+
func Test_autocmd_closing_cmdwin()
au BufWinLeave * nested q
call assert_fails("norm 7q?\n", 'E855:')
diff --git a/src/nvim/testdir/test_blockedit.vim b/src/nvim/testdir/test_blockedit.vim
index 180524cd73..38978ef689 100644
--- a/src/nvim/testdir/test_blockedit.vim
+++ b/src/nvim/testdir/test_blockedit.vim
@@ -15,6 +15,58 @@ func Test_blockinsert_indent()
bwipe!
endfunc
+func Test_blockinsert_autoindent()
+ new
+ let lines =<< trim END
+ var d = {
+ a: () => 0,
+ b: () => 0,
+ c: () => 0,
+ }
+ END
+ call setline(1, lines)
+ filetype plugin indent on
+ setlocal sw=2 et ft=vim
+ setlocal indentkeys+=:
+ exe "norm! 2Gf)\<c-v>2jA: asdf\<esc>"
+ let expected =<< trim END
+ var d = {
+ a: (): asdf => 0,
+ b: (): asdf => 0,
+ c: (): asdf => 0,
+ }
+ END
+ call assert_equal(expected, getline(1, 5))
+
+ " insert on the next column should do exactly the same
+ :%dele
+ call setline(1, lines)
+ exe "norm! 2Gf)l\<c-v>2jI: asdf\<esc>"
+ call assert_equal(expected, getline(1, 5))
+
+ :%dele
+ call setline(1, lines)
+ setlocal sw=8 noet
+ exe "norm! 2Gf)\<c-v>2jA: asdf\<esc>"
+ let expected =<< trim END
+ var d = {
+ a: (): asdf => 0,
+ b: (): asdf => 0,
+ c: (): asdf => 0,
+ }
+ END
+ call assert_equal(expected, getline(1, 5))
+
+ " insert on the next column should do exactly the same
+ :%dele
+ call setline(1, lines)
+ exe "norm! 2Gf)l\<c-v>2jI: asdf\<esc>"
+ call assert_equal(expected, getline(1, 5))
+
+ filetype off
+ bwipe!
+endfunc
+
func Test_blockinsert_delete()
new
let _bs = &bs
diff --git a/src/nvim/testdir/test_bufwintabinfo.vim b/src/nvim/testdir/test_bufwintabinfo.vim
index bb672cf0ec..c04c8fbf60 100644
--- a/src/nvim/testdir/test_bufwintabinfo.vim
+++ b/src/nvim/testdir/test_bufwintabinfo.vim
@@ -1,108 +1,110 @@
" Tests for the getbufinfo(), getwininfo() and gettabinfo() functions
function Test_getbufwintabinfo()
- edit Xtestfile1
- edit Xtestfile2
- let buflist = getbufinfo()
- call assert_equal(2, len(buflist))
- call assert_match('Xtestfile1', buflist[0].name)
- call assert_match('Xtestfile2', getbufinfo('Xtestfile2')[0].name)
- call assert_equal([], getbufinfo(2016))
- edit Xtestfile1
- hide edit Xtestfile2
- hide enew
- call assert_equal(3, len(getbufinfo({'bufloaded':1})))
-
- set tabstop&vim
- let b:editor = 'vim'
+ edit Xtestfile1
+ edit Xtestfile2
+ let buflist = getbufinfo()
+ call assert_equal(2, len(buflist))
+ call assert_match('Xtestfile1', buflist[0].name)
+ call assert_match('Xtestfile2', getbufinfo('Xtestfile2')[0].name)
+ call assert_equal([], getbufinfo(2016))
+ edit Xtestfile1
+ hide edit Xtestfile2
+ hide enew
+ call assert_equal(3, len(getbufinfo({'bufloaded':1})))
+
+ set tabstop&vim
+ let b:editor = 'vim'
+ let l = getbufinfo('%')
+ call assert_equal(bufnr('%'), l[0].bufnr)
+ call assert_equal('vim', l[0].variables.editor)
+ call assert_notequal(-1, index(l[0].windows, '%'->bufwinid()))
+
+ " Test for getbufinfo() with 'bufmodified'
+ call assert_equal(0, len(getbufinfo({'bufmodified' : 1})))
+ call setbufline('Xtestfile1', 1, ["Line1"])
+ let l = getbufinfo({'bufmodified' : 1})
+ call assert_equal(1, len(l))
+ call assert_equal(bufnr('Xtestfile1'), l[0].bufnr)
+
+ if has('signs')
+ call append(0, ['Linux', 'Windows', 'Mac'])
+ sign define Mark text=>> texthl=Search
+ exe "sign place 2 line=3 name=Mark buffer=" . bufnr('%')
let l = getbufinfo('%')
- call assert_equal(bufnr('%'), l[0].bufnr)
- call assert_equal('vim', l[0].variables.editor)
- call assert_notequal(-1, index(l[0].windows, '%'->bufwinid()))
-
- " Test for getbufinfo() with 'bufmodified'
- call assert_equal(0, len(getbufinfo({'bufmodified' : 1})))
- call setbufline('Xtestfile1', 1, ["Line1"])
- let l = getbufinfo({'bufmodified' : 1})
- call assert_equal(1, len(l))
- call assert_equal(bufnr('Xtestfile1'), l[0].bufnr)
-
- if has('signs')
- call append(0, ['Linux', 'Windows', 'Mac'])
- sign define Mark text=>> texthl=Search
- exe "sign place 2 line=3 name=Mark buffer=" . bufnr('%')
- let l = getbufinfo('%')
- call assert_equal(2, l[0].signs[0].id)
- call assert_equal(3, l[0].signs[0].lnum)
- call assert_equal('Mark', l[0].signs[0].name)
- sign unplace *
- sign undefine Mark
- enew!
- endif
-
- only
- let w1_id = win_getid()
- new
- let w2_id = win_getid()
- tabnew | let w3_id = win_getid()
- new | let w4_id = win_getid()
- vert new | let w5_id = win_getid()
- call setwinvar(0, 'signal', 'green')
- tabfirst
- let winlist = getwininfo()
- call assert_equal(5, len(winlist))
- call assert_equal(winwidth(1), winlist[0].width)
- call assert_equal(1, winlist[0].wincol)
- " tabline adds one row in terminal, not in GUI
- let tablineheight = winlist[0].winrow == 2 ? 1 : 0
- call assert_equal(tablineheight + 1, winlist[0].winrow)
-
- call assert_equal(winbufnr(2), winlist[1].bufnr)
- call assert_equal(winheight(2), winlist[1].height)
- call assert_equal(1, winlist[1].wincol)
- call assert_equal(tablineheight + winheight(1) + 2, winlist[1].winrow)
-
- call assert_equal(1, winlist[2].winnr)
- call assert_equal(tablineheight + 1, winlist[2].winrow)
- call assert_equal(1, winlist[2].wincol)
-
- call assert_equal(winlist[2].width + 2, winlist[3].wincol)
- call assert_equal(1, winlist[4].wincol)
-
- call assert_equal(1, winlist[0].tabnr)
- call assert_equal(1, winlist[1].tabnr)
- call assert_equal(2, winlist[2].tabnr)
- call assert_equal(2, winlist[3].tabnr)
- call assert_equal(2, winlist[4].tabnr)
-
- call assert_equal('green', winlist[2].variables.signal)
- call assert_equal(w4_id, winlist[3].winid)
- let winfo = w5_id->getwininfo()[0]
- call assert_equal(2, winfo.tabnr)
- call assert_equal([], getwininfo(3))
-
- call settabvar(1, 'space', 'build')
- let tablist = gettabinfo()
- call assert_equal(2, len(tablist))
- call assert_equal(3, len(tablist[1].windows))
- call assert_equal(2, tablist[1].tabnr)
- call assert_equal('build', tablist[0].variables.space)
- call assert_equal(w2_id, tablist[0].windows[0])
- call assert_equal([], 3->gettabinfo())
-
- tabonly | only
-
- lexpr ''
- lopen
- copen
- let winlist = getwininfo()
- call assert_false(winlist[0].quickfix)
- call assert_false(winlist[0].loclist)
- call assert_true(winlist[1].quickfix)
- call assert_true(winlist[1].loclist)
- call assert_true(winlist[2].quickfix)
- call assert_false(winlist[2].loclist)
- wincmd t | only
+ call assert_equal(2, l[0].signs[0].id)
+ call assert_equal(3, l[0].signs[0].lnum)
+ call assert_equal('Mark', l[0].signs[0].name)
+ sign unplace *
+ sign undefine Mark
+ enew!
+ endif
+
+ only
+ let w1_id = win_getid()
+ setl foldcolumn=3
+ new
+ let w2_id = win_getid()
+ tabnew | let w3_id = win_getid()
+ new | let w4_id = win_getid()
+ vert new | let w5_id = win_getid()
+ call setwinvar(0, 'signal', 'green')
+ tabfirst
+ let winlist = getwininfo()
+ call assert_equal(5, len(winlist))
+ call assert_equal(winwidth(1), winlist[0].width)
+ call assert_equal(1, winlist[0].wincol)
+ " tabline adds one row in terminal, not in GUI
+ let tablineheight = winlist[0].winrow == 2 ? 1 : 0
+ call assert_equal(tablineheight + 1, winlist[0].winrow)
+
+ call assert_equal(winbufnr(2), winlist[1].bufnr)
+ call assert_equal(winheight(2), winlist[1].height)
+ call assert_equal(1, winlist[1].wincol)
+ call assert_equal(3, winlist[1].textoff) " foldcolumn
+ call assert_equal(tablineheight + winheight(1) + 2, winlist[1].winrow)
+
+ call assert_equal(1, winlist[2].winnr)
+ call assert_equal(tablineheight + 1, winlist[2].winrow)
+ call assert_equal(1, winlist[2].wincol)
+
+ call assert_equal(winlist[2].width + 2, winlist[3].wincol)
+ call assert_equal(1, winlist[4].wincol)
+
+ call assert_equal(1, winlist[0].tabnr)
+ call assert_equal(1, winlist[1].tabnr)
+ call assert_equal(2, winlist[2].tabnr)
+ call assert_equal(2, winlist[3].tabnr)
+ call assert_equal(2, winlist[4].tabnr)
+
+ call assert_equal('green', winlist[2].variables.signal)
+ call assert_equal(w4_id, winlist[3].winid)
+ let winfo = w5_id->getwininfo()[0]
+ call assert_equal(2, winfo.tabnr)
+ call assert_equal([], getwininfo(3))
+
+ call settabvar(1, 'space', 'build')
+ let tablist = gettabinfo()
+ call assert_equal(2, len(tablist))
+ call assert_equal(3, len(tablist[1].windows))
+ call assert_equal(2, tablist[1].tabnr)
+ call assert_equal('build', tablist[0].variables.space)
+ call assert_equal(w2_id, tablist[0].windows[0])
+ call assert_equal([], 3->gettabinfo())
+
+ tabonly | only
+
+ lexpr ''
+ lopen
+ copen
+ let winlist = getwininfo()
+ call assert_false(winlist[0].quickfix)
+ call assert_false(winlist[0].loclist)
+ call assert_true(winlist[1].quickfix)
+ call assert_true(winlist[1].loclist)
+ call assert_true(winlist[2].quickfix)
+ call assert_false(winlist[2].loclist)
+ wincmd t | only
endfunction
function Test_get_buf_options()
diff --git a/src/nvim/testdir/test_cd.vim b/src/nvim/testdir/test_cd.vim
index 0bba321ee2..57db0a2544 100644
--- a/src/nvim/testdir/test_cd.vim
+++ b/src/nvim/testdir/test_cd.vim
@@ -215,3 +215,42 @@ func Test_cd_from_non_existing_dir()
cd -
call assert_equal(saveddir, getcwd())
endfunc
+
+func Test_cd_unknown_dir()
+ call mkdir('Xa')
+ cd Xa
+ call writefile(['text'], 'Xb.txt')
+ edit Xa/Xb.txt
+ let first_buf = bufnr()
+ cd ..
+ edit
+ call assert_equal(first_buf, bufnr())
+ edit Xa/Xb.txt
+ call assert_notequal(first_buf, bufnr())
+
+ bwipe!
+ exe "bwipe! " .. first_buf
+ call delete('Xa', 'rf')
+endfunc
+
+func Test_getcwd_actual_dir()
+ CheckFunction test_autochdir
+ let startdir = getcwd()
+ call mkdir('Xactual')
+ call test_autochdir()
+ set autochdir
+ edit Xactual/file.txt
+ call assert_match('testdir.Xactual$', getcwd())
+ lcd ..
+ call assert_match('testdir$', getcwd())
+ edit
+ call assert_match('testdir.Xactual$', getcwd())
+ call assert_match('testdir$', getcwd(win_getid()))
+
+ set noautochdir
+ bwipe!
+ call chdir(startdir)
+ call delete('Xactual', 'rf')
+endfunc
+
+" vim: shiftwidth=2 sts=2 expandtab
diff --git a/src/nvim/testdir/test_cmdline.vim b/src/nvim/testdir/test_cmdline.vim
index 98340d0ac6..75e17b47b8 100644
--- a/src/nvim/testdir/test_cmdline.vim
+++ b/src/nvim/testdir/test_cmdline.vim
@@ -428,14 +428,17 @@ func Test_getcompletion()
call assert_equal([], l)
func T(a, c, p)
+ let g:cmdline_compl_params = [a:a, a:c, a:p]
return "oneA\noneB\noneC"
endfunc
command -nargs=1 -complete=custom,T MyCmd
let l = getcompletion('MyCmd ', 'cmdline')
call assert_equal(['oneA', 'oneB', 'oneC'], l)
+ call assert_equal(['', 'MyCmd ', 6], g:cmdline_compl_params)
delcommand MyCmd
delfunc T
+ unlet g:cmdline_compl_params
" For others test if the name is recognized.
let names = ['buffer', 'environment', 'file_in_path', 'mapping', 'tag', 'tag_listfiles', 'user']
diff --git a/src/nvim/testdir/test_filetype.vim b/src/nvim/testdir/test_filetype.vim
index 9651b8dce0..48b434b9fd 100644
--- a/src/nvim/testdir/test_filetype.vim
+++ b/src/nvim/testdir/test_filetype.vim
@@ -59,7 +59,7 @@ let s:filename_checks = {
\ 'aml': ['file.aml'],
\ 'ampl': ['file.run'],
\ 'ant': ['build.xml'],
- \ 'apache': ['.htaccess', '/etc/httpd/file.conf', '/etc/apache2/sites-2/file.com', '/etc/apache2/some.config', '/etc/apache2/conf.file/conf', '/etc/apache2/mods-some/file', '/etc/apache2/sites-some/file', '/etc/httpd/conf.d/file.config', '/etc/apache2/conf.file/file', '/etc/apache2/file.conf', '/etc/apache2/file.conf-file', '/etc/apache2/mods-file/file', '/etc/apache2/sites-file/file', '/etc/apache2/sites-file/file.com', '/etc/httpd/conf.d/file.conf', '/etc/httpd/conf.d/file.conf-file', 'access.conf', 'access.conf-file', 'any/etc/apache2/conf.file/file', 'any/etc/apache2/file.conf', 'any/etc/apache2/file.conf-file', 'any/etc/apache2/mods-file/file', 'any/etc/apache2/sites-file/file', 'any/etc/apache2/sites-file/file.com', 'any/etc/httpd/conf.d/file.conf', 'any/etc/httpd/conf.d/file.conf-file', 'any/etc/httpd/file.conf', 'apache.conf', 'apache.conf-file', 'apache2.conf', 'apache2.conf-file', 'httpd.conf', 'httpd.conf-file', 'srm.conf', 'srm.conf-file'],
+ \ 'apache': ['.htaccess', '/etc/httpd/file.conf', '/etc/apache2/sites-2/file.com', '/etc/apache2/some.config', '/etc/apache2/conf.file/conf', '/etc/apache2/mods-some/file', '/etc/apache2/sites-some/file', '/etc/httpd/conf.d/file.config', '/etc/apache2/conf.file/file', '/etc/apache2/file.conf', '/etc/apache2/file.conf-file', '/etc/apache2/mods-file/file', '/etc/apache2/sites-file/file', '/etc/apache2/sites-file/file.com', '/etc/httpd/conf.d/file.conf', '/etc/httpd/conf.d/file.conf-file', 'access.conf', 'access.conf-file', 'any/etc/apache2/conf.file/file', 'any/etc/apache2/file.conf', 'any/etc/apache2/file.conf-file', 'any/etc/apache2/mods-file/file', 'any/etc/apache2/sites-file/file', 'any/etc/apache2/sites-file/file.com', 'any/etc/httpd/conf.d/file.conf', 'any/etc/httpd/conf.d/file.conf-file', 'any/etc/httpd/file.conf', 'apache.conf', 'apache.conf-file', 'apache2.conf', 'apache2.conf-file', 'httpd.conf', 'httpd.conf-file', 'srm.conf', 'srm.conf-file', '/etc/httpd/mods-some/file', '/etc/httpd/sites-some/file', '/etc/httpd/conf.file/conf'],
\ 'apachestyle': ['/etc/proftpd/file.config,/etc/proftpd/conf.file/file', '/etc/proftpd/conf.file/file', '/etc/proftpd/file.conf', '/etc/proftpd/file.conf-file', 'any/etc/proftpd/conf.file/file', 'any/etc/proftpd/file.conf', 'any/etc/proftpd/file.conf-file', 'proftpd.conf', 'proftpd.conf-file'],
\ 'applescript': ['file.scpt'],
\ 'aptconf': ['apt.conf', '/.aptitude/config', 'any/.aptitude/config'],
@@ -142,7 +142,7 @@ let s:filename_checks = {
\ 'desc': ['file.desc'],
\ 'desktop': ['file.desktop', '.directory', 'file.directory'],
\ 'dictconf': ['dict.conf', '.dictrc'],
- \ 'dictdconf': ['dictd.conf'],
+ \ 'dictdconf': ['dictd.conf', 'dictdfile.conf', 'dictd-file.conf'],
\ 'diff': ['file.diff', 'file.rej'],
\ 'dircolors': ['.dir_colors', '.dircolors', '/etc/DIR_COLORS', 'any/etc/DIR_COLORS'],
\ 'dnsmasq': ['/etc/dnsmasq.conf', '/etc/dnsmasq.d/file', 'any/etc/dnsmasq.conf', 'any/etc/dnsmasq.d/file'],
@@ -182,11 +182,12 @@ let s:filename_checks = {
\ 'fgl': ['file.4gl', 'file.4gh', 'file.m4gl'],
\ 'fish': ['file.fish'],
\ 'focexec': ['file.fex', 'file.focexec'],
- \ 'forth': ['file.fs', 'file.ft', 'file.fth'],
+ \ 'forth': ['file.ft', 'file.fth'],
\ 'fortran': ['file.f', 'file.for', 'file.fortran', 'file.fpp', 'file.ftn', 'file.f77', 'file.f90', 'file.f95', 'file.f03', 'file.f08'],
\ 'fpcmake': ['file.fpc'],
\ 'framescript': ['file.fsl'],
\ 'freebasic': ['file.fb', 'file.bi'],
+ \ 'fsharp': ['file.fs', 'file.fsi', 'file.fsx'],
\ 'fstab': ['fstab', 'mtab'],
\ 'fvwm': ['/.fvwm/file', 'any/.fvwm/file'],
\ 'gdb': ['.gdbinit', 'gdbinit'],
@@ -553,7 +554,7 @@ let s:filename_checks = {
\ 'xhtml': ['file.xhtml', 'file.xht'],
\ 'xinetd': ['/etc/xinetd.conf', '/etc/xinetd.d/file', 'any/etc/xinetd.conf', 'any/etc/xinetd.d/file'],
\ 'xmath': ['file.msc', 'file.msf'],
- \ 'xml': ['/etc/blkid.tab', '/etc/blkid.tab.old', 'file.xmi', 'file.csproj', 'file.csproj.user', 'file.ui', 'file.tpm', '/etc/xdg/menus/file.menu', 'fglrxrc', 'file.xlf', 'file.xliff', 'file.xul', 'file.wsdl', 'file.wpl', 'any/etc/blkid.tab', 'any/etc/blkid.tab.old', 'any/etc/xdg/menus/file.menu'],
+ \ 'xml': ['/etc/blkid.tab', '/etc/blkid.tab.old', 'file.xmi', 'file.csproj', 'file.csproj.user', 'file.fsproj', 'file.fsproj.user', 'file.vbproj', 'file.vbproj.user', 'file.ui', 'file.tpm', '/etc/xdg/menus/file.menu', 'fglrxrc', 'file.xlf', 'file.xliff', 'file.xul', 'file.wsdl', 'file.wpl', 'any/etc/blkid.tab', 'any/etc/blkid.tab.old', 'any/etc/xdg/menus/file.menu', 'file.atom', 'file.rss', 'file.cdxml', 'file.psc1', 'file.mpd'],
\ 'xmodmap': ['anyXmodmap', 'Xmodmap', 'some-Xmodmap', 'some-xmodmap', 'some-xmodmap-file', 'xmodmap', 'xmodmap-file'],
\ 'xf86conf': ['xorg.conf', 'xorg.conf-4'],
\ 'xpm': ['file.xpm'],
@@ -663,6 +664,7 @@ let s:script_checks = {
\ 'fennel': [['#!/path/fennel']],
\ 'routeros': [['#!/path/rsc']],
\ 'fish': [['#!/path/fish']],
+ \ 'forth': [['#!/path/gforth']],
\ }
" Various forms of "env" optional arguments.
@@ -866,6 +868,16 @@ func Test_m_file()
call assert_equal('objc', &filetype)
bwipe!
+ call writefile(['#include <header.h>'], 'Xfile.m')
+ split Xfile.m
+ call assert_equal('objc', &filetype)
+ bwipe!
+
+ call writefile(['#define FORTY_TWO'], 'Xfile.m')
+ split Xfile.m
+ call assert_equal('objc', &filetype)
+ bwipe!
+
" Octave
call writefile(['# Octave line comment'], 'Xfile.m')
@@ -935,4 +947,57 @@ func Test_xpm_file()
filetype off
endfunc
+func Test_fs_file()
+ filetype on
+
+ call writefile(['looks like F#'], 'Xfile.fs')
+ split Xfile.fs
+ call assert_equal('fsharp', &filetype)
+ bwipe!
+
+ let g:filetype_fs = 'forth'
+ split Xfile.fs
+ call assert_equal('forth', &filetype)
+ bwipe!
+ unlet g:filetype_fs
+
+ " Test dist#ft#FTfs()
+
+ " Forth (Gforth)
+
+ call writefile(['( Forth inline comment )'], 'Xfile.fs')
+ split Xfile.fs
+ call assert_equal('forth', &filetype)
+ bwipe!
+
+ call writefile(['.( Forth displayed inline comment )'], 'Xfile.fs')
+ split Xfile.fs
+ call assert_equal('forth', &filetype)
+ bwipe!
+
+ call writefile(['\ Forth line comment'], 'Xfile.fs')
+ split Xfile.fs
+ call assert_equal('forth', &filetype)
+ bwipe!
+
+ " empty line comment - no space required
+ call writefile(['\'], 'Xfile.fs')
+ split Xfile.fs
+ call assert_equal('forth', &filetype)
+ bwipe!
+
+ call writefile(['\G Forth documentation comment '], 'Xfile.fs')
+ split Xfile.fs
+ call assert_equal('forth', &filetype)
+ bwipe!
+
+ call writefile([': squared ( n -- n^2 )', 'dup * ;'], 'Xfile.fs')
+ split Xfile.fs
+ call assert_equal('forth', &filetype)
+ bwipe!
+
+ call delete('Xfile.fs')
+ filetype off
+endfunc
+
" vim: shiftwidth=2 sts=2 expandtab
diff --git a/src/nvim/testdir/test_functions.vim b/src/nvim/testdir/test_functions.vim
index d10fad690c..4a2ade5afa 100644
--- a/src/nvim/testdir/test_functions.vim
+++ b/src/nvim/testdir/test_functions.vim
@@ -1592,6 +1592,10 @@ func Test_bufadd_bufload()
endfunc
func Test_readdir()
+ if isdirectory('Xdir')
+ call delete('Xdir', 'rf')
+ endif
+
call mkdir('Xdir')
call writefile([], 'Xdir/foo.txt')
call writefile([], 'Xdir/bar.txt')
diff --git a/src/nvim/testdir/test_highlight.vim b/src/nvim/testdir/test_highlight.vim
index 6fd9477ce9..c38bfa5677 100644
--- a/src/nvim/testdir/test_highlight.vim
+++ b/src/nvim/testdir/test_highlight.vim
@@ -651,6 +651,16 @@ func Test_1_highlight_Normalgroup_exists()
endif
endfunc
+function Test_no_space_before_xxx()
+ " Note: we need to create this highlight group in the test because it does not exist in Neovim
+ execute('hi StatusLineTermNC ctermfg=green')
+ let l:org_columns = &columns
+ set columns=17
+ let l:hi_StatusLineTermNC = join(split(execute('hi StatusLineTermNC')))
+ call assert_match('StatusLineTermNC xxx', l:hi_StatusLineTermNC)
+ let &columns = l:org_columns
+endfunction
+
" Test for using RGB color values in a highlight group
func Test_xxlast_highlight_RGB_color()
CheckCanRunGui
diff --git a/src/nvim/testdir/test_listchars.vim b/src/nvim/testdir/test_listchars.vim
index 751be8eff5..9906b00222 100644
--- a/src/nvim/testdir/test_listchars.vim
+++ b/src/nvim/testdir/test_listchars.vim
@@ -112,7 +112,7 @@ func Test_listchars()
" Test lead and trail
normal ggdG
- set listchars=eol:$
+ set listchars=eol:$ " Accommodate Nvim default
set listchars+=lead:>,trail:<,space:x
set list
@@ -142,7 +142,7 @@ func Test_listchars()
" Test multispace
normal ggdG
- set listchars=eol:$
+ set listchars=eol:$ " Accommodate Nvim default
set listchars+=multispace:yYzZ
set list
@@ -305,7 +305,7 @@ func Test_listchars_invalid()
enew!
set ff=unix
- set listchars=eol:$
+ set listchars=eol:$ " Accommodate Nvim default
set list
set ambiwidth=double
@@ -369,3 +369,138 @@ func Test_listchars_composing()
enew!
set listchars& ff&
endfunction
+
+" Check for the value of the 'listchars' option
+func s:CheckListCharsValue(expected)
+ call assert_equal(a:expected, &listchars)
+ call assert_equal(a:expected, getwinvar(0, '&listchars'))
+endfunc
+
+" Test for using a window local value for 'listchars'
+func Test_listchars_window_local()
+ %bw!
+ set list listchars&
+ let l:default_listchars = &listchars " Accommodate Nvim default
+ new
+ " set a local value for 'listchars'
+ setlocal listchars=tab:+-,eol:#
+ call s:CheckListCharsValue('tab:+-,eol:#')
+ " When local value is reset, global value should be used
+ setlocal listchars=
+ call s:CheckListCharsValue(l:default_listchars) " Accommodate Nvim default
+ " Use 'setlocal <' to copy global value
+ setlocal listchars=space:.,extends:>
+ setlocal listchars<
+ call s:CheckListCharsValue(l:default_listchars) " Accommodate Nvim default
+ " Use 'set <' to copy global value
+ setlocal listchars=space:.,extends:>
+ set listchars<
+ call s:CheckListCharsValue(l:default_listchars) " Accommodate Nvim default
+ " Changing global setting should not change the local setting
+ setlocal listchars=space:.,extends:>
+ setglobal listchars=tab:+-,eol:#
+ call s:CheckListCharsValue('space:.,extends:>')
+ " when split opening a new window, local value should be copied
+ split
+ call s:CheckListCharsValue('space:.,extends:>')
+ " clearing local value in one window should not change the other window
+ set listchars&
+ call s:CheckListCharsValue(l:default_listchars) " Accommodate Nvim default
+ close
+ call s:CheckListCharsValue('space:.,extends:>')
+
+ " use different values for 'listchars' items in two different windows
+ call setline(1, ["\t one two "])
+ setlocal listchars=tab:<->,lead:_,space:.,trail:@,eol:#
+ split
+ setlocal listchars=tab:[.],lead:#,space:_,trail:.,eol:&
+ split
+ set listchars=tab:+-+,lead:^,space:>,trail:<,eol:%
+ call assert_equal(['+------+^^one>>two<<%'], ScreenLines(1, virtcol('$')))
+ close
+ call assert_equal(['[......]##one__two..&'], ScreenLines(1, virtcol('$')))
+ close
+ call assert_equal(['<------>__one..two@@#'], ScreenLines(1, virtcol('$')))
+ " changing the global setting should not change the local value
+ setglobal listchars=tab:[.],lead:#,space:_,trail:.,eol:&
+ call assert_equal(['<------>__one..two@@#'], ScreenLines(1, virtcol('$')))
+ set listchars<
+ call assert_equal(['[......]##one__two..&'], ScreenLines(1, virtcol('$')))
+
+ " Using setglobal in a window with local setting should not affect the
+ " window. But should impact other windows using the global setting.
+ enew! | only
+ call setline(1, ["\t one two "])
+ set listchars=tab:[.],lead:#,space:_,trail:.,eol:&
+ split
+ setlocal listchars=tab:+-+,lead:^,space:>,trail:<,eol:%
+ split
+ setlocal listchars=tab:<->,lead:_,space:.,trail:@,eol:#
+ setglobal listchars=tab:{.},lead:-,space:=,trail:#,eol:$
+ call assert_equal(['<------>__one..two@@#'], ScreenLines(1, virtcol('$')))
+ close
+ call assert_equal(['+------+^^one>>two<<%'], ScreenLines(1, virtcol('$')))
+ close
+ call assert_equal(['{......}--one==two##$'], ScreenLines(1, virtcol('$')))
+
+ " Setting the global setting to the default value should not impact a window
+ " using a local setting.
+ split
+ setlocal listchars=tab:<->,lead:_,space:.,trail:@,eol:#
+ setglobal listchars=eol:$ " Accommodate Nvim default
+ call assert_equal(['<------>__one..two@@#'], ScreenLines(1, virtcol('$')))
+ close
+ call assert_equal(['^I one two $'], ScreenLines(1, virtcol('$')))
+
+ " Setting the local setting to the default value should not impact a window
+ " using a global setting.
+ set listchars=tab:{.},lead:-,space:=,trail:#,eol:$
+ split
+ setlocal listchars=tab:<->,lead:_,space:.,trail:@,eol:#
+ call assert_equal(['<------>__one..two@@#'], ScreenLines(1, virtcol('$')))
+ setlocal listchars=eol:$ " Accommodate Nvim default
+ call assert_equal(['^I one two $'], ScreenLines(1, virtcol('$')))
+ close
+ call assert_equal(['{......}--one==two##$'], ScreenLines(1, virtcol('$')))
+
+ " Using set in a window with a local setting should change it to use the
+ " global setting and also impact other windows using the global setting.
+ split
+ setlocal listchars=tab:<->,lead:_,space:.,trail:@,eol:#
+ call assert_equal(['<------>__one..two@@#'], ScreenLines(1, virtcol('$')))
+ set listchars=tab:+-+,lead:^,space:>,trail:<,eol:%
+ call assert_equal(['+------+^^one>>two<<%'], ScreenLines(1, virtcol('$')))
+ close
+ call assert_equal(['+------+^^one>>two<<%'], ScreenLines(1, virtcol('$')))
+
+ " Setting invalid value for a local setting should not impact the local and
+ " global settings.
+ split
+ setlocal listchars=tab:<->,lead:_,space:.,trail:@,eol:#
+ let cmd = 'setlocal listchars=tab:{.},lead:-,space:=,trail:#,eol:$,x'
+ call assert_fails(cmd, 'E474:')
+ call assert_equal(['<------>__one..two@@#'], ScreenLines(1, virtcol('$')))
+ close
+ call assert_equal(['+------+^^one>>two<<%'], ScreenLines(1, virtcol('$')))
+
+ " Setting invalid value for a global setting should not impact the local and
+ " global settings.
+ split
+ setlocal listchars=tab:<->,lead:_,space:.,trail:@,eol:#
+ let cmd = 'setglobal listchars=tab:{.},lead:-,space:=,trail:#,eol:$,x'
+ call assert_fails(cmd, 'E474:')
+ call assert_equal(['<------>__one..two@@#'], ScreenLines(1, virtcol('$')))
+ close
+ call assert_equal(['+------+^^one>>two<<%'], ScreenLines(1, virtcol('$')))
+
+ " Closing window with local lcs-multispace should not cause a memory leak.
+ setlocal listchars=multispace:---+
+ split
+ call s:CheckListCharsValue('multispace:---+')
+ close
+
+ %bw!
+ set list& listchars&
+endfunc
+
+" vim: shiftwidth=2 sts=2 expandtab
diff --git a/src/nvim/testdir/test_listlbr.vim b/src/nvim/testdir/test_listlbr.vim
index e0518de3c2..2fda12d8b4 100644
--- a/src/nvim/testdir/test_listlbr.vim
+++ b/src/nvim/testdir/test_listlbr.vim
@@ -43,6 +43,7 @@ endfunc
func Test_linebreak_with_list()
throw 'skipped: Nvim does not support enc=latin1'
+ set listchars=
call s:test_windows('setl ts=4 sbr=+ list listchars=')
call setline(1, "\tabcdef hijklmn\tpqrstuvwxyz_1060ABCDEFGHIJKLMNOP ")
let lines = s:screen_lines([1, 4], winwidth(0))
@@ -54,6 +55,7 @@ func Test_linebreak_with_list()
\ ]
call s:compare_lines(expect, lines)
call s:close_windows()
+ set listchars&vim
endfunc
func Test_linebreak_with_nolist()
diff --git a/src/nvim/testdir/test_put.vim b/src/nvim/testdir/test_put.vim
index 15745d5619..8d8cc77025 100644
--- a/src/nvim/testdir/test_put.vim
+++ b/src/nvim/testdir/test_put.vim
@@ -111,3 +111,16 @@ func Test_put_p_indent_visual()
call assert_equal('select that text', getline(2))
bwipe!
endfunc
+
+func Test_multibyte_op_end_mark()
+ new
+ call setline(1, 'тест')
+ normal viwdp
+ call assert_equal([0, 1, 7, 0], getpos("'>"))
+ call assert_equal([0, 1, 7, 0], getpos("']"))
+
+ normal Vyp
+ call assert_equal([0, 1, 2147483647, 0], getpos("'>"))
+ call assert_equal([0, 2, 7, 0], getpos("']"))
+ bwipe!
+ endfunc
diff --git a/src/nvim/testdir/test_quickfix.vim b/src/nvim/testdir/test_quickfix.vim
index 8c6ce63ade..b38a59e98f 100644
--- a/src/nvim/testdir/test_quickfix.vim
+++ b/src/nvim/testdir/test_quickfix.vim
@@ -3653,6 +3653,9 @@ func Xqftick_tests(cchar)
\ {'filename' : 'F7', 'lnum' : 11, 'text' : 'L11'}], 'r')
call assert_equal(2, g:Xgetlist({'changedtick' : 0}).changedtick)
+ if isdirectory("Xone")
+ call delete("Xone", 'rf')
+ endif
call writefile(["F8:80:L80", "F8:81:L81"], "Xone")
Xfile Xone
call assert_equal(1, g:Xgetlist({'changedtick' : 0}).changedtick)
diff --git a/src/nvim/testdir/test_registers.vim b/src/nvim/testdir/test_registers.vim
index fd8653a2eb..84a5aca3d5 100644
--- a/src/nvim/testdir/test_registers.vim
+++ b/src/nvim/testdir/test_registers.vim
@@ -43,6 +43,10 @@ func Test_yank_shows_register()
endfunc
func Test_display_registers()
+ " Disable clipboard
+ let save_clipboard = get(g:, 'clipboard', {})
+ let g:clipboard = {}
+
e file1
e file2
call setline(1, ['foo', 'bar'])
@@ -78,6 +82,7 @@ func Test_display_registers()
\ . ' c ": ls', a)
bwipe!
+ let g:clipboard = save_clipboard
endfunc
func Test_recording_status_in_ex_line()
diff --git a/src/nvim/testdir/test_textobjects.vim b/src/nvim/testdir/test_textobjects.vim
index c259453b5e..2b6bb8b302 100644
--- a/src/nvim/testdir/test_textobjects.vim
+++ b/src/nvim/testdir/test_textobjects.vim
@@ -421,4 +421,36 @@ func Test_textobj_quote()
close!
endfunc
+" Test for i(, i<, etc. when cursor is in front of a block
+func Test_textobj_find_paren_forward()
+ new
+
+ " i< and a> when cursor is in front of a block
+ call setline(1, '#include <foo.h>')
+ normal 0yi<
+ call assert_equal('foo.h', @")
+ normal 0ya>
+ call assert_equal('<foo.h>', @")
+
+ " 2i(, 3i( in front of a block enters second/third nested '('
+ call setline(1, 'foo (bar (baz (quux)))')
+ normal 0yi)
+ call assert_equal('bar (baz (quux))', @")
+ normal 02yi)
+ call assert_equal('baz (quux)', @")
+ normal 03yi)
+ call assert_equal('quux', @")
+
+ " 3i( in front of a block doesn't enter third but un-nested '('
+ call setline(1, 'foo (bar (baz) (quux))')
+ normal 03di)
+ call assert_equal('foo (bar (baz) (quux))', getline(1))
+ normal 02di)
+ call assert_equal('foo (bar () (quux))', getline(1))
+ normal 0di)
+ call assert_equal('foo ()', getline(1))
+
+ close!
+endfunc
+
" vim: shiftwidth=2 sts=2 expandtab
diff --git a/src/nvim/undo.c b/src/nvim/undo.c
index 7eb76abd2c..8161fce9f4 100644
--- a/src/nvim/undo.c
+++ b/src/nvim/undo.c
@@ -922,7 +922,7 @@ static u_header_T *unserialize_uhp(bufinfo_T *bi, const char *file_name)
uhp->uh_time = undo_read_time(bi);
// Unserialize optional fields.
- for (;; ) {
+ for (;;) {
int len = undo_read_byte(bi);
if (len == EOF) {
@@ -1504,7 +1504,7 @@ void u_read_undo(char *name, const char_u *hash, const char_u *orig_name FUNC_AT
// Optional header fields.
long last_save_nr = 0;
- for (;; ) {
+ for (;;) {
int len = undo_read_byte(&bi);
if (len == 0 || len == EOF) {
diff --git a/src/nvim/version.c b/src/nvim/version.c
index 1fcbae8be3..5e2a81795a 100644
--- a/src/nvim/version.c
+++ b/src/nvim/version.c
@@ -458,11 +458,11 @@ static const int included_patches[] = {
1466,
1465,
1464,
- // 1463,
+ 1463,
1462,
- // 1461,
- // 1460,
- // 1459,
+ 1461,
+ 1460,
+ 1459,
1458,
1457,
1456,
diff --git a/src/nvim/viml/parser/expressions.c b/src/nvim/viml/parser/expressions.c
index 4f028fa87f..800ecf10db 100644
--- a/src/nvim/viml/parser/expressions.c
+++ b/src/nvim/viml/parser/expressions.c
@@ -1036,7 +1036,7 @@ void viml_pexpr_free_ast(ExprAST ast)
ExprASTNode **const cur_node = kv_last(ast_stack);
#ifndef NDEBUG
// Explicitly check for AST recursiveness.
- for (size_t i = 0 ; i < kv_size(ast_stack) - 1 ; i++) {
+ for (size_t i = 0; i < kv_size(ast_stack) - 1; i++) {
assert(*kv_A(ast_stack, i) != *cur_node);
}
#endif
diff --git a/src/nvim/window.c b/src/nvim/window.c
index 9f6481f5de..3e6e42dec2 100644
--- a/src/nvim/window.c
+++ b/src/nvim/window.c
@@ -224,7 +224,7 @@ newwindow:
beep_flush();
} else {
if (Prenum) { // go to specified window
- for (wp = firstwin; --Prenum > 0; ) {
+ for (wp = firstwin; --Prenum > 0;) {
if (wp->w_next == NULL) {
break;
} else {
@@ -1958,8 +1958,8 @@ static void win_equal_rec(win_T *next_curwin, bool current, frame_T *topfr, int
// Set the width/height of this frame.
// Redraw when size or position changes
if (topfr->fr_height != height || topfr->fr_win->w_winrow != row
- || topfr->fr_width != width ||
- topfr->fr_win->w_wincol != col) {
+ || topfr->fr_width != width
+ || topfr->fr_win->w_wincol != col) {
topfr->fr_win->w_winrow = row;
frame_new_height(topfr, height, false, false);
topfr->fr_win->w_wincol = col;
@@ -2239,7 +2239,7 @@ void close_windows(buf_T *buf, int keep_curwin)
++RedrawingDisabled;
- for (win_T *wp = firstwin; wp != NULL && !ONE_WINDOW; ) {
+ for (win_T *wp = firstwin; wp != NULL && !ONE_WINDOW;) {
if (wp->w_buffer == buf && (!keep_curwin || wp != curwin)
&& !(wp->w_closing || wp->w_buffer->b_locked > 0)) {
if (win_close(wp, false) == FAIL) {
@@ -2582,7 +2582,7 @@ int win_close(win_T *win, bool free_buf)
* If the cursor goes to the preview or the quickfix window, try
* finding another window to go to.
*/
- for (;; ) {
+ for (;;) {
if (wp->w_next == NULL) {
wp = firstwin;
} else {
@@ -3147,12 +3147,12 @@ static void frame_new_height(frame_T *topfrp, int height, bool topfirst, bool wf
break;
}
if (topfirst) {
- do{
+ do {
frp = frp->fr_next;
}
while (wfh && frp != NULL && frame_fixed_height(frp));
} else {
- do{
+ do {
frp = frp->fr_prev;
}
while (wfh && frp != NULL && frame_fixed_height(frp));
@@ -3347,12 +3347,12 @@ static void frame_new_width(frame_T *topfrp, int width, bool leftfirst, bool wfw
break;
}
if (leftfirst) {
- do{
+ do {
frp = frp->fr_next;
}
while (wfw && frp != NULL && frame_fixed_width(frp));
} else {
- do{
+ do {
frp = frp->fr_prev;
}
while (wfw && frp != NULL && frame_fixed_width(frp));
@@ -4316,7 +4316,7 @@ win_T *win_vert_neighbor(tabpage_T *tp, win_T *wp, bool up, long count)
* downwards neighbor.
*/
fr = foundfr;
- for (;; ) {
+ for (;;) {
if (fr == tp->tp_topframe) {
goto end;
}
@@ -4334,7 +4334,7 @@ win_T *win_vert_neighbor(tabpage_T *tp, win_T *wp, bool up, long count)
/*
* Now go downwards to find the bottom or top frame in it.
*/
- for (;; ) {
+ for (;;) {
if (nfr->fr_layout == FR_LEAF) {
foundfr = nfr;
break;
@@ -4399,7 +4399,7 @@ win_T *win_horz_neighbor(tabpage_T *tp, win_T *wp, bool left, long count)
* right neighbor.
*/
fr = foundfr;
- for (;; ) {
+ for (;;) {
if (fr == tp->tp_topframe) {
goto end;
}
@@ -4417,7 +4417,7 @@ win_T *win_horz_neighbor(tabpage_T *tp, win_T *wp, bool left, long count)
/*
* Now go downwards to find the leftmost or rightmost frame in it.
*/
- for (;; ) {
+ for (;;) {
if (nfr->fr_layout == FR_LEAF) {
foundfr = nfr;
break;
@@ -4525,6 +4525,7 @@ static void win_enter_ext(win_T *const wp, const int flags)
fix_current_dir();
+ // Careful: autocommands may close the window and make "wp" invalid
if (flags & WEE_TRIGGER_NEW_AUTOCMDS) {
apply_autocmds(EVENT_WINNEW, NULL, NULL, false, curbuf);
}
@@ -4558,7 +4559,7 @@ static void win_enter_ext(win_T *const wp, const int flags)
}
// set window width to desired minimal value
- if (curwin->w_width < p_wiw && !curwin->w_p_wfw && !wp->w_floating) {
+ if (curwin->w_width < p_wiw && !curwin->w_p_wfw && !curwin->w_floating) {
win_setwidth((int)p_wiw);
}
@@ -4592,6 +4593,7 @@ void fix_current_dir(void)
do_autocmd_dirchanged(new_dir, curwin->w_localdir
? kCdScopeWindow : kCdScopeTabpage, kCdCauseWindow);
}
+ last_chdir_reason = NULL;
shorten_fnames(true);
}
} else if (globaldir != NULL) {
@@ -4603,6 +4605,7 @@ void fix_current_dir(void)
}
}
XFREE_CLEAR(globaldir);
+ last_chdir_reason = NULL;
shorten_fnames(true);
}
}
@@ -4754,6 +4757,8 @@ static void win_free(win_T *wp, tabpage_T *tp)
clear_winopt(&wp->w_onebuf_opt);
clear_winopt(&wp->w_allbuf_opt);
+ xfree(wp->w_p_lcs_chars.multispace);
+
vars_clear(&wp->w_vars->dv_hashtab); // free all w: variables
hash_init(&wp->w_vars->dv_hashtab);
unref_var_dict(wp->w_vars);
@@ -5827,8 +5832,8 @@ void scroll_to_fraction(win_T *wp, int prev_height)
// is visible.
if (height > 0
&& (!wp->w_p_scb || wp == curwin)
- && (height < wp->w_buffer->b_ml.ml_line_count ||
- wp->w_topline > 1)) {
+ && (height < wp->w_buffer->b_ml.ml_line_count
+ || wp->w_topline > 1)) {
/*
* Find a value for w_topline that shows the cursor at the same
* relative position in the window as before (more or less).
@@ -6084,7 +6089,7 @@ void command_height(void)
static void frame_add_height(frame_T *frp, int n)
{
frame_new_height(frp, frp->fr_height + n, false, false);
- for (;; ) {
+ for (;;) {
frp = frp->fr_parent;
if (frp == NULL) {
break;
@@ -7010,7 +7015,7 @@ int win_getid(typval_T *argvars)
wp = tp->tp_firstwin;
}
}
- for ( ; wp != NULL; wp = wp->w_next) {
+ for (; wp != NULL; wp = wp->w_next) {
if (--winnr == 0) {
return wp->handle;
}
diff --git a/src/uncrustify.cfg b/src/uncrustify.cfg
index c06bf41d47..558fa1759f 100644
--- a/src/uncrustify.cfg
+++ b/src/uncrustify.cfg
@@ -141,7 +141,7 @@ sp_enum_before_assign = ignore # ignore/add/remove/force/not_defined
# Add or remove space after assignment '=' in enum.
#
# Overrides sp_enum_assign.
-sp_enum_after_assign = ignore # ignore/add/remove/force/not_defined
+sp_enum_after_assign = force # ignore/add/remove/force/not_defined
# Add or remove space around assignment ':' in enum.
sp_enum_colon = ignore # ignore/add/remove/force/not_defined
@@ -149,11 +149,11 @@ sp_enum_colon = ignore # ignore/add/remove/force/not_defined
# Add or remove space around preprocessor '##' concatenation operator.
#
# Default: add
-sp_pp_concat = ignore # ignore/add/remove/force/not_defined
+sp_pp_concat = remove # ignore/add/remove/force/not_defined
# Add or remove space after preprocessor '#' stringify operator.
# Also affects the '#@' charizing operator.
-sp_pp_stringify = ignore # ignore/add/remove/force/not_defined
+sp_pp_stringify = remove # ignore/add/remove/force/not_defined
# Add or remove space before preprocessor '#' stringify operator
# as in '#define x(y) L#y'.
@@ -334,10 +334,10 @@ sp_after_sparen = ignore # ignore/add/remove/force/not_defined
sp_sparen_brace = ignore # ignore/add/remove/force/not_defined
# Add or remove space between 'do' and '{'.
-sp_do_brace_open = ignore # ignore/add/remove/force/not_defined
+sp_do_brace_open = force # ignore/add/remove/force/not_defined
# Add or remove space between '}' and 'while'.
-sp_brace_close_while = ignore # ignore/add/remove/force/not_defined
+sp_brace_close_while = force # ignore/add/remove/force/not_defined
# Add or remove space between 'while' and '('. Overrides sp_before_sparen.
sp_while_paren_open = ignore # ignore/add/remove/force/not_defined
@@ -354,18 +354,18 @@ sp_special_semi = ignore # ignore/add/remove/force/not_defined
# Add or remove space before ';'.
#
# Default: remove
-sp_before_semi = ignore # ignore/add/remove/force/not_defined
+sp_before_semi = remove # ignore/add/remove/force/not_defined
# Add or remove space before ';' in non-empty 'for' statements.
-sp_before_semi_for = ignore # ignore/add/remove/force/not_defined
+sp_before_semi_for = remove # ignore/add/remove/force/not_defined
# Add or remove space before a semicolon of an empty left part of a for
# statement, as in 'for ( <here> ; ; )'.
-sp_before_semi_for_empty = ignore # ignore/add/remove/force/not_defined
+sp_before_semi_for_empty = remove # ignore/add/remove/force/not_defined
# Add or remove space between the semicolons of an empty middle part of a for
# statement, as in 'for ( ; <here> ; )'.
-sp_between_semi_for_empty = ignore # ignore/add/remove/force/not_defined
+sp_between_semi_for_empty = remove # ignore/add/remove/force/not_defined
# Add or remove space after ';', except when followed by a comment.
#
@@ -379,10 +379,10 @@ sp_after_semi_for = force # ignore/add/remove/force/not_defined
# Add or remove space after the final semicolon of an empty part of a for
# statement, as in 'for ( ; ; <here> )'.
-sp_after_semi_for_empty = ignore # ignore/add/remove/force/not_defined
+sp_after_semi_for_empty = remove # ignore/add/remove/force/not_defined
# Add or remove space before '[' (except '[]').
-sp_before_square = ignore # ignore/add/remove/force/not_defined
+sp_before_square = remove # ignore/add/remove/force/not_defined
# Add or remove space before '[' for a variable definition.
#
@@ -393,13 +393,13 @@ sp_before_vardef_square = remove # ignore/add/remove/force/not_defined
sp_before_square_asm_block = ignore # ignore/add/remove/force/not_defined
# Add or remove space before '[]'.
-sp_before_squares = ignore # ignore/add/remove/force/not_defined
+sp_before_squares = remove # ignore/add/remove/force/not_defined
# Add or remove space before C++17 structured bindings.
sp_cpp_before_struct_binding = ignore # ignore/add/remove/force/not_defined
# Add or remove space inside a non-empty '[' and ']'.
-sp_inside_square = ignore # ignore/add/remove/force/not_defined
+sp_inside_square = remove # ignore/add/remove/force/not_defined
# Add or remove space inside '[]'.
sp_inside_square_empty = ignore # ignore/add/remove/force/not_defined
@@ -592,18 +592,18 @@ sp_func_def_paren_empty = ignore # ignore/add/remove/force/not_defined
# Add or remove space inside empty function '()'.
# Overrides sp_after_angle unless use_sp_after_angle_always is set to true.
-sp_inside_fparens = ignore # ignore/add/remove/force/not_defined
+sp_inside_fparens = remove # ignore/add/remove/force/not_defined
# Add or remove space inside function '(' and ')'.
-sp_inside_fparen = ignore # ignore/add/remove/force/not_defined
+sp_inside_fparen = remove # ignore/add/remove/force/not_defined
# Add or remove space inside the first parentheses in a function type, as in
# 'void (*x)(...)'.
-sp_inside_tparen = ignore # ignore/add/remove/force/not_defined
+sp_inside_tparen = remove # ignore/add/remove/force/not_defined
# Add or remove space between the ')' and '(' in a function type, as in
# 'void (*x)(...)'.
-sp_after_tparen_close = ignore # ignore/add/remove/force/not_defined
+sp_after_tparen_close = remove # ignore/add/remove/force/not_defined
# Add or remove space between ']' and '(' when part of a function call.
sp_square_fparen = ignore # ignore/add/remove/force/not_defined
@@ -649,7 +649,7 @@ sp_func_class_paren = ignore # ignore/add/remove/force/not_defined
sp_func_class_paren_empty = ignore # ignore/add/remove/force/not_defined
# Add or remove space between 'return' and '('.
-sp_return_paren = ignore # ignore/add/remove/force/not_defined
+sp_return_paren = force # ignore/add/remove/force/not_defined
# Add or remove space between 'return' and '{'.
sp_return_brace = ignore # ignore/add/remove/force/not_defined
@@ -714,7 +714,7 @@ sp_else_brace = add # ignore/add/remove/force/not_defined
sp_brace_else = add # ignore/add/remove/force/not_defined
# Add or remove space between '}' and the name of a typedef on the same line.
-sp_brace_typedef = ignore # ignore/add/remove/force/not_defined
+sp_brace_typedef = force # ignore/add/remove/force/not_defined
# Add or remove space before the '{' of a 'catch' statement, if the '{' and
# 'catch' are on the same line, as in 'catch (decl) <here> {'.
@@ -1632,7 +1632,7 @@ nl_using_brace = ignore # ignore/add/remove/force/not_defined
nl_brace_brace = ignore # ignore/add/remove/force/not_defined
# Add or remove newline between 'do' and '{'.
-nl_do_brace = ignore # ignore/add/remove/force/not_defined
+nl_do_brace = remove # ignore/add/remove/force/not_defined
# Add or remove newline between '}' and 'while' of 'do' statement.
nl_brace_while = ignore # ignore/add/remove/force/not_defined
@@ -2333,7 +2333,7 @@ pos_arith = ignore # ignore/break/force/lead/trail/join/
pos_assign = ignore # ignore/break/force/lead/trail/join/lead_break/lead_force/trail_break/trail_force
# The position of Boolean operators in wrapped expressions.
-pos_bool = ignore # ignore/break/force/lead/trail/join/lead_break/lead_force/trail_break/trail_force
+pos_bool = lead # ignore/break/force/lead/trail/join/lead_break/lead_force/trail_break/trail_force
# The position of comparison operators in wrapped expressions.
pos_compare = ignore # ignore/break/force/lead/trail/join/lead_break/lead_force/trail_break/trail_force
@@ -3307,5 +3307,5 @@ set QUESTION REAL_FATTR_CONST
set QUESTION REAL_FATTR_NONNULL_ALL
set QUESTION REAL_FATTR_PURE
set QUESTION REAL_FATTR_WARN_UNUSED_RESULT
-# option(s) with 'not default' value: 69
+# option(s) with 'not default' value: 87
#
diff --git a/test/functional/core/fileio_spec.lua b/test/functional/core/fileio_spec.lua
index f4c476560d..c68bc18eed 100644
--- a/test/functional/core/fileio_spec.lua
+++ b/test/functional/core/fileio_spec.lua
@@ -15,6 +15,7 @@ local read_file = helpers.read_file
local trim = helpers.trim
local currentdir = helpers.funcs.getcwd
local iswin = helpers.iswin
+local assert_alive = helpers.assert_alive
describe('fileio', function()
before_each(function()
@@ -26,6 +27,7 @@ describe('fileio', function()
os.remove('Xtest_startup_file1~')
os.remove('Xtest_startup_file2')
os.remove('Xtest_тест.md')
+ os.remove('Xtest-u8-int-max')
rmdir('Xtest_startup_swapdir')
rmdir('Xtest_backupdir')
end)
@@ -128,5 +130,12 @@ describe('fileio', function()
table.insert(text, '')
eq(text, funcs.readfile(fname, 'b'))
end)
+ it('read invalid u8 over INT_MAX doesn\'t segfault', function()
+ clear()
+ command('call writefile(0zFFFFFFFF, "Xtest-u8-int-max")')
+ -- This should not segfault
+ command('edit ++enc=utf32 Xtest-u8-int-max')
+ assert_alive()
+ end)
end)
diff --git a/test/functional/core/startup_spec.lua b/test/functional/core/startup_spec.lua
index d1dce0f8da..4220d68ee1 100644
--- a/test/functional/core/startup_spec.lua
+++ b/test/functional/core/startup_spec.lua
@@ -560,7 +560,7 @@ describe('user config init', function()
it('loads default lua config, but shows an error', function()
clear{ args_rm={'-u'}, env=xenv }
- feed('<cr>') -- TODO check this, test execution is blocked without it
+ feed('<cr>') -- confirm "Conflicting config ..." message
eq(1, eval('g:lua_rc'))
matches('^E5422: Conflicting configs', meths.exec('messages', true))
end)
diff --git a/test/functional/ex_cmds/cd_spec.lua b/test/functional/ex_cmds/cd_spec.lua
index 283fcf9672..f9cce0deb6 100644
--- a/test/functional/ex_cmds/cd_spec.lua
+++ b/test/functional/ex_cmds/cd_spec.lua
@@ -294,7 +294,16 @@ describe("getcwd()", function ()
command('set autochdir')
command('edit ' .. directories.global .. '/foo')
eq(curdir .. pathsep .. directories.global, cwd())
+ eq(curdir, wcwd())
+ call('mkdir', 'bar')
+ command('edit ' .. 'bar/foo')
+ eq(curdir .. pathsep .. directories.global .. pathsep .. 'bar', cwd())
+ eq(curdir, wcwd())
+ command('lcd ..')
+ eq(curdir .. pathsep .. directories.global, cwd())
+ eq(curdir .. pathsep .. directories.global, wcwd())
+ command('edit')
+ eq(curdir .. pathsep .. directories.global .. pathsep .. 'bar', cwd())
+ eq(curdir .. pathsep .. directories.global, wcwd())
end)
end)
-
-
diff --git a/test/functional/fixtures/api_level_8.mpack b/test/functional/fixtures/api_level_8.mpack
new file mode 100644
index 0000000000..0447fce3ed
--- /dev/null
+++ b/test/functional/fixtures/api_level_8.mpack
Binary files differ
diff --git a/test/functional/legacy/autochdir_spec.lua b/test/functional/legacy/autochdir_spec.lua
index 466e3ed830..37a94476a0 100644
--- a/test/functional/legacy/autochdir_spec.lua
+++ b/test/functional/legacy/autochdir_spec.lua
@@ -1,10 +1,11 @@
local lfs = require('lfs')
local helpers = require('test.functional.helpers')(after_each)
-local clear, eq = helpers.clear, helpers.eq
-local eval, command = helpers.eval, helpers.command
+local clear, eq, matches = helpers.clear, helpers.eq, helpers.matches
+local eval, command, call = helpers.eval, helpers.command, helpers.call
+local exec_capture = helpers.exec_capture
describe('autochdir behavior', function()
- local dir = 'Xtest-functional-legacy-autochdir'
+ local dir = 'Xtest_functional_legacy_autochdir'
before_each(function()
lfs.mkdir(dir)
@@ -23,4 +24,35 @@ describe('autochdir behavior', function()
eq('Xtest', eval("expand('%')"))
eq(dir, eval([[substitute(getcwd(), '.*[/\\]\(\k*\)', '\1', '')]]))
end)
+
+ it(':verbose pwd shows whether autochdir is used', function()
+ local subdir = 'Xautodir'
+ command('cd '..dir)
+ local cwd = eval('getcwd()')
+ command('edit global.txt')
+ matches('%[global%].*'..dir, exec_capture('verbose pwd'))
+ call('mkdir', subdir)
+ command('split '..subdir..'/local.txt')
+ command('lcd '..subdir)
+ matches('%[window%].*'..dir..'[/\\]'..subdir, exec_capture('verbose pwd'))
+ command('set autochdir')
+ command('wincmd w')
+ matches('%[autochdir%].*'..dir, exec_capture('verbose pwd'))
+ command('lcd '..cwd)
+ matches('%[window%].*'..dir, exec_capture('verbose pwd'))
+ command('tcd '..cwd)
+ matches('%[tabpage%].*'..dir, exec_capture('verbose pwd'))
+ command('cd '..cwd)
+ matches('%[global%].*'..dir, exec_capture('verbose pwd'))
+ command('edit')
+ matches('%[autochdir%].*'..dir, exec_capture('verbose pwd'))
+ command('wincmd w')
+ matches('%[autochdir%].*'..dir..'[/\\]'..subdir, exec_capture('verbose pwd'))
+ command('set noautochdir')
+ matches('%[autochdir%].*'..dir..'[/\\]'..subdir, exec_capture('verbose pwd'))
+ command('wincmd w')
+ matches('%[global%].*'..dir, exec_capture('verbose pwd'))
+ command('wincmd w')
+ matches('%[window%].*'..dir..'[/\\]'..subdir, exec_capture('verbose pwd'))
+ end)
end)
diff --git a/test/functional/legacy/fnamemodify_spec.lua b/test/functional/legacy/fnamemodify_spec.lua
index 6a5538c26f..6262db3a2f 100644
--- a/test/functional/legacy/fnamemodify_spec.lua
+++ b/test/functional/legacy/fnamemodify_spec.lua
@@ -29,7 +29,7 @@ describe('filename modifiers', function()
call assert_equal('test.out', fnamemodify('test.out', ':.'))
call assert_equal('../testdir/a', fnamemodify('../testdir/a', ':.'))
call assert_equal(fnamemodify(tmpdir, ':~').'/test.out', fnamemodify('test.out', ':~'))
- call assert_equal('../testdir/a', fnamemodify('../testdir/a', ':~'))
+ call assert_equal(fnamemodify(tmpdir, ':~').'/../testdir/a', fnamemodify('../testdir/a', ':~'))
call assert_equal('a', fnamemodify('../testdir/a', ':t'))
call assert_equal('', fnamemodify('.', ':p:t'))
call assert_equal('test.out', fnamemodify('test.out', ':p:t'))
diff --git a/test/functional/legacy/packadd_spec.lua b/test/functional/legacy/packadd_spec.lua
index 48cd3ef9f8..4f9f5a0237 100644
--- a/test/functional/legacy/packadd_spec.lua
+++ b/test/functional/legacy/packadd_spec.lua
@@ -20,6 +20,9 @@ describe('packadd', function()
func SetUp()
let s:topdir = expand(getcwd() . '/Xdir')
+ if isdirectory(s:topdir)
+ call delete(s:topdir, 'rf')
+ endif
exe 'set packpath=' . s:topdir
let s:plugdir = expand(s:topdir . '/pack/mine/opt/mytest')
endfunc
diff --git a/test/functional/lua/diagnostic_spec.lua b/test/functional/lua/diagnostic_spec.lua
index 6414483c0d..927ee8060d 100644
--- a/test/functional/lua/diagnostic_spec.lua
+++ b/test/functional/lua/diagnostic_spec.lua
@@ -110,20 +110,35 @@ describe('vim.diagnostic', function()
it('retrieves diagnostics from all buffers and namespaces', function()
local result = exec_lua [[
- vim.diagnostic.set(diagnostic_ns, 1, {
+ local other_bufnr = vim.api.nvim_create_buf(true, false)
+ local lines = vim.api.nvim_buf_get_lines(diagnostic_bufnr, 0, -1, true)
+ vim.api.nvim_buf_set_lines(other_bufnr, 0, 1, false, lines)
+
+ vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, {
make_error('Diagnostic #1', 1, 1, 1, 1),
make_error('Diagnostic #2', 2, 1, 2, 1),
})
- vim.diagnostic.set(other_ns, 2, {
+ vim.diagnostic.set(other_ns, other_bufnr, {
make_error('Diagnostic #3', 3, 1, 3, 1),
})
return vim.diagnostic.get()
]]
eq(3, #result)
- eq(2, exec_lua([[return #vim.tbl_filter(function(d) return d.bufnr == 1 end, ...)]], result))
+ eq(2, exec_lua([[return #vim.tbl_filter(function(d) return d.bufnr == diagnostic_bufnr end, ...)]], result))
eq('Diagnostic #1', result[1].message)
end)
+ it('resolves buffer number 0 to the current buffer', function()
+ eq(2, exec_lua [[
+ vim.api.nvim_set_current_buf(diagnostic_bufnr)
+ vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, {
+ make_error('Diagnostic #1', 1, 1, 1, 1),
+ make_error('Diagnostic #2', 2, 1, 2, 1),
+ })
+ return #vim.diagnostic.get(0)
+ ]])
+ end)
+
it('saves and count a single error', function()
eq(1, exec_lua [[
vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, {
@@ -339,6 +354,16 @@ describe('vim.diagnostic', function()
eq(0, result[5])
eq(3, result[6])
end)
+
+ it("doesn't error after bwipeout on buffer", function()
+ exec_lua [[
+ vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, {{ lnum = 0, end_lnum = 0, col = 0, end_col = 0 }})
+ vim.cmd("bwipeout! " .. diagnostic_bufnr)
+
+ vim.diagnostic.show(diagnostic_ns)
+ vim.diagnostic.hide(diagnostic_ns)
+ ]]
+ end)
end)
describe('enable() and disable()', function()
@@ -625,6 +650,15 @@ describe('vim.diagnostic', function()
]])
end)
+
+ it("doesn't error after bwipeout called on buffer", function()
+ exec_lua [[
+ vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, {{ lnum = 0, end_lnum = 0, col = 0, end_col = 0 }})
+ vim.cmd("bwipeout! " .. diagnostic_bufnr)
+
+ vim.diagnostic.reset(diagnostic_ns)
+ ]]
+ end)
end)
describe('get_next_pos()', function()
@@ -682,6 +716,19 @@ describe('vim.diagnostic', function()
return vim.diagnostic.get_prev_pos { namespace = diagnostic_ns }
]])
end)
+
+ it('works with diagnostics past the end of the line #16349', function()
+ eq({4, 0}, exec_lua [[
+ vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, {
+ make_error('Diagnostic #1', 3, 9001, 3, 9001),
+ make_error('Diagnostic #2', 4, 0, 4, 0),
+ })
+ vim.api.nvim_win_set_buf(0, diagnostic_bufnr)
+ vim.api.nvim_win_set_cursor(0, {1, 1})
+ vim.diagnostic.goto_next { float = false }
+ return vim.diagnostic.get_next_pos { namespace = diagnostic_ns }
+ ]])
+ end)
end)
describe('get_prev_pos()', function()
@@ -878,7 +925,7 @@ describe('vim.diagnostic', function()
]]
eq(1, exec_lua [[return count_diagnostics(diagnostic_bufnr, vim.diagnostic.severity.ERROR, diagnostic_ns)]])
- -- eq(1, exec_lua [[return count_extmarks(diagnostic_bufnr, diagnostic_ns)]])
+ eq(1, exec_lua [[return count_extmarks(diagnostic_bufnr, diagnostic_ns)]])
end)
it('allows filtering by severity', function()
@@ -1323,7 +1370,7 @@ describe('vim.diagnostic', function()
}
vim.api.nvim_win_set_buf(0, diagnostic_bufnr)
vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, diagnostics)
- local float_bufnr, winnr = vim.diagnostic.open_float(0, {header = false})
+ local float_bufnr, winnr = vim.diagnostic.open_float(0, {header = false, scope="buffer"})
local lines = vim.api.nvim_buf_get_lines(float_bufnr, 0, -1, false)
vim.api.nvim_win_close(winnr, true)
return lines
@@ -1340,7 +1387,7 @@ describe('vim.diagnostic', function()
vim.api.nvim_win_set_buf(0, diagnostic_bufnr)
vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, diagnostics)
vim.api.nvim_win_set_cursor(0, {2, 1})
- local float_bufnr, winnr = vim.diagnostic.open_float(0, {header=false, scope="line"})
+ local float_bufnr, winnr = vim.diagnostic.open_float(0, {header=false})
local lines = vim.api.nvim_buf_get_lines(float_bufnr, 0, -1, false)
vim.api.nvim_win_close(winnr, true)
return lines
@@ -1355,7 +1402,7 @@ describe('vim.diagnostic', function()
vim.api.nvim_win_set_buf(0, diagnostic_bufnr)
vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, diagnostics)
vim.api.nvim_win_set_cursor(0, {1, 1})
- local float_bufnr, winnr = vim.diagnostic.open_float(0, {header=false, scope="line", pos=1})
+ local float_bufnr, winnr = vim.diagnostic.open_float(0, {header=false, pos=1})
local lines = vim.api.nvim_buf_get_lines(float_bufnr, 0, -1, false)
vim.api.nvim_win_close(winnr, true)
return lines
@@ -1419,7 +1466,7 @@ describe('vim.diagnostic', function()
}
vim.api.nvim_win_set_buf(0, diagnostic_bufnr)
vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, diagnostics)
- local float_bufnr, winnr = vim.diagnostic.open_float(diagnostic_bufnr, {scope="line"})
+ local float_bufnr, winnr = vim.diagnostic.open_float(diagnostic_bufnr)
local lines = vim.api.nvim_buf_get_lines(float_bufnr, 0, -1, false)
vim.api.nvim_win_close(winnr, true)
return #lines
@@ -1486,7 +1533,7 @@ describe('vim.diagnostic', function()
}
vim.api.nvim_win_set_buf(0, diagnostic_bufnr)
vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, diagnostics)
- local float_bufnr, winnr = vim.diagnostic.open_float(diagnostic_bufnr, {header = false, scope = "line", pos = 5})
+ local float_bufnr, winnr = vim.diagnostic.open_float(diagnostic_bufnr, {header = false, pos = 5})
local lines = vim.api.nvim_buf_get_lines(float_bufnr, 0, -1, false)
vim.api.nvim_win_close(winnr, true)
return #lines
@@ -1618,7 +1665,7 @@ describe('vim.diagnostic', function()
}
vim.api.nvim_win_set_buf(0, diagnostic_bufnr)
vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, diagnostics)
- local float_bufnr, winnr = vim.diagnostic.open_float(0, {header = false})
+ local float_bufnr, winnr = vim.diagnostic.open_float(0, {header = false, scope = "buffer"})
local lines = vim.api.nvim_buf_get_lines(float_bufnr, 0, -1, false)
vim.api.nvim_win_close(winnr, true)
return lines
@@ -1631,7 +1678,7 @@ describe('vim.diagnostic', function()
}
vim.api.nvim_win_set_buf(0, diagnostic_bufnr)
vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, diagnostics)
- local float_bufnr, winnr = vim.diagnostic.open_float(0, {header = false, prefix = ""})
+ local float_bufnr, winnr = vim.diagnostic.open_float(0, {header = false, scope = "buffer", prefix = ""})
local lines = vim.api.nvim_buf_get_lines(float_bufnr, 0, -1, false)
vim.api.nvim_win_close(winnr, true)
return lines
@@ -1640,7 +1687,7 @@ describe('vim.diagnostic', function()
eq({'1. Syntax error', '2. Some warning'}, exec_lua [[
local diagnostics = {
make_error("Syntax error", 0, 1, 0, 3),
- make_warning("Some warning", 1, 1, 1, 3),
+ make_warning("Some warning", 0, 1, 0, 3),
}
vim.api.nvim_win_set_buf(0, diagnostic_bufnr)
vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, diagnostics)
diff --git a/test/functional/lua/uri_spec.lua b/test/functional/lua/uri_spec.lua
index 81f1820986..dbfbe2dbfe 100644
--- a/test/functional/lua/uri_spec.lua
+++ b/test/functional/lua/uri_spec.lua
@@ -143,8 +143,8 @@ describe('URI methods', function()
end)
it('uri_to_fname returns non-file scheme URI without authority unchanged', function()
- eq('zipfile:/path/to/archive.zip%3A%3Afilename.txt', exec_lua [[
- return vim.uri_to_fname('zipfile:/path/to/archive.zip%3A%3Afilename.txt')
+ eq('zipfile:///path/to/archive.zip%3A%3Afilename.txt', exec_lua [[
+ return vim.uri_to_fname('zipfile:///path/to/archive.zip%3A%3Afilename.txt')
]])
end)
end)
@@ -186,7 +186,7 @@ describe('URI methods', function()
end)
it('uri_to_bufnr & uri_from_bufnr returns original uri for non-file uris without authority', function()
- local uri = 'zipfile:/path/to/archive.zip%3A%3Afilename.txt'
+ local uri = 'zipfile:///path/to/archive.zip%3A%3Afilename.txt'
local test_case = string.format([[
local uri = '%s'
return vim.uri_from_bufnr(vim.uri_to_bufnr(uri))
diff --git a/test/functional/lua/vim_spec.lua b/test/functional/lua/vim_spec.lua
index 3832d27a22..28471bdd46 100644
--- a/test/functional/lua/vim_spec.lua
+++ b/test/functional/lua/vim_spec.lua
@@ -396,6 +396,20 @@ describe('lua stdlib', function()
return t1.f() ~= t2.f()
]]))
+ ok(exec_lua([[
+ local t1 = {a = 5}
+ t1.self = t1
+ local t2 = vim.deepcopy(t1)
+ return t2.self == t2 and t2.self ~= t1
+ ]]))
+
+ ok(exec_lua([[
+ local mt = {mt=true}
+ local t1 = setmetatable({a = 5}, mt)
+ local t2 = vim.deepcopy(t1)
+ return getmetatable(t2) == mt
+ ]]))
+
eq('Error executing lua: vim/shared.lua:0: Cannot deepcopy object of type thread',
pcall_err(exec_lua, [[
local thread = coroutine.create(function () return 0 end)
diff --git a/test/functional/options/chars_spec.lua b/test/functional/options/chars_spec.lua
index 5439ca3dba..a082204980 100644
--- a/test/functional/options/chars_spec.lua
+++ b/test/functional/options/chars_spec.lua
@@ -67,36 +67,52 @@ describe("'fillchars'", function()
shouldfail('eob:xy') -- two ascii chars
shouldfail('eob:\255', 'eob:<ff>') -- invalid UTF-8
end)
- it('has global value', function()
- screen:try_resize(50, 5)
- insert("foo\nbar")
- command('set laststatus=0')
- command('1,2fold')
- command('vsplit')
- command('set fillchars=fold:x')
- screen:expect([[
- ^+-- 2 lines: fooxxxxxxxx│+-- 2 lines: fooxxxxxxx|
- ~ │~ |
- ~ │~ |
- ~ │~ |
- |
- ]])
- end)
- it('has local window value', function()
- screen:try_resize(50, 5)
- insert("foo\nbar")
- command('set laststatus=0')
- command('1,2fold')
- command('vsplit')
- command('setl fillchars=fold:x')
- screen:expect([[
- ^+-- 2 lines: fooxxxxxxxx│+-- 2 lines: foo·······|
- ~ │~ |
- ~ │~ |
- ~ │~ |
- |
- ]])
- end)
+ end)
+ it('has global value', function()
+ screen:try_resize(50, 5)
+ insert("foo\nbar")
+ command('set laststatus=0')
+ command('1,2fold')
+ command('vsplit')
+ command('set fillchars=fold:x')
+ screen:expect([[
+ ^+-- 2 lines: fooxxxxxxxx│+-- 2 lines: fooxxxxxxx|
+ ~ │~ |
+ ~ │~ |
+ ~ │~ |
+ |
+ ]])
+ end)
+ it('has window-local value', function()
+ screen:try_resize(50, 5)
+ insert("foo\nbar")
+ command('set laststatus=0')
+ command('1,2fold')
+ command('vsplit')
+ command('setl fillchars=fold:x')
+ screen:expect([[
+ ^+-- 2 lines: fooxxxxxxxx│+-- 2 lines: foo·······|
+ ~ │~ |
+ ~ │~ |
+ ~ │~ |
+ |
+ ]])
+ end)
+ it('using :set clears window-local value', function()
+ screen:try_resize(50, 5)
+ insert("foo\nbar")
+ command('set laststatus=0')
+ command('setl fillchars=fold:x')
+ command('1,2fold')
+ command('vsplit')
+ command('set fillchars&')
+ screen:expect([[
+ ^+-- 2 lines: foo········│+-- 2 lines: fooxxxxxxx|
+ ~ │~ |
+ ~ │~ |
+ ~ │~ |
+ |
+ ]])
end)
end)
@@ -122,7 +138,7 @@ describe("'listchars'", function()
|
]])
end)
- it('has value local to window', function()
+ it('has window-local value', function()
feed('i<tab><tab><tab><esc>')
command('set list laststatus=0')
command('setl listchars=tab:<->')
@@ -136,4 +152,18 @@ describe("'listchars'", function()
|
]])
end)
+ it('using :set clears window-local value', function()
+ feed('i<tab><tab><tab><esc>')
+ command('set list laststatus=0')
+ command('setl listchars=tab:<->')
+ command('vsplit')
+ command('set listchars=tab:>-,eol:$')
+ screen:expect([[
+ >------->-------^>-------$│<------><------><------>|
+ ~ │~ |
+ ~ │~ |
+ ~ │~ |
+ |
+ ]])
+ end)
end)
diff --git a/test/functional/plugin/lsp/incremental_sync_spec.lua b/test/functional/plugin/lsp/incremental_sync_spec.lua
index 890db4abf5..5dd34e7665 100644
--- a/test/functional/plugin/lsp/incremental_sync_spec.lua
+++ b/test/functional/plugin/lsp/incremental_sync_spec.lua
@@ -297,7 +297,31 @@ describe('incremental synchronization', function()
}
test_edit({"🔥"}, {"x"}, expected_text_changes, 'utf-16', '\n')
end)
- it('deleting a multiple lines containing multibyte characters', function()
+ it('deleting a multibyte character from a long line', function()
+ local expected_text_changes = {
+ {
+ range = {
+ ['start'] = {
+ character = 85,
+ line = 1
+ },
+ ['end'] = {
+ character = 86,
+ line = 1
+ }
+ },
+ rangeLength = 1,
+ text = ''
+ }
+ }
+ local original_lines = {
+ "\\begin{document}",
+ "→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→",
+ "\\end{document}",
+ }
+ test_edit(original_lines, {"jx"}, expected_text_changes, 'utf-16', '\n')
+ end)
+ it('deleting multiple lines containing multibyte characters', function()
local expected_text_changes = {
{
range = {
diff --git a/test/functional/plugin/lsp_spec.lua b/test/functional/plugin/lsp_spec.lua
index 228fc06e9b..b12d4227d5 100644
--- a/test/functional/plugin/lsp_spec.lua
+++ b/test/functional/plugin/lsp_spec.lua
@@ -66,7 +66,10 @@ local function fake_lsp_server_setup(test_name, timeout_ms, options)
end
end;
});
- root_dir = vim.loop.cwd();
+ workspace_folders = {{
+ uri = 'file://' .. vim.loop.cwd(),
+ name = 'test_folder',
+ }};
on_init = function(client, result)
TEST_RPC_CLIENT = client
vim.rpcrequest(1, "init", result)
@@ -153,7 +156,10 @@ describe('LSP', function()
"-c", string.format("lua TEST_NAME = %q", test_name),
"-c", "luafile "..fixture_filename;
};
- root_dir = vim.loop.cwd();
+ workspace_folders = {{
+ uri = 'file://' .. vim.loop.cwd(),
+ name = 'test_folder',
+ }};
}
end
TEST_CLIENT1 = test__start_client()
diff --git a/test/functional/treesitter/parser_spec.lua b/test/functional/treesitter/parser_spec.lua
index ffaa4141c4..1138cfbf4c 100644
--- a/test/functional/treesitter/parser_spec.lua
+++ b/test/functional/treesitter/parser_spec.lua
@@ -231,11 +231,11 @@ void ui_refresh(void)
insert('char* astring = "\\n"; (1 + 1) * 2 != 2;')
local res = exec_lua([[
- cquery = vim.treesitter.parse_query("c", '((_) @plus (vim-match? @plus "^\\\\+$"))'..
- '((_) @times (vim-match? @times "^\\\\*$"))'..
- '((_) @paren (vim-match? @paren "^\\\\($"))'..
- '((_) @escape (vim-match? @escape "^\\\\\\\\n$"))'..
- '((_) @string (vim-match? @string "^\\"\\\\\\\\n\\"$"))')
+ cquery = vim.treesitter.parse_query("c", '([_] @plus (#vim-match? @plus "^\\\\+$"))'..
+ '([_] @times (#vim-match? @times "^\\\\*$"))'..
+ '([_] @paren (#vim-match? @paren "^\\\\($"))'..
+ '([_] @escape (#vim-match? @escape "^\\\\\\\\n$"))'..
+ '([_] @string (#vim-match? @string "^\\"\\\\\\\\n\\"$"))')
parser = vim.treesitter.get_parser(0, "c")
tree = parser:parse()[1]
res = {}
@@ -321,7 +321,7 @@ void ui_refresh(void)
insert('char* astring = "Hello World!";')
local res = exec_lua([[
- cquery = vim.treesitter.parse_query("c", '((_) @quote (vim-match? @quote "^\\"$")) ((_) @quote (lua-match? @quote "^\\"$"))')
+ cquery = vim.treesitter.parse_query("c", '([_] @quote (#vim-match? @quote "^\\"$")) ([_] @quote (#lua-match? @quote "^\\"$"))')
parser = vim.treesitter.get_parser(0, "c")
tree = parser:parse()[1]
res = {}
diff --git a/test/unit/path_spec.lua b/test/unit/path_spec.lua
index 41954de9be..15ce59747e 100644
--- a/test/unit/path_spec.lua
+++ b/test/unit/path_spec.lua
@@ -54,15 +54,21 @@ describe('path.c', function()
eq(lfs.currentdir(), (ffi.string(buffer)))
end)
- itp('fails if the given directory does not exist', function()
- eq(FAIL, path_full_dir_name('does_not_exist', buffer, length))
- end)
-
itp('works with a normal relative dir', function()
local result = path_full_dir_name('unit-test-directory', buffer, length)
eq(lfs.currentdir() .. '/unit-test-directory', (ffi.string(buffer)))
eq(OK, result)
end)
+
+ itp('works with a non-existing relative dir', function()
+ local result = path_full_dir_name('does-not-exist', buffer, length)
+ eq(lfs.currentdir() .. '/does-not-exist', (ffi.string(buffer)))
+ eq(OK, result)
+ end)
+
+ itp('fails with a non-existing absolute dir', function()
+ eq(FAIL, path_full_dir_name('/does_not_exist', buffer, length))
+ end)
end)
describe('path_full_compare', function()
diff --git a/third-party/CMakeLists.txt b/third-party/CMakeLists.txt
index 8ad71cfd3a..52839d8efa 100644
--- a/third-party/CMakeLists.txt
+++ b/third-party/CMakeLists.txt
@@ -97,7 +97,7 @@ endif()
if(MINGW AND CMAKE_GENERATOR MATCHES "Ninja")
find_program(MAKE_PRG NAMES mingw32-make)
if(NOT MAKE_PRG)
- message(FATAL_ERROR "GNU Make for mingw32 is required to build the dependecies.")
+ message(FATAL_ERROR "GNU Make for mingw32 is required to build the dependencies.")
else()
message(STATUS "Found GNU Make for mingw32: ${MAKE_PRG}")
endif()
@@ -157,8 +157,8 @@ set(LUAJIT_SHA256 6c9e46877db2df16ca0fa76db4043ed30a1ae60c89d9ba2c3e4d35eb2360cd
set(LUA_URL https://www.lua.org/ftp/lua-5.1.5.tar.gz)
set(LUA_SHA256 2640fc56a795f29d28ef15e13c34a47e223960b0240e8cb0a82d9b0738695333)
-set(LUAROCKS_URL https://github.com/luarocks/luarocks/archive/v3.7.0.tar.gz)
-set(LUAROCKS_SHA256 968c98ae894cea2c850f077133e3feb9f8ce94df7a33a5611bd4d25e07c94925)
+set(LUAROCKS_URL https://github.com/luarocks/luarocks/archive/v3.8.0.tar.gz)
+set(LUAROCKS_SHA256 ab6612ca9ab87c6984871d2712d05525775e8b50172701a0a1cabddf76de2be7)
set(UNIBILIUM_URL https://github.com/neovim/unibilium/archive/92d929f.tar.gz)
set(UNIBILIUM_SHA256 29815283c654277ef77a3adcc8840db79ddbb20a0f0b0c8f648bd8cd49a02e4b)
@@ -200,11 +200,11 @@ set(GETTEXT_SHA256 66415634c6e8c3fa8b71362879ec7575e27da43da562c798a8a2f223e6e47
set(LIBICONV_URL https://ftp.gnu.org/pub/gnu/libiconv/libiconv-1.15.tar.gz)
set(LIBICONV_SHA256 ccf536620a45458d26ba83887a983b96827001e92a13847b45e4925cc8913178)
-set(TREESITTER_C_URL https://github.com/tree-sitter/tree-sitter-c/archive/5aa0bbb.tar.gz)
-set(TREESITTER_C_SHA256 a5dcb37460d83002dfae7f9a208170ddbc9a047f231b9d6b75da7d36d707db2f)
+set(TREESITTER_C_URL https://github.com/tree-sitter/tree-sitter-c/archive/v0.20.1.tar.gz)
+set(TREESITTER_C_SHA256 ffcc2ef0eded59ad1acec9aec4f9b0c7dd209fc1a85d85f8b0e81298e3dddcc2)
-set(TREESITTER_URL https://github.com/tree-sitter/tree-sitter/archive/7890a29db0b186b7b21a0a95d99fa6c562b8316b.tar.gz)
-set(TREESITTER_SHA256 634006b0336a5eef1b07d2f80a4d4f8ac1522bf15759ec3e5dda0032a734fb19)
+set(TREESITTER_URL https://github.com/tree-sitter/tree-sitter/archive/v0.20.1.tar.gz)
+set(TREESITTER_SHA256 12a3f7206af3028dbe8a0de50d8ebd6d7010bf762db918acae76fc7585f1258d)
if(USE_BUNDLED_UNIBILIUM)
include(BuildUnibilium)