aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.git-blame-ignore-revs11
-rw-r--r--CONTRIBUTING.md15
-rw-r--r--README.md2
-rw-r--r--contrib/flake.lock12
-rw-r--r--contrib/flake.nix10
-rw-r--r--contrib/uncrustify.cfg3831
-rw-r--r--runtime/autoload/man.vim18
-rw-r--r--runtime/doc/cmdline.txt5
-rw-r--r--runtime/doc/eval.txt341
-rw-r--r--runtime/doc/lsp.txt65
-rw-r--r--runtime/doc/lua.txt4
-rw-r--r--runtime/doc/nvim_terminal_emulator.txt2
-rw-r--r--runtime/doc/options.txt20
-rw-r--r--runtime/doc/starting.txt41
-rw-r--r--runtime/doc/syntax.txt11
-rw-r--r--runtime/doc/testing.txt36
-rw-r--r--runtime/doc/vim_diff.txt26
-rw-r--r--runtime/ftplugin/jsonc.vim27
-rw-r--r--runtime/ftplugin/man.vim14
-rw-r--r--runtime/indent/jsonc.vim189
-rw-r--r--runtime/lua/vim/F.lua9
-rw-r--r--runtime/lua/vim/highlight.lua6
-rw-r--r--runtime/lua/vim/lsp.lua4
-rw-r--r--runtime/lua/vim/lsp/codelens.lua3
-rw-r--r--runtime/lua/vim/lsp/diagnostic.lua9
-rw-r--r--runtime/lua/vim/lsp/util.lua18
-rw-r--r--runtime/lua/vim/treesitter.lua3
-rw-r--r--runtime/plugin/man.vim4
-rw-r--r--runtime/syntax/jsonc.vim44
-rw-r--r--runtime/syntax/man.vim8
-rw-r--r--runtime/tutor/en/vim-01-beginner.tutor222
-rw-r--r--runtime/tutor/en/vim-01-beginner.tutor.json70
-rw-r--r--src/nvim/CMakeLists.txt14
-rw-r--r--src/nvim/api/private/helpers.c30
-rw-r--r--src/nvim/api/vim.c42
-rw-r--r--src/nvim/aucmd.c24
-rw-r--r--src/nvim/buffer.c32
-rw-r--r--src/nvim/channel.c17
-rw-r--r--src/nvim/eval.c525
-rw-r--r--src/nvim/eval.lua225
-rw-r--r--src/nvim/eval/funcs.c68
-rw-r--r--src/nvim/eval/funcs.h5
-rw-r--r--src/nvim/eval/userfunc.c139
-rw-r--r--src/nvim/eval/userfunc.h26
-rw-r--r--src/nvim/event/process.c24
-rw-r--r--src/nvim/event/process.h1
-rw-r--r--src/nvim/fileio.c38
-rw-r--r--src/nvim/fold.h2
-rw-r--r--src/nvim/generators/gen_api_dispatch.lua4
-rw-r--r--src/nvim/generators/gen_eval.lua7
-rw-r--r--src/nvim/globals.h1
-rw-r--r--src/nvim/highlight_defs.h6
-rw-r--r--src/nvim/lua/converter.c40
-rw-r--r--src/nvim/lua/executor.c37
-rw-r--r--src/nvim/lua/vim.lua6
-rw-r--r--src/nvim/main.c23
-rw-r--r--src/nvim/math.c38
-rw-r--r--src/nvim/memline.c2
-rw-r--r--src/nvim/msgpack_rpc/helpers.c22
-rw-r--r--src/nvim/normal.c13
-rw-r--r--src/nvim/ops.c5
-rw-r--r--src/nvim/option.c24
-rw-r--r--src/nvim/regexp.c14
-rw-r--r--src/nvim/screen.c1055
-rw-r--r--src/nvim/syntax.c2
-rw-r--r--src/nvim/tag.c51
-rw-r--r--src/nvim/testdir/sautest/autoload/foo.vim4
-rw-r--r--src/nvim/testdir/test_arglist.vim4
-rw-r--r--src/nvim/testdir/test_assert.vim2
-rw-r--r--src/nvim/testdir/test_autoload.vim2
-rw-r--r--src/nvim/testdir/test_bufline.vim8
-rw-r--r--src/nvim/testdir/test_bufwintabinfo.vim2
-rw-r--r--src/nvim/testdir/test_cindent.vim10
-rw-r--r--src/nvim/testdir/test_diffmode.vim14
-rw-r--r--src/nvim/testdir/test_float_func.vim27
-rw-r--r--src/nvim/testdir/test_functions.vim57
-rw-r--r--src/nvim/testdir/test_hide.vim2
-rw-r--r--src/nvim/testdir/test_lambda.vim2
-rw-r--r--src/nvim/testdir/test_match.vim2
-rw-r--r--src/nvim/testdir/test_method.vim159
-rw-r--r--src/nvim/testdir/test_number.vim33
-rw-r--r--src/nvim/testdir/test_popup.vim6
-rw-r--r--src/nvim/testdir/test_syntax.vim4
-rw-r--r--src/nvim/testdir/test_system.vim4
-rw-r--r--src/nvim/testdir/test_tagjump.vim10
-rw-r--r--src/nvim/testdir/test_user_func.vim18
-rw-r--r--src/nvim/testdir/test_vimscript.vim4
-rw-r--r--src/nvim/testdir/test_visual.vim9
-rw-r--r--src/nvim/undo.c10
-rw-r--r--test/functional/api/extmark_spec.lua5
-rw-r--r--test/functional/api/server_notifications_spec.lua8
-rw-r--r--test/functional/api/server_requests_spec.lua5
-rw-r--r--test/functional/api/vim_spec.lua58
-rw-r--r--test/functional/core/exit_spec.lua3
-rw-r--r--test/functional/core/job_spec.lua3
-rw-r--r--test/functional/core/startup_spec.lua5
-rw-r--r--test/functional/eval/modeline_spec.lua4
-rw-r--r--test/functional/eval/null_spec.lua6
-rw-r--r--test/functional/eval/system_spec.lua7
-rw-r--r--test/functional/ex_cmds/dict_notifications_spec.lua5
-rw-r--r--test/functional/ex_cmds/swapfile_preserve_recover_spec.lua3
-rw-r--r--test/functional/insert/ctrl_o_spec.lua3
-rw-r--r--test/functional/legacy/assert_spec.lua65
-rw-r--r--test/functional/legacy/eval_spec.lua3
-rw-r--r--test/functional/lua/buffer_updates_spec.lua16
-rw-r--r--test/functional/lua/highlight_spec.lua25
-rw-r--r--test/functional/lua/luaeval_spec.lua22
-rw-r--r--test/functional/lua/vim_spec.lua19
-rw-r--r--test/functional/options/defaults_spec.lua28
-rw-r--r--test/functional/options/tabstop_spec.lua5
-rw-r--r--test/functional/plugin/lsp_spec.lua78
-rw-r--r--test/functional/provider/clipboard_spec.lua2
-rw-r--r--test/functional/provider/python3_spec.lua3
-rw-r--r--test/functional/provider/ruby_spec.lua4
-rw-r--r--test/functional/shada/history_spec.lua4
-rw-r--r--test/functional/terminal/buffer_spec.lua23
-rw-r--r--test/functional/terminal/ex_terminal_spec.lua3
-rw-r--r--test/functional/terminal/tui_spec.lua4
-rw-r--r--test/functional/terminal/window_split_tab_spec.lua3
-rw-r--r--test/functional/ui/cursor_spec.lua4
-rw-r--r--test/functional/ui/float_spec.lua2
-rw-r--r--test/functional/ui/highlight_spec.lua69
-rw-r--r--test/functional/ui/output_spec.lua6
-rw-r--r--test/functional/ui/popupmenu_spec.lua4
-rw-r--r--test/functional/viml/completion_spec.lua3
125 files changed, 6018 insertions, 2527 deletions
diff --git a/.git-blame-ignore-revs b/.git-blame-ignore-revs
new file mode 100644
index 0000000000..00e7c7f3a5
--- /dev/null
+++ b/.git-blame-ignore-revs
@@ -0,0 +1,11 @@
+# To use this file (requires git 2.23):
+# git config blame.ignoreRevsFile .git-blame-ignore-revs
+
+# eval.c: factor out eval/funcs.c #11828
+# - This is a move/rename. git 2.33 doesn't know how to ignore it.
+# It is here anyway, (1) in case git improves later, and (2) to
+# save you the trouble of attempting this.
+6c5bbf07d988ef55e5e8ba8d70b62c1f0885261b
+
+# style / uncrustify
+2d240024acbd68c2d3f82bc72cb12b1a4928c6bf
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index da222bbc90..4d93c979ed 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -183,20 +183,21 @@ master build. To view the defects, just request access; you will be approved.
```
git log --oneline --no-merges --grep coverity
```
-
+
### Clang sanitizers (ASAN and UBSAN)
ASAN/UBSAN can be used to detect memory errors and other common forms of undefined behavior at runtime in debug builds.
- To build neovim with sanitizers enabled, use
+
+- To build Neovim with sanitizers enabled, use
```
rm -rf build && CMAKE_EXTRA_FLAGS="-DCMAKE_C_COMPILER=clang -DCLANG_ASAN_UBSAN=1" make
```
- When running neovim, use
+- When running Neovim, use
```
UBSAN_OPTIONS=print_stacktrace=1 ASAN_OPTIONS=log_path=/tmp/nvim_asan nvim args...
```
- If neovim exits unexpectedly, check `/tmp/nvim_asan.{PID}` (or your preferred `log_path`) for log files with error messages.
-
+- If Neovim exits unexpectedly, check `/tmp/nvim_asan.{PID}` (or your preferred `log_path`) for log files with error messages.
+
Coding
------
@@ -226,6 +227,10 @@ operator in Nvim:
### Navigate
+- Set `blame.ignoreRevsFile` to ignore [noise commits](https://github.com/neovim/neovim/commit/2d240024acbd68c2d3f82bc72cb12b1a4928c6bf) in git blame:
+ ```
+ git config blame.ignoreRevsFile .git-blame-ignore-revs
+ ```
- Use **[universal-ctags](https://github.com/universal-ctags/ctags).**
("Exuberant ctags", the typical `ctags` binary provided by your distro, is
unmaintained and won't recognize many function signatures in Neovim source.)
diff --git a/README.md b/README.md
index ba8e7bff37..8342c27fd7 100644
--- a/README.md
+++ b/README.md
@@ -4,7 +4,7 @@
[Chat](https://app.element.io/#/room/#neovim:matrix.org) |
[Twitter](https://twitter.com/Neovim)
-[![GitHub CI](https://github.com/neovim/neovim/workflows/CI/badge.svg)](https://github.com/neovim/neovim/actions?query=workflow%3A%22CI%22)
+[![GitHub CI](https://github.com/neovim/neovim/workflows/CI/badge.svg)](https://github.com/neovim/neovim/actions?query=workflow%3ACI+branch%3Amaster+event%3Apush)
[![Codecov coverage](https://img.shields.io/codecov/c/github/neovim/neovim.svg)](https://codecov.io/gh/neovim/neovim)
[![Coverity Scan analysis](https://scan.coverity.com/projects/2227/badge.svg)](https://scan.coverity.com/projects/2227)
[![Clang analysis](https://neovim.io/doc/reports/clang/badge.svg)](https://neovim.io/doc/reports/clang)
diff --git a/contrib/flake.lock b/contrib/flake.lock
index b9e074db52..c4d7f120ba 100644
--- a/contrib/flake.lock
+++ b/contrib/flake.lock
@@ -2,11 +2,11 @@
"nodes": {
"flake-utils": {
"locked": {
- "lastModified": 1623875721,
- "narHash": "sha256-A8BU7bjS5GirpAUv4QA+QnJ4CceLHkcXdRp4xITDB0s=",
+ "lastModified": 1629481132,
+ "narHash": "sha256-JHgasjPR0/J1J3DRm4KxM4zTyAj4IOJY8vIl75v/kPI=",
"owner": "numtide",
"repo": "flake-utils",
- "rev": "f7e004a55b120c02ecb6219596820fcd32ca8772",
+ "rev": "997f7efcb746a9c140ce1f13c72263189225f482",
"type": "github"
},
"original": {
@@ -17,11 +17,11 @@
},
"nixpkgs": {
"locked": {
- "lastModified": 1625697353,
- "narHash": "sha256-/v85RkZ0Z+lxipkG2sjYNRINktc8VySbLQmPbirY0hQ=",
+ "lastModified": 1630074300,
+ "narHash": "sha256-BFM7OiXRs0RvSUZd6NCGAKWVPn3VodgYQ4TUQXxbMBU=",
"owner": "nixos",
"repo": "nixpkgs",
- "rev": "87807e64a5ef5206b745a40af118c7be8db73681",
+ "rev": "21c937f8cb1e6adcfeb36dfd6c90d9d9bfab1d28",
"type": "github"
},
"original": {
diff --git a/contrib/flake.nix b/contrib/flake.nix
index d07067a7a1..848c52d208 100644
--- a/contrib/flake.nix
+++ b/contrib/flake.nix
@@ -20,12 +20,16 @@
# a development binary to help debug issues
neovim-debug = let
- stdenv = pkgs.stdenvAdapters.keepDebugInfo (if pkgs.stdenv.isLinux then pkgs.llvmPackages_latest.stdenv else pkgs.stdenv);
+ stdenv = if pkgs.stdenv.isLinux then pkgs.llvmPackages_latest.stdenv else pkgs.stdenv;
in
- pkgs.enableDebugging ((neovim.override {
- lua = pkgs.enableDebugging pkgs.luajit;
+ ((neovim.override {
+ lua = pkgs.luajit;
inherit stdenv;
}).overrideAttrs (oa: {
+
+ dontStrip = true;
+ NIX_CFLAGS_COMPILE = " -ggdb -Og";
+
cmakeBuildType = "Debug";
cmakeFlags = oa.cmakeFlags ++ [
"-DMIN_LOG_LEVEL=0"
diff --git a/contrib/uncrustify.cfg b/contrib/uncrustify.cfg
index 11da34d59a..8dbd752d05 100644
--- a/contrib/uncrustify.cfg
+++ b/contrib/uncrustify.cfg
@@ -1,1578 +1,3283 @@
-# Uncrustify 0.60
+# Uncrustify_d-0.73.0-159-81b1bc77
#
# General options
#
-# The type of line endings
-newlines = auto # auto/lf/crlf/cr
+# The type of line endings.
+#
+# Default: auto
+newlines = auto # lf/crlf/cr/auto
-# The original size of tabs in the input
-input_tab_size = 8 # number
+# The original size of tabs in the input.
+#
+# Default: 8
+input_tab_size = 8 # unsigned number
-# The size of tabs in the output (only used if align_with_tabs=true)
-output_tab_size = 8 # number
+# The size of tabs in the output (only used if align_with_tabs=true).
+#
+# Default: 8
+output_tab_size = 8 # unsigned number
+
+# The ASCII value of the string escape char, usually 92 (\) or (Pawn) 94 (^).
+#
+# Default: 92
+string_escape_char = 92 # unsigned number
-# The ASCII value of the string escape char, usually 92 (\) or 94 (^). (Pawn)
-string_escape_char = 92 # number
+# Alternate string escape char (usually only used for Pawn).
+# Only works right before the quote char.
+string_escape_char2 = 0 # unsigned number
-# Alternate string escape char for Pawn. Only works right before the quote char.
-string_escape_char2 = 0 # number
+# Replace tab characters found in string literals with the escape sequence \t
+# instead.
+string_replace_tab_chars = false # true/false
-# Allow interpreting '>=' and '>>=' as part of a template in 'void f(list<list<B>>=val);'.
-# If true (default), 'assert(x<0 && y>=3)' will be broken.
+# Allow interpreting '>=' and '>>=' as part of a template in code like
+# 'void f(list<list<B>>=val);'. If true, 'assert(x<0 && y>=3)' will be broken.
# Improvements to template detection may make this option obsolete.
-tok_split_gte = false # false/true
+tok_split_gte = false # true/false
-# Control what to do with the UTF-8 BOM (recommend 'remove')
-utf8_bom = ignore # ignore/add/remove/force
+# Disable formatting of NL_CONT ('\\n') ended lines (e.g. multi-line macros).
+disable_processing_nl_cont = false # true/false
+
+# Specify the marker used in comments to disable processing of part of the
+# file.
+#
+# Default: *INDENT-OFF*
+disable_processing_cmt = " *INDENT-OFF*" # string
+
+# Specify the marker used in comments to (re)enable processing in a file.
+#
+# Default: *INDENT-ON*
+enable_processing_cmt = " *INDENT-ON*" # string
-# If the file contains bytes with values between 128 and 255, but is not UTF-8, then output as UTF-8
-utf8_byte = false # false/true
+# Enable parsing of digraphs.
+enable_digraphs = false # true/false
-# Force the output encoding to UTF-8
-utf8_force = false # false/true
+# Option to allow both disable_processing_cmt and enable_processing_cmt
+# strings, if specified, to be interpreted as ECMAScript regular expressions.
+# If true, a regex search will be performed within comments according to the
+# specified patterns in order to disable/enable processing.
+processing_cmt_as_regex = false # true/false
+
+# Add or remove the UTF-8 BOM (recommend 'remove').
+utf8_bom = remove # ignore/add/remove/force/not_defined
+
+# If the file contains bytes with values between 128 and 255, but is not
+# UTF-8, then output as UTF-8.
+utf8_byte = false # true/false
+
+# Force the output encoding to UTF-8.
+utf8_force = false # true/false
#
-# Indenting
+# Spacing options
#
-# The number of columns to indent per level.
-# Usually 2, 3, 4, or 8.
-indent_columns = 2 # number
+# Add or remove space around non-assignment symbolic operators ('+', '/', '%',
+# '<<', and so forth).
+sp_arith = ignore # ignore/add/remove/force/not_defined
-# The continuation indent. If non-zero, this overrides the indent of '(' and '=' continuation indents.
-# For FreeBSD, this is set to 4. Negative value is absolute and not increased for each ( level
-indent_continue = 0 # number
+# Add or remove space around arithmetic operators '+' and '-'.
+#
+# Overrides sp_arith.
+sp_arith_additive = ignore # ignore/add/remove/force/not_defined
-# How to use tabs when indenting code
-# 0=spaces only
-# 1=indent with tabs to brace level, align with spaces
-# 2=indent and align with tabs, using spaces when not on a tabstop
-indent_with_tabs = 0 # number
+# Add or remove space around assignment operator '=', '+=', etc.
+sp_assign = ignore # ignore/add/remove/force/not_defined
-# Comments that are not a brace level are indented with tabs on a tabstop.
-# Requires indent_with_tabs=2. If false, will use spaces.
-indent_cmt_with_tabs = false # false/true
+# Add or remove space around '=' in C++11 lambda capture specifications.
+#
+# Overrides sp_assign.
+sp_cpp_lambda_assign = ignore # ignore/add/remove/force/not_defined
-# Whether to indent strings broken by '\' so that they line up
-indent_align_string = true # false/true
+# Add or remove space after the capture specification of a C++11 lambda when
+# an argument list is present, as in '[] <here> (int x){ ... }'.
+sp_cpp_lambda_square_paren = ignore # ignore/add/remove/force/not_defined
-# The number of spaces to indent multi-line XML strings.
-# Requires indent_align_string=True
-indent_xml_string = 0 # number
+# Add or remove space after the capture specification of a C++11 lambda with
+# no argument list is present, as in '[] <here> { ... }'.
+sp_cpp_lambda_square_brace = ignore # ignore/add/remove/force/not_defined
-# Spaces to indent '{' from level
-indent_brace = 0 # number
+# Add or remove space after the opening parenthesis and before the closing
+# parenthesis of a argument list of a C++11 lambda, as in
+# '[]( <here> int x <here> ){ ... }'.
+sp_cpp_lambda_argument_list = ignore # ignore/add/remove/force/not_defined
-# Whether braces are indented to the body level
-indent_braces = false # false/true
+# Add or remove space after the argument list of a C++11 lambda, as in
+# '[](int x) <here> { ... }'.
+sp_cpp_lambda_paren_brace = ignore # ignore/add/remove/force/not_defined
-# Disabled indenting function braces if indent_braces is true
-indent_braces_no_func = false # false/true
+# Add or remove space between a lambda body and its call operator of an
+# immediately invoked lambda, as in '[]( ... ){ ... } <here> ( ... )'.
+sp_cpp_lambda_fparen = ignore # ignore/add/remove/force/not_defined
-# Disabled indenting class braces if indent_braces is true
-indent_braces_no_class = false # false/true
+# Add or remove space around assignment operator '=' in a prototype.
+#
+# If set to ignore, use sp_assign.
+sp_assign_default = ignore # ignore/add/remove/force/not_defined
-# Disabled indenting struct braces if indent_braces is true
-indent_braces_no_struct = false # false/true
+# Add or remove space before assignment operator '=', '+=', etc.
+#
+# Overrides sp_assign.
+sp_before_assign = ignore # ignore/add/remove/force/not_defined
-# Indent based on the size of the brace parent, i.e. 'if' => 3 spaces, 'for' => 4 spaces, etc.
-indent_brace_parent = false # false/true
+# Add or remove space after assignment operator '=', '+=', etc.
+#
+# Overrides sp_assign.
+sp_after_assign = ignore # ignore/add/remove/force/not_defined
-# Whether the 'namespace' body is indented
-indent_namespace = false # false/true
+# Add or remove space in 'NS_ENUM ('.
+sp_enum_paren = ignore # ignore/add/remove/force/not_defined
-# The number of spaces to indent a namespace block
-indent_namespace_level = 0 # number
+# Add or remove space around assignment '=' in enum.
+sp_enum_assign = ignore # ignore/add/remove/force/not_defined
-# If the body of the namespace is longer than this number, it won't be indented.
-# Requires indent_namespace=true. Default=0 (no limit)
-indent_namespace_limit = 0 # number
+# Add or remove space before assignment '=' in enum.
+#
+# Overrides sp_enum_assign.
+sp_enum_before_assign = ignore # ignore/add/remove/force/not_defined
-# Whether the 'extern "C"' body is indented
-indent_extern = false # false/true
+# Add or remove space after assignment '=' in enum.
+#
+# Overrides sp_enum_assign.
+sp_enum_after_assign = ignore # ignore/add/remove/force/not_defined
-# Whether the 'class' body is indented
-indent_class = true # false/true
+# Add or remove space around assignment ':' in enum.
+sp_enum_colon = ignore # ignore/add/remove/force/not_defined
-# Whether to indent the stuff after a leading class colon
-indent_class_colon = true # false/true
+# Add or remove space around preprocessor '##' concatenation operator.
+#
+# Default: add
+sp_pp_concat = ignore # ignore/add/remove/force/not_defined
-# Virtual indent from the ':' for member initializers. Default is 2
-indent_ctor_init_leading = 2 # number
+# Add or remove space after preprocessor '#' stringify operator.
+# Also affects the '#@' charizing operator.
+sp_pp_stringify = ignore # ignore/add/remove/force/not_defined
-# Additional indenting for constructor initializer list
-indent_ctor_init = 0 # number
+# Add or remove space before preprocessor '#' stringify operator
+# as in '#define x(y) L#y'.
+sp_before_pp_stringify = ignore # ignore/add/remove/force/not_defined
-# False=treat 'else\nif' as 'else if' for indenting purposes
-# True=indent the 'if' one level
-indent_else_if = false # false/true
+# Add or remove space around boolean operators '&&' and '||'.
+sp_bool = ignore # ignore/add/remove/force/not_defined
-# Amount to indent variable declarations after an open brace. neg=relative, pos=absolute
-indent_var_def_blk = 0 # number
+# Add or remove space around compare operator '<', '>', '==', etc.
+sp_compare = ignore # ignore/add/remove/force/not_defined
-# Indent continued variable declarations instead of aligning.
-indent_var_def_cont = false # false/true
+# Add or remove space inside '(' and ')'.
+sp_inside_paren = ignore # ignore/add/remove/force/not_defined
-# True: force indentation of function definition to start in column 1
-# False: use the default behavior
-indent_func_def_force_col1 = false # false/true
+# Add or remove space between nested parentheses, i.e. '((' vs. ') )'.
+sp_paren_paren = ignore # ignore/add/remove/force/not_defined
-# True: indent continued function call parameters one indent level
-# False: align parameters under the open paren
-indent_func_call_param = false # false/true
+# Add or remove space between back-to-back parentheses, i.e. ')(' vs. ') ('.
+sp_cparen_oparen = ignore # ignore/add/remove/force/not_defined
-# Same as indent_func_call_param, but for function defs
-indent_func_def_param = false # false/true
+# Whether to balance spaces inside nested parentheses.
+sp_balance_nested_parens = false # true/false
-# Same as indent_func_call_param, but for function protos
-indent_func_proto_param = false # false/true
+# Add or remove space between ')' and '{'.
+sp_paren_brace = ignore # ignore/add/remove/force/not_defined
-# Same as indent_func_call_param, but for class declarations
-indent_func_class_param = false # false/true
+# Add or remove space between nested braces, i.e. '{{' vs. '{ {'.
+sp_brace_brace = ignore # ignore/add/remove/force/not_defined
-# Same as indent_func_call_param, but for class variable constructors
-indent_func_ctor_var_param = false # false/true
+# Add or remove space before pointer star '*'.
+sp_before_ptr_star = ignore # ignore/add/remove/force/not_defined
-# Same as indent_func_call_param, but for templates
-indent_template_param = false # false/true
+# Add or remove space before pointer star '*' that isn't followed by a
+# variable name. If set to ignore, sp_before_ptr_star is used instead.
+sp_before_unnamed_ptr_star = ignore # ignore/add/remove/force/not_defined
-# Double the indent for indent_func_xxx_param options
-indent_func_param_double = false # false/true
+# Add or remove space between pointer stars '*', as in 'int ***a;'.
+sp_between_ptr_star = ignore # ignore/add/remove/force/not_defined
-# Indentation column for standalone 'const' function decl/proto qualifier
-indent_func_const = 0 # number
+# Add or remove space after pointer star '*', if followed by a word.
+#
+# Overrides sp_type_func.
+sp_after_ptr_star = ignore # ignore/add/remove/force/not_defined
-# Indentation column for standalone 'throw' function decl/proto qualifier
-indent_func_throw = 0 # number
+# Add or remove space after pointer caret '^', if followed by a word.
+sp_after_ptr_block_caret = ignore # ignore/add/remove/force/not_defined
-# The number of spaces to indent a continued '->' or '.'
-# Usually set to 0, 1, or indent_columns.
-indent_member = 0 # number
+# Add or remove space after pointer star '*', if followed by a qualifier.
+sp_after_ptr_star_qualifier = ignore # ignore/add/remove/force/not_defined
-# Spaces to indent single line ('//') comments on lines before code
-indent_sing_line_comments = 0 # number
+# Add or remove space after a pointer star '*', if followed by a function
+# prototype or function definition.
+#
+# Overrides sp_after_ptr_star and sp_type_func.
+sp_after_ptr_star_func = ignore # ignore/add/remove/force/not_defined
-# If set, will indent trailing single line ('//') comments relative
-# to the code instead of trying to keep the same absolute column
-indent_relative_single_line_comments = false # false/true
+# Add or remove space after a pointer star '*' in the trailing return of a
+# function prototype or function definition.
+sp_after_ptr_star_trailing = ignore # ignore/add/remove/force/not_defined
-# Spaces to indent 'case' from 'switch'
-# Usually 0 or indent_columns.
-indent_switch_case = 0 # number
+# Add or remove space after a pointer star '*', if followed by an open
+# parenthesis, as in 'void* (*)()'.
+sp_ptr_star_paren = ignore # ignore/add/remove/force/not_defined
-# Spaces to shift the 'case' line, without affecting any other lines
-# Usually 0.
-indent_case_shift = 0 # number
+# Add or remove space before a pointer star '*', if followed by a function
+# prototype or function definition.
+sp_before_ptr_star_func = ignore # ignore/add/remove/force/not_defined
-# Spaces to indent '{' from 'case'.
-# By default, the brace will appear under the 'c' in case.
-# Usually set to 0 or indent_columns.
-indent_case_brace = 0 # number
+# Add or remove space before a pointer star '*' in the trailing return of a
+# function prototype or function definition.
+sp_before_ptr_star_trailing = ignore # ignore/add/remove/force/not_defined
-# Whether to indent comments found in first column
-indent_col1_comment = true # false/true
+# Add or remove space before a reference sign '&'.
+sp_before_byref = ignore # ignore/add/remove/force/not_defined
-# How to indent goto labels
-# >0 : absolute column where 1 is the leftmost column
-# <=0 : subtract from brace indent
-indent_label = 0 # number
+# Add or remove space before a reference sign '&' that isn't followed by a
+# variable name. If set to ignore, sp_before_byref is used instead.
+sp_before_unnamed_byref = ignore # ignore/add/remove/force/not_defined
-# Same as indent_label, but for access specifiers that are followed by a colon
-indent_access_spec = 1 # number
+# Add or remove space after reference sign '&', if followed by a word.
+#
+# Overrides sp_type_func.
+sp_after_byref = ignore # ignore/add/remove/force/not_defined
-# Indent the code after an access specifier by one level.
-# If set, this option forces 'indent_access_spec=0'
-indent_access_spec_body = false # false/true
+# Add or remove space after a reference sign '&', if followed by a function
+# prototype or function definition.
+#
+# Overrides sp_after_byref and sp_type_func.
+sp_after_byref_func = ignore # ignore/add/remove/force/not_defined
-# If an open paren is followed by a newline, indent the next line so that it lines up after the open paren (not recommended)
-indent_paren_nl = false # false/true
+# Add or remove space before a reference sign '&', if followed by a function
+# prototype or function definition.
+sp_before_byref_func = ignore # ignore/add/remove/force/not_defined
-# Controls the indent of a close paren after a newline.
-# 0: Indent to body level
-# 1: Align under the open paren
-# 2: Indent to the brace level
-indent_paren_close = 0 # number
+# Add or remove space between type and word. In cases where total removal of
+# whitespace would be a syntax error, a value of 'remove' is treated the same
+# as 'force'.
+#
+# This also affects some other instances of space following a type that are
+# not covered by other options; for example, between the return type and
+# parenthesis of a function type template argument, between the type and
+# parenthesis of an array parameter, or between 'decltype(...)' and the
+# following word.
+#
+# Default: force
+sp_after_type = ignore # ignore/add/remove/force/not_defined
-# Controls the indent of a comma when inside a paren.If TRUE, aligns under the open paren
-indent_comma_paren = false # false/true
+# Add or remove space between 'decltype(...)' and word,
+# brace or function call.
+sp_after_decltype = ignore # ignore/add/remove/force/not_defined
-# Controls the indent of a BOOL operator when inside a paren.If TRUE, aligns under the open paren
-indent_bool_paren = false # false/true
+# (D) Add or remove space before the parenthesis in the D constructs
+# 'template Foo(' and 'class Foo('.
+sp_before_template_paren = ignore # ignore/add/remove/force/not_defined
-# If 'indent_bool_paren' is true, controls the indent of the first expression. If TRUE, aligns the first expression to the following ones
-indent_first_bool_expr = false # false/true
+# Add or remove space between 'template' and '<'.
+# If set to ignore, sp_before_angle is used.
+sp_template_angle = ignore # ignore/add/remove/force/not_defined
-# If an open square is followed by a newline, indent the next line so that it lines up after the open square (not recommended)
-indent_square_nl = false # false/true
+# Add or remove space before '<'.
+sp_before_angle = ignore # ignore/add/remove/force/not_defined
-# Don't change the relative indent of ESQL/C 'EXEC SQL' bodies
-indent_preserve_sql = false # false/true
+# Add or remove space inside '<' and '>'.
+sp_inside_angle = ignore # ignore/add/remove/force/not_defined
-# Align continued statements at the '='. Default=True
-# If FALSE or the '=' is followed by a newline, the next line is indent one tab.
-indent_align_assign = true # false/true
+# Add or remove space inside '<>'.
+sp_inside_angle_empty = ignore # ignore/add/remove/force/not_defined
-# Indent OC blocks at brace level instead of usual rules.
-indent_oc_block = false # false/true
+# Add or remove space between '>' and ':'.
+sp_angle_colon = ignore # ignore/add/remove/force/not_defined
-# Indent OC blocks in a message relative to the parameter name.
-# 0=use indent_oc_block rules, 1+=spaces to indent
-indent_oc_block_msg = 0 # number
+# Add or remove space after '>'.
+sp_after_angle = ignore # ignore/add/remove/force/not_defined
-# Minimum indent for subsequent parameters
-indent_oc_msg_colon = 0 # number
+# Add or remove space between '>' and '(' as found in 'new List<byte>(foo);'.
+sp_angle_paren = ignore # ignore/add/remove/force/not_defined
+# Add or remove space between '>' and '()' as found in 'new List<byte>();'.
+sp_angle_paren_empty = ignore # ignore/add/remove/force/not_defined
+
+# Add or remove space between '>' and a word as in 'List<byte> m;' or
+# 'template <typename T> static ...'.
+sp_angle_word = ignore # ignore/add/remove/force/not_defined
+
+# Add or remove space between '>' and '>' in '>>' (template stuff).
#
-# Spacing options
-#
+# Default: add
+sp_angle_shift = ignore # ignore/add/remove/force/not_defined
-# Add or remove space around arithmetic operator '+', '-', '/', '*', etc
-sp_arith = add # ignore/add/remove/force
+# (C++11) Permit removal of the space between '>>' in 'foo<bar<int> >'. Note
+# that sp_angle_shift cannot remove the space without this option.
+sp_permit_cpp11_shift = false # true/false
-# Add or remove space around assignment operator '=', '+=', etc
-sp_assign = add # ignore/add/remove/force
+# Add or remove space before '(' of control statements ('if', 'for', 'switch',
+# 'while', etc.).
+sp_before_sparen = ignore # ignore/add/remove/force/not_defined
-# Add or remove space around '=' in C++11 lambda capture specifications. Overrides sp_assign
-sp_cpp_lambda_assign = ignore # ignore/add/remove/force
+# Add or remove space inside '(' and ')' of control statements.
+sp_inside_sparen = ignore # ignore/add/remove/force/not_defined
-# Add or remove space after the capture specification in C++11 lambda.
-sp_cpp_lambda_paren = ignore # ignore/add/remove/force
+# Add or remove space after '(' of control statements.
+#
+# Overrides sp_inside_sparen.
+sp_inside_sparen_open = remove # ignore/add/remove/force/not_defined
-# Add or remove space around assignment operator '=' in a prototype
-sp_assign_default = ignore # ignore/add/remove/force
+# Add or remove space before ')' of control statements.
+#
+# Overrides sp_inside_sparen.
+sp_inside_sparen_close = ignore # ignore/add/remove/force/not_defined
-# Add or remove space before assignment operator '=', '+=', etc. Overrides sp_assign.
-sp_before_assign = ignore # ignore/add/remove/force
+# Add or remove space between '((' or '))' of control statements.
+sp_sparen_paren = ignore # ignore/add/remove/force/not_defined
-# Add or remove space after assignment operator '=', '+=', etc. Overrides sp_assign.
-sp_after_assign = ignore # ignore/add/remove/force
+# Add or remove space after ')' of control statements.
+sp_after_sparen = ignore # ignore/add/remove/force/not_defined
-# Add or remove space around assignment '=' in enum
-sp_enum_assign = add # ignore/add/remove/force
+# Add or remove space between ')' and '{' of control statements.
+sp_sparen_brace = ignore # ignore/add/remove/force/not_defined
-# Add or remove space before assignment '=' in enum. Overrides sp_enum_assign.
-sp_enum_before_assign = ignore # ignore/add/remove/force
+# Add or remove space between 'do' and '{'.
+sp_do_brace_open = 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
+# Add or remove space between '}' and 'while'.
+sp_brace_close_while = ignore # ignore/add/remove/force/not_defined
-# Add or remove space around preprocessor '##' concatenation operator. Default=Add
-sp_pp_concat = add # ignore/add/remove/force
+# Add or remove space between 'while' and '('. Overrides sp_before_sparen.
+sp_while_paren_open = ignore # ignore/add/remove/force/not_defined
-# Add or remove space after preprocessor '#' stringify operator. Also affects the '#@' charizing operator.
-sp_pp_stringify = add # ignore/add/remove/force
+# (D) Add or remove space between 'invariant' and '('.
+sp_invariant_paren = ignore # ignore/add/remove/force/not_defined
-# Add or remove space before preprocessor '#' stringify operator as in '#define x(y) L#y'.
-sp_before_pp_stringify = ignore # ignore/add/remove/force
+# (D) Add or remove space after the ')' in 'invariant (C) c'.
+sp_after_invariant_paren = ignore # ignore/add/remove/force/not_defined
-# Add or remove space around boolean operators '&&' and '||'
-sp_bool = add # ignore/add/remove/force
+# Add or remove space before empty statement ';' on 'if', 'for' and 'while'.
+sp_special_semi = ignore # ignore/add/remove/force/not_defined
-# Add or remove space around compare operator '<', '>', '==', etc
-sp_compare = add # ignore/add/remove/force
+# Add or remove space before ';'.
+#
+# Default: remove
+sp_before_semi = ignore # ignore/add/remove/force/not_defined
-# Add or remove space inside '(' and ')'
-sp_inside_paren = remove # ignore/add/remove/force
+# Add or remove space before ';' in non-empty 'for' statements.
+sp_before_semi_for = ignore # ignore/add/remove/force/not_defined
-# Add or remove space between nested parens
-sp_paren_paren = remove # ignore/add/remove/force
+# 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
-# Whether to balance spaces inside nested parens
-sp_balance_nested_parens = false # false/true
+# 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
-# Add or remove space between ')' and '{'
-sp_paren_brace = add # ignore/add/remove/force
+# Add or remove space after ';', except when followed by a comment.
+#
+# Default: add
+sp_after_semi = ignore # ignore/add/remove/force/not_defined
-# Add or remove space before pointer star '*'
-sp_before_ptr_star = add # ignore/add/remove/force
+# Add or remove space after ';' in non-empty 'for' statements.
+#
+# Default: force
+sp_after_semi_for = ignore # ignore/add/remove/force/not_defined
-# Add or remove space before pointer star '*' that isn't followed by a variable name
-# If set to 'ignore', sp_before_ptr_star is used instead.
-sp_before_unnamed_ptr_star = add # ignore/add/remove/force
+# 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
-# Add or remove space between pointer stars '*'
-sp_between_ptr_star = remove # ignore/add/remove/force
+# Add or remove space before '[' (except '[]').
+sp_before_square = ignore # ignore/add/remove/force/not_defined
-# Add or remove space after pointer star '*', if followed by a word.
-sp_after_ptr_star = remove # ignore/add/remove/force
+# Add or remove space before '[' for a variable definition.
+#
+# Default: remove
+sp_before_vardef_square = ignore # ignore/add/remove/force/not_defined
-# Add or remove space after a pointer star '*', if followed by a func proto/def.
-sp_after_ptr_star_func = add # ignore/add/remove/force
+# Add or remove space before '[' for asm block.
+sp_before_square_asm_block = ignore # ignore/add/remove/force/not_defined
-# Add or remove space after a pointer star '*', if followed by an open paren (function types).
-sp_ptr_star_paren = ignore # ignore/add/remove/force
+# Add or remove space before '[]'.
+sp_before_squares = ignore # ignore/add/remove/force/not_defined
-# Add or remove space before a pointer star '*', if followed by a func proto/def.
-sp_before_ptr_star_func = remove # ignore/add/remove/force
+# 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 before a reference sign '&'
-sp_before_byref = remove # ignore/add/remove/force
+# Add or remove space inside a non-empty '[' and ']'.
+sp_inside_square = ignore # ignore/add/remove/force/not_defined
-# Add or remove space before a reference sign '&' that isn't followed by a variable name
-# If set to 'ignore', sp_before_byref is used instead.
-sp_before_unnamed_byref = remove # ignore/add/remove/force
+# Add or remove space inside '[]'.
+sp_inside_square_empty = ignore # ignore/add/remove/force/not_defined
-# Add or remove space after reference sign '&', if followed by a word.
-sp_after_byref = add # ignore/add/remove/force
+# (OC) Add or remove space inside a non-empty Objective-C boxed array '@[' and
+# ']'. If set to ignore, sp_inside_square is used.
+sp_inside_square_oc_array = ignore # ignore/add/remove/force/not_defined
-# Add or remove space after a reference sign '&', if followed by a func proto/def.
-sp_after_byref_func = add # ignore/add/remove/force
+# Add or remove space after ',', i.e. 'a,b' vs. 'a, b'.
+sp_after_comma = add # ignore/add/remove/force/not_defined
-# Add or remove space before a reference sign '&', if followed by a func proto/def.
-sp_before_byref_func = remove # ignore/add/remove/force
+# Add or remove space before ',', i.e. 'a,b' vs. 'a ,b'.
+#
+# Default: remove
+sp_before_comma = remove # ignore/add/remove/force/not_defined
-# Add or remove space between type and word. Default=Force
-sp_after_type = add # ignore/add/remove/force
+# (C#) Add or remove space between ',' and ']' in multidimensional array type
+# like 'int[,,]'.
+sp_after_mdatype_commas = ignore # ignore/add/remove/force/not_defined
-# Add or remove space before the paren in the D constructs 'template Foo(' and 'class Foo('.
-sp_before_template_paren = ignore # ignore/add/remove/force
+# (C#) Add or remove space between '[' and ',' in multidimensional array type
+# like 'int[,,]'.
+sp_before_mdatype_commas = ignore # ignore/add/remove/force/not_defined
-# Add or remove space in 'template <' vs 'template<'.
-# If set to ignore, sp_before_angle is used.
-sp_template_angle = ignore # ignore/add/remove/force
+# (C#) Add or remove space between ',' in multidimensional array type
+# like 'int[,,]'.
+sp_between_mdatype_commas = ignore # ignore/add/remove/force/not_defined
-# Add or remove space before '<>'
-sp_before_angle = remove # ignore/add/remove/force
+# Add or remove space between an open parenthesis and comma,
+# i.e. '(,' vs. '( ,'.
+#
+# Default: force
+sp_paren_comma = ignore # ignore/add/remove/force/not_defined
-# Add or remove space inside '<' and '>'
-sp_inside_angle = remove # ignore/add/remove/force
+# Add or remove space after the variadic '...' when preceded by a
+# non-punctuator.
+# The value REMOVE will be overriden with FORCE
+sp_after_ellipsis = ignore # ignore/add/remove/force/not_defined
-# Add or remove space after '<>'
-sp_after_angle = remove # ignore/add/remove/force
+# Add or remove space before the variadic '...' when preceded by a
+# non-punctuator.
+# The value REMOVE will be overriden with FORCE
+sp_before_ellipsis = ignore # ignore/add/remove/force/not_defined
-# Add or remove space between '<>' and '(' as found in 'new List<byte>();'
-sp_angle_paren = remove # ignore/add/remove/force
+# Add or remove space between a type and '...'.
+sp_type_ellipsis = ignore # ignore/add/remove/force/not_defined
-# Add or remove space between '<>' and a word as in 'List<byte> m;'
-sp_angle_word = remove # ignore/add/remove/force
+# (D) Add or remove space between a type and '?'.
+sp_type_question = ignore # ignore/add/remove/force/not_defined
-# Add or remove space between '>' and '>' in '>>' (template stuff C++/C# only). Default=Add
-sp_angle_shift = add # ignore/add/remove/force
+# Add or remove space between ')' and '...'.
+sp_paren_ellipsis = ignore # ignore/add/remove/force/not_defined
-# Permit removal of the space between '>>' in 'foo<bar<int> >' (C++11 only). Default=False
-# sp_angle_shift cannot remove the space without this option.
-sp_permit_cpp11_shift = false # false/true
+# Add or remove space between ')' and a qualifier such as 'const'.
+sp_paren_qualifier = ignore # ignore/add/remove/force/not_defined
-# Add or remove space before '(' of 'if', 'for', 'switch', and 'while'
-sp_before_sparen = add # ignore/add/remove/force
+# Add or remove space between ')' and 'noexcept'.
+sp_paren_noexcept = ignore # ignore/add/remove/force/not_defined
-# Add or remove space inside if-condition '(' and ')'
-sp_inside_sparen = remove # ignore/add/remove/force
+# Add or remove space after class ':'.
+sp_after_class_colon = ignore # ignore/add/remove/force/not_defined
-# Add or remove space before if-condition ')'. Overrides sp_inside_sparen.
-sp_inside_sparen_close = ignore # ignore/add/remove/force
+# Add or remove space before class ':'.
+sp_before_class_colon = ignore # ignore/add/remove/force/not_defined
-# Add or remove space before if-condition '('. Overrides sp_inside_sparen.
-sp_inside_sparen_open = ignore # ignore/add/remove/force
+# Add or remove space after class constructor ':'.
+sp_after_constr_colon = ignore # ignore/add/remove/force/not_defined
-# Add or remove space after ')' of 'if', 'for', 'switch', and 'while'
-sp_after_sparen = ignore # ignore/add/remove/force
+# Add or remove space before class constructor ':'.
+sp_before_constr_colon = ignore # ignore/add/remove/force/not_defined
-# Add or remove space between ')' and '{' of 'if', 'for', 'switch', and 'while'
-sp_sparen_brace = add # ignore/add/remove/force
+# Add or remove space before case ':'.
+#
+# Default: remove
+sp_before_case_colon = remove # ignore/add/remove/force/not_defined
-# Add or remove space between 'invariant' and '(' in the D language.
-sp_invariant_paren = ignore # ignore/add/remove/force
+# Add or remove space between 'operator' and operator sign.
+sp_after_operator = ignore # ignore/add/remove/force/not_defined
-# Add or remove space after the ')' in 'invariant (C) c' in the D language.
-sp_after_invariant_paren = ignore # ignore/add/remove/force
+# Add or remove space between the operator symbol and the open parenthesis, as
+# in 'operator ++('.
+sp_after_operator_sym = ignore # ignore/add/remove/force/not_defined
-# Add or remove space before empty statement ';' on 'if', 'for' and 'while'
-sp_special_semi = remove # ignore/add/remove/force
+# Overrides sp_after_operator_sym when the operator has no arguments, as in
+# 'operator *()'.
+sp_after_operator_sym_empty = ignore # ignore/add/remove/force/not_defined
-# Add or remove space before ';'. Default=Remove
-sp_before_semi = remove # ignore/add/remove/force
+# Add or remove space after C/D cast, i.e. 'cast(int)a' vs. 'cast(int) a' or
+# '(int)a' vs. '(int) a'.
+sp_after_cast = remove # ignore/add/remove/force/not_defined
-# Add or remove space before ';' in non-empty 'for' statements
-sp_before_semi_for = remove # ignore/add/remove/force
+# Add or remove spaces inside cast parentheses.
+sp_inside_paren_cast = ignore # ignore/add/remove/force/not_defined
-# Add or remove space before a semicolon of an empty part of a for statement.
-sp_before_semi_for_empty = remove # ignore/add/remove/force
+# Add or remove space between the type and open parenthesis in a C++ cast,
+# i.e. 'int(exp)' vs. 'int (exp)'.
+sp_cpp_cast_paren = ignore # ignore/add/remove/force/not_defined
-# Add or remove space after ';', except when followed by a comment. Default=Add
-sp_after_semi = add # ignore/add/remove/force
+# Add or remove space between 'sizeof' and '('.
+sp_sizeof_paren = ignore # ignore/add/remove/force/not_defined
-# Add or remove space after ';' in non-empty 'for' statements. Default=Force
-sp_after_semi_for = force # ignore/add/remove/force
+# Add or remove space between 'sizeof' and '...'.
+sp_sizeof_ellipsis = ignore # ignore/add/remove/force/not_defined
-# Add or remove space after the final semicolon of an empty part of a for statement: for ( ; ; <here> ).
-sp_after_semi_for_empty = remove # ignore/add/remove/force
+# Add or remove space between 'sizeof...' and '('.
+sp_sizeof_ellipsis_paren = ignore # ignore/add/remove/force/not_defined
-# Add or remove space before '[' (except '[]')
-sp_before_square = remove # ignore/add/remove/force
+# Add or remove space between 'decltype' and '('.
+sp_decltype_paren = ignore # ignore/add/remove/force/not_defined
-# Add or remove space before '[]'
-sp_before_squares = remove # ignore/add/remove/force
+# (Pawn) Add or remove space after the tag keyword.
+sp_after_tag = ignore # ignore/add/remove/force/not_defined
-# Add or remove space inside a non-empty '[' and ']'
-sp_inside_square = remove # ignore/add/remove/force
+# Add or remove space inside enum '{' and '}'.
+sp_inside_braces_enum = ignore # ignore/add/remove/force/not_defined
-# Add or remove space after ','
-sp_after_comma = add # ignore/add/remove/force
+# Add or remove space inside struct/union '{' and '}'.
+sp_inside_braces_struct = ignore # ignore/add/remove/force/not_defined
-# Add or remove space before ','
-sp_before_comma = remove # ignore/add/remove/force
+# (OC) Add or remove space inside Objective-C boxed dictionary '{' and '}'
+sp_inside_braces_oc_dict = ignore # ignore/add/remove/force/not_defined
-# Add or remove space between an open paren and comma: '(,' vs '( ,'
-sp_paren_comma = force # ignore/add/remove/force
+# Add or remove space after open brace in an unnamed temporary
+# direct-list-initialization.
+sp_after_type_brace_init_lst_open = ignore # ignore/add/remove/force/not_defined
-# Add or remove space before the variadic '...' when preceded by a non-punctuator
-sp_before_ellipsis = ignore # ignore/add/remove/force
+# Add or remove space before close brace in an unnamed temporary
+# direct-list-initialization.
+sp_before_type_brace_init_lst_close = ignore # ignore/add/remove/force/not_defined
-# Add or remove space after class ':'
-sp_after_class_colon = add # ignore/add/remove/force
+# Add or remove space inside an unnamed temporary direct-list-initialization.
+sp_inside_type_brace_init_lst = ignore # ignore/add/remove/force/not_defined
-# Add or remove space before class ':'
-sp_before_class_colon = add # ignore/add/remove/force
+# Add or remove space inside '{' and '}'.
+sp_inside_braces = add # ignore/add/remove/force/not_defined
-# Add or remove space before case ':'. Default=Remove
-sp_before_case_colon = remove # ignore/add/remove/force
+# Add or remove space inside '{}'.
+sp_inside_braces_empty = ignore # ignore/add/remove/force/not_defined
-# Add or remove space between 'operator' and operator sign
-sp_after_operator = remove # ignore/add/remove/force
+# Add or remove space around trailing return operator '->'.
+sp_trailing_return = ignore # ignore/add/remove/force/not_defined
-# Add or remove space between the operator symbol and the open paren, as in 'operator ++('
-sp_after_operator_sym = remove # ignore/add/remove/force
+# Add or remove space between return type and function name. A minimum of 1
+# is forced except for pointer return types.
+sp_type_func = ignore # ignore/add/remove/force/not_defined
-# Add or remove space after C/D cast, i.e. 'cast(int)a' vs 'cast(int) a' or '(int)a' vs '(int) a'
-sp_after_cast = remove # ignore/add/remove/force
+# Add or remove space between type and open brace of an unnamed temporary
+# direct-list-initialization.
+sp_type_brace_init_lst = ignore # ignore/add/remove/force/not_defined
-# Add or remove spaces inside cast parens
-sp_inside_paren_cast = remove # ignore/add/remove/force
+# Add or remove space between function name and '(' on function declaration.
+sp_func_proto_paren = ignore # ignore/add/remove/force/not_defined
-# Add or remove space between the type and open paren in a C++ cast, i.e. 'int(exp)' vs 'int (exp)'
-sp_cpp_cast_paren = remove # ignore/add/remove/force
+# Add or remove space between function name and '()' on function declaration
+# without parameters.
+sp_func_proto_paren_empty = ignore # ignore/add/remove/force/not_defined
-# Add or remove space between 'sizeof' and '('
-sp_sizeof_paren = remove # ignore/add/remove/force
+# Add or remove space between function name and '(' with a typedef specifier.
+sp_func_type_paren = ignore # ignore/add/remove/force/not_defined
-# Add or remove space after the tag keyword (Pawn)
-sp_after_tag = ignore # ignore/add/remove/force
+# Add or remove space between alias name and '(' of a non-pointer function type typedef.
+sp_func_def_paren = remove # ignore/add/remove/force/not_defined
-# Add or remove space inside enum '{' and '}'
-sp_inside_braces_enum = add # ignore/add/remove/force
+# Add or remove space between function name and '()' on function definition
+# without parameters.
+sp_func_def_paren_empty = ignore # ignore/add/remove/force/not_defined
-# Add or remove space inside struct/union '{' and '}'
-sp_inside_braces_struct = add # ignore/add/remove/force
+# 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
-# Add or remove space inside '{' and '}'
-sp_inside_braces = add # ignore/add/remove/force
+# Add or remove space inside function '(' and ')'.
+sp_inside_fparen = ignore # ignore/add/remove/force/not_defined
-# Add or remove space inside '{}'
-sp_inside_braces_empty = remove # ignore/add/remove/force
+# 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
-# Add or remove space between return type and function name
-# A minimum of 1 is forced except for pointer return types.
-sp_type_func = add # ignore/add/remove/force
+# 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
-# Add or remove space between function name and '(' on function declaration
-sp_func_proto_paren = remove # ignore/add/remove/force
+# Add or remove space between ']' and '(' when part of a function call.
+sp_square_fparen = ignore # ignore/add/remove/force/not_defined
-# Add or remove space between function name and '(' on function definition
-sp_func_def_paren = remove # ignore/add/remove/force
+# Add or remove space between ')' and '{' of function.
+sp_fparen_brace = ignore # ignore/add/remove/force/not_defined
-# Add or remove space inside empty function '()'
-sp_inside_fparens = remove # ignore/add/remove/force
+# Add or remove space between ')' and '{' of a function call in object
+# initialization.
+#
+# Overrides sp_fparen_brace.
+sp_fparen_brace_initializer = ignore # ignore/add/remove/force/not_defined
-# Add or remove space inside function '(' and ')'
-sp_inside_fparen = remove # ignore/add/remove/force
+# (Java) Add or remove space between ')' and '{{' of double brace initializer.
+sp_fparen_dbrace = ignore # ignore/add/remove/force/not_defined
-# Add or remove space inside the first parens in the function type: 'void (*x)(...)'
-sp_inside_tparen = ignore # ignore/add/remove/force
+# Add or remove space between function name and '(' on function calls.
+sp_func_call_paren = ignore # ignore/add/remove/force/not_defined
-# Add or remove between the parens in the function type: 'void (*x)(...)'
-sp_after_tparen_close = ignore # ignore/add/remove/force
+# Add or remove space between function name and '()' on function calls without
+# parameters. If set to ignore (the default), sp_func_call_paren is used.
+sp_func_call_paren_empty = ignore # ignore/add/remove/force/not_defined
-# Add or remove space between ']' and '(' when part of a function call.
-sp_square_fparen = remove # ignore/add/remove/force
+# Add or remove space between the user function name and '(' on function
+# calls. You need to set a keyword to be a user function in the config file,
+# like:
+# set func_call_user tr _ i18n
+sp_func_call_user_paren = ignore # ignore/add/remove/force/not_defined
-# Add or remove space between ')' and '{' of function
-sp_fparen_brace = add # ignore/add/remove/force
+# Add or remove space inside user function '(' and ')'.
+sp_func_call_user_inside_fparen = ignore # ignore/add/remove/force/not_defined
-# Add or remove space between function name and '(' on function calls
-sp_func_call_paren = remove # ignore/add/remove/force
+# Add or remove space between nested parentheses with user functions,
+# i.e. '((' vs. '( ('.
+sp_func_call_user_paren_paren = ignore # ignore/add/remove/force/not_defined
-# Add or remove space between function name and '()' on function calls without parameters.
-# If set to 'ignore' (the default), sp_func_call_paren is used.
-sp_func_call_paren_empty = ignore # ignore/add/remove/force
+# Add or remove space between a constructor/destructor and the open
+# parenthesis.
+sp_func_class_paren = ignore # ignore/add/remove/force/not_defined
-# Add or remove space between the user function name and '(' on function calls
-# You need to set a keyword to be a user function, like this: 'set func_call_user _' in the config file.
-sp_func_call_user_paren = remove # ignore/add/remove/force
+# Add or remove space between a constructor without parameters or destructor
+# and '()'.
+sp_func_class_paren_empty = ignore # ignore/add/remove/force/not_defined
-# Add or remove space between a constructor/destructor and the open paren
-sp_func_class_paren = remove # ignore/add/remove/force
+# Add or remove space between 'return' and '('.
+sp_return_paren = ignore # ignore/add/remove/force/not_defined
-# Add or remove space between 'return' and '('
-sp_return_paren = add # ignore/add/remove/force
+# Add or remove space between 'return' and '{'.
+sp_return_brace = ignore # ignore/add/remove/force/not_defined
-# Add or remove space between '__attribute__' and '('
-sp_attribute_paren = remove # ignore/add/remove/force
+# Add or remove space between '__attribute__' and '('.
+sp_attribute_paren = ignore # ignore/add/remove/force/not_defined
-# Add or remove space between 'defined' and '(' in '#if defined (FOO)'
-sp_defined_paren = remove # ignore/add/remove/force
+# Add or remove space between 'defined' and '(' in '#if defined (FOO)'.
+sp_defined_paren = ignore # ignore/add/remove/force/not_defined
-# Add or remove space between 'throw' and '(' in 'throw (something)'
-sp_throw_paren = remove # ignore/add/remove/force
+# Add or remove space between 'throw' and '(' in 'throw (something)'.
+sp_throw_paren = ignore # ignore/add/remove/force/not_defined
-# Add or remove space between 'throw' and anything other than '(' as in '@throw [...];'
-sp_after_throw = ignore # ignore/add/remove/force
+# Add or remove space between 'throw' and anything other than '(' as in
+# '@throw [...];'.
+sp_after_throw = ignore # ignore/add/remove/force/not_defined
-# Add or remove space between 'catch' and '(' in 'catch (something) { }'
+# Add or remove space between 'catch' and '(' in 'catch (something) { }'.
# If set to ignore, sp_before_sparen is used.
-sp_catch_paren = ignore # ignore/add/remove/force
+sp_catch_paren = ignore # ignore/add/remove/force/not_defined
-# Add or remove space between 'version' and '(' in 'version (something) { }' (D language)
-# If set to ignore, sp_before_sparen is used.
-sp_version_paren = ignore # ignore/add/remove/force
+# (OC) Add or remove space between '@catch' and '('
+# in '@catch (something) { }'. If set to ignore, sp_catch_paren is used.
+sp_oc_catch_paren = ignore # ignore/add/remove/force/not_defined
-# Add or remove space between 'scope' and '(' in 'scope (something) { }' (D language)
-# If set to ignore, sp_before_sparen is used.
-sp_scope_paren = ignore # ignore/add/remove/force
+# (OC) Add or remove space before Objective-C protocol list
+# as in '@protocol Protocol<here><Protocol_A>' or '@interface MyClass : NSObject<here><MyProtocol>'.
+sp_before_oc_proto_list = ignore # ignore/add/remove/force/not_defined
+
+# (OC) Add or remove space between class name and '('
+# in '@interface className(categoryName)<ProtocolName>:BaseClass'
+sp_oc_classname_paren = ignore # ignore/add/remove/force/not_defined
+
+# (D) Add or remove space between 'version' and '('
+# in 'version (something) { }'. If set to ignore, sp_before_sparen is used.
+sp_version_paren = ignore # ignore/add/remove/force/not_defined
+
+# (D) Add or remove space between 'scope' and '('
+# in 'scope (something) { }'. If set to ignore, sp_before_sparen is used.
+sp_scope_paren = ignore # ignore/add/remove/force/not_defined
+
+# Add or remove space between 'super' and '(' in 'super (something)'.
+#
+# Default: remove
+sp_super_paren = ignore # ignore/add/remove/force/not_defined
+
+# Add or remove space between 'this' and '(' in 'this (something)'.
+#
+# Default: remove
+sp_this_paren = ignore # ignore/add/remove/force/not_defined
+
+# Add or remove space between a macro name and its definition.
+sp_macro = ignore # ignore/add/remove/force/not_defined
+
+# Add or remove space between a macro function ')' and its definition.
+sp_macro_func = ignore # ignore/add/remove/force/not_defined
+
+# Add or remove space between 'else' and '{' if on the same line.
+sp_else_brace = add # ignore/add/remove/force/not_defined
+
+# Add or remove space between '}' and 'else' if on the same line.
+sp_brace_else = add # ignore/add/remove/force/not_defined
-# Add or remove space between macro and value
-sp_macro = add # ignore/add/remove/force
+# 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
-# Add or remove space between macro function ')' and value
-sp_macro_func = remove # ignore/add/remove/force
+# Add or remove space before the '{' of a 'catch' statement, if the '{' and
+# 'catch' are on the same line, as in 'catch (decl) <here> {'.
+sp_catch_brace = ignore # ignore/add/remove/force/not_defined
-# Add or remove space between 'else' and '{' if on the same line
-sp_else_brace = add # ignore/add/remove/force
+# (OC) Add or remove space before the '{' of a '@catch' statement, if the '{'
+# and '@catch' are on the same line, as in '@catch (decl) <here> {'.
+# If set to ignore, sp_catch_brace is used.
+sp_oc_catch_brace = ignore # ignore/add/remove/force/not_defined
-# Add or remove space between '}' and 'else' if on the same line
-sp_brace_else = add # ignore/add/remove/force
+# Add or remove space between '}' and 'catch' if on the same line.
+sp_brace_catch = ignore # ignore/add/remove/force/not_defined
-# Add or remove space between '}' and the name of a typedef on the same line
-sp_brace_typedef = add # ignore/add/remove/force
+# (OC) Add or remove space between '}' and '@catch' if on the same line.
+# If set to ignore, sp_brace_catch is used.
+sp_oc_brace_catch = ignore # ignore/add/remove/force/not_defined
-# Add or remove space between 'catch' and '{' if on the same line
-sp_catch_brace = add # ignore/add/remove/force
+# Add or remove space between 'finally' and '{' if on the same line.
+sp_finally_brace = ignore # ignore/add/remove/force/not_defined
-# Add or remove space between '}' and 'catch' if on the same line
-sp_brace_catch = add # ignore/add/remove/force
+# Add or remove space between '}' and 'finally' if on the same line.
+sp_brace_finally = ignore # ignore/add/remove/force/not_defined
-# Add or remove space between 'finally' and '{' if on the same line
-sp_finally_brace = add # ignore/add/remove/force
+# Add or remove space between 'try' and '{' if on the same line.
+sp_try_brace = ignore # ignore/add/remove/force/not_defined
-# Add or remove space between '}' and 'finally' if on the same line
-sp_brace_finally = add # ignore/add/remove/force
+# Add or remove space between get/set and '{' if on the same line.
+sp_getset_brace = ignore # ignore/add/remove/force/not_defined
-# Add or remove space between 'try' and '{' if on the same line
-sp_try_brace = add # ignore/add/remove/force
+# Add or remove space between a variable and '{' for C++ uniform
+# initialization.
+sp_word_brace_init_lst = ignore # ignore/add/remove/force/not_defined
-# Add or remove space between get/set and '{' if on the same line
-sp_getset_brace = add # ignore/add/remove/force
+# Add or remove space between a variable and '{' for a namespace.
+#
+# Default: add
+sp_word_brace_ns = ignore # ignore/add/remove/force/not_defined
-# Add or remove space before the '::' operator
-sp_before_dc = remove # ignore/add/remove/force
+# Add or remove space before the '::' operator.
+sp_before_dc = ignore # ignore/add/remove/force/not_defined
-# Add or remove space after the '::' operator
-sp_after_dc = remove # ignore/add/remove/force
+# Add or remove space after the '::' operator.
+sp_after_dc = ignore # ignore/add/remove/force/not_defined
-# Add or remove around the D named array initializer ':' operator
-sp_d_array_colon = ignore # ignore/add/remove/force
+# (D) Add or remove around the D named array initializer ':' operator.
+sp_d_array_colon = ignore # ignore/add/remove/force/not_defined
-# Add or remove space after the '!' (not) operator. Default=Remove
-sp_not = remove # ignore/add/remove/force
+# Add or remove space after the '!' (not) unary operator.
+#
+# Default: remove
+sp_not = ignore # ignore/add/remove/force/not_defined
-# Add or remove space after the '~' (invert) operator. Default=Remove
-sp_inv = remove # ignore/add/remove/force
+# Add or remove space after the '~' (invert) unary operator.
+#
+# Default: remove
+sp_inv = ignore # ignore/add/remove/force/not_defined
-# Add or remove space after the '&' (address-of) operator. Default=Remove
-# This does not affect the spacing after a '&' that is part of a type.
-sp_addr = remove # ignore/add/remove/force
+# Add or remove space after the '&' (address-of) unary operator. This does not
+# affect the spacing after a '&' that is part of a type.
+#
+# Default: remove
+sp_addr = ignore # ignore/add/remove/force/not_defined
-# Add or remove space around the '.' or '->' operators. Default=Remove
-sp_member = remove # ignore/add/remove/force
+# Add or remove space around the '.' or '->' operators.
+#
+# Default: remove
+sp_member = ignore # ignore/add/remove/force/not_defined
-# Add or remove space after the '*' (dereference) operator. Default=Remove
-# This does not affect the spacing after a '*' that is part of a type.
-sp_deref = remove # ignore/add/remove/force
+# Add or remove space after the '*' (dereference) unary operator. This does
+# not affect the spacing after a '*' that is part of a type.
+#
+# Default: remove
+sp_deref = ignore # ignore/add/remove/force/not_defined
-# Add or remove space after '+' or '-', as in 'x = -5' or 'y = +7'. Default=Remove
-sp_sign = remove # ignore/add/remove/force
+# Add or remove space after '+' or '-', as in 'x = -5' or 'y = +7'.
+#
+# Default: remove
+sp_sign = ignore # ignore/add/remove/force/not_defined
-# Add or remove space before or after '++' and '--', as in '(--x)' or 'y++;'. Default=Remove
-sp_incdec = remove # ignore/add/remove/force
+# Add or remove space between '++' and '--' the word to which it is being
+# applied, as in '(--x)' or 'y++;'.
+#
+# Default: remove
+sp_incdec = ignore # ignore/add/remove/force/not_defined
-# Add or remove space before a backslash-newline at the end of a line. Default=Add
-sp_before_nl_cont = remove # ignore/add/remove/force
+# Add or remove space before a backslash-newline at the end of a line.
+#
+# Default: add
+sp_before_nl_cont = ignore # ignore/add/remove/force/not_defined
-# Add or remove space after the scope '+' or '-', as in '-(void) foo;' or '+(int) bar;'
-sp_after_oc_scope = remove # ignore/add/remove/force
+# (OC) Add or remove space after the scope '+' or '-', as in '-(void) foo;'
+# or '+(int) bar;'.
+sp_after_oc_scope = ignore # ignore/add/remove/force/not_defined
-# Add or remove space after the colon in message specs
-# '-(int) f:(int) x;' vs '-(int) f: (int) x;'
-sp_after_oc_colon = remove # ignore/add/remove/force
+# (OC) Add or remove space after the colon in message specs,
+# i.e. '-(int) f:(int) x;' vs. '-(int) f: (int) x;'.
+sp_after_oc_colon = ignore # ignore/add/remove/force/not_defined
-# Add or remove space before the colon in message specs
-# '-(int) f: (int) x;' vs '-(int) f : (int) x;'
-sp_before_oc_colon = remove # ignore/add/remove/force
+# (OC) Add or remove space before the colon in message specs,
+# i.e. '-(int) f: (int) x;' vs. '-(int) f : (int) x;'.
+sp_before_oc_colon = ignore # ignore/add/remove/force/not_defined
-# Add or remove space after the colon in immutable dictionary expression
-# 'NSDictionary *test = @{@"foo" :@"bar"};'
-sp_after_oc_dict_colon = ignore # ignore/add/remove/force
+# (OC) Add or remove space after the colon in immutable dictionary expression
+# 'NSDictionary *test = @{@"foo" :@"bar"};'.
+sp_after_oc_dict_colon = ignore # ignore/add/remove/force/not_defined
-# Add or remove space before the colon in immutable dictionary expression
-# 'NSDictionary *test = @{@"foo" :@"bar"};'
-sp_before_oc_dict_colon = ignore # ignore/add/remove/force
+# (OC) Add or remove space before the colon in immutable dictionary expression
+# 'NSDictionary *test = @{@"foo" :@"bar"};'.
+sp_before_oc_dict_colon = ignore # ignore/add/remove/force/not_defined
-# Add or remove space after the colon in message specs
-# '[object setValue:1];' vs '[object setValue: 1];'
-sp_after_send_oc_colon = add # ignore/add/remove/force
+# (OC) Add or remove space after the colon in message specs,
+# i.e. '[object setValue:1];' vs. '[object setValue: 1];'.
+sp_after_send_oc_colon = ignore # ignore/add/remove/force/not_defined
-# Add or remove space before the colon in message specs
-# '[object setValue:1];' vs '[object setValue :1];'
-sp_before_send_oc_colon = remove # ignore/add/remove/force
+# (OC) Add or remove space before the colon in message specs,
+# i.e. '[object setValue:1];' vs. '[object setValue :1];'.
+sp_before_send_oc_colon = ignore # ignore/add/remove/force/not_defined
-# Add or remove space after the (type) in message specs
-# '-(int)f: (int) x;' vs '-(int)f: (int)x;'
-sp_after_oc_type = remove # ignore/add/remove/force
+# (OC) Add or remove space after the (type) in message specs,
+# i.e. '-(int)f: (int) x;' vs. '-(int)f: (int)x;'.
+sp_after_oc_type = ignore # ignore/add/remove/force/not_defined
-# Add or remove space after the first (type) in message specs
-# '-(int) f:(int)x;' vs '-(int)f:(int)x;'
-sp_after_oc_return_type = ignore # ignore/add/remove/force
+# (OC) Add or remove space after the first (type) in message specs,
+# i.e. '-(int) f:(int)x;' vs. '-(int)f:(int)x;'.
+sp_after_oc_return_type = ignore # ignore/add/remove/force/not_defined
-# Add or remove space between '@selector' and '('
-# '@selector(msgName)' vs '@selector (msgName)'
-# Also applies to @protocol() constructs
-sp_after_oc_at_sel = ignore # ignore/add/remove/force
+# (OC) Add or remove space between '@selector' and '(',
+# i.e. '@selector(msgName)' vs. '@selector (msgName)'.
+# Also applies to '@protocol()' constructs.
+sp_after_oc_at_sel = ignore # ignore/add/remove/force/not_defined
-# Add or remove space between '@selector(x)' and the following word
-# '@selector(foo) a:' vs '@selector(foo)a:'
-sp_after_oc_at_sel_parens = ignore # ignore/add/remove/force
+# (OC) Add or remove space between '@selector(x)' and the following word,
+# i.e. '@selector(foo) a:' vs. '@selector(foo)a:'.
+sp_after_oc_at_sel_parens = ignore # ignore/add/remove/force/not_defined
-# Add or remove space inside '@selector' parens
-# '@selector(foo)' vs '@selector( foo )'
-# Also applies to @protocol() constructs
-sp_inside_oc_at_sel_parens = ignore # ignore/add/remove/force
+# (OC) Add or remove space inside '@selector' parentheses,
+# i.e. '@selector(foo)' vs. '@selector( foo )'.
+# Also applies to '@protocol()' constructs.
+sp_inside_oc_at_sel_parens = ignore # ignore/add/remove/force/not_defined
-# Add or remove space before a block pointer caret
-# '^int (int arg){...}' vs. ' ^int (int arg){...}'
-sp_before_oc_block_caret = ignore # ignore/add/remove/force
+# (OC) Add or remove space before a block pointer caret,
+# i.e. '^int (int arg){...}' vs. ' ^int (int arg){...}'.
+sp_before_oc_block_caret = ignore # ignore/add/remove/force/not_defined
-# Add or remove space after a block pointer caret
-# '^int (int arg){...}' vs. '^ int (int arg){...}'
-sp_after_oc_block_caret = ignore # ignore/add/remove/force
+# (OC) Add or remove space after a block pointer caret,
+# i.e. '^int (int arg){...}' vs. '^ int (int arg){...}'.
+sp_after_oc_block_caret = ignore # ignore/add/remove/force/not_defined
-# Add or remove space between the receiver and selector in a message.
-# '[receiver selector ...]'
-sp_after_oc_msg_receiver = ignore # ignore/add/remove/force
+# (OC) Add or remove space between the receiver and selector in a message,
+# as in '[receiver selector ...]'.
+sp_after_oc_msg_receiver = ignore # ignore/add/remove/force/not_defined
-# Add or remove space after @property.
-sp_after_oc_property = ignore # ignore/add/remove/force
+# (OC) Add or remove space after '@property'.
+sp_after_oc_property = ignore # ignore/add/remove/force/not_defined
-# Add or remove space around the ':' in 'b ? t : f'
-sp_cond_colon = add # ignore/add/remove/force
+# (OC) Add or remove space between '@synchronized' and the open parenthesis,
+# i.e. '@synchronized(foo)' vs. '@synchronized (foo)'.
+sp_after_oc_synchronized = ignore # ignore/add/remove/force/not_defined
-# Add or remove space around the '?' in 'b ? t : f'
-sp_cond_question = add # ignore/add/remove/force
+# Add or remove space around the ':' in 'b ? t : f'.
+sp_cond_colon = ignore # ignore/add/remove/force/not_defined
-# Fix the spacing between 'case' and the label. Only 'ignore' and 'force' make sense here.
-sp_case_label = ignore # ignore/add/remove/force
+# Add or remove space before the ':' in 'b ? t : f'.
+#
+# Overrides sp_cond_colon.
+sp_cond_colon_before = ignore # ignore/add/remove/force/not_defined
+
+# Add or remove space after the ':' in 'b ? t : f'.
+#
+# Overrides sp_cond_colon.
+sp_cond_colon_after = ignore # ignore/add/remove/force/not_defined
-# Control the space around the D '..' operator.
-sp_range = ignore # ignore/add/remove/force
+# Add or remove space around the '?' in 'b ? t : f'.
+sp_cond_question = ignore # ignore/add/remove/force/not_defined
-# Control the spacing after ':' in 'for (TYPE VAR : EXPR)' (Java)
-sp_after_for_colon = ignore # ignore/add/remove/force
+# Add or remove space before the '?' in 'b ? t : f'.
+#
+# Overrides sp_cond_question.
+sp_cond_question_before = ignore # ignore/add/remove/force/not_defined
-# Control the spacing before ':' in 'for (TYPE VAR : EXPR)' (Java)
-sp_before_for_colon = ignore # ignore/add/remove/force
+# Add or remove space after the '?' in 'b ? t : f'.
+#
+# Overrides sp_cond_question.
+sp_cond_question_after = ignore # ignore/add/remove/force/not_defined
-# Control the spacing in 'extern (C)' (D)
-sp_extern_paren = ignore # ignore/add/remove/force
+# In the abbreviated ternary form '(a ?: b)', add or remove space between '?'
+# and ':'.
+#
+# Overrides all other sp_cond_* options.
+sp_cond_ternary_short = ignore # ignore/add/remove/force/not_defined
-# Control the space after the opening of a C++ comment '// A' vs '//A'
-sp_cmt_cpp_start = add # ignore/add/remove/force
+# Fix the spacing between 'case' and the label. Only 'ignore' and 'force' make
+# sense here.
+sp_case_label = ignore # ignore/add/remove/force/not_defined
-# Controls the spaces between #else or #endif and a trailing comment
-sp_endif_cmt = ignore # ignore/add/remove/force
+# (D) Add or remove space around the D '..' operator.
+sp_range = ignore # ignore/add/remove/force/not_defined
-# Controls the spaces after 'new', 'delete', and 'delete[]'
-sp_after_new = ignore # ignore/add/remove/force
+# Add or remove space after ':' in a Java/C++11 range-based 'for',
+# as in 'for (Type var : <here> expr)'.
+sp_after_for_colon = ignore # ignore/add/remove/force/not_defined
-# Controls the spaces before a trailing or embedded comment
-sp_before_tr_emb_cmt = ignore # ignore/add/remove/force
+# Add or remove space before ':' in a Java/C++11 range-based 'for',
+# as in 'for (Type var <here> : expr)'.
+sp_before_for_colon = ignore # ignore/add/remove/force/not_defined
-# Number of spaces before a trailing or embedded comment
-sp_num_before_tr_emb_cmt = 0 # number
+# (D) Add or remove space between 'extern' and '(' as in 'extern <here> (C)'.
+sp_extern_paren = ignore # ignore/add/remove/force/not_defined
-# Control space between a Java annotation and the open paren.
-sp_annotation_paren = ignore # ignore/add/remove/force
+# Add or remove space after the opening of a C++ comment, as in '// <here> A'.
+sp_cmt_cpp_start = ignore # ignore/add/remove/force/not_defined
+# Add or remove space in a C++ region marker comment, as in '// <here> BEGIN'.
+# A region marker is defined as a comment which is not preceded by other text
+# (i.e. the comment is the first non-whitespace on the line), and which starts
+# with either 'BEGIN' or 'END'.
#
-# Code alignment (not left column spaces/tabs)
+# Overrides sp_cmt_cpp_start.
+sp_cmt_cpp_region = ignore # ignore/add/remove/force/not_defined
+
+# If true, space added with sp_cmt_cpp_start will be added after Doxygen
+# sequences like '///', '///<', '//!' and '//!<'.
+sp_cmt_cpp_doxygen = false # true/false
+
+# If true, space added with sp_cmt_cpp_start will be added after Qt translator
+# or meta-data comments like '//:', '//=', and '//~'.
+sp_cmt_cpp_qttr = false # true/false
+
+# Add or remove space between #else or #endif and a trailing comment.
+sp_endif_cmt = ignore # ignore/add/remove/force/not_defined
+
+# Add or remove space after 'new', 'delete' and 'delete[]'.
+sp_after_new = ignore # ignore/add/remove/force/not_defined
+
+# Add or remove space between 'new' and '(' in 'new()'.
+sp_between_new_paren = ignore # ignore/add/remove/force/not_defined
+
+# Add or remove space between ')' and type in 'new(foo) BAR'.
+sp_after_newop_paren = ignore # ignore/add/remove/force/not_defined
+
+# Add or remove space inside parenthesis of the new operator
+# as in 'new(foo) BAR'.
+sp_inside_newop_paren = ignore # ignore/add/remove/force/not_defined
+
+# Add or remove space after the open parenthesis of the new operator,
+# as in 'new(foo) BAR'.
#
+# Overrides sp_inside_newop_paren.
+sp_inside_newop_paren_open = ignore # ignore/add/remove/force/not_defined
-# Whether to keep non-indenting tabs
-align_keep_tabs = false # false/true
+# Add or remove space before the close parenthesis of the new operator,
+# as in 'new(foo) BAR'.
+#
+# Overrides sp_inside_newop_paren.
+sp_inside_newop_paren_close = ignore # ignore/add/remove/force/not_defined
-# Whether to use tabs for aligning
-align_with_tabs = false # false/true
+# Add or remove space before a trailing or embedded comment.
+sp_before_tr_emb_cmt = add # ignore/add/remove/force/not_defined
-# Whether to bump out to the next tab when aligning
-align_on_tabstop = false # false/true
+# Number of spaces before a trailing or embedded comment.
+sp_num_before_tr_emb_cmt = 2 # unsigned number
-# Whether to left-align numbers
-align_number_left = false # false/true
+# (Java) Add or remove space between an annotation and the open parenthesis.
+sp_annotation_paren = ignore # ignore/add/remove/force/not_defined
-# Align variable definitions in prototypes and functions
-align_func_params = true # false/true
+# If true, vbrace tokens are dropped to the previous token and skipped.
+sp_skip_vbrace_tokens = false # true/false
-# Align parameters in single-line functions that have the same name.
-# The function names must already be aligned with each other.
-align_same_func_call_params = true # false/true
+# Add or remove space after 'noexcept'.
+sp_after_noexcept = ignore # ignore/add/remove/force/not_defined
-# The span for aligning variable definitions (0=don't align)
-align_var_def_span = 0 # number
+# Add or remove space after '_'.
+sp_vala_after_translation = ignore # ignore/add/remove/force/not_defined
-# How to align the star in variable definitions.
-# 0=Part of the type 'void * foo;'
-# 1=Part of the variable 'void *foo;'
-# 2=Dangling 'void *foo;'
-align_var_def_star_style = 1 # number
+# If true, a <TAB> is inserted after #define.
+force_tab_after_define = false # true/false
-# How to align the '&' in variable definitions.
-# 0=Part of the type
-# 1=Part of the variable
-# 2=Dangling
-align_var_def_amp_style = 2 # number
+#
+# Indenting options
+#
-# The threshold for aligning variable definitions (0=no limit)
-align_var_def_thresh = 3 # number
+# The number of columns to indent per level. Usually 2, 3, 4, or 8.
+#
+# Default: 8
+indent_columns = 2 # unsigned number
-# The gap for aligning variable definitions
-align_var_def_gap = 1 # number
+# The continuation indent. If non-zero, this overrides the indent of '(', '['
+# and '=' continuation indents. Negative values are OK; negative value is
+# absolute and not increased for each '(' or '[' level.
+#
+# For FreeBSD, this is set to 4.
+indent_continue = 0 # number
-# Whether to align the colon in struct bit fields
-align_var_def_colon = true # false/true
+# The continuation indent, only for class header line(s). If non-zero, this
+# overrides the indent of 'class' continuation indents.
+indent_continue_class_head = 0 # unsigned number
-# Whether to align any attribute after the variable name
-align_var_def_attribute = true # false/true
+# Whether to indent empty lines (i.e. lines which contain only spaces before
+# the newline character).
+indent_single_newlines = false # true/false
-# Whether to align inline struct/enum/union variable definitions
-align_var_def_inline = true # false/true
+# The continuation indent for func_*_param if they are true. If non-zero, this
+# overrides the indent.
+indent_param = 0 # unsigned number
-# The span for aligning on '=' in assignments (0=don't align)
-align_assign_span = 0 # number
+# How to use tabs when indenting code.
+#
+# 0: Spaces only
+# 1: Indent with tabs to brace level, align with spaces (default)
+# 2: Indent and align with tabs, using spaces when not on a tabstop
+#
+# Default: 1
+indent_with_tabs = 0 # unsigned number
-# The threshold for aligning on '=' in assignments (0=no limit)
-align_assign_thresh = 0 # number
+# Whether to indent comments that are not at a brace level with tabs on a
+# tabstop. Requires indent_with_tabs=2. If false, will use spaces.
+indent_cmt_with_tabs = false # true/false
-# The span for aligning on '=' in enums (0=don't align)
-align_enum_equ_span = 0 # number
+# Whether to indent strings broken by '\' so that they line up.
+indent_align_string = false # true/false
-# The threshold for aligning on '=' in enums (0=no limit)
-align_enum_equ_thresh = 0 # number
+# The number of spaces to indent multi-line XML strings.
+# Requires indent_align_string=true.
+indent_xml_string = 0 # unsigned number
-# The span for aligning struct/union (0=don't align)
-align_var_struct_span = 0 # number
+# Spaces to indent '{' from level.
+indent_brace = 0 # unsigned number
-# The threshold for aligning struct/union member definitions (0=no limit)
-align_var_struct_thresh = 0 # number
+# Whether braces are indented to the body level.
+indent_braces = false # true/false
-# The gap for aligning struct/union member definitions
-align_var_struct_gap = 0 # number
+# Whether to disable indenting function braces if indent_braces=true.
+indent_braces_no_func = false # true/false
-# The span for aligning struct initializer values (0=don't align)
-align_struct_init_span = 0 # number
+# Whether to disable indenting class braces if indent_braces=true.
+indent_braces_no_class = false # true/false
-# The minimum space between the type and the synonym of a typedef
-align_typedef_gap = 0 # number
+# Whether to disable indenting struct braces if indent_braces=true.
+indent_braces_no_struct = false # true/false
-# The span for aligning single-line typedefs (0=don't align)
-align_typedef_span = 0 # number
+# Whether to indent based on the size of the brace parent,
+# i.e. 'if' => 3 spaces, 'for' => 4 spaces, etc.
+indent_brace_parent = false # true/false
-# How to align typedef'd functions with other typedefs
-# 0: Don't mix them at all
-# 1: align the open paren with the types
-# 2: align the function type name with the other type names
-align_typedef_func = 0 # number
+# Whether to indent based on the open parenthesis instead of the open brace
+# in '({\n'.
+indent_paren_open_brace = false # true/false
-# Controls the positioning of the '*' in typedefs. Just try it.
-# 0: Align on typedef type, ignore '*'
-# 1: The '*' is part of type name: typedef int *pint;
-# 2: The '*' is part of the type, but dangling: typedef int *pint;
-align_typedef_star_style = 2 # number
+# (C#) Whether to indent the brace of a C# delegate by another level.
+indent_cs_delegate_brace = false # true/false
-# Controls the positioning of the '&' in typedefs. Just try it.
-# 0: Align on typedef type, ignore '&'
-# 1: The '&' is part of type name: typedef int &pint;
-# 2: The '&' is part of the type, but dangling: typedef int &pint;
-align_typedef_amp_style = 2 # number
+# (C#) Whether to indent a C# delegate (to handle delegates with no brace) by
+# another level.
+indent_cs_delegate_body = false # true/false
-# The span for aligning comments that end lines (0=don't align)
-align_right_cmt_span = 4 # number
+# Whether to indent the body of a 'namespace'.
+indent_namespace = false # true/false
-# If aligning comments, mix with comments after '}' and #endif with less than 3 spaces before the comment
-align_right_cmt_mix = false # false/true
+# Whether to indent only the first namespace, and not any nested namespaces.
+# Requires indent_namespace=true.
+indent_namespace_single_indent = false # true/false
-# If a trailing comment is more than this number of columns away from the text it follows,
-# it will qualify for being aligned. This has to be > 0 to do anything.
-align_right_cmt_gap = 0 # number
+# The number of spaces to indent a namespace block.
+# If set to zero, use the value indent_columns
+indent_namespace_level = 0 # unsigned number
-# Align trailing comment at or beyond column N; 'pulls in' comments as a bonus side effect (0=ignore)
-align_right_cmt_at_col = 1 # number
+# If the body of the namespace is longer than this number, it won't be
+# indented. Requires indent_namespace=true. 0 means no limit.
+indent_namespace_limit = 0 # unsigned number
-# The span for aligning function prototypes (0=don't align)
-align_func_proto_span = 0 # number
+# Whether the 'extern "C"' body is indented.
+indent_extern = false # true/false
-# Minimum gap between the return type and the function name.
-align_func_proto_gap = 0 # number
+# Whether the 'class' body is indented.
+indent_class = false # true/false
-# Align function protos on the 'operator' keyword instead of what follows
-align_on_operator = true # false/true
+# Additional indent before the leading base class colon.
+# Negative values decrease indent down to the first column.
+# Requires a newline break before colon (see pos_class_colon
+# and nl_class_colon)
+indent_before_class_colon = 0 # number
-# Whether to mix aligning prototype and variable declarations.
-# If true, align_var_def_XXX options are used instead of align_func_proto_XXX options.
-align_mix_var_proto = false # false/true
+# Whether to indent the stuff after a leading base class colon.
+indent_class_colon = false # true/false
-# Align single-line functions with function prototypes, uses align_func_proto_span
-align_single_line_func = true # false/true
+# Whether to indent based on a class colon instead of the stuff after the
+# colon. Requires indent_class_colon=true.
+indent_class_on_colon = false # true/false
-# Aligning the open brace of single-line functions.
-# Requires align_single_line_func=true, uses align_func_proto_span
-align_single_line_brace = true # false/true
+# Whether to indent the stuff after a leading class initializer colon.
+indent_constr_colon = false # true/false
-# Gap for align_single_line_brace.
-align_single_line_brace_gap = 0 # number
+# Virtual indent from the ':' for member initializers.
+#
+# Default: 2
+indent_ctor_init_leading = 2 # unsigned number
+
+# Additional indent for constructor initializer list.
+# Negative values decrease indent down to the first column.
+indent_ctor_init = 0 # number
+
+# Whether to indent 'if' following 'else' as a new block under the 'else'.
+# If false, 'else\nif' is treated as 'else if' for indenting purposes.
+indent_else_if = false # true/false
+
+# Amount to indent variable declarations after a open brace.
+#
+# <0: Relative
+# >=0: Absolute
+indent_var_def_blk = 0 # number
+
+# Whether to indent continued variable declarations instead of aligning.
+indent_var_def_cont = false # true/false
+
+# Whether to indent continued shift expressions ('<<' and '>>') instead of
+# aligning. Set align_left_shift=false when enabling this.
+indent_shift = false # true/false
+
+# Whether to force indentation of function definitions to start in column 1.
+indent_func_def_force_col1 = false # true/false
+
+# Whether to indent continued function call parameters one indent level,
+# rather than aligning parameters under the open parenthesis.
+indent_func_call_param = false # true/false
-# The span for aligning ObjC msg spec (0=don't align)
-align_oc_msg_spec_span = 0 # number
+# Whether to indent continued function definition parameters one indent level,
+# rather than aligning parameters under the open parenthesis.
+indent_func_def_param = false # true/false
-# Whether to align macros wrapped with a backslash and a newline.
-# This will not work right if the macro contains a multi-line comment.
-align_nl_cont = true # false/true
+# for function definitions, only if indent_func_def_param is false
+# Allows to align params when appropriate and indent them when not
+# behave as if it was true if paren position is more than this value
+# if paren position is more than the option value
+indent_func_def_param_paren_pos_threshold = 0 # unsigned number
-# # Align macro functions and variables together
-align_pp_define_together = false # false/true
+# Whether to indent continued function call prototype one indent level,
+# rather than aligning parameters under the open parenthesis.
+indent_func_proto_param = false # true/false
-# The minimum space between label and value of a preprocessor define
-align_pp_define_gap = 0 # number
+# Whether to indent continued function call declaration one indent level,
+# rather than aligning parameters under the open parenthesis.
+indent_func_class_param = false # true/false
-# The span for aligning on '#define' bodies (0=don't align)
-align_pp_define_span = 0 # number
+# Whether to indent continued class variable constructors one indent level,
+# rather than aligning parameters under the open parenthesis.
+indent_func_ctor_var_param = false # true/false
-# Align lines that start with '<<' with previous '<<'. Default=true
-align_left_shift = true # false/true
+# Whether to indent continued template parameter list one indent level,
+# rather than aligning parameters under the open parenthesis.
+indent_template_param = false # true/false
-# Span for aligning parameters in an Obj-C message call on the ':' (0=don't align)
-align_oc_msg_colon_span = 0 # number
+# Double the indent for indent_func_xxx_param options.
+# Use both values of the options indent_columns and indent_param.
+indent_func_param_double = false # true/false
-# If true, always align with the first parameter, even if it is too short.
-align_oc_msg_colon_first = false # false/true
+# Indentation column for standalone 'const' qualifier on a function
+# prototype.
+indent_func_const = 0 # unsigned number
-# Aligning parameters in an Obj-C '+' or '-' declaration on the ':'
-align_oc_decl_colon = false # false/true
+# Indentation column for standalone 'throw' qualifier on a function
+# prototype.
+indent_func_throw = 0 # unsigned number
+
+# How to indent within a macro followed by a brace on the same line
+# This allows reducing the indent in macros that have (for example)
+# `do { ... } while (0)` blocks bracketing them.
+#
+# true: add an indent for the brace on the same line as the macro
+# false: do not add an indent for the brace on the same line as the macro
+#
+# Default: true
+indent_macro_brace = false # true/false
+
+# The number of spaces to indent a continued '->' or '.'.
+# Usually set to 0, 1, or indent_columns.
+indent_member = 0 # unsigned number
+
+# Whether lines broken at '.' or '->' should be indented by a single indent.
+# The indent_member option will not be effective if this is set to true.
+indent_member_single = false # true/false
+
+# Spaces to indent single line ('//') comments on lines before code.
+indent_single_line_comments_before = 0 # unsigned number
+
+# Spaces to indent single line ('//') comments on lines after code.
+indent_single_line_comments_after = 0 # unsigned number
+
+# When opening a paren for a control statement (if, for, while, etc), increase
+# the indent level by this value. Negative values decrease the indent level.
+indent_sparen_extra = 0 # number
+
+# Whether to indent trailing single line ('//') comments relative to the code
+# instead of trying to keep the same absolute column.
+indent_relative_single_line_comments = true # true/false
+
+# Spaces to indent 'case' from 'switch'. Usually 0 or indent_columns.
+# It might wise to choose the same value for the option indent_case_brace.
+indent_switch_case = 0 # unsigned number
+
+# Spaces to indent '{' from 'case'. By default, the brace will appear under
+# the 'c' in case. Usually set to 0 or indent_columns. Negative values are OK.
+# It might wise to choose the same value for the option indent_switch_case.
+indent_case_brace = 2 # number
+
+# indent 'break' with 'case' from 'switch'.
+indent_switch_break_with_case = false # true/false
+
+# Whether to indent preprocessor statements inside of switch statements.
+#
+# Default: true
+indent_switch_pp = true # true/false
+
+# Spaces to shift the 'case' line, without affecting any other lines.
+# Usually 0.
+indent_case_shift = 0 # unsigned number
+
+# Whether to indent comments found in first column.
+indent_col1_comment = false # true/false
+
+# Whether to indent multi string literal in first column.
+indent_col1_multi_string_literal = false # true/false
+
+# How to indent goto labels.
+#
+# >0: Absolute column where 1 is the leftmost column
+# <=0: Subtract from brace indent
+#
+# Default: 1
+indent_label = 1 # number
+
+# How to indent access specifiers that are followed by a
+# colon.
+#
+# >0: Absolute column where 1 is the leftmost column
+# <=0: Subtract from brace indent
+#
+# Default: 1
+indent_access_spec = 1 # number
+
+# Whether to indent the code after an access specifier by one level.
+# If true, this option forces 'indent_access_spec=0'.
+indent_access_spec_body = false # true/false
+
+# If an open parenthesis is followed by a newline, whether to indent the next
+# line so that it lines up after the open parenthesis (not recommended).
+indent_paren_nl = false # true/false
+
+# How to indent a close parenthesis after a newline.
+#
+# 0: Indent to body level (default)
+# 1: Align under the open parenthesis
+# 2: Indent to the brace level
+indent_paren_close = 0 # unsigned number
+
+# Whether to indent the open parenthesis of a function definition,
+# if the parenthesis is on its own line.
+indent_paren_after_func_def = false # true/false
+
+# Whether to indent the open parenthesis of a function declaration,
+# if the parenthesis is on its own line.
+indent_paren_after_func_decl = false # true/false
+
+# Whether to indent the open parenthesis of a function call,
+# if the parenthesis is on its own line.
+indent_paren_after_func_call = true # true/false
+
+# Whether to indent a comma when inside a brace.
+# If true, aligns under the open brace.
+indent_comma_brace = false # true/false
+
+# Whether to indent a comma when inside a parenthesis.
+# If true, aligns under the open parenthesis.
+indent_comma_paren = false # true/false
+
+# Whether to indent a Boolean operator when inside a parenthesis.
+# If true, aligns under the open parenthesis.
+indent_bool_paren = false # true/false
+
+# Whether to indent a semicolon when inside a for parenthesis.
+# If true, aligns under the open for parenthesis.
+indent_semicolon_for_paren = false # true/false
+
+# Whether to align the first expression to following ones
+# if indent_bool_paren=true.
+indent_first_bool_expr = false # true/false
+
+# Whether to align the first expression to following ones
+# if indent_semicolon_for_paren=true.
+indent_first_for_expr = false # true/false
+
+# If an open square is followed by a newline, whether to indent the next line
+# so that it lines up after the open square (not recommended).
+indent_square_nl = false # true/false
+
+# (ESQL/C) Whether to preserve the relative indent of 'EXEC SQL' bodies.
+indent_preserve_sql = false # true/false
+
+# Whether to align continued statements at the '='. If false or if the '=' is
+# followed by a newline, the next line is indent one tab.
+#
+# Default: true
+indent_align_assign = true # true/false
+
+# If true, the indentation of the chunks after a '=' sequence will be set at
+# LHS token indentation column before '='.
+indent_off_after_assign = false # true/false
+
+# Whether to align continued statements at the '('. If false or the '(' is
+# followed by a newline, the next line indent is one tab.
+#
+# Default: true
+indent_align_paren = true # true/false
+
+# (OC) Whether to indent Objective-C code inside message selectors.
+indent_oc_inside_msg_sel = false # true/false
+
+# (OC) Whether to indent Objective-C blocks at brace level instead of usual
+# rules.
+indent_oc_block = false # true/false
+
+# (OC) Indent for Objective-C blocks in a message relative to the parameter
+# name.
+#
+# =0: Use indent_oc_block rules
+# >0: Use specified number of spaces to indent
+indent_oc_block_msg = 0 # unsigned number
+
+# (OC) Minimum indent for subsequent parameters
+indent_oc_msg_colon = 0 # unsigned number
+
+# (OC) Whether to prioritize aligning with initial colon (and stripping spaces
+# from lines, if necessary).
+#
+# Default: true
+indent_oc_msg_prioritize_first_colon = true # true/false
+
+# (OC) Whether to indent blocks the way that Xcode does by default
+# (from the keyword if the parameter is on its own line; otherwise, from the
+# previous indentation level). Requires indent_oc_block_msg=true.
+indent_oc_block_msg_xcode_style = false # true/false
+
+# (OC) Whether to indent blocks from where the brace is, relative to a
+# message keyword. Requires indent_oc_block_msg=true.
+indent_oc_block_msg_from_keyword = false # true/false
+
+# (OC) Whether to indent blocks from where the brace is, relative to a message
+# colon. Requires indent_oc_block_msg=true.
+indent_oc_block_msg_from_colon = false # true/false
+
+# (OC) Whether to indent blocks from where the block caret is.
+# Requires indent_oc_block_msg=true.
+indent_oc_block_msg_from_caret = false # true/false
+
+# (OC) Whether to indent blocks from where the brace caret is.
+# Requires indent_oc_block_msg=true.
+indent_oc_block_msg_from_brace = false # true/false
+
+# When indenting after virtual brace open and newline add further spaces to
+# reach this minimum indent.
+indent_min_vbrace_open = 0 # unsigned number
+
+# Whether to add further spaces after regular indent to reach next tabstop
+# when indenting after virtual brace open and newline.
+indent_vbrace_open_on_tabstop = false # true/false
+
+# How to indent after a brace followed by another token (not a newline).
+# true: indent all contained lines to match the token
+# false: indent all contained lines to match the brace
+#
+# Default: true
+indent_token_after_brace = true # true/false
+
+# Whether to indent the body of a C++11 lambda.
+indent_cpp_lambda_body = false # true/false
+
+# How to indent compound literals that are being returned.
+# true: add both the indent from return & the compound literal open brace
+# (i.e. 2 indent levels)
+# false: only indent 1 level, don't add the indent for the open brace, only
+# add the indent for the return.
+#
+# Default: true
+indent_compound_literal_return = false # true/false
+
+# (C#) Whether to indent a 'using' block if no braces are used.
+#
+# Default: true
+indent_using_block = true # true/false
+
+# How to indent the continuation of ternary operator.
+#
+# 0: Off (default)
+# 1: When the `if_false` is a continuation, indent it under `if_false`
+# 2: When the `:` is a continuation, indent it under `?`
+indent_ternary_operator = 2 # unsigned number
+
+# Whether to indent the statements inside ternary operator.
+indent_inside_ternary_operator = false # true/false
+
+# If true, the indentation of the chunks after a `return` sequence will be set at return indentation column.
+indent_off_after_return = false # true/false
+
+# If true, the indentation of the chunks after a `return new` sequence will be set at return indentation column.
+indent_off_after_return_new = false # true/false
+
+# If true, the tokens after return are indented with regular single indentation. By default (false) the indentation is after the return token.
+indent_single_after_return = false # true/false
+
+# Whether to ignore indent and alignment for 'asm' blocks (i.e. assume they
+# have their own indentation).
+indent_ignore_asm_block = false # true/false
+
+# Don't indent the close parenthesis of a function definition,
+# if the parenthesis is on its own line.
+donot_indent_func_def_close_paren = false # true/false
#
# Newline adding and removing options
#
-# Whether to collapse empty blocks between '{' and '}'
-nl_collapse_empty_body = true # false/true
+# Whether to collapse empty blocks between '{' and '}'.
+# If true, overrides nl_inside_empty_func
+nl_collapse_empty_body = false # true/false
+
+# Don't split one-line braced assignments, as in 'foo_t f = { 1, 2 };'.
+nl_assign_leave_one_liners = false # true/false
+
+# Don't split one-line braced statements inside a 'class xx { }' body.
+nl_class_leave_one_liners = false # true/false
+
+# Don't split one-line enums, as in 'enum foo { BAR = 15 };'
+nl_enum_leave_one_liners = false # true/false
+
+# Don't split one-line get or set functions.
+nl_getset_leave_one_liners = false # true/false
+
+# (C#) Don't split one-line property get or set functions.
+nl_cs_property_leave_one_liners = false # true/false
+
+# Don't split one-line function definitions, as in 'int foo() { return 0; }'.
+# might modify nl_func_type_name
+nl_func_leave_one_liners = false # true/false
+
+# Don't split one-line C++11 lambdas, as in '[]() { return 0; }'.
+nl_cpp_lambda_leave_one_liners = false # true/false
+
+# Don't split one-line if/else statements, as in 'if(...) b++;'.
+nl_if_leave_one_liners = false # true/false
+
+# Don't split one-line while statements, as in 'while(...) b++;'.
+nl_while_leave_one_liners = false # true/false
+
+# Don't split one-line do statements, as in 'do { b++; } while(...);'.
+nl_do_leave_one_liners = false # true/false
+
+# Don't split one-line for statements, as in 'for(...) b++;'.
+nl_for_leave_one_liners = false # true/false
+
+# (OC) Don't split one-line Objective-C messages.
+nl_oc_msg_leave_one_liner = false # true/false
+
+# (OC) Add or remove newline between method declaration and '{'.
+nl_oc_mdef_brace = ignore # ignore/add/remove/force/not_defined
+
+# (OC) Add or remove newline between Objective-C block signature and '{'.
+nl_oc_block_brace = ignore # ignore/add/remove/force/not_defined
+
+# (OC) Add or remove blank line before '@interface' statement.
+nl_oc_before_interface = ignore # ignore/add/remove/force/not_defined
-# Don't split one-line braced assignments - 'foo_t f = { 1, 2 };'
-nl_assign_leave_one_liners = false # false/true
+# (OC) Add or remove blank line before '@implementation' statement.
+nl_oc_before_implementation = ignore # ignore/add/remove/force/not_defined
-# Don't split one-line braced statements inside a class xx { } body
-nl_class_leave_one_liners = false # false/true
+# (OC) Add or remove blank line before '@end' statement.
+nl_oc_before_end = ignore # ignore/add/remove/force/not_defined
-# Don't split one-line enums: 'enum foo { BAR = 15 };'
-nl_enum_leave_one_liners = false # false/true
+# (OC) Add or remove newline between '@interface' and '{'.
+nl_oc_interface_brace = ignore # ignore/add/remove/force/not_defined
-# Don't split one-line get or set functions
-nl_getset_leave_one_liners = false # false/true
+# (OC) Add or remove newline between '@implementation' and '{'.
+nl_oc_implementation_brace = ignore # ignore/add/remove/force/not_defined
-# Don't split one-line function definitions - 'int foo() { return 0; }'
-nl_func_leave_one_liners = false # false/true
+# Add or remove newlines at the start of the file.
+nl_start_of_file = ignore # ignore/add/remove/force/not_defined
-# Don't split one-line if/else statements - 'if(a) b++;'
-nl_if_leave_one_liners = true # false/true
+# The minimum number of newlines at the start of the file (only used if
+# nl_start_of_file is 'add' or 'force').
+nl_start_of_file_min = 0 # unsigned number
-# Don't split one-line OC messages
-nl_oc_msg_leave_one_liner = false # false/true
+# Add or remove newline at the end of the file.
+nl_end_of_file = ignore # ignore/add/remove/force/not_defined
-# Add or remove newlines at the start of the file
-nl_start_of_file = ignore # ignore/add/remove/force
+# The minimum number of newlines at the end of the file (only used if
+# nl_end_of_file is 'add' or 'force').
+nl_end_of_file_min = 0 # unsigned number
-# The number of newlines at the start of the file (only used if nl_start_of_file is 'add' or 'force'
-nl_start_of_file_min = 0 # number
+# Add or remove newline between '=' and '{'.
+nl_assign_brace = ignore # ignore/add/remove/force/not_defined
-# Add or remove newline at the end of the file
-nl_end_of_file = add # ignore/add/remove/force
+# (D) Add or remove newline between '=' and '['.
+nl_assign_square = ignore # ignore/add/remove/force/not_defined
-# The number of newlines at the end of the file (only used if nl_end_of_file is 'add' or 'force')
-nl_end_of_file_min = 1 # number
+# Add or remove newline between '[]' and '{'.
+nl_tsquare_brace = ignore # ignore/add/remove/force/not_defined
-# Add or remove newline between '=' and '{'
-nl_assign_brace = ignore # ignore/add/remove/force
+# (D) Add or remove newline after '= ['. Will also affect the newline before
+# the ']'.
+nl_after_square_assign = ignore # ignore/add/remove/force/not_defined
-# Add or remove newline between '=' and '[' (D only)
-nl_assign_square = ignore # ignore/add/remove/force
+# Add or remove newline between a function call's ')' and '{', as in
+# 'list_for_each(item, &list) { }'.
+nl_fcall_brace = ignore # ignore/add/remove/force/not_defined
-# Add or remove newline after '= [' (D only). Will also affect the newline before the ']'
-nl_after_square_assign = ignore # ignore/add/remove/force
+# Add or remove newline between 'enum' and '{'.
+nl_enum_brace = ignore # ignore/add/remove/force/not_defined
-# The number of blank lines after a block of variable definitions at the top of a function body
-# 0 = No change (default)
-nl_func_var_def_blk = 1 # number
+# Add or remove newline between 'enum' and 'class'.
+nl_enum_class = ignore # ignore/add/remove/force/not_defined
-# The number of newlines before a block of typedefs
-# 0 = No change (default)
-nl_typedef_blk_start = 0 # number
+# Add or remove newline between 'enum class' and the identifier.
+nl_enum_class_identifier = ignore # ignore/add/remove/force/not_defined
-# The number of newlines after a block of typedefs
-# 0 = No change (default)
-nl_typedef_blk_end = 0 # number
+# Add or remove newline between 'enum class' type and ':'.
+nl_enum_identifier_colon = ignore # ignore/add/remove/force/not_defined
-# The maximum consecutive newlines within a block of typedefs
-# 0 = No change (default)
-nl_typedef_blk_in = 0 # number
+# Add or remove newline between 'enum class identifier :' and type.
+nl_enum_colon_type = ignore # ignore/add/remove/force/not_defined
-# The number of newlines before a block of variable definitions not at the top of a function body
-# 0 = No change (default)
-nl_var_def_blk_start = 0 # number
+# Add or remove newline between 'struct and '{'.
+nl_struct_brace = ignore # ignore/add/remove/force/not_defined
-# The number of newlines after a block of variable definitions not at the top of a function body
-# 0 = No change (default)
-nl_var_def_blk_end = 0 # number
+# Add or remove newline between 'union' and '{'.
+nl_union_brace = ignore # ignore/add/remove/force/not_defined
-# The maximum consecutive newlines within a block of variable definitions
-# 0 = No change (default)
-nl_var_def_blk_in = 0 # number
+# Add or remove newline between 'if' and '{'.
+nl_if_brace = remove # ignore/add/remove/force/not_defined
-# Add or remove newline between a function call's ')' and '{', as in:
-# list_for_each(item, &list) { }
-nl_fcall_brace = ignore # ignore/add/remove/force
+# Add or remove newline between '}' and 'else'.
+nl_brace_else = remove # ignore/add/remove/force/not_defined
-# Add or remove newline between 'enum' and '{'
-nl_enum_brace = ignore # ignore/add/remove/force
+# Add or remove newline between 'else if' and '{'. If set to ignore,
+# nl_if_brace is used instead.
+nl_elseif_brace = ignore # ignore/add/remove/force/not_defined
-# Add or remove newline between 'struct and '{'
-nl_struct_brace = ignore # ignore/add/remove/force
+# Add or remove newline between 'else' and '{'.
+nl_else_brace = ignore # ignore/add/remove/force/not_defined
-# Add or remove newline between 'union' and '{'
-nl_union_brace = ignore # ignore/add/remove/force
+# Add or remove newline between 'else' and 'if'.
+nl_else_if = ignore # ignore/add/remove/force/not_defined
-# Add or remove newline between 'if' and '{'
-nl_if_brace = ignore # ignore/add/remove/force
+# Add or remove newline before '{' opening brace
+nl_before_opening_brace_func_class_def = ignore # ignore/add/remove/force/not_defined
-# Add or remove newline between '}' and 'else'
-nl_brace_else = remove # ignore/add/remove/force
+# Add or remove newline before 'if'/'else if' closing parenthesis.
+nl_before_if_closing_paren = ignore # ignore/add/remove/force/not_defined
-# Add or remove newline between 'else if' and '{'
-# If set to ignore, nl_if_brace is used instead
-nl_elseif_brace = ignore # ignore/add/remove/force
+# Add or remove newline between '}' and 'finally'.
+nl_brace_finally = ignore # ignore/add/remove/force/not_defined
-# Add or remove newline between 'else' and '{'
-nl_else_brace = ignore # ignore/add/remove/force
+# Add or remove newline between 'finally' and '{'.
+nl_finally_brace = ignore # ignore/add/remove/force/not_defined
-# Add or remove newline between 'else' and 'if'
-nl_else_if = ignore # ignore/add/remove/force
+# Add or remove newline between 'try' and '{'.
+nl_try_brace = ignore # ignore/add/remove/force/not_defined
-# Add or remove newline between '}' and 'finally'
-nl_brace_finally = ignore # ignore/add/remove/force
+# Add or remove newline between get/set and '{'.
+nl_getset_brace = ignore # ignore/add/remove/force/not_defined
-# Add or remove newline between 'finally' and '{'
-nl_finally_brace = ignore # ignore/add/remove/force
+# Add or remove newline between 'for' and '{'.
+nl_for_brace = ignore # ignore/add/remove/force/not_defined
-# Add or remove newline between 'try' and '{'
-nl_try_brace = ignore # ignore/add/remove/force
+# Add or remove newline before the '{' of a 'catch' statement, as in
+# 'catch (decl) <here> {'.
+nl_catch_brace = ignore # ignore/add/remove/force/not_defined
-# Add or remove newline between get/set and '{'
-nl_getset_brace = ignore # ignore/add/remove/force
+# (OC) Add or remove newline before the '{' of a '@catch' statement, as in
+# '@catch (decl) <here> {'. If set to ignore, nl_catch_brace is used.
+nl_oc_catch_brace = ignore # ignore/add/remove/force/not_defined
-# Add or remove newline between 'for' and '{'
-nl_for_brace = ignore # ignore/add/remove/force
+# Add or remove newline between '}' and 'catch'.
+nl_brace_catch = ignore # ignore/add/remove/force/not_defined
-# Add or remove newline between 'catch' and '{'
-nl_catch_brace = ignore # ignore/add/remove/force
+# (OC) Add or remove newline between '}' and '@catch'. If set to ignore,
+# nl_brace_catch is used.
+nl_oc_brace_catch = ignore # ignore/add/remove/force/not_defined
-# Add or remove newline between '}' and 'catch'
-nl_brace_catch = ignore # ignore/add/remove/force
+# Add or remove newline between '}' and ']'.
+nl_brace_square = ignore # ignore/add/remove/force/not_defined
-# Add or remove newline between 'while' and '{'
-nl_while_brace = ignore # ignore/add/remove/force
+# Add or remove newline between '}' and ')' in a function invocation.
+nl_brace_fparen = ignore # ignore/add/remove/force/not_defined
-# Add or remove newline between 'scope (x)' and '{' (D)
-nl_scope_brace = ignore # ignore/add/remove/force
+# Add or remove newline between 'while' and '{'.
+nl_while_brace = ignore # ignore/add/remove/force/not_defined
-# Add or remove newline between 'unittest' and '{' (D)
-nl_unittest_brace = ignore # ignore/add/remove/force
+# (D) Add or remove newline between 'scope (x)' and '{'.
+nl_scope_brace = ignore # ignore/add/remove/force/not_defined
-# Add or remove newline between 'version (x)' and '{' (D)
-nl_version_brace = ignore # ignore/add/remove/force
+# (D) Add or remove newline between 'unittest' and '{'.
+nl_unittest_brace = ignore # ignore/add/remove/force/not_defined
-# Add or remove newline between 'using' and '{'
-nl_using_brace = ignore # ignore/add/remove/force
+# (D) Add or remove newline between 'version (x)' and '{'.
+nl_version_brace = ignore # ignore/add/remove/force/not_defined
-# Add or remove newline between two open or close braces.
-# Due to general newline/brace handling, REMOVE may not work.
-nl_brace_brace = ignore # ignore/add/remove/force
+# (C#) Add or remove newline between 'using' and '{'.
+nl_using_brace = ignore # ignore/add/remove/force/not_defined
-# Add or remove newline between 'do' and '{'
-nl_do_brace = ignore # ignore/add/remove/force
+# Add or remove newline between two open or close braces. Due to general
+# newline/brace handling, REMOVE may not work.
+nl_brace_brace = ignore # ignore/add/remove/force/not_defined
-# Add or remove newline between '}' and 'while' of 'do' statement
-nl_brace_while = ignore # ignore/add/remove/force
+# Add or remove newline between 'do' and '{'.
+nl_do_brace = ignore # ignore/add/remove/force/not_defined
-# Add or remove newline between 'switch' and '{'
-nl_switch_brace = ignore # ignore/add/remove/force
+# Add or remove newline between '}' and 'while' of 'do' statement.
+nl_brace_while = ignore # ignore/add/remove/force/not_defined
-# Add a newline between ')' and '{' if the ')' is on a different line than the if/for/etc.
-# Overrides nl_for_brace, nl_if_brace, nl_switch_brace, nl_while_switch, and nl_catch_brace.
-nl_multi_line_cond = false # false/true
+# Add or remove newline between 'switch' and '{'.
+nl_switch_brace = ignore # ignore/add/remove/force/not_defined
+
+# Add or remove newline between 'synchronized' and '{'.
+nl_synchronized_brace = ignore # ignore/add/remove/force/not_defined
+
+# Add a newline between ')' and '{' if the ')' is on a different line than the
+# if/for/etc.
+#
+# Overrides nl_for_brace, nl_if_brace, nl_switch_brace, nl_while_switch and
+# nl_catch_brace.
+nl_multi_line_cond = false # true/false
+
+# Add a newline after '(' if an if/for/while/switch condition spans multiple
+# lines
+nl_multi_line_sparen_open = ignore # ignore/add/remove/force/not_defined
+
+# Add a newline before ')' if an if/for/while/switch condition spans multiple
+# lines. Overrides nl_before_if_closing_paren if both are specified.
+nl_multi_line_sparen_close = remove # ignore/add/remove/force/not_defined
# Force a newline in a define after the macro name for multi-line defines.
-nl_multi_line_define = false # false/true
+nl_multi_line_define = false # true/false
-# Whether to put a newline before 'case' statement
-nl_before_case = true # false/true
+# Whether to add a newline before 'case', and a blank line before a 'case'
+# statement that follows a ';' or '}'.
+nl_before_case = false # true/false
-# Add or remove newline between ')' and 'throw'
-nl_before_throw = ignore # ignore/add/remove/force
+# Whether to add a newline after a 'case' statement.
+nl_after_case = false # true/false
-# Whether to put a newline after 'case' statement
-nl_after_case = true # false/true
+# Add or remove newline between a case ':' and '{'.
+#
+# Overrides nl_after_case.
+nl_case_colon_brace = ignore # ignore/add/remove/force/not_defined
-# Add or remove a newline between a case ':' and '{'. Overrides nl_after_case.
-nl_case_colon_brace = ignore # ignore/add/remove/force
+# Add or remove newline between ')' and 'throw'.
+nl_before_throw = ignore # ignore/add/remove/force/not_defined
-# Newline between namespace and {
-nl_namespace_brace = remove # ignore/add/remove/force
+# Add or remove newline between 'namespace' and '{'.
+nl_namespace_brace = ignore # ignore/add/remove/force/not_defined
-# Add or remove newline between 'template<>' and whatever follows.
-nl_template_class = ignore # ignore/add/remove/force
+# Add or remove newline after 'template<...>' of a template class.
+nl_template_class = ignore # ignore/add/remove/force/not_defined
-# Add or remove newline between 'class' and '{'
-nl_class_brace = remove # ignore/add/remove/force
+# Add or remove newline after 'template<...>' of a template class declaration.
+#
+# Overrides nl_template_class.
+nl_template_class_decl = ignore # ignore/add/remove/force/not_defined
-# Add or remove newline after each ',' in the constructor member initialization
-nl_class_init_args = add # ignore/add/remove/force
+# Add or remove newline after 'template<>' of a specialized class declaration.
+#
+# Overrides nl_template_class_decl.
+nl_template_class_decl_special = ignore # ignore/add/remove/force/not_defined
-# Add or remove newline between return type and function name in a function definition
-nl_func_type_name = ignore # ignore/add/remove/force
+# Add or remove newline after 'template<...>' of a template class definition.
+#
+# Overrides nl_template_class.
+nl_template_class_def = ignore # ignore/add/remove/force/not_defined
-# Add or remove newline between return type and function name inside a class {}
-# Uses nl_func_type_name or nl_func_proto_type_name if set to ignore.
-nl_func_type_name_class = ignore # ignore/add/remove/force
+# Add or remove newline after 'template<>' of a specialized class definition.
+#
+# Overrides nl_template_class_def.
+nl_template_class_def_special = ignore # ignore/add/remove/force/not_defined
+
+# Add or remove newline after 'template<...>' of a template function.
+nl_template_func = ignore # ignore/add/remove/force/not_defined
+
+# Add or remove newline after 'template<...>' of a template function
+# declaration.
+#
+# Overrides nl_template_func.
+nl_template_func_decl = ignore # ignore/add/remove/force/not_defined
-# Add or remove newline between function scope and name in a definition
-# Controls the newline after '::' in 'void A::f() { }'
-nl_func_scope_name = ignore # ignore/add/remove/force
+# Add or remove newline after 'template<>' of a specialized function
+# declaration.
+#
+# Overrides nl_template_func_decl.
+nl_template_func_decl_special = ignore # ignore/add/remove/force/not_defined
+
+# Add or remove newline after 'template<...>' of a template function
+# definition.
+#
+# Overrides nl_template_func.
+nl_template_func_def = ignore # ignore/add/remove/force/not_defined
-# Add or remove newline between return type and function name in a prototype
-nl_func_proto_type_name = ignore # ignore/add/remove/force
+# Add or remove newline after 'template<>' of a specialized function
+# definition.
+#
+# Overrides nl_template_func_def.
+nl_template_func_def_special = ignore # ignore/add/remove/force/not_defined
-# Add or remove newline between a function name and the opening '('
-nl_func_paren = ignore # ignore/add/remove/force
+# Add or remove newline after 'template<...>' of a template variable.
+nl_template_var = ignore # ignore/add/remove/force/not_defined
-# Add or remove newline between a function name and the opening '(' in the definition
-nl_func_def_paren = ignore # ignore/add/remove/force
+# Add or remove newline between 'template<...>' and 'using' of a templated
+# type alias.
+nl_template_using = ignore # ignore/add/remove/force/not_defined
-# Add or remove newline after '(' in a function declaration
-nl_func_decl_start = ignore # ignore/add/remove/force
+# Add or remove newline between 'class' and '{'.
+nl_class_brace = ignore # ignore/add/remove/force/not_defined
-# Add or remove newline after '(' in a function definition
-nl_func_def_start = ignore # ignore/add/remove/force
+# Add or remove newline before or after (depending on pos_class_comma,
+# may not be IGNORE) each',' in the base class list.
+nl_class_init_args = ignore # ignore/add/remove/force/not_defined
+
+# Add or remove newline after each ',' in the constructor member
+# initialization. Related to nl_constr_colon, pos_constr_colon and
+# pos_constr_comma.
+nl_constr_init_args = ignore # ignore/add/remove/force/not_defined
+
+# Add or remove newline before first element, after comma, and after last
+# element, in 'enum'.
+nl_enum_own_lines = ignore # ignore/add/remove/force/not_defined
+
+# Add or remove newline between return type and function name in a function
+# definition.
+# might be modified by nl_func_leave_one_liners
+nl_func_type_name = remove # ignore/add/remove/force/not_defined
+
+# Add or remove newline between return type and function name inside a class
+# definition. If set to ignore, nl_func_type_name or nl_func_proto_type_name
+# is used instead.
+nl_func_type_name_class = ignore # ignore/add/remove/force/not_defined
+
+# Add or remove newline between class specification and '::'
+# in 'void A::f() { }'. Only appears in separate member implementation (does
+# not appear with in-line implementation).
+nl_func_class_scope = ignore # ignore/add/remove/force/not_defined
+
+# Add or remove newline between function scope and name, as in
+# 'void A :: <here> f() { }'.
+nl_func_scope_name = ignore # ignore/add/remove/force/not_defined
+
+# Add or remove newline between return type and function name in a prototype.
+nl_func_proto_type_name = ignore # ignore/add/remove/force/not_defined
+
+# Add or remove newline between a function name and the opening '(' in the
+# declaration.
+nl_func_paren = ignore # ignore/add/remove/force/not_defined
+
+# Overrides nl_func_paren for functions with no parameters.
+nl_func_paren_empty = ignore # ignore/add/remove/force/not_defined
+
+# Add or remove newline between a function name and the opening '(' in the
+# definition.
+nl_func_def_paren = ignore # ignore/add/remove/force/not_defined
+
+# Overrides nl_func_def_paren for functions with no parameters.
+nl_func_def_paren_empty = ignore # ignore/add/remove/force/not_defined
+
+# Add or remove newline between a function name and the opening '(' in the
+# call.
+nl_func_call_paren = ignore # ignore/add/remove/force/not_defined
+
+# Overrides nl_func_call_paren for functions with no parameters.
+nl_func_call_paren_empty = ignore # ignore/add/remove/force/not_defined
+
+# Add or remove newline after '(' in a function declaration.
+nl_func_decl_start = ignore # ignore/add/remove/force/not_defined
+
+# Add or remove newline after '(' in a function definition.
+nl_func_def_start = remove # ignore/add/remove/force/not_defined
# Overrides nl_func_decl_start when there is only one parameter.
-nl_func_decl_start_single = ignore # ignore/add/remove/force
+nl_func_decl_start_single = ignore # ignore/add/remove/force/not_defined
# Overrides nl_func_def_start when there is only one parameter.
-nl_func_def_start_single = ignore # ignore/add/remove/force
+nl_func_def_start_single = ignore # ignore/add/remove/force/not_defined
+
+# Whether to add a newline after '(' in a function declaration if '(' and ')'
+# are in different lines. If false, nl_func_decl_start is used instead.
+nl_func_decl_start_multi_line = false # true/false
-# Add or remove newline after each ',' in a function declaration
-nl_func_decl_args = add # ignore/add/remove/force
+# Whether to add a newline after '(' in a function definition if '(' and ')'
+# are in different lines. If false, nl_func_def_start is used instead.
+nl_func_def_start_multi_line = false # true/false
-# Add or remove newline after each ',' in a function definition
-nl_func_def_args = ignore # ignore/add/remove/force
+# Add or remove newline after each ',' in a function declaration.
+nl_func_decl_args = ignore # ignore/add/remove/force/not_defined
-# Add or remove newline before the ')' in a function declaration
-nl_func_decl_end = ignore # ignore/add/remove/force
+# Add or remove newline after each ',' in a function definition.
+nl_func_def_args = remove # ignore/add/remove/force/not_defined
-# Add or remove newline before the ')' in a function definition
-nl_func_def_end = ignore # ignore/add/remove/force
+# Add or remove newline after each ',' in a function call.
+nl_func_call_args = ignore # ignore/add/remove/force/not_defined
+
+# Whether to add a newline after each ',' in a function declaration if '('
+# and ')' are in different lines. If false, nl_func_decl_args is used instead.
+nl_func_decl_args_multi_line = false # true/false
+
+# Whether to add a newline after each ',' in a function definition if '('
+# and ')' are in different lines. If false, nl_func_def_args is used instead.
+nl_func_def_args_multi_line = false # true/false
+
+# Add or remove newline before the ')' in a function declaration.
+nl_func_decl_end = ignore # ignore/add/remove/force/not_defined
+
+# Add or remove newline before the ')' in a function definition.
+nl_func_def_end = remove # ignore/add/remove/force/not_defined
# Overrides nl_func_decl_end when there is only one parameter.
-nl_func_decl_end_single = ignore # ignore/add/remove/force
+nl_func_decl_end_single = ignore # ignore/add/remove/force/not_defined
# Overrides nl_func_def_end when there is only one parameter.
-nl_func_def_end_single = ignore # ignore/add/remove/force
+nl_func_def_end_single = ignore # ignore/add/remove/force/not_defined
+
+# Whether to add a newline before ')' in a function declaration if '(' and ')'
+# are in different lines. If false, nl_func_decl_end is used instead.
+nl_func_decl_end_multi_line = false # true/false
+
+# Whether to add a newline before ')' in a function definition if '(' and ')'
+# are in different lines. If false, nl_func_def_end is used instead.
+nl_func_def_end_multi_line = false # true/false
# Add or remove newline between '()' in a function declaration.
-nl_func_decl_empty = ignore # ignore/add/remove/force
+nl_func_decl_empty = ignore # ignore/add/remove/force/not_defined
# Add or remove newline between '()' in a function definition.
-nl_func_def_empty = ignore # ignore/add/remove/force
+nl_func_def_empty = ignore # ignore/add/remove/force/not_defined
+
+# Add or remove newline between '()' in a function call.
+nl_func_call_empty = ignore # ignore/add/remove/force/not_defined
+
+# Whether to add a newline after '(' in a function call,
+# has preference over nl_func_call_start_multi_line.
+nl_func_call_start = remove # ignore/add/remove/force/not_defined
+
+# Whether to add a newline before ')' in a function call.
+nl_func_call_end = ignore # ignore/add/remove/force/not_defined
+
+# Whether to add a newline after '(' in a function call if '(' and ')' are in
+# different lines.
+nl_func_call_start_multi_line = false # true/false
+
+# Whether to add a newline after each ',' in a function call if '(' and ')'
+# are in different lines.
+nl_func_call_args_multi_line = false # true/false
+
+# Whether to add a newline before ')' in a function call if '(' and ')' are in
+# different lines.
+nl_func_call_end_multi_line = false # true/false
+
+# Whether to respect nl_func_call_XXX option in case of closure args.
+nl_func_call_args_multi_line_ignore_closures = false # true/false
+
+# Whether to add a newline after '<' of a template parameter list.
+nl_template_start = false # true/false
+
+# Whether to add a newline after each ',' in a template parameter list.
+nl_template_args = false # true/false
+
+# Whether to add a newline before '>' of a template parameter list.
+nl_template_end = false # true/false
-# Whether to put each OC message parameter on a separate line
-# See nl_oc_msg_leave_one_liner
-nl_oc_msg_args = false # false/true
+# (OC) Whether to put each Objective-C message parameter on a separate line.
+# See nl_oc_msg_leave_one_liner.
+nl_oc_msg_args = false # true/false
-# Add or remove newline between function signature and '{'
-nl_fdef_brace = ignore # ignore/add/remove/force
+# Add or remove newline between function signature and '{'.
+nl_fdef_brace = ignore # ignore/add/remove/force/not_defined
-# Add or remove a newline between the return keyword and return expression.
-nl_return_expr = ignore # ignore/add/remove/force
+# Add or remove newline between function signature and '{',
+# if signature ends with ')'. Overrides nl_fdef_brace.
+nl_fdef_brace_cond = ignore # ignore/add/remove/force/not_defined
-# Whether to put a newline after semicolons, except in 'for' statements
-nl_after_semicolon = false # false/true
+# Add or remove newline between C++11 lambda signature and '{'.
+nl_cpp_ldef_brace = ignore # ignore/add/remove/force/not_defined
-# Whether to put a newline after brace open.
-# This also adds a newline before the matching brace close.
-nl_after_brace_open = false # false/true
+# Add or remove newline between 'return' and the return expression.
+nl_return_expr = ignore # ignore/add/remove/force/not_defined
-# If nl_after_brace_open and nl_after_brace_open_cmt are true, a newline is
-# placed between the open brace and a trailing single-line comment.
-nl_after_brace_open_cmt = false # false/true
+# Whether to add a newline after semicolons, except in 'for' statements.
+nl_after_semicolon = false # true/false
-# Whether to put a newline after a virtual brace open with a non-empty body.
+# (Java) Add or remove newline between the ')' and '{{' of the double brace
+# initializer.
+nl_paren_dbrace_open = ignore # ignore/add/remove/force/not_defined
+
+# Whether to add a newline after the type in an unnamed temporary
+# direct-list-initialization.
+nl_type_brace_init_lst = ignore # ignore/add/remove/force/not_defined
+
+# Whether to add a newline after the open brace in an unnamed temporary
+# direct-list-initialization.
+nl_type_brace_init_lst_open = ignore # ignore/add/remove/force/not_defined
+
+# Whether to add a newline before the close brace in an unnamed temporary
+# direct-list-initialization.
+nl_type_brace_init_lst_close = ignore # ignore/add/remove/force/not_defined
+
+# Whether to add a newline before '{'.
+nl_before_brace_open = false # true/false
+
+# Whether to add a newline after '{'.
+nl_after_brace_open = false # true/false
+
+# Whether to add a newline between the open brace and a trailing single-line
+# comment. Requires nl_after_brace_open=true.
+nl_after_brace_open_cmt = false # true/false
+
+# Whether to add a newline after a virtual brace open with a non-empty body.
# These occur in un-braced if/while/do/for statement bodies.
-nl_after_vbrace_open = false # false/true
+nl_after_vbrace_open = false # true/false
-# Whether to put a newline after a virtual brace open with an empty body.
+# Whether to add a newline after a virtual brace open with an empty body.
# These occur in un-braced if/while/do/for statement bodies.
-nl_after_vbrace_open_empty = false # false/true
+nl_after_vbrace_open_empty = false # true/false
-# Whether to put a newline after a brace close.
-# Does not apply if followed by a necessary ';'.
-nl_after_brace_close = false # false/true
+# Whether to add a newline after '}'. Does not apply if followed by a
+# necessary ';'.
+nl_after_brace_close = false # true/false
-# Whether to put a newline after a virtual brace close.
-# Would add a newline before return in: 'if (foo) a++; return;'
-nl_after_vbrace_close = false # false/true
+# Whether to add a newline after a virtual brace close,
+# as in 'if (foo) a++; <here> return;'.
+nl_after_vbrace_close = false # true/false
-# Control the newline between the close brace and 'b' in: 'struct { int a; } b;'
-# Affects enums, unions, and structures. If set to ignore, uses nl_after_brace_close
-nl_brace_struct_var = ignore # ignore/add/remove/force
+# Add or remove newline between the close brace and identifier,
+# as in 'struct { int a; } <here> b;'. Affects enumerations, unions and
+# structures. If set to ignore, uses nl_after_brace_close.
+nl_brace_struct_var = ignore # ignore/add/remove/force/not_defined
-# Whether to alter newlines in '#define' macros
-nl_define_macro = true # false/true
+# Whether to alter newlines in '#define' macros.
+nl_define_macro = false # true/false
-# Whether to not put blanks after '#ifxx', '#elxx', or before '#endif'
-nl_squeeze_ifdef = false # false/true
+# Whether to alter newlines between consecutive parenthesis closes. The number
+# of closing parentheses in a line will depend on respective open parenthesis
+# lines.
+nl_squeeze_paren_close = false # true/false
-# Add or remove blank line before 'if'
-nl_before_if = add # ignore/add/remove/force
+# Whether to remove blanks after '#ifxx' and '#elxx', or before '#elxx' and
+# '#endif'. Does not affect top-level #ifdefs.
+nl_squeeze_ifdef = false # true/false
-# Add or remove blank line after 'if' statement
-nl_after_if = ignore # ignore/add/remove/force
+# Makes the nl_squeeze_ifdef option affect the top-level #ifdefs as well.
+nl_squeeze_ifdef_top_level = false # true/false
-# Add or remove blank line before 'for'
-nl_before_for = add # ignore/add/remove/force
+# Add or remove blank line before 'if'.
+nl_before_if = ignore # ignore/add/remove/force/not_defined
-# Add or remove blank line after 'for' statement
-nl_after_for = ignore # ignore/add/remove/force
+# Add or remove blank line after 'if' statement. Add/Force work only if the
+# next token is not a closing brace.
+nl_after_if = ignore # ignore/add/remove/force/not_defined
-# Add or remove blank line before 'while'
-nl_before_while = add # ignore/add/remove/force
+# Add or remove blank line before 'for'.
+nl_before_for = ignore # ignore/add/remove/force/not_defined
-# Add or remove blank line after 'while' statement
-nl_after_while = ignore # ignore/add/remove/force
+# Add or remove blank line after 'for' statement.
+nl_after_for = ignore # ignore/add/remove/force/not_defined
-# Add or remove blank line before 'switch'
-nl_before_switch = add # ignore/add/remove/force
+# Add or remove blank line before 'while'.
+nl_before_while = ignore # ignore/add/remove/force/not_defined
-# Add or remove blank line after 'switch' statement
-nl_after_switch = ignore # ignore/add/remove/force
+# Add or remove blank line after 'while' statement.
+nl_after_while = ignore # ignore/add/remove/force/not_defined
-# Add or remove blank line before 'do'
-nl_before_do = add # ignore/add/remove/force
+# Add or remove blank line before 'switch'.
+nl_before_switch = ignore # ignore/add/remove/force/not_defined
-# Add or remove blank line after 'do/while' statement
-nl_after_do = ignore # ignore/add/remove/force
+# Add or remove blank line after 'switch' statement.
+nl_after_switch = ignore # ignore/add/remove/force/not_defined
-# Whether to double-space commented-entries in struct/enum
-nl_ds_struct_enum_cmt = true # false/true
+# Add or remove blank line before 'synchronized'.
+nl_before_synchronized = ignore # ignore/add/remove/force/not_defined
-# Whether to double-space before the close brace of a struct/union/enum
-# (lower priority than 'eat_blanks_before_close_brace')
-nl_ds_struct_enum_close_brace = true # false/true
+# Add or remove blank line after 'synchronized' statement.
+nl_after_synchronized = ignore # ignore/add/remove/force/not_defined
-# Add or remove a newline around a class colon.
-# Related to pos_class_colon, nl_class_init_args, and pos_comma.
-nl_class_colon = ignore # ignore/add/remove/force
+# Add or remove blank line before 'do'.
+nl_before_do = ignore # ignore/add/remove/force/not_defined
-# Change simple unbraced if statements into a one-liner
-# 'if(b)\n i++;' => 'if(b) i++;'
-nl_create_if_one_liner = true # false/true
+# Add or remove blank line after 'do/while' statement.
+nl_after_do = ignore # ignore/add/remove/force/not_defined
-# Change simple unbraced for statements into a one-liner
-# 'for (i=0;i<5;i++)\n foo(i);' => 'for (i=0;i<5;i++) foo(i);'
-nl_create_for_one_liner = true # false/true
+# Ignore nl_before_{if,for,switch,do,synchronized} if the control
+# statement is immediately after a case statement.
+# if nl_before_{if,for,switch,do} is set to remove, this option
+# does nothing.
+nl_before_ignore_after_case = false # true/false
-# Change simple unbraced while statements into a one-liner
-# 'while (i<5)\n foo(i++);' => 'while (i<5) foo(i++);'
-nl_create_while_one_liner = true # false/true
+# Whether to put a blank line before 'return' statements, unless after an open
+# brace.
+nl_before_return = false # true/false
-#
-# Positioning options
-#
+# Whether to put a blank line after 'return' statements, unless followed by a
+# close brace.
+nl_after_return = false # true/false
+
+# Whether to put a blank line before a member '.' or '->' operators.
+nl_before_member = ignore # ignore/add/remove/force/not_defined
+
+# (Java) Whether to put a blank line after a member '.' or '->' operators.
+nl_after_member = ignore # ignore/add/remove/force/not_defined
+
+# Whether to double-space commented-entries in 'struct'/'union'/'enum'.
+nl_ds_struct_enum_cmt = false # true/false
+
+# Whether to force a newline before '}' of a 'struct'/'union'/'enum'.
+# (Lower priority than eat_blanks_before_close_brace.)
+nl_ds_struct_enum_close_brace = false # true/false
+
+# Add or remove newline before or after (depending on pos_class_colon) a class
+# colon, as in 'class Foo <here> : <or here> public Bar'.
+nl_class_colon = ignore # ignore/add/remove/force/not_defined
+
+# Add or remove newline around a class constructor colon. The exact position
+# depends on nl_constr_init_args, pos_constr_colon and pos_constr_comma.
+nl_constr_colon = ignore # ignore/add/remove/force/not_defined
-# The position of arithmetic operators in wrapped expressions
-pos_arith = ignore # ignore/join/lead/lead_break/lead_force/trail/trail_break/trail_force
+# Whether to collapse a two-line namespace, like 'namespace foo\n{ decl; }'
+# into a single line. If true, prevents other brace newline rules from turning
+# such code into four lines.
+nl_namespace_two_to_one_liner = false # true/false
-# The position of assignment in wrapped expressions.
-# Do not affect '=' followed by '{'
-pos_assign = ignore # ignore/join/lead/lead_break/lead_force/trail/trail_break/trail_force
+# Whether to remove a newline in simple unbraced if statements, turning them
+# into one-liners, as in 'if(b)\n i++;' => 'if(b) i++;'.
+nl_create_if_one_liner = false # true/false
-# The position of boolean operators in wrapped expressions
-pos_bool = lead_break # ignore/join/lead/lead_break/lead_force/trail/trail_break/trail_force
+# Whether to remove a newline in simple unbraced for statements, turning them
+# into one-liners, as in 'for (...)\n stmt;' => 'for (...) stmt;'.
+nl_create_for_one_liner = false # true/false
-# The position of comparison operators in wrapped expressions
-pos_compare = ignore # ignore/join/lead/lead_break/lead_force/trail/trail_break/trail_force
+# Whether to remove a newline in simple unbraced while statements, turning
+# them into one-liners, as in 'while (expr)\n stmt;' => 'while (expr) stmt;'.
+nl_create_while_one_liner = false # true/false
-# The position of conditional (b ? t : f) operators in wrapped expressions
-pos_conditional = ignore # ignore/join/lead/lead_break/lead_force/trail/trail_break/trail_force
+# Whether to collapse a function definition whose body (not counting braces)
+# is only one line so that the entire definition (prototype, braces, body) is
+# a single line.
+nl_create_func_def_one_liner = false # true/false
-# The position of the comma in wrapped expressions
-pos_comma = ignore # ignore/join/lead/lead_break/lead_force/trail/trail_break/trail_force
+# Whether to split one-line simple list definitions into three lines by
+# adding newlines, as in 'int a[12] = { <here> 0 <here> };'.
+nl_create_list_one_liner = false # true/false
-# The position of the comma in the constructor initialization list
-pos_class_comma = ignore # ignore/join/lead/lead_break/lead_force/trail/trail_break/trail_force
+# Whether to split one-line simple unbraced if statements into two lines by
+# adding a newline, as in 'if(b) <here> i++;'.
+nl_split_if_one_liner = false # true/false
-# The position of colons between constructor and member initialization
-pos_class_colon = ignore # ignore/join/lead/lead_break/lead_force/trail/trail_break/trail_force
+# Whether to split one-line simple unbraced for statements into two lines by
+# adding a newline, as in 'for (...) <here> stmt;'.
+nl_split_for_one_liner = false # true/false
+
+# Whether to split one-line simple unbraced while statements into two lines by
+# adding a newline, as in 'while (expr) <here> stmt;'.
+nl_split_while_one_liner = false # true/false
+
+# Don't add a newline before a cpp-comment in a parameter list of a function
+# call.
+donot_add_nl_before_cpp_comment = false # true/false
#
-# Line Splitting options
+# Blank line options
#
-# Try to limit code width to N number of columns
-code_width = 80 # number
+# The maximum number of consecutive newlines (3 = 2 blank lines).
+nl_max = 0 # unsigned number
+
+# The maximum number of consecutive newlines in a function.
+nl_max_blank_in_func = 0 # unsigned number
+
+# The number of newlines inside an empty function body.
+# This option overrides eat_blanks_after_open_brace and
+# eat_blanks_before_close_brace, but is ignored when
+# nl_collapse_empty_body=true
+nl_inside_empty_func = 0 # unsigned number
+
+# The number of newlines before a function prototype.
+nl_before_func_body_proto = 0 # unsigned number
+
+# The number of newlines before a multi-line function definition. Where
+# applicable, this option is overridden with eat_blanks_after_open_brace=true
+nl_before_func_body_def = 0 # unsigned number
+
+# The number of newlines before a class constructor/destructor prototype.
+nl_before_func_class_proto = 0 # unsigned number
+
+# The number of newlines before a class constructor/destructor definition.
+nl_before_func_class_def = 0 # unsigned number
-# Whether to fully split long 'for' statements at semi-colons
-ls_for_split_full = false # false/true
+# The number of newlines after a function prototype.
+nl_after_func_proto = 0 # unsigned number
-# Whether to fully split long function protos/calls at commas
-ls_func_split_full = true # false/true
+# The number of newlines after a function prototype, if not followed by
+# another function prototype.
+nl_after_func_proto_group = 0 # unsigned number
-# Whether to split lines as close to code_width as possible and ignore some groupings
-ls_code_width = false # false/true
+# The number of newlines after a class constructor/destructor prototype.
+nl_after_func_class_proto = 0 # unsigned number
+# The number of newlines after a class constructor/destructor prototype,
+# if not followed by another constructor/destructor prototype.
+nl_after_func_class_proto_group = 0 # unsigned number
+
+# Whether one-line method definitions inside a class body should be treated
+# as if they were prototypes for the purposes of adding newlines.
#
-# Blank line options
+# Requires nl_class_leave_one_liners=true. Overrides nl_before_func_body_def
+# and nl_before_func_class_def for one-liners.
+nl_class_leave_one_liner_groups = false # true/false
+
+# The number of newlines after '}' of a multi-line function body.
+nl_after_func_body = 0 # unsigned number
+
+# The number of newlines after '}' of a multi-line function body in a class
+# declaration. Also affects class constructors/destructors.
#
+# Overrides nl_after_func_body.
+nl_after_func_body_class = 0 # unsigned number
-# The maximum consecutive newlines
-nl_max = 3 # number
+# The number of newlines after '}' of a single line function body. Also
+# affects class constructors/destructors.
+#
+# Overrides nl_after_func_body and nl_after_func_body_class.
+nl_after_func_body_one_liner = 0 # unsigned number
-# The number of newlines after a function prototype, if followed by another function prototype
-nl_after_func_proto = 0 # number
+# The number of blank lines after a block of variable definitions at the top
+# of a function body.
+#
+# 0: No change (default).
+nl_func_var_def_blk = 0 # unsigned number
-# The number of newlines after a function prototype, if not followed by another function prototype
-nl_after_func_proto_group = 0 # number
+# The number of newlines before a block of typedefs. If nl_after_access_spec
+# is non-zero, that option takes precedence.
+#
+# 0: No change (default).
+nl_typedef_blk_start = 0 # unsigned number
-# The number of newlines after '}' of a multi-line function body
-nl_after_func_body = 2 # number
+# The number of newlines after a block of typedefs.
+#
+# 0: No change (default).
+nl_typedef_blk_end = 0 # unsigned number
-# The number of newlines after '}' of a multi-line function body in a class declaration
-nl_after_func_body_class = 0 # number
+# The maximum number of consecutive newlines within a block of typedefs.
+#
+# 0: No change (default).
+nl_typedef_blk_in = 0 # unsigned number
+
+# The number of newlines before a block of variable definitions not at the top
+# of a function body. If nl_after_access_spec is non-zero, that option takes
+# precedence.
+#
+# 0: No change (default).
+nl_var_def_blk_start = 0 # unsigned number
+
+# The number of newlines after a block of variable definitions not at the top
+# of a function body.
+#
+# 0: No change (default).
+nl_var_def_blk_end = 0 # unsigned number
-# The number of newlines after '}' of a single line function body
-nl_after_func_body_one_liner = 2 # number
+# The maximum number of consecutive newlines within a block of variable
+# definitions.
+#
+# 0: No change (default).
+nl_var_def_blk_in = 0 # unsigned number
# The minimum number of newlines before a multi-line comment.
# Doesn't apply if after a brace open or another multi-line comment.
-nl_before_block_comment = 2 # number
+nl_before_block_comment = 0 # unsigned number
# The minimum number of newlines before a single-line C comment.
# Doesn't apply if after a brace open or other single-line C comments.
-nl_before_c_comment = 2 # number
+nl_before_c_comment = 0 # unsigned number
# The minimum number of newlines before a CPP comment.
# Doesn't apply if after a brace open or other CPP comments.
-nl_before_cpp_comment = 2 # number
+nl_before_cpp_comment = 0 # unsigned number
# Whether to force a newline after a multi-line comment.
-nl_after_multiline_comment = true # false/true
+nl_after_multiline_comment = false # true/false
+
+# Whether to force a newline after a label's colon.
+nl_after_label_colon = false # true/false
+
+# The number of newlines before a struct definition.
+nl_before_struct = 0 # unsigned number
-# The number of newlines after '}' or ';' of a struct/enum/union definition
-nl_after_struct = 0 # number
+# The number of newlines after '}' or ';' of a struct/enum/union definition.
+nl_after_struct = 0 # unsigned number
-# The number of newlines after '}' or ';' of a class definition
-nl_after_class = 0 # number
+# The number of newlines before a class definition.
+nl_before_class = 0 # unsigned number
-# The number of newlines before a 'private:', 'public:', 'protected:', 'signals:', or 'slots:' label.
-# Will not change the newline count if after a brace open.
-# 0 = No change.
-nl_before_access_spec = 2 # number
+# The number of newlines after '}' or ';' of a class definition.
+nl_after_class = 0 # unsigned number
-# The number of newlines after a 'private:', 'public:', 'protected:', 'signals:', or 'slots:' label.
-# 0 = No change.
-nl_after_access_spec = 2 # number
+# The number of newlines before a namespace.
+nl_before_namespace = 0 # unsigned number
+
+# The number of newlines after '{' of a namespace. This also adds newlines
+# before the matching '}'.
+#
+# 0: Apply eat_blanks_after_open_brace or eat_blanks_before_close_brace if
+# applicable, otherwise no change.
+#
+# Overrides eat_blanks_after_open_brace and eat_blanks_before_close_brace.
+nl_inside_namespace = 0 # unsigned number
+
+# The number of newlines after '}' of a namespace.
+nl_after_namespace = 0 # unsigned number
+
+# The number of newlines before an access specifier label. This also includes
+# the Qt-specific 'signals:' and 'slots:'. Will not change the newline count
+# if after a brace open.
+#
+# 0: No change (default).
+nl_before_access_spec = 0 # unsigned number
+
+# The number of newlines after an access specifier label. This also includes
+# the Qt-specific 'signals:' and 'slots:'. Will not change the newline count
+# if after a brace open.
+#
+# 0: No change (default).
+#
+# Overrides nl_typedef_blk_start and nl_var_def_blk_start.
+nl_after_access_spec = 0 # unsigned number
-# The number of newlines between a function def and the function comment.
-# 0 = No change.
-nl_comment_func_def = 1 # number
+# The number of newlines between a function definition and the function
+# comment, as in '// comment\n <here> void foo() {...}'.
+#
+# 0: No change (default).
+nl_comment_func_def = 0 # unsigned number
-# The number of newlines after a try-catch-finally block that isn't followed by a brace close.
-# 0 = No change.
-nl_after_try_catch_finally = 1 # number
+# The number of newlines after a try-catch-finally block that isn't followed
+# by a brace close.
+#
+# 0: No change (default).
+nl_after_try_catch_finally = 0 # unsigned number
-# The number of newlines before and after a property, indexer or event decl.
-# 0 = No change.
-nl_around_cs_property = 0 # number
+# (C#) The number of newlines before and after a property, indexer or event
+# declaration.
+#
+# 0: No change (default).
+nl_around_cs_property = 0 # unsigned number
-# The number of newlines between the get/set/add/remove handlers in C#.
-# 0 = No change.
-nl_between_get_set = 0 # number
+# (C#) The number of newlines between the get/set/add/remove handlers.
+#
+# 0: No change (default).
+nl_between_get_set = 0 # unsigned number
-# Add or remove newline between C# property and the '{'
-nl_property_brace = ignore # ignore/add/remove/force
+# (C#) Add or remove newline between property and the '{'.
+nl_property_brace = ignore # ignore/add/remove/force/not_defined
-# Whether to remove blank lines after '{'
-eat_blanks_after_open_brace = true # false/true
+# Whether to remove blank lines after '{'.
+eat_blanks_after_open_brace = true # true/false
-# Whether to remove blank lines before '}'
-eat_blanks_before_close_brace = true # false/true
+# Whether to remove blank lines before '}'.
+eat_blanks_before_close_brace = true # true/false
-# How aggressively to remove extra newlines not in preproc.
-# 0: No change
+# How aggressively to remove extra newlines not in preprocessor.
+#
+# 0: No change (default)
# 1: Remove most newlines not handled by other config
# 2: Remove all newlines and reformat completely by config
-nl_remove_extra_newlines = 0 # number
+nl_remove_extra_newlines = 0 # unsigned number
-# Whether to put a blank line before 'return' statements, unless after an open brace.
-nl_before_return = false # false/true
+# (Java) Add or remove newline after an annotation statement. Only affects
+# annotations that are after a newline.
+nl_after_annotation = ignore # ignore/add/remove/force/not_defined
-# Whether to put a blank line after 'return' statements, unless followed by a close brace.
-nl_after_return = true # false/true
+# (Java) Add or remove newline between two annotations.
+nl_between_annotation = ignore # ignore/add/remove/force/not_defined
-# Whether to put a newline after a Java annotation statement.
-# Only affects annotations that are after a newline.
-nl_after_annotation = ignore # ignore/add/remove/force
+# The number of newlines before a whole-file #ifdef.
+#
+# 0: No change (default).
+nl_before_whole_file_ifdef = 0 # unsigned number
-# Controls the newline between two annotations.
-nl_between_annotation = ignore # ignore/add/remove/force
+# The number of newlines after a whole-file #ifdef.
+#
+# 0: No change (default).
+nl_after_whole_file_ifdef = 0 # unsigned number
+# The number of newlines before a whole-file #endif.
#
-# Code modifying options (non-whitespace)
+# 0: No change (default).
+nl_before_whole_file_endif = 0 # unsigned number
+
+# The number of newlines after a whole-file #endif.
+#
+# 0: No change (default).
+nl_after_whole_file_endif = 0 # unsigned number
+
+#
+# Positioning options
#
-# Add or remove braces on single-line 'do' statement
-mod_full_brace_do = add # ignore/add/remove/force
+# The position of arithmetic operators in wrapped expressions.
+pos_arith = ignore # ignore/break/force/lead/trail/join/lead_break/lead_force/trail_break/trail_force
-# Add or remove braces on single-line 'for' statement
-mod_full_brace_for = add # ignore/add/remove/force
+# The position of assignment in wrapped expressions. Do not affect '='
+# followed by '{'.
+pos_assign = ignore # ignore/break/force/lead/trail/join/lead_break/lead_force/trail_break/trail_force
-# Add or remove braces on single-line function definitions. (Pawn)
-mod_full_brace_function = ignore # ignore/add/remove/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
-# Add or remove braces on single-line 'if' statement. Will not remove the braces if they contain an 'else'.
-mod_full_brace_if = add # ignore/add/remove/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
-# Make all if/elseif/else statements in a chain be braced or not. Overrides mod_full_brace_if.
-# If any must be braced, they are all braced. If all can be unbraced, then the braces are removed.
-mod_full_brace_if_chain = false # false/true
+# The position of conditional operators, as in the '?' and ':' of
+# 'expr ? stmt : stmt', in wrapped expressions.
+pos_conditional = ignore # ignore/break/force/lead/trail/join/lead_break/lead_force/trail_break/trail_force
-# Don't remove braces around statements that span N newlines
-mod_full_brace_nl = 1 # number
+# The position of the comma in wrapped expressions.
+pos_comma = ignore # ignore/break/force/lead/trail/join/lead_break/lead_force/trail_break/trail_force
+
+# The position of the comma in enum entries.
+pos_enum_comma = ignore # ignore/break/force/lead/trail/join/lead_break/lead_force/trail_break/trail_force
+
+# The position of the comma in the base class list if there is more than one
+# line. Affects nl_class_init_args.
+pos_class_comma = ignore # ignore/break/force/lead/trail/join/lead_break/lead_force/trail_break/trail_force
+
+# The position of the comma in the constructor initialization list.
+# Related to nl_constr_colon, nl_constr_init_args and pos_constr_colon.
+pos_constr_comma = ignore # ignore/break/force/lead/trail/join/lead_break/lead_force/trail_break/trail_force
+
+# The position of trailing/leading class colon, between class and base class
+# list. Affects nl_class_colon.
+pos_class_colon = ignore # ignore/break/force/lead/trail/join/lead_break/lead_force/trail_break/trail_force
+
+# The position of colons between constructor and member initialization.
+# Related to nl_constr_colon, nl_constr_init_args and pos_constr_comma.
+pos_constr_colon = ignore # ignore/break/force/lead/trail/join/lead_break/lead_force/trail_break/trail_force
+
+# The position of shift operators in wrapped expressions.
+pos_shift = ignore # ignore/break/force/lead/trail/join/lead_break/lead_force/trail_break/trail_force
+
+#
+# Line splitting options
+#
+
+# Try to limit code width to N columns.
+code_width = 100 # unsigned number
+
+# Whether to fully split long 'for' statements at semi-colons.
+ls_for_split_full = false # true/false
+
+# Whether to fully split long function prototypes/calls at commas.
+# The option ls_code_width has priority over the option ls_func_split_full.
+ls_func_split_full = false # true/false
+
+# Whether to split lines as close to code_width as possible and ignore some
+# groupings.
+# The option ls_code_width has priority over the option ls_func_split_full.
+ls_code_width = false # true/false
+
+#
+# Code alignment options (not left column spaces/tabs)
+#
+
+# Whether to keep non-indenting tabs.
+align_keep_tabs = false # true/false
+
+# Whether to use tabs for aligning.
+align_with_tabs = false # true/false
-# Add or remove braces on single-line 'while' statement
-mod_full_brace_while = add # ignore/add/remove/force
+# Whether to bump out to the next tab when aligning.
+align_on_tabstop = false # true/false
-# Add or remove braces on single-line 'using ()' statement
-mod_full_brace_using = ignore # ignore/add/remove/force
+# Whether to right-align numbers.
+align_number_right = false # true/false
-# Add or remove unnecessary paren on 'return' statement
-mod_paren_on_return = remove # ignore/add/remove/force
+# Whether to keep whitespace not required for alignment.
+align_keep_extra_space = false # true/false
-# Whether to change optional semicolons to real semicolons
-mod_pawn_semicolon = false # false/true
+# Whether to align variable definitions in prototypes and functions.
+align_func_params = false # true/false
-# Add parens on 'while' and 'if' statement around bools
-mod_full_paren_if_bool = true # false/true
+# The span for aligning parameter definitions in function on parameter name.
+#
+# 0: Don't align (default).
+align_func_params_span = 0 # unsigned number
+
+# The threshold for aligning function parameter definitions.
+# Use a negative number for absolute thresholds.
+#
+# 0: No limit (default).
+align_func_params_thresh = 0 # number
+
+# The gap for aligning function parameter definitions.
+align_func_params_gap = 0 # unsigned number
+
+# The span for aligning constructor value.
+#
+# 0: Don't align (default).
+align_constr_value_span = 0 # unsigned number
+
+# The threshold for aligning constructor value.
+# Use a negative number for absolute thresholds.
+#
+# 0: No limit (default).
+align_constr_value_thresh = 0 # number
+
+# The gap for aligning constructor value.
+align_constr_value_gap = 0 # unsigned number
+
+# Whether to align parameters in single-line functions that have the same
+# name. The function names must already be aligned with each other.
+align_same_func_call_params = false # true/false
+
+# The span for aligning function-call parameters for single line functions.
+#
+# 0: Don't align (default).
+align_same_func_call_params_span = 0 # unsigned number
+
+# The threshold for aligning function-call parameters for single line
+# functions.
+# Use a negative number for absolute thresholds.
+#
+# 0: No limit (default).
+align_same_func_call_params_thresh = 0 # number
+
+# The span for aligning variable definitions.
+#
+# 0: Don't align (default).
+align_var_def_span = 0 # unsigned number
+
+# How to consider (or treat) the '*' in the alignment of variable definitions.
+#
+# 0: Part of the type 'void * foo;' (default)
+# 1: Part of the variable 'void *foo;'
+# 2: Dangling 'void *foo;'
+# Dangling: the '*' will not be taken into account when aligning.
+align_var_def_star_style = 0 # unsigned number
+
+# How to consider (or treat) the '&' in the alignment of variable definitions.
+#
+# 0: Part of the type 'long & foo;' (default)
+# 1: Part of the variable 'long &foo;'
+# 2: Dangling 'long &foo;'
+# Dangling: the '&' will not be taken into account when aligning.
+align_var_def_amp_style = 0 # unsigned number
+
+# The threshold for aligning variable definitions.
+# Use a negative number for absolute thresholds.
+#
+# 0: No limit (default).
+align_var_def_thresh = 0 # number
+
+# The gap for aligning variable definitions.
+align_var_def_gap = 0 # unsigned number
+
+# Whether to align the colon in struct bit fields.
+align_var_def_colon = false # true/false
+
+# The gap for aligning the colon in struct bit fields.
+align_var_def_colon_gap = 0 # unsigned number
+
+# Whether to align any attribute after the variable name.
+align_var_def_attribute = false # true/false
+
+# Whether to align inline struct/enum/union variable definitions.
+align_var_def_inline = false # true/false
+
+# The span for aligning on '=' in assignments.
+#
+# 0: Don't align (default).
+align_assign_span = 0 # unsigned number
+
+# The span for aligning on '=' in function prototype modifier.
+#
+# 0: Don't align (default).
+align_assign_func_proto_span = 0 # unsigned number
+
+# The threshold for aligning on '=' in assignments.
+# Use a negative number for absolute thresholds.
+#
+# 0: No limit (default).
+align_assign_thresh = 0 # number
+
+# How to apply align_assign_span to function declaration "assignments", i.e.
+# 'virtual void foo() = 0' or '~foo() = {default|delete}'.
+#
+# 0: Align with other assignments (default)
+# 1: Align with each other, ignoring regular assignments
+# 2: Don't align
+align_assign_decl_func = 0 # unsigned number
-# Whether to remove superfluous semicolons
-mod_remove_extra_semicolon = true # false/true
+# The span for aligning on '=' in enums.
+#
+# 0: Don't align (default).
+align_enum_equ_span = 0 # unsigned number
-# If a function body exceeds the specified number of newlines and doesn't have a comment after
-# the close brace, a comment will be added.
-mod_add_long_function_closebrace_comment = 0 # number
+# The threshold for aligning on '=' in enums.
+# Use a negative number for absolute thresholds.
+#
+# 0: no limit (default).
+align_enum_equ_thresh = 0 # number
-# If a switch body exceeds the specified number of newlines and doesn't have a comment after
-# the close brace, a comment will be added.
-mod_add_long_switch_closebrace_comment = 0 # number
+# The span for aligning class member definitions.
+#
+# 0: Don't align (default).
+align_var_class_span = 0 # unsigned number
-# If an #ifdef body exceeds the specified number of newlines and doesn't have a comment after
-# the #endif, a comment will be added.
-mod_add_long_ifdef_endif_comment = 1 # number
+# The threshold for aligning class member definitions.
+# Use a negative number for absolute thresholds.
+#
+# 0: No limit (default).
+align_var_class_thresh = 0 # number
-# If an #ifdef or #else body exceeds the specified number of newlines and doesn't have a comment after
-# the #else, a comment will be added.
-mod_add_long_ifdef_else_comment = 1 # number
+# The gap for aligning class member definitions.
+align_var_class_gap = 0 # unsigned number
-# If TRUE, will sort consecutive single-line 'import' statements [Java, D]
-mod_sort_import = false # false/true
+# The span for aligning struct/union member definitions.
+#
+# 0: Don't align (default).
+align_var_struct_span = 0 # unsigned number
-# If TRUE, will sort consecutive single-line 'using' statements [C#]
-mod_sort_using = false # false/true
+# The threshold for aligning struct/union member definitions.
+# Use a negative number for absolute thresholds.
+#
+# 0: No limit (default).
+align_var_struct_thresh = 0 # number
-# If TRUE, will sort consecutive single-line '#include' statements [C/C++] and '#import' statements [Obj-C]
-# This is generally a bad idea, as it may break your code.
-mod_sort_include = false # false/true
+# The gap for aligning struct/union member definitions.
+align_var_struct_gap = 0 # unsigned number
-# If TRUE, it will move a 'break' that appears after a fully braced 'case' before the close brace.
-mod_move_case_break = true # false/true
+# The span for aligning struct initializer values.
+#
+# 0: Don't align (default).
+align_struct_init_span = 0 # unsigned number
-# Will add or remove the braces around a fully braced case statement.
-# Will only remove the braces if there are no variable declarations in the block.
-mod_case_brace = ignore # ignore/add/remove/force
+# The span for aligning single-line typedefs.
+#
+# 0: Don't align (default).
+align_typedef_span = 0 # unsigned number
-# If TRUE, it will remove a void 'return;' that appears as the last statement in a function.
-mod_remove_empty_return = true # false/true
+# The minimum space between the type and the synonym of a typedef.
+align_typedef_gap = 0 # unsigned number
+# How to align typedef'd functions with other typedefs.
#
-# Comment modifications
+# 0: Don't mix them at all (default)
+# 1: Align the open parenthesis with the types
+# 2: Align the function type name with the other type names
+align_typedef_func = 0 # unsigned number
+
+# How to consider (or treat) the '*' in the alignment of typedefs.
+#
+# 0: Part of the typedef type, 'typedef int * pint;' (default)
+# 1: Part of type name: 'typedef int *pint;'
+# 2: Dangling: 'typedef int *pint;'
+# Dangling: the '*' will not be taken into account when aligning.
+align_typedef_star_style = 0 # unsigned number
+
+# How to consider (or treat) the '&' in the alignment of typedefs.
+#
+# 0: Part of the typedef type, 'typedef int & intref;' (default)
+# 1: Part of type name: 'typedef int &intref;'
+# 2: Dangling: 'typedef int &intref;'
+# Dangling: the '&' will not be taken into account when aligning.
+align_typedef_amp_style = 0 # unsigned number
+
+# The span for aligning comments that end lines.
#
+# 0: Don't align (default).
+align_right_cmt_span = 0 # unsigned number
-# Try to wrap comments at cmt_width columns
-cmt_width = 80 # number
+# Minimum number of columns between preceding text and a trailing comment in
+# order for the comment to qualify for being aligned. Must be non-zero to have
+# an effect.
+align_right_cmt_gap = 0 # unsigned number
-# Set the comment reflow mode (default: 0)
-# 0: no reflowing (apart from the line wrapping due to cmt_width)
-# 1: no touching at all
-# 2: full reflow
-cmt_reflow_mode = 0 # number
+# If aligning comments, whether to mix with comments after '}' and #endif with
+# less than three spaces before the comment.
+align_right_cmt_mix = false # true/false
-# If false, disable all multi-line comment changes, including cmt_width. keyword substitution, and leading chars.
-# Default is true.
-cmt_indent_multi = true # false/true
+# Whether to only align trailing comments that are at the same brace level.
+align_right_cmt_same_level = false # true/false
-# Whether to group c-comments that look like they are in a block
-cmt_c_group = false # false/true
+# Minimum column at which to align trailing comments. Comments which are
+# aligned beyond this column, but which can be aligned in a lesser column,
+# may be "pulled in".
+#
+# 0: Ignore (default).
+align_right_cmt_at_col = 0 # unsigned number
-# Whether to put an empty '/*' on the first line of the combined c-comment
-cmt_c_nl_start = false # false/true
+# The span for aligning function prototypes.
+#
+# 0: Don't align (default).
+align_func_proto_span = 0 # unsigned number
-# Whether to put a newline before the closing '*/' of the combined c-comment
-cmt_c_nl_end = false # false/true
+# The threshold for aligning function prototypes.
+# Use a negative number for absolute thresholds.
+#
+# 0: No limit (default).
+align_func_proto_thresh = 0 # number
-# Whether to group cpp-comments that look like they are in a block
-cmt_cpp_group = false # false/true
+# Minimum gap between the return type and the function name.
+align_func_proto_gap = 0 # unsigned number
+
+# Whether to align function prototypes on the 'operator' keyword instead of
+# what follows.
+align_on_operator = false # true/false
+
+# Whether to mix aligning prototype and variable declarations. If true,
+# align_var_def_XXX options are used instead of align_func_proto_XXX options.
+align_mix_var_proto = false # true/false
+
+# Whether to align single-line functions with function prototypes.
+# Uses align_func_proto_span.
+align_single_line_func = false # true/false
+
+# Whether to align the open brace of single-line functions.
+# Requires align_single_line_func=true. Uses align_func_proto_span.
+align_single_line_brace = false # true/false
+
+# Gap for align_single_line_brace.
+align_single_line_brace_gap = 0 # unsigned number
+
+# (OC) The span for aligning Objective-C message specifications.
+#
+# 0: Don't align (default).
+align_oc_msg_spec_span = 0 # unsigned number
+
+# Whether to align macros wrapped with a backslash and a newline. This will
+# not work right if the macro contains a multi-line comment.
+align_nl_cont = false # true/false
+
+# Whether to align macro functions and variables together.
+align_pp_define_together = false # true/false
+
+# The span for aligning on '#define' bodies.
+#
+# =0: Don't align (default)
+# >0: Number of lines (including comments) between blocks
+align_pp_define_span = 0 # unsigned number
+
+# The minimum space between label and value of a preprocessor define.
+align_pp_define_gap = 0 # unsigned number
+
+# Whether to align lines that start with '<<' with previous '<<'.
+#
+# Default: true
+align_left_shift = true # true/false
+
+# Whether to align comma-separated statements following '<<' (as used to
+# initialize Eigen matrices).
+align_eigen_comma_init = false # true/false
+
+# Whether to align text after 'asm volatile ()' colons.
+align_asm_colon = false # true/false
+
+# (OC) Span for aligning parameters in an Objective-C message call
+# on the ':'.
+#
+# 0: Don't align.
+align_oc_msg_colon_span = 0 # unsigned number
+
+# (OC) Whether to always align with the first parameter, even if it is too
+# short.
+align_oc_msg_colon_first = false # true/false
+
+# (OC) Whether to align parameters in an Objective-C '+' or '-' declaration
+# on the ':'.
+align_oc_decl_colon = false # true/false
+
+# (OC) Whether to not align parameters in an Objectve-C message call if first
+# colon is not on next line of the message call (the same way Xcode does
+# aligment)
+align_oc_msg_colon_xcode_like = false # true/false
+
+#
+# Comment modification options
+#
+
+# Try to wrap comments at N columns.
+cmt_width = 0 # unsigned number
+
+# How to reflow comments.
+#
+# 0: No reflowing (apart from the line wrapping due to cmt_width) (default)
+# 1: No touching at all
+# 2: Full reflow (enable cmt_indent_multi for indent with line wrapping due to cmt_width)
+cmt_reflow_mode = 0 # unsigned number
+
+# Path to a file that contains regular expressions describing patterns for
+# which the end of one line and the beginning of the next will be folded into
+# the same sentence or paragraph during full comment reflow. The regular
+# expressions are described using ECMAScript syntax. The syntax for this
+# specification is as follows, where "..." indicates the custom regular
+# expression and "n" indicates the nth end_of_prev_line_regex and
+# beg_of_next_line_regex regular expression pair:
+#
+# end_of_prev_line_regex[1] = "...$"
+# beg_of_next_line_regex[1] = "^..."
+# end_of_prev_line_regex[2] = "...$"
+# beg_of_next_line_regex[2] = "^..."
+# .
+# .
+# .
+# end_of_prev_line_regex[n] = "...$"
+# beg_of_next_line_regex[n] = "^..."
+#
+# Note that use of this option overrides the default reflow fold regular
+# expressions, which are internally defined as follows:
+#
+# end_of_prev_line_regex[1] = "[\w,\]\)]$"
+# beg_of_next_line_regex[1] = "^[\w,\[\(]"
+# end_of_prev_line_regex[2] = "\.$"
+# beg_of_next_line_regex[2] = "^[A-Z]"
+cmt_reflow_fold_regex_file = "" # string
+
+# Whether to indent wrapped lines to the start of the encompassing paragraph
+# during full comment reflow (cmt_reflow_mode = 2). Overrides the value
+# specified by cmt_sp_after_star_cont.
+#
+# Note that cmt_align_doxygen_javadoc_tags overrides this option for
+# paragraphs associated with javadoc tags
+cmt_reflow_indent_to_paragraph_start = false # true/false
+
+# Whether to convert all tabs to spaces in comments. If false, tabs in
+# comments are left alone, unless used for indenting.
+cmt_convert_tab_to_spaces = true # true/false
+
+# Whether to apply changes to multi-line comments, including cmt_width,
+# keyword substitution and leading chars.
+#
+# Default: true
+cmt_indent_multi = true # true/false
+
+# Whether to align doxygen javadoc-style tags ('@param', '@return', etc.)
+# and corresponding fields such that groups of consecutive block tags,
+# parameter names, and descriptions align with one another. Overrides that
+# which is specified by the cmt_sp_after_star_cont. If cmt_width > 0, it may
+# be necessary to enable cmt_indent_multi and set cmt_reflow_mode = 2
+# in order to achieve the desired alignment for line-wrapping.
+cmt_align_doxygen_javadoc_tags = false # true/false
+
+# The number of spaces to insert after the star and before doxygen
+# javadoc-style tags (@param, @return, etc). Requires enabling
+# cmt_align_doxygen_javadoc_tags. Overrides that which is specified by the
+# cmt_sp_after_star_cont.
+#
+# Default: 1
+cmt_sp_before_doxygen_javadoc_tags = 1 # unsigned number
+
+# Whether to change trailing, single-line c-comments into cpp-comments.
+cmt_trailing_single_line_c_to_cpp = true # true/false
+
+# Whether to group c-comments that look like they are in a block.
+cmt_c_group = false # true/false
+
+# Whether to put an empty '/*' on the first line of the combined c-comment.
+cmt_c_nl_start = false # true/false
+
+# Whether to add a newline before the closing '*/' of the combined c-comment.
+cmt_c_nl_end = false # true/false
+
+# Whether to change cpp-comments into c-comments.
+cmt_cpp_to_c = false # true/false
+
+# Whether to group cpp-comments that look like they are in a block. Only
+# meaningful if cmt_cpp_to_c=true.
+cmt_cpp_group = false # true/false
# Whether to put an empty '/*' on the first line of the combined cpp-comment
-cmt_cpp_nl_start = false # false/true
+# when converting to a c-comment.
+#
+# Requires cmt_cpp_to_c=true and cmt_cpp_group=true.
+cmt_cpp_nl_start = false # true/false
+
+# Whether to add a newline before the closing '*/' of the combined cpp-comment
+# when converting to a c-comment.
+#
+# Requires cmt_cpp_to_c=true and cmt_cpp_group=true.
+cmt_cpp_nl_end = false # true/false
+
+# Whether to put a star on subsequent comment lines.
+cmt_star_cont = false # true/false
+
+# The number of spaces to insert at the start of subsequent comment lines.
+cmt_sp_before_star_cont = 0 # unsigned number
+
+# The number of spaces to insert after the star on subsequent comment lines.
+cmt_sp_after_star_cont = 0 # unsigned number
-# Whether to put a newline before the closing '*/' of the combined cpp-comment
-cmt_cpp_nl_end = false # false/true
+# For multi-line comments with a '*' lead, remove leading spaces if the first
+# and last lines of the comment are the same length.
+#
+# Default: true
+cmt_multi_check_last = true # true/false
-# Whether to change cpp-comments into c-comments
-cmt_cpp_to_c = false # false/true
+# For multi-line comments with a '*' lead, remove leading spaces if the first
+# and last lines of the comment are the same length AND if the length is
+# bigger as the first_len minimum.
+#
+# Default: 4
+cmt_multi_first_len_minimum = 4 # unsigned number
+
+# Path to a file that contains text to insert at the beginning of a file if
+# the file doesn't start with a C/C++ comment. If the inserted text contains
+# '$(filename)', that will be replaced with the current file's name.
+cmt_insert_file_header = "" # string
+
+# Path to a file that contains text to insert at the end of a file if the
+# file doesn't end with a C/C++ comment. If the inserted text contains
+# '$(filename)', that will be replaced with the current file's name.
+cmt_insert_file_footer = "" # string
+
+# Path to a file that contains text to insert before a function definition if
+# the function isn't preceded by a C/C++ comment. If the inserted text
+# contains '$(function)', '$(javaparam)' or '$(fclass)', these will be
+# replaced with, respectively, the name of the function, the javadoc '@param'
+# and '@return' stuff, or the name of the class to which the member function
+# belongs.
+cmt_insert_func_header = "" # string
+
+# Path to a file that contains text to insert before a class if the class
+# isn't preceded by a C/C++ comment. If the inserted text contains '$(class)',
+# that will be replaced with the class name.
+cmt_insert_class_header = "" # string
+
+# Path to a file that contains text to insert before an Objective-C message
+# specification, if the method isn't preceded by a C/C++ comment. If the
+# inserted text contains '$(message)' or '$(javaparam)', these will be
+# replaced with, respectively, the name of the function, or the javadoc
+# '@param' and '@return' stuff.
+cmt_insert_oc_msg_header = "" # string
+
+# Whether a comment should be inserted if a preprocessor is encountered when
+# stepping backwards from a function name.
+#
+# Applies to cmt_insert_oc_msg_header, cmt_insert_func_header and
+# cmt_insert_class_header.
+cmt_insert_before_preproc = false # true/false
-# Whether to put a star on subsequent comment lines
-cmt_star_cont = false # false/true
+# Whether a comment should be inserted if a function is declared inline to a
+# class definition.
+#
+# Applies to cmt_insert_func_header.
+#
+# Default: true
+cmt_insert_before_inlines = true # true/false
-# The number of spaces to insert at the start of subsequent comment lines
-cmt_sp_before_star_cont = 0 # number
+# Whether a comment should be inserted if the function is a class constructor
+# or destructor.
+#
+# Applies to cmt_insert_func_header.
+cmt_insert_before_ctor_dtor = false # true/false
-# The number of spaces to insert after the star on subsequent comment lines
-cmt_sp_after_star_cont = 0 # number
+#
+# Code modifying options (non-whitespace)
+#
-# For multi-line comments with a '*' lead, remove leading spaces if the first and last lines of
-# the comment are the same length. Default=True
-cmt_multi_check_last = true # false/true
+# Add or remove braces on a single-line 'do' statement.
+mod_full_brace_do = ignore # ignore/add/remove/force/not_defined
-# The filename that contains text to insert at the head of a file if the file doesn't start with a C/C++ comment.
-# Will substitute $(filename) with the current file's name.
-cmt_insert_file_header = "" # string
+# Add or remove braces on a single-line 'for' statement.
+mod_full_brace_for = add # ignore/add/remove/force/not_defined
-# The filename that contains text to insert at the end of a file if the file doesn't end with a C/C++ comment.
-# Will substitute $(filename) with the current file's name.
-cmt_insert_file_footer = "" # string
+# (Pawn) Add or remove braces on a single-line function definition.
+mod_full_brace_function = ignore # ignore/add/remove/force/not_defined
-# The filename that contains text to insert before a function implementation if the function isn't preceded with a C/C++ comment.
-# Will substitute $(function) with the function name and $(javaparam) with the javadoc @param and @return stuff.
-# Will also substitute $(fclass) with the class name: void CFoo::Bar() { ... }
-cmt_insert_func_header = "" # string
+# Add or remove braces on a single-line 'if' statement. Braces will not be
+# removed if the braced statement contains an 'else'.
+mod_full_brace_if = add # ignore/add/remove/force/not_defined
-# The filename that contains text to insert before a class if the class isn't preceded with a C/C++ comment.
-# Will substitute $(class) with the class name.
-cmt_insert_class_header = "" # string
+# Whether to enforce that all blocks of an 'if'/'else if'/'else' chain either
+# have, or do not have, braces. If true, braces will be added if any block
+# needs braces, and will only be removed if they can be removed from all
+# blocks.
+#
+# Overrides mod_full_brace_if.
+mod_full_brace_if_chain = false # true/false
+
+# Whether to add braces to all blocks of an 'if'/'else if'/'else' chain.
+# If true, mod_full_brace_if_chain will only remove braces from an 'if' that
+# does not have an 'else if' or 'else'.
+mod_full_brace_if_chain_only = false # true/false
-# The filename that contains text to insert before an Obj-C message specification if the method isn't preceded with a C/C++ comment.
-# Will substitute $(message) with the function name and $(javaparam) with the javadoc @param and @return stuff.
-cmt_insert_oc_msg_header = "" # string
+# Add or remove braces on single-line 'while' statement.
+mod_full_brace_while = add # ignore/add/remove/force/not_defined
-# If a preprocessor is encountered when stepping backwards from a function name, then
-# this option decides whether the comment should be inserted.
-# Affects cmt_insert_oc_msg_header, cmt_insert_func_header and cmt_insert_class_header.
-cmt_insert_before_preproc = false # false/true
+# Add or remove braces on single-line 'using ()' statement.
+mod_full_brace_using = ignore # ignore/add/remove/force/not_defined
+
+# Don't remove braces around statements that span N newlines
+mod_full_brace_nl = 0 # unsigned number
+
+# Whether to prevent removal of braces from 'if'/'for'/'while'/etc. blocks
+# which span multiple lines.
+#
+# Affects:
+# mod_full_brace_for
+# mod_full_brace_if
+# mod_full_brace_if_chain
+# mod_full_brace_if_chain_only
+# mod_full_brace_while
+# mod_full_brace_using
+#
+# Does not affect:
+# mod_full_brace_do
+# mod_full_brace_function
+mod_full_brace_nl_block_rem_mlcond = false # true/false
+
+# Add or remove unnecessary parenthesis on 'return' statement.
+mod_paren_on_return = ignore # ignore/add/remove/force/not_defined
+
+# (Pawn) Whether to change optional semicolons to real semicolons.
+mod_pawn_semicolon = false # true/false
+
+# Whether to fully parenthesize Boolean expressions in 'while' and 'if'
+# statement, as in 'if (a && b > c)' => 'if (a && (b > c))'.
+mod_full_paren_if_bool = false # true/false
+
+# Whether to remove superfluous semicolons.
+mod_remove_extra_semicolon = false # true/false
+
+# Whether to remove duplicate include.
+mod_remove_duplicate_include = false # true/false
+
+# If a function body exceeds the specified number of newlines and doesn't have
+# a comment after the close brace, a comment will be added.
+mod_add_long_function_closebrace_comment = 0 # unsigned number
+
+# If a namespace body exceeds the specified number of newlines and doesn't
+# have a comment after the close brace, a comment will be added.
+mod_add_long_namespace_closebrace_comment = 0 # unsigned number
+
+# If a class body exceeds the specified number of newlines and doesn't have a
+# comment after the close brace, a comment will be added.
+mod_add_long_class_closebrace_comment = 0 # unsigned number
+
+# If a switch body exceeds the specified number of newlines and doesn't have a
+# comment after the close brace, a comment will be added.
+mod_add_long_switch_closebrace_comment = 0 # unsigned number
+
+# If an #ifdef body exceeds the specified number of newlines and doesn't have
+# a comment after the #endif, a comment will be added.
+mod_add_long_ifdef_endif_comment = 0 # unsigned number
+
+# If an #ifdef or #else body exceeds the specified number of newlines and
+# doesn't have a comment after the #else, a comment will be added.
+mod_add_long_ifdef_else_comment = 0 # unsigned number
+
+# Whether to take care of the case by the mod_sort_xx options.
+mod_sort_case_sensitive = false # true/false
+
+# Whether to sort consecutive single-line 'import' statements.
+mod_sort_import = false # true/false
+
+# (C#) Whether to sort consecutive single-line 'using' statements.
+mod_sort_using = false # true/false
+
+# Whether to sort consecutive single-line '#include' statements (C/C++) and
+# '#import' statements (Objective-C). Be aware that this has the potential to
+# break your code if your includes/imports have ordering dependencies.
+mod_sort_include = true # true/false
+
+# Whether to prioritize '#include' and '#import' statements that contain
+# filename without extension when sorting is enabled.
+mod_sort_incl_import_prioritize_filename = false # true/false
+
+# Whether to prioritize '#include' and '#import' statements that does not
+# contain extensions when sorting is enabled.
+mod_sort_incl_import_prioritize_extensionless = false # true/false
+
+# Whether to prioritize '#include' and '#import' statements that contain
+# angle over quotes when sorting is enabled.
+mod_sort_incl_import_prioritize_angle_over_quotes = true # true/false
+
+# Whether to ignore file extension in '#include' and '#import' statements
+# for sorting comparison.
+mod_sort_incl_import_ignore_extension = false # true/false
+
+# Whether to group '#include' and '#import' statements when sorting is enabled.
+mod_sort_incl_import_grouping_enabled = true # true/false
+
+# Whether to move a 'break' that appears after a fully braced 'case' before
+# the close brace, as in 'case X: { ... } break;' => 'case X: { ... break; }'.
+mod_move_case_break = false # true/false
+
+# Add or remove braces around a fully braced case statement. Will only remove
+# braces if there are no variable declarations in the block.
+mod_case_brace = ignore # ignore/add/remove/force/not_defined
+
+# Whether to remove a void 'return;' that appears as the last statement in a
+# function.
+mod_remove_empty_return = false # true/false
+
+# Add or remove the comma after the last value of an enumeration.
+mod_enum_last_comma = ignore # ignore/add/remove/force/not_defined
+
+# (OC) Whether to organize the properties. If true, properties will be
+# rearranged according to the mod_sort_oc_property_*_weight factors.
+mod_sort_oc_properties = false # true/false
+
+# (OC) Weight of a class property modifier.
+mod_sort_oc_property_class_weight = 0 # number
+
+# (OC) Weight of 'atomic' and 'nonatomic'.
+mod_sort_oc_property_thread_safe_weight = 0 # number
+
+# (OC) Weight of 'readwrite' when organizing properties.
+mod_sort_oc_property_readwrite_weight = 0 # number
+
+# (OC) Weight of a reference type specifier ('retain', 'copy', 'assign',
+# 'weak', 'strong') when organizing properties.
+mod_sort_oc_property_reference_weight = 0 # number
+
+# (OC) Weight of getter type ('getter=') when organizing properties.
+mod_sort_oc_property_getter_weight = 0 # number
+
+# (OC) Weight of setter type ('setter=') when organizing properties.
+mod_sort_oc_property_setter_weight = 0 # number
+
+# (OC) Weight of nullability type ('nullable', 'nonnull', 'null_unspecified',
+# 'null_resettable') when organizing properties.
+mod_sort_oc_property_nullability_weight = 0 # number
#
# Preprocessor options
#
-# Control indent of preprocessors inside #if blocks at brace level 0
-pp_indent = ignore # ignore/add/remove/force
+# Add or remove indentation of preprocessor directives inside #if blocks
+# at brace level 0 (file-level).
+pp_indent = ignore # ignore/add/remove/force/not_defined
-# Whether to indent #if/#else/#endif at the brace level (true) or from column 1 (false)
-pp_indent_at_level = false # false/true
+# Whether to indent #if/#else/#endif at the brace level. If false, these are
+# indented from column 1.
+pp_indent_at_level = false # true/false
+
+# Specifies the number of columns to indent preprocessors per level
+# at brace level 0 (file-level). If pp_indent_at_level=false, also specifies
+# the number of columns to indent preprocessors per level
+# at brace level > 0 (function-level).
+#
+# Default: 1
+pp_indent_count = 1 # unsigned number
-# If pp_indent_at_level=false, specifies the number of columns to indent per level. Default=1.
-pp_indent_count = 1 # number
+# Add or remove space after # based on pp_level of #if blocks.
+pp_space = ignore # ignore/add/remove/force/not_defined
-# Add or remove space after # based on pp_level of #if blocks
-pp_space = add # ignore/add/remove/force
+# Sets the number of spaces per level added with pp_space.
+pp_space_count = 0 # unsigned number
-# Sets the number of spaces added with pp_space
-pp_space_count = 0 # number
+# The indent for '#region' and '#endregion' in C# and '#pragma region' in
+# C/C++. Negative values decrease indent down to the first column.
+pp_indent_region = 0 # number
-# The indent for #region and #endregion in C# and '#pragma region' in C/C++
-pp_indent_region = 0 # number
+# Whether to indent the code between #region and #endregion.
+pp_region_indent_code = false # true/false
-# Whether to indent the code between #region and #endregion
-pp_region_indent_code = false # false/true
+# If pp_indent_at_level=true, sets the indent for #if, #else and #endif when
+# not at file-level. Negative values decrease indent down to the first column.
+#
+# =0: Indent preprocessors using output_tab_size
+# >0: Column at which all preprocessors will be indented
+pp_indent_if = 0 # number
+
+# Whether to indent the code between #if, #else and #endif.
+pp_if_indent_code = false # true/false
+
+# Whether to indent the body of an #if that encompasses all the code in the file.
+pp_indent_in_guard = false # true/false
+
+# Whether to indent '#define' at the brace level. If false, these are
+# indented from column 1.
+pp_define_at_level = false # true/false
+
+# Whether to ignore the '#define' body while formatting.
+pp_ignore_define_body = false # true/false
+
+# Whether to indent case statements between #if, #else, and #endif.
+# Only applies to the indent of the preprocesser that the case statements
+# directly inside of.
+#
+# Default: true
+pp_indent_case = true # true/false
+
+# Whether to indent whole function definitions between #if, #else, and #endif.
+# Only applies to the indent of the preprocesser that the function definition
+# is directly inside of.
+#
+# Default: true
+pp_indent_func_def = true # true/false
+
+# Whether to indent extern C blocks between #if, #else, and #endif.
+# Only applies to the indent of the preprocesser that the extern block is
+# directly inside of.
+#
+# Default: true
+pp_indent_extern = true # true/false
+
+# Whether to indent braces directly inside #if, #else, and #endif.
+# Only applies to the indent of the preprocesser that the braces are directly
+# inside of.
+#
+# Default: true
+pp_indent_brace = true # true/false
+
+#
+# Sort includes options
+#
-# If pp_indent_at_level=true, sets the indent for #if, #else, and #endif when not at file-level
-pp_indent_if = 0 # number
+# The regex for include category with priority 0.
+include_category_0 = "" # string
-# Control whether to indent the code between #if, #else and #endif when not at file-level
-pp_if_indent_code = false # false/true
+# The regex for include category with priority 1.
+include_category_1 = "" # string
-# Whether to indent '#define' at the brace level (true) or from column 1 (false)
-pp_define_at_level = false # false/true
+# The regex for include category with priority 2.
+include_category_2 = "" # string
-# You can force a token to be a type with the 'type' option.
-# Example:
-# type myfoo1 myfoo2
#
-# You can create custom macro-based indentation using macro-open,
-# macro-else and macro-close.
-# Example:
-# macro-open BEGIN_TEMPLATE_MESSAGE_MAP
-# macro-open BEGIN_MESSAGE_MAP
-# macro-close END_MESSAGE_MAP
+# Use or Do not Use options
+#
+
+# true: indent_func_call_param will be used (default)
+# false: indent_func_call_param will NOT be used
+#
+# Default: true
+use_indent_func_call_param = true # true/false
+
+# The value of the indentation for a continuation line is calculated
+# differently if the statement is:
+# - a declaration: your case with QString fileName ...
+# - an assignment: your case with pSettings = new QSettings( ...
+#
+# At the second case the indentation value might be used twice:
+# - at the assignment
+# - at the function call (if present)
+#
+# To prevent the double use of the indentation value, use this option with the
+# value 'true'.
+#
+# true: indent_continue will be used only once
+# false: indent_continue will be used every time (default)
+use_indent_continue_only_once = false # true/false
+
+# The value might be used twice:
+# - at the assignment
+# - at the opening brace
+#
+# To prevent the double use of the indentation value, use this option with the
+# value 'true'.
+#
+# true: indentation will be used only once
+# false: indentation will be used every time (default)
+indent_cpp_lambda_only_once = false # true/false
+
+# Whether sp_after_angle takes precedence over sp_inside_fparen. This was the
+# historic behavior, but is probably not the desired behavior, so this is off
+# by default.
+use_sp_after_angle_always = false # true/false
+
+# Whether to apply special formatting for Qt SIGNAL/SLOT macros. Essentially,
+# this tries to format these so that they match Qt's normalized form (i.e. the
+# result of QMetaObject::normalizedSignature), which can slightly improve the
+# performance of the QObject::connect call, rather than how they would
+# otherwise be formatted.
+#
+# See options_for_QT.cpp for details.
+#
+# Default: true
+use_options_overriding_for_qt_macros = true # true/false
+
+# If true: the form feed character is removed from the list of whitespace
+# characters. See https://en.cppreference.com/w/cpp/string/byte/isspace.
+use_form_feed_no_more_as_whitespace_character = false # true/false
+
+#
+# Warn levels - 1: error, 2: warning (default), 3: note
+#
+
+# (C#) Warning is given if doing tab-to-\t replacement and we have found one
+# in a C# verbatim string literal.
+#
+# Default: 2
+warn_level_tabs_found_in_verbatim_string_literals = 2 # unsigned number
+
+# Limit the number of loops.
+# Used by uncrustify.cpp to exit from infinite loop.
+# 0: no limit.
+debug_max_number_of_loops = 0 # number
+
+# Set the number of the line to protocol;
+# Used in the function prot_the_line if the 2. parameter is zero.
+# 0: nothing protocol.
+debug_line_number_to_protocol = 0 # number
+
+# Set the number of second(s) before terminating formatting the current file,
+# 0: no timeout.
+# only for linux
+debug_timeout = 0 # number
+
+# Set the number of characters to be printed if the text is too long,
+# 0: do not truncate.
+debug_truncate = 0 # unsigned number
+
+# Meaning of the settings:
+# Ignore - do not do any changes
+# Add - makes sure there is 1 or more space/brace/newline/etc
+# Force - makes sure there is exactly 1 space/brace/newline/etc,
+# behaves like Add in some contexts
+# Remove - removes space/brace/newline/etc
+#
+#
+# - Token(s) can be treated as specific type(s) with the 'set' option:
+# `set tokenType tokenString [tokenString...]`
+#
+# Example:
+# `set BOOL __AND__ __OR__`
+#
+# tokenTypes are defined in src/token_enum.h, use them without the
+# 'CT_' prefix: 'CT_BOOL' => 'BOOL'
+#
+#
+# - Token(s) can be treated as type(s) with the 'type' option.
+# `type tokenString [tokenString...]`
+#
+# Example:
+# `type int c_uint_8 Rectangle`
+#
+# This can also be achieved with `set TYPE int c_uint_8 Rectangle`
+#
+#
+# To embed whitespace in tokenStrings use the '\' escape character, or quote
+# the tokenStrings. These quotes are supported: "'`
+#
+#
+# - Support for the auto detection of languages through the file ending can be
+# added using the 'file_ext' command.
+# `file_ext langType langString [langString..]`
+#
+# Example:
+# `file_ext CPP .ch .cxx .cpp.in`
+#
+# langTypes are defined in uncrusify_types.h in the lang_flag_e enum, use
+# them without the 'LANG_' prefix: 'LANG_CPP' => 'CPP'
#
-# You can assign any keyword to any type with the set option.
-# set func_call_user _ N_
#
-# The full syntax description of all custom definition config entries
-# is shown below:
+# - Custom macro-based indentation can be set up using 'macro-open',
+# 'macro-else' and 'macro-close'.
+# `(macro-open | macro-else | macro-close) tokenString`
#
-# define custom tokens as:
-# - embed whitespace in token using '' escape character, or
-# put token in quotes
-# - these: ' " and ` are recognized as quote delimiters
+# Example:
+# `macro-open BEGIN_TEMPLATE_MESSAGE_MAP`
+# `macro-open BEGIN_MESSAGE_MAP`
+# `macro-close END_MESSAGE_MAP`
#
-# type token1 token2 token3 ...
-# ^ optionally specify multiple tokens on a single line
-# define def_token output_token
-# ^ output_token is optional, then NULL is assumed
-# macro-open token
-# macro-close token
-# macro-else token
-# set id token1 token2 ...
-# ^ optionally specify multiple tokens on a single line
-# ^ id is one of the names in token_enum.h sans the CT_ prefix,
-# e.g. PP_PRAGMA
#
-# all tokens are separated by any mix of ',' commas, '=' equal signs
-# and whitespace (space, tab)
+set PREPROC FUNC_API_CHECK_TEXTLOCK
+set PREPROC FUNC_API_DEPRECATED_SINCE
+set PREPROC FUNC_API_FAST
+set PREPROC FUNC_API_LUA_ONLY
+set PREPROC FUNC_API_NOEXPORT
+set PREPROC FUNC_API_REMOTE_ONLY
+set PREPROC FUNC_API_SINCE
+set PREPROC FUNC_ATTR_ALWAYS_INLINE
+set PREPROC FUNC_ATTR_CONST
+set PREPROC FUNC_ATTR_MALLOC
+set PREPROC FUNC_ATTR_NONNULL_ALL
+set PREPROC FUNC_ATTR_NONNULL_ARG
+set PREPROC FUNC_ATTR_NONNULL_RET
+set PREPROC FUNC_ATTR_NORETURN
+set PREPROC FUNC_ATTR_NO_SANITIZE_UNDEFINED
+set PREPROC FUNC_ATTR_PRINTF
+set PREPROC FUNC_ATTR_PURE
+set PREPROC FUNC_ATTR_UNUSED
+set PREPROC FUNC_ATTR_WARN_UNUSED_RESULT
+set PREPROC REAL_FATTR_ALWAYS_INLINE
+set PREPROC REAL_FATTR_CONST
+set PREPROC REAL_FATTR_NONNULL_ALL
+set PREPROC REAL_FATTR_PURE
+set PREPROC REAL_FATTR_WARN_UNUSED_RESULT
+# option(s) with 'not default' value: 56
#
diff --git a/runtime/autoload/man.vim b/runtime/autoload/man.vim
index 4f556e6e87..8bf95651b7 100644
--- a/runtime/autoload/man.vim
+++ b/runtime/autoload/man.vim
@@ -65,6 +65,7 @@ function! man#open_page(count, mods, ...) abort
let b:man_sect = sect
endfunction
+" Called when a man:// buffer is opened.
function! man#read_page(ref) abort
try
let [sect, name] = s:extract_sect_and_name_ref(a:ref)
@@ -121,6 +122,15 @@ function! s:system(cmd, ...) abort
return opts.stdout
endfunction
+function! s:set_options(pager) abort
+ setlocal filetype=man
+ setlocal noswapfile buftype=nofile bufhidden=hide
+ setlocal nomodified readonly nomodifiable
+ if a:pager
+ nnoremap <silent> <buffer> <nowait> q :lclose<CR>:q<CR>
+ endif
+endfunction
+
function! s:get_page(path) abort
" Disable hard-wrap by using a big $MANWIDTH (max 1000 on some systems #9065).
" Soft-wrap: ftplugin/man.vim sets wrap/breakindent/….
@@ -134,9 +144,7 @@ function! s:get_page(path) abort
endfunction
function! s:put_page(page) abort
- setlocal modifiable
- setlocal noreadonly
- setlocal noswapfile
+ setlocal modifiable noreadonly noswapfile
silent keepjumps %delete _
silent put =a:page
while getline(1) =~# '^\s*$'
@@ -148,7 +156,7 @@ function! s:put_page(page) abort
silent! keeppatterns keepjumps %s/\s\{199,}/\=repeat(' ', 10)/g
1
lua require("man").highlight_man_page()
- setlocal filetype=man
+ call s:set_options(v:false)
endfunction
function! man#show_toc() abort
@@ -397,6 +405,7 @@ function! s:format_candidate(path, psect) abort
endif
endfunction
+" Called when Nvim is invoked as $MANPAGER.
function! man#init_pager() abort
" https://github.com/neovim/neovim/issues/6828
let og_modifiable = &modifiable
@@ -420,6 +429,7 @@ function! man#init_pager() abort
execute 'silent file man://'.tolower(fnameescape(ref))
endif
+ call s:set_options(v:true)
let &l:modifiable = og_modifiable
endfunction
diff --git a/runtime/doc/cmdline.txt b/runtime/doc/cmdline.txt
index 2db694cf07..689fb1ecd2 100644
--- a/runtime/doc/cmdline.txt
+++ b/runtime/doc/cmdline.txt
@@ -1140,6 +1140,11 @@ Thus you can resize the command-line window, but not others.
The |getcmdwintype()| function returns the type of the command-line being
edited as described in |cmdwin-char|.
+Nvim defines this default CmdWinEnter autocmd in the "nvim_cmdwin" group: >
+ autocmd CmdWinEnter [:>] syntax sync minlines=1 maxlines=1
+<
+You can disable this in your config with "autocmd! nvim_cmdwin". |default-autocmds|
+
AUTOCOMMANDS
diff --git a/runtime/doc/eval.txt b/runtime/doc/eval.txt
index e02d80252f..87240831a2 100644
--- a/runtime/doc/eval.txt
+++ b/runtime/doc/eval.txt
@@ -669,12 +669,14 @@ Expression syntax summary, from least to most significant:
expr8[expr1 : expr1] substring of a String or sublist of a |List|
expr8.name entry in a |Dictionary|
expr8(expr1, ...) function call with |Funcref| variable
+ expr8->name(expr1, ...) |method| call
|expr9| number number constant
"string" string constant, backslash is special
'string' string constant, ' is doubled
[expr1, ...] |List|
{expr1: expr1, ...} |Dictionary|
+ #{key: expr1, ...} |Dictionary|
&option option value
(expr1) nested expression
variable internal variable
@@ -939,9 +941,11 @@ expr8 *expr8*
-----
This expression is either |expr9| or a sequence of the alternatives below,
in any order. E.g., these are all possible:
- expr9[expr1].name
- expr9.name[expr1]
- expr9(expr1, ...)[expr1].name
+ expr8[expr1].name
+ expr8.name[expr1]
+ expr8(expr1, ...)[expr1].name
+ expr8->(expr1, ...)[expr1]
+Evaluation is always from left to right.
expr8[expr1] item of String or |List| *expr-[]* *E111*
@@ -1043,6 +1047,36 @@ expr8(expr1, ...) |Funcref| function call
When expr8 is a |Funcref| type variable, invoke the function it refers to.
+expr8->name([args]) method call *method* *->*
+expr8->{lambda}([args])
+
+For methods that are also available as global functions this is the same as: >
+ name(expr8 [, args])
+There can also be methods specifically for the type of "expr8".
+
+This allows for chaining, passing the value that one method returns to the
+next method: >
+ mylist->filter(filterexpr)->map(mapexpr)->sort()->join()
+<
+Example of using a lambda: >
+ GetPercentage->{x -> x * 100}()->printf('%d%%')
+<
+When using -> the |expr7| operators will be applied first, thus: >
+ -1.234->string()
+Is equivalent to: >
+ (-1.234)->string()
+And NOT: >
+ -(1.234->string())
+<
+ *E274*
+"->name(" must not contain white space. There can be white space before the
+"->" and after the "(", thus you can split the lines like this: >
+ mylist
+ \ ->filter(filterexpr)
+ \ ->map(mapexpr)
+ \ ->sort()
+ \ ->join()
+<
*expr9*
number
@@ -2583,6 +2617,8 @@ abs({expr}) *abs()*
echo abs(-4)
< 4
+ Can also be used as a |method|: >
+ Compute()->abs()
acos({expr}) *acos()*
Return the arc cosine of {expr} measured in radians, as a
@@ -2595,6 +2631,8 @@ acos({expr}) *acos()*
:echo acos(-0.5)
< 2.094395
+ Can also be used as a |method|: >
+ Compute()->acos()
add({list}, {expr}) *add()*
Append the item {expr} to |List| {list}. Returns the
@@ -2605,12 +2643,16 @@ add({list}, {expr}) *add()*
item. Use |extend()| to concatenate |Lists|.
Use |insert()| to add an item at another position.
+ Can also be used as a |method|: >
+ mylist->add(val1)->add(val2)
and({expr}, {expr}) *and()*
Bitwise AND on the two arguments. The arguments are converted
to a number. A List, Dict or Float argument causes an error.
Example: >
:let flag = and(bits, 0x80)
+< Can also be used as a |method|: >
+ :let flag = bits->and(0x80)
api_info() *api_info()*
Returns Dictionary of |api-metadata|.
@@ -2629,6 +2671,9 @@ append({lnum}, {text}) *append()*
:let failed = append(line('$'), "# THE END")
:let failed = append(0, ["Chapter 1", "the beginning"])
+< Can also be used as a |method| after a List: >
+ mylist->append(lnum)
+
appendbufline({expr}, {lnum}, {text}) *appendbufline()*
Like |append()| but append the text in buffer {expr}.
@@ -2647,8 +2692,10 @@ appendbufline({expr}, {lnum}, {text}) *appendbufline()*
error message is given. Example: >
:let failed = appendbufline(13, 0, "# THE START")
<
- *argc()*
-argc([{winid}])
+ Can also be used as a |method| after a List: >
+ mylist->appendbufline(buf, lnum)
+
+argc([{winid}]) *argc()*
The result is the number of files in the argument list. See
|arglist|.
If {winid} is not supplied, the argument list of the current
@@ -2702,6 +2749,9 @@ asin({expr}) *asin()*
:echo asin(-0.5)
< -0.523599
+ Can also be used as a |method|: >
+ Compute()->asin()
+
assert_ functions are documented here: |assert-functions-details|
@@ -2716,6 +2766,8 @@ atan({expr}) *atan()*
:echo atan(-4.01)
< -1.326405
+ Can also be used as a |method|: >
+ Compute()->atan()
atan2({expr1}, {expr2}) *atan2()*
Return the arc tangent of {expr1} / {expr2}, measured in
@@ -2727,6 +2779,8 @@ atan2({expr1}, {expr2}) *atan2()*
:echo atan2(1, -1)
< 2.356194
+ Can also be used as a |method|: >
+ Compute()->atan2(1)
*browse()*
browse({save}, {title}, {initdir}, {default})
@@ -2737,8 +2791,8 @@ browse({save}, {title}, {initdir}, {default})
{title} title for the requester
{initdir} directory to start browsing in
{default} default file name
- When the "Cancel" button is hit, something went wrong, or
- browsing is not possible, an empty string is returned.
+ An empty string is returned when the "Cancel" button is hit,
+ something went wrong, or browsing is not possible.
*browsedir()*
browsedir({title}, {initdir})
@@ -2760,6 +2814,8 @@ bufadd({name}) *bufadd()*
created buffer. When {name} is an empty string then a new
buffer is always created.
The buffer will not have' 'buflisted' set.
+< Can also be used as a |method|: >
+ let bufnr = 'somename'->bufadd()
bufexists({expr}) *bufexists()*
The result is a Number, which is |TRUE| if a buffer called
@@ -2783,11 +2839,17 @@ bufexists({expr}) *bufexists()*
Use "bufexists(0)" to test for the existence of an alternate
file name.
+ Can also be used as a |method|: >
+ let exists = 'somename'->bufexists()
+
buflisted({expr}) *buflisted()*
The result is a Number, which is |TRUE| if a buffer called
{expr} exists and is listed (has the 'buflisted' option set).
The {expr} argument is used like with |bufexists()|.
+ Can also be used as a |method|: >
+ let listed = 'somename'->buflisted()
+
bufload({expr}) *bufload()*
Ensure the buffer {expr} is loaded. When the buffer name
refers to an existing file then the file is read. Otherwise
@@ -2797,15 +2859,21 @@ bufload({expr}) *bufload()*
there will be no dialog, the buffer will be loaded anyway.
The {expr} argument is used like with |bufexists()|.
+ Can also be used as a |method|: >
+ eval 'somename'->bufload()
+
bufloaded({expr}) *bufloaded()*
The result is a Number, which is |TRUE| if a buffer called
{expr} exists and is loaded (shown in a window or hidden).
The {expr} argument is used like with |bufexists()|.
+ Can also be used as a |method|: >
+ let loaded = 'somename'->bufloaded()
+
bufname([{expr}]) *bufname()*
The result is the name of a buffer, as it is displayed by the
":ls" command.
-+ If {expr} is omitted the current buffer is used.
+ If {expr} is omitted the current buffer is used.
If {expr} is a Number, that buffer number's name is given.
Number zero is the alternate buffer for the current window.
If {expr} is a String, it is used as a |file-pattern| to match
@@ -2824,6 +2892,9 @@ bufname([{expr}]) *bufname()*
If the {expr} is a String, but you want to use it as a buffer
number, force it to be a Number by adding zero to it: >
:echo bufname("3" + 0)
+< Can also be used as a |method|: >
+ echo bufnr->bufname()
+
< If the buffer doesn't exist, or doesn't have a name, an empty
string is returned. >
bufname("#") alternate buffer name
@@ -2846,6 +2917,9 @@ bufnr([{expr} [, {create}]])
number necessarily exist, because ":bwipeout" may have removed
them. Use bufexists() to test for the existence of a buffer.
+ Can also be used as a |method|: >
+ echo bufref->bufnr()
+
bufwinid({expr}) *bufwinid()*
The result is a Number, which is the |window-ID| of the first
window associated with buffer {expr}. For the use of {expr},
@@ -2856,18 +2930,22 @@ bufwinid({expr}) *bufwinid()*
<
Only deals with the current tab page.
+ Can also be used as a |method|: >
+ FindBuffer()->bufwinid()
+
bufwinnr({expr}) *bufwinnr()*
- The result is a Number, which is the number of the first
- window associated with buffer {expr}. For the use of {expr},
- see |bufname()| above. If buffer {expr} doesn't exist or
- there is no such window, -1 is returned. Example: >
+ Like |bufwinid()| but return the window number instead of the
+ |window-ID|.
+ If buffer {expr} doesn't exist or there is no such window, -1
+ is returned. Example: >
echo "A window containing buffer 1 is " . (bufwinnr(1))
< The number can be used with |CTRL-W_w| and ":wincmd w"
|:wincmd|.
- Only deals with the current tab page.
+ Can also be used as a |method|: >
+ FindBuffer()->bufwinnr()
byte2line({byte}) *byte2line()*
Return the line number that contains the character at byte
@@ -2877,6 +2955,9 @@ byte2line({byte}) *byte2line()*
one.
Also see |line2byte()|, |go| and |:goto|.
+ Can also be used as a |method|: >
+ GetOffset()->byte2line()
+
byteidx({expr}, {nr}) *byteidx()*
Return byte index of the {nr}'th character in the string
{expr}. Use zero for the first character, it then returns
@@ -2899,6 +2980,9 @@ byteidx({expr}, {nr}) *byteidx()*
If there are exactly {nr} characters the length of the string
in bytes is returned.
+ Can also be used as a |method|: >
+ GetName()->byteidx(idx)
+
byteidxcomp({expr}, {nr}) *byteidxcomp()*
Like byteidx(), except that a composing character is counted
as a separate character. Example: >
@@ -2912,6 +2996,9 @@ byteidxcomp({expr}, {nr}) *byteidxcomp()*
Only works differently from byteidx() when 'encoding' is set to
a Unicode encoding.
+ Can also be used as a |method|: >
+ GetName()->byteidxcomp(idx)
+
call({func}, {arglist} [, {dict}]) *call()* *E699*
Call function {func} with the items in |List| {arglist} as
arguments.
@@ -2921,6 +3008,9 @@ call({func}, {arglist} [, {dict}]) *call()* *E699*
{dict} is for functions with the "dict" attribute. It will be
used to set the local variable "self". |Dictionary-function|
+ Can also be used as a |method|: >
+ GetFunc()->call([arg, arg], dict)
+
ceil({expr}) *ceil()*
Return the smallest integral value greater than or equal to
{expr} as a |Float| (round up).
@@ -2933,6 +3023,9 @@ ceil({expr}) *ceil()*
echo ceil(4.0)
< 4.0
+ Can also be used as a |method|: >
+ Compute()->ceil()
+
changenr() *changenr()*
Return the number of the most recent change. This is the same
number as what is displayed with |:undolist| and can be used
@@ -2982,6 +3075,9 @@ char2nr({expr} [, {utf8}]) *char2nr()*
A combining character is a separate character.
|nr2char()| does the opposite.
+ Can also be used as a |method|: >
+ GetChar()->char2nr()
+
*charidx()*
charidx({string}, {idx} [, {countcc}])
Return the character index of the byte at {idx} in {string}.
@@ -3013,12 +3109,18 @@ cindent({lnum}) *cindent()*
When {lnum} is invalid -1 is returned.
See |C-indenting|.
+ Can also be used as a |method|: >
+ GetLnum()->cindent()
+
clearmatches([{win}]) *clearmatches()*
Clears all matches previously defined for the current window
by |matchadd()| and the |:match| commands.
If {win} is specified, use the window with this number or
window ID instead of the current window.
+ Can also be used as a |method|: >
+ GetWin()->clearmatches()
+<
*col()*
col({expr}) The result is a Number, which is the byte index of the column
position given with {expr}. The accepted positions are:
@@ -3054,6 +3156,9 @@ col({expr}) The result is a Number, which is the byte index of the column
\<C-O>:set ve=all<CR>
\<C-O>:echo col(".") . "\n" <Bar>
\let &ve = save_ve<CR>
+
+< Can also be used as a |method|: >
+ GetPos()->col()
<
complete({startcol}, {matches}) *complete()* *E785*
@@ -3085,6 +3190,10 @@ complete({startcol}, {matches}) *complete()* *E785*
< This isn't very useful, but it shows how it works. Note that
an empty string is returned to avoid a zero being inserted.
+ Can also be used as a |method|, the second argument is passed
+ in: >
+ GetMatches()->complete(col('.'))
+
complete_add({expr}) *complete_add()*
Add {expr} to the list of matches. Only to be used by the
function specified with the 'completefunc' option.
@@ -3094,6 +3203,9 @@ complete_add({expr}) *complete_add()*
See |complete-functions| for an explanation of {expr}. It is
the same as one item in the list that 'omnifunc' would return.
+ Can also be used as a |method|: >
+ GetMoreMatches()->complete_add()
+
complete_check() *complete_check()*
Check for a key typed while looking for completion matches.
This is to be used when looking for matches takes some time.
@@ -3154,6 +3266,9 @@ complete_info([{what}])
call complete_info(['mode'])
" Get only 'mode' and 'pum_visible'
call complete_info(['mode', 'pum_visible'])
+
+< Can also be used as a |method|: >
+ GetItems()->complete_info()
<
*confirm()*
confirm({msg} [, {choices} [, {default} [, {type}]]])
@@ -3207,6 +3322,9 @@ confirm({msg} [, {choices} [, {default} [, {type}]]])
don't fit, a vertical layout is used anyway. For some systems
the horizontal layout is always used.
+ Can also be used as a |method|in: >
+ BuildMessage()->confirm("&Yes\n&No")
+
*copy()*
copy({expr}) Make a copy of {expr}. For Numbers and Strings this isn't
different from using {expr} directly.
@@ -3216,6 +3334,8 @@ copy({expr}) Make a copy of {expr}. For Numbers and Strings this isn't
changing an item changes the contents of both |Lists|.
A |Dictionary| is copied in a similar way as a |List|.
Also see |deepcopy()|.
+ Can also be used as a |method|: >
+ mylist->copy()
cos({expr}) *cos()*
Return the cosine of {expr}, measured in radians, as a |Float|.
@@ -3226,6 +3346,8 @@ cos({expr}) *cos()*
:echo cos(-4.01)
< -0.646043
+ Can also be used as a |method|: >
+ Compute()->cos()
cosh({expr}) *cosh()*
Return the hyperbolic cosine of {expr} as a |Float| in the range
@@ -3237,6 +3359,8 @@ cosh({expr}) *cosh()*
:echo cosh(-0.5)
< -1.127626
+ Can also be used as a |method|: >
+ Compute()->cosh()
count({comp}, {expr} [, {ic} [, {start}]]) *count()*
Return the number of times an item with value {expr} appears
@@ -3251,6 +3375,9 @@ count({comp}, {expr} [, {ic} [, {start}]]) *count()*
occurrences of {expr} is returned. Zero is returned when
{expr} is an empty string.
+ 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
@@ -3346,6 +3473,8 @@ cursor({list})
position within a <Tab> or after the last character.
Returns 0 when the position could be set, -1 otherwise.
+ Can also be used as a |method|: >
+ GetCursorPos()->cursor()
deepcopy({expr}[, {noref}]) *deepcopy()* *E698*
Make a copy of {expr}. For Numbers and Strings this isn't
@@ -3367,6 +3496,9 @@ deepcopy({expr}[, {noref}]) *deepcopy()* *E698*
{noref} set to 1 will fail.
Also see |copy()|.
+ Can also be used as a |method|: >
+ GetObject()->deepcopy()
+
delete({fname} [, {flags}]) *delete()*
Without {flags} or with {flags} empty: Deletes the file by the
name {fname}. This also works when {fname} is a symbolic link.
@@ -3384,6 +3516,9 @@ delete({fname} [, {flags}]) *delete()*
operation was successful and -1/true when the deletion failed
or partly failed.
+ Can also be used as a |method|: >
+ GetName()->delete()
+
deletebufline({expr}, {first}[, {last}]) *deletebufline()*
Delete lines {first} to {last} (inclusive) from buffer {expr}.
If {last} is omitted then delete line {first} only.
@@ -3398,6 +3533,9 @@ deletebufline({expr}, {first}[, {last}]) *deletebufline()*
when using |line()| this refers to the current buffer. Use "$"
to refer to the last line in buffer {expr}.
+ Can also be used as a |method|: >
+ GetBuffer()->deletebufline(1)
+
dictwatcheradd({dict}, {pattern}, {callback}) *dictwatcheradd()*
Adds a watcher to a dictionary. A dictionary watcher is
identified by three components:
@@ -3464,6 +3602,9 @@ diff_filler({lnum}) *diff_filler()*
line, "'m" mark m, etc.
Returns 0 if the current window is not in diff mode.
+ Can also be used as a |method|: >
+ GetLnum()->diff_filler()
+
diff_hlID({lnum}, {col}) *diff_hlID()*
Returns the highlight ID for diff mode at line {lnum} column
{col} (byte index). When the current line does not have a
@@ -3475,11 +3616,16 @@ diff_hlID({lnum}, {col}) *diff_hlID()*
The highlight ID can be used with |synIDattr()| to obtain
syntax information about the highlighting.
+ Can also be used as a |method|: >
+ GetLnum()->diff_hlID(col)
+
empty({expr}) *empty()*
Return the Number 1 if {expr} is empty, zero otherwise.
A |List| or |Dictionary| is empty when it does not have any
items. A Number is empty when its value is zero. Special
variable is empty when it is |v:false| or |v:null|.
+ Can also be used as a |method|: >
+ mylist->empty()
environ() *environ()*
Return all of environment variables as dictionary. You can
@@ -3504,6 +3650,9 @@ eval({string}) Evaluate {string} and return the result. Especially useful to
them. Also works for |Funcref|s that refer to existing
functions.
+ Can also be used as a |method|: >
+ argv->join()->eval()
+
eventhandler() *eventhandler()*
Returns 1 when inside an event handler. That is that Vim got
interrupted while waiting for the user to type a character,
@@ -3661,12 +3810,18 @@ exp({expr}) *exp()*
:echo exp(-1)
< 0.367879
+ Can also be used as a |method|: >
+ Compute()->exp()
+
debugbreak({pid}) *debugbreak()*
Specifically used to interrupt a program being debugged. It
will cause process {pid} to get a SIGTRAP. Behavior for other
processes is undefined. See |terminal-debugger|.
{Sends a SIGINT to a process {pid} other than MS-Windows}
+ Can also be used as a |method|: >
+ GetPid()->debugbreak()
+
expand({expr} [, {nosuf} [, {list}]]) *expand()*
Expand wildcards and the following special keywords in {expr}.
'wildignorecase' applies.
@@ -3795,6 +3950,8 @@ extend({expr1}, {expr2} [, {expr3}]) *extend()*
fails.
Returns {expr1}.
+ Can also be used as a |method|: >
+ mylist->extend(otherlist)
feedkeys({string} [, {mode}]) *feedkeys()*
Characters in {string} are queued for processing as if they
@@ -3848,7 +4005,11 @@ filereadable({file}) *filereadable()*
expression, which is used as a String.
If you don't care about the file being readable you can use
|glob()|.
-
+ {file} is used as-is, you may want to expand wildcards first: >
+ echo filereadable('~/.vimrc')
+ 0
+ echo filereadable(expand('~/.vimrc'))
+ 1
filewritable({file}) *filewritable()*
The result is a Number, which is 1 when a file with the
@@ -3904,6 +4065,8 @@ filter({expr1}, {expr2}) *filter()*
Funcref errors inside a function are ignored, unless it was
defined with the "abort" flag.
+ Can also be used as a |method|: >
+ mylist->filter(expr2)
finddir({name} [, {path} [, {count}]]) *finddir()*
Find directory {name} in {path}. Supports both downwards and
@@ -3966,6 +4129,8 @@ float2nr({expr}) *float2nr()*
echo float2nr(1.0e-100)
< 0
+ Can also be used as a |method|: >
+ Compute()->float2nr()
floor({expr}) *floor()*
Return the largest integral value less than or equal to
@@ -3979,6 +4144,8 @@ floor({expr}) *floor()*
echo floor(4.0)
< 4.0
+ Can also be used as a |method|: >
+ Compute()->floor()
fmod({expr1}, {expr2}) *fmod()*
Return the remainder of {expr1} / {expr2}, even if the
@@ -3994,6 +4161,8 @@ fmod({expr1}, {expr2}) *fmod()*
:echo fmod(-12.33, 1.22)
< -0.13
+ Can also be used as a |method|: >
+ Compute()->fmod(1.22)
fnameescape({string}) *fnameescape()*
Escape {string} for use as file name command argument. All
@@ -4160,6 +4329,8 @@ get({list}, {idx} [, {default}]) *get()*
Get item {idx} from |List| {list}. When this item is not
available return {default}. Return zero when {default} is
omitted.
+ Can also be used as a |method|: >
+ mylist->get(idx)
get({dict}, {key} [, {default}])
Get item with key {key} from |Dictionary| {dict}. When this
item is not available return {default}. Return zero when
@@ -5171,6 +5342,9 @@ has_key({dict}, {key}) *has_key()*
The result is a Number, which is TRUE if |Dictionary| {dict}
has an entry with key {key}. FALSE otherwise.
+ Can also be used as a |method|: >
+ mydict->has_key(key)
+
haslocaldir([{winnr}[, {tabnr}]]) *haslocaldir()*
The result is a Number, which is 1 when the tabpage or window
has set a local path via |:tcd| or |:lcd|, otherwise 0.
@@ -5514,6 +5688,9 @@ insert({list}, {item} [, {idx}]) *insert()*
Note that when {item} is a |List| it is inserted as a single
item. Use |extend()| to concatenate |Lists|.
+ Can also be used as a |method|: >
+ mylist->insert(item)
+
interrupt() *interrupt()*
Interrupt script execution. It works more or less like the
user typing CTRL-C, most commands won't execute and control
@@ -5531,6 +5708,8 @@ invert({expr}) *invert()*
Bitwise invert. The argument is converted to a number. A
List, Dict or Float argument causes an error. Example: >
:let bits = invert(bits)
+< Can also be used as a |method|: >
+ :let bits = bits->invert()
isdirectory({directory}) *isdirectory()*
The result is a Number, which is |TRUE| when a directory
@@ -5546,6 +5725,9 @@ isinf({expr}) *isinf()*
:echo isinf(-1.0 / 0.0)
< -1
+ Can also be used as a |method|: >
+ Compute()->isinf()
+
islocked({expr}) *islocked()* *E786*
The result is a Number, which is |TRUE| when {expr} is the
name of a locked variable.
@@ -5581,12 +5763,17 @@ items({dict}) *items()*
|List| item is a list with two items: the key of a {dict}
entry and the value of this entry. The |List| is in arbitrary
order.
+ Can also be used as a |method|: >
+ mydict->items()
isnan({expr}) *isnan()*
Return |TRUE| if {expr} is a float with value NaN. >
echo isnan(0.0 / 0.0)
< 1
+ Can also be used as a |method|: >
+ Compute()->isnan()
+
jobpid({job}) *jobpid()*
Return the PID (process id) of |job-id| {job}.
@@ -5714,6 +5901,9 @@ join({list} [, {sep}]) *join()*
converted into a string like with |string()|.
The opposite function is |split()|.
+ Can also be used as a |method|: >
+ mylist->join()
+
json_decode({expr}) *json_decode()*
Convert {expr} from JSON object. Accepts |readfile()|-style
list as the input, as well as regular string. May output any
@@ -5744,8 +5934,10 @@ json_encode({expr}) *json_encode()*
keys({dict}) *keys()*
Return a |List| with all the keys of {dict}. The |List| is in
arbitrary order.
+ Can also be used as a |method|: >
+ mydict->keys()
- *len()* *E701*
+< *len()* *E701*
len({expr}) The result is a Number, which is the length of the argument.
When {expr} is a String or a Number the length in bytes is
used, as with |strlen()|.
@@ -5756,7 +5948,10 @@ len({expr}) The result is a Number, which is the length of the argument.
|Dictionary| is returned.
Otherwise an error is given.
- *libcall()* *E364* *E368*
+ Can also be used as a |method|: >
+ mylist->len()
+
+< *libcall()* *E364* *E368*
libcall({libname}, {funcname}, {argument})
Call function {funcname} in the run-time library {libname}
with single argument {argument}.
@@ -5881,6 +6076,8 @@ log({expr}) *log()*
:echo log(exp(5))
< 5.0
+ Can also be used as a |method|: >
+ Compute()->log()
log10({expr}) *log10()*
Return the logarithm of Float {expr} to base 10 as a |Float|.
@@ -5891,6 +6088,9 @@ log10({expr}) *log10()*
:echo log10(0.01)
< -2.0
+ Can also be used as a |method|: >
+ Compute()->log10()
+
luaeval({expr}[, {expr}])
Evaluate Lua expression {expr} and return its result converted
to Vim data structures. See |lua-eval| for more details.
@@ -5939,6 +6139,8 @@ map({expr1}, {expr2}) *map()*
Funcref errors inside a function are ignored, unless it was
defined with the "abort" flag.
+ Can also be used as a |method|: >
+ mylist->map(expr2)
maparg({name} [, {mode} [, {abbr} [, {dict}]]]) *maparg()*
When {dict} is omitted or zero: Return the rhs of mapping
@@ -6274,6 +6476,9 @@ max({expr}) Return the maximum value of all items in {expr}.
items in {expr} cannot be used as a Number this results in
an error. An empty |List| or |Dictionary| results in zero.
+ Can also be used as a |method|: >
+ mylist->max()
+
menu_get({path}, {modes}) *menu_get()*
Returns a |List| of |Dictionaries| describing |menus| (defined
by |:menu|, |:amenu|, …), including |hidden-menus|.
@@ -6328,7 +6533,10 @@ min({expr}) Return the minimum value of all items in {expr}.
items in {expr} cannot be used as a Number this results in
an error. An empty |List| or |Dictionary| results in zero.
- *mkdir()* *E739*
+ Can also be used as a |method|: >
+ mylist->min()
+
+< *mkdir()* *E739*
mkdir({name} [, {path} [, {prot}]])
Create directory {name}.
If {path} is "p" then intermediate directories are created as
@@ -6523,7 +6731,8 @@ or({expr}, {expr}) *or()*
to a number. A List, Dict or Float argument causes an error.
Example: >
:let bits = or(bits, 0x80)
-
+< Can also be used as a |method|: >
+ :let bits = bits->or(0x80)
pathshorten({expr}) *pathshorten()*
Shorten directory names in the path {expr} and return the
@@ -6560,6 +6769,9 @@ pow({x}, {y}) *pow()*
:echo pow(32, 0.20)
< 2.0
+ Can also be used as a |method|: >
+ Compute()->pow(3)
+
prevnonblank({lnum}) *prevnonblank()*
Return the line number of the first line at or above {lnum}
that is not blank. Example: >
@@ -6576,7 +6788,11 @@ printf({fmt}, {expr1} ...) *printf()*
< May result in:
" 99: E42 asdfasdfasdfasdfasdfasdfasdfas" ~
- Often used items are:
+ When used as a |method| the base is passed as the second
+ argument: >
+ Compute()->printf("result: %d")
+
+< Often used items are:
%s string
%6S string right-aligned in 6 display cells
%6s string right-aligned in 6 bytes
@@ -7086,6 +7302,10 @@ remove({list}, {idx} [, {end}]) *remove()*
Example: >
:echo "last item: " . remove(mylist, -1)
:call remove(mylist, 0, 9)
+
+< Can also be used as a |method|: >
+ mylist->remove(idx)
+
remove({dict}, {key})
Remove the entry from {dict} with key {key} and return it.
Example: >
@@ -7112,6 +7332,8 @@ repeat({expr}, {count}) *repeat()*
:let longlist = repeat(['a', 'b'], 3)
< Results in ['a', 'b', 'a', 'b', 'a', 'b'].
+ Can also be used as a |method|: >
+ mylist->repeat(count)
resolve({filename}) *resolve()* *E655*
On MS-Windows, when {filename} is a shortcut (a .lnk file),
@@ -7131,6 +7353,8 @@ reverse({list}) Reverse the order of items in {list} in-place. Returns
{list}.
If you want a list to remain unmodified make a copy first: >
:let revlist = reverse(copy(mylist))
+< Can also be used as a |method|: >
+ mylist->reverse()
round({expr}) *round()*
Round off {expr} to the nearest integral value and return it
@@ -7145,6 +7369,9 @@ round({expr}) *round()*
echo round(-4.5)
< -5.0
+ Can also be used as a |method|: >
+ Compute()->round()
+
rpcnotify({channel}, {event}[, {args}...]) *rpcnotify()*
Sends {event} to {channel} via |RPC| and returns immediately.
If {channel} is 0, the event is broadcast to all channels.
@@ -8121,6 +8348,8 @@ sin({expr}) *sin()*
:echo sin(-4.01)
< 0.763301
+ Can also be used as a |method|: >
+ Compute()->sin()
sinh({expr}) *sinh()*
Return the hyperbolic sine of {expr} as a |Float| in the range
@@ -8132,6 +8361,9 @@ sinh({expr}) *sinh()*
:echo sinh(-0.9)
< -1.026517
+ Can also be used as a |method|: >
+ Compute()->sinh()
+
sockconnect({mode}, {address}, {opts}) *sockconnect()*
Connect a socket to an address. If {mode} is "pipe" then
{address} should be the path of a named pipe. If {mode} is
@@ -8210,7 +8442,10 @@ sort({list} [, {func} [, {dict}]]) *sort()* *E702*
on numbers, text strings will sort next to each other, in the
same order as they were originally.
- Also see |uniq()|.
+ Can also be used as a |method|: >
+ mylist->sort()
+
+< Also see |uniq()|.
Example: >
func MyCompare(i1, i2)
@@ -8303,6 +8538,8 @@ split({expr} [, {pattern} [, {keepempty}]]) *split()*
:let items = split(line, ':', 1)
< The opposite function is |join()|.
+ Can also be used as a |method|: >
+ GetString()->split()
sqrt({expr}) *sqrt()*
Return the non-negative square root of Float {expr} as a
@@ -8316,6 +8553,8 @@ sqrt({expr}) *sqrt()*
< nan
"nan" may be different, it depends on system libraries.
+ Can also be used as a |method|: >
+ Compute()->sqrt()
stdioopen({opts}) *stdioopen()*
With |--headless| this opens stdin and stdout as a |channel|.
@@ -8367,6 +8606,9 @@ str2float({expr}) *str2float()*
12.0. You can strip out thousands separators with
|substitute()|: >
let f = str2float(substitute(text, ',', '', 'g'))
+<
+ Can also be used as a |method|: >
+ let f = text->substitute(',', '', 'g')->str2float()
str2list({expr} [, {utf8}]) *str2list()*
Return a list containing the number values which represent
@@ -8381,12 +8623,18 @@ str2list({expr} [, {utf8}]) *str2list()*
properly: >
str2list("á") returns [97, 769]
+< Can also be used as a |method|: >
+ GetString()->str2list()
+
str2nr({expr} [, {base}]) *str2nr()*
Convert string {expr} to a number.
{base} is the conversion base, it can be 2, 8, 10 or 16.
+
When {base} is omitted base 10 is used. This also means that
a leading zero doesn't cause octal conversion to be used, as
- with the default String to Number conversion.
+ with the default String to Number conversion. Example: >
+ let nr = str2nr('123')
+<
When {base} is 16 a leading "0x" or "0X" is ignored. With a
different base the result will be zero. Similarly, when {base}
is 8 a leading "0" is ignored, and when {base} is 2 a leading
@@ -8505,6 +8753,9 @@ string({expr}) Return {expr} converted to a String. If {expr} is a Number,
method, use |msgpackdump()| or |json_encode()| if you need to
share data with other application.
+ Can also be used as a |method|: >
+ mylist->string()
+
*strlen()*
strlen({expr}) The result is a Number, which is the length of the String
{expr} in bytes.
@@ -8514,6 +8765,9 @@ strlen({expr}) The result is a Number, which is the length of the String
|strchars()|.
Also see |len()|, |strdisplaywidth()| and |strwidth()|.
+ Can also be used as a |method|: >
+ GetString()->strlen()
+
strpart({src}, {start} [, {len} [, {chars}]]) *strpart()*
The result is a String, which is part of {src}, starting from
byte {start}, with the byte length {len}.
@@ -8588,6 +8842,9 @@ strtrans({expr}) *strtrans()*
< This displays a newline in register a as "^@" instead of
starting a new line.
+ Can also be used as a |method|: >
+ GetString()->strtrans()
+
strwidth({expr}) *strwidth()*
The result is a Number, which is the number of display cells
String {expr} occupies. A Tab character is counted as one
@@ -8596,6 +8853,9 @@ strwidth({expr}) *strwidth()*
Ambiguous, this function's return value depends on 'ambiwidth'.
Also see |strlen()|, |strdisplaywidth()| and |strchars()|.
+ Can also be used as a |method|: >
+ GetString()->strwidth()
+
submatch({nr} [, {list}]) *submatch()* *E935*
Only for an expression in a |:substitute| command or
substitute() function.
@@ -8663,6 +8923,9 @@ substitute({expr}, {pat}, {sub}, {flags}) *substitute()*
|submatch()| returns. Example: >
:echo substitute(s, '%\(\x\x\)', {m -> '0x' . m[1]}, 'g')
+< Can also be used as a |method|: >
+ GetString()->substitute(pat, sub, flags)
+
swapinfo({fname}) *swapinfo()*
The result is a dictionary, which holds information about the
swapfile {fname}. The available fields are:
@@ -8747,12 +9010,18 @@ synIDattr({synID}, {what} [, {mode}]) *synIDattr()*
cursor): >
:echo synIDattr(synIDtrans(synID(line("."), col("."), 1)), "fg")
<
+ Can also be used as a |method|: >
+ :echo synID(line("."), col("."), 1)->synIDtrans()->synIDattr("fg")
+
synIDtrans({synID}) *synIDtrans()*
The result is a Number, which is the translated syntax ID of
{synID}. This is the syntax group ID of what is being used to
highlight the character. Highlight links given with
":highlight link" are followed.
+ Can also be used as a |method|: >
+ :echo synID(line("."), col("."), 1)->synIDtrans()->synIDattr("fg")
+
synconcealed({lnum}, {col}) *synconcealed()*
The result is a |List| with currently three items:
1. The first item in the list is 0 if the character at the
@@ -8849,6 +9118,8 @@ system({cmd} [, {input}]) *system()* *E677*
Unlike ":!cmd" there is no automatic check for changed files.
Use |:checktime| to force a check.
+ Can also be used as a |method|: >
+ :echo GetCmd()->system()
systemlist({cmd} [, {input} [, {keepempty}]]) *systemlist()*
Same as |system()|, but returns a |List| with lines (parts of
@@ -8864,6 +9135,8 @@ systemlist({cmd} [, {input} [, {keepempty}]]) *systemlist()*
<
Returns an empty string on error.
+ Can also be used as a |method|: >
+ :echo GetCmd()->systemlist()
tabpagebuflist([{arg}]) *tabpagebuflist()*
The result is a |List|, where each item is the number of the
@@ -8987,6 +9260,8 @@ tan({expr}) *tan()*
:echo tan(-4.01)
< -1.181502
+ Can also be used as a |method|: >
+ Compute()->tan()
tanh({expr}) *tanh()*
Return the hyperbolic tangent of {expr} as a |Float| in the
@@ -8998,6 +9273,8 @@ tanh({expr}) *tanh()*
:echo tanh(-1)
< -0.761594
+ Can also be used as a |method|: >
+ Compute()->tanh()
*timer_info()*
timer_info([{id}])
@@ -9124,6 +9401,9 @@ trunc({expr}) *trunc()*
echo trunc(4.0)
< 4.0
+ Can also be used as a |method|: >
+ Compute()->trunc()
+
type({expr}) *type()*
The result is a Number representing the type of {expr}.
Instead of using the number directly, it is better to use the
@@ -9150,6 +9430,9 @@ type({expr}) *type()*
< To check if the v:t_ variables exist use this: >
:if exists('v:t_number')
+< Can also be used as a |method|: >
+ mylist->type()
+
undofile({name}) *undofile()*
Return the name of the undo file that would be used for a file
with name {name} when writing. This uses the 'undodir'
@@ -9212,10 +9495,15 @@ uniq({list} [, {func} [, {dict}]]) *uniq()* *E882*
< The default compare function uses the string representation of
each item. For the use of {func} and {dict} see |sort()|.
+ Can also be used as a |method|: >
+ mylist->uniq()
+
values({dict}) *values()*
Return a |List| with all the values of {dict}. The |List| is
in arbitrary order.
+ Can also be used as a |method|: >
+ mydict->values()
virtcol({expr}) *virtcol()*
The result is a Number, which is the screen column of the file
@@ -9393,6 +9681,9 @@ winbufnr({nr}) The result is a Number, which is the number of the buffer
Example: >
:echo "The file in the current window is " . bufname(winbufnr(0))
<
+ Can also be used as a |method|: >
+ FindWindow()->winbufnr()->bufname()
+<
*wincol()*
wincol() The result is a Number, which is the virtual column of the
cursor in the window. This is counting screen cells from the
@@ -9606,6 +9897,8 @@ xor({expr}, {expr}) *xor()*
to a number. A List, Dict or Float argument causes an error.
Example: >
:let bits = xor(bits, 0x80)
+< Can also be used as a |method|: >
+ :let bits = bits->xor(0x80)
<
@@ -9943,7 +10236,9 @@ This function can then be called with: >
The recursiveness of user functions is restricted with the |'maxfuncdepth'|
option.
-It is also possible to use `:eval`. It does not support a range.
+It is also possible to use `:eval`. It does not support a range, but does
+allow for method chaining, e.g.: >
+ eval GetList()->Filter()->append('$')
AUTOMATICALLY LOADING FUNCTIONS ~
@@ -10686,7 +10981,7 @@ text...
<
*:eval*
:eval {expr} Evaluate {expr} and discard the result. Example: >
- :eval append(Filter(Getlist()), '$')
+ :eval Getlist()->Filter()->append('$')
< The expression is supposed to have a side effect,
since the resulting value is not used. In the example
diff --git a/runtime/doc/lsp.txt b/runtime/doc/lsp.txt
index 688e906063..e76e224596 100644
--- a/runtime/doc/lsp.txt
+++ b/runtime/doc/lsp.txt
@@ -1207,34 +1207,6 @@ workspace_symbol({query}) *vim.lsp.buf.workspace_symbol()*
==============================================================================
Lua module: vim.lsp.diagnostic *lsp-diagnostic*
- *vim.lsp.diagnostic.apply_to_diagnostic_items()*
-apply_to_diagnostic_items({item_handler}, {command}, {opts})
- Gets diagnostics, converts them to quickfix/location list
- items, and applies the item_handler callback to the items.
-
- Parameters: ~
- {item_handler} function Callback to apply to the
- diagnostic items
- {command} string|nil Command to execute after
- applying the item_handler
- {opts} table|nil Configuration table. Keys:
- • {client_id}: (number)
- • If nil, will consider all clients
- attached to buffer.
-
- • {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.
-
- • {workspace}: (boolean, default false)
- • Set the list with workspace
- diagnostics
-
*vim.lsp.diagnostic.clear()*
clear({bufnr}, {client_id}, {diagnostic_ns}, {sign_ns})
Clears the currently displayed diagnostics
@@ -1657,31 +1629,6 @@ set_virtual_text({diagnostics}, {bufnr}, {client_id}, {diagnostic_ns}, {opts})
E.g. "Warning" means { "Error",
"Warning" } will be valid.
- *vim.lsp.diagnostic.show_diagnostics()*
-show_diagnostics({opts}, {diagnostics})
- Open a floating window with the provided diagnostics
-
- The floating window can be customized with the following
- highlight groups: >
-
- LspDiagnosticsFloatingError
- LspDiagnosticsFloatingWarning
- LspDiagnosticsFloatingInformation
- LspDiagnosticsFloatingHint
-<
-
- Parameters: ~
- {opts} table Configuration table
- • show_header (boolean, default true): Show
- "Diagnostics:" header
- • all opts for
- |vim.lsp.util.open_floating_preview()|
- can be used here
- {diagnostics} table: The diagnostics to display
-
- Return: ~
- table {popup_bufnr, win_id}
-
*vim.lsp.diagnostic.show_line_diagnostics()*
show_line_diagnostics({opts}, {buf_nr}, {line_nr}, {client_id})
Parameters: ~
@@ -1698,6 +1645,8 @@ show_line_diagnostics({opts}, {buf_nr}, {line_nr}, {client_id})
*vim.lsp.diagnostic.show_position_diagnostics()*
show_position_diagnostics({opts}, {buf_nr}, {position})
+ Open a floating window with the diagnostics from {position}
+
Parameters: ~
{opts} table|nil Configuration keys
• severity: (DiagnosticSeverity, default nil)
@@ -1733,6 +1682,10 @@ display({lenses}, {bufnr}, {client_id}) *vim.lsp.codelens.display()*
get({bufnr}) *vim.lsp.codelens.get()*
Return all lenses for the given buffer
+ Parameters: ~
+ {bufnr} number Buffer number. 0 can be used for the
+ current buffer.
+
Return: ~
table ( `CodeLens[]` )
@@ -1838,12 +1791,6 @@ apply_workspace_edit({workspace_edit})
Parameters: ~
{workspace_edit} (table) `WorkspaceEdit`
-border_height({id}) *vim.lsp.util.border_height()*
- TODO: Documentation
-
-border_width({id}) *vim.lsp.util.border_width()*
- TODO: Documentation
-
buf_clear_references({bufnr}) *vim.lsp.util.buf_clear_references()*
Removes document highlights from a buffer.
diff --git a/runtime/doc/lua.txt b/runtime/doc/lua.txt
index d4c6e55d0e..a44b2e42f5 100644
--- a/runtime/doc/lua.txt
+++ b/runtime/doc/lua.txt
@@ -391,6 +391,10 @@ where the args are converted to Lua values. The expression >
is equivalent to the Lua chunk >
return somemod.func(...)
+The `v:lua` prefix may be used to call Lua functions as |method|s. For
+example: >
+ arg1->v:lua.somemod.func(arg2)
+
You can use `v:lua` in "func" options like 'tagfunc', 'omnifunc', etc.
For example consider the following Lua omnifunc handler: >
diff --git a/runtime/doc/nvim_terminal_emulator.txt b/runtime/doc/nvim_terminal_emulator.txt
index e0589ba7b8..0bf58f85fc 100644
--- a/runtime/doc/nvim_terminal_emulator.txt
+++ b/runtime/doc/nvim_terminal_emulator.txt
@@ -13,7 +13,7 @@ from the connected program.
Terminal buffers behave like normal buffers, except:
- With 'modifiable', lines can be edited but not deleted.
- 'scrollback' controls how many lines are kept.
-- Output is followed if the cursor is on the last line.
+- Output is followed ("tailed") if cursor is on the last line.
- 'modified' is the default. You can set 'nomodified' to avoid a warning when
closing the terminal buffer.
- 'bufhidden' defaults to "hide".
diff --git a/runtime/doc/options.txt b/runtime/doc/options.txt
index 364d4c5167..475ccb66b3 100644
--- a/runtime/doc/options.txt
+++ b/runtime/doc/options.txt
@@ -824,12 +824,12 @@ A jump table for the options with a short description can be found at |Q_op|.
again not rename the file.
*'backupdir'* *'bdir'*
-'backupdir' 'bdir' string (default ".,$XDG_DATA_HOME/nvim/backup")
+'backupdir' 'bdir' string (default ".,$XDG_DATA_HOME/nvim/backup//")
global
List of directories for the backup file, separated with commas.
- The backup file will be created in the first directory in the list
- where this is possible. The directory must exist, Vim will not
- create it for you.
+ where this is possible. If none of the directories exist Nvim will
+ attempt to create the last directory in the list.
- Empty means that no backup file will be created ('patchmode' is
impossible!). Writing may fail because of this.
- A directory "." means to put the backup file in the same directory
@@ -6533,17 +6533,17 @@ A jump table for the options with a short description can be found at |Q_op|.
'ttyfast' 'tf' Removed. |vim-differences|
*'undodir'* *'udir'* *E5003*
-'undodir' 'udir' string (default "$XDG_DATA_HOME/nvim/undo")
+'undodir' 'udir' string (default "$XDG_DATA_HOME/nvim/undo//")
global
List of directory names for undo files, separated with commas.
- See |'backupdir'| for details of the format.
+ See 'backupdir' for details of the format.
"." means using the directory of the file. The undo file name for
"file.txt" is ".file.txt.un~".
For other directories the file name is the full path of the edited
file, with path separators replaced with "%".
When writing: The first directory that exists is used. "." always
- works, no directories after "." will be used for writing. If none of
- the directories exist Neovim will attempt to create last directory in
+ works, no directories after "." will be used for writing. If none of
+ the directories exist Nvim will attempt to create the last directory in
the list.
When reading all entries are tried to find an undo file. The first
undo file that exists is used. When it cannot be read an error is
@@ -6552,6 +6552,10 @@ A jump table for the options with a short description can be found at |Q_op|.
This option cannot be set from a |modeline| or in the |sandbox|, for
security reasons.
+ Note that unlike 'directory' and 'backupdir', 'undodir' always acts as
+ though the trailing slashes are present (see 'backupdir' for what this
+ means).
+
*'undofile'* *'noundofile'* *'udf'* *'noudf'*
'undofile' 'udf' boolean (default off)
local to buffer
@@ -6692,7 +6696,7 @@ A jump table for the options with a short description can be found at |Q_op|.
displayed when 'verbosefile' is set.
*'viewdir'* *'vdir'*
-'viewdir' 'vdir' string (default: "$XDG_DATA_HOME/nvim/view")
+'viewdir' 'vdir' string (default: "$XDG_DATA_HOME/nvim/view//")
global
Name of the directory where to store files for |:mkview|.
This option cannot be set from a |modeline| or in the |sandbox|, for
diff --git a/runtime/doc/starting.txt b/runtime/doc/starting.txt
index 80b8dd52ea..d6b54fbd01 100644
--- a/runtime/doc/starting.txt
+++ b/runtime/doc/starting.txt
@@ -388,8 +388,8 @@ argument.
==============================================================================
Initialization *initialization* *startup*
-At startup, Vim checks environment variables and files and sets values
-accordingly. Vim proceeds in this order:
+At startup, Nvim checks environment variables and files and sets values
+accordingly, proceeding as follows:
1. Set the 'shell' option *SHELL* *COMSPEC*
The environment variable SHELL, if it exists, is used to set the
@@ -406,7 +406,9 @@ accordingly. Vim proceeds in this order:
Nvim started with |--embed| waits for the UI to connect before
proceeding to load user configuration.
-4. Load user config (execute Ex commands from files, environment, …).
+4. Setup |default-mappings| and |default-autocmds|.
+
+5. Load user config (execute Ex commands from files, environment, …).
$VIMINIT environment variable is read as one Ex command line (separate
multiple commands with '|' or <NL>).
*config* *init.vim* *init.lua* *vimrc* *exrc*
@@ -450,7 +452,7 @@ accordingly. Vim proceeds in this order:
- The file ".nvimrc"
- The file ".exrc"
-5. Enable filetype and indent plugins.
+6. Enable filetype and indent plugins.
This does the same as the commands: >
:runtime! filetype.vim
:runtime! ftplugin.vim
@@ -458,13 +460,13 @@ accordingly. Vim proceeds in this order:
< Skipped if ":filetype … off" was called or if the "-u NONE" command
line argument was given.
-6. Enable syntax highlighting.
+7. Enable syntax highlighting.
This does the same as the command: >
:runtime! syntax/syntax.vim
< Skipped if ":syntax off" was called or if the "-u NONE" command
line argument was given.
-7. Load the plugin scripts. *load-plugins*
+8. Load the plugin scripts. *load-plugins*
This does the same as the command: >
:runtime! plugin/**/*.vim
:runtime! plugin/**/*.lua
@@ -494,38 +496,33 @@ accordingly. Vim proceeds in this order:
if packages have been found, but that should not add a directory
ending in "after".
-8. Set 'shellpipe' and 'shellredir'
+9. Set 'shellpipe' and 'shellredir'
The 'shellpipe' and 'shellredir' options are set according to the
value of the 'shell' option, unless they have been set before.
- This means that Vim will figure out the values of 'shellpipe' and
+ This means that Nvim will figure out the values of 'shellpipe' and
'shellredir' for you, unless you have set them yourself.
-9. Set 'updatecount' to zero, if "-n" command argument used
+10. Set 'updatecount' to zero, if "-n" command argument used
-10. Set binary options
- If the "-b" flag was given to Vim, the options for binary editing will
- be set now. See |-b|.
+11. Set binary options if the |-b| flag was given.
-11. Read the ShaDa file
- See |shada-file|.
+12. Read the |shada-file|.
-12. Read the quickfix file
- If the "-q" flag was given to Vim, the quickfix file is read. If this
- fails, Vim exits.
+13. Read the quickfix file if the |-q| flag was given, or exit on failure.
-13. Open all windows
+14. Open all windows
When the |-o| flag was given, windows will be opened (but not
displayed yet).
When the |-p| flag was given, tab pages will be created (but not
displayed yet).
When switching screens, it happens now. Redrawing starts.
- If the "-q" flag was given to Vim, the first error is jumped to.
+ If the |-q| flag was given, the first error is jumped to.
Buffers for all windows will be loaded, without triggering |BufAdd|
autocommands.
-14. Execute startup commands
- If a "-t" flag was given to Vim, the tag is jumped to.
- The commands given with the |-c| and |+cmd| arguments are executed.
+15. Execute startup commands
+ If a |-t| flag was given, the tag is jumped to.
+ Commands given with |-c| and |+cmd| are executed.
If the 'insertmode' option is set, Insert mode is entered.
The starting flag is reset, has("vim_starting") will now return zero.
The |v:vim_did_enter| variable is set to 1.
diff --git a/runtime/doc/syntax.txt b/runtime/doc/syntax.txt
index 0cd3aed7a2..161b4f0d04 100644
--- a/runtime/doc/syntax.txt
+++ b/runtime/doc/syntax.txt
@@ -5064,10 +5064,15 @@ Substitute |:substitute| replacement text highlighting
*hl-LineNr*
LineNr Line number for ":number" and ":#" commands, and when 'number'
or 'relativenumber' option is set.
+ *hl-LineNrAbove*
+LineNrAbove Line number for when the 'relativenumber'
+ option is set, above the cursor line.
+ *hl-LineNrBelow*
+LineNrBelow Line number for when the 'relativenumber'
+ option is set, below the cursor line.
*hl-CursorLineNr*
-CursorLineNr Like LineNr when 'cursorline' is set and 'cursorlineopt' is
- set to "number" or "both", or 'relativenumber' is set, for
- the cursor line.
+CursorLineNr Like LineNr when 'cursorline' is set and 'cursorlineopt'
+ contains "number" or is "both", for the cursor line.
*hl-MatchParen*
MatchParen The character under the cursor or just before it, if it
is a paired bracket, and its match. |pi_paren.txt|
diff --git a/runtime/doc/testing.txt b/runtime/doc/testing.txt
index ef8d6b5ea9..3b59dfa908 100644
--- a/runtime/doc/testing.txt
+++ b/runtime/doc/testing.txt
@@ -53,6 +53,9 @@ assert_beeps({cmd}) *assert_beeps()*
Also see |assert_fails()|, |assert_nobeep()| and
|assert-return|.
+ Can also be used as a |method|: >
+ GetCmd()->assert_beeps()
+<
*assert_equal()*
assert_equal({expected}, {actual} [, {msg}])
When {expected} and {actual} are not equal an error message is
@@ -69,7 +72,10 @@ assert_equal({expected}, {actual} [, {msg}])
< Will result in a string to be added to |v:errors|:
test.vim line 12: Expected 'foo' but got 'bar' ~
- *assert_equalfile()*
+ Can also be used as a |method|: >
+ mylist->assert_equal([1, 2, 3])
+
+< *assert_equalfile()*
assert_equalfile({fname-one}, {fname-two})
When the files {fname-one} and {fname-two} do not contain
exactly the same text an error message is added to |v:errors|.
@@ -77,6 +83,9 @@ assert_equalfile({fname-one}, {fname-two})
When {fname-one} or {fname-two} does not exist the error will
mention that.
+ Can also be used as a |method|: >
+ GetLog()->assert_equalfile('expected.log')
+
assert_exception({error} [, {msg}]) *assert_exception()*
When v:exception does not contain the string {error} an error
message is added to |v:errors|. Also see |assert-return|.
@@ -97,6 +106,9 @@ assert_fails({cmd} [, {error} [, {msg}]]) *assert_fails()*
Note that beeping is not considered an error, and some failing
commands only beep. Use |assert_beeps()| for those.
+ Can also be used as a |method|: >
+ GetCmd()->assert_fails('E99:')
+
assert_false({actual} [, {msg}]) *assert_false()*
When {actual} is not false an error message is added to
|v:errors|, like with |assert_equal()|.
@@ -106,6 +118,9 @@ assert_false({actual} [, {msg}]) *assert_false()*
When {msg} is omitted an error in the form
"Expected False but got {actual}" is produced.
+ Can also be used as a |method|: >
+ GetResult()->assert_false()
+
assert_inrange({lower}, {upper}, {actual} [, {msg}]) *assert_inrange()*
This asserts number and |Float| values. When {actual} is lower
than {lower} or higher than {upper} an error message is added
@@ -134,6 +149,9 @@ assert_match({pattern}, {actual} [, {msg}])
< Will result in a string to be added to |v:errors|:
test.vim line 12: Pattern '^f.*o$' does not match 'foobar' ~
+ Can also be used as a |method|: >
+ getFile()->assert_match('foo.*')
+<
assert_nobeep({cmd}) *assert_nobeep()*
Run {cmd} and add an error message to |v:errors| if it
produces a beep or visual bell.
@@ -145,16 +163,27 @@ assert_notequal({expected}, {actual} [, {msg}])
|v:errors| when {expected} and {actual} are equal.
Also see |assert-return|.
- *assert_notmatch()*
+ Can also be used as a |method|: >
+ mylist->assert_notequal([1, 2, 3])
+
+< *assert_notmatch()*
assert_notmatch({pattern}, {actual} [, {msg}])
The opposite of `assert_match()`: add an error message to
|v:errors| when {pattern} matches {actual}.
Also see |assert-return|.
+ Can also be used as a |method|: >
+ getFile()->assert_notmatch('bar.*')
+
+
assert_report({msg}) *assert_report()*
Report a test failure directly, using {msg}.
Always returns one.
+ Can also be used as a |method|: >
+ GetMessage()->assert_report()
+
+
assert_true({actual} [, {msg}]) *assert_true()*
When {actual} is not true an error message is added to
|v:errors|, like with |assert_equal()|.
@@ -164,5 +193,8 @@ assert_true({actual} [, {msg}]) *assert_true()*
When {msg} is omitted an error in the form "Expected True but
got {actual}" is produced.
+ Can also be used as a |method|: >
+ GetResult()->assert_true()
+<
vim:tw=78:ts=8:noet:ft=help:norl:
diff --git a/runtime/doc/vim_diff.txt b/runtime/doc/vim_diff.txt
index 166c0c17aa..4b134926a2 100644
--- a/runtime/doc/vim_diff.txt
+++ b/runtime/doc/vim_diff.txt
@@ -30,7 +30,7 @@ the differences.
- 'autoread' is enabled
- 'background' defaults to "dark" (unless set automatically by the terminal/UI)
- 'backspace' defaults to "indent,eol,start"
-- 'backupdir' defaults to .,~/.local/share/nvim/backup (|xdg|)
+- 'backupdir' defaults to .,~/.local/share/nvim/backup// (|xdg|), auto-created
- 'belloff' defaults to "all"
- 'compatible' is always disabled
- 'complete' excludes "i"
@@ -63,7 +63,7 @@ the differences.
- 'tags' defaults to "./tags;,tags"
- 'ttimeoutlen' defaults to 50
- 'ttyfast' is always set
-- 'undodir' defaults to ~/.local/share/nvim/undo (|xdg|), auto-created
+- 'undodir' defaults to ~/.local/share/nvim/undo// (|xdg|), auto-created
- 'viewoptions' includes "unix,slash", excludes "options"
- 'viminfo' includes "!"
- 'wildmenu' is enabled
@@ -76,12 +76,24 @@ the differences.
- |g:vimsyn_embed| defaults to "l" to enable Lua highlighting
-Default Mappings: *default-mappings*
+Default Mappings ~
+ *default-mappings*
+>
+ nnoremap Y y$
+ nnoremap <C-L> <Cmd>nohlsearch<Bar>diffupdate<CR><C-L>
+ inoremap <C-U> <C-G>u<C-U>
+ inoremap <C-W> <C-G>u<C-W>
+<
+Default Autocommands ~
+ *default-autocmds*
+Default autocommands exist in the following groups. Use ":autocmd! {group}" to
+remove them and ":autocmd {group}" to see how they're defined.
+
+nvim_terminal:
+- BufReadCmd: Treats "term://" buffers as |terminal| buffers. |terminal-start|
-nnoremap Y y$
-nnoremap <C-L> <Cmd>nohlsearch<Bar>diffupdate<CR><C-L>
-inoremap <C-U> <C-G>u<C-U>
-inoremap <C-W> <C-G>u<C-W>
+nvim_cmdwin:
+- CmdwinEnter: Limits syntax sync to maxlines=1 in the |cmdwin|.
==============================================================================
3. New Features *nvim-features*
diff --git a/runtime/ftplugin/jsonc.vim b/runtime/ftplugin/jsonc.vim
new file mode 100644
index 0000000000..90d52cd0d3
--- /dev/null
+++ b/runtime/ftplugin/jsonc.vim
@@ -0,0 +1,27 @@
+" Vim filetype plugin
+" Language: JSONC (JSON with Comments)
+" Original Author: Izhak Jakov <izhak724@gmail.com>
+" 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
+
+runtime! ftplugin/json.vim
+
+if exists('b:did_ftplugin_jsonc')
+ finish
+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
diff --git a/runtime/ftplugin/man.vim b/runtime/ftplugin/man.vim
index 5d3e00d033..fce12012b5 100644
--- a/runtime/ftplugin/man.vim
+++ b/runtime/ftplugin/man.vim
@@ -6,14 +6,6 @@ if exists('b:did_ftplugin') || &filetype !=# 'man'
endif
let b:did_ftplugin = 1
-let s:pager = !exists('b:man_sect')
-
-if s:pager
- call man#init_pager()
-endif
-
-setlocal noswapfile buftype=nofile bufhidden=hide
-setlocal nomodified readonly nomodifiable
setlocal noexpandtab tabstop=8 softtabstop=8 shiftwidth=8
setlocal wrap breakindent linebreak
@@ -32,11 +24,7 @@ if !exists('g:no_plugin_maps') && !exists('g:no_man_maps')
nnoremap <silent> <buffer> k gk
nnoremap <silent> <buffer> gO :call man#show_toc()<CR>
nnoremap <silent> <buffer> <2-LeftMouse> :Man<CR>
- if s:pager
- nnoremap <silent> <buffer> <nowait> q :lclose<CR>:q<CR>
- else
- nnoremap <silent> <buffer> <nowait> q :lclose<CR><C-W>c
- endif
+ nnoremap <silent> <buffer> <nowait> q :lclose<CR><C-W>c
endif
if get(g:, 'ft_man_folding_enable', 0)
diff --git a/runtime/indent/jsonc.vim b/runtime/indent/jsonc.vim
new file mode 100644
index 0000000000..bf8e501dd5
--- /dev/null
+++ b/runtime/indent/jsonc.vim
@@ -0,0 +1,189 @@
+" Vim indent file
+" Language: JSONC (JSON with Comments)
+" Original Author: Izhak Jakov <izhak724@gmail.com>
+" Acknowledgement: Based off of vim-json maintained by Eli Parra <eli@elzr.com>
+" https://github.com/elzr/vim-json
+" Last Change: 2021-07-01
+
+" 0. Initialization {{{1
+" =================
+
+" Only load this indent file when no other was loaded.
+if exists("b:did_indent")
+ finish
+endif
+let b:did_indent = 1
+
+setlocal nosmartindent
+
+" Now, set up our indentation expression and keys that trigger it.
+setlocal indentexpr=GetJSONCIndent()
+setlocal indentkeys=0{,0},0),0[,0],!^F,o,O,e
+
+" Only define the function once.
+if exists("*GetJSONCIndent")
+ finish
+endif
+
+let s:cpo_save = &cpo
+set cpo&vim
+
+" 1. Variables {{{1
+" ============
+
+let s:line_term = '\s*\%(\%(\/\/\).*\)\=$'
+" Regex that defines blocks.
+let s:block_regex = '\%({\)\s*\%(|\%([*@]\=\h\w*,\=\s*\)\%(,\s*[*@]\=\h\w*\)*|\)\=' . s:line_term
+
+" 2. Auxiliary Functions {{{1
+" ======================
+
+" Check if the character at lnum:col is inside a string.
+function s:IsInString(lnum, col)
+ return synIDattr(synID(a:lnum, a:col, 1), 'name') == 'jsonString'
+endfunction
+
+" Find line above 'lnum' that isn't empty, or in a string.
+function s:PrevNonBlankNonString(lnum)
+ let lnum = prevnonblank(a:lnum)
+ while lnum > 0
+ " If the line isn't empty or in a string, end search.
+ let line = getline(lnum)
+ if !(s:IsInString(lnum, 1) && s:IsInString(lnum, strlen(line)))
+ break
+ endif
+ let lnum = prevnonblank(lnum - 1)
+ endwhile
+ return lnum
+endfunction
+
+" Check if line 'lnum' has more opening brackets than closing ones.
+function s:LineHasOpeningBrackets(lnum)
+ let open_0 = 0
+ let open_2 = 0
+ let open_4 = 0
+ let line = getline(a:lnum)
+ let pos = match(line, '[][(){}]', 0)
+ while pos != -1
+ let idx = stridx('(){}[]', line[pos])
+ if idx % 2 == 0
+ let open_{idx} = open_{idx} + 1
+ else
+ let open_{idx - 1} = open_{idx - 1} - 1
+ endif
+ let pos = match(line, '[][(){}]', pos + 1)
+ endwhile
+ return (open_0 > 0) . (open_2 > 0) . (open_4 > 0)
+endfunction
+
+function s:Match(lnum, regex)
+ let col = match(getline(a:lnum), a:regex) + 1
+ return col > 0 && !s:IsInString(a:lnum, col) ? col : 0
+endfunction
+
+" 3. GetJSONCIndent Function {{{1
+" =========================
+
+function GetJSONCIndent()
+ if !exists("s:inside_comment")
+ let s:inside_comment = 0
+ endif
+
+ " 3.1. Setup {{{2
+ " ----------
+
+ " Set up variables for restoring position in file. Could use v:lnum here.
+ let vcol = col('.')
+
+ " 3.2. Work on the current line {{{2
+ " -----------------------------
+
+
+ " Get the current line.
+ let line = getline(v:lnum)
+ let ind = -1
+ if s:inside_comment == 0
+ " TODO iterate through all the matches in a line
+ let col = matchend(line, '\/\*')
+ if col > 0 && !s:IsInString(v:lnum, col)
+ let s:inside_comment = 1
+ endif
+ endif
+ " If we're in the middle of a comment
+ if s:inside_comment == 1
+ let col = matchend(line, '\*\/')
+ if col > 0 && !s:IsInString(v:lnum, col)
+ let s:inside_comment = 0
+ endif
+ return ind
+ endif
+ if line =~ '^\s*//'
+ return ind
+ endif
+
+ " If we got a closing bracket on an empty line, find its match and indent
+ " according to it.
+ let col = matchend(line, '^\s*[]}]')
+
+ if col > 0 && !s:IsInString(v:lnum, col)
+ call cursor(v:lnum, col)
+ let bs = strpart('{}[]', stridx('}]', line[col - 1]) * 2, 2)
+
+ let pairstart = escape(bs[0], '[')
+ let pairend = escape(bs[1], ']')
+ let pairline = searchpair(pairstart, '', pairend, 'bW')
+
+ if pairline > 0
+ let ind = indent(pairline)
+ else
+ let ind = virtcol('.') - 1
+ endif
+
+ return ind
+ endif
+
+ " If we are in a multi-line string, don't do anything to it.
+ if s:IsInString(v:lnum, matchend(line, '^\s*') + 1)
+ return indent('.')
+ endif
+
+ " 3.3. Work on the previous line. {{{2
+ " -------------------------------
+
+ let lnum = prevnonblank(v:lnum - 1)
+
+ if lnum == 0
+ return 0
+ endif
+
+ " Set up variables for current line.
+ let line = getline(lnum)
+ let ind = indent(lnum)
+
+ " If the previous line ended with a block opening, add a level of indent.
+ " if s:Match(lnum, s:block_regex)
+ " return indent(lnum) + shiftwidth()
+ " endif
+
+ " If the previous line contained an opening bracket, and we are still in it,
+ " add indent depending on the bracket type.
+ if line =~ '[[({]'
+ let counts = s:LineHasOpeningBrackets(lnum)
+ if counts[0] == '1' || counts[1] == '1' || counts[2] == '1'
+ return ind + shiftwidth()
+ else
+ call cursor(v:lnum, vcol)
+ end
+ endif
+
+ " }}}2
+
+ return ind
+endfunction
+
+" }}}1
+
+let &cpo = s:cpo_save
+unlet s:cpo_save
+
+" vim:set sw=2 sts=2 ts=8 noet:
diff --git a/runtime/lua/vim/F.lua b/runtime/lua/vim/F.lua
index 09467eb8c6..1a258546a5 100644
--- a/runtime/lua/vim/F.lua
+++ b/runtime/lua/vim/F.lua
@@ -27,5 +27,14 @@ function F.nil_wrap(fn)
end
end
+--- like {...} except preserve the lenght explicitly
+function F.pack_len(...)
+ return {n=select('#', ...), ...}
+end
+
+--- like unpack() but use the length set by F.pack_len if present
+function F.unpack_len(t)
+ return unpack(t, 1, t.n)
+end
return F
diff --git a/runtime/lua/vim/highlight.lua b/runtime/lua/vim/highlight.lua
index 4cb1994419..236f3165f2 100644
--- a/runtime/lua/vim/highlight.lua
+++ b/runtime/lua/vim/highlight.lua
@@ -85,7 +85,11 @@ function highlight.on_yank(opts)
highlight.range(bufnr, yank_ns, higroup, pos1, pos2, event.regtype, event.inclusive)
vim.defer_fn(
- function() api.nvim_buf_clear_namespace(bufnr, yank_ns, 0, -1) end,
+ function()
+ if api.nvim_buf_is_valid(bufnr) then
+ api.nvim_buf_clear_namespace(bufnr, yank_ns, 0, -1)
+ end
+ end,
timeout
)
end
diff --git a/runtime/lua/vim/lsp.lua b/runtime/lua/vim/lsp.lua
index 8821bd53e7..0fdd43e210 100644
--- a/runtime/lua/vim/lsp.lua
+++ b/runtime/lua/vim/lsp.lua
@@ -381,7 +381,7 @@ do
end
state.pending_change = function()
state.pending_change = nil
- if client.is_stopped() then
+ if client.is_stopped() or not vim.api.nvim_buf_is_valid(bufnr) then
return
end
local contentChanges
@@ -1152,7 +1152,7 @@ end
---@param bufnr (number) Buffer handle, or 0 for current
---@param client_id (number) the client id
function lsp.buf_is_attached(bufnr, client_id)
- return (all_buffer_active_clients[bufnr] or {})[client_id] == true
+ return (all_buffer_active_clients[resolve_bufnr(bufnr)] or {})[client_id] == true
end
--- Gets a client by id, or nil if the id is invalid.
diff --git a/runtime/lua/vim/lsp/codelens.lua b/runtime/lua/vim/lsp/codelens.lua
index 3af1d836c7..7e706823f0 100644
--- a/runtime/lua/vim/lsp/codelens.lua
+++ b/runtime/lua/vim/lsp/codelens.lua
@@ -44,9 +44,10 @@ end
--- Return all lenses for the given buffer
---
+---@param bufnr number Buffer number. 0 can be used for the current buffer.
---@return table (`CodeLens[]`)
function M.get(bufnr)
- local lenses_by_client = lens_cache_by_buf[bufnr]
+ local lenses_by_client = lens_cache_by_buf[bufnr or 0]
if not lenses_by_client then return {} end
local lenses = {}
for _, client_lenses in pairs(lenses_by_client) do
diff --git a/runtime/lua/vim/lsp/diagnostic.lua b/runtime/lua/vim/lsp/diagnostic.lua
index 11bfa41097..41a62da522 100644
--- a/runtime/lua/vim/lsp/diagnostic.lua
+++ b/runtime/lua/vim/lsp/diagnostic.lua
@@ -1217,9 +1217,8 @@ function M.redraw(bufnr, client_id)
)
end
--- }}}
--- Diagnostic User Functions {{{
+---@private
--- Open a floating window with the provided diagnostics
---
--- The floating window can be customized with the following highlight groups:
@@ -1268,8 +1267,11 @@ local function show_diagnostics(opts, diagnostics)
return popup_bufnr, winnr
end
---- Open a floating window with the diagnostics from {position}
+-- }}}
+-- Diagnostic User Functions {{{
+
+--- Open a floating window with the diagnostics from {position}
---@param opts table|nil Configuration keys
--- - severity: (DiagnosticSeverity, default nil)
--- - Only return diagnostics with this severity. Overrides severity_limit
@@ -1337,6 +1339,7 @@ function M.reset(client_id, buffer_client_map)
end)
end
+---@private
--- Gets diagnostics, converts them to quickfix/location list items, and applies the item_handler callback to the items.
---@param item_handler function Callback to apply to the diagnostic items
---@param command string|nil Command to execute after applying the item_handler
diff --git a/runtime/lua/vim/lsp/util.lua b/runtime/lua/vim/lsp/util.lua
index a4b3298fd8..a4c8b69f6c 100644
--- a/runtime/lua/vim/lsp/util.lua
+++ b/runtime/lua/vim/lsp/util.lua
@@ -43,7 +43,9 @@ local loclist_type_map = {
---@private
--- Check the border given by opts or the default border for the additional
--- size it adds to a float.
----@returns size of border in height and width
+---@param opts (table, optional) options for the floating window
+--- - border (string or table) the border
+---@returns (table) size of border in the form of { height = height, width = width }
local function get_border_size(opts)
local border = opts and opts.border or default_border
local height = 0
@@ -52,12 +54,16 @@ local function get_border_size(opts)
if type(border) == 'string' then
local border_size = {none = {0, 0}, single = {2, 2}, double = {2, 2}, rounded = {2, 2}, solid = {2, 2}, shadow = {1, 1}}
if border_size[border] == nil then
- error("floating preview border is not correct. Please refer to the docs |vim.api.nvim_open_win()|"
- .. vim.inspect(border))
+ error(string.format("invalid floating preview border: %s. :help vim.api.nvim_open_win()", vim.inspect(border)))
end
height, width = unpack(border_size[border])
else
+ if 8 % #border ~= 0 then
+ error(string.format("invalid floating preview border: %s. :help vim.api.nvim_open_win()", vim.inspect(border)))
+ end
+ ---@private
local function border_width(id)
+ id = (id - 1) % #border + 1
if type(border[id]) == "table" then
-- border specified as a table of <character, highlight group>
return vim.fn.strdisplaywidth(border[id][1])
@@ -65,9 +71,11 @@ local function get_border_size(opts)
-- border specified as a list of border characters
return vim.fn.strdisplaywidth(border[id])
end
- error("floating preview border is not correct. Please refer to the docs |vim.api.nvim_open_win()|" .. vim.inspect(border))
+ error(string.format("invalid floating preview border: %s. :help vim.api.nvim_open_win()", vim.inspect(border)))
end
+ ---@private
local function border_height(id)
+ id = (id - 1) % #border + 1
if type(border[id]) == "table" then
-- border specified as a table of <character, highlight group>
return #border[id][1] > 0 and 1 or 0
@@ -75,7 +83,7 @@ local function get_border_size(opts)
-- border specified as a list of border characters
return #border[id] > 0 and 1 or 0
end
- error("floating preview border is not correct. Please refer to the docs |vim.api.nvim_open_win()|" .. vim.inspect(border))
+ error(string.format("invalid floating preview border: %s. :help vim.api.nvim_open_win()", vim.inspect(border)))
end
height = height + border_height(2) -- top
height = height + border_height(6) -- bottom
diff --git a/runtime/lua/vim/treesitter.lua b/runtime/lua/vim/treesitter.lua
index a09e0a9cf7..66999c5f7f 100644
--- a/runtime/lua/vim/treesitter.lua
+++ b/runtime/lua/vim/treesitter.lua
@@ -20,6 +20,9 @@ setmetatable(M, {
elseif k == "language" then
t[k] = require"vim.treesitter.language"
return t[k]
+ elseif k == "query" then
+ t[k] = require"vim.treesitter.query"
+ return t[k]
end
end
})
diff --git a/runtime/plugin/man.vim b/runtime/plugin/man.vim
index 689aa32ef3..b10677593f 100644
--- a/runtime/plugin/man.vim
+++ b/runtime/plugin/man.vim
@@ -5,8 +5,8 @@ if exists('g:loaded_man')
endif
let g:loaded_man = 1
-command! -bang -bar -range=-1 -complete=customlist,man#complete -nargs=* Man
- \ if <bang>0 | set ft=man |
+command! -bang -bar -addr=other -complete=customlist,man#complete -nargs=* Man
+ \ if <bang>0 | call man#init_pager() |
\ else | call man#open_page(<count>, <q-mods>, <f-args>) | endif
augroup man
diff --git a/runtime/syntax/jsonc.vim b/runtime/syntax/jsonc.vim
new file mode 100644
index 0000000000..d0df16bbf1
--- /dev/null
+++ b/runtime/syntax/jsonc.vim
@@ -0,0 +1,44 @@
+" Vim syntax file
+" Language: JSONC (JSON with Comments)
+" Original Author: Izhak Jakov <izhak724@gmail.com>
+" 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
+
+" Ensure syntax is loaded once, unless nested inside another (main) syntax
+" For description of main_syntax, see https://stackoverflow.com/q/16164549
+if !exists('g:main_syntax')
+ if exists('b:current_syntax') && b:current_syntax ==# 'jsonc'
+ finish
+ endif
+ let g:main_syntax = 'jsonc'
+endif
+
+" Based on vim-json syntax
+runtime! syntax/json.vim
+
+" Remove syntax group for comments treated as errors
+if !exists("g:vim_json_warnings") || g:vim_json_warnings
+ syn clear jsonCommentError
+endif
+
+syn match jsonStringMatch /"\([^"]\|\\\"\)\+"\ze\(\_s*\/\/.*\_s*\)*[}\]]/ contains=jsonString
+syn match jsonStringMatch /"\([^"]\|\\\"\)\+"\ze\_s*\/\*\_.*\*\/\_s*[}\]]/ contains=jsonString
+syn match jsonTrailingCommaError /\(,\)\+\ze\(\_s*\/\/.*\_s*\)*[}\]]/
+syn match jsonTrailingCommaError /\(,\)\+\ze\_s*\/\*\_.*\*\/\_s*[}\]]/
+
+" Define syntax matching comments and their contents
+syn keyword jsonCommentTodo FIXME NOTE TBD TODO XXX
+syn region jsonLineComment start=+\/\/+ end=+$+ contains=@Spell,jsonCommentTodo keepend
+syn region jsonComment start='/\*' end='\*/' contains=@Spell,jsonCommentTodo fold
+
+" Link comment syntax comment to highlighting
+hi! def link jsonLineComment Comment
+hi! def link jsonComment Comment
+
+" Set/Unset syntax to avoid duplicate inclusion and correctly handle nesting
+let b:current_syntax = 'jsonc'
+if g:main_syntax ==# 'jsonc'
+ unlet g:main_syntax
+endif
diff --git a/runtime/syntax/man.vim b/runtime/syntax/man.vim
index a01bd1c0e7..55b0e16de9 100644
--- a/runtime/syntax/man.vim
+++ b/runtime/syntax/man.vim
@@ -6,7 +6,7 @@ if exists('b:current_syntax')
endif
syntax case ignore
-syntax match manReference display '[^()[:space:]]\+([0-9nx][a-z]*)'
+syntax match manReference display '[^()[:space:]]\+(\%([0-9][a-z]*\|[nlpox]\))'
syntax match manSectionHeading display '^\S.*$'
syntax match manHeader display '^\%1l.*$'
syntax match manSubHeading display '^ \{3\}\S.*$'
@@ -27,11 +27,7 @@ if &filetype != 'man'
finish
endif
-if !exists('b:man_sect')
- call man#init_pager()
-endif
-
-if b:man_sect =~# '^[023]'
+if get(b:, 'man_sect', '') =~# '^[023]'
syntax case match
syntax include @c $VIMRUNTIME/syntax/c.vim
syntax match manCFuncDefinition display '\<\h\w*\>\ze\(\s\|\n\)*(' contained
diff --git a/runtime/tutor/en/vim-01-beginner.tutor b/runtime/tutor/en/vim-01-beginner.tutor
index 5ae0fde0da..7c0c357e80 100644
--- a/runtime/tutor/en/vim-01-beginner.tutor
+++ b/runtime/tutor/en/vim-01-beginner.tutor
@@ -1,4 +1,4 @@
-# Welcome to the VIM Tutor
+# Welcome to the VIM Tutor
Vim is a very powerful editor that has many commands, too many to explain in
a tutor such as this. This tutor is designed to describe enough of the
@@ -21,7 +21,9 @@ This tutorial is interactive, and there are a few things you should know.
- Type [<Enter>](<Enter>) on links [like this](holy-grail ) to open the linked help section.
- Or simply type [K](K) on any word to find its documentation!
- Sometimes you will be required to modify text like
-this here
+
+ this here
+
Once you have done the changes correctly, the ✗ sign at the left will change
to ✓. I imagine you can already see how neat Vim can be. ;)
Other times, you'll be prompted to run a command (I'll explain this later):
@@ -32,7 +34,6 @@ or press a sequence of keys
~~~ normal
<Esc>0f<Space>d3wP$P
~~~
-
Text within <'s and >'s (like `<Enter>`{normal}) describes a key to press
instead of text to type.
@@ -48,12 +49,12 @@ Now, move to the next lesson (use the `j`{normal} key to scroll down).
j The `j`{normal} key looks like a down arrow.
- 1. Move the cursor around the screen until you are comfortable.
+ 1. Move the cursor around the screen until you are comfortable.
- 2. Hold down the down key (`j`{normal}) until it repeats.
- Now you know how to move to the next lesson.
+ 2. Hold down the down key (`j`{normal}) until it repeats.
+ Now you know how to move to the next lesson.
- 3. Using the down key, move to Lesson 1.2.
+ 3. Using the down key, move to Lesson 1.2.
NOTE: If you are ever unsure about something you typed, press <Esc> to place
you in Normal mode. Then retype the command you wanted.
@@ -63,8 +64,7 @@ NOTE: The cursor keys should also work. But using hjkl you will be able to
# Lesson 1.2: EXITING VIM
-!! NOTE: Before executing any of the steps below,
-read this entire lesson !!
+!! NOTE: Before executing any of the steps below, read this entire lesson !!
1. Press the <Esc> key (to make sure you are in Normal mode).
@@ -72,18 +72,18 @@ read this entire lesson !!
`:q!`{vim} `<Enter>`{normal}.
- This exits the editor, DISCARDING any changes you have made.
+ This exits the editor, DISCARDING any changes you have made.
3. Open vim and get back here by executing the command that got you into
- this tutor. That might be:
+ this tutor. That might be:
- :Tutor <Enter>
+ :Tutor <Enter>
4. If you have these steps memorized and are confident, execute steps
- 1 through 3 to exit and re-enter the editor.
+ 1 through 3 to exit and re-enter the editor.
NOTE: [:q!](:q) <Enter> discards any changes you made. In a few lessons you
- will learn how to save the changes to a file.
+ will learn how to save the changes to a file.
5. Move the cursor down to Lesson 1.3.
@@ -94,7 +94,7 @@ NOTE: [:q!](:q) <Enter> discards any changes you made. In a few lessons you
1. Move the cursor to the line below marked ✗.
2. To fix the errors, move the cursor until it is on top of the
- character to be deleted.
+ character to be deleted.
3. Press [the x key](x) to delete the unwanted character.
@@ -104,8 +104,9 @@ The ccow jumpedd ovverr thhe mooon.
5. Now that the line is correct, go on to Lesson 1.4.
-NOTE: As you go through this tutor, do not try to memorize, learn by
- usage.
+NOTE: As you go through this tutor, do not try to memorize everything,
+ your Vim vocabulary will expand with usage. Consider returning to
+ this tutor periodically for a refresher.
# Lesson 1.4: TEXT EDITING: INSERTION
@@ -114,12 +115,12 @@ NOTE: As you go through this tutor, do not try to memorize, learn by
1. Move the cursor to the first line below marked ✗.
2. To make the first line the same as the second, move the cursor on top
- of the first character AFTER where the text is to be inserted.
+ of the first character AFTER where the text is to be inserted.
3. Press `i`{normal} and type in the necessary additions.
4. As each error is fixed press `<Esc>`{normal} to return to Normal mode.
- Repeat steps 2 through 4 to correct the sentence.
+ Repeat steps 2 through 4 to correct the sentence.
There is text misng this .
There is some text missing from this line.
@@ -136,7 +137,7 @@ There is some text missing from this line.
2. Press [A](A) and type in the necessary additions.
3. As the text has been appended press `<Esc>`{normal} to return to Normal
- mode.
+ mode.
4. Move the cursor to the second line marked ✗ and repeat
steps 2 and 3 to correct this sentence.
@@ -159,7 +160,7 @@ There is also some text missing here.
2. At the shell prompt type this command:
~~~ sh
- $ nvim tutor
+ $ nvim tutor
~~~
'nvim' is the command to start the Nvim editor, 'tutor' is the name of
the file you wish to edit. Use a file that may be changed.
@@ -168,13 +169,12 @@ There is also some text missing here.
4. Save the file with changes and exit Vim with:
~~~ cmd
- :wq
+ :wq
~~~
-
Note you'll need to press `<Enter>` to execute the command.
5. If you have quit vimtutor in step 1 restart the vimtutor and move down
- to the following summary.
+ to the following summary.
6. After reading the above steps and understanding them: do it.
@@ -184,15 +184,11 @@ There is also some text missing here.
h (left) j (down) k (up) l (right)
2. To start Vim from the shell prompt type:
-
~~~ sh
$ nvim FILENAME
~~~
-
- 3. To exit Vim type: `<Esc>`{normal} `:q!`{vim} `<Enter>`{normal} to trash
- all changes.
- OR type: `<Esc>`{normal} `:wq`{vim} `<Enter>`{normal} to save
- the changes.
+ 3. To exit Vim type: `<Esc>`{normal} `:q!`{vim} `<Enter>`{normal} to trash all changes.
+ OR type: `<Esc>`{normal} `:wq`{vim} `<Enter>`{normal} to save the changes.
4. To delete the character at the cursor type: `x`{normal}
@@ -239,8 +235,7 @@ Somebody typed the end of this line twice. end of this line twice.
# Lesson 2.3: ON OPERATORS AND MOTIONS
-Many commands that change text are made from an [operator](operator) and
-a [motion](navigation).
+Many commands that change text are made from an [operator](operator) and a [motion](navigation).
The format for a delete command with the [d](d) delete operator is as follows:
d motion
@@ -318,16 +313,13 @@ it would be easier to simply type two d's to delete a line.
** Press `u`{normal} to undo the last commands, `U`{normal} to fix a whole line. **
- 1. Move the cursor to the line below marked ✗ and place it on the
- first error.
+ 1. Move the cursor to the line below marked ✗ and place it on the first error.
2. Type `x`{normal} to delete the first unwanted character.
3. Now type `u`{normal} to undo the last command executed.
4. This time fix all the errors on the line using the `x`{normal} command.
5. Now type a capital `U`{normal} to return the line to its original state.
- 6. Now type `u`{normal} a few times to undo the `U`{normal} and preceding
- commands.
- 7. Now type `<C-r>`{normal} (Control + R) a few times to redo the commands
- (undo the undos).
+ 6. Now type `u`{normal} a few times to undo the `U`{normal} and preceding commands.
+ 7. Now type `<C-r>`{normal} (Control + R) a few times to redo the commands.
Fiix the errors oon thhis line and reeplace them witth undo.
@@ -341,11 +333,14 @@ Fiix the errors oon thhis line and reeplace them witth undo.
4. To repeat a motion prepend it with a number: `2w`{normal}
5. The format for a change command is:
- operator [number] motion
+
+ operator [number] motion
+
where:
- operator - is what to do, such as [d](d) for delete
- [number] - is an optional count to repeat the motion
- motion - moves over the text to operate on, such as:
+
+ operator - is what to do, such as [d](d) for delete
+ [number] - is an optional count to repeat the motion
+ motion - moves over the text to operate on, such as:
[w](w) (word),
[$]($) (to the end of line), etc.
@@ -403,8 +398,7 @@ NOTE: Remember that you should be learning by doing, not memorization.
3. Type `ce`{normal} and the correct word (in this case, type "ine" ).
- 4. Press `<Esc>`{normal} and move to the next character that needs to be
- changed.
+ 4. Press `<Esc>`{normal} and move to the next character that needs to be changed.
5. Repeat steps 3 and 4 until the first sentence is the same as the second.
@@ -419,7 +413,7 @@ Notice that [c](c)e deletes the word and places you in Insert mode.
1. The change operator works in the same way as delete. The format is:
- c [number] motion
+ c [number] motion
2. The motions are the same, such as `w`{normal} (word) and `$`{normal} (end of line).
@@ -449,7 +443,7 @@ NOTE: You can use the Backspace key to correct mistakes while typing.
4. The format for change is:
- c [number] motion
+ c [number] motion
Now go on to the next lesson.
@@ -460,13 +454,13 @@ Now go on to the next lesson.
NOTE: Read this entire lesson before executing any of the steps!!
- 1. Hold down the `<Ctrl>`{normal} key and press `g`{normal}. We call this
- `<C-g>`{normal}. A message will appear at the bottom of the page with the
- filename and the position in the file. Remember the line number for
- Step 3.
+ 1. Hold down the `<Ctrl>`{normal} key and press `g`{normal}. We call this `<C-g>`{normal}.
+ A message will appear at the bottom of the page with the filename and
+ the position in the file. Remember the line number for Step 3.
NOTE: You may see the cursor position in the lower right corner of the
screen. This happens when the ['ruler']('ruler') option is set.
+
2. Press [G](G) to move you to the bottom of the file.
Type [gg](gg) to move you to the start of the file.
@@ -482,17 +476,16 @@ NOTE: You may see the cursor position in the lower right corner of the
1. In Normal mode type the `/`{normal} character. Notice that it and the
cursor appear at the bottom of the screen as with the `:`{normal} command.
- 2. Now type 'errroor' `<Enter>`{normal}. This is the word you want to search
- for.
+ 2. Now type 'errroor' `<Enter>`{normal}. This is the word you want to search for.
3. To search for the same phrase again, simply type [n](n).
To search for the same phrase in the opposite direction, type [N](N).
- 4. To search for a phrase in the backward direction, use [?](?) instead
- of `/`{normal}.
+ 4. To search for a phrase in the backward direction, use [?](?) instead of `/`{normal}.
- 5. To go back to where you came from press `<C-o>`{normal} (keep `<Ctrl>`{normal} pressed down while pressing the letter `o`{normal}). Repeat to go back
- further. `<C-i>`{normal} goes forward.
+ 5. To go back to where you came from press `<C-o>`{normal}.
+ (keep `<Ctrl>`{normal} pressed down while pressing the letter `o`{normal}).
+ Repeat to go back further. `<C-i>`{normal} goes forward.
"errroor" is not the way to spell error; errroor is an error.
@@ -525,16 +518,14 @@ NOTE: This is very useful in debugging a program with unmatched parentheses!
2. Type
~~~ cmd
- :s/thee/the/
+ :s/thee/the/
~~~
-
- NOTE that the [:s](:s) command only changed the first occurrence of "thee" in the line.
+ NOTE: the [:s](:s) command only changed the first match of "thee" in the line.
3. Now type
~~~ cmd
- :s/thee/the/g
+ :s/thee/the/g
~~~
-
Adding the g [flag](:s_flags) means to substitute globally in the line,
change all occurrences of "thee" in the line.
@@ -542,20 +533,20 @@ Usually thee best time to see thee flowers is in thee spring.
4. To change every occurrence of a character string between two lines, type
~~~ cmd
- :#,#s/old/new/g
+ :#,#s/old/new/g
~~~
where #,# are the line numbers of the range of lines where the
substitution is to be done.
Type
~~~ cmd
- :%s/old/new/g
+ :%s/old/new/g
~~~
to change every occurrence in the whole file.
Type
~~~ cmd
- :%s/old/new/gc
+ :%s/old/new/gc
~~~
to find every occurrence in the whole file, with a prompt whether to
substitute or not.
@@ -564,7 +555,7 @@ Usually thee best time to see thee flowers is in thee spring.
1. `<C-g>`{normal} displays your location and the file status.
`G`{normal} moves to the end of the file.
- number `G`{normal} moves to that line number.
+ number `G`{normal} moves to that line number.
`gg`{normal} moves to the first line.
2. Typing `/`{normal} followed by a phrase searches FORWARD for the phrase.
@@ -643,7 +634,6 @@ NOTE: If you were to exit Vim and start it again with `nvim TEST`, the file
~~~ cmd
:!rm TEST
~~~
-
# Lesson 5.3: SELECTING TEXT TO WRITE
** To save part of the file, type `v`{normal} motion `:w FILENAME`{vim}. **
@@ -655,7 +645,7 @@ NOTE: If you were to exit Vim and start it again with `nvim TEST`, the file
3. Press the `:`{normal} character. At the bottom of the screen
- :'<,'>
+ `:'<,'>`{vim}
will appear.
@@ -669,12 +659,12 @@ NOTE: If you were to exit Vim and start it again with `nvim TEST`, the file
before you press `<Enter>`{normal}.
- 5. Vim will write the selected lines to the file TEST. Use `:!ls`{vim} to see it. Do not remove it yet! We will use it in the next lesson.
+ 5. Vim will write the selected lines to the file TEST. Use `:!ls`{vim} to see it.
+ Do not remove it yet! We will use it in the next lesson.
-NOTE: Pressing [v](v) starts [Visual selection](visual-mode). You can move
- the cursor around to make the selection bigger or smaller. Then you can
- use an operator to do something with the text. For example, `d`{normal}
- deletes the text.
+NOTE: Pressing [v](v) starts [Visual selection](visual-mode). You can move the cursor around to
+ make the selection bigger or smaller. Then you can use an operator to
+ do something with the text. For example, `d`{normal} deletes the text.
# Lesson 5.4: RETRIEVING AND MERGING FILES
@@ -689,8 +679,8 @@ NOTE: After executing Step 2 you will see text from Lesson 5.3. Then move
`:r TEST`{vim}
- where TEST is the name of the file you used.
- The file you retrieve is placed below the cursor line.
+ where TEST is the name of the file you used.
+ The file you retrieve is placed below the cursor line.
3. To verify that a file was retrieved, cursor back and notice that there
are now two copies of Lesson 5.3, the original and the file version.
@@ -706,20 +696,20 @@ NOTE: You can also read the output of an external command. For example,
1. [:!command](:!cmd) executes an external command.
Some useful examples are:
- `:!ls`{vim} - shows a directory listing
- `:!rm FILENAME`{vim} - removes file FILENAME
+ `:!ls`{vim} - shows a directory listing
+ `:!rm FILENAME`{vim} - removes file FILENAME
- 2. [:w](:w) FILENAME writes the current Vim file to disk with
- name FILENAME.
+ 2. [:w](:w) FILENAME writes the current Vim file to disk with
+ name FILENAME.
3. [v](v) motion :w FILENAME saves the Visually selected lines in file
FILENAME.
- 4. [:r](:r) FILENAME retrieves disk file FILENAME and puts it
- below the cursor position.
+ 4. [:r](:r) FILENAME retrieves disk file FILENAME and puts it
+ below the cursor position.
- 5. [:r !dir](:r!) reads the output of the dir command and
- puts it below the cursor position.
+ 5. [:r !dir](:r!) reads the output of the dir command and
+ puts it below the cursor position.
# Lesson 6.1: THE OPEN COMMAND
@@ -747,14 +737,11 @@ Open up a line above this by typing O while the cursor is on this line.
2. Press `e`{normal} until the cursor is on the end of "li".
- 3. Type the lowercase letter `a`{normal} to [append](a) text AFTER the
- cursor.
+ 3. Type the lowercase letter `a`{normal} to [append](a) text AFTER the cursor.
- 4. Complete the word like the line below it. Press `<Esc>`{normal} to exit
- Insert mode.
+ 4. Complete the word like the line below it. Press `<Esc>`{normal} to exit Insert mode.
- 5. Use `e`{normal} to move to the next incomplete word and repeat steps 3
- and 4.
+ 5. Use `e`{normal} to move to the next incomplete word and repeat steps 3 and 4.
This li will allow you to pract appendi text to a line.
This line will allow you to practice appending text to a line.
@@ -767,21 +754,21 @@ NOTE: [a](a), [i](i) and [A](A) all go to the same Insert mode, the only
** Type a capital `R`{normal} to replace more than one character. **
1. Move the cursor to the first line below marked ✗. Move the cursor to
- the beginning of the first "xxx".
+ the beginning of the first "xxx".
2. Now press `R`{normal} ([capital R](R)) and type the number below it in the
- second line, so that it replaces the "xxx".
+ second line, so that it replaces the "xxx".
3. Press `<Esc>`{normal} to leave [Replace mode](mode-replace). Notice that
- the rest of the line remains unmodified.
+ the rest of the line remains unmodified.
4. Repeat the steps to replace the remaining "xxx".
Adding 123 to xxx gives you xxx.
Adding 123 to 456 gives you 579.
-NOTE: Replace mode is like Insert mode, but every typed character deletes an
- existing character.
+NOTE: Replace mode is like Insert mode, but every typed character
+ deletes an existing character.
# Lesson 6.4: COPY AND PASTE TEXT
@@ -875,17 +862,17 @@ NOTE: If you want to ignore case for just one search command, use [\c](/\c)
~~~ cmd
:set invic
~~~
-
# Lesson 7.1: GETTING HELP
** Use the on-line help system. **
-Vim has a comprehensive on-line help system. To get started, try one of
-these three:
- - press the `<HELP>`{normal} key (if you have one)
- - press the `<F1>`{normal} key (if you have one)
- - type
- `:help`{vim}
+Vim has a comprehensive on-line help system.
+
+To get started, try one of these three:
+
+ - press the `<HELP>`{normal} key (if you have one)
+ - press the `<F1>`{normal} key (if you have one)
+ - type `:help`{vim}
Read the text in the help window to find out how the help works.
Type `<C-w><C-w>`{normal} to jump from one window to another.
@@ -907,10 +894,12 @@ Vim has many more features than Vi, but most of them are disabled by
default. To start using more features you have to create a "vimrc" file.
1. Start editing the "vimrc" file.
+
`:call mkdir(stdpath('config'),'p')`{vim}
`:exe 'edit' stdpath('config').'/init.vim'`{vim}
2. Write the file with:
+
`:w`{vim}
You can add all your preferred settings to this "vimrc" file.
@@ -924,17 +913,15 @@ default. To start using more features you have to create a "vimrc" file.
2. Type the start of a command: `:e`{vim}
- 3. Press `<C-d>`{normal} and Vim will show a list of commands that start
- with "e".
+ 3. Press `<C-d>`{normal} and Vim will show a list of commands beginning with "e".
4. Press `<Tab>`{normal} and Vim will complete the command name to ":edit".
5. Now add a space and the start of an existing file name: `:edit FIL`{vim}
- 6. Press `<Tab>`{normal}. Vim will complete the name (if it is unique).
+ 6. Press `<Tab>`{normal}. Vim will complete the name ("FIL" -> "FILE", if it is unique).
-NOTE: Completion works for many commands. It is especially useful for
- `:help`{vim}.
+NOTE: Completion works for many commands. It is especially useful for `:help`{vim}.
# Lesson 7 SUMMARY
@@ -950,7 +937,7 @@ NOTE: Completion works for many commands. It is especially useful for
5. Create a vimrc startup script to keep your preferred settings.
6. While in command mode, press `<C-d>`{normal} to see possible completions.
- Press `<Tab>`{normal} to use one completion.
+ Press `<Tab>`{normal} to use one completion.
# CONCLUSION
@@ -961,13 +948,20 @@ many many more commands. Consult the help often.
There are many resources online to learn more about vim. Here's a bunch of
them:
-- *Learn Vim Progressively*: http://yannesposito.com/Scratch/en/blog/Learn-Vim-Progressively/
-- *Learning Vim in 2014*: http://benmccormick.org/learning-vim-in-2014/
-- *Vimcasts*: http://vimcasts.org/
-- *Vim Video-Tutorials by Derek Wyatt*: http://derekwyatt.org/vim/tutorials/
-- *Learn Vimscript the Hard Way*: http://learnvimscriptthehardway.stevelosh.com/
-- *7 Habits of Effective Text Editing*: http://www.moolenaar.net/habits.html
-- *vim-galore*: https://github.com/mhinz/vim-galore
+- *Learn Vim Progressively*:
+ http://yannesposito.com/Scratch/en/blog/Learn-Vim-Progressively/
+- *Learning Vim in 2013*:
+ http://benmccormick.org/learning-vim-in-2014/
+- *Vimcasts*:
+ http://vimcasts.org/
+- *Vim Video-Tutorials by Derek Wyatt*:
+ http://derekwyatt.org/vim/tutorials/
+- *Learn Vimscript the Hard Way*:
+ http://learnvimscriptthehardway.stevelosh.com/
+- *7 Habits of Effective Text Editing*:
+ http://www.moolenaar.net/habits.html
+- *vim-galore*:
+ https://github.com/mhinz/vim-galore
If you prefer a book, *Practical Vim* by Drew Neil is recommended often
(the sequel, *Modern Vim*, includes material specific to nvim).
@@ -978,3 +972,5 @@ University. E-mail: bware@mines.colorado.edu.
Modified for Vim by Bram Moolenaar.
Modified for vim-tutor-mode by Felipe Morales.
+
+// vim: nowrap
diff --git a/runtime/tutor/en/vim-01-beginner.tutor.json b/runtime/tutor/en/vim-01-beginner.tutor.json
index af22cf2aca..e71ead976d 100644
--- a/runtime/tutor/en/vim-01-beginner.tutor.json
+++ b/runtime/tutor/en/vim-01-beginner.tutor.json
@@ -1,45 +1,45 @@
{
"expect": {
- "24": -1,
+ "25": -1,
"103": "The cow jumped over the moon.",
- "124": "There is some text missing from this line.",
"125": "There is some text missing from this line.",
- "144": "There is some text missing from this line.",
+ "126": "There is some text missing from this line.",
"145": "There is some text missing from this line.",
- "146": "There is also some text missing here.",
+ "146": "There is some text missing from this line.",
"147": "There is also some text missing here.",
- "220": "There are some words that don't belong in this sentence.",
- "236": "Somebody typed the end of this line twice.",
- "276": -1,
- "295": "This line of words is cleaned up.",
+ "148": "There is also some text missing here.",
+ "216": "There are some words that don't belong in this sentence.",
+ "232": "Somebody typed the end of this line twice.",
+ "271": -1,
+ "290": "This line of words is cleaned up.",
+ "304": -1,
+ "305": -1,
+ "306": -1,
+ "307": -1,
+ "308": -1,
"309": -1,
"310": -1,
- "311": -1,
- "312": -1,
- "313": -1,
- "314": -1,
- "315": -1,
- "332": "Fix the errors on this line and replace them with undo.",
- "372": -1,
- "373": -1,
- "374": -1,
- "375": -1,
- "389": "When this line was typed in, someone pressed some wrong keys!",
- "390": "When this line was typed in, someone pressed some wrong keys!",
- "411": "This line has a few words that need changing using the change operator.",
- "412": "This line has a few words that need changing using the change operator.",
- "432": "The end of this line needs to be corrected using the `c$` command.",
- "433": "The end of this line needs to be corrected using the `c$` command.",
- "497": -1,
- "516": -1,
- "541": "Usually the best time to see the flowers is in the spring.",
- "735": -1,
- "740": -1,
- "759": "This line will allow you to practice appending text to a line.",
- "760": "This line will allow you to practice appending text to a line.",
- "780": "Adding 123 to 456 gives you 579.",
- "781": "Adding 123 to 456 gives you 579.",
- "807": "a) This is the first item.",
- "808": "b) This is the second item."
+ "324": "Fix the errors on this line and replace them with undo.",
+ "367": -1,
+ "368": -1,
+ "369": -1,
+ "370": -1,
+ "384": "When this line was typed in, someone pressed some wrong keys!",
+ "385": "When this line was typed in, someone pressed some wrong keys!",
+ "405": "This line has a few words that need changing using the change operator.",
+ "406": "This line has a few words that need changing using the change operator.",
+ "426": "The end of this line needs to be corrected using the `c$` command.",
+ "427": "The end of this line needs to be corrected using the `c$` command.",
+ "490": -1,
+ "509": -1,
+ "532": "Usually the best time to see the flowers is in the spring.",
+ "725": -1,
+ "730": -1,
+ "746": "This line will allow you to practice appending text to a line.",
+ "747": "This line will allow you to practice appending text to a line.",
+ "767": "Adding 123 to 456 gives you 579.",
+ "768": "Adding 123 to 456 gives you 579.",
+ "794": "a) This is the first item.",
+ "795": "b) This is the second item."
}
}
diff --git a/src/nvim/CMakeLists.txt b/src/nvim/CMakeLists.txt
index e4d7115654..3b2207f80b 100644
--- a/src/nvim/CMakeLists.txt
+++ b/src/nvim/CMakeLists.txt
@@ -29,7 +29,7 @@ set(API_UI_EVENTS_GENERATOR ${GENERATOR_DIR}/gen_api_ui_events.lua)
set(GENERATOR_C_GRAMMAR ${GENERATOR_DIR}/c_grammar.lua)
set(API_METADATA ${PROJECT_BINARY_DIR}/api_metadata.mpack)
set(FUNCS_DATA ${PROJECT_BINARY_DIR}/funcs_data.mpack)
-set(MSGPACK_LUA_C_BINDINGS ${GENERATED_DIR}/msgpack_lua_c_bindings.generated.c)
+set(LUA_API_C_BINDINGS ${GENERATED_DIR}/lua_api_c_bindings.generated.c)
set(HEADER_GENERATOR ${GENERATOR_DIR}/gen_declarations.lua)
set(GENERATED_INCLUDES_DIR ${PROJECT_BINARY_DIR}/include)
set(GENERATED_API_DISPATCH ${GENERATED_DIR}/api/private/dispatch_wrappers.generated.h)
@@ -56,6 +56,8 @@ set(VIM_MODULE_FILE ${GENERATED_DIR}/lua/vim_module.generated.h)
set(LUA_VIM_MODULE_SOURCE ${PROJECT_SOURCE_DIR}/src/nvim/lua/vim.lua)
set(LUA_SHARED_MODULE_SOURCE ${PROJECT_SOURCE_DIR}/runtime/lua/vim/shared.lua)
set(LUA_INSPECT_MODULE_SOURCE ${PROJECT_SOURCE_DIR}/runtime/lua/vim/inspect.lua)
+set(LUA_F_MODULE_SOURCE ${PROJECT_SOURCE_DIR}/runtime/lua/vim/F.lua)
+set(LUA_META_MODULE_SOURCE ${PROJECT_SOURCE_DIR}/runtime/lua/vim/_meta.lua)
set(CHAR_BLOB_GENERATOR ${GENERATOR_DIR}/gen_char_blob.lua)
set(LINT_SUPPRESS_FILE ${PROJECT_BINARY_DIR}/errors.json)
set(LINT_SUPPRESS_URL_BASE "https://raw.githubusercontent.com/neovim/doc/gh-pages/reports/clint")
@@ -305,11 +307,11 @@ add_custom_command(OUTPUT ${GENERATED_UNICODE_TABLES}
add_custom_command(
OUTPUT ${GENERATED_API_DISPATCH} ${GENERATED_FUNCS_METADATA}
- ${API_METADATA} ${MSGPACK_LUA_C_BINDINGS}
+ ${API_METADATA} ${LUA_API_C_BINDINGS}
COMMAND ${LUA_PRG} ${API_DISPATCH_GENERATOR} ${CMAKE_CURRENT_LIST_DIR}
${GENERATED_API_DISPATCH}
${GENERATED_FUNCS_METADATA} ${API_METADATA}
- ${MSGPACK_LUA_C_BINDINGS}
+ ${LUA_API_C_BINDINGS}
${API_HEADERS}
DEPENDS
${API_HEADERS}
@@ -325,15 +327,19 @@ add_custom_command(
${LUA_VIM_MODULE_SOURCE} vim_module
${LUA_SHARED_MODULE_SOURCE} shared_module
${LUA_INSPECT_MODULE_SOURCE} inspect_module
+ ${LUA_F_MODULE_SOURCE} lua_F_module
+ ${LUA_META_MODULE_SOURCE} lua_meta_module
DEPENDS
${CHAR_BLOB_GENERATOR}
${LUA_VIM_MODULE_SOURCE}
${LUA_SHARED_MODULE_SOURCE}
${LUA_INSPECT_MODULE_SOURCE}
+ ${LUA_F_MODULE_SOURCE}
+ ${LUA_META_MODULE_SOURCE}
)
list(APPEND NVIM_GENERATED_SOURCES
- "${MSGPACK_LUA_C_BINDINGS}"
+ "${LUA_API_C_BINDINGS}"
)
add_custom_command(
diff --git a/src/nvim/api/private/helpers.c b/src/nvim/api/private/helpers.c
index eedcfd69b8..0ed5e6408b 100644
--- a/src/nvim/api/private/helpers.c
+++ b/src/nvim/api/private/helpers.c
@@ -37,7 +37,7 @@
/// Helper structure for vim_to_object
typedef struct {
- kvec_t(Object) stack; ///< Object stack.
+ kvec_withinit_t(Object, 2) stack; ///< Object stack.
} EncodedData;
#ifdef INCLUDE_GENERATED_DECLARATIONS
@@ -418,28 +418,25 @@ void set_option_to(uint64_t channel_id, void *to, int type,
#define TYPVAL_ENCODE_ALLOW_SPECIALS false
#define TYPVAL_ENCODE_CONV_NIL(tv) \
- kv_push(edata->stack, NIL)
+ kvi_push(edata->stack, NIL)
#define TYPVAL_ENCODE_CONV_BOOL(tv, num) \
- kv_push(edata->stack, BOOLEAN_OBJ((Boolean)(num)))
+ kvi_push(edata->stack, BOOLEAN_OBJ((Boolean)(num)))
#define TYPVAL_ENCODE_CONV_NUMBER(tv, num) \
- kv_push(edata->stack, INTEGER_OBJ((Integer)(num)))
+ kvi_push(edata->stack, INTEGER_OBJ((Integer)(num)))
#define TYPVAL_ENCODE_CONV_UNSIGNED_NUMBER TYPVAL_ENCODE_CONV_NUMBER
#define TYPVAL_ENCODE_CONV_FLOAT(tv, flt) \
- kv_push(edata->stack, FLOAT_OBJ((Float)(flt)))
+ kvi_push(edata->stack, FLOAT_OBJ((Float)(flt)))
#define TYPVAL_ENCODE_CONV_STRING(tv, str, len) \
do { \
const size_t len_ = (size_t)(len); \
const char *const str_ = (const char *)(str); \
assert(len_ == 0 || str_ != NULL); \
- kv_push(edata->stack, STRING_OBJ(((String) { \
- .data = xmemdupz((len_?str_:""), len_), \
- .size = len_ \
- }))); \
+ kvi_push(edata->stack, STRING_OBJ(cbuf_to_string((len_?str_:""), len_))); \
} while (0)
#define TYPVAL_ENCODE_CONV_STR_STRING TYPVAL_ENCODE_CONV_STRING
@@ -458,17 +455,17 @@ void set_option_to(uint64_t channel_id, void *to, int type,
#define TYPVAL_ENCODE_CONV_FUNC_END(tv)
#define TYPVAL_ENCODE_CONV_EMPTY_LIST(tv) \
- kv_push(edata->stack, ARRAY_OBJ(((Array) { .capacity = 0, .size = 0 })))
+ kvi_push(edata->stack, ARRAY_OBJ(((Array) { .capacity = 0, .size = 0 })))
#define TYPVAL_ENCODE_CONV_EMPTY_DICT(tv, dict) \
- kv_push(edata->stack, \
- DICTIONARY_OBJ(((Dictionary) { .capacity = 0, .size = 0 })))
+ kvi_push(edata->stack, \
+ DICTIONARY_OBJ(((Dictionary) { .capacity = 0, .size = 0 })))
static inline void typval_encode_list_start(EncodedData *const edata,
const size_t len)
FUNC_ATTR_ALWAYS_INLINE FUNC_ATTR_NONNULL_ALL
{
- kv_push(edata->stack, ARRAY_OBJ(((Array) {
+ kvi_push(edata->stack, ARRAY_OBJ(((Array) {
.capacity = len,
.size = 0,
.items = xmalloc(len * sizeof(*((Object)OBJECT_INIT).data.array.items)),
@@ -510,7 +507,7 @@ static inline void typval_encode_dict_start(EncodedData *const edata,
const size_t len)
FUNC_ATTR_ALWAYS_INLINE FUNC_ATTR_NONNULL_ALL
{
- kv_push(edata->stack, DICTIONARY_OBJ(((Dictionary) {
+ kvi_push(edata->stack, DICTIONARY_OBJ(((Dictionary) {
.capacity = len,
.size = 0,
.items = xmalloc(len * sizeof(
@@ -618,14 +615,15 @@ static inline void typval_encode_dict_end(EncodedData *const edata)
/// @return The converted value
Object vim_to_object(typval_T *obj)
{
- EncodedData edata = { .stack = KV_INITIAL_VALUE };
+ EncodedData edata;
+ kvi_init(edata.stack);
const int evo_ret = encode_vim_to_object(&edata, obj,
"vim_to_object argument");
(void)evo_ret;
assert(evo_ret == OK);
Object ret = kv_A(edata.stack, 0);
assert(kv_size(edata.stack) == 1);
- kv_destroy(edata.stack);
+ kvi_destroy(edata.stack);
return ret;
}
diff --git a/src/nvim/api/vim.c b/src/nvim/api/vim.c
index 90c43a1b04..5f48a26a29 100644
--- a/src/nvim/api/vim.c
+++ b/src/nvim/api/vim.c
@@ -608,12 +608,15 @@ static Object _call_function(String fn, Array args, dict_T *self, Error *err)
recursive++;
try_start();
typval_T rettv;
- int dummy;
+ funcexe_T funcexe = FUNCEXE_INIT;
+ funcexe.firstline = curwin->w_cursor.lnum;
+ funcexe.lastline = curwin->w_cursor.lnum;
+ funcexe.evaluate = true;
+ funcexe.selfdict = self;
// call_func() retval is deceptive, ignore it. Instead we set `msg_list`
// (see above) to capture abort-causing non-exception errors.
(void)call_func((char_u *)fn.data, (int)fn.size, &rettv, (int)args.size,
- vim_args, NULL, curwin->w_cursor.lnum, curwin->w_cursor.lnum,
- &dummy, true, NULL, self);
+ vim_args, &funcexe);
if (!try_end(err)) {
rv = vim_to_object(&rettv);
}
@@ -2054,27 +2057,28 @@ void nvim_set_client_info(uint64_t channel_id, String name,
rpc_set_client_info(channel_id, info);
}
-/// Get information about a channel.
+/// Gets information about a channel.
///
/// @returns Dictionary describing a channel, with these keys:
-/// - "stream" the stream underlying the channel
+/// - "id" Channel id.
+/// - "argv" (optional) Job arguments list.
+/// - "stream" Stream underlying the channel.
/// - "stdio" stdin and stdout of this Nvim instance
/// - "stderr" stderr of this Nvim instance
/// - "socket" TCP/IP socket or named pipe
-/// - "job" job with communication over its stdio
-/// - "mode" how data received on the channel is interpreted
-/// - "bytes" send and receive raw bytes
-/// - "terminal" a |terminal| instance interprets ASCII sequences
-/// - "rpc" |RPC| communication on the channel is active
-/// - "pty" Name of pseudoterminal, if one is used (optional).
-/// On a POSIX system, this will be a device path like
-/// /dev/pts/1. Even if the name is unknown, the key will
-/// still be present to indicate a pty is used. This is
-/// currently the case when using winpty on windows.
-/// - "buffer" buffer with connected |terminal| instance (optional)
-/// - "client" information about the client on the other end of the
-/// RPC channel, if it has added it using
-/// |nvim_set_client_info()|. (optional)
+/// - "job" Job with communication over its stdio.
+/// - "mode" How data received on the channel is interpreted.
+/// - "bytes" Send and receive raw bytes.
+/// - "terminal" |terminal| instance interprets ASCII sequences.
+/// - "rpc" |RPC| communication on the channel is active.
+/// - "pty" (optional) Name of pseudoterminal. On a POSIX system this
+/// is a device path like "/dev/pts/1". If the name is unknown,
+/// the key will still be present if a pty is used (e.g. for
+/// winpty on Windows).
+/// - "buffer" (optional) Buffer with connected |terminal| instance.
+/// - "client" (optional) Info about the peer (client on the other end of
+/// the RPC channel), if provided by it via
+/// |nvim_set_client_info()|.
///
Dictionary nvim_get_chan_info(Integer chan, Error *err)
FUNC_API_SINCE(4)
diff --git a/src/nvim/aucmd.c b/src/nvim/aucmd.c
index 32c77fa288..802fc9de57 100644
--- a/src/nvim/aucmd.c
+++ b/src/nvim/aucmd.c
@@ -8,6 +8,7 @@
#include "nvim/ui.h"
#include "nvim/aucmd.h"
#include "nvim/eval.h"
+#include "nvim/ex_docmd.h"
#include "nvim/ex_getln.h"
#include "nvim/buffer.h"
@@ -35,6 +36,29 @@ void do_autocmd_uienter(uint64_t chanid, bool attached)
recursive = false;
}
+void init_default_autocmds(void)
+{
+ // open terminals when opening files that start with term://
+#define PROTO "term://"
+ do_cmdline_cmd("augroup nvim_terminal");
+ do_cmdline_cmd("autocmd BufReadCmd " PROTO "* ++nested "
+ "if !exists('b:term_title')|call termopen("
+ // Capture the command string
+ "matchstr(expand(\"<amatch>\"), "
+ "'\\c\\m" PROTO "\\%(.\\{-}//\\%(\\d\\+:\\)\\?\\)\\?\\zs.*'), "
+ // capture the working directory
+ "{'cwd': expand(get(matchlist(expand(\"<amatch>\"), "
+ "'\\c\\m" PROTO "\\(.\\{-}\\)//'), 1, ''))})"
+ "|endif");
+ do_cmdline_cmd("augroup END");
+#undef PROTO
+
+ // limit syntax synchronization in the command window
+ do_cmdline_cmd("augroup nvim_cmdwin");
+ do_cmdline_cmd("autocmd! CmdwinEnter [:>] syntax sync minlines=1 maxlines=1");
+ do_cmdline_cmd("augroup END");
+}
+
static void focusgained_event(void **argv)
{
bool *gainedp = argv[0];
diff --git a/src/nvim/buffer.c b/src/nvim/buffer.c
index fdb3ffdc7e..81f8b9073e 100644
--- a/src/nvim/buffer.c
+++ b/src/nvim/buffer.c
@@ -1218,8 +1218,8 @@ do_buffer(
return FAIL;
}
- if (!forceit && (buf->terminal || bufIsChanged(buf))) {
- if ((p_confirm || cmdmod.confirm) && p_write && !buf->terminal) {
+ if (!forceit && bufIsChanged(buf)) {
+ if ((p_confirm || cmdmod.confirm) && p_write) {
dialog_changed(buf, false);
if (!bufref_valid(&bufref)) {
// Autocommand deleted buffer, oops! It's not changed now.
@@ -1231,22 +1231,22 @@ do_buffer(
return FAIL;
}
} else {
- if (buf->terminal) {
- if (p_confirm || cmdmod.confirm) {
- if (!dialog_close_terminal(buf)) {
- return FAIL;
- }
- } else {
- EMSG2(_("E89: %s will be killed (add ! to override)"),
- (char *)buf->b_fname);
- return FAIL;
- }
- } else {
- EMSGN(_("E89: No write since last change for buffer %" PRId64
- " (add ! to override)"),
- buf->b_fnum);
+ EMSGN(_("E89: No write since last change for buffer %" PRId64
+ " (add ! to override)"),
+ buf->b_fnum);
+ return FAIL;
+ }
+ }
+
+ if (!forceit && buf->terminal && terminal_running(buf->terminal)) {
+ if (p_confirm || cmdmod.confirm) {
+ if (!dialog_close_terminal(buf)) {
return FAIL;
}
+ } else {
+ EMSG2(_("E89: %s will be killed (add ! to override)"),
+ (char *)buf->b_fname);
+ return FAIL;
}
}
diff --git a/src/nvim/channel.c b/src/nvim/channel.c
index 6f12d2eab8..94db7fb3b9 100644
--- a/src/nvim/channel.c
+++ b/src/nvim/channel.c
@@ -240,6 +240,10 @@ static void free_channel_event(void **argv)
rpc_free(chan);
}
+ if (chan->streamtype == kChannelStreamProc) {
+ process_free(&chan->stream.proc);
+ }
+
callback_reader_free(&chan->on_data);
callback_reader_free(&chan->on_stderr);
callback_free(&chan->on_exit);
@@ -847,13 +851,24 @@ Dictionary channel_info(uint64_t id)
const char *stream_desc, *mode_desc;
switch (chan->streamtype) {
- case kChannelStreamProc:
+ case kChannelStreamProc: {
stream_desc = "job";
if (chan->stream.proc.type == kProcessTypePty) {
const char *name = pty_process_tty_name(&chan->stream.pty);
PUT(info, "pty", STRING_OBJ(cstr_to_string(name)));
}
+
+ char **p = chan->stream.proc.argv;
+ Array argv = ARRAY_DICT_INIT;
+ if (p != NULL) {
+ while (*p != NULL) {
+ ADD(argv, STRING_OBJ(cstr_to_string(*p)));
+ p++;
+ }
+ }
+ PUT(info, "argv", ARRAY_OBJ(argv));
break;
+ }
case kChannelStreamStdio:
stream_desc = "stdio";
diff --git a/src/nvim/eval.c b/src/nvim/eval.c
index 5e18a77b6d..5603fbb082 100644
--- a/src/nvim/eval.c
+++ b/src/nvim/eval.c
@@ -65,6 +65,8 @@ static char *e_missbrac = N_("E111: Missing ']'");
static char *e_dictrange = N_("E719: Cannot use [:] with a Dictionary");
static char *e_illvar = N_("E461: Illegal variable name: %s");
static char *e_cannot_mod = N_("E995: Cannot modify existing variable");
+static char *e_nowhitespace
+ = N_("E274: No white space allowed before parenthesis");
static char *e_invalwindow = N_("E957: Invalid window number");
static char *e_lock_unlock = N_("E940: Cannot lock or unlock variable %s");
@@ -736,15 +738,15 @@ int eval_expr_typval(const typval_T *expr, typval_T *argv,
int argc, typval_T *rettv)
FUNC_ATTR_NONNULL_ARG(1, 2, 4)
{
- int dummy;
+ funcexe_T funcexe = FUNCEXE_INIT;
if (expr->v_type == VAR_FUNC) {
const char_u *const s = expr->vval.v_string;
if (s == NULL || *s == NUL) {
return FAIL;
}
- if (call_func(s, -1, rettv, argc, argv, NULL,
- 0L, 0L, &dummy, true, NULL, NULL) == FAIL) {
+ funcexe.evaluate = true;
+ if (call_func(s, -1, rettv, argc, argv, &funcexe) == FAIL) {
return FAIL;
}
} else if (expr->v_type == VAR_PARTIAL) {
@@ -753,8 +755,9 @@ int eval_expr_typval(const typval_T *expr, typval_T *argv,
if (s == NULL || *s == NUL) {
return FAIL;
}
- if (call_func(s, -1, rettv, argc, argv, NULL,
- 0L, 0L, &dummy, true, partial, NULL) == FAIL) {
+ funcexe.evaluate = true;
+ funcexe.partial = partial;
+ if (call_func(s, -1, rettv, argc, argv, &funcexe) == FAIL) {
return FAIL;
}
} else {
@@ -1050,7 +1053,6 @@ int call_vim_function(
)
FUNC_ATTR_NONNULL_ALL
{
- int doesrange;
int ret;
int len = (int)STRLEN(func);
partial_T *pt = NULL;
@@ -1066,9 +1068,12 @@ int call_vim_function(
}
rettv->v_type = VAR_UNKNOWN; // tv_clear() uses this.
- ret = call_func(func, len, rettv, argc, argv, NULL,
- curwin->w_cursor.lnum, curwin->w_cursor.lnum,
- &doesrange, true, pt, NULL);
+ funcexe_T funcexe = FUNCEXE_INIT;
+ funcexe.firstline = curwin->w_cursor.lnum;
+ funcexe.lastline = curwin->w_cursor.lnum;
+ funcexe.evaluate = true;
+ funcexe.partial = pt;
+ ret = call_func(func, len, rettv, argc, argv, &funcexe);
fail:
if (ret == FAIL) {
@@ -1724,7 +1729,9 @@ static const char *list_arg_vars(exarg_T *eap, const char *arg, int *first)
} else {
// handle d.key, l[idx], f(expr)
const char *const arg_subsc = arg;
- if (handle_subscript(&arg, &tv, true, true) == FAIL) {
+ if (handle_subscript(&arg, &tv, true, true, (const char_u *)name,
+ (const char_u **)&name)
+ == FAIL) {
error = true;
} else {
if (arg == arg_subsc && len == 2 && name[1] == ':') {
@@ -3142,6 +3149,65 @@ static int pattern_match(char_u *pat, char_u *text, bool ic)
return matches;
}
+/// Handle a name followed by "(". Both for just "name(arg)" and for
+/// "expr->name(arg)".
+//
+/// @param arg Points to "(", will be advanced
+/// @param basetv "expr" for "expr->name(arg)"
+//
+/// @return OK or FAIL.
+static int eval_func(char_u **const arg, char_u *const name, const int name_len,
+ typval_T *const rettv, const bool evaluate,
+ typval_T *const basetv)
+ FUNC_ATTR_NONNULL_ARG(1, 2, 4)
+{
+ char_u *s = name;
+ int len = name_len;
+
+ if (!evaluate) {
+ check_vars((const char *)s, len);
+ }
+
+ // If "s" is the name of a variable of type VAR_FUNC
+ // use its contents.
+ partial_T *partial;
+ s = deref_func_name((const char *)s, &len, &partial, !evaluate);
+
+ // Need to make a copy, in case evaluating the arguments makes
+ // the name invalid.
+ s = xmemdupz(s, len);
+
+ // Invoke the function.
+ funcexe_T funcexe = FUNCEXE_INIT;
+ funcexe.firstline = curwin->w_cursor.lnum;
+ funcexe.lastline = curwin->w_cursor.lnum;
+ funcexe.evaluate = evaluate;
+ funcexe.partial = partial;
+ funcexe.basetv = basetv;
+ int ret = get_func_tv(s, len, rettv, arg, &funcexe);
+
+ xfree(s);
+
+ // If evaluate is false rettv->v_type was not set in
+ // get_func_tv, but it's needed in handle_subscript() to parse
+ // what follows. So set it here.
+ if (rettv->v_type == VAR_UNKNOWN && !evaluate && **arg == '(') {
+ rettv->vval.v_string = (char_u *)tv_empty_string;
+ rettv->v_type = VAR_FUNC;
+ }
+
+ // Stop the expression evaluation when immediately
+ // aborting on error, or when an interrupt occurred or
+ // an exception was thrown but not caught.
+ if (evaluate && aborting()) {
+ if (ret == OK) {
+ tv_clear(rettv);
+ }
+ ret = FAIL;
+ }
+ return ret;
+}
+
// TODO(ZyX-I): move to eval/expressions
/*
@@ -3161,6 +3227,8 @@ int eval0(char_u *arg, typval_T *rettv, char_u **nextcmd, int evaluate)
{
int ret;
char_u *p;
+ const int did_emsg_before = did_emsg;
+ const int called_emsg_before = called_emsg;
p = skipwhite(arg);
ret = eval1(&p, rettv, evaluate);
@@ -3170,8 +3238,10 @@ int eval0(char_u *arg, typval_T *rettv, char_u **nextcmd, int evaluate)
}
// Report the invalid expression unless the expression evaluation has
// been cancelled due to an aborting error, an interrupt, or an
- // exception.
- if (!aborting()) {
+ // exception, or we already gave a more specific error.
+ // Also check called_emsg for when using assert_fails().
+ if (!aborting() && did_emsg == did_emsg_before
+ && called_emsg == called_emsg_before) {
emsgf(_(e_invexpr2), arg);
}
ret = FAIL;
@@ -3801,6 +3871,7 @@ static int eval6(char_u **arg, typval_T *rettv, int evaluate, int want_string)
// + in front unary plus (ignored)
// trailing [] subscript in String or List
// trailing .name entry in Dictionary
+// trailing ->name() method call
//
// "arg" must point to the first non-white of the expression.
// "arg" is advanced to the next non-white after the recognized expression.
@@ -3815,10 +3886,10 @@ static int eval7(
{
varnumber_T n;
int len;
- char_u *s;
- char_u *start_leader, *end_leader;
+ char_u *s;
+ const char_u *start_leader, *end_leader;
int ret = OK;
- char_u *alias;
+ char_u *alias;
// Initialise variable so that tv_clear() can't mistake this for a
// string and free a string that isn't there.
@@ -3968,44 +4039,7 @@ static int eval7(
ret = FAIL;
} else {
if (**arg == '(') { // recursive!
- partial_T *partial;
-
- if (!evaluate) {
- check_vars((const char *)s, len);
- }
-
- // If "s" is the name of a variable of type VAR_FUNC
- // use its contents.
- s = deref_func_name((const char *)s, &len, &partial, !evaluate);
-
- // Need to make a copy, in case evaluating the arguments makes
- // the name invalid.
- s = xmemdupz(s, len);
-
- // Invoke the function.
- ret = get_func_tv(s, len, rettv, arg,
- curwin->w_cursor.lnum, curwin->w_cursor.lnum,
- &len, evaluate, partial, NULL);
-
- xfree(s);
-
- // If evaluate is false rettv->v_type was not set in
- // get_func_tv, but it's needed in handle_subscript() to parse
- // what follows. So set it here.
- if (rettv->v_type == VAR_UNKNOWN && !evaluate && **arg == '(') {
- rettv->vval.v_string = (char_u *)tv_empty_string;
- rettv->v_type = VAR_FUNC;
- }
-
- // Stop the expression evaluation when immediately
- // aborting on error, or when an interrupt occurred or
- // an exception was thrown but not caught.
- if (evaluate && aborting()) {
- if (ret == OK) {
- tv_clear(rettv);
- }
- ret = FAIL;
- }
+ ret = eval_func(arg, s, len, rettv, evaluate, NULL);
} else if (evaluate) {
ret = get_var_tv((const char *)s, len, rettv, NULL, true, false);
} else {
@@ -4019,53 +4053,232 @@ static int eval7(
*arg = skipwhite(*arg);
// Handle following '[', '(' and '.' for expr[expr], expr.name,
- // expr(expr).
+ // expr(expr), expr->name(expr)
if (ret == OK) {
- ret = handle_subscript((const char **)arg, rettv, evaluate, true);
+ ret = handle_subscript((const char **)arg, rettv, evaluate, true,
+ start_leader, &end_leader);
}
// Apply logical NOT and unary '-', from right to left, ignore '+'.
if (ret == OK && evaluate && end_leader > start_leader) {
- bool error = false;
- varnumber_T val = 0;
- float_T f = 0.0;
+ ret = eval7_leader(rettv, start_leader, &end_leader);
+ }
+ return ret;
+}
+/// Apply the leading "!" and "-" before an eval7 expression to "rettv".
+/// Adjusts "end_leaderp" until it is at "start_leader".
+/// @return OK on success, FAIL on failure.
+static int eval7_leader(typval_T *const rettv, const char_u *const start_leader,
+ const char_u **const end_leaderp)
+ FUNC_ATTR_NONNULL_ALL
+{
+ const char_u *end_leader = *end_leaderp;
+ int ret = OK;
+ bool error = false;
+ varnumber_T val = 0;
+ float_T f = 0.0;
+
+ if (rettv->v_type == VAR_FLOAT) {
+ f = rettv->vval.v_float;
+ } else {
+ val = tv_get_number_chk(rettv, &error);
+ }
+ if (error) {
+ tv_clear(rettv);
+ ret = FAIL;
+ } else {
+ while (end_leader > start_leader) {
+ end_leader--;
+ if (*end_leader == '!') {
+ if (rettv->v_type == VAR_FLOAT) {
+ f = !f;
+ } else {
+ val = !val;
+ }
+ } else if (*end_leader == '-') {
+ if (rettv->v_type == VAR_FLOAT) {
+ f = -f;
+ } else {
+ val = -val;
+ }
+ }
+ }
if (rettv->v_type == VAR_FLOAT) {
- f = rettv->vval.v_float;
+ tv_clear(rettv);
+ rettv->vval.v_float = f;
} else {
- val = tv_get_number_chk(rettv, &error);
- }
- if (error) {
tv_clear(rettv);
- ret = FAIL;
+ rettv->v_type = VAR_NUMBER;
+ rettv->vval.v_number = val;
+ }
+ }
+
+ *end_leaderp = end_leader;
+ return ret;
+}
+
+/// Call the function referred to in "rettv".
+/// @param lua_funcname If `rettv` refers to a v:lua function, this must point
+/// to the name of the Lua function to call (after the
+/// "v:lua." prefix).
+/// @return OK on success, FAIL on failure.
+static int call_func_rettv(char_u **const arg,
+ typval_T *const rettv,
+ const bool evaluate,
+ dict_T *const selfdict,
+ typval_T *const basetv,
+ const char_u *const lua_funcname)
+ FUNC_ATTR_NONNULL_ARG(1, 2)
+{
+ partial_T *pt = NULL;
+ typval_T functv;
+ const char_u *funcname;
+ bool is_lua = false;
+
+ // need to copy the funcref so that we can clear rettv
+ if (evaluate) {
+ functv = *rettv;
+ rettv->v_type = VAR_UNKNOWN;
+
+ // Invoke the function. Recursive!
+ if (functv.v_type == VAR_PARTIAL) {
+ pt = functv.vval.v_partial;
+ is_lua = is_luafunc(pt);
+ funcname = is_lua ? lua_funcname : partial_name(pt);
} else {
- while (end_leader > start_leader) {
- --end_leader;
- if (*end_leader == '!') {
- if (rettv->v_type == VAR_FLOAT) {
- f = !f;
- } else {
- val = !val;
- }
- } else if (*end_leader == '-') {
- if (rettv->v_type == VAR_FLOAT) {
- f = -f;
- } else {
- val = -val;
- }
- }
+ funcname = functv.vval.v_string;
+ }
+ } else {
+ funcname = (char_u *)"";
+ }
+
+ funcexe_T funcexe = FUNCEXE_INIT;
+ funcexe.firstline = curwin->w_cursor.lnum;
+ funcexe.lastline = curwin->w_cursor.lnum;
+ funcexe.evaluate = evaluate;
+ funcexe.partial = pt;
+ funcexe.selfdict = selfdict;
+ funcexe.basetv = basetv;
+ const int ret = get_func_tv(funcname, is_lua ? *arg - funcname : -1, rettv,
+ (char_u **)arg, &funcexe);
+
+ // Clear the funcref afterwards, so that deleting it while
+ // evaluating the arguments is possible (see test55).
+ if (evaluate) {
+ tv_clear(&functv);
+ }
+
+ return ret;
+}
+
+/// Evaluate "->method()".
+/// @param verbose if true, give error messages.
+/// @note "*arg" points to the '-'.
+/// @return FAIL or OK. @note "*arg" is advanced to after the ')'.
+static int eval_lambda(char_u **const arg, typval_T *const rettv,
+ const bool evaluate, const bool verbose)
+ FUNC_ATTR_NONNULL_ALL
+{
+ // Skip over the ->.
+ *arg += 2;
+ typval_T base = *rettv;
+ rettv->v_type = VAR_UNKNOWN;
+
+ int ret = get_lambda_tv(arg, rettv, evaluate);
+ if (ret == NOTDONE) {
+ return FAIL;
+ } else if (**arg != '(') {
+ if (verbose) {
+ if (*skipwhite(*arg) == '(') {
+ EMSG(_(e_nowhitespace));
+ } else {
+ EMSG2(_(e_missingparen), "lambda");
}
- if (rettv->v_type == VAR_FLOAT) {
- tv_clear(rettv);
- rettv->vval.v_float = f;
+ }
+ tv_clear(rettv);
+ ret = FAIL;
+ } else {
+ ret = call_func_rettv(arg, rettv, evaluate, NULL, &base, NULL);
+ }
+
+ // Clear the funcref afterwards, so that deleting it while
+ // evaluating the arguments is possible (see test55).
+ if (evaluate) {
+ tv_clear(&base);
+ }
+
+ return ret;
+}
+
+/// Evaluate "->method()" or "->v:lua.method()".
+/// @note "*arg" points to the '-'.
+/// @return FAIL or OK. "*arg" is advanced to after the ')'.
+static int eval_method(char_u **const arg, typval_T *const rettv,
+ const bool evaluate, const bool verbose)
+ FUNC_ATTR_NONNULL_ALL
+{
+ // Skip over the ->.
+ *arg += 2;
+ typval_T base = *rettv;
+ rettv->v_type = VAR_UNKNOWN;
+
+ // Locate the method name.
+ int len;
+ char_u *name = *arg;
+ char_u *lua_funcname = NULL;
+ if (STRNCMP(name, "v:lua.", 6) == 0) {
+ lua_funcname = name + 6;
+ *arg = (char_u *)skip_luafunc_name((const char *)lua_funcname);
+ *arg = skipwhite(*arg); // to detect trailing whitespace later
+ len = *arg - lua_funcname;
+ } else {
+ char_u *alias;
+ len = get_name_len((const char **)arg, (char **)&alias, evaluate, true);
+ if (alias != NULL) {
+ name = alias;
+ }
+ }
+
+ int ret;
+ if (len <= 0) {
+ if (verbose) {
+ if (lua_funcname == NULL) {
+ EMSG(_("E260: Missing name after ->"));
} else {
- tv_clear(rettv);
- rettv->v_type = VAR_NUMBER;
- rettv->vval.v_number = val;
+ EMSG2(_(e_invexpr2), name);
+ }
+ }
+ ret = FAIL;
+ } else {
+ if (**arg != '(') {
+ if (verbose) {
+ EMSG2(_(e_missingparen), name);
+ }
+ ret = FAIL;
+ } else if (ascii_iswhite((*arg)[-1])) {
+ if (verbose) {
+ EMSG(_(e_nowhitespace));
+ }
+ ret = FAIL;
+ } else if (lua_funcname != NULL) {
+ if (evaluate) {
+ rettv->v_type = VAR_PARTIAL;
+ rettv->vval.v_partial = vvlua_partial;
+ rettv->vval.v_partial->pt_refcount++;
}
+ ret = call_func_rettv(arg, rettv, evaluate, NULL, &base, lua_funcname);
+ } else {
+ ret = eval_func(arg, name, len, rettv, evaluate, &base);
}
}
+ // Clear the funcref afterwards, so that deleting it while
+ // evaluating the arguments is possible (see test55).
+ if (evaluate) {
+ tv_clear(&base);
+ }
+
return ret;
}
@@ -7255,10 +7468,12 @@ bool callback_call(Callback *const callback, const int argcount_in,
abort();
}
- int dummy;
- return call_func(name, -1, rettv, argcount_in, argvars_in,
- NULL, curwin->w_cursor.lnum, curwin->w_cursor.lnum, &dummy,
- true, partial, NULL);
+ funcexe_T funcexe = FUNCEXE_INIT;
+ funcexe.firstline = curwin->w_cursor.lnum;
+ funcexe.lastline = curwin->w_cursor.lnum;
+ funcexe.evaluate = true;
+ funcexe.partial = partial;
+ return call_func(name, -1, rettv, argcount_in, argvars_in, &funcexe);
}
static bool set_ref_in_callback(Callback *callback, int copyID,
@@ -8393,13 +8608,23 @@ static bool tv_is_luafunc(typval_T *tv)
return tv->v_type == VAR_PARTIAL && is_luafunc(tv->vval.v_partial);
}
-/// check the function name after "v:lua."
-int check_luafunc_name(const char *str, bool paren)
+/// Skips one character past the end of the name of a v:lua function.
+/// @param p Pointer to the char AFTER the "v:lua." prefix.
+/// @return Pointer to the char one past the end of the function's name.
+const char *skip_luafunc_name(const char *p)
+ FUNC_ATTR_NONNULL_ALL FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT
{
- const char *p = str;
while (ASCII_ISALNUM(*p) || *p == '_' || *p == '.' || *p == '\'') {
p++;
}
+ return p;
+}
+
+/// check the function name after "v:lua."
+int check_luafunc_name(const char *const str, const bool paren)
+ FUNC_ATTR_NONNULL_ALL FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT
+{
+ const char *const p = skip_luafunc_name(str);
if (*p != (paren ? '(' : NUL)) {
return 0;
} else {
@@ -8407,24 +8632,26 @@ int check_luafunc_name(const char *str, bool paren)
}
}
-/// Handle expr[expr], expr[expr:expr] subscript and .name lookup.
-/// Also handle function call with Funcref variable: func(expr)
-/// Can all be combined: dict.func(expr)[idx]['func'](expr)
+/// Handle:
+/// - expr[expr], expr[expr:expr] subscript
+/// - ".name" lookup
+/// - function call with Funcref variable: func(expr)
+/// - method call: var->method()
+///
+/// Can all be combined in any order: dict.func(expr)[idx]['func'](expr)->len()
int
handle_subscript(
const char **const arg,
typval_T *rettv,
- int evaluate, // do more than finding the end
- int verbose // give error messages
+ int evaluate, // do more than finding the end
+ int verbose, // give error messages
+ const char_u *const start_leader, // start of '!' and '-' prefixes
+ const char_u **const end_leaderp // end of '!' and '-' prefixes
)
{
int ret = OK;
- dict_T *selfdict = NULL;
- const char_u *s;
- int len;
- typval_T functv;
- int slen = 0;
- bool lua = false;
+ dict_T *selfdict = NULL;
+ const char_u *lua_funcname = NULL;
if (tv_is_luafunc(rettv)) {
if (**arg != '.') {
@@ -8433,55 +8660,28 @@ handle_subscript(
} else {
(*arg)++;
- lua = true;
- s = (char_u *)(*arg);
- slen = check_luafunc_name(*arg, true);
- if (slen == 0) {
+ lua_funcname = (char_u *)(*arg);
+ const int len = check_luafunc_name(*arg, true);
+ if (len == 0) {
tv_clear(rettv);
ret = FAIL;
}
- (*arg) += slen;
+ (*arg) += len;
}
}
-
while (ret == OK
- && (**arg == '['
- || (**arg == '.' && rettv->v_type == VAR_DICT)
- || (**arg == '(' && (!evaluate || tv_is_func(*rettv))))
- && !ascii_iswhite(*(*arg - 1))) {
+ && (((**arg == '[' || (**arg == '.' && rettv->v_type == VAR_DICT)
+ || (**arg == '(' && (!evaluate || tv_is_func(*rettv))))
+ && !ascii_iswhite(*(*arg - 1)))
+ || (**arg == '-' && (*arg)[1] == '>'))) {
if (**arg == '(') {
- partial_T *pt = NULL;
- // need to copy the funcref so that we can clear rettv
- if (evaluate) {
- functv = *rettv;
- rettv->v_type = VAR_UNKNOWN;
-
- // Invoke the function. Recursive!
- if (functv.v_type == VAR_PARTIAL) {
- pt = functv.vval.v_partial;
- if (!lua) {
- s = partial_name(pt);
- }
- } else {
- s = functv.vval.v_string;
- }
- } else {
- s = (char_u *)"";
- }
- ret = get_func_tv(s, lua ? slen : -1, rettv, (char_u **)arg,
- curwin->w_cursor.lnum, curwin->w_cursor.lnum,
- &len, evaluate, pt, selfdict);
-
- // Clear the funcref afterwards, so that deleting it while
- // evaluating the arguments is possible (see test55).
- if (evaluate) {
- tv_clear(&functv);
- }
+ ret = call_func_rettv((char_u **)arg, rettv, evaluate, selfdict, NULL,
+ lua_funcname);
- /* Stop the expression evaluation when immediately aborting on
- * error, or when an interrupt occurred or an exception was thrown
- * but not caught. */
+ // Stop the expression evaluation when immediately aborting on
+ // error, or when an interrupt occurred or an exception was thrown
+ // but not caught.
if (aborting()) {
if (ret == OK) {
tv_clear(rettv);
@@ -8490,6 +8690,21 @@ handle_subscript(
}
tv_dict_unref(selfdict);
selfdict = NULL;
+ } else if (**arg == '-') {
+ // Expression "-1.0->method()" applies the leader "-" before
+ // applying ->.
+ if (evaluate && *end_leaderp > start_leader) {
+ ret = eval7_leader(rettv, start_leader, end_leaderp);
+ }
+ if (ret == OK) {
+ if ((*arg)[2] == '{') {
+ // expr->{lambda}()
+ ret = eval_lambda((char_u **)arg, rettv, evaluate, verbose);
+ } else {
+ // expr->name()
+ ret = eval_method((char_u **)arg, rettv, evaluate, verbose);
+ }
+ }
} else { // **arg == '[' || **arg == '.'
tv_dict_unref(selfdict);
if (rettv->v_type == VAR_DICT) {
@@ -9274,6 +9489,7 @@ void ex_echo(exarg_T *eap)
bool atstart = true;
bool need_clear = true;
const int did_emsg_before = did_emsg;
+ const int called_emsg_before = called_emsg;
if (eap->skip)
++emsg_skip;
@@ -9288,7 +9504,8 @@ void ex_echo(exarg_T *eap)
// Report the invalid expression unless the expression evaluation
// has been cancelled due to an aborting error, an interrupt, or an
// exception.
- if (!aborting() && did_emsg == did_emsg_before) {
+ if (!aborting() && did_emsg == did_emsg_before
+ && called_emsg == called_emsg_before) {
EMSG2(_(e_invexpr2), p);
}
need_clr_eos = false;
@@ -10409,19 +10626,11 @@ typval_T eval_call_provider(char *provider, char *method, list_T *arguments,
typval_T rettv = { .v_type = VAR_UNKNOWN, .v_lock = VAR_UNLOCKED };
tv_list_ref(arguments);
- int dummy;
- (void)call_func((const char_u *)func,
- name_len,
- &rettv,
- 2,
- argvars,
- NULL,
- curwin->w_cursor.lnum,
- curwin->w_cursor.lnum,
- &dummy,
- true,
- NULL,
- NULL);
+ funcexe_T funcexe = FUNCEXE_INIT;
+ funcexe.firstline = curwin->w_cursor.lnum;
+ funcexe.lastline = curwin->w_cursor.lnum;
+ funcexe.evaluate = true;
+ (void)call_func((const char_u *)func, name_len, &rettv, 2, argvars, &funcexe);
tv_list_unref(arguments);
// Restore caller scope information
@@ -10779,7 +10988,9 @@ bool var_exists(const char *var)
n = get_var_tv(name, len, &tv, NULL, false, true) == OK;
if (n) {
// Handle d.key, l[idx], f(expr).
- n = handle_subscript(&var, &tv, true, false) == OK;
+ n = handle_subscript(&var, &tv, true, false, (const char_u *)name,
+ (const char_u **)&name)
+ == OK;
if (n) {
tv_clear(&tv);
}
diff --git a/src/nvim/eval.lua b/src/nvim/eval.lua
index eb20cd1bc8..faff29b268 100644
--- a/src/nvim/eval.lua
+++ b/src/nvim/eval.lua
@@ -5,6 +5,9 @@
-- args Number of arguments, list with maximum and minimum number of arguments
-- or list with a minimum number of arguments only. Defaults to zero
-- arguments.
+-- base For methods: the argument to use as the base argument (1-indexed):
+-- base->method()
+-- Defaults to BASE_NONE (function cannot be used as a method).
-- func Name of the C function which implements the VimL function. Defaults to
-- `f_{funcname}`.
@@ -12,111 +15,115 @@ local varargs = function(nr)
return {nr}
end
+-- Usable with the base key: use the last function argument as the method base.
+-- Value is from funcs.h file. "BASE_" prefix is omitted.
+local LAST = "BASE_LAST"
+
return {
funcs={
- abs={args=1},
- acos={args=1, func="float_op_wrapper", data="&acos"}, -- WJMc
- add={args=2},
- ['and']={args=2},
+ abs={args=1, base=1},
+ acos={args=1, base=1, func="float_op_wrapper", data="&acos"}, -- WJMc
+ add={args=2, base=1},
+ ['and']={args=2, base=1},
api_info={},
- append={args=2},
- appendbufline={args=3},
+ append={args=2, base=LAST},
+ appendbufline={args=3, base=LAST},
argc={args={0, 1}},
argidx={},
arglistid={args={0, 2}},
argv={args={0, 2}},
- asin={args=1, func="float_op_wrapper", data="&asin"}, -- WJMc
- assert_beeps={args={1}},
- assert_equal={args={2, 3}},
- assert_equalfile={args={2, 3}},
+ asin={args=1, base=1, func="float_op_wrapper", data="&asin"}, -- WJMc
+ assert_beeps={args={1}, base=1},
+ assert_equal={args={2, 3}, base=2},
+ assert_equalfile={args={2, 3}, base=1},
assert_exception={args={1, 2}},
- assert_fails={args={1, 3}},
- assert_false={args={1, 2}},
- assert_inrange={args={3, 4}},
- assert_match={args={2, 3}},
+ assert_fails={args={1, 3}, base=1},
+ assert_false={args={1, 2}, base=1},
+ assert_inrange={args={3, 4}, base=3},
+ assert_match={args={2, 3}, base=2},
assert_nobeep={args={1}},
- assert_notequal={args={2, 3}},
- assert_notmatch={args={2, 3}},
- assert_report={args=1},
- assert_true={args={1, 2}},
- atan={args=1, func="float_op_wrapper", data="&atan"},
- atan2={args=2},
+ assert_notequal={args={2, 3}, base=2},
+ assert_notmatch={args={2, 3}, base=2},
+ assert_report={args=1, base=1},
+ assert_true={args={1, 2}, base=1},
+ atan={args=1, base=1, func="float_op_wrapper", data="&atan"},
+ atan2={args=2, base=1},
browse={args=4},
browsedir={args=2},
- bufadd={args=1},
- bufexists={args=1},
- buffer_exists={args=1, func='f_bufexists'}, -- obsolete
+ bufadd={args=1, base=1},
+ bufexists={args=1, base=1},
+ buffer_exists={args=1, base=1, func='f_bufexists'}, -- obsolete
buffer_name={args={0, 1}, func='f_bufname'}, -- obsolete
buffer_number={args={0, 1}, func='f_bufnr'}, -- obsolete
- buflisted={args=1},
- bufload={args=1},
- bufloaded={args=1},
- bufname={args={0, 1}},
- bufnr={args={0, 2}},
- bufwinid={args=1},
- bufwinnr={args=1},
- byte2line={args=1},
- byteidx={args=2},
- byteidxcomp={args=2},
- call={args={2, 3}},
- ceil={args=1, func="float_op_wrapper", data="&ceil"},
+ buflisted={args=1, base=1},
+ bufload={args=1, base=1},
+ bufloaded={args=1, base=1},
+ bufname={args={0, 1}, base=1},
+ bufnr={args={0, 2}, base=1},
+ bufwinid={args=1, base=1},
+ bufwinnr={args=1, base=1},
+ byte2line={args=1, base=1},
+ byteidx={args=2, base=1},
+ byteidxcomp={args=2, base=1},
+ call={args={2, 3}, base=1},
+ ceil={args=1, base=1, func="float_op_wrapper", data="&ceil"},
changenr={},
chanclose={args={1, 2}},
chansend={args=2},
- char2nr={args={1, 2}},
+ char2nr={args={1, 2}, base=1},
charidx={args={2, 3}},
- cindent={args=1},
- clearmatches={args={0, 1}},
- col={args=1},
- complete={args=2},
- complete_add={args=1},
+ cindent={args=1, base=1},
+ clearmatches={args={0, 1}, base=1},
+ col={args=1, base=1},
+ complete={args=2, base=2},
+ complete_add={args=1, base=1},
complete_check={},
- complete_info={args={0, 1}},
- confirm={args={1, 4}},
- copy={args=1},
- cos={args=1, func="float_op_wrapper", data="&cos"},
- cosh={args=1, func="float_op_wrapper", data="&cosh"},
- count={args={2, 4}},
+ complete_info={args={0, 1}, base=1},
+ confirm={args={1, 4}, base=1},
+ copy={args=1, base=1},
+ cos={args=1, base=1, func="float_op_wrapper", data="&cos"},
+ cosh={args=1, base=1, func="float_op_wrapper", data="&cosh"},
+ count={args={2, 4}, base=1},
cscope_connection={args={0, 3}},
ctxget={args={0, 1}},
ctxpop={},
ctxpush={args={0, 1}},
ctxset={args={1, 2}},
ctxsize={},
- cursor={args={1, 3}},
- debugbreak={args={1, 1}},
- deepcopy={args={1, 2}},
- delete={args={1,2}},
- deletebufline={args={2,3}},
+ cursor={args={1, 3}, base=1},
+ debugbreak={args={1, 1}, base=1},
+ deepcopy={args={1, 2}, base=1},
+ delete={args={1,2}, base=1},
+ deletebufline={args={2,3}, base=1},
dictwatcheradd={args=3},
dictwatcherdel={args=3},
did_filetype={},
- diff_filler={args=1},
- diff_hlID={args=2},
- empty={args=1},
+ diff_filler={args=1, base=1},
+ diff_hlID={args=2, base=1},
+ empty={args=1, base=1},
environ={},
escape={args=2},
- eval={args=1},
+ eval={args=1, base=1},
eventhandler={},
executable={args=1},
execute={args={1, 2}},
exepath={args=1},
exists={args=1},
- exp={args=1, func="float_op_wrapper", data="&exp"},
+ exp={args=1, base=1, func="float_op_wrapper", data="&exp"},
expand={args={1, 3}},
expandcmd={args=1},
- extend={args={2, 3}},
+ extend={args={2, 3}, base=1},
feedkeys={args={1, 2}},
file_readable={args=1, func='f_filereadable'}, -- obsolete
filereadable={args=1},
filewritable={args=1},
- filter={args=2},
+ filter={args=2, base=1},
finddir={args={1, 3}},
findfile={args={1, 3}},
flatten={args={1, 2}},
- float2nr={args=1},
- floor={args=1, func="float_op_wrapper", data="&floor"},
- fmod={args=2},
+ float2nr={args=1, base=1},
+ floor={args=1, base=1, func="float_op_wrapper", data="&floor"},
+ fmod={args=2, base=1},
fnameescape={args=1},
fnamemodify={args=2},
foldclosed={args=1},
@@ -128,7 +135,7 @@ return {
funcref={args={1, 3}},
['function']={args={1, 3}},
garbagecollect={args={0, 1}},
- get={args={2, 3}},
+ get={args={2, 3}, base=1},
getbufinfo={args={0, 1}},
getbufline={args={2, 3}},
getbufvar={args={2, 3}},
@@ -173,7 +180,7 @@ return {
glob2regpat={args=1},
globpath={args={2, 5}},
has={args=1},
- has_key={args=2},
+ has_key={args=2, base=1},
haslocaldir={args={0,2}},
hasmapto={args={1, 3}},
highlightID={args=1, func='f_hlID'}, -- obsolete
@@ -187,22 +194,22 @@ return {
hostname={},
iconv={args=3},
indent={args=1},
- index={args={2, 4}},
+ index={args={2, 4}, base=1},
input={args={1, 3}},
inputdialog={args={1, 3}},
inputlist={args=1},
inputrestore={},
inputsave={},
inputsecret={args={1, 2}},
- insert={args={2, 3}},
+ insert={args={2, 3}, base=1},
interrupt={args=0},
- invert={args=1},
+ invert={args=1, base=1},
isdirectory={args=1},
- isinf={args=1},
+ isinf={args=1, base=1},
islocked={args=1},
- isnan={args=1},
+ isnan={args=1, base=1},
id={args=1},
- items={args=1},
+ items={args=1, base=1},
jobclose={args={1, 2}, func="f_chanclose"},
jobpid={args=1},
jobresize={args=3},
@@ -210,12 +217,12 @@ return {
jobstart={args={1, 2}},
jobstop={args=1},
jobwait={args={1, 2}},
- join={args={1, 2}},
+ join={args={1, 2}, base=1},
json_decode={args=1},
json_encode={args=1},
- keys={args=1},
+ keys={args=1, base=1},
last_buffer_nr={}, -- obsolete
- len={args=1},
+ len={args=1, base=1},
libcall={args=3},
libcallnr={args=3},
line={args={1, 2}},
@@ -223,10 +230,10 @@ return {
lispindent={args=1},
list2str={args={1, 2}},
localtime={},
- log={args=1, func="float_op_wrapper", data="&log"},
- log10={args=1, func="float_op_wrapper", data="&log10"},
+ log={args=1, base=1, func="float_op_wrapper", data="&log"},
+ log10={args=1, base=1, func="float_op_wrapper", data="&log10"},
luaeval={args={1, 2}},
- map={args=2},
+ map={args=2, base=1},
maparg={args={1, 4}},
mapcheck={args={1, 3}},
match={args={2, 4}},
@@ -238,20 +245,20 @@ return {
matchlist={args={2, 4}},
matchstr={args={2, 4}},
matchstrpos={args={2,4}},
- max={args=1},
+ max={args=1, base=1},
menu_get={args={1, 2}},
- min={args=1},
+ min={args=1, base=1},
mkdir={args={1, 3}},
mode={args={0, 1}},
msgpackdump={args=1},
msgpackparse={args=1},
nextnonblank={args=1},
nr2char={args={1, 2}},
- ['or']={args=2},
+ ['or']={args=2, base=1},
pathshorten={args=1},
- pow={args=2},
+ pow={args=2, base=1},
prevnonblank={args=1},
- printf={args=varargs(1)},
+ printf={args=varargs(1), base=2},
prompt_getprompt={args=1},
prompt_setcallback={args={2, 2}},
prompt_setinterrupt={args={2, 2}},
@@ -270,12 +277,12 @@ return {
reltime={args={0, 2}},
reltimefloat={args=1},
reltimestr={args=1},
- remove={args={2, 3}},
+ remove={args={2, 3}, base=1},
rename={args=2},
- ['repeat']={args=2},
+ ['repeat']={args=2, base=1},
resolve={args=1},
- reverse={args=1},
- round={args=1, func="float_op_wrapper", data="&round"},
+ reverse={args=1, base=1},
+ round={args=1, base=1, func="float_op_wrapper", data="&round"},
rpcnotify={args=varargs(2)},
rpcrequest={args=varargs(2)},
rpcstart={args={1, 2}},
@@ -324,19 +331,19 @@ return {
sign_unplace={args={1, 2}},
sign_unplacelist={args={1}},
simplify={args=1},
- sin={args=1, func="float_op_wrapper", data="&sin"},
- sinh={args=1, func="float_op_wrapper", data="&sinh"},
+ sin={args=1, base=1, func="float_op_wrapper", data="&sin"},
+ sinh={args=1, base=1, func="float_op_wrapper", data="&sinh"},
sockconnect={args={2,3}},
- sort={args={1, 3}},
+ sort={args={1, 3}, base=1},
soundfold={args=1},
stdioopen={args=1},
spellbadword={args={0, 1}},
spellsuggest={args={1, 3}},
- split={args={1, 3}},
- sqrt={args=1, func="float_op_wrapper", data="&sqrt"},
+ split={args={1, 3}, base=1},
+ sqrt={args=1, base=1, func="float_op_wrapper", data="&sqrt"},
stdpath={args=1},
- str2float={args=1},
- str2list={args={1, 2}},
+ str2float={args=1, base=1},
+ str2list={args={1, 2}, base=1},
str2nr={args={1, 2}},
strcharpart={args={2, 3}},
strchars={args={1,2}},
@@ -344,31 +351,31 @@ return {
strftime={args={1, 2}},
strgetchar={args={2, 2}},
stridx={args={2, 3}},
- string={args=1},
- strlen={args=1},
+ string={args=1, base=1},
+ strlen={args=1, base=1},
strpart={args={2, 4}},
strptime={args=2},
strridx={args={2, 3}},
- strtrans={args=1},
- strwidth={args=1},
+ strtrans={args=1, base=1},
+ strwidth={args=1, base=1},
submatch={args={1, 2}},
- substitute={args=4},
+ substitute={args=4, base=1},
swapinfo={args={1}},
swapname={args={1}},
synID={args=3},
- synIDattr={args={2, 3}},
- synIDtrans={args=1},
+ synIDattr={args={2, 3}, base=1},
+ synIDtrans={args=1, base=1},
synconcealed={args=2},
synstack={args=2},
- system={args={1, 2}},
- systemlist={args={1, 3}},
+ system={args={1, 2}, base=1},
+ systemlist={args={1, 3}, base=1},
tabpagebuflist={args={0, 1}},
tabpagenr={args={0, 1}},
tabpagewinnr={args={1, 2}},
tagfiles={},
taglist={args={1, 2}},
- tan={args=1, func="float_op_wrapper", data="&tan"},
- tanh={args=1, func="float_op_wrapper", data="&tanh"},
+ tan={args=1, base=1, func="float_op_wrapper", data="&tan"},
+ tanh={args=1, base=1, func="float_op_wrapper", data="&tanh"},
tempname={},
termopen={args={1, 2}},
test_garbagecollect_now={},
@@ -382,12 +389,12 @@ return {
toupper={args=1},
tr={args=3},
trim={args={1,3}},
- trunc={args=1, func="float_op_wrapper", data="&trunc"},
- type={args=1},
+ trunc={args=1, base=1, func="float_op_wrapper", data="&trunc"},
+ type={args=1, base=1},
undofile={args=1},
undotree={},
- uniq={args={1, 3}},
- values={args=1},
+ uniq={args={1, 3}, base=1},
+ values={args=1, base=1},
virtcol={args=1},
visualmode={args={0, 1}},
wait={args={2,3}},
@@ -401,7 +408,7 @@ return {
win_id2win={args=1},
win_screenpos={args=1},
win_splitmove={args={2, 3}},
- winbufnr={args=1},
+ winbufnr={args=1, base=1},
wincol={},
windowsversion={},
winheight={args=1},
@@ -414,6 +421,6 @@ return {
winwidth={args=1},
wordcount={},
writefile={args={2, 3}},
- xor={args=2},
+ xor={args=2, base=1},
},
}
diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c
index 4e409cca50..99f9f17e0a 100644
--- a/src/nvim/eval/funcs.c
+++ b/src/nvim/eval/funcs.c
@@ -175,6 +175,53 @@ const VimLFuncDef *find_internal_func(const char *const name)
return find_internal_func_gperf(name, len);
}
+int call_internal_func(const char_u *const fname, const int argcount,
+ typval_T *const argvars, typval_T *const rettv)
+ FUNC_ATTR_NONNULL_ALL
+{
+ const VimLFuncDef *const fdef = find_internal_func((const char *)fname);
+ if (fdef == NULL) {
+ return ERROR_UNKNOWN;
+ } else if (argcount < fdef->min_argc) {
+ return ERROR_TOOFEW;
+ } else if (argcount > fdef->max_argc) {
+ return ERROR_TOOMANY;
+ }
+ argvars[argcount].v_type = VAR_UNKNOWN;
+ fdef->func(argvars, rettv, fdef->data);
+ return ERROR_NONE;
+}
+
+/// Invoke a method for base->method().
+int call_internal_method(const char_u *const fname, const int argcount,
+ typval_T *const argvars, typval_T *const rettv,
+ typval_T *const basetv)
+ FUNC_ATTR_NONNULL_ALL
+{
+ const VimLFuncDef *const fdef = find_internal_func((const char *)fname);
+ if (fdef == NULL) {
+ return ERROR_UNKNOWN;
+ } else if (fdef->base_arg == BASE_NONE) {
+ return ERROR_NOTMETHOD;
+ } else if (argcount + 1 < fdef->min_argc) {
+ return ERROR_TOOFEW;
+ } else if (argcount + 1 > fdef->max_argc) {
+ return ERROR_TOOMANY;
+ }
+
+ typval_T argv[MAX_FUNC_ARGS + 1];
+ const ptrdiff_t base_index
+ = fdef->base_arg == BASE_LAST ? argcount : fdef->base_arg - 1;
+ memcpy(argv, argvars, base_index * sizeof(typval_T));
+ argv[base_index] = *basetv;
+ memcpy(argv + base_index + 1, argvars + base_index,
+ (argcount - base_index) * sizeof(typval_T));
+ argv[argcount + 1].v_type = VAR_UNKNOWN;
+
+ fdef->func(argv, rettv, fdef->data);
+ return ERROR_NONE;
+}
+
/*
* Return TRUE for a non-zero Number and a non-empty String.
*/
@@ -5357,14 +5404,19 @@ static void f_jobwait(typval_T *argvars, typval_T *rettv, FunPtr fptr)
TV_LIST_ITER_CONST(args, arg, {
Channel *chan = NULL;
if (TV_LIST_ITEM_TV(arg)->v_type != VAR_NUMBER
- || !(chan = find_job(TV_LIST_ITEM_TV(arg)->vval.v_number, false))) {
+ || !(chan = find_channel(TV_LIST_ITEM_TV(arg)->vval.v_number))
+ || chan->streamtype != kChannelStreamProc) {
+ jobs[i] = NULL; // Invalid job.
+ } else if (process_is_stopped(&chan->stream.proc)) {
+ // Job is stopped but not fully destroyed.
+ // Ensure all callbacks on its event queue are executed. #15402
+ process_wait(&chan->stream.proc, -1, NULL);
jobs[i] = NULL; // Invalid job.
} else {
jobs[i] = chan;
channel_incref(chan);
if (chan->stream.proc.status < 0) {
- // Process any pending events on the job's queue before temporarily
- // replacing it.
+ // Flush any events in the job's queue before temporarily replacing it.
multiqueue_process_events(chan->events);
multiqueue_replace_parent(chan->events, waiting_jobs);
}
@@ -9420,7 +9472,6 @@ static int item_compare2(const void *s1, const void *s2, bool keep_zero)
int res;
typval_T rettv;
typval_T argv[3];
- int dummy;
const char *func_name;
partial_T *partial = sortinfo->item_compare_partial;
@@ -9444,10 +9495,11 @@ static int item_compare2(const void *s1, const void *s2, bool keep_zero)
tv_copy(TV_LIST_ITEM_TV(si2->item), &argv[1]);
rettv.v_type = VAR_UNKNOWN; // tv_clear() uses this
- res = call_func((const char_u *)func_name,
- -1,
- &rettv, 2, argv, NULL, 0L, 0L, &dummy, true,
- partial, sortinfo->item_compare_selfdict);
+ funcexe_T funcexe = FUNCEXE_INIT;
+ funcexe.evaluate = true;
+ funcexe.partial = partial;
+ funcexe.selfdict = sortinfo->item_compare_selfdict;
+ res = call_func((const char_u *)func_name, -1, &rettv, 2, argv, &funcexe);
tv_clear(&argv[0]);
tv_clear(&argv[1]);
diff --git a/src/nvim/eval/funcs.h b/src/nvim/eval/funcs.h
index a343290734..c6a0cb959e 100644
--- a/src/nvim/eval/funcs.h
+++ b/src/nvim/eval/funcs.h
@@ -9,11 +9,16 @@ typedef void (*FunPtr)(void);
/// Prototype of C function that implements VimL function
typedef void (*VimLFunc)(typval_T *args, typval_T *rvar, FunPtr data);
+/// Special flags for base_arg @see VimLFuncDef
+#define BASE_NONE 0 ///< Not a method (no base argument).
+#define BASE_LAST UINT8_MAX ///< Use the last argument as the method base.
+
/// Structure holding VimL function definition
typedef struct fst {
char *name; ///< Name of the function.
uint8_t min_argc; ///< Minimal number of arguments.
uint8_t max_argc; ///< Maximal number of arguments.
+ uint8_t base_arg; ///< Method base arg # (1-indexed), BASE_NONE or BASE_LAST.
VimLFunc func; ///< Function implementation.
FunPtr data; ///< Userdata for function implementation.
} VimLFuncDef;
diff --git a/src/nvim/eval/userfunc.c b/src/nvim/eval/userfunc.c
index deddec413b..4184e4d922 100644
--- a/src/nvim/eval/userfunc.c
+++ b/src/nvim/eval/userfunc.c
@@ -414,12 +414,7 @@ get_func_tv(
int len, // length of "name" or -1 to use strlen()
typval_T *rettv,
char_u **arg, // argument, pointing to the '('
- linenr_T firstline, // first line of range
- linenr_T lastline, // last line of range
- int *doesrange, // return: function handled range
- int evaluate,
- partial_T *partial, // for extra arguments
- dict_T *selfdict // Dictionary for "self"
+ funcexe_T *funcexe // various values
)
{
char_u *argp;
@@ -431,12 +426,13 @@ get_func_tv(
* Get the arguments.
*/
argp = *arg;
- while (argcount < MAX_FUNC_ARGS - (partial == NULL ? 0 : partial->pt_argc)) {
+ while (argcount < MAX_FUNC_ARGS
+ - (funcexe->partial == NULL ? 0 : funcexe->partial->pt_argc)) {
argp = skipwhite(argp + 1); // skip the '(' or ','
if (*argp == ')' || *argp == ',' || *argp == NUL) {
break;
}
- if (eval1(&argp, &argvars[argcount], evaluate) == FAIL) {
+ if (eval1(&argp, &argvars[argcount], funcexe->evaluate) == FAIL) {
ret = FAIL;
break;
}
@@ -463,9 +459,7 @@ get_func_tv(
((typval_T **)funcargs.ga_data)[funcargs.ga_len++] = &argvars[i];
}
}
- ret = call_func(name, len, rettv, argcount, argvars, NULL,
- firstline, lastline, doesrange, evaluate,
- partial, selfdict);
+ ret = call_func(name, len, rettv, argcount, argvars, funcexe);
funcargs.ga_len -= i;
} else if (!aborting()) {
@@ -1367,7 +1361,6 @@ int func_call(char_u *name, typval_T *args, partial_T *partial,
{
typval_T argv[MAX_FUNC_ARGS + 1];
int argc = 0;
- int dummy;
int r = 0;
TV_LIST_ITER(args->vval.v_list, item, {
@@ -1380,9 +1373,13 @@ int func_call(char_u *name, typval_T *args, partial_T *partial,
tv_copy(TV_LIST_ITEM_TV(item), &argv[argc++]);
});
- r = call_func(name, -1, rettv, argc, argv, NULL,
- curwin->w_cursor.lnum, curwin->w_cursor.lnum,
- &dummy, true, partial, selfdict);
+ funcexe_T funcexe = FUNCEXE_INIT;
+ funcexe.firstline = curwin->w_cursor.lnum;
+ funcexe.lastline = curwin->w_cursor.lnum;
+ funcexe.evaluate = true;
+ funcexe.partial = partial;
+ funcexe.selfdict = selfdict;
+ r = call_func(name, -1, rettv, argc, argv, &funcexe);
func_call_skip_call:
// Free the arguments.
@@ -1402,6 +1399,9 @@ static void user_func_error(int error, const char_u *name)
case ERROR_UNKNOWN:
emsg_funcname(N_("E117: Unknown function: %s"), name);
break;
+ case ERROR_NOTMETHOD:
+ emsg_funcname(N_("E276: Cannot use function as a method: %s"), name);
+ break;
case ERROR_DELETED:
emsg_funcname(N_("E933: Function was deleted: %s"), name);
break;
@@ -1423,12 +1423,25 @@ static void user_func_error(int error, const char_u *name)
}
}
+/// Used by call_func to add a method base (if any) to a function argument list
+/// as the first argument. @see call_func
+static void argv_add_base(typval_T *const basetv, typval_T **const argvars,
+ int *const argcount, typval_T *const new_argvars,
+ int *const argv_base)
+ FUNC_ATTR_NONNULL_ARG(2, 3, 4, 5)
+{
+ if (basetv != NULL) {
+ // Method call: base->Method()
+ memmove(&new_argvars[1], *argvars, sizeof(typval_T) * (*argcount));
+ new_argvars[0] = *basetv;
+ (*argcount)++;
+ *argvars = new_argvars;
+ *argv_base = 1;
+ }
+}
+
/// Call a function with its resolved parameters
///
-/// "argv_func", when not NULL, can be used to fill in arguments only when the
-/// invoked function uses them. It is called like this:
-/// new_argcount = argv_func(current_argcount, argv, called_func_argcount)
-///
/// @return FAIL if function cannot be called, else OK (even if an error
/// occurred while executing the function! Set `msg_list` to capture
/// the error, see do_cmdline()).
@@ -1440,15 +1453,9 @@ call_func(
int argcount_in, // number of "argvars"
typval_T *argvars_in, // vars for arguments, must have "argcount"
// PLUS ONE elements!
- ArgvFunc argv_func, // function to fill in argvars
- linenr_T firstline, // first line of range
- linenr_T lastline, // last line of range
- int *doesrange, // [out] function handled range
- bool evaluate,
- partial_T *partial, // optional, can be NULL
- dict_T *selfdict_in // Dictionary for "self"
+ funcexe_T *funcexe // more arguments
)
- FUNC_ATTR_NONNULL_ARG(1, 3, 5, 9)
+ FUNC_ATTR_NONNULL_ARG(1, 3, 5, 6)
{
int ret = FAIL;
int error = ERROR_NONE;
@@ -1459,9 +1466,12 @@ call_func(
char_u *name = NULL;
int argcount = argcount_in;
typval_T *argvars = argvars_in;
- dict_T *selfdict = selfdict_in;
- typval_T argv[MAX_FUNC_ARGS + 1]; // used when "partial" is not NULL
+ dict_T *selfdict = funcexe->selfdict;
+ typval_T argv[MAX_FUNC_ARGS + 1]; // used when "partial" or
+ // "funcexe->basetv" is not NULL
int argv_clear = 0;
+ int argv_base = 0;
+ partial_T *partial = funcexe->partial;
// Initialize rettv so that it is safe for caller to invoke clear_tv(rettv)
// even when call_func() returns FAIL.
@@ -1480,14 +1490,15 @@ call_func(
fname = fname_trans_sid(name, fname_buf, &tofree, &error);
}
- *doesrange = false;
+ if (funcexe->doesrange != NULL) {
+ *funcexe->doesrange = false;
+ }
if (partial != NULL) {
// When the function has a partial with a dict and there is a dict
// argument, use the dict argument. That is backwards compatible.
// When the dict was bound explicitly use the one from the partial.
- if (partial->pt_dict != NULL
- && (selfdict_in == NULL || !partial->pt_auto)) {
+ if (partial->pt_dict != NULL && (selfdict == NULL || !partial->pt_auto)) {
selfdict = partial->pt_dict;
}
if (error == ERROR_NONE && partial->pt_argc > 0) {
@@ -1506,7 +1517,7 @@ call_func(
}
}
- if (error == ERROR_NONE && evaluate) {
+ if (error == ERROR_NONE && funcexe->evaluate) {
char_u *rfname = fname;
// Ignore "g:" before a function name.
@@ -1521,7 +1532,12 @@ call_func(
if (is_luafunc(partial)) {
if (len > 0) {
error = ERROR_NONE;
+ argv_add_base(funcexe->basetv, &argvars, &argcount, argv, &argv_base);
nlua_typval_call((const char *)funcname, len, argvars, argcount, rettv);
+ } else {
+ // v:lua was called directly; show its name in the emsg
+ XFREE_CLEAR(name);
+ funcname = (const char_u *)"v:lua";
}
} else if (fp != NULL || !builtin_function((const char *)rfname, -1)) {
// User defined function.
@@ -1549,13 +1565,16 @@ call_func(
cfunc_T cb = fp->uf_cb;
error = (*cb)(argcount, argvars, rettv, fp->uf_cb_state);
} else if (fp != NULL) {
- if (argv_func != NULL) {
+ if (funcexe->argv_func != NULL) {
// postponed filling in the arguments, do it now
- argcount = argv_func(argcount, argvars, argv_clear,
- fp->uf_args.ga_len);
+ argcount = funcexe->argv_func(argcount, argvars, argv_clear,
+ fp->uf_args.ga_len);
}
- if (fp->uf_flags & FC_RANGE) {
- *doesrange = true;
+
+ argv_add_base(funcexe->basetv, &argvars, &argcount, argv, &argv_base);
+
+ if (fp->uf_flags & FC_RANGE && funcexe->doesrange != NULL) {
+ *funcexe->doesrange = true;
}
if (argcount < fp->uf_args.ga_len - fp->uf_def_args.ga_len) {
error = ERROR_TOOFEW;
@@ -1565,25 +1584,20 @@ call_func(
error = ERROR_DICT;
} else {
// Call the user function.
- call_user_func(fp, argcount, argvars, rettv, firstline, lastline,
+ call_user_func(fp, argcount, argvars, rettv, funcexe->firstline,
+ funcexe->lastline,
(fp->uf_flags & FC_DICT) ? selfdict : NULL);
error = ERROR_NONE;
}
}
+ } else if (funcexe->basetv != NULL) {
+ // expr->method(): Find the method name in the table, call its
+ // implementation with the base as one of the arguments.
+ error = call_internal_method(fname, argcount, argvars, rettv,
+ funcexe->basetv);
} else {
// Find the function name in the table, call its implementation.
- const VimLFuncDef *const fdef = find_internal_func((const char *)fname);
- if (fdef != NULL) {
- if (argcount < fdef->min_argc) {
- error = ERROR_TOOFEW;
- } else if (argcount > fdef->max_argc) {
- error = ERROR_TOOMANY;
- } else {
- argvars[argcount].v_type = VAR_UNKNOWN;
- fdef->func(argvars, rettv, fdef->data);
- error = ERROR_NONE;
- }
- }
+ error = call_internal_func(fname, argcount, argvars, rettv);
}
/*
* The function call (or "FuncUndefined" autocommand sequence) might
@@ -1607,9 +1621,11 @@ theend:
user_func_error(error, (name != NULL) ? name : funcname);
}
+ // clear the copies made from the partial
while (argv_clear > 0) {
- tv_clear(&argv[--argv_clear]);
+ tv_clear(&argv[--argv_clear + argv_base]);
}
+
xfree(tofree);
xfree(name);
@@ -2901,7 +2917,7 @@ void ex_call(exarg_T *eap)
int len;
typval_T rettv;
linenr_T lnum;
- int doesrange;
+ bool doesrange;
bool failed = false;
funcdict_T fudi;
partial_T *partial = NULL;
@@ -2947,7 +2963,7 @@ void ex_call(exarg_T *eap)
rettv.v_type = VAR_UNKNOWN; // tv_clear() uses this.
if (*startarg != '(') {
- EMSG2(_("E107: Missing parentheses: %s"), eap->arg);
+ EMSG2(_(e_missingparen), eap->arg);
goto end;
}
@@ -2965,15 +2981,22 @@ void ex_call(exarg_T *eap)
curwin->w_cursor.coladd = 0;
}
arg = startarg;
- if (get_func_tv(name, -1, &rettv, &arg,
- eap->line1, eap->line2, &doesrange,
- true, partial, fudi.fd_dict) == FAIL) {
+
+ funcexe_T funcexe = FUNCEXE_INIT;
+ funcexe.firstline = eap->line1;
+ funcexe.lastline = eap->line2;
+ funcexe.doesrange = &doesrange;
+ funcexe.evaluate = true;
+ funcexe.partial = partial;
+ funcexe.selfdict = fudi.fd_dict;
+ if (get_func_tv(name, -1, &rettv, &arg, &funcexe) == FAIL) {
failed = true;
break;
}
// Handle a function returning a Funcref, Dictionary or List.
- if (handle_subscript((const char **)&arg, &rettv, true, true)
+ if (handle_subscript((const char **)&arg, &rettv, true, true,
+ (const char_u *)name, (const char_u **)&name)
== FAIL) {
failed = true;
break;
diff --git a/src/nvim/eval/userfunc.h b/src/nvim/eval/userfunc.h
index e8ad0bf1da..3f111343d2 100644
--- a/src/nvim/eval/userfunc.h
+++ b/src/nvim/eval/userfunc.h
@@ -28,11 +28,37 @@ typedef enum {
ERROR_OTHER,
ERROR_BOTH,
ERROR_DELETED,
+ ERROR_NOTMETHOD,
} FnameTransError;
+/// Used in funcexe_T. Returns the new argcount.
typedef int (*ArgvFunc)(int current_argcount, typval_T *argv, int argskip,
int called_func_argcount);
+/// Structure passed between functions dealing with function call execution.
+typedef struct {
+ ArgvFunc argv_func; ///< when not NULL, can be used to fill in arguments only
+ ///< when the invoked function uses them
+ linenr_T firstline; ///< first line of range
+ linenr_T lastline; ///< last line of range
+ bool *doesrange; ///< [out] if not NULL: function handled range
+ bool evaluate; ///< actually evaluate expressions
+ partial_T *partial; ///< for extra arguments
+ dict_T *selfdict; ///< Dictionary for "self"
+ typval_T *basetv; ///< base for base->method()
+} funcexe_T;
+
+#define FUNCEXE_INIT (funcexe_T) { \
+ .argv_func = NULL, \
+ .firstline = 0, \
+ .lastline = 0, \
+ .doesrange = NULL, \
+ .evaluate = false, \
+ .partial = NULL, \
+ .selfdict = NULL, \
+ .basetv = NULL, \
+}
+
#define FUNCARG(fp, j) ((char_u **)(fp->uf_args.ga_data))[j]
#define FUNCLINE(fp, j) ((char_u **)(fp->uf_lines.ga_data))[j]
diff --git a/src/nvim/event/process.c b/src/nvim/event/process.c
index b93d6cc0ab..8b366d0f3c 100644
--- a/src/nvim/event/process.c
+++ b/src/nvim/event/process.c
@@ -88,7 +88,7 @@ int process_spawn(Process *proc, bool in, bool out, bool err)
} else {
process_close(proc);
}
- shell_free_argv(proc->argv);
+ process_free(proc);
proc->status = -1;
return status;
}
@@ -200,9 +200,9 @@ int process_wait(Process *proc, int ms, MultiQueue *events)
if (proc->refcount == 1) {
// Job exited, free its resources.
decref(proc);
- if (events) {
- // the decref call created an exit event, process it now
- multiqueue_process_events(events);
+ if (proc->events) {
+ // decref() created an exit event, process it now.
+ multiqueue_process_events(proc->events);
}
} else {
proc->refcount--;
@@ -239,6 +239,15 @@ void process_stop(Process *proc) FUNC_ATTR_NONNULL_ALL
KILL_TIMEOUT_MS, 0);
}
+// Frees process-owned resources.
+void process_free(Process *proc) FUNC_ATTR_NONNULL_ALL
+{
+ if (proc->argv != NULL) {
+ shell_free_argv(proc->argv);
+ proc->argv = NULL;
+ }
+}
+
/// Sends SIGKILL (or SIGTERM..SIGKILL for PTY jobs) to processes that did
/// not terminate after process_stop().
static void children_kill_cb(uv_timer_t *handle)
@@ -269,9 +278,12 @@ static void children_kill_cb(uv_timer_t *handle)
static void process_close_event(void **argv)
{
Process *proc = argv[0];
- shell_free_argv(proc->argv);
- if (proc->cb) { // "on_exit" for jobstart(). See channel_job_start().
+ if (proc->cb) {
+ // User (hint: channel_job_start) is responsible for calling
+ // process_free().
proc->cb(proc, proc->status, proc->data);
+ } else {
+ process_free(proc);
}
}
diff --git a/src/nvim/event/process.h b/src/nvim/event/process.h
index 24debdb276..20c02e4900 100644
--- a/src/nvim/event/process.h
+++ b/src/nvim/event/process.h
@@ -26,6 +26,7 @@ struct process {
char **argv;
dict_T *env;
Stream in, out, err;
+ /// Exit handler. If set, user must call process_free().
process_exit_cb cb;
internal_process_cb internal_exit_cb, internal_close_cb;
bool closed, detach, overlapped;
diff --git a/src/nvim/fileio.c b/src/nvim/fileio.c
index 3d058e1d09..92b48c36cb 100644
--- a/src/nvim/fileio.c
+++ b/src/nvim/fileio.c
@@ -2688,9 +2688,22 @@ buf_write(
/*
* Isolate one directory name, using an entry in 'bdir'.
*/
- (void)copy_option_part(&dirp, IObuff, IOSIZE, ",");
- p = IObuff + STRLEN(IObuff);
- if (after_pathsep((char *)IObuff, (char *)p) && p[-1] == p[-2]) {
+ size_t dir_len = copy_option_part(&dirp, IObuff, IOSIZE, ",");
+ p = IObuff + dir_len;
+ bool trailing_pathseps = after_pathsep((char *)IObuff, (char *)p) && p[-1] == p[-2];
+ if (trailing_pathseps) {
+ IObuff[dir_len - 2] = NUL;
+ }
+ if (*dirp == NUL && !os_isdir(IObuff)) {
+ int ret;
+ char *failed_dir;
+ if ((ret = os_mkdir_recurse((char *)IObuff, 0755, &failed_dir)) != 0) {
+ EMSG3(_("E303: Unable to create directory \"%s\" for backup file: %s"),
+ failed_dir, os_strerror(ret));
+ xfree(failed_dir);
+ }
+ }
+ if (trailing_pathseps) {
// Ends with '//', Use Full path
if ((p = (char_u *)make_percent_swname((char *)IObuff, (char *)fname))
!= NULL) {
@@ -2840,9 +2853,22 @@ nobackup:
/*
* Isolate one directory name and make the backup file name.
*/
- (void)copy_option_part(&dirp, IObuff, IOSIZE, ",");
- p = IObuff + STRLEN(IObuff);
- if (after_pathsep((char *)IObuff, (char *)p) && p[-1] == p[-2]) {
+ size_t dir_len = copy_option_part(&dirp, IObuff, IOSIZE, ",");
+ p = IObuff + dir_len;
+ bool trailing_pathseps = after_pathsep((char *)IObuff, (char *)p) && p[-1] == p[-2];
+ if (trailing_pathseps) {
+ IObuff[dir_len - 2] = NUL;
+ }
+ if (*dirp == NUL && !os_isdir(IObuff)) {
+ int ret;
+ char *failed_dir;
+ if ((ret = os_mkdir_recurse((char *)IObuff, 0755, &failed_dir)) != 0) {
+ EMSG3(_("E303: Unable to create directory \"%s\" for backup file: %s"),
+ failed_dir, os_strerror(ret));
+ xfree(failed_dir);
+ }
+ }
+ if (trailing_pathseps) {
// path ends with '//', use full path
if ((p = (char_u *)make_percent_swname((char *)IObuff, (char *)fname))
!= NULL) {
diff --git a/src/nvim/fold.h b/src/nvim/fold.h
index 95c4b0c1dc..37fab4da60 100644
--- a/src/nvim/fold.h
+++ b/src/nvim/fold.h
@@ -21,6 +21,8 @@ typedef struct foldinfo {
long fi_lines;
} foldinfo_T;
+#define FOLDINFO_INIT { 0, 0, 0, 0 }
+
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "fold.h.generated.h"
diff --git a/src/nvim/generators/gen_api_dispatch.lua b/src/nvim/generators/gen_api_dispatch.lua
index c14b465f92..99d80cdebc 100644
--- a/src/nvim/generators/gen_api_dispatch.lua
+++ b/src/nvim/generators/gen_api_dispatch.lua
@@ -7,7 +7,7 @@ if arg[1] == '--help' then
print(' 2: dispatch output file (dispatch_wrappers.generated.h)')
print(' 3: functions metadata output file (funcs_metadata.generated.h)')
print(' 4: API metadata output file (api_metadata.mpack)')
- print(' 5: lua C bindings output file (msgpack_lua_c_bindings.generated.c)')
+ print(' 5: lua C bindings output file (lua_api_c_bindings.generated.c)')
print(' rest: C files where API functions are defined')
end
assert(#arg >= 4)
@@ -378,7 +378,7 @@ output:write('\n')
local lua_c_functions = {}
local function process_function(fn)
- local lua_c_function_name = ('nlua_msgpack_%s'):format(fn.name)
+ local lua_c_function_name = ('nlua_api_%s'):format(fn.name)
write_shifted_output(output, string.format([[
static int %s(lua_State *lstate)
diff --git a/src/nvim/generators/gen_eval.lua b/src/nvim/generators/gen_eval.lua
index 679895421a..945fa5099f 100644
--- a/src/nvim/generators/gen_eval.lua
+++ b/src/nvim/generators/gen_eval.lua
@@ -42,7 +42,7 @@ gperfpipe:write([[
%language=ANSI-C
%global-table
%readonly-tables
-%define initializer-suffix ,0,0,NULL,NULL
+%define initializer-suffix ,0,0,BASE_NONE,NULL,NULL
%define word-array-name functions
%define hash-function-name hash_internal_func_gperf
%define lookup-function-name find_internal_func_gperf
@@ -59,9 +59,10 @@ for name, def in pairs(funcs) do
elseif #args == 1 then
args[2] = 'MAX_FUNC_ARGS'
end
+ local base = def.base or "BASE_NONE"
local func = def.func or ('f_' .. name)
local data = def.data or "NULL"
- gperfpipe:write(('%s, %s, %s, &%s, (FunPtr)%s\n')
- :format(name, args[1], args[2], func, data))
+ gperfpipe:write(('%s, %s, %s, %s, &%s, (FunPtr)%s\n')
+ :format(name, args[1], args[2], base, func, data))
end
gperfpipe:close()
diff --git a/src/nvim/globals.h b/src/nvim/globals.h
index 96acca4ac7..2a72dbcd09 100644
--- a/src/nvim/globals.h
+++ b/src/nvim/globals.h
@@ -972,6 +972,7 @@ EXTERN char_u e_write[] INIT(= N_("E80: Error while writing"));
EXTERN char_u e_zerocount[] INIT(= N_("E939: Positive count required"));
EXTERN char_u e_usingsid[] INIT(= N_(
"E81: Using <SID> not in a script context"));
+EXTERN char_u e_missingparen[] INIT(= N_("E107: Missing parentheses: %s"));
EXTERN char_u e_maxmempat[] INIT(= N_(
"E363: pattern uses more memory than 'maxmempattern'"));
EXTERN char_u e_emptybuf[] INIT(= N_("E749: empty buffer"));
diff --git a/src/nvim/highlight_defs.h b/src/nvim/highlight_defs.h
index ed4aefb577..a0e8bad11f 100644
--- a/src/nvim/highlight_defs.h
+++ b/src/nvim/highlight_defs.h
@@ -63,7 +63,9 @@ typedef enum {
, HLF_M // "--More--" message
, HLF_CM // Mode (e.g., "-- INSERT --")
, HLF_N // line number for ":number" and ":#" commands
- , HLF_CLN // current line number
+ , HLF_LNA // LineNrAbove
+ , HLF_LNB // LineNrBelow
+ , HLF_CLN // current line number when 'cursorline' is set
, HLF_R // return to continue message and yes/no questions
, HLF_S // status lines
, HLF_SNC // status lines of not-current windows
@@ -118,6 +120,8 @@ EXTERN const char *hlf_names[] INIT(= {
[HLF_M] = "MoreMsg",
[HLF_CM] = "ModeMsg",
[HLF_N] = "LineNr",
+ [HLF_LNA] = "LineNrAbove",
+ [HLF_LNB] = "LineNrBelow",
[HLF_CLN] = "CursorLineNr",
[HLF_R] = "Question",
[HLF_S] = "StatusLine",
diff --git a/src/nvim/lua/converter.c b/src/nvim/lua/converter.c
index ce8c9b0d06..1a59cd94ae 100644
--- a/src/nvim/lua/converter.c
+++ b/src/nvim/lua/converter.c
@@ -196,8 +196,9 @@ bool nlua_pop_typval(lua_State *lstate, typval_T *ret_tv)
{
bool ret = true;
const int initial_size = lua_gettop(lstate);
- kvec_t(TVPopStackItem) stack = KV_INITIAL_VALUE;
- kv_push(stack, ((TVPopStackItem) { ret_tv, false, false, 0 }));
+ kvec_withinit_t(TVPopStackItem, 2) stack = KV_INITIAL_VALUE;
+ kvi_init(stack);
+ kvi_push(stack, ((TVPopStackItem) { ret_tv, false, false, 0 }));
while (ret && kv_size(stack)) {
if (!lua_checkstack(lstate, lua_gettop(lstate) + 3)) {
emsgf(_("E1502: Lua failed to grow stack to %i"), lua_gettop(lstate) + 3);
@@ -234,7 +235,7 @@ bool nlua_pop_typval(lua_State *lstate, typval_T *ret_tv)
tv_list_append_owned_tv(kv_pair, (typval_T) {
.v_type = VAR_UNKNOWN,
});
- kv_push(stack, cur);
+ kvi_push(stack, cur);
tv_list_append_list(cur.tv->vval.v_list, kv_pair);
cur = (TVPopStackItem) {
.tv = TV_LIST_ITEM_TV(tv_list_last(kv_pair)),
@@ -247,7 +248,7 @@ bool nlua_pop_typval(lua_State *lstate, typval_T *ret_tv)
if (tv_dict_add(cur.tv->vval.v_dict, di) == FAIL) {
abort();
}
- kv_push(stack, cur);
+ kvi_push(stack, cur);
cur = (TVPopStackItem) { &di->di_tv, false, false, 0 };
}
} else {
@@ -265,7 +266,7 @@ bool nlua_pop_typval(lua_State *lstate, typval_T *ret_tv)
tv_list_append_owned_tv(cur.tv->vval.v_list, (typval_T) {
.v_type = VAR_UNKNOWN,
});
- kv_push(stack, cur);
+ kvi_push(stack, cur);
// TODO(ZyX-I): Use indexes, here list item *will* be reallocated.
cur = (TVPopStackItem) {
.tv = TV_LIST_ITEM_TV(tv_list_last(cur.tv->vval.v_list)),
@@ -343,7 +344,7 @@ bool nlua_pop_typval(lua_State *lstate, typval_T *ret_tv)
if (table_props.maxidx != 0) {
cur.container = true;
cur.idx = lua_gettop(lstate);
- kv_push(stack, cur);
+ kvi_push(stack, cur);
}
break;
}
@@ -373,7 +374,7 @@ bool nlua_pop_typval(lua_State *lstate, typval_T *ret_tv)
}
cur.container = true;
cur.idx = lua_gettop(lstate);
- kv_push(stack, cur);
+ kvi_push(stack, cur);
lua_pushnil(lstate);
}
break;
@@ -434,7 +435,7 @@ nlua_pop_typval_table_processing_end:
lua_pop(lstate, 1);
}
}
- kv_destroy(stack);
+ kvi_destroy(stack);
if (!ret) {
tv_clear(ret_tv);
*ret_tv = (typval_T) {
@@ -1060,15 +1061,16 @@ Object nlua_pop_Object(lua_State *const lstate, bool ref, Error *const err)
{
Object ret = NIL;
const int initial_size = lua_gettop(lstate);
- kvec_t(ObjPopStackItem) stack = KV_INITIAL_VALUE;
- kv_push(stack, ((ObjPopStackItem) { &ret, false }));
+ kvec_withinit_t(ObjPopStackItem, 2) stack = KV_INITIAL_VALUE;
+ kvi_init(stack);
+ kvi_push(stack, ((ObjPopStackItem) { &ret, false }));
while (!ERROR_SET(err) && kv_size(stack)) {
- if (!lua_checkstack(lstate, lua_gettop(lstate) + 3)) {
- api_set_error(err, kErrorTypeException, "Lua failed to grow stack");
- break;
- }
ObjPopStackItem cur = kv_pop(stack);
if (cur.container) {
+ if (!lua_checkstack(lstate, lua_gettop(lstate) + 3)) {
+ api_set_error(err, kErrorTypeException, "Lua failed to grow stack");
+ break;
+ }
if (cur.obj->type == kObjectTypeDictionary) {
// stack: …, dict, key
if (cur.obj->data.dictionary.size
@@ -1095,7 +1097,7 @@ Object nlua_pop_Object(lua_State *const lstate, bool ref, Error *const err)
.data = xmemdupz(s, len),
.size = len,
};
- kv_push(stack, cur);
+ kvi_push(stack, cur);
cur = (ObjPopStackItem) {
.obj = &cur.obj->data.dictionary.items[idx].value,
.container = false,
@@ -1117,7 +1119,7 @@ Object nlua_pop_Object(lua_State *const lstate, bool ref, Error *const err)
lua_pop(lstate, 2);
continue;
}
- kv_push(stack, cur);
+ kvi_push(stack, cur);
cur = (ObjPopStackItem) {
.obj = &cur.obj->data.array.items[idx],
.container = false,
@@ -1169,7 +1171,7 @@ Object nlua_pop_Object(lua_State *const lstate, bool ref, Error *const err)
sizeof(cur.obj->data.array.items[0]));
cur.obj->data.array.capacity = table_props.maxidx;
cur.container = true;
- kv_push(stack, cur);
+ kvi_push(stack, cur);
}
break;
}
@@ -1185,7 +1187,7 @@ Object nlua_pop_Object(lua_State *const lstate, bool ref, Error *const err)
sizeof(cur.obj->data.dictionary.items[0]));
cur.obj->data.dictionary.capacity = table_props.string_keys_num;
cur.container = true;
- kv_push(stack, cur);
+ kvi_push(stack, cur);
lua_pushnil(lstate);
}
break;
@@ -1239,7 +1241,7 @@ type_error:
lua_pop(lstate, 1);
}
}
- kv_destroy(stack);
+ kvi_destroy(stack);
if (ERROR_SET(err)) {
api_free_object(ret);
ret = NIL;
diff --git a/src/nvim/lua/executor.c b/src/nvim/lua/executor.c
index cbc2273bc9..5cd9894f9d 100644
--- a/src/nvim/lua/executor.c
+++ b/src/nvim/lua/executor.c
@@ -544,8 +544,17 @@ static int nlua_state_init(lua_State *const lstate) FUNC_ATTR_NONNULL_ALL
return 1;
}
// [package, loaded, inspect]
-
lua_setfield(lstate, -2, "vim.inspect"); // [package, loaded]
+
+ code = (char *)&lua_F_module[0];
+ if (luaL_loadbuffer(lstate, code, strlen(code), "@vim/F.lua")
+ || lua_pcall(lstate, 0, 1, 0)) {
+ nlua_error(lstate, _("E5106: Error while creating vim.F module: %.*s"));
+ return 1;
+ }
+ // [package, loaded, module]
+ lua_setfield(lstate, -2, "vim.F"); // [package, loaded]
+
lua_pop(lstate, 2); // []
}
@@ -558,6 +567,22 @@ static int nlua_state_init(lua_State *const lstate) FUNC_ATTR_NONNULL_ALL
}
}
+ {
+ lua_getglobal(lstate, "package"); // [package]
+ lua_getfield(lstate, -1, "loaded"); // [package, loaded]
+
+ const char *code = (char *)&lua_meta_module[0];
+ if (luaL_loadbuffer(lstate, code, strlen(code), "@vim/_meta.lua")
+ || lua_pcall(lstate, 0, 1, 0)) {
+ nlua_error(lstate, _("E5106: Error while creating vim._meta module: %.*s"));
+ return 1;
+ }
+ // [package, loaded, module]
+ lua_setfield(lstate, -2, "vim._meta"); // [package, loaded]
+
+ lua_pop(lstate, 2); // []
+ }
+
return 0;
}
@@ -785,13 +810,13 @@ int nlua_call(lua_State *lstate)
try_start();
typval_T rettv;
- int dummy;
+ funcexe_T funcexe = FUNCEXE_INIT;
+ funcexe.firstline = curwin->w_cursor.lnum;
+ funcexe.lastline = curwin->w_cursor.lnum;
+ funcexe.evaluate = true;
// call_func() retval is deceptive, ignore it. Instead we set `msg_list`
// (TRY_WRAP) to capture abort-causing non-exception errors.
- (void)call_func(name, (int)name_len, &rettv, nargs,
- vim_args, NULL,
- curwin->w_cursor.lnum, curwin->w_cursor.lnum,
- &dummy, true, NULL, NULL);
+ (void)call_func(name, (int)name_len, &rettv, nargs, vim_args, &funcexe);
if (!try_end(&err)) {
nlua_push_typval(lstate, &rettv, false);
}
diff --git a/src/nvim/lua/vim.lua b/src/nvim/lua/vim.lua
index ed435439a4..34b314b40d 100644
--- a/src/nvim/lua/vim.lua
+++ b/src/nvim/lua/vim.lua
@@ -273,8 +273,8 @@ end
---@see |vim.in_fast_event()|
function vim.schedule_wrap(cb)
return (function (...)
- local args = {...}
- vim.schedule(function() cb(unpack(args)) end)
+ local args = vim.F.pack_len(...)
+ vim.schedule(function() cb(vim.F.unpack_len(args)) end)
end)
end
@@ -642,6 +642,4 @@ vim._expand_pat_get_parts = function(lua_string)
return parts, search_index
end
-pcall(require, 'vim._meta')
-
return module
diff --git a/src/nvim/main.c b/src/nvim/main.c
index 9fc82a75af..b73f5aad76 100644
--- a/src/nvim/main.c
+++ b/src/nvim/main.c
@@ -309,9 +309,6 @@ int main(int argc, char **argv)
init_highlight(true, false); // Default highlight groups.
TIME_MSG("init highlight");
- init_default_mappings(); // Default mappings.
- TIME_MSG("init default mappings");
-
// Set the break level after the terminal is initialized.
debug_break_level = params.use_debug_break_level;
@@ -340,21 +337,11 @@ int main(int argc, char **argv)
TIME_MSG("initialized screen early for UI");
}
- // open terminals when opening files that start with term://
-#define PROTO "term://"
- do_cmdline_cmd("augroup nvim_terminal");
- do_cmdline_cmd("autocmd!");
- do_cmdline_cmd("autocmd BufReadCmd " PROTO "* nested "
- ":if !exists('b:term_title')|call termopen( "
- // Capture the command string
- "matchstr(expand(\"<amatch>\"), "
- "'\\c\\m" PROTO "\\%(.\\{-}//\\%(\\d\\+:\\)\\?\\)\\?\\zs.*'), "
- // capture the working directory
- "{'cwd': expand(get(matchlist(expand(\"<amatch>\"), "
- "'\\c\\m" PROTO "\\(.\\{-}\\)//'), 1, ''))})"
- "|endif");
- do_cmdline_cmd("augroup END");
-#undef PROTO
+ init_default_mappings(); // Default mappings.
+ TIME_MSG("init default mappings");
+
+ init_default_autocmds();
+ TIME_MSG("init default autocommands");
// Reset 'loadplugins' for "-u NONE" before "--cmd" arguments.
// Allows for setting 'loadplugins' there.
diff --git a/src/nvim/math.c b/src/nvim/math.c
index b51f335ed7..63309b6f7a 100644
--- a/src/nvim/math.c
+++ b/src/nvim/math.c
@@ -2,6 +2,8 @@
// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
#include <math.h>
+#include <stdint.h>
+#include <string.h>
#include "nvim/math.h"
@@ -9,34 +11,26 @@
# include "math.c.generated.h"
#endif
-#if defined(__clang__) && __clang__ == 1 && __clang_major__ >= 6
-// Workaround glibc + Clang 6+ bug. #8274
-// https://bugzilla.redhat.com/show_bug.cgi?id=1472437
-# pragma clang diagnostic push
-# pragma clang diagnostic ignored "-Wconversion"
-#endif
int xfpclassify(double d)
{
-#if defined(__MINGW32__)
- // Workaround mingw warning. #7863
- return __fpclassify(d);
-#else
- return fpclassify(d);
-#endif
+ uint64_t m;
+ int e;
+
+ memcpy(&m, &d, sizeof(m));
+ e = 0x7ff & (m >> 52);
+ m = 0xfffffffffffffULL & m;
+
+ switch (e) {
+ default: return FP_NORMAL;
+ case 0x000: return m ? FP_SUBNORMAL : FP_ZERO;
+ case 0x7ff: return m ? FP_NAN : FP_INFINITE;
+ }
}
int xisinf(double d)
{
- return isinf(d);
+ return FP_INFINITE == xfpclassify(d);
}
int xisnan(double d)
{
-#if defined(__MINGW32__)
- // Workaround mingw warning. #7863
- return _isnan(d);
-#else
- return isnan(d);
-#endif
+ return FP_NAN == xfpclassify(d);
}
-#if defined(__clang__) && __clang__ == 1 && __clang_major__ >= 6
-# pragma clang diagnostic pop
-#endif
diff --git a/src/nvim/memline.c b/src/nvim/memline.c
index 4d435bc99f..230361b997 100644
--- a/src/nvim/memline.c
+++ b/src/nvim/memline.c
@@ -1442,7 +1442,7 @@ recover_names (
* Append the full path to name with path separators made into percent
* signs, to dir. An unnamed buffer is handled as "" (<currentdir>/"")
*/
-char *make_percent_swname(const char *dir, char *name)
+char *make_percent_swname(const char *dir, const char *name)
FUNC_ATTR_NONNULL_ARG(1)
{
char *d = NULL;
diff --git a/src/nvim/msgpack_rpc/helpers.c b/src/nvim/msgpack_rpc/helpers.c
index a4a36e5ebf..35f126eab1 100644
--- a/src/nvim/msgpack_rpc/helpers.c
+++ b/src/nvim/msgpack_rpc/helpers.c
@@ -86,8 +86,9 @@ bool msgpack_rpc_to_object(const msgpack_object *const obj, Object *const arg)
FUNC_ATTR_NONNULL_ALL
{
bool ret = true;
- kvec_t(MPToAPIObjectStackItem) stack = KV_INITIAL_VALUE;
- kv_push(stack, ((MPToAPIObjectStackItem) {
+ kvec_withinit_t(MPToAPIObjectStackItem, 2) stack = KV_INITIAL_VALUE;
+ kvi_init(stack);
+ kvi_push(stack, ((MPToAPIObjectStackItem) {
.mobj = obj,
.aobj = arg,
.container = false,
@@ -155,7 +156,7 @@ bool msgpack_rpc_to_object(const msgpack_object *const obj, Object *const arg)
const size_t idx = cur.idx;
cur.idx++;
kv_last(stack) = cur;
- kv_push(stack, ((MPToAPIObjectStackItem) {
+ kvi_push(stack, ((MPToAPIObjectStackItem) {
.mobj = &cur.mobj->via.array.ptr[idx],
.aobj = &cur.aobj->data.array.items[idx],
.container = false,
@@ -209,7 +210,7 @@ bool msgpack_rpc_to_object(const msgpack_object *const obj, Object *const arg)
}
}
if (ret) {
- kv_push(stack, ((MPToAPIObjectStackItem) {
+ kvi_push(stack, ((MPToAPIObjectStackItem) {
.mobj = &cur.mobj->via.map.ptr[idx].val,
.aobj = &cur.aobj->data.dictionary.items[idx].value,
.container = false,
@@ -265,7 +266,7 @@ bool msgpack_rpc_to_object(const msgpack_object *const obj, Object *const arg)
(void)kv_pop(stack);
}
}
- kv_destroy(stack);
+ kvi_destroy(stack);
return ret;
}
@@ -375,8 +376,9 @@ typedef struct {
void msgpack_rpc_from_object(const Object result, msgpack_packer *const res)
FUNC_ATTR_NONNULL_ARG(2)
{
- kvec_t(APIToMPObjectStackItem) stack = KV_INITIAL_VALUE;
- kv_push(stack, ((APIToMPObjectStackItem) { &result, false, 0 }));
+ kvec_withinit_t(APIToMPObjectStackItem, 2) stack = KV_INITIAL_VALUE;
+ kvi_init(stack);
+ kvi_push(stack, ((APIToMPObjectStackItem) { &result, false, 0 }));
while (kv_size(stack)) {
APIToMPObjectStackItem cur = kv_last(stack);
STATIC_ASSERT(kObjectTypeWindow == kObjectTypeBuffer + 1
@@ -428,7 +430,7 @@ void msgpack_rpc_from_object(const Object result, msgpack_packer *const res)
const size_t idx = cur.idx;
cur.idx++;
kv_last(stack) = cur;
- kv_push(stack, ((APIToMPObjectStackItem) {
+ kvi_push(stack, ((APIToMPObjectStackItem) {
.aobj = &cur.aobj->data.array.items[idx],
.container = false,
}));
@@ -451,7 +453,7 @@ void msgpack_rpc_from_object(const Object result, msgpack_packer *const res)
kv_last(stack) = cur;
msgpack_rpc_from_string(cur.aobj->data.dictionary.items[idx].key,
res);
- kv_push(stack, ((APIToMPObjectStackItem) {
+ kvi_push(stack, ((APIToMPObjectStackItem) {
.aobj = &cur.aobj->data.dictionary.items[idx].value,
.container = false,
}));
@@ -468,7 +470,7 @@ void msgpack_rpc_from_object(const Object result, msgpack_packer *const res)
(void)kv_pop(stack);
}
}
- kv_destroy(stack);
+ kvi_destroy(stack);
}
void msgpack_rpc_from_array(Array result, msgpack_packer *res)
diff --git a/src/nvim/normal.c b/src/nvim/normal.c
index 7b2f77a6f9..4c3d7d58de 100644
--- a/src/nvim/normal.c
+++ b/src/nvim/normal.c
@@ -2531,12 +2531,12 @@ do_mouse (
}
};
typval_T rettv;
- int doesrange;
- (void)call_func((char_u *)tab_page_click_defs[mouse_col].func,
- -1,
- &rettv, ARRAY_SIZE(argv), argv, NULL,
- curwin->w_cursor.lnum, curwin->w_cursor.lnum,
- &doesrange, true, NULL, NULL);
+ funcexe_T funcexe = FUNCEXE_INIT;
+ funcexe.firstline = curwin->w_cursor.lnum;
+ funcexe.lastline = curwin->w_cursor.lnum;
+ funcexe.evaluate = true;
+ (void)call_func((char_u *)tab_page_click_defs[mouse_col].func, -1,
+ &rettv, ARRAY_SIZE(argv), argv, &funcexe);
tv_clear(&rettv);
break;
}
@@ -3277,6 +3277,7 @@ static void clearop(oparg_T *oap)
oap->regname = 0;
oap->motion_force = NUL;
oap->use_reg_one = false;
+ motion_force = NUL;
}
static void clearopbeep(oparg_T *oap)
diff --git a/src/nvim/ops.c b/src/nvim/ops.c
index 178b454e4e..a06db4a551 100644
--- a/src/nvim/ops.c
+++ b/src/nvim/ops.c
@@ -3444,8 +3444,9 @@ void do_put(int regname, yankreg_T *reg, int dir, long count, int flags)
(int)y_size-1, lastsize, totsize,
kExtmarkUndo);
} else if (y_type == kMTLineWise && flags & PUT_LINE_SPLIT) {
- extmark_splice(curbuf, (int)new_cursor.lnum-1, col, 0, 0, 0,
- (int)y_size+1, 0, totsize+1, kExtmarkUndo);
+ // Account for last pasted NL + last NL
+ extmark_splice(curbuf, (int)new_cursor.lnum-1, col + 1, 0, 0, 0,
+ (int)y_size+1, 0, totsize+2, kExtmarkUndo);
}
}
diff --git a/src/nvim/option.c b/src/nvim/option.c
index 0595776f79..d11bbc8ecc 100644
--- a/src/nvim/option.c
+++ b/src/nvim/option.c
@@ -260,15 +260,13 @@ typedef struct vimoption {
#define P_MLE 0x80000000U ///< under control of 'modelineexpr'
#define HIGHLIGHT_INIT \
- "8:SpecialKey,~:EndOfBuffer,z:TermCursor,Z:TermCursorNC,@:NonText," \
- "d:Directory,e:ErrorMsg,i:IncSearch,l:Search,m:MoreMsg,M:ModeMsg,n:LineNr," \
- "N:CursorLineNr,r:Question,s:StatusLine,S:StatusLineNC,c:VertSplit,t:Title," \
- "v:Visual,V:VisualNOS,w:WarningMsg,W:WildMenu,f:Folded,F:FoldColumn," \
- "A:DiffAdd,C:DiffChange,D:DiffDelete,T:DiffText,>:SignColumn,-:Conceal," \
- "B:SpellBad,P:SpellCap,R:SpellRare,L:SpellLocal,+:Pmenu,=:PmenuSel," \
- "x:PmenuSbar,X:PmenuThumb,*:TabLine,#:TabLineSel,_:TabLineFill," \
- "!:CursorColumn,.:CursorLine,o:ColorColumn,q:QuickFixLine," \
- "0:Whitespace,I:NormalNC"
+ "8:SpecialKey,~:EndOfBuffer,z:TermCursor,Z:TermCursorNC,@:NonText,d:Directory,e:ErrorMsg," \
+ "i:IncSearch,l:Search,m:MoreMsg,M:ModeMsg,n:LineNr,a:LineNrAbove,b:LineNrBelow,N:CursorLineNr," \
+ "r:Question,s:StatusLine,S:StatusLineNC,c:VertSplit,t:Title,v:Visual,V:VisualNOS,w:WarningMsg," \
+ "W:WildMenu,f:Folded,F:FoldColumn,A:DiffAdd,C:DiffChange,D:DiffDelete,T:DiffText,>:SignColumn," \
+ "-:Conceal,B:SpellBad,P:SpellCap,R:SpellRare,L:SpellLocal,+:Pmenu,=:PmenuSel,x:PmenuSbar," \
+ "X:PmenuThumb,*:TabLine,#:TabLineSel,_:TabLineFill,!:CursorColumn,.:CursorLine,o:ColorColumn," \
+ "q:QuickFixLine,0:Whitespace,I:NormalNC"
/*
* options[] is initialized here.
@@ -485,17 +483,17 @@ void set_init_1(bool clean_arg)
#endif
false);
- char *backupdir = stdpaths_user_data_subpath("backup", 0, true);
+ char *backupdir = stdpaths_user_data_subpath("backup", 2, true);
const size_t backupdir_len = strlen(backupdir);
backupdir = xrealloc(backupdir, backupdir_len + 3);
memmove(backupdir + 2, backupdir, backupdir_len + 1);
memmove(backupdir, ".,", 2);
- set_string_default("viewdir", stdpaths_user_data_subpath("view", 0, true),
- true);
set_string_default("backupdir", backupdir, true);
+ set_string_default("viewdir", stdpaths_user_data_subpath("view", 2, true),
+ true);
set_string_default("directory", stdpaths_user_data_subpath("swap", 2, true),
true);
- set_string_default("undodir", stdpaths_user_data_subpath("undo", 0, true),
+ set_string_default("undodir", stdpaths_user_data_subpath("undo", 2, true),
true);
// Set default for &runtimepath. All necessary expansions are performed in
// this function.
diff --git a/src/nvim/regexp.c b/src/nvim/regexp.c
index 6379174938..98a46cf781 100644
--- a/src/nvim/regexp.c
+++ b/src/nvim/regexp.c
@@ -6726,26 +6726,24 @@ static int vim_regsub_both(char_u *source, typval_T *expr, char_u *dest,
if (expr != NULL) {
typval_T argv[2];
- int dummy;
typval_T rettv;
staticList10_T matchList = TV_LIST_STATIC10_INIT;
-
rettv.v_type = VAR_STRING;
rettv.vval.v_string = NULL;
argv[0].v_type = VAR_LIST;
argv[0].vval.v_list = &matchList.sl_list;
+ funcexe_T funcexe = FUNCEXE_INIT;
+ funcexe.argv_func = fill_submatch_list;
+ funcexe.evaluate = true;
if (expr->v_type == VAR_FUNC) {
s = expr->vval.v_string;
- call_func(s, -1, &rettv, 1, argv,
- fill_submatch_list, 0L, 0L, &dummy,
- true, NULL, NULL);
+ call_func(s, -1, &rettv, 1, argv, &funcexe);
} else if (expr->v_type == VAR_PARTIAL) {
partial_T *partial = expr->vval.v_partial;
s = partial_name(partial);
- call_func(s, -1, &rettv, 1, argv,
- fill_submatch_list, 0L, 0L, &dummy,
- true, partial, NULL);
+ funcexe.partial = partial;
+ call_func(s, -1, &rettv, 1, argv, &funcexe);
}
if (tv_list_len(&matchList.sl_list) > 0) {
// fill_submatch_list() was called.
diff --git a/src/nvim/screen.c b/src/nvim/screen.c
index 208ae3488f..5a995b9a40 100644
--- a/src/nvim/screen.c
+++ b/src/nvim/screen.c
@@ -65,46 +65,50 @@
#include <stdbool.h>
#include <string.h>
-#include "nvim/log.h"
-#include "nvim/vim.h"
-#include "nvim/ascii.h"
+#include "nvim/api/private/helpers.h"
+#include "nvim/api/vim.h"
#include "nvim/arabic.h"
-#include "nvim/screen.h"
+#include "nvim/ascii.h"
#include "nvim/buffer.h"
#include "nvim/charset.h"
#include "nvim/cursor.h"
#include "nvim/cursor_shape.h"
+#include "nvim/decoration.h"
#include "nvim/diff.h"
+#include "nvim/edit.h"
#include "nvim/eval.h"
#include "nvim/ex_cmds.h"
#include "nvim/ex_cmds2.h"
#include "nvim/ex_getln.h"
-#include "nvim/edit.h"
+#include "nvim/extmark.h"
#include "nvim/fileio.h"
#include "nvim/fold.h"
-#include "nvim/indent.h"
+#include "nvim/garray.h"
#include "nvim/getchar.h"
#include "nvim/highlight.h"
+#include "nvim/indent.h"
+#include "nvim/lib/kvec.h"
+#include "nvim/log.h"
+#include "nvim/lua/executor.h"
#include "nvim/main.h"
#include "nvim/mark.h"
-#include "nvim/extmark.h"
-#include "nvim/decoration.h"
#include "nvim/mbyte.h"
#include "nvim/memline.h"
#include "nvim/memory.h"
#include "nvim/menu.h"
#include "nvim/message.h"
#include "nvim/misc1.h"
-#include "nvim/garray.h"
#include "nvim/move.h"
#include "nvim/normal.h"
#include "nvim/option.h"
+#include "nvim/os/time.h"
#include "nvim/os_unix.h"
#include "nvim/path.h"
#include "nvim/plines.h"
#include "nvim/popupmnu.h"
#include "nvim/quickfix.h"
#include "nvim/regexp.h"
+#include "nvim/screen.h"
#include "nvim/search.h"
#include "nvim/sign.h"
#include "nvim/spell.h"
@@ -116,12 +120,8 @@
#include "nvim/ui_compositor.h"
#include "nvim/undo.h"
#include "nvim/version.h"
+#include "nvim/vim.h"
#include "nvim/window.h"
-#include "nvim/os/time.h"
-#include "nvim/api/private/helpers.h"
-#include "nvim/api/vim.h"
-#include "nvim/lua/executor.h"
-#include "nvim/lib/kvec.h"
#define MB_FILLER_CHAR '<' /* character used when a double-width character
* doesn't fit. */
@@ -135,7 +135,7 @@ static size_t linebuf_size = 0;
static schar_T *linebuf_char = NULL;
static sattr_T *linebuf_attr = NULL;
-static match_T search_hl; /* used for 'hlsearch' highlight matching */
+static match_T search_hl; // used for 'hlsearch' highlight matching
StlClickDefinition *tab_page_click_defs = NULL;
@@ -168,8 +168,7 @@ static bool resizing = false;
static char * provider_err = NULL;
-static bool provider_invoke(NS ns_id, const char *name, LuaRef ref,
- Array args, bool default_true)
+static bool provider_invoke(NS ns_id, const char *name, LuaRef ref, Array args, bool default_true)
{
Error err = ERROR_INIT;
@@ -208,10 +207,12 @@ void redraw_later(win_T *wp, int type)
{
if (!exiting && wp->w_redr_type < type) {
wp->w_redr_type = type;
- if (type >= NOT_VALID)
+ if (type >= NOT_VALID) {
wp->w_lines_valid = 0;
- if (must_redraw < type) /* must_redraw is the maximum of all windows */
+ }
+ if (must_redraw < type) { // must_redraw is the maximum of all windows
must_redraw = type;
+ }
}
}
@@ -270,10 +271,10 @@ void redraw_buf_range_later(buf_T *buf, linenr_T firstline, linenr_T lastline)
if (wp->w_buffer == buf
&& lastline >= wp->w_topline && firstline < wp->w_botline) {
if (wp->w_redraw_top == 0 || wp->w_redraw_top > firstline) {
- wp->w_redraw_top = firstline;
+ wp->w_redraw_top = firstline;
}
if (wp->w_redraw_bot == 0 || wp->w_redraw_bot < lastline) {
- wp->w_redraw_bot = lastline;
+ wp->w_redraw_bot = lastline;
}
redraw_later(wp, VALID);
}
@@ -288,20 +289,16 @@ void redraw_buf_range_later(buf_T *buf, linenr_T firstline, linenr_T lastline)
* Note that when also inserting/deleting lines w_redraw_top and w_redraw_bot
* may become invalid and the whole window will have to be redrawn.
*/
-void
-redrawWinline(
- win_T *wp,
- linenr_T lnum
-)
+void redrawWinline(win_T *wp, linenr_T lnum)
FUNC_ATTR_NONNULL_ALL
{
if (lnum >= wp->w_topline
&& lnum < wp->w_botline) {
if (wp->w_redraw_top == 0 || wp->w_redraw_top > lnum) {
- wp->w_redraw_top = lnum;
+ wp->w_redraw_top = lnum;
}
if (wp->w_redraw_bot == 0 || wp->w_redraw_bot < lnum) {
- wp->w_redraw_bot = lnum;
+ wp->w_redraw_bot = lnum;
}
redraw_later(wp, VALID);
}
@@ -339,8 +336,9 @@ int update_screen(int type)
}
if (must_redraw) {
- if (type < must_redraw) /* use maximal type */
+ if (type < must_redraw) { // use maximal type
type = must_redraw;
+ }
/* must_redraw is reset here, so that when we run into some weird
* reason to redraw while busy redrawing (e.g., asynchronous
@@ -349,9 +347,10 @@ int update_screen(int type)
must_redraw = 0;
}
- /* Need to update w_lines[]. */
- if (curwin->w_lines_valid == 0 && type < NOT_VALID)
+ // Need to update w_lines[].
+ if (curwin->w_lines_valid == 0 && type < NOT_VALID) {
type = NOT_VALID;
+ }
/* Postpone the redrawing when it's not needed and when being called
* recursively. */
@@ -448,12 +447,13 @@ int update_screen(int type)
win_ui_flush();
msg_ext_check_clear();
- /* reset cmdline_row now (may have been changed temporarily) */
+ // reset cmdline_row now (may have been changed temporarily)
compute_cmdrow();
- /* Check for changed highlighting */
- if (need_highlight_changed)
+ // Check for changed highlighting
+ if (need_highlight_changed) {
highlight_changed();
+ }
if (type == CLEAR) { // first clear screen
screenclear(); // will reset clear_cmdline
@@ -503,21 +503,24 @@ int update_screen(int type)
redraw_tabline = true;
}
- if (clear_cmdline) /* going to clear cmdline (done below) */
+ if (clear_cmdline) { // going to clear cmdline (done below)
check_for_delay(FALSE);
+ }
/* Force redraw when width of 'number' or 'relativenumber' column
* changes. */
if (curwin->w_redr_type < NOT_VALID
&& curwin->w_nrwidth != ((curwin->w_p_nu || curwin->w_p_rnu)
- ? number_width(curwin) : 0))
+ ? number_width(curwin) : 0)) {
curwin->w_redr_type = NOT_VALID;
+ }
/*
* Only start redrawing if there is really something to do.
*/
- if (type == INVERTED)
+ if (type == INVERTED) {
update_curswant();
+ }
if (curwin->w_redr_type < type
&& !((type == VALID
&& curwin->w_lines[0].wl_valid
@@ -530,8 +533,9 @@ int update_screen(int type)
&& curwin->w_old_visual_mode == VIsual_mode
&& (curwin->w_valid & VALID_VIRTCOL)
&& curwin->w_old_curswant == curwin->w_curswant)
- ))
+ )) {
curwin->w_redr_type = type;
+ }
// Redraw the tab pages line if needed.
if (redraw_tabline || type >= NOT_VALID) {
@@ -602,7 +606,7 @@ int update_screen(int type)
win_update(wp, &providers);
}
- /* redraw status line after the window to minimize cursor movement */
+ // redraw status line after the window to minimize cursor movement
if (wp->w_redr_status) {
win_redr_status(wp);
}
@@ -631,9 +635,10 @@ int update_screen(int type)
showmode();
}
- /* May put up an introductory message when not editing a file */
- if (!did_intro)
+ // May put up an introductory message when not editing a file
+ if (!did_intro) {
maybe_intro_message();
+ }
did_intro = true;
for (size_t i = 0; i < kv_size(providers); i++) {
@@ -704,7 +709,7 @@ bool win_cursorline_standout(const win_T *wp)
FUNC_ATTR_NONNULL_ALL
{
return wp->w_p_cul
- || (wp->w_p_cole > 0 && (VIsual_active || !conceal_cursor_line(wp)));
+ || (wp->w_p_cole > 0 && (VIsual_active || !conceal_cursor_line(wp)));
}
/*
@@ -715,22 +720,22 @@ bool win_cursorline_standout(const win_T *wp)
*
* How the window is redrawn depends on wp->w_redr_type. Each type also
* implies the one below it.
- * NOT_VALID redraw the whole window
- * SOME_VALID redraw the whole window but do scroll when possible
- * REDRAW_TOP redraw the top w_upd_rows window lines, otherwise like VALID
- * INVERTED redraw the changed part of the Visual area
- * INVERTED_ALL redraw the whole Visual area
- * VALID 1. scroll up/down to adjust for a changed w_topline
- * 2. update lines at the top when scrolled down
- * 3. redraw changed text:
- * - if wp->w_buffer->b_mod_set set, update lines between
- * b_mod_top and b_mod_bot.
- * - if wp->w_redraw_top non-zero, redraw lines between
- * wp->w_redraw_top and wp->w_redr_bot.
- * - continue redrawing when syntax status is invalid.
- * 4. if scrolled up, update lines at the bottom.
+ * NOT_VALID redraw the whole window
+ * SOME_VALID redraw the whole window but do scroll when possible
+ * REDRAW_TOP redraw the top w_upd_rows window lines, otherwise like VALID
+ * INVERTED redraw the changed part of the Visual area
+ * INVERTED_ALL redraw the whole Visual area
+ * VALID 1. scroll up/down to adjust for a changed w_topline
+ * 2. update lines at the top when scrolled down
+ * 3. redraw changed text:
+ * - if wp->w_buffer->b_mod_set set, update lines between
+ * b_mod_top and b_mod_bot.
+ * - if wp->w_redraw_top non-zero, redraw lines between
+ * wp->w_redraw_top and wp->w_redr_bot.
+ * - continue redrawing when syntax status is invalid.
+ * 4. if scrolled up, update lines at the bottom.
* This results in three areas that may need updating:
- * top: from first row to top_end (when scrolled down)
+ * top: from first row to top_end (when scrolled down)
* mid: from mid_start to mid_end (update inversion or changed text)
* bot: from bot_start to last row (when scrolled up)
*/
@@ -749,10 +754,10 @@ static void win_update(win_T *wp, Providers *providers)
bool scrolled_down = false; // true when scrolled down when w_topline got smaller a bit
bool top_to_mod = false; // redraw above mod_top
- int row; /* current window row to display */
- linenr_T lnum; /* current buffer lnum to display */
- int idx; /* current index in w_lines[] */
- int srow; /* starting row of the current line */
+ int row; // current window row to display
+ linenr_T lnum; // current buffer lnum to display
+ int idx; // current index in w_lines[]
+ int srow; // starting row of the current line
bool eof = false; // if true, we hit the end of the file
bool didline = false; // if true, we finished the last line
@@ -767,7 +772,7 @@ static void win_update(win_T *wp, Providers *providers)
#define DID_LINE 2 // updated a normal line
#define DID_FOLD 3 // updated a folded line
int did_update = DID_NONE;
- linenr_T syntax_last_parsed = 0; /* last parsed text line */
+ linenr_T syntax_last_parsed = 0; // last parsed text line
linenr_T mod_top = 0;
linenr_T mod_bot = 0;
int save_got_int;
@@ -824,10 +829,11 @@ static void win_update(win_T *wp, Providers *providers)
* changes. Set mod_bot to the first line after the changes.
*/
mod_top = wp->w_redraw_top;
- if (wp->w_redraw_bot != 0)
+ if (wp->w_redraw_bot != 0) {
mod_bot = wp->w_redraw_bot + 1;
- else
+ } else {
mod_bot = 0;
+ }
if (buf->b_mod_set) {
if (mod_top == 0 || mod_top > buf->b_mod_top) {
mod_top = buf->b_mod_top;
@@ -835,12 +841,14 @@ static void win_update(win_T *wp, Providers *providers)
* in a pattern match. */
if (syntax_present(wp)) {
mod_top -= buf->b_s.b_syn_sync_linebreaks;
- if (mod_top < 1)
+ if (mod_top < 1) {
mod_top = 1;
+ }
}
}
- if (mod_bot == 0 || mod_bot < buf->b_mod_bot)
+ if (mod_bot == 0 || mod_bot < buf->b_mod_bot) {
mod_bot = buf->b_mod_bot;
+ }
// When 'hlsearch' is on and using a multi-line search pattern, a
// change in one line may make the Search highlighting in a
@@ -879,10 +887,11 @@ static void win_update(win_T *wp, Providers *providers)
* to this line. If there is no valid entry, use MAXLNUM. */
lnumt = wp->w_topline;
lnumb = MAXLNUM;
- for (i = 0; i < wp->w_lines_valid; ++i)
+ for (i = 0; i < wp->w_lines_valid; ++i) {
if (wp->w_lines[i].wl_valid) {
- if (wp->w_lines[i].wl_lastlnum < mod_top)
+ if (wp->w_lines[i].wl_lastlnum < mod_top) {
lnumt = wp->w_lines[i].wl_lastlnum + 1;
+ }
if (lnumb == MAXLNUM && wp->w_lines[i].wl_lnum >= mod_bot) {
lnumb = wp->w_lines[i].wl_lnum;
// When there is a fold column it might need updating
@@ -892,6 +901,7 @@ static void win_update(win_T *wp, Providers *providers)
}
}
}
+ }
(void)hasFoldingWin(wp, mod_top, &mod_top, NULL, true, NULL);
if (mod_top > lnumt) {
@@ -912,16 +922,18 @@ static void win_update(win_T *wp, Providers *providers)
* If the end of the change is above w_topline: do like no change was
* made, but redraw the first line to find changes in syntax. */
if (mod_top != 0 && mod_top < wp->w_topline) {
- if (mod_bot > wp->w_topline)
+ if (mod_bot > wp->w_topline) {
mod_top = wp->w_topline;
- else if (syntax_present(wp))
+ } else if (syntax_present(wp)) {
top_end = 1;
+ }
}
/* When line numbers are displayed need to redraw all lines below
* inserted/deleted lines. */
- if (mod_top != 0 && buf->b_mod_xlines != 0 && wp->w_p_nu)
+ if (mod_top != 0 && buf->b_mod_xlines != 0 && wp->w_p_nu) {
mod_bot = MAXLNUM;
+ }
}
wp->w_redraw_top = 0; // reset for next time
wp->w_redraw_bot = 0;
@@ -939,12 +951,13 @@ static void win_update(win_T *wp, Providers *providers)
break;
}
}
- if (top_end == 0)
- /* not found (cannot happen?): redraw everything */
+ if (top_end == 0) {
+ // not found (cannot happen?): redraw everything
type = NOT_VALID;
- else
- /* top area defined, the rest is VALID */
+ } else {
+ // top area defined, the rest is VALID
type = VALID;
+ }
}
/*
@@ -957,8 +970,7 @@ static void win_update(win_T *wp, Providers *providers)
*/
if ((type == VALID || type == SOME_VALID
|| type == INVERTED || type == INVERTED_ALL)
- && !wp->w_botfill && !wp->w_old_botfill
- ) {
+ && !wp->w_botfill && !wp->w_old_botfill) {
if (mod_top != 0
&& wp->w_topline == mod_top
&& (!wp->w_lines[0].wl_valid
@@ -986,14 +998,16 @@ static void win_update(win_T *wp, Providers *providers)
}
(void)hasFoldingWin(wp, ln, NULL, &ln, true, NULL);
}
- } else
+ } else {
j = wp->w_lines[0].wl_lnum - wp->w_topline;
+ }
if (j < wp->w_grid.Rows - 2) { // not too far off
i = plines_m_win(wp, wp->w_topline, wp->w_lines[0].wl_lnum - 1);
- /* insert extra lines for previously invisible filler lines */
- if (wp->w_lines[0].wl_lnum != wp->w_topline)
+ // insert extra lines for previously invisible filler lines
+ if (wp->w_lines[0].wl_lnum != wp->w_topline) {
i += diff_check_fill(wp, wp->w_lines[0].wl_lnum)
- wp->w_old_topfill;
+ }
if (i != 0 && i < wp->w_grid.Rows - 2) { // less than a screen off
// Try to insert the correct number of lines.
// If not the last window, delete the lines at the bottom.
@@ -1030,7 +1044,7 @@ static void win_update(win_T *wp, Providers *providers)
* needs updating.
*/
- /* try to find wp->w_topline in wp->w_lines[].wl_lnum */
+ // try to find wp->w_topline in wp->w_lines[].wl_lnum
j = -1;
row = 0;
for (i = 0; i < wp->w_lines_valid; i++) {
@@ -1052,11 +1066,12 @@ static void win_update(win_T *wp, Providers *providers)
*/
/* If the topline didn't change, delete old filler lines,
* otherwise delete filler lines of the new topline... */
- if (wp->w_lines[0].wl_lnum == wp->w_topline)
+ if (wp->w_lines[0].wl_lnum == wp->w_topline) {
row += wp->w_old_topfill;
- else
+ } else {
row += diff_check_fill(wp, wp->w_topline);
- /* ... but don't delete new filler lines. */
+ }
+ // ... but don't delete new filler lines.
row -= wp->w_topfill;
if (row > 0) {
win_scroll_lines(wp, 0, -row);
@@ -1065,7 +1080,7 @@ static void win_update(win_T *wp, Providers *providers)
if ((row == 0 || bot_start < 999) && wp->w_lines_valid != 0) {
/*
* Skip the lines (below the deleted lines) that are still
- * valid and don't need redrawing. Copy their info
+ * valid and don't need redrawing. Copy their info
* upwards, to compensate for the deleted lines. Set
* bot_start to the first row that needs redrawing.
*/
@@ -1082,7 +1097,7 @@ static void win_update(win_T *wp, Providers *providers)
}
bot_start += wp->w_lines[idx++].wl_size;
- /* stop at the last valid entry in w_lines[].wl_size */
+ // stop at the last valid entry in w_lines[].wl_size
if (++j >= wp->w_lines_valid) {
wp->w_lines_valid = idx;
break;
@@ -1090,10 +1105,11 @@ static void win_update(win_T *wp, Providers *providers)
}
/* Correct the first entry for filler lines at the top
* when it won't get updated below. */
- if (wp->w_p_diff && bot_start > 0)
+ if (wp->w_p_diff && bot_start > 0) {
wp->w_lines[0].wl_size =
plines_win_nofill(wp, wp->w_topline, true)
+ wp->w_topfill;
+ }
}
}
}
@@ -1103,19 +1119,19 @@ static void win_update(win_T *wp, Providers *providers)
mid_end = wp->w_grid.Rows;
}
} else {
- /* Not VALID or INVERTED: redraw all lines. */
+ // Not VALID or INVERTED: redraw all lines.
mid_start = 0;
mid_end = wp->w_grid.Rows;
}
if (type == SOME_VALID) {
- /* SOME_VALID: redraw all lines. */
+ // SOME_VALID: redraw all lines.
mid_start = 0;
mid_end = wp->w_grid.Rows;
type = NOT_VALID;
}
- /* check if we are updating or removing the inverted part */
+ // check if we are updating or removing the inverted part
if ((VIsual_active && buf == curwin->w_buffer)
|| (wp->w_old_cursor_lnum != 0 && type != NOT_VALID)) {
linenr_T from, to;
@@ -1132,15 +1148,19 @@ static void win_update(win_T *wp, Providers *providers)
from = VIsual.lnum;
to = curwin->w_cursor.lnum;
}
- /* redraw more when the cursor moved as well */
- if (wp->w_old_cursor_lnum < from)
+ // redraw more when the cursor moved as well
+ if (wp->w_old_cursor_lnum < from) {
from = wp->w_old_cursor_lnum;
- if (wp->w_old_cursor_lnum > to)
+ }
+ if (wp->w_old_cursor_lnum > to) {
to = wp->w_old_cursor_lnum;
- if (wp->w_old_visual_lnum < from)
+ }
+ if (wp->w_old_visual_lnum < from) {
from = wp->w_old_visual_lnum;
- if (wp->w_old_visual_lnum > to)
+ }
+ if (wp->w_old_visual_lnum > to) {
to = wp->w_old_visual_lnum;
+ }
} else {
/*
* Find the line numbers that need to be updated: The lines
@@ -1153,21 +1173,26 @@ static void win_update(win_T *wp, Providers *providers)
} else {
from = wp->w_old_cursor_lnum;
to = curwin->w_cursor.lnum;
- if (from == 0) /* Visual mode just started */
+ if (from == 0) { // Visual mode just started
from = to;
+ }
}
if (VIsual.lnum != wp->w_old_visual_lnum
|| VIsual.col != wp->w_old_visual_col) {
if (wp->w_old_visual_lnum < from
- && wp->w_old_visual_lnum != 0)
+ && wp->w_old_visual_lnum != 0) {
from = wp->w_old_visual_lnum;
- if (wp->w_old_visual_lnum > to)
+ }
+ if (wp->w_old_visual_lnum > to) {
to = wp->w_old_visual_lnum;
- if (VIsual.lnum < from)
+ }
+ if (VIsual.lnum < from) {
from = VIsual.lnum;
- if (VIsual.lnum > to)
+ }
+ if (VIsual.lnum > to) {
to = VIsual.lnum;
+ }
}
}
@@ -1180,8 +1205,9 @@ static void win_update(win_T *wp, Providers *providers)
colnr_T fromc, toc;
int save_ve_flags = ve_flags;
- if (curwin->w_p_lbr)
+ if (curwin->w_p_lbr) {
ve_flags = VE_ALL;
+ }
getvcols(wp, &VIsual, &curwin->w_cursor, &fromc, &toc);
ve_flags = save_ve_flags;
@@ -1194,16 +1220,18 @@ static void win_update(win_T *wp, Providers *providers)
if (fromc != wp->w_old_cursor_fcol
|| toc != wp->w_old_cursor_lcol) {
- if (from > VIsual.lnum)
+ if (from > VIsual.lnum) {
from = VIsual.lnum;
- if (to < VIsual.lnum)
+ }
+ if (to < VIsual.lnum) {
to = VIsual.lnum;
+ }
}
wp->w_old_cursor_fcol = fromc;
wp->w_old_cursor_lcol = toc;
}
} else {
- /* Use the line numbers of the old Visual area. */
+ // Use the line numbers of the old Visual area.
if (wp->w_old_cursor_lnum < wp->w_old_visual_lnum) {
from = wp->w_old_cursor_lnum;
to = wp->w_old_visual_lnum;
@@ -1216,18 +1244,21 @@ static void win_update(win_T *wp, Providers *providers)
/*
* There is no need to update lines above the top of the window.
*/
- if (from < wp->w_topline)
+ if (from < wp->w_topline) {
from = wp->w_topline;
+ }
/*
* If we know the value of w_botline, use it to restrict the update to
* the lines that are visible in the window.
*/
if (wp->w_valid & VALID_BOTLINE) {
- if (from >= wp->w_botline)
+ if (from >= wp->w_botline) {
from = wp->w_botline - 1;
- if (to >= wp->w_botline)
+ }
+ if (to >= wp->w_botline) {
to = wp->w_botline - 1;
+ }
}
/*
@@ -1243,27 +1274,30 @@ static void win_update(win_T *wp, Providers *providers)
lnum = wp->w_topline;
idx = 0;
srow = 0;
- if (scrolled_down)
+ if (scrolled_down) {
mid_start = top_end;
- else
+ } else {
mid_start = 0;
- while (lnum < from && idx < wp->w_lines_valid) { /* find start */
- if (wp->w_lines[idx].wl_valid)
+ }
+ while (lnum < from && idx < wp->w_lines_valid) { // find start
+ if (wp->w_lines[idx].wl_valid) {
mid_start += wp->w_lines[idx].wl_size;
- else if (!scrolled_down)
+ } else if (!scrolled_down) {
srow += wp->w_lines[idx].wl_size;
+ }
++idx;
- if (idx < wp->w_lines_valid && wp->w_lines[idx].wl_valid)
+ if (idx < wp->w_lines_valid && wp->w_lines[idx].wl_valid) {
lnum = wp->w_lines[idx].wl_lnum;
- else
+ } else {
++lnum;
+ }
}
srow += mid_start;
mid_end = wp->w_grid.Rows;
for (; idx < wp->w_lines_valid; idx++) { // find end
if (wp->w_lines[idx].wl_valid
&& wp->w_lines[idx].wl_lnum >= to + 1) {
- /* Only update until first row of this line */
+ // Only update until first row of this line
mid_end = srow;
break;
}
@@ -1285,7 +1319,7 @@ static void win_update(win_T *wp, Providers *providers)
wp->w_old_visual_col = 0;
}
- /* reset got_int, otherwise regexp won't work */
+ // reset got_int, otherwise regexp won't work
save_got_int = got_int;
got_int = 0;
// Set the time limit to 'redrawtime'.
@@ -1295,7 +1329,7 @@ static void win_update(win_T *wp, Providers *providers)
/*
* Update all the window rows.
*/
- idx = 0; /* first entry in w_lines[].wl_size */
+ idx = 0; // first entry in w_lines[].wl_size
row = 0;
srow = 0;
lnum = wp->w_topline; // first line shown in window
@@ -1335,7 +1369,7 @@ static void win_update(win_T *wp, Providers *providers)
break;
}
- /* stop updating when hit the end of the file */
+ // stop updating when hit the end of the file
if (lnum > buf->b_ml.ml_line_count) {
eof = true;
break;
@@ -1400,8 +1434,9 @@ static void win_update(win_T *wp, Providers *providers)
/* Only valid lines have a meaningful wl_lnum. Invalid
* lines are part of the changed area. */
if (wp->w_lines[i].wl_valid
- && wp->w_lines[i].wl_lnum == mod_bot)
+ && wp->w_lines[i].wl_lnum == mod_bot) {
break;
+ }
old_rows += wp->w_lines[i].wl_size;
if (wp->w_lines[i].wl_valid
&& wp->w_lines[i].wl_lastlnum + 1 == mod_bot) {
@@ -1409,8 +1444,9 @@ static void win_update(win_T *wp, Providers *providers)
* Add following invalid entries. */
++i;
while (i < wp->w_lines_valid
- && !wp->w_lines[i].wl_valid)
+ && !wp->w_lines[i].wl_valid) {
old_rows += wp->w_lines[i++].wl_size;
+ }
break;
}
}
@@ -1473,15 +1509,15 @@ static void win_update(win_T *wp, Providers *providers)
if (j < i) {
int x = row + new_rows;
- /* move entries in w_lines[] upwards */
+ // move entries in w_lines[] upwards
for (;; ) {
- /* stop at last valid entry in w_lines[] */
+ // stop at last valid entry in w_lines[]
if (i >= wp->w_lines_valid) {
wp->w_lines_valid = j;
break;
}
wp->w_lines[j] = wp->w_lines[i];
- /* stop at a line that won't fit */
+ // stop at a line that won't fit
if (x + (int)wp->w_lines[j].wl_size
> wp->w_grid.Rows) {
wp->w_lines_valid = j + 1;
@@ -1490,10 +1526,11 @@ static void win_update(win_T *wp, Providers *providers)
x += wp->w_lines[j++].wl_size;
++i;
}
- if (bot_start > x)
+ if (bot_start > x) {
bot_start = x;
- } else { /* j > i */
- /* move entries in w_lines[] downwards */
+ }
+ } else { // j > i
+ // move entries in w_lines[] downwards
j -= i;
wp->w_lines_valid += j;
if (wp->w_lines_valid > wp->w_grid.Rows) {
@@ -1529,17 +1566,17 @@ static void win_update(win_T *wp, Providers *providers)
&& lnum > wp->w_topline
&& !(dy_flags & (DY_LASTLINE | DY_TRUNCATE))
&& srow + wp->w_lines[idx].wl_size > wp->w_grid.Rows
- && diff_check_fill(wp, lnum) == 0
- ) {
+ && diff_check_fill(wp, lnum) == 0) {
// This line is not going to fit. Don't draw anything here,
// will draw "@ " lines below.
row = wp->w_grid.Rows + 1;
} else {
prepare_search_hl(wp, lnum);
- /* Let the syntax stuff know we skipped a few lines. */
+ // Let the syntax stuff know we skipped a few lines.
if (syntax_last_parsed != 0 && syntax_last_parsed + 1 < lnum
- && syntax_present(wp))
+ && syntax_present(wp)) {
syntax_end_parsing(syntax_last_parsed + 1);
+ }
// Display one line
row = win_line(wp, lnum, srow,
@@ -1603,14 +1640,16 @@ static void win_update(win_T *wp, Providers *providers)
*/
- if (idx > wp->w_lines_valid)
+ if (idx > wp->w_lines_valid) {
wp->w_lines_valid = idx;
+ }
/*
* Let the syntax stuff know we stop parsing here.
*/
- if (syntax_last_parsed != 0 && syntax_present(wp))
+ if (syntax_last_parsed != 0 && syntax_present(wp)) {
syntax_end_parsing(syntax_last_parsed + 1);
+ }
/*
* If we didn't hit the end of the file, and we didn't finish the last
@@ -1656,20 +1695,15 @@ static void win_update(win_T *wp, Providers *providers)
wp->w_botline = buf->b_ml.ml_line_count + 1;
j = diff_check_fill(wp, wp->w_botline);
if (j > 0 && !wp->w_botfill) {
- // display filler lines at the end of the file
- if (char2cells(wp->w_p_fcs_chars.diff) > 1) {
- i = '-';
- } else {
- i = wp->w_p_fcs_chars.diff;
- }
- if (row + j > wp->w_grid.Rows) {
- j = wp->w_grid.Rows - row;
- }
- win_draw_end(wp, i, i, true, row, row + (int)j, HLF_DED);
- row += j;
+ // Display filler text below last line. win_line() will check
+ // for ml_line_count+1 and only draw filler lines
+ foldinfo_T info = FOLDINFO_INIT;
+ row = win_line(wp, wp->w_botline, row, wp->w_grid.Rows,
+ false, false, info, &line_providers);
}
- } else if (dollar_vcol == -1)
+ } else if (dollar_vcol == -1) {
wp->w_botline = lnum;
+ }
// make sure the rest of the screen is blank
// write the 'eob' character to rows that aren't part of the file.
@@ -1684,7 +1718,7 @@ static void win_update(win_T *wp, Providers *providers)
}
syn_set_timeout(NULL);
- /* Reset the type of redrawing required, the window has been updated. */
+ // Reset the type of redrawing required, the window has been updated.
wp->w_redr_type = 0;
wp->w_old_topfill = wp->w_topfill;
wp->w_old_botfill = wp->w_botfill;
@@ -1754,9 +1788,10 @@ static void win_update(win_T *wp, Providers *providers)
}
- /* restore got_int, unless CTRL-C was hit while redrawing */
- if (!got_int)
+ // restore got_int, unless CTRL-C was hit while redrawing
+ if (!got_int) {
got_int = save_got_int;
+ }
} // NOLINT(readability/fn_size)
/// Returns width of the signcolumn that should be used for the whole window
@@ -1776,8 +1811,8 @@ int win_signcol_width(win_T *wp)
/// Call grid_fill() with columns adjusted for 'rightleft' if needed.
/// Return the new offset.
-static int win_fill_end(win_T *wp, int c1, int c2, int off, int width, int row,
- int endrow, int attr)
+static int win_fill_end(win_T *wp, int c1, int c2, int off, int width, int row, int endrow,
+ int attr)
{
int nn = off + width;
@@ -1798,8 +1833,7 @@ static int win_fill_end(win_T *wp, int c1, int c2, int off, int width, int row,
/// Clear lines near the end of the window and mark the unused lines with "c1".
/// Use "c2" as filler character.
/// When "draw_margin" is true, then draw the sign/fold/number columns.
-static void win_draw_end(win_T *wp, int c1, int c2, bool draw_margin, int row,
- int endrow, hlf_T hl)
+static void win_draw_end(win_T *wp, int c1, int c2, bool draw_margin, int row, int endrow, hlf_T hl)
{
assert(hl >= 0 && hl < HLF_COUNT);
int n = 0;
@@ -1844,8 +1878,9 @@ static void win_draw_end(win_T *wp, int c1, int c2, bool draw_margin, int row,
/// @return true when there are columns to draw.
static bool advance_color_col(int vcol, int **color_cols)
{
- while (**color_cols >= 0 && vcol > **color_cols)
+ while (**color_cols >= 0 && vcol > **color_cols) {
++*color_cols;
+ }
return **color_cols >= 0;
}
@@ -1923,13 +1958,7 @@ static int line_putchar(LineState *s, schar_T *dest, int maxcells, bool rl)
///
/// Assume monocell characters
/// @return number of chars added to \param p
-static size_t
-fill_foldcolumn(
- char_u *p,
- win_T *wp,
- foldinfo_T foldinfo,
- linenr_T lnum
-)
+static size_t fill_foldcolumn(char_u *p, win_T *wp, foldinfo_T foldinfo, linenr_T lnum)
{
int i = 0;
int level;
@@ -1998,9 +2027,8 @@ fill_foldcolumn(
/// or explicitly return `false`.
///
/// @return the number of last row the line occupies.
-static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow,
- bool nochange, bool number_only, foldinfo_T foldinfo,
- Providers *providers)
+static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
+ bool number_only, foldinfo_T foldinfo, Providers *providers)
{
int c = 0; // init for GCC
long vcol = 0; // virtual column (for tabs)
@@ -2033,12 +2061,12 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow,
int saved_c_final = 0;
int saved_char_attr = 0;
- int n_attr = 0; /* chars with special attr */
- int saved_attr2 = 0; /* char_attr saved for n_attr */
- int n_attr3 = 0; /* chars with overruling special attr */
- int saved_attr3 = 0; /* char_attr saved for n_attr3 */
+ int n_attr = 0; // chars with special attr
+ int saved_attr2 = 0; // char_attr saved for n_attr
+ int n_attr3 = 0; // chars with overruling special attr
+ int saved_attr3 = 0; // char_attr saved for n_attr3
- int n_skip = 0; /* nr of chars to skip for 'nowrap' */
+ int n_skip = 0; // nr of chars to skip for 'nowrap'
int fromcol = -10; // start of inverting
int tocol = MAXCOL; // end of inverting
@@ -2048,29 +2076,29 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow,
pos_T pos;
long v;
- int char_attr = 0; /* attributes for next character */
- int attr_pri = FALSE; /* char_attr has priority */
+ int char_attr = 0; // attributes for next character
+ int attr_pri = FALSE; // char_attr has priority
int area_highlighting = FALSE; /* Visual or incsearch highlighting
in this line */
- int attr = 0; /* attributes for area highlighting */
- int area_attr = 0; /* attributes desired by highlighting */
- int search_attr = 0; /* attributes desired by 'hlsearch' */
- int vcol_save_attr = 0; /* saved attr for 'cursorcolumn' */
- int syntax_attr = 0; /* attributes desired by syntax */
- int has_syntax = FALSE; /* this buffer has syntax highl. */
+ int attr = 0; // attributes for area highlighting
+ int area_attr = 0; // attributes desired by highlighting
+ int search_attr = 0; // attributes desired by 'hlsearch'
+ int vcol_save_attr = 0; // saved attr for 'cursorcolumn'
+ int syntax_attr = 0; // attributes desired by syntax
+ int has_syntax = FALSE; // this buffer has syntax highl.
int save_did_emsg;
int eol_hl_off = 0; // 1 if highlighted char after EOL
bool draw_color_col = false; // highlight colorcolumn
int *color_cols = NULL; // pointer to according columns array
bool has_spell = false; // this buffer has spell checking
# define SPWORDLEN 150
- char_u nextline[SPWORDLEN * 2]; /* text with start of the next line */
- int nextlinecol = 0; /* column where nextline[] starts */
+ char_u nextline[SPWORDLEN * 2]; // text with start of the next line
+ int nextlinecol = 0; // column where nextline[] starts
int nextline_idx = 0; /* index in nextline[] where next line
starts */
- int spell_attr = 0; /* attributes desired by spelling */
- int word_end = 0; /* last byte with same spell_attr */
- static linenr_T checked_lnum = 0; /* line number for "checked_col" */
+ int spell_attr = 0; // attributes desired by spelling
+ int word_end = 0; // last byte with same spell_attr
+ static linenr_T checked_lnum = 0; // line number for "checked_col"
static int checked_col = 0; /* column in "checked_lnum" up to which
* there are no spell errors */
static int cap_col = -1; // column to check for Cap word
@@ -2122,16 +2150,16 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow,
int left_curline_col = 0;
int right_curline_col = 0;
- /* draw_state: items that are drawn in sequence: */
-#define WL_START 0 /* nothing done yet */
-# define WL_CMDLINE WL_START + 1 /* cmdline window column */
-# define WL_FOLD WL_CMDLINE + 1 /* 'foldcolumn' */
-# define WL_SIGN WL_FOLD + 1 /* column for signs */
-#define WL_NR WL_SIGN + 1 /* line number */
-# define WL_BRI WL_NR + 1 /* 'breakindent' */
-# define WL_SBR WL_BRI + 1 /* 'showbreak' or 'diff' */
-#define WL_LINE WL_SBR + 1 /* text in the line */
- int draw_state = WL_START; /* what to draw next */
+ // draw_state: items that are drawn in sequence:
+#define WL_START 0 // nothing done yet
+# define WL_CMDLINE WL_START + 1 // cmdline window column
+# define WL_FOLD WL_CMDLINE + 1 // 'foldcolumn'
+# define WL_SIGN WL_FOLD + 1 // column for signs
+#define WL_NR WL_SIGN + 1 // line number
+# define WL_BRI WL_NR + 1 // 'breakindent'
+# define WL_SBR WL_BRI + 1 // 'showbreak' or 'diff'
+#define WL_LINE WL_SBR + 1 // text in the line
+ int draw_state = WL_START; // what to draw next
int syntax_flags = 0;
int syntax_seqnr = 0;
@@ -2155,12 +2183,14 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow,
boguscols = 0; \
}
- if (startrow > endrow) /* past the end already! */
+ if (startrow > endrow) { // past the end already!
return startrow;
+ }
row = startrow;
buf_T *buf = wp->w_buffer;
+ bool end_fill = (lnum == buf->b_ml.ml_line_count+1);
if (!number_only) {
// To speed up the loop below, set extra_check when there is linebreak,
@@ -2228,6 +2258,7 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow,
if (wp->w_p_spell
&& !has_fold
+ && !end_fill
&& *wp->w_s->b_p_spl != NUL
&& !GA_EMPTY(&wp->w_s->b_langp)
&& *(char **)(wp->w_s->b_langp.ga_data) != NULL) {
@@ -2327,7 +2358,7 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow,
area_highlighting = true;
attr = win_hl_attr(wp, HLF_V);
}
- // handle 'incsearch' and ":s///c" highlighting
+ // handle 'incsearch' and ":s///c" highlighting
} else if (highlight_match
&& wp == curwin
&& !has_fold
@@ -2356,19 +2387,22 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow,
filler_lines = diff_check(wp, lnum);
if (filler_lines < 0) {
if (filler_lines == -1) {
- if (diff_find_change(wp, lnum, &change_start, &change_end))
- diff_hlf = HLF_ADD; /* added line */
- else if (change_start == 0)
- diff_hlf = HLF_TXD; /* changed text */
- else
- diff_hlf = HLF_CHD; /* changed line */
- } else
- diff_hlf = HLF_ADD; /* added line */
+ if (diff_find_change(wp, lnum, &change_start, &change_end)) {
+ diff_hlf = HLF_ADD; // added line
+ } else if (change_start == 0) {
+ diff_hlf = HLF_TXD; // changed text
+ } else {
+ diff_hlf = HLF_CHD; // changed line
+ }
+ } else {
+ diff_hlf = HLF_ADD; // added line
+ }
filler_lines = 0;
area_highlighting = TRUE;
}
- if (lnum == wp->w_topline)
+ if (lnum == wp->w_topline) {
filler_lines = wp->w_topfill;
+ }
filler_todo = filler_lines;
// Cursor line highlighting for 'cursorline' in the current window.
@@ -2428,7 +2462,7 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow,
line_attr_lowprio_save = line_attr_lowprio;
}
- line = ml_get_buf(wp->w_buffer, lnum, false);
+ line = end_fill ? (char_u *)"" : ml_get_buf(wp->w_buffer, lnum, false);
ptr = line;
if (has_spell && !number_only) {
@@ -2441,7 +2475,7 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow,
* current line into nextline[]. Above the start of the next line was
* copied to nextline[SPWORDLEN]. */
if (nextline[SPWORDLEN] == NUL) {
- /* No next line or it is empty. */
+ // No next line or it is empty.
nextlinecol = MAXCOL;
nextline_idx = 0;
} else {
@@ -2454,7 +2488,7 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow,
STRMOVE(nextline + v, nextline + SPWORDLEN);
nextline_idx = v + 1;
} else {
- /* Long line, use only the last SPWORDLEN bytes. */
+ // Long line, use only the last SPWORDLEN bytes.
nextlinecol = v - SPWORDLEN;
memmove(nextline, line + nextlinecol, SPWORDLEN); // -V512
nextline_idx = SPWORDLEN + 1;
@@ -2462,7 +2496,7 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow,
}
}
- if (wp->w_p_list && !has_fold) {
+ if (wp->w_p_list && !has_fold && !end_fill) {
if (wp->w_p_lcs_chars.space
|| wp->w_p_lcs_chars.trail
|| wp->w_p_lcs_chars.lead
@@ -2475,7 +2509,7 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow,
while (trailcol > (colnr_T)0 && ascii_iswhite(ptr[trailcol - 1])) {
trailcol--;
}
- trailcol += (colnr_T) (ptr - line);
+ trailcol += (colnr_T)(ptr - line);
}
// find end of leading whitespace
if (wp->w_p_lcs_chars.lead) {
@@ -2497,10 +2531,11 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow,
* 'nowrap' or 'wrap' and a single line that doesn't fit: Advance to the
* first character to be displayed.
*/
- if (wp->w_p_wrap)
+ if (wp->w_p_wrap) {
v = wp->w_skipcol;
- else
+ } else {
v = wp->w_leftcol;
+ }
if (v > 0 && !number_only) {
char_u *prev_ptr = ptr;
while (vcol < v && *ptr != NUL) {
@@ -2539,10 +2574,11 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow,
* Adjust for when the inverted text is before the screen,
* and when the start of the inverted text is before the screen.
*/
- if (tocol <= vcol)
+ if (tocol <= vcol) {
fromcol = 0;
- else if (fromcol >= 0 && fromcol < vcol)
+ } else if (fromcol >= 0 && fromcol < vcol) {
fromcol = vcol;
+ }
// When w_skipcol is non-zero, first line needs 'showbreak'
if (wp->w_p_wrap) {
@@ -2570,13 +2606,14 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow,
spell_hlf = HLF_COUNT;
word_end = (int)(spell_to_word_end(ptr, wp) - line + 1);
} else {
- /* bad word found, use attributes until end of word */
+ // bad word found, use attributes until end of word
assert(len <= INT_MAX);
word_end = wp->w_cursor.col + (int)len + 1;
- /* Turn index into actual attributes. */
- if (spell_hlf != HLF_COUNT)
+ // Turn index into actual attributes.
+ if (spell_hlf != HLF_COUNT) {
spell_attr = highlight_attr[spell_hlf];
+ }
}
wp->w_cursor = pos;
@@ -2598,12 +2635,14 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow,
* cursor */
fromcol_prev = fromcol;
fromcol = -1;
- } else if ((colnr_T)fromcol < wp->w_virtcol)
- /* restart highlighting after the cursor */
+ } else if ((colnr_T)fromcol < wp->w_virtcol) {
+ // restart highlighting after the cursor
fromcol_prev = wp->w_virtcol;
+ }
}
- if (fromcol >= tocol)
+ if (fromcol >= tocol) {
fromcol = -1;
+ }
}
/*
@@ -2613,8 +2652,7 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow,
cur = wp->w_match_head;
shl_flag = false;
while ((cur != NULL || !shl_flag) && !number_only
- && !has_fold
- ) {
+ && !has_fold && !end_fill) {
if (!shl_flag) {
shl = &search_hl;
shl_flag = true;
@@ -2647,18 +2685,18 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow,
shl->startcol = 0;
}
if (lnum == shl->lnum + shl->rm.endpos[0].lnum
- - shl->rm.startpos[0].lnum) {
- shl->endcol = shl->rm.endpos[0].col;
+ - shl->rm.startpos[0].lnum) {
+ shl->endcol = shl->rm.endpos[0].col;
} else {
- shl->endcol = MAXCOL;
+ shl->endcol = MAXCOL;
}
// Highlight one character for an empty match.
if (shl->startcol == shl->endcol) {
- if (line[shl->endcol] != NUL) {
- shl->endcol += (*mb_ptr2len)(line + shl->endcol);
- } else {
- ++shl->endcol;
- }
+ if (line[shl->endcol] != NUL) {
+ shl->endcol += (*mb_ptr2len)(line + shl->endcol);
+ } else {
+ ++shl->endcol;
+ }
}
if ((long)shl->startcol < v) { // match at leftcol
shl->attr_cur = shl->attr;
@@ -2667,8 +2705,9 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow,
}
area_highlighting = true;
}
- if (shl != &search_hl && cur != NULL)
+ if (shl != &search_hl && cur != NULL) {
cur = cur->next;
+ }
}
unsigned off = 0; // Offset relative start of line
@@ -2705,7 +2744,7 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow,
if (draw_state == WL_CMDLINE - 1 && n_extra == 0) {
draw_state = WL_CMDLINE;
if (cmdwin_type != 0 && wp == curwin) {
- /* Draw the cmdline character. */
+ // Draw the cmdline character.
n_extra = 1;
c_extra = cmdwin_type;
c_final = NUL;
@@ -2733,18 +2772,17 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow,
// sign column, this is hit until sign_idx reaches count
if (draw_state == WL_SIGN - 1 && n_extra == 0) {
- draw_state = WL_SIGN;
- /* Show the sign column when there are any signs in this
- * buffer or when using Netbeans. */
- int count = win_signcol_count(wp);
- if (count > 0) {
- get_sign_display_info(
- false, wp, sattrs, row,
- startrow, filler_lines, filler_todo, count,
- &c_extra, &c_final, extra, sizeof(extra),
- &p_extra, &n_extra,
- &char_attr, &draw_state, &sign_idx);
- }
+ draw_state = WL_SIGN;
+ /* Show the sign column when there are any signs in this
+ * buffer or when using Netbeans. */
+ int count = win_signcol_count(wp);
+ if (count > 0) {
+ get_sign_display_info(false, wp, sattrs, row,
+ startrow, filler_lines, filler_todo, count,
+ &c_extra, &c_final, extra, sizeof(extra),
+ &p_extra, &n_extra,
+ &char_attr, &draw_state, &sign_idx);
+ }
}
if (draw_state == WL_NR - 1 && n_extra == 0) {
@@ -2760,12 +2798,11 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow,
if (*wp->w_p_scl == 'n' && *(wp->w_p_scl + 1) == 'u'
&& num_signs > 0) {
int count = win_signcol_count(wp);
- get_sign_display_info(
- true, wp, sattrs, row,
- startrow, filler_lines, filler_todo, count,
- &c_extra, &c_final, extra, sizeof(extra),
- &p_extra, &n_extra,
- &char_attr, &draw_state, &sign_idx);
+ get_sign_display_info(true, wp, sattrs, row,
+ startrow, filler_lines, filler_todo, count,
+ &c_extra, &c_final, extra, sizeof(extra),
+ &p_extra, &n_extra,
+ &char_attr, &draw_state, &sign_idx);
} else {
if (row == startrow + filler_lines) {
// Draw the line number (empty space after wrapping). */
@@ -2812,6 +2849,15 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow,
n_extra = number_width(wp) + 1;
char_attr = win_hl_attr(wp, HLF_N);
+ if (wp->w_p_rnu && lnum < wp->w_cursor.lnum) {
+ // Use LineNrAbove
+ char_attr = win_hl_attr(wp, HLF_LNA);
+ }
+ if (wp->w_p_rnu && lnum > wp->w_cursor.lnum) {
+ // Use LineNrBelow
+ char_attr = win_hl_attr(wp, HLF_LNB);
+ }
+
sign_attrs_T *num_sattr = sign_get_attr(SIGN_NUMHL, sattrs, 0, 1);
if (num_sattr != NULL) {
// :sign defined with "numhl" highlight.
@@ -2899,7 +2945,7 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow,
char_attr = win_hl_attr(wp, HLF_DED);
}
if (*p_sbr != NUL && need_showbreak) {
- /* Draw 'showbreak' at the start of each broken line. */
+ // Draw 'showbreak' at the start of each broken line.
p_extra = p_sbr;
c_extra = NUL;
c_final = NUL;
@@ -2911,8 +2957,9 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow,
vcol_sbr = vcol + MB_CHARLEN(p_sbr);
/* Correct end of highlighted area for 'showbreak',
* required when 'linebreak' is also set. */
- if (tocol == vcol)
+ if (tocol == vcol) {
tocol += n_extra;
+ }
// Combine 'showbreak' with 'cursorline', prioritizing 'showbreak'.
if (cul_attr) {
char_attr = hl_combine_attr(cul_attr, char_attr);
@@ -2930,7 +2977,7 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow,
}
if (saved_n_extra) {
- /* Continue item from end of wrapped line. */
+ // Continue item from end of wrapped line.
n_extra = saved_n_extra;
c_extra = saved_c_extra;
c_final = saved_c_final;
@@ -2984,20 +3031,20 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow,
&& vcol == 0
&& n_extra == 0
&& row == startrow) {
- char_attr = win_hl_attr(wp, HLF_FL);
+ char_attr = win_hl_attr(wp, HLF_FL);
- linenr_T lnume = lnum + foldinfo.fi_lines - 1;
- memset(buf_fold, ' ', FOLD_TEXT_LEN);
- p_extra = get_foldtext(wp, lnum, lnume, foldinfo, buf_fold);
- n_extra = STRLEN(p_extra);
+ linenr_T lnume = lnum + foldinfo.fi_lines - 1;
+ memset(buf_fold, ' ', FOLD_TEXT_LEN);
+ p_extra = get_foldtext(wp, lnum, lnume, foldinfo, buf_fold);
+ n_extra = STRLEN(p_extra);
- if (p_extra != buf_fold) {
- xfree(p_extra_free);
- p_extra_free = p_extra;
- }
- c_extra = NUL;
- c_final = NUL;
- p_extra[n_extra] = NUL;
+ if (p_extra != buf_fold) {
+ xfree(p_extra_free);
+ p_extra_free = p_extra;
+ }
+ c_extra = NUL;
+ c_final = NUL;
+ p_extra[n_extra] = NUL;
}
if (draw_state == WL_LINE
@@ -3038,7 +3085,7 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow,
&& (colnr_T)vcol == wp->w_virtcol))) {
area_attr = 0; // stop highlighting
area_active = false;
- }
+ }
if (!n_extra) {
/*
@@ -3063,10 +3110,10 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow,
if (cur != NULL) {
cur->pos.cur = 0;
}
- bool pos_inprogress = true; // mark that a position match search is
- // in progress
+ bool pos_inprogress = true; // mark that a position match search is
+ // in progress
while (shl->rm.regprog != NULL
- || (cur != NULL && pos_inprogress)) {
+ || (cur != NULL && pos_inprogress)) {
if (shl->startcol != MAXCOL
&& v >= (long)shl->startcol
&& v < (long)shl->endcol) {
@@ -3100,10 +3147,11 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow,
if (shl->lnum == lnum) {
shl->startcol = shl->rm.startpos[0].col;
- if (shl->rm.endpos[0].lnum == 0)
+ if (shl->rm.endpos[0].lnum == 0) {
shl->endcol = shl->rm.endpos[0].col;
- else
+ } else {
shl->endcol = MAXCOL;
+ }
if (shl->startcol == shl->endcol) {
// highlight empty match, try again after it
@@ -3117,8 +3165,9 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow,
}
break;
}
- if (shl != &search_hl && cur != NULL)
+ if (shl != &search_hl && cur != NULL) {
cur = cur->next;
+ }
}
/* Use attributes from match with highest priority among
@@ -3139,8 +3188,9 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow,
search_attr = shl->attr_cur;
search_attr_from_match = shl != &search_hl;
}
- if (shl != &search_hl && cur != NULL)
+ if (shl != &search_hl && cur != NULL) {
cur = cur->next;
+ }
}
// Only highlight one character after the last column.
if (*ptr == NUL
@@ -3403,8 +3453,9 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow,
if (did_emsg) {
wp->w_s->b_syn_error = TRUE;
has_syntax = FALSE;
- } else
+ } else {
did_emsg = save_did_emsg;
+ }
// Need to get the line again, a multi-line regexp may
// have made it invalid.
@@ -3484,9 +3535,10 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow,
checked_col = (int)((p - nextline) + len - nextline_idx);
}
- /* Turn index into actual attributes. */
- if (spell_hlf != HLF_COUNT)
+ // Turn index into actual attributes.
+ if (spell_hlf != HLF_COUNT) {
spell_attr = highlight_attr[spell_hlf];
+ }
if (cap_col > 0) {
if (p != prev_ptr
@@ -3496,17 +3548,19 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow,
capcol_lnum = lnum + 1;
cap_col = (int)((p - nextline) + cap_col
- nextline_idx);
- } else
- /* Compute the actual column. */
+ } else {
+ // Compute the actual column.
cap_col += (int)(prev_ptr - line);
+ }
}
}
}
if (spell_attr != 0) {
- if (!attr_pri)
+ if (!attr_pri) {
char_attr = hl_combine_attr(char_attr, spell_attr);
- else
+ } else {
char_attr = hl_combine_attr(spell_attr, char_attr);
+ }
}
if (wp->w_buffer->terminal) {
@@ -3541,9 +3595,10 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow,
c_extra = mb_off > 0 ? MB_FILLER_CHAR : ' ';
c_final = NUL;
if (ascii_iswhite(c)) {
- if (c == TAB)
- /* See "Tab alignment" below. */
+ if (c == TAB) {
+ // See "Tab alignment" below.
FIX_FOR_BOGUSCOLS;
+ }
if (!wp->w_p_list) {
c = ' ';
}
@@ -3690,7 +3745,7 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow,
? wp->w_p_lcs_chars.tab3
: wp->w_p_lcs_chars.tab1;
if (wp->w_p_lbr) {
- c_extra = NUL; /* using p_extra from above */
+ c_extra = NUL; // using p_extra from above
} else {
c_extra = wp->w_p_lcs_chars.tab2;
}
@@ -3756,10 +3811,11 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow,
} else if (c != NUL) {
p_extra = transchar_buf(wp->w_buffer, c);
if (n_extra == 0) {
- n_extra = byte2cells(c) - 1;
+ n_extra = byte2cells(c) - 1;
+ }
+ if ((dy_flags & DY_UHEX) && wp->w_p_rl) {
+ rl_mirror(p_extra); // reverse "<12>"
}
- if ((dy_flags & DY_UHEX) && wp->w_p_rl)
- rl_mirror(p_extra); /* reverse "<12>" */
c_extra = NUL;
c_final = NUL;
if (wp->w_p_lbr) {
@@ -3817,8 +3873,9 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow,
prev_syntax_id = syntax_seqnr;
- if (n_extra > 0)
+ if (n_extra > 0) {
vcol_off += n_extra;
+ }
vcol += n_extra;
if (wp->w_p_wrap && n_extra > 0) {
if (wp->w_p_rl) {
@@ -3944,8 +4001,9 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow,
int n = 0;
if (wp->w_p_rl) {
- if (col < 0)
+ if (col < 0) {
n = 1;
+ }
} else {
if (col >= grid->Columns) {
n = -1;
@@ -4006,16 +4064,18 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow,
v = wp->w_leftcol;
}
- /* check if line ends before left margin */
- if (vcol < v + col - win_col_off(wp))
+ // check if line ends before left margin
+ if (vcol < v + col - win_col_off(wp)) {
vcol = v + col - win_col_off(wp);
+ }
// Get rid of the boguscols now, we want to draw until the right
// edge for 'cursorcolumn'.
col -= boguscols;
// boguscols = 0; // Disabled because value never read after this
- if (draw_color_col)
+ if (draw_color_col) {
draw_color_col = advance_color_col(VCOL_HLC, &color_cols);
+ }
bool has_virttext = false;
// Make sure alignment is the same regardless
@@ -4226,7 +4286,7 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow,
tocol++;
}
if (wp->w_p_rl) {
- /* now it's time to backup one cell */
+ // now it's time to backup one cell
--off;
--col;
}
@@ -4241,8 +4301,9 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow,
} else if (wp->w_p_cole > 0 && is_concealing) {
--n_skip;
++vcol_off;
- if (n_extra > 0)
+ if (n_extra > 0) {
vcol_off += n_extra;
+ }
if (wp->w_p_wrap) {
/*
* Special voodoo required if 'wrap' is on.
@@ -4296,27 +4357,30 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow,
n_attr = 0;
}
}
-
- } else
+ } else {
--n_skip;
+ }
/* Only advance the "vcol" when after the 'number' or 'relativenumber'
* column. */
if (draw_state > WL_NR
- && filler_todo <= 0
- )
+ && filler_todo <= 0) {
++vcol;
+ }
- if (vcol_save_attr >= 0)
+ if (vcol_save_attr >= 0) {
char_attr = vcol_save_attr;
+ }
- /* restore attributes after "predeces" in 'listchars' */
- if (draw_state > WL_NR && n_attr3 > 0 && --n_attr3 == 0)
+ // restore attributes after "predeces" in 'listchars'
+ if (draw_state > WL_NR && n_attr3 > 0 && --n_attr3 == 0) {
char_attr = saved_attr3;
+ }
- /* restore attributes after last 'listchars' or 'number' char */
- if (n_attr > 0 && draw_state == WL_LINE && --n_attr == 0)
+ // restore attributes after last 'listchars' or 'number' char
+ if (n_attr > 0 && draw_state == WL_LINE && --n_attr == 0) {
char_attr = saved_attr2;
+ }
/*
* At end of screen line and there is more to come: Display the line
@@ -4328,15 +4392,15 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow,
|| 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.
- && row != endrow - 1 // Not the last line being displayed.
- && (grid->Columns == Columns // Window spans the width of the screen,
- || ui_has(kUIMultigrid)) // or has dedicated grid.
- && !wp->w_p_rl; // Not right-to-left.
+ && filler_todo <= 0 // Not drawing diff filler lines.
+ && lcs_eol_one != -1 // Haven't printed the lcs_eol character.
+ && row != endrow - 1 // Not the last line being displayed.
+ && (grid->Columns == Columns // Window spans the width of the screen,
+ || ui_has(kUIMultigrid)) // or has dedicated grid.
+ && !wp->w_p_rl; // Not right-to-left.
int draw_col = col - boguscols;
draw_virt_text(buf, win_col_offset, &draw_col, grid->Columns);
@@ -4361,8 +4425,9 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow,
* '$' and highlighting until last column, break here. */
if ((!wp->w_p_wrap
&& filler_todo <= 0
- ) || lcs_eol_one == -1)
+ ) || lcs_eol_one == -1) {
break;
+ }
// When the window is too narrow draw all "@" lines.
if (draw_state != WL_LINE && filler_todo <= 0) {
@@ -4370,7 +4435,7 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow,
row = endrow;
}
- /* When line got too long for screen break here. */
+ // When line got too long for screen break here.
if (row == endrow) {
++row;
break;
@@ -4383,7 +4448,7 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow,
off += col;
}
- /* reset the drawing state for the start of a wrapped line */
+ // reset the drawing state for the start of a wrapped line
draw_state = WL_START;
saved_n_extra = n_extra;
saved_p_extra = p_extra;
@@ -4398,14 +4463,13 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow,
filler_todo--;
// When the filler lines are actually below the last line of the
// file, don't draw the line itself, break here.
- if (filler_todo == 0 && wp->w_botfill) {
+ if (filler_todo == 0 && (wp->w_botfill || end_fill)) {
break;
}
}
+ } // for every character in the line
- } /* for every character in the line */
-
- /* After an empty line check first word for capital. */
+ // After an empty line check first word for capital.
if (*skipwhite(line) == NUL) {
capcol_lnum = lnum + 1;
cap_col = 0;
@@ -4511,25 +4575,11 @@ void screen_adjust_grid(ScreenGrid **grid, int *row_off, int *col_off)
// @param count max number of signs
// @param[out] n_extrap number of characters from pp_extra to display
// @param[in, out] sign_idxp Index of the displayed sign
-static void get_sign_display_info(
- bool nrcol,
- win_T *wp,
- sign_attrs_T sattrs[],
- int row,
- int startrow,
- int filler_lines,
- int filler_todo,
- int count,
- int *c_extrap,
- int *c_finalp,
- char_u *extra,
- size_t extra_size,
- char_u **pp_extra,
- int *n_extrap,
- int *char_attrp,
- int *draw_statep,
- int *sign_idxp
-)
+static void get_sign_display_info(bool nrcol, win_T *wp, sign_attrs_T sattrs[], int row,
+ int startrow, int filler_lines, int filler_todo, int count,
+ int *c_extrap, int *c_finalp, char_u *extra, size_t extra_size,
+ char_u **pp_extra, int *n_extrap, int *char_attrp,
+ int *draw_statep, int *sign_idxp)
{
// Draw cells with the sign value or blank.
*c_extrap = ' ';
@@ -4567,7 +4617,7 @@ static void get_sign_display_info(
assert((size_t)win_signcol_width(wp) >= mb_string2cells(*pp_extra));
// symbol(s) bytes + (filling spaces) (one byte each)
*n_extrap = symbol_blen +
- (win_signcol_width(wp) - mb_string2cells(*pp_extra));
+ (win_signcol_width(wp) - mb_string2cells(*pp_extra));
assert(extra_size > (size_t)symbol_blen);
memset(extra, ' ', extra_size);
@@ -4597,8 +4647,7 @@ static void get_sign_display_info(
* - the character is multi-byte and the next byte is different
* - the character is two cells wide and the second cell differs.
*/
-static int grid_char_needs_redraw(ScreenGrid *grid, int off_from, int off_to,
- int cols)
+static int grid_char_needs_redraw(ScreenGrid *grid, int off_from, int off_to, int cols)
{
return (cols > 0
&& ((schar_cmp(linebuf_char[off_from], grid->chars[off_to])
@@ -4620,9 +4669,8 @@ static int grid_char_needs_redraw(ScreenGrid *grid, int off_from, int off_to,
/// When FALSE and "clear_width" > 0, clear columns "endcol" to "clear_width"
/// If "wrap" is true, then hint to the UI that "row" contains a line
/// which has wrapped into the next row.
-static void grid_put_linebuf(ScreenGrid *grid, int row, int coloff, int endcol,
- int clear_width, int rlflag, win_T *wp,
- int bg_attr, bool wrap)
+static void grid_put_linebuf(ScreenGrid *grid, int row, int coloff, int endcol, int clear_width,
+ int rlflag, win_T *wp, int bg_attr, bool wrap)
{
unsigned off_from;
unsigned off_to;
@@ -4659,12 +4707,11 @@ static void grid_put_linebuf(ScreenGrid *grid, int row, int coloff, int endcol,
max_off_to = grid->line_offset[row] + grid->Columns;
if (rlflag) {
- /* Clear rest first, because it's left of the text. */
+ // Clear rest first, because it's left of the text.
if (clear_width > 0) {
while (col <= endcol && grid->chars[off_to][0] == ' '
&& grid->chars[off_to][1] == NUL
- && grid->attrs[off_to] == bg_attr
- ) {
+ && grid->attrs[off_to] == bg_attr) {
++off_to;
++col;
}
@@ -4805,7 +4852,6 @@ void rl_mirror(char_u *str)
*/
void status_redraw_all(void)
{
-
FOR_ALL_WINDOWS_IN_TAB(wp, curtab) {
if (wp->w_status_height) {
wp->w_redr_status = true;
@@ -4841,8 +4887,9 @@ void redraw_statuslines(void)
win_redr_status(wp);
}
}
- if (redraw_tabline)
+ if (redraw_tabline) {
draw_tabline();
+ }
}
/*
@@ -4894,9 +4941,10 @@ static int status_match_len(expand_T *xp, char_u *s)
int emenu = (xp->xp_context == EXPAND_MENUS
|| xp->xp_context == EXPAND_MENUNAMES);
- /* Check for menu separators - replace with '|'. */
- if (emenu && menu_is_separator(s))
+ // Check for menu separators - replace with '|'.
+ if (emenu && menu_is_separator(s)) {
return 1;
+ }
while (*s != NUL) {
s += skip_status_match_char(xp, s);
@@ -4916,11 +4964,12 @@ 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] == '!')
+ if (xp->xp_shell && csh_like_shell() && s[1] == '\\' && s[2] == '!') {
return 2;
+ }
#endif
return 1;
}
@@ -4934,20 +4983,14 @@ static int skip_status_match_char(expand_T *xp, char_u *s)
*
* If inversion is possible we use it. Else '=' characters are used.
*/
-void
-win_redr_status_matches (
- expand_T *xp,
- int num_matches,
- char_u **matches, /* list of matches */
- int match,
- int showtail
-)
+void win_redr_status_matches(expand_T *xp, int num_matches, char_u **matches, // list of matches
+ int match, int showtail)
{
#define L_MATCH(m) (showtail ? sm_gettail(matches[m], false) : matches[m])
int row;
char_u *buf;
int len;
- int clen; /* length in screen cells */
+ int clen; // length in screen cells
int fillchar;
int attr;
int i;
@@ -4961,33 +5004,36 @@ win_redr_status_matches (
int emenu;
int l;
- if (matches == NULL) /* interrupted completion? */
+ if (matches == NULL) { // interrupted completion?
return;
+ }
buf = xmalloc(Columns * MB_MAXBYTES + 1);
- if (match == -1) { /* don't show match but original text */
+ if (match == -1) { // don't show match but original text
match = 0;
highlight = false;
}
- /* count 1 for the ending ">" */
+ // count 1 for the ending ">"
clen = status_match_len(xp, L_MATCH(match)) + 3;
- if (match == 0)
+ if (match == 0) {
first_match = 0;
- else if (match < first_match) {
- /* jumping left, as far as we can go */
+ } else if (match < first_match) {
+ // jumping left, as far as we can go
first_match = match;
add_left = true;
} else {
- /* check if match fits on the screen */
- for (i = first_match; i < match; ++i)
+ // check if match fits on the screen
+ for (i = first_match; i < match; ++i) {
clen += status_match_len(xp, L_MATCH(i)) + 2;
- if (first_match > 0)
+ }
+ if (first_match > 0) {
clen += 2;
+ }
// jumping right, put match at the left
if ((long)clen > Columns) {
first_match = match;
- /* if showing the last match, we can add some on the left */
+ // if showing the last match, we can add some on the left
clen = 2;
for (i = match; i < num_matches; ++i) {
clen += status_match_len(xp, L_MATCH(i)) + 2;
@@ -5000,7 +5046,7 @@ win_redr_status_matches (
}
}
}
- if (add_left)
+ if (add_left) {
while (first_match > 0) {
clen += status_match_len(xp, L_MATCH(first_match - 1)) + 2;
if ((long)clen >= Columns) {
@@ -5008,6 +5054,7 @@ win_redr_status_matches (
}
first_match--;
}
+ }
fillchar = fillchar_status(&attr, curwin);
@@ -5028,7 +5075,7 @@ win_redr_status_matches (
}
s = L_MATCH(i);
- /* Check for menu separators - replace with '|' */
+ // Check for menu separators - replace with '|'
emenu = (xp->xp_context == EXPAND_MENUS
|| xp->xp_context == EXPAND_MENUNAMES);
if (emenu && menu_is_separator(s)) {
@@ -5036,7 +5083,7 @@ win_redr_status_matches (
l = (int)STRLEN(buf + len);
len += l;
clen += l;
- } else
+ } else {
for (; *s != NUL; ++s) {
s += skip_status_match_char(xp, s);
clen += ptr2cells(s);
@@ -5049,14 +5096,17 @@ win_redr_status_matches (
len += (int)STRLEN(buf + len);
}
}
- if (i == match)
+ }
+ if (i == match) {
selend = buf + len;
+ }
*(buf + len++) = ' ';
*(buf + len++) = ' ';
clen += 2;
- if (++i == num_matches)
+ if (++i == num_matches) {
break;
+ }
}
if (i != num_matches) {
@@ -5145,7 +5195,7 @@ static void win_redr_status(win_T *wp)
// popup menu is visible and may be drawn over it
wp->w_redr_status = true;
} else if (*p_stl != NUL || *wp->w_p_stl != NUL) {
- /* redraw custom status line */
+ // redraw custom status line
redraw_custom_statusline(wp);
} else {
fillchar = fillchar_status(&attr, wp);
@@ -5210,9 +5260,10 @@ static void win_redr_status(win_T *wp)
this_ru_col + wp->w_wincol, fillchar, fillchar, attr);
if (get_keymap_str(wp, (char_u *)"<%s>", NameBuff, MAXPATHL)
- && this_ru_col - len > (int)(STRLEN(NameBuff) + 1))
+ && this_ru_col - len > (int)(STRLEN(NameBuff) + 1)) {
grid_puts(&default_grid, NameBuff, row,
(int)(this_ru_col - STRLEN(NameBuff) - 1), attr);
+ }
win_redr_ruler(wp, true);
}
@@ -5242,8 +5293,9 @@ static void redraw_custom_statusline(win_T *wp)
/* When called recursively return. This can happen when the statusline
* contains an expression that triggers a redraw. */
- if (entered)
+ if (entered) {
return;
+ }
entered = true;
did_emsg = false;
@@ -5271,8 +5323,9 @@ bool stl_connected(win_T *wp)
fr = wp->w_frame;
while (fr->fr_parent != NULL) {
if (fr->fr_parent->fr_layout == FR_COL) {
- if (fr->fr_next != NULL)
+ if (fr->fr_next != NULL) {
break;
+ }
} else {
if (fr->fr_next != NULL) {
return true;
@@ -5304,7 +5357,7 @@ bool get_keymap_str(win_T *wp, char_u *fmt, char_u *buf, int len)
curbuf = wp->w_buffer;
curwin = wp;
- STRCPY(buf, "b:keymap_name"); /* must be writable */
+ STRCPY(buf, "b:keymap_name"); // must be writable
++emsg_skip;
s = p = eval_to_string(buf, NULL, FALSE);
--emsg_skip;
@@ -5329,11 +5382,7 @@ bool get_keymap_str(win_T *wp, char_u *fmt, char_u *buf, int len)
* Redraw the status line or ruler of window "wp".
* When "wp" is NULL redraw the tab pages line from 'tabline'.
*/
-static void
-win_redr_custom (
- win_T *wp,
- bool draw_ruler
-)
+static void win_redr_custom(win_T *wp, bool draw_ruler)
{
static bool entered = false;
int attr;
@@ -5359,13 +5408,14 @@ win_redr_custom (
/* There is a tiny chance that this gets called recursively: When
* redrawing a status line triggers redrawing the ruler or tabline.
* Avoid trouble by not allowing recursion. */
- if (entered)
+ if (entered) {
return;
+ }
entered = true;
- /* setup environment for the task at hand */
+ // setup environment for the task at hand
if (wp == NULL) {
- /* Use 'tabline'. Always at the first line of the screen. */
+ // Use 'tabline'. Always at the first line of the screen.
stl = p_tal;
row = 0;
fillchar = ' ';
@@ -5379,15 +5429,19 @@ win_redr_custom (
if (draw_ruler) {
stl = p_ruf;
- /* advance past any leading group spec - implicit in ru_col */
+ // advance past any leading group spec - implicit in ru_col
if (*stl == '%') {
- if (*++stl == '-')
+ if (*++stl == '-') {
stl++;
- if (atoi((char *)stl))
- while (ascii_isdigit(*stl))
+ }
+ if (atoi((char *)stl)) {
+ while (ascii_isdigit(*stl)) {
stl++;
- if (*stl++ != '(')
+ }
+ }
+ if (*stl++ != '(') {
stl = p_ruf;
+ }
}
col = ru_col - (Columns - wp->w_width);
if (col < (wp->w_width + 1) / 2) {
@@ -5404,19 +5458,21 @@ win_redr_custom (
use_sandbox = was_set_insecurely(wp, (char_u *)"rulerformat", 0);
} else {
- if (*wp->w_p_stl != NUL)
+ if (*wp->w_p_stl != NUL) {
stl = wp->w_p_stl;
- else
+ } else {
stl = p_stl;
- use_sandbox = was_set_insecurely(
- wp, (char_u *)"statusline", *wp->w_p_stl == NUL ? 0 : OPT_LOCAL);
+ }
+ use_sandbox = was_set_insecurely(wp, (char_u *)"statusline",
+ *wp->w_p_stl == NUL ? 0 : OPT_LOCAL);
}
col += wp->w_wincol;
}
- if (maxwidth <= 0)
+ if (maxwidth <= 0) {
goto theend;
+ }
/* Temporarily reset 'cursorbind', we don't want a side effect from moving
* the cursor away and back. */
@@ -5439,7 +5495,7 @@ win_redr_custom (
len = (size_t)len < sizeof(buf) ? len : (int)sizeof(buf) - 1;
xfree(p);
- /* fill up with "fillchar" */
+ // fill up with "fillchar"
while (width < maxwidth && len < (int)sizeof(buf) - 1) {
len += utf_char2bytes(fillchar, buf + len);
width++;
@@ -5459,14 +5515,15 @@ win_redr_custom (
col += vim_strnsize(p, textlen);
p = hltab[n].start;
- if (hltab[n].userhl == 0)
+ if (hltab[n].userhl == 0) {
curattr = attr;
- else if (hltab[n].userhl < 0)
+ } else if (hltab[n].userhl < 0) {
curattr = syn_id2attr(-hltab[n].userhl);
- else if (wp != NULL && wp != curwin && wp->w_status_height != 0)
+ } else if (wp != NULL && wp != curwin && wp->w_status_height != 0) {
curattr = highlight_stlnc[hltab[n].userhl - 1];
- else
+ } else {
curattr = highlight_user[hltab[n].userhl - 1];
+ }
}
// Make sure to use an empty string instead of p, if p is beyond buf + len.
grid_puts(grid, p >= buf + len ? (char_u *)"" : p, row, col,
@@ -5483,11 +5540,11 @@ win_redr_custom (
.type = kStlClickDisabled,
};
for (n = 0; tabtab[n].start != NULL; n++) {
- len += vim_strnsize(p, (int)(tabtab[n].start - (char *) p));
+ len += vim_strnsize(p, (int)(tabtab[n].start - (char *)p));
while (col < len) {
tab_page_click_defs[col++] = cur_click_def;
}
- p = (char_u *) tabtab[n].start;
+ p = (char_u *)tabtab[n].start;
cur_click_def = tabtab[n].def;
}
while (col < Columns) {
@@ -5651,8 +5708,7 @@ void grid_putchar(ScreenGrid *grid, int c, int row, int col, int attr)
/// get a single character directly from grid.chars into "bytes[]".
/// Also return its attribute in *attrp;
-void grid_getbytes(ScreenGrid *grid, int row, int col, char_u *bytes,
- int *attrp)
+void grid_getbytes(ScreenGrid *grid, int row, int col, char_u *bytes, int *attrp)
{
unsigned off;
@@ -5699,19 +5755,18 @@ void grid_put_schar(ScreenGrid *grid, int row, int col, char_u *schar, int attr)
assert(put_dirty_row == row);
unsigned int off = grid->line_offset[row] + col;
if (grid->attrs[off] != attr || schar_cmp(grid->chars[off], schar)) {
- schar_copy(grid->chars[off], schar);
- grid->attrs[off] = attr;
+ schar_copy(grid->chars[off], schar);
+ grid->attrs[off] = attr;
- put_dirty_first = MIN(put_dirty_first, col);
- // TODO(bfredl): Y U NO DOUBLEWIDTH?
- put_dirty_last = MAX(put_dirty_last, col+1);
+ put_dirty_first = MIN(put_dirty_first, col);
+ // TODO(bfredl): Y U NO DOUBLEWIDTH?
+ put_dirty_last = MAX(put_dirty_last, col+1);
}
}
/// like grid_puts(), but output "text[len]". When "len" is -1 output up to
/// a NUL.
-void grid_puts_len(ScreenGrid *grid, char_u *text, int textlen, int row,
- int col, int attr)
+void grid_puts_len(ScreenGrid *grid, char_u *text, int textlen, int row, int col, int attr)
{
unsigned off;
char_u *ptr = text;
@@ -5723,7 +5778,7 @@ void grid_puts_len(ScreenGrid *grid, char_u *text, int textlen, int row,
int u8c = 0;
int u8cc[MAX_MCO];
int clear_next_cell = FALSE;
- int prev_c = 0; /* previous Arabic character */
+ int prev_c = 0; // previous Arabic character
int pc, nc, nc1;
int pcc[MAX_MCO];
int need_redraw;
@@ -5816,7 +5871,7 @@ void grid_puts_len(ScreenGrid *grid, char_u *text, int textlen, int row,
if (clear_next_cell) {
clear_next_cell = false;
} else if ((len < 0 ? ptr[mbyte_blen] == NUL
- : ptr + mbyte_blen >= text + len)
+ : ptr + mbyte_blen >= text + len)
&& ((mbyte_cells == 1
&& grid_off2cells(grid, off, max_off) > 1)
|| (mbyte_cells == 2
@@ -5915,10 +5970,11 @@ static void init_search_hl(win_T *wp)
matchitem_T *cur = wp->w_match_head;
while (cur != NULL) {
cur->hl.rm = cur->match;
- if (cur->hlg_id == 0)
+ if (cur->hlg_id == 0) {
cur->hl.attr = 0;
- else
+ } else {
cur->hl.attr = syn_id2attr(cur->hlg_id);
+ }
cur->hl.buf = wp->w_buffer;
cur->hl.lnum = 0;
cur->hl.first_lnum = 0;
@@ -5972,8 +6028,8 @@ static void prepare_search_hl(win_T *wp, linenr_T lnum)
if (cur != NULL) {
cur->pos.cur = 0;
}
- bool pos_inprogress = true; // mark that a position match search is
- // in progress
+ bool pos_inprogress = true; // mark that a position match search is
+ // in progress
int n = 0;
while (shl->first_lnum < lnum && (shl->rm.regprog != NULL
|| (cur != NULL && pos_inprogress))) {
@@ -5991,8 +6047,9 @@ static void prepare_search_hl(win_T *wp, linenr_T lnum)
}
}
}
- if (shl != &search_hl && cur != NULL)
+ if (shl != &search_hl && cur != NULL) {
cur = cur->next;
+ }
}
}
@@ -6004,14 +6061,10 @@ static void prepare_search_hl(win_T *wp, linenr_T lnum)
* shl->lnum is zero.
* Careful: Any pointers for buffer lines will become invalid.
*/
-static void
-next_search_hl (
- win_T *win,
- match_T *shl, /* points to search_hl or a match */
- linenr_T lnum,
- colnr_T mincol, /* minimal column for a match */
- matchitem_T *cur /* to retrieve match positions if any */
-)
+static void next_search_hl(win_T *win, match_T *shl, // points to search_hl or a match
+ linenr_T lnum, colnr_T mincol, // minimal column for a match
+ matchitem_T *cur // to retrieve match positions if any
+ )
FUNC_ATTR_NONNULL_ARG(2)
{
linenr_T l;
@@ -6031,10 +6084,11 @@ next_search_hl (
// 2. If the previous match includes "mincol", use it.
// 3. Continue after the previous match.
l = shl->lnum + shl->rm.endpos[0].lnum - shl->rm.startpos[0].lnum;
- if (lnum > l)
+ if (lnum > l) {
shl->lnum = 0;
- else if (lnum < l || shl->rm.endpos[0].col > mincol)
+ } else if (lnum < l || shl->rm.endpos[0].col > mincol) {
return;
+ }
}
/*
@@ -6045,7 +6099,7 @@ next_search_hl (
for (;; ) {
// Stop searching after passing the time limit.
if (profile_passed_limit(shl->tm)) {
- shl->lnum = 0; /* no match found in time */
+ shl->lnum = 0; // no match found in time
break;
}
// Three situations:
@@ -6097,7 +6151,7 @@ next_search_hl (
}
shl->rm.regprog = NULL;
shl->lnum = 0;
- got_int = FALSE; // avoid the "Type :quit to exit Vim" message
+ got_int = FALSE; // avoid the "Type :quit to exit Vim" message
break;
}
} else if (cur != NULL) {
@@ -6122,13 +6176,10 @@ next_search_hl (
/// If there is a match fill "shl" and return one.
/// Return zero otherwise.
-static int
-next_search_hl_pos(
- match_T *shl, // points to a match
- linenr_T lnum,
- posmatch_T *posmatch, // match positions
- colnr_T mincol // minimal column for a match
-)
+static int next_search_hl_pos(match_T *shl, // points to a match
+ linenr_T lnum, posmatch_T *posmatch, // match positions
+ colnr_T mincol // minimal column for a match
+ )
FUNC_ATTR_NONNULL_ALL
{
int i;
@@ -6182,8 +6233,8 @@ next_search_hl_pos(
/// Fill the grid from 'start_row' to 'end_row', from 'start_col' to 'end_col'
/// with character 'c1' in first column followed by 'c2' in the other columns.
/// Use attributes 'attr'.
-void grid_fill(ScreenGrid *grid, int start_row, int end_row, int start_col,
- int end_col, int c1, int c2, int attr)
+void grid_fill(ScreenGrid *grid, int start_row, int end_row, int start_col, int end_col, int c1,
+ int c2, int attr)
{
schar_T sc;
@@ -6421,9 +6472,9 @@ retry:
msg_grid_invalid = true;
}
- win_new_shellsize(); /* fit the windows in the new sized shell */
+ win_new_shellsize(); // fit the windows in the new sized shell
- comp_col(); /* recompute columns for shown command and ruler */
+ comp_col(); // recompute columns for shown command and ruler
// We're changing the size of the screen.
// - Allocate new arrays for default_grid
@@ -6436,8 +6487,8 @@ retry:
// size is wrong.
grid_alloc(&default_grid, Rows, Columns, true, true);
- StlClickDefinition *new_tab_page_click_defs = xcalloc(
- (size_t)Columns, sizeof(*new_tab_page_click_defs));
+ StlClickDefinition *new_tab_page_click_defs =
+ xcalloc((size_t)Columns, sizeof(*new_tab_page_click_defs));
clear_tab_page_click_defs(tab_page_click_defs, tab_page_click_defs_size);
xfree(tab_page_click_defs);
@@ -6545,8 +6596,7 @@ void screen_free_all_mem(void)
///
/// @param[out] tpcd Table to clear.
/// @param[in] tpcd_size Size of the table.
-void clear_tab_page_click_defs(StlClickDefinition *const tpcd,
- const long tpcd_size)
+void clear_tab_page_click_defs(StlClickDefinition *const tpcd, const long tpcd_size)
{
if (tpcd != NULL) {
for (long i = 0; i < tpcd_size; i++) {
@@ -6554,7 +6604,7 @@ void clear_tab_page_click_defs(StlClickDefinition *const tpcd,
xfree(tpcd[i].func);
}
}
- memset(tpcd, 0, (size_t) tpcd_size * sizeof(tpcd[0]));
+ memset(tpcd, 0, (size_t)tpcd_size * sizeof(tpcd[0]));
}
}
@@ -6659,8 +6709,8 @@ void setcursor(void)
// With 'rightleft' set and the cursor on a double-wide character,
// position it on the leftmost column.
col = curwin->w_width_inner - curwin->w_wcol
- - ((utf_ptr2cells(get_cursor_pos_ptr()) == 2
- && vim_isprintc(gchar_cursor())) ? 2 : 1);
+ - ((utf_ptr2cells(get_cursor_pos_ptr()) == 2
+ && vim_isprintc(gchar_cursor())) ? 2 : 1);
}
screen_adjust_grid(&grid, &row, &col);
@@ -6709,8 +6759,7 @@ void win_scroll_lines(win_T *wp, int row, int line_count)
/// 'col' is the column from with we start inserting.
//
/// 'row', 'col' and 'end' are relative to the start of the region.
-void grid_ins_lines(ScreenGrid *grid, int row, int line_count, int end, int col,
- int width)
+void grid_ins_lines(ScreenGrid *grid, int row, int line_count, int end, int col, int width)
{
int i;
int j;
@@ -6761,8 +6810,7 @@ void grid_ins_lines(ScreenGrid *grid, int row, int line_count, int end, int col,
/// 'end' is the line after the scrolled part. Normally it is Rows.
/// When scrolling region used 'off' is the offset from the top for the region.
/// 'row' and 'end' are relative to the start of the region.
-void grid_del_lines(ScreenGrid *grid, int row, int line_count, int end, int col,
- int width)
+void grid_del_lines(ScreenGrid *grid, int row, int line_count, int end, int col, int width)
{
int j;
int i;
@@ -6850,16 +6898,16 @@ int showmode(void)
bool nwr_save = need_wait_return;
- /* wait a bit before overwriting an important message */
+ // wait a bit before overwriting an important message
check_for_delay(FALSE);
- /* if the cmdline is more than one line high, erase top lines */
+ // if the cmdline is more than one line high, erase top lines
need_clear = clear_cmdline;
if (clear_cmdline && cmdline_row < Rows - 1) {
msg_clr_cmdline(); // will reset clear_cmdline
}
- /* Position on the last line in the window, column 0 */
+ // Position on the last line in the window, column 0
msg_pos_mode();
attr = HL_ATTR(HLF_CM); // Highlight mode
@@ -6885,8 +6933,9 @@ int showmode(void)
length -= vim_strsize(edit_submode_extra);
}
if (length > 0) {
- if (edit_submode_pre != NULL)
+ if (edit_submode_pre != NULL) {
length -= vim_strsize(edit_submode_pre);
+ }
if (length - vim_strsize(edit_submode) > 0) {
if (edit_submode_pre != NULL) {
msg_puts_attr((const char *)edit_submode_pre, attr);
@@ -6906,13 +6955,14 @@ int showmode(void)
} else {
if (State & TERM_FOCUS) {
MSG_PUTS_ATTR(_(" TERMINAL"), attr);
- } else if (State & VREPLACE_FLAG)
+ } else if (State & VREPLACE_FLAG) {
MSG_PUTS_ATTR(_(" VREPLACE"), attr);
- else if (State & REPLACE_FLAG)
+ } else if (State & REPLACE_FLAG) {
MSG_PUTS_ATTR(_(" REPLACE"), attr);
- else if (State & INSERT) {
- if (p_ri)
+ } else if (State & INSERT) {
+ if (p_ri) {
MSG_PUTS_ATTR(_(" REVERSE"), attr);
+ }
MSG_PUTS_ATTR(_(" INSERT"), attr);
} else if (restart_edit == 'I' || restart_edit == 'i'
|| restart_edit == 'a') {
@@ -6933,8 +6983,9 @@ int showmode(void)
MSG_PUTS_ATTR(NameBuff, attr);
}
}
- if ((State & INSERT) && p_paste)
+ if ((State & INSERT) && p_paste) {
MSG_PUTS_ATTR(_(" (paste)"), attr);
+ }
if (VIsual_active) {
char *p;
@@ -6983,9 +7034,10 @@ int showmode(void)
// NB: also handles clearing the showmode if it was empty or disabled
msg_ext_flush_showmode();
- /* In Visual mode the size of the selected area must be redrawn. */
- if (VIsual_active)
+ // In Visual mode the size of the selected area must be redrawn.
+ if (VIsual_active) {
clear_showcmd();
+ }
// If the last window has no status line, the ruler is after the mode
// message and must be redrawn
@@ -7082,15 +7134,16 @@ void draw_tabline(void)
return;
}
- if (tabline_height() < 1)
+ if (tabline_height() < 1) {
return;
+ }
// Init TabPageIdxs[] to zero: Clicking outside of tabs has no effect.
assert(Columns == tab_page_click_defs_size);
clear_tab_page_click_defs(tab_page_click_defs, tab_page_click_defs_size);
- /* Use the 'tabline' option if it's set. */
+ // Use the 'tabline' option if it's set.
if (*p_tal != NUL) {
int saved_did_emsg = did_emsg;
@@ -7176,7 +7229,7 @@ void draw_tabline(void)
room = scol - col + tabwidth - 1;
if (room > 0) {
- /* Get buffer name in NameBuff[] */
+ // Get buffer name in NameBuff[]
get_trans_bufname(cwp->w_buffer);
(void)shorten_dir(NameBuff);
len = vim_strsize(NameBuff);
@@ -7206,13 +7259,14 @@ void draw_tabline(void)
}
}
- if (use_sep_chars)
+ if (use_sep_chars) {
c = '_';
- else
+ } else {
c = ' ';
+ }
grid_fill(&default_grid, 0, 1, col, Columns, c, c, attr_fill);
- /* Put an "X" for closing the current tab if there are several. */
+ // Put an "X" for closing the current tab if there are several.
if (first_tabpage->tp_next != NULL) {
grid_putchar(&default_grid, 'X', 0, Columns - 1, attr_nosel);
tab_page_click_defs[Columns - 1] = (StlClickDefinition) {
@@ -7267,10 +7321,11 @@ void ui_ext_tabline_update(void)
*/
void get_trans_bufname(buf_T *buf)
{
- if (buf_spname(buf) != NULL)
+ if (buf_spname(buf) != NULL) {
STRLCPY(NameBuff, buf_spname(buf), MAXPATHL);
- else
+ } else {
home_replace(buf, buf->b_fname, NameBuff, MAXPATHL, TRUE);
+ }
trans_characters(NameBuff, MAXPATHL);
}
@@ -7334,8 +7389,9 @@ int messaging(void)
/// @param always if false, only show ruler if position has changed.
void showruler(bool always)
{
- if (!always && !redrawing())
+ if (!always && !redrawing()) {
return;
+ }
if ((*p_stl != NUL || *curwin->w_p_stl != NUL) && curwin->w_status_height) {
redraw_custom_statusline(curwin);
} else {
@@ -7344,12 +7400,13 @@ void showruler(bool always)
if (need_maketitle
|| (p_icon && (stl_syntax & STL_IN_ICON))
- || (p_title && (stl_syntax & STL_IN_TITLE))
- )
+ || (p_title && (stl_syntax & STL_IN_TITLE))) {
maketitle();
- /* Redraw the tab pages line if needed. */
- if (redraw_tabline)
+ }
+ // Redraw the tab pages line if needed.
+ if (redraw_tabline) {
draw_tabline();
+ }
}
static void win_redr_ruler(win_T *wp, bool always)
@@ -7365,8 +7422,9 @@ static void win_redr_ruler(win_T *wp, bool always)
* Check if cursor.lnum is valid, since win_redr_ruler() may be called
* after deleting lines, before cursor.lnum is corrected.
*/
- if (wp->w_cursor.lnum > wp->w_buffer->b_ml.ml_line_count)
+ if (wp->w_cursor.lnum > wp->w_buffer->b_ml.ml_line_count) {
return;
+ }
// Don't draw the ruler while doing insert-completion, it might overwrite
// the (long) mode message.
@@ -7394,24 +7452,24 @@ static void win_redr_ruler(win_T *wp, bool always)
*/
int empty_line = FALSE;
if (!(State & INSERT)
- && *ml_get_buf(wp->w_buffer, wp->w_cursor.lnum, FALSE) == NUL)
+ && *ml_get_buf(wp->w_buffer, wp->w_cursor.lnum, FALSE) == NUL) {
empty_line = TRUE;
+ }
/*
* Only draw the ruler when something changed.
*/
validate_virtcol_win(wp);
- if ( redraw_cmdline
- || always
- || wp->w_cursor.lnum != wp->w_ru_cursor.lnum
- || wp->w_cursor.col != wp->w_ru_cursor.col
- || wp->w_virtcol != wp->w_ru_virtcol
- || wp->w_cursor.coladd != wp->w_ru_cursor.coladd
- || wp->w_topline != wp->w_ru_topline
- || wp->w_buffer->b_ml.ml_line_count != wp->w_ru_line_count
- || wp->w_topfill != wp->w_ru_topfill
- || empty_line != wp->w_ru_empty) {
-
+ if (redraw_cmdline
+ || always
+ || wp->w_cursor.lnum != wp->w_ru_cursor.lnum
+ || wp->w_cursor.col != wp->w_ru_cursor.col
+ || wp->w_virtcol != wp->w_ru_virtcol
+ || wp->w_cursor.coladd != wp->w_ru_cursor.coladd
+ || wp->w_topline != wp->w_ru_topline
+ || wp->w_buffer->b_ml.ml_line_count != wp->w_ru_line_count
+ || wp->w_topfill != wp->w_ru_topfill
+ || empty_line != wp->w_ru_empty) {
int width;
int row;
int fillchar;
@@ -7449,12 +7507,12 @@ static void win_redr_ruler(win_T *wp, bool always)
* To avoid portability problems we use strlen() here.
*/
vim_snprintf((char *)buffer, RULER_BUF_LEN, "%" PRId64 ",",
- (wp->w_buffer->b_ml.ml_flags & ML_EMPTY) ? (int64_t)0L
- : (int64_t)wp->w_cursor.lnum);
+ (wp->w_buffer->b_ml.ml_flags & ML_EMPTY) ? (int64_t)0L
+ : (int64_t)wp->w_cursor.lnum);
size_t len = STRLEN(buffer);
col_print(buffer + len, RULER_BUF_LEN - len,
- empty_line ? 0 : (int)wp->w_cursor.col + 1,
- (int)virtcol + 1);
+ empty_line ? 0 : (int)wp->w_cursor.col + 1,
+ (int)virtcol + 1);
/*
* Add a "50%" if there is room for it.
@@ -7542,8 +7600,9 @@ int number_width(win_T *wp)
lnum = wp->w_buffer->b_ml.ml_line_count;
}
- if (lnum == wp->w_nrwidth_line_count)
+ if (lnum == wp->w_nrwidth_line_count) {
return wp->w_nrwidth_width;
+ }
wp->w_nrwidth_line_count = lnum;
n = 0;
@@ -7622,11 +7681,12 @@ void screen_resize(int width, int height)
return;
}
- if (width < 0 || height < 0) /* just checking... */
+ if (width < 0 || height < 0) { // just checking...
return;
+ }
if (State == HITRETURN || State == SETWSIZE) {
- /* postpone the resizing */
+ // postpone the resizing
State = SETWSIZE;
return;
}
@@ -7635,8 +7695,9 @@ void screen_resize(int width, int height)
* buffer has already been closed and removing a scrollbar causes a resize
* event. Don't resize then, it will happen after entering another buffer.
*/
- if (curwin->w_buffer == NULL)
+ if (curwin->w_buffer == NULL) {
return;
+ }
recursive = true;
diff --git a/src/nvim/syntax.c b/src/nvim/syntax.c
index bdbbc4aacf..e5d4752760 100644
--- a/src/nvim/syntax.c
+++ b/src/nvim/syntax.c
@@ -6028,6 +6028,8 @@ static const char *highlight_init_both[] = {
"VertSplit cterm=reverse gui=reverse",
"WildMenu ctermbg=Yellow ctermfg=Black guibg=Yellow guifg=Black",
"default link EndOfBuffer NonText",
+ "default link LineNrAbove LineNr",
+ "default link LineNrBelow LineNr",
"default link QuickFixLine Search",
"default link Substitute Search",
"default link Whitespace NonText",
diff --git a/src/nvim/tag.c b/src/nvim/tag.c
index a971849f4c..61d48eb4bf 100644
--- a/src/nvim/tag.c
+++ b/src/nvim/tag.c
@@ -3061,24 +3061,26 @@ expand_tags (
)
{
int i;
- int c;
- int tagnmflag;
- char_u tagnm[100];
+ int extra_flag;
+ char_u *name_buf;
+ size_t name_buf_size = 100;
tagptrs_T t_p;
int ret;
- if (tagnames)
- tagnmflag = TAG_NAMES;
- else
- tagnmflag = 0;
+ name_buf = xmalloc(name_buf_size);
+
+ if (tagnames) {
+ extra_flag = TAG_NAMES;
+ } else {
+ extra_flag = 0;
+ }
if (pat[0] == '/') {
ret = find_tags(pat + 1, num_file, file,
- TAG_REGEXP | tagnmflag | TAG_VERBOSE | TAG_NO_TAGFUNC,
+ TAG_REGEXP | extra_flag | TAG_VERBOSE | TAG_NO_TAGFUNC,
TAG_MANY, curbuf->b_ffname);
} else {
ret = find_tags(pat, num_file, file,
- TAG_REGEXP | tagnmflag | TAG_VERBOSE
- | TAG_NO_TAGFUNC | TAG_NOIC,
+ TAG_REGEXP | extra_flag | TAG_VERBOSE | TAG_NO_TAGFUNC | TAG_NOIC,
TAG_MANY, curbuf->b_ffname);
}
if (ret == OK && !tagnames) {
@@ -3086,18 +3088,29 @@ expand_tags (
* "<tagname>\0<kind>\0<filename>\0"
*/
for (i = 0; i < *num_file; i++) {
+ size_t len;
+
parse_match((*file)[i], &t_p);
- c = (int)(t_p.tagname_end - t_p.tagname);
- memmove(tagnm, t_p.tagname, (size_t)c);
- tagnm[c++] = 0;
- tagnm[c++] = (t_p.tagkind != NULL && *t_p.tagkind)
- ? *t_p.tagkind : 'f';
- tagnm[c++] = 0;
- memmove((*file)[i] + c, t_p.fname, t_p.fname_end - t_p.fname);
- (*file)[i][c + (t_p.fname_end - t_p.fname)] = 0;
- memmove((*file)[i], tagnm, (size_t)c);
+ len = t_p.tagname_end - t_p.tagname;
+ if (len > name_buf_size - 3) {
+ char_u *buf;
+
+ name_buf_size = len + 3;
+ buf = xrealloc(name_buf, name_buf_size);
+ name_buf = buf;
+ }
+
+ memmove(name_buf, t_p.tagname, len);
+ name_buf[len++] = 0;
+ name_buf[len++] = (t_p.tagkind != NULL && *t_p.tagkind)
+ ? *t_p.tagkind : 'f';
+ name_buf[len++] = 0;
+ memmove((*file)[i] + len, t_p.fname, t_p.fname_end - t_p.fname);
+ (*file)[i][len + (t_p.fname_end - t_p.fname)] = 0;
+ memmove((*file)[i], name_buf, len);
}
}
+ xfree(name_buf);
return ret;
}
diff --git a/src/nvim/testdir/sautest/autoload/foo.vim b/src/nvim/testdir/sautest/autoload/foo.vim
index d7dcd5ce3d..298e7275d8 100644
--- a/src/nvim/testdir/sautest/autoload/foo.vim
+++ b/src/nvim/testdir/sautest/autoload/foo.vim
@@ -5,3 +5,7 @@ let foo#bar = {}
func foo#bar.echo()
let g:called_foo_bar_echo += 1
endfunc
+
+func foo#addFoo(head)
+ return a:head .. 'foo'
+endfunc
diff --git a/src/nvim/testdir/test_arglist.vim b/src/nvim/testdir/test_arglist.vim
index a1ef8325ec..01d8f32893 100644
--- a/src/nvim/testdir/test_arglist.vim
+++ b/src/nvim/testdir/test_arglist.vim
@@ -90,8 +90,8 @@ func Test_argadd_empty_curbuf()
call assert_equal('', bufname('%'))
call assert_equal(1, line('$'))
rew
- call assert_notequal(curbuf, bufnr('%'))
- call assert_equal('Xargadd', bufname('%'))
+ call assert_notequal(curbuf, '%'->bufnr())
+ call assert_equal('Xargadd', '%'->bufname())
call assert_equal(2, line('$'))
%argd
diff --git a/src/nvim/testdir/test_assert.vim b/src/nvim/testdir/test_assert.vim
index 1d114221dc..52f243aaea 100644
--- a/src/nvim/testdir/test_assert.vim
+++ b/src/nvim/testdir/test_assert.vim
@@ -7,7 +7,7 @@ func Test_assert_equalfile()
let goodtext = ["one", "two", "three"]
call writefile(goodtext, 'Xone')
- call assert_equal(1, assert_equalfile('Xone', 'xyzxyz'))
+ call assert_equal(1, 'Xone'->assert_equalfile('xyzxyz'))
call assert_match("E485: Can't read file xyzxyz", v:errors[0])
call remove(v:errors, 0)
diff --git a/src/nvim/testdir/test_autoload.vim b/src/nvim/testdir/test_autoload.vim
index 7396c227c9..b8c4fa251f 100644
--- a/src/nvim/testdir/test_autoload.vim
+++ b/src/nvim/testdir/test_autoload.vim
@@ -8,6 +8,8 @@ func Test_autoload_dict_func()
call g:foo#bar.echo()
call assert_equal(1, g:loaded_foo_vim)
call assert_equal(1, g:called_foo_bar_echo)
+
+ eval 'bar'->g:foo#addFoo()->assert_equal('barfoo')
endfunc
func Test_source_autoload()
diff --git a/src/nvim/testdir/test_bufline.vim b/src/nvim/testdir/test_bufline.vim
index e038bce08e..b4e8a0bc71 100644
--- a/src/nvim/testdir/test_bufline.vim
+++ b/src/nvim/testdir/test_bufline.vim
@@ -102,7 +102,7 @@ func Test_deletebufline()
call assert_equal(0, deletebufline(b, 2, 8))
call assert_equal(['aaa'], getbufline(b, 1, 2))
exe "bd!" b
- call assert_equal(1, deletebufline(b, 1))
+ call assert_equal(1, b->deletebufline(1))
split Xtest
call setline(1, ['a', 'b', 'c'])
@@ -131,11 +131,11 @@ func Test_appendbufline_redraw()
endif
let lines =<< trim END
new foo
- let winnr=bufwinnr('foo')
- let buf=bufnr('foo')
+ let winnr = 'foo'->bufwinnr()
+ let buf = bufnr('foo')
wincmd p
call appendbufline(buf, '$', range(1,200))
- exe winnr. 'wincmd w'
+ exe winnr .. 'wincmd w'
norm! G
wincmd p
call deletebufline(buf, 1, '$')
diff --git a/src/nvim/testdir/test_bufwintabinfo.vim b/src/nvim/testdir/test_bufwintabinfo.vim
index cb7ab44798..4b5b55e6bf 100644
--- a/src/nvim/testdir/test_bufwintabinfo.vim
+++ b/src/nvim/testdir/test_bufwintabinfo.vim
@@ -18,7 +18,7 @@ function Test_getbufwintabinfo()
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('%')))
+ call assert_notequal(-1, index(l[0].windows, '%'->bufwinid()))
" Test for getbufinfo() with 'bufmodified'
call assert_equal(0, len(getbufinfo({'bufmodified' : 1})))
diff --git a/src/nvim/testdir/test_cindent.vim b/src/nvim/testdir/test_cindent.vim
index b6c2d1467e..562867f548 100644
--- a/src/nvim/testdir/test_cindent.vim
+++ b/src/nvim/testdir/test_cindent.vim
@@ -118,6 +118,16 @@ b = something();
bw!
endfunc
+func Test_cindent_func()
+ new
+ setlocal cindent
+ call setline(1, ['int main(void)', '{', 'return 0;', '}'])
+ call assert_equal(-1, cindent(0))
+ call assert_equal(&sw, 3->cindent())
+ call assert_equal(-1, cindent(line('$')+1))
+ bwipe!
+endfunc
+
" this was going beyond the end of the line.
func Test_cindent_case()
new
diff --git a/src/nvim/testdir/test_diffmode.vim b/src/nvim/testdir/test_diffmode.vim
index f39cda7663..efa7f552e0 100644
--- a/src/nvim/testdir/test_diffmode.vim
+++ b/src/nvim/testdir/test_diffmode.vim
@@ -725,7 +725,7 @@ func Test_diff_filler()
diffthis
redraw
- call assert_equal([0, 0, 0, 0, 0, 0, 0, 1, 0], map(range(-1, 7), 'diff_filler(v:val)'))
+ call assert_equal([0, 0, 0, 0, 0, 0, 0, 1, 0], map(range(-1, 7), 'v:val->diff_filler()'))
wincmd w
call assert_equal([0, 0, 0, 0, 2, 0, 0, 0], map(range(-1, 6), 'diff_filler(v:val)'))
@@ -741,16 +741,16 @@ func Test_diff_hlID()
diffthis
redraw
- call assert_equal(synIDattr(diff_hlID(-1, 1), "name"), "")
+ call diff_hlID(-1, 1)->synIDattr("name")->assert_equal("")
call assert_equal(diff_hlID(1, 1), hlID("DiffChange"))
- call assert_equal(synIDattr(diff_hlID(1, 1), "name"), "DiffChange")
+ call diff_hlID(1, 1)->synIDattr("name")->assert_equal("DiffChange")
call assert_equal(diff_hlID(1, 2), hlID("DiffText"))
- call assert_equal(synIDattr(diff_hlID(1, 2), "name"), "DiffText")
- call assert_equal(synIDattr(diff_hlID(2, 1), "name"), "")
+ call diff_hlID(1, 2)->synIDattr("name")->assert_equal("DiffText")
+ call diff_hlID(2, 1)->synIDattr("name")->assert_equal("")
call assert_equal(diff_hlID(3, 1), hlID("DiffAdd"))
- call assert_equal(synIDattr(diff_hlID(3, 1), "name"), "DiffAdd")
- call assert_equal(synIDattr(diff_hlID(4, 1), "name"), "")
+ call diff_hlID(3, 1)->synIDattr("name")->assert_equal("DiffAdd")
+ call diff_hlID(4, 1)->synIDattr("name")->assert_equal("")
wincmd w
call assert_equal(diff_hlID(1, 1), hlID("DiffChange"))
diff --git a/src/nvim/testdir/test_float_func.vim b/src/nvim/testdir/test_float_func.vim
index 154ef570e0..78675d7016 100644
--- a/src/nvim/testdir/test_float_func.vim
+++ b/src/nvim/testdir/test_float_func.vim
@@ -7,6 +7,8 @@ end
func Test_abs()
call assert_equal('1.23', string(abs(1.23)))
call assert_equal('1.23', string(abs(-1.23)))
+ eval -1.23->abs()->string()->assert_equal('1.23')
+
call assert_equal('0.0', string(abs(0.0)))
call assert_equal('0.0', string(abs(1.0/(1.0/0.0))))
call assert_equal('0.0', string(abs(-1.0/(1.0/0.0))))
@@ -22,6 +24,7 @@ endfunc
func Test_sqrt()
call assert_equal('0.0', string(sqrt(0.0)))
call assert_equal('1.414214', string(sqrt(2.0)))
+ eval 2.0->sqrt()->string()->assert_equal('1.414214')
call assert_equal("str2float('inf')", string(sqrt(1.0/0.0)))
call assert_equal("str2float('nan')", string(sqrt(-1.0)))
call assert_equal("str2float('nan')", string(sqrt(0.0/0.0)))
@@ -31,6 +34,7 @@ endfunc
func Test_log()
call assert_equal('0.0', string(log(1.0)))
call assert_equal('-0.693147', string(log(0.5)))
+ eval 0.5->log()->string()->assert_equal('-0.693147')
call assert_equal("-str2float('inf')", string(log(0.0)))
call assert_equal("str2float('nan')", string(log(-1.0)))
call assert_equal("str2float('inf')", string(log(1.0/0.0)))
@@ -42,6 +46,7 @@ func Test_log10()
call assert_equal('0.0', string(log10(1.0)))
call assert_equal('2.0', string(log10(100.0)))
call assert_equal('2.079181', string(log10(120.0)))
+ eval 120.0->log10()->string()->assert_equal('2.079181')
call assert_equal("-str2float('inf')", string(log10(0.0)))
call assert_equal("str2float('nan')", string(log10(-1.0)))
call assert_equal("str2float('inf')", string(log10(1.0/0.0)))
@@ -53,6 +58,7 @@ func Test_exp()
call assert_equal('1.0', string(exp(0.0)))
call assert_equal('7.389056', string(exp(2.0)))
call assert_equal('0.367879', string(exp(-1.0)))
+ eval -1.0->exp()->string()->assert_equal('0.367879')
call assert_equal("str2float('inf')", string(exp(1.0/0.0)))
call assert_equal('0.0', string(exp(-1.0/0.0)))
call assert_equal("str2float('nan')", string(exp(0.0/0.0)))
@@ -63,6 +69,7 @@ func Test_sin()
call assert_equal('0.0', string(sin(0.0)))
call assert_equal('0.841471', string(sin(1.0)))
call assert_equal('-0.479426', string(sin(-0.5)))
+ eval -0.5->sin()->string()->assert_equal('-0.479426')
call assert_equal("str2float('nan')", string(sin(0.0/0.0)))
call assert_equal("str2float('nan')", string(sin(1.0/0.0)))
call assert_equal('0.0', string(sin(1.0/(1.0/0.0))))
@@ -73,6 +80,8 @@ endfunc
func Test_asin()
call assert_equal('0.0', string(asin(0.0)))
call assert_equal('1.570796', string(asin(1.0)))
+ eval 1.0->asin()->string()->assert_equal('1.570796')
+
call assert_equal('-0.523599', string(asin(-0.5)))
call assert_equal("str2float('nan')", string(asin(1.1)))
call assert_equal("str2float('nan')", string(asin(1.0/0.0)))
@@ -84,6 +93,7 @@ func Test_sinh()
call assert_equal('0.0', string(sinh(0.0)))
call assert_equal('0.521095', string(sinh(0.5)))
call assert_equal('-1.026517', string(sinh(-0.9)))
+ eval -0.9->sinh()->string()->assert_equal('-1.026517')
call assert_equal("str2float('inf')", string(sinh(1.0/0.0)))
call assert_equal("-str2float('inf')", string(sinh(-1.0/0.0)))
call assert_equal("str2float('nan')", string(sinh(0.0/0.0)))
@@ -94,6 +104,7 @@ func Test_cos()
call assert_equal('1.0', string(cos(0.0)))
call assert_equal('0.540302', string(cos(1.0)))
call assert_equal('0.877583', string(cos(-0.5)))
+ eval -0.5->cos()->string()->assert_equal('0.877583')
call assert_equal("str2float('nan')", string(cos(0.0/0.0)))
call assert_equal("str2float('nan')", string(cos(1.0/0.0)))
call assert_fails('call cos("")', 'E808:')
@@ -103,6 +114,7 @@ func Test_acos()
call assert_equal('1.570796', string(acos(0.0)))
call assert_equal('0.0', string(acos(1.0)))
call assert_equal('3.141593', string(acos(-1.0)))
+ eval -1.0->acos()->string()->assert_equal('3.141593')
call assert_equal('2.094395', string(acos(-0.5)))
call assert_equal("str2float('nan')", string(acos(1.1)))
call assert_equal("str2float('nan')", string(acos(1.0/0.0)))
@@ -113,6 +125,7 @@ endfunc
func Test_cosh()
call assert_equal('1.0', string(cosh(0.0)))
call assert_equal('1.127626', string(cosh(0.5)))
+ eval 0.5->cosh()->string()->assert_equal('1.127626')
call assert_equal("str2float('inf')", string(cosh(1.0/0.0)))
call assert_equal("str2float('inf')", string(cosh(-1.0/0.0)))
call assert_equal("str2float('nan')", string(cosh(0.0/0.0)))
@@ -123,6 +136,7 @@ func Test_tan()
call assert_equal('0.0', string(tan(0.0)))
call assert_equal('0.546302', string(tan(0.5)))
call assert_equal('-0.546302', string(tan(-0.5)))
+ eval -0.5->tan()->string()->assert_equal('-0.546302')
call assert_equal("str2float('nan')", string(tan(1.0/0.0)))
call assert_equal("str2float('nan')", string(cos(0.0/0.0)))
call assert_equal('0.0', string(tan(1.0/(1.0/0.0))))
@@ -134,6 +148,7 @@ func Test_atan()
call assert_equal('0.0', string(atan(0.0)))
call assert_equal('0.463648', string(atan(0.5)))
call assert_equal('-0.785398', string(atan(-1.0)))
+ eval -1.0->atan()->string()->assert_equal('-0.785398')
call assert_equal('1.570796', string(atan(1.0/0.0)))
call assert_equal('-1.570796', string(atan(-1.0/0.0)))
call assert_equal("str2float('nan')", string(atan(0.0/0.0)))
@@ -144,6 +159,7 @@ func Test_atan2()
call assert_equal('-2.356194', string(atan2(-1, -1)))
call assert_equal('2.356194', string(atan2(1, -1)))
call assert_equal('0.0', string(atan2(1.0, 1.0/0.0)))
+ eval 1.0->atan2(1.0/0.0)->string()->assert_equal('0.0')
call assert_equal('1.570796', string(atan2(1.0/0.0, 1.0)))
call assert_equal("str2float('nan')", string(atan2(0.0/0.0, 1.0)))
call assert_fails('call atan2("", -1)', 'E808:')
@@ -154,6 +170,7 @@ func Test_tanh()
call assert_equal('0.0', string(tanh(0.0)))
call assert_equal('0.462117', string(tanh(0.5)))
call assert_equal('-0.761594', string(tanh(-1.0)))
+ eval -1.0->tanh()->string()->assert_equal('-0.761594')
call assert_equal('1.0', string(tanh(1.0/0.0)))
call assert_equal('-1.0', string(tanh(-1.0/0.0)))
call assert_equal("str2float('nan')", string(tanh(0.0/0.0)))
@@ -164,6 +181,7 @@ func Test_fmod()
call assert_equal('0.13', string(fmod(12.33, 1.22)))
call assert_equal('-0.13', string(fmod(-12.33, 1.22)))
call assert_equal("str2float('nan')", string(fmod(1.0/0.0, 1.0)))
+ eval (1.0/0.0)->fmod(1.0)->string()->assert_equal("str2float('nan')")
" On Windows we get "nan" instead of 1.0, accept both.
let res = string(fmod(1.0, 1.0/0.0))
if res != "str2float('nan')"
@@ -177,6 +195,7 @@ endfunc
func Test_pow()
call assert_equal('1.0', string(pow(0.0, 0.0)))
call assert_equal('8.0', string(pow(2.0, 3.0)))
+ eval 2.0->pow(3.0)->string()->assert_equal('8.0')
call assert_equal("str2float('nan')", string(pow(2.0, 0.0/0.0)))
call assert_equal("str2float('nan')", string(pow(0.0/0.0, 3.0)))
call assert_equal("str2float('nan')", string(pow(0.0/0.0, 3.0)))
@@ -192,6 +211,7 @@ func Test_str2float()
call assert_equal('1.0', string(str2float(' 1.0 ')))
call assert_equal('1.23', string(str2float('1.23')))
call assert_equal('1.23', string(str2float('1.23abc')))
+ eval '1.23abc'->str2float()->string()->assert_equal('1.23')
call assert_equal('1.0e40', string(str2float('1e40')))
call assert_equal('-1.23', string(str2float('-1.23')))
call assert_equal('1.23', string(str2float(' + 1.23 ')))
@@ -228,6 +248,7 @@ func Test_float2nr()
call assert_equal(1, float2nr(1.234))
call assert_equal(123, float2nr(1.234e2))
call assert_equal(12, float2nr(123.4e-1))
+ eval 123.4e-1->float2nr()->assert_equal(12)
let max_number = 1/0
let min_number = -max_number
call assert_equal(max_number/2+1, float2nr(pow(2, 62)))
@@ -242,6 +263,7 @@ func Test_floor()
call assert_equal('2.0', string(floor(2.0)))
call assert_equal('2.0', string(floor(2.11)))
call assert_equal('2.0', string(floor(2.99)))
+ eval 2.99->floor()->string()->assert_equal('2.0')
call assert_equal('-3.0', string(floor(-2.11)))
call assert_equal('-3.0', string(floor(-2.99)))
call assert_equal("str2float('nan')", string(floor(0.0/0.0)))
@@ -255,6 +277,7 @@ func Test_ceil()
call assert_equal('3.0', string(ceil(2.11)))
call assert_equal('3.0', string(ceil(2.99)))
call assert_equal('-2.0', string(ceil(-2.11)))
+ eval -2.11->ceil()->string()->assert_equal('-2.0')
call assert_equal('-2.0', string(ceil(-2.99)))
call assert_equal("str2float('nan')", string(ceil(0.0/0.0)))
call assert_equal("str2float('inf')", string(ceil(1.0/0.0)))
@@ -266,6 +289,7 @@ func Test_round()
call assert_equal('2.0', string(round(2.1)))
call assert_equal('3.0', string(round(2.5)))
call assert_equal('3.0', string(round(2.9)))
+ eval 2.9->round()->string()->assert_equal('3.0')
call assert_equal('-2.0', string(round(-2.1)))
call assert_equal('-3.0', string(round(-2.5)))
call assert_equal('-3.0', string(round(-2.9)))
@@ -279,6 +303,7 @@ func Test_trunc()
call assert_equal('2.0', string(trunc(2.1)))
call assert_equal('2.0', string(trunc(2.5)))
call assert_equal('2.0', string(trunc(2.9)))
+ eval 2.9->trunc()->string()->assert_equal('2.0')
call assert_equal('-2.0', string(trunc(-2.1)))
call assert_equal('-2.0', string(trunc(-2.5)))
call assert_equal('-2.0', string(trunc(-2.9)))
@@ -291,6 +316,7 @@ endfunc
func Test_isinf()
call assert_equal(1, isinf(1.0/0.0))
call assert_equal(-1, isinf(-1.0/0.0))
+ eval (-1.0/0.0)->isinf()->assert_equal(-1)
call assert_false(isinf(1.0))
call assert_false(isinf(0.0/0.0))
call assert_false(isinf('a'))
@@ -302,6 +328,7 @@ func Test_isnan()
call assert_true(isnan(0.0/0.0))
call assert_false(isnan(1.0))
call assert_false(isnan(1.0/0.0))
+ eval (1.0/0.0)->isnan()->assert_false()
call assert_false(isnan(-1.0/0.0))
call assert_false(isnan('a'))
call assert_false(isnan([]))
diff --git a/src/nvim/testdir/test_functions.vim b/src/nvim/testdir/test_functions.vim
index 48f97be96b..6cb3e24201 100644
--- a/src/nvim/testdir/test_functions.vim
+++ b/src/nvim/testdir/test_functions.vim
@@ -852,7 +852,7 @@ func Test_byte2line_line2byte()
set fileformat=mac
call assert_equal([-1, -1, 1, 1, 2, 2, 2, 3, 3, -1],
- \ map(range(-1, 8), 'byte2line(v:val)'))
+ \ map(range(-1, 8), 'v:val->byte2line()'))
call assert_equal([-1, -1, 1, 3, 6, 8, -1],
\ map(range(-1, 5), 'line2byte(v:val)'))
@@ -875,6 +875,34 @@ func Test_byte2line_line2byte()
bw!
endfunc
+func Test_byteidx()
+ let a = '.é.' " one char of two bytes
+ call assert_equal(0, byteidx(a, 0))
+ call assert_equal(0, byteidxcomp(a, 0))
+ call assert_equal(1, byteidx(a, 1))
+ call assert_equal(1, byteidxcomp(a, 1))
+ call assert_equal(3, byteidx(a, 2))
+ call assert_equal(3, byteidxcomp(a, 2))
+ call assert_equal(4, byteidx(a, 3))
+ call assert_equal(4, byteidxcomp(a, 3))
+ call assert_equal(-1, byteidx(a, 4))
+ call assert_equal(-1, byteidxcomp(a, 4))
+
+ let b = '.é.' " normal e with composing char
+ call assert_equal(0, b->byteidx(0))
+ call assert_equal(1, b->byteidx(1))
+ call assert_equal(4, b->byteidx(2))
+ call assert_equal(5, b->byteidx(3))
+ call assert_equal(-1, b->byteidx(4))
+
+ call assert_equal(0, b->byteidxcomp(0))
+ call assert_equal(1, b->byteidxcomp(1))
+ call assert_equal(2, b->byteidxcomp(2))
+ call assert_equal(4, b->byteidxcomp(3))
+ call assert_equal(5, b->byteidxcomp(4))
+ call assert_equal(-1, b->byteidxcomp(5))
+endfunc
+
" Test for charidx()
func Test_charidx()
let a = 'xáb́y'
@@ -1065,7 +1093,7 @@ func Test_col()
call assert_equal(7, col('$'))
call assert_equal(4, col("'x"))
call assert_equal(6, col("'Y"))
- call assert_equal(2, col([1, 2]))
+ call assert_equal(2, [1, 2]->col())
call assert_equal(7, col([1, '$']))
call assert_equal(0, col(''))
@@ -1413,13 +1441,13 @@ func Test_bufadd_bufload()
call assert_equal([''], getbufline(buf, 1, '$'))
let curbuf = bufnr('')
- call writefile(['some', 'text'], 'otherName')
- let buf = bufadd('otherName')
+ call writefile(['some', 'text'], 'XotherName')
+ let buf = 'XotherName'->bufadd()
call assert_notequal(0, buf)
- call assert_equal(1, bufexists('otherName'))
+ eval 'XotherName'->bufexists()->assert_equal(1)
call assert_equal(0, getbufvar(buf, '&buflisted'))
call assert_equal(0, bufloaded(buf))
- call bufload(buf)
+ eval buf->bufload()
call assert_equal(1, bufloaded(buf))
call assert_equal(['some', 'text'], getbufline(buf, 1, '$'))
call assert_equal(curbuf, bufnr(''))
@@ -1439,8 +1467,9 @@ func Test_bufadd_bufload()
call assert_equal(0, bufexists(buf2))
bwipe someName
- bwipe otherName
+ bwipe XotherName
call assert_equal(0, bufexists('someName'))
+ call delete('XotherName')
endfunc
func Test_readdir()
@@ -1473,6 +1502,20 @@ func Test_readdir()
call delete('Xdir', 'rf')
endfunc
+func Test_call()
+ call assert_equal(3, call('len', [123]))
+ call assert_equal(3, 'len'->call([123]))
+ call assert_fails("call call('len', 123)", 'E714:')
+ call assert_equal(0, call('', []))
+
+ function Mylen() dict
+ return len(self.data)
+ endfunction
+ let mydict = {'data': [0, 1, 2, 3], 'len': function("Mylen")}
+ eval mydict.len->call([], mydict)->assert_equal(4)
+ call assert_fails("call call('Mylen', [], 0)", 'E715:')
+endfunc
+
" Test for the eval() function
func Test_eval()
call assert_fails("call eval('5 a')", 'E488:')
diff --git a/src/nvim/testdir/test_hide.vim b/src/nvim/testdir/test_hide.vim
index 128b8ff945..41b1a4ad7c 100644
--- a/src/nvim/testdir/test_hide.vim
+++ b/src/nvim/testdir/test_hide.vim
@@ -37,7 +37,7 @@ function Test_hide()
" :hide as a command
hide
call assert_equal([orig_bname, orig_winnr], [bufname(''), winnr('$')])
- call assert_equal([1, 1], [buflisted('Xf1'), bufloaded('Xf1')])
+ call assert_equal([1, 1], ['Xf1'->buflisted(), 'Xf1'->bufloaded()])
bwipeout! Xf1
new Xf1
diff --git a/src/nvim/testdir/test_lambda.vim b/src/nvim/testdir/test_lambda.vim
index f026c8a55f..63bb4ae1ef 100644
--- a/src/nvim/testdir/test_lambda.vim
+++ b/src/nvim/testdir/test_lambda.vim
@@ -61,7 +61,7 @@ endfunction
function Test_lambda_fails()
call assert_equal(3, {a, b -> a + b}(1, 2))
- call assert_fails('echo {a, a -> a + a}(1, 2)', 'E15:')
+ call assert_fails('echo {a, a -> a + a}(1, 2)', 'E853:')
call assert_fails('echo {a, b -> a + b)}(1, 2)', 'E15:')
endfunc
diff --git a/src/nvim/testdir/test_match.vim b/src/nvim/testdir/test_match.vim
index 0fd76a23ea..505a052a19 100644
--- a/src/nvim/testdir/test_match.vim
+++ b/src/nvim/testdir/test_match.vim
@@ -242,7 +242,7 @@ func Test_matchaddpos_otherwin()
\]
call assert_equal(expect, savematches)
- call clearmatches(winid)
+ eval winid->clearmatches()
call assert_equal([], getmatches(winid))
call setmatches(savematches, winid)
diff --git a/src/nvim/testdir/test_method.vim b/src/nvim/testdir/test_method.vim
new file mode 100644
index 0000000000..7a6e6aa19d
--- /dev/null
+++ b/src/nvim/testdir/test_method.vim
@@ -0,0 +1,159 @@
+" Tests for ->method()
+
+func Test_list_method()
+ let l = [1, 2, 3]
+ call assert_equal([1, 2, 3, 4], [1, 2, 3]->add(4))
+ eval l->assert_equal(l)
+ eval l->assert_equal(l, 'wrong')
+ eval l->assert_notequal([3, 2, 1])
+ eval l->assert_notequal([3, 2, 1], 'wrong')
+ call assert_equal(l, l->copy())
+ call assert_equal(l, l->deepcopy())
+ call assert_equal(1, l->count(2))
+ call assert_false(l->empty())
+ call assert_true([]->empty())
+ call assert_equal(579, ['123', '+', '456']->join()->eval())
+ call assert_equal([1, 2, 3, 4, 5], [1, 2, 3]->extend([4, 5]))
+ call assert_equal([1, 3], [1, 2, 3]->filter('v:val != 2'))
+ call assert_equal(2, l->get(1))
+ call assert_equal(1, l->index(2))
+ call assert_equal([0, 1, 2, 3], [1, 2, 3]->insert(0))
+ call assert_fails('eval l->items()', 'E715:')
+ call assert_equal('1 2 3', l->join())
+ call assert_fails('eval l->keys()', 'E715:')
+ call assert_equal(3, l->len())
+ call assert_equal([2, 3, 4], [1, 2, 3]->map('v:val + 1'))
+ call assert_equal(3, l->max())
+ call assert_equal(1, l->min())
+ call assert_equal(2, [1, 2, 3]->remove(1))
+ call assert_equal([1, 2, 3, 1, 2, 3], l->repeat(2))
+ call assert_equal([3, 2, 1], [1, 2, 3]->reverse())
+ call assert_equal([1, 2, 3, 4], [4, 2, 3, 1]->sort())
+ call assert_equal('[1, 2, 3]', l->string())
+ call assert_equal(v:t_list, l->type())
+ call assert_equal([1, 2, 3], [1, 1, 2, 3, 3]->uniq())
+ call assert_fails('eval l->values()', 'E715:')
+endfunc
+
+func Test_dict_method()
+ let d = #{one: 1, two: 2, three: 3}
+
+ call assert_equal(d, d->copy())
+ call assert_equal(d, d->deepcopy())
+ call assert_equal(1, d->count(2))
+ call assert_false(d->empty())
+ call assert_true({}->empty())
+ call assert_equal(#{one: 1, two: 2, three: 3, four: 4}, d->extend(#{four: 4}))
+ call assert_equal(#{one: 1, two: 2, three: 3}, d->filter('v:val != 4'))
+ call assert_equal(2, d->get('two'))
+ " Nvim doesn't support Blobs yet; expect a different emsg
+ " call assert_fails("let x = d->index(2)", 'E897:')
+ " call assert_fails("let x = d->insert(0)", 'E899:')
+ call assert_fails("let x = d->index(2)", 'E714:')
+ call assert_fails("let x = d->insert(0)", 'E686:')
+ call assert_true(d->has_key('two'))
+ call assert_equal([['one', 1], ['two', 2], ['three', 3]], d->items())
+ call assert_fails("let x = d->join()", 'E714:')
+ call assert_equal(['one', 'two', 'three'], d->keys())
+ call assert_equal(3, d->len())
+ call assert_equal(#{one: 2, two: 3, three: 4}, d->map('v:val + 1'))
+ call assert_equal(#{one: 1, two: 2, three: 3}, d->map('v:val - 1'))
+ call assert_equal(3, d->max())
+ call assert_equal(1, d->min())
+ call assert_equal(2, d->remove("two"))
+ let d.two = 2
+ call assert_fails('let x = d->repeat(2)', 'E731:')
+ " Nvim doesn't support Blobs yet; expect a different emsg
+ " call assert_fails('let x = d->reverse()', 'E899:')
+ call assert_fails('let x = d->reverse()', 'E686:')
+ call assert_fails('let x = d->sort()', 'E686:')
+ call assert_equal("{'one': 1, 'two': 2, 'three': 3}", d->string())
+ call assert_equal(v:t_dict, d->type())
+ call assert_fails('let x = d->uniq()', 'E686:')
+ call assert_equal([1, 2, 3], d->values())
+endfunc
+
+func Test_string_method()
+ eval '1 2 3'->split()->assert_equal(['1', '2', '3'])
+ eval '1 2 3'->split()->map({i, v -> str2nr(v)})->assert_equal([1, 2, 3])
+ eval 'ABC'->str2list()->assert_equal([65, 66, 67])
+ eval 'ABC'->strlen()->assert_equal(3)
+ eval "a\rb\ec"->strtrans()->assert_equal('a^Mb^[c')
+ eval "aあb"->strwidth()->assert_equal(4)
+ eval 'abc'->substitute('b', 'x', '')->assert_equal('axc')
+
+ eval 'abc'->printf('the %s arg')->assert_equal('the abc arg')
+endfunc
+
+func Test_method_append()
+ new
+ eval ['one', 'two', 'three']->append(1)
+ call assert_equal(['', 'one', 'two', 'three'], getline(1, '$'))
+
+ %del
+ let bnr = bufnr('')
+ wincmd w
+ eval ['one', 'two', 'three']->appendbufline(bnr, 1)
+ call assert_equal(['', 'one', 'two', 'three'], getbufline(bnr, 1, '$'))
+
+ exe 'bwipe! ' .. bnr
+endfunc
+
+func Test_method_funcref()
+ func Concat(one, two, three)
+ return a:one .. a:two .. a:three
+ endfunc
+ let FuncRef = function('Concat')
+ eval 'foo'->FuncRef('bar', 'tail')->assert_equal('foobartail')
+
+ " not enough arguments
+ call assert_fails("eval 'foo'->FuncRef('bar')", 'E119:')
+ " too many arguments
+ call assert_fails("eval 'foo'->FuncRef('bar', 'tail', 'four')", 'E118:')
+
+ let Partial = function('Concat', ['two'])
+ eval 'one'->Partial('three')->assert_equal('onetwothree')
+
+ " not enough arguments
+ call assert_fails("eval 'one'->Partial()", 'E119:')
+ " too many arguments
+ call assert_fails("eval 'one'->Partial('three', 'four')", 'E118:')
+
+ delfunc Concat
+endfunc
+
+func Test_method_float()
+ eval 1.234->string()->assert_equal('1.234')
+ eval -1.234->string()->assert_equal('-1.234')
+endfunc
+
+func Test_method_syntax()
+ eval [1, 2, 3] ->sort( )
+ eval [1, 2, 3]
+ \ ->sort(
+ \ )
+ call assert_fails('eval [1, 2, 3]-> sort()', 'E260:')
+ call assert_fails('eval [1, 2, 3]->sort ()', 'E274:')
+ call assert_fails('eval [1, 2, 3]-> sort ()', 'E260:')
+endfunc
+
+func Test_method_lambda()
+ eval "text"->{x -> x .. " extended"}()->assert_equal('text extended')
+ eval "text"->{x, y -> x .. " extended " .. y}('more')->assert_equal('text extended more')
+
+ call assert_fails('eval "text"->{x -> x .. " extended"} ()', 'E274:')
+
+ " todo: lambda accepts more arguments than it consumes
+ " call assert_fails('eval "text"->{x -> x .. " extended"}("more")', 'E99:')
+
+ " Nvim doesn't include test_refcount().
+ " let l = [1, 2, 3]
+ " eval l->{x -> x}()
+ " call assert_equal(1, test_refcount(l))
+endfunc
+
+func Test_method_not_supported()
+ call assert_fails('eval 123->changenr()', 'E276:')
+endfunc
+
+" vim: shiftwidth=2 sts=2 expandtab
diff --git a/src/nvim/testdir/test_number.vim b/src/nvim/testdir/test_number.vim
index eaabe3f67e..92a1bf3c9a 100644
--- a/src/nvim/testdir/test_number.vim
+++ b/src/nvim/testdir/test_number.vim
@@ -3,6 +3,8 @@
source check.vim
source view_util.vim
+source screendump.vim
+
func s:screen_lines(start, end) abort
return ScreenLines([a:start, a:end], 8)
endfunc
@@ -265,6 +267,37 @@ func Test_relativenumber_uninitialised()
bwipe!
endfunc
+func Test_relativenumber_colors()
+ CheckScreendump
+
+ let lines =<< trim [CODE]
+ call setline(1, range(200))
+ 111
+ set number relativenumber
+ hi LineNr ctermfg=red
+ [CODE]
+ call writefile(lines, 'XTest_relnr')
+
+ " Check that the balloon shows up after a mouse move
+ let buf = RunVimInTerminal('-S XTest_relnr', {'rows': 10, 'cols': 50})
+ call term_wait(buf, 100)
+ " Default colors
+ call VerifyScreenDump(buf, 'Test_relnr_colors_1', {})
+
+ call term_sendkeys(buf, ":hi LineNrAbove ctermfg=blue\<CR>")
+ call VerifyScreenDump(buf, 'Test_relnr_colors_2', {})
+
+ call term_sendkeys(buf, ":hi LineNrBelow ctermfg=green\<CR>")
+ call VerifyScreenDump(buf, 'Test_relnr_colors_3', {})
+
+ call term_sendkeys(buf, ":hi clear LineNrAbove\<CR>")
+ call VerifyScreenDump(buf, 'Test_relnr_colors_4', {})
+
+ " clean up
+ call StopVimInTerminal(buf)
+ call delete('XTest_relnr')
+endfunc
+
" Test for displaying line numbers with 'rightleft'
func Test_number_rightleft()
CheckFeature rightleft
diff --git a/src/nvim/testdir/test_popup.vim b/src/nvim/testdir/test_popup.vim
index 06bdb1236a..710450293c 100644
--- a/src/nvim/testdir/test_popup.vim
+++ b/src/nvim/testdir/test_popup.vim
@@ -250,7 +250,7 @@ endfunc
func Test_noinsert_complete()
func! s:complTest1() abort
- call complete(1, ['source', 'soundfold'])
+ eval ['source', 'soundfold']->complete(1)
return ''
endfunc
@@ -403,7 +403,7 @@ func DummyCompleteFour(findstart, base)
return 0
else
call complete_add('four1')
- call complete_add('four2')
+ eval 'four2'->complete_add()
call complete_check()
call complete_add('four3')
call complete_add('four4')
@@ -989,7 +989,7 @@ func GetCompleteInfo()
if empty(g:compl_what)
let g:compl_info = complete_info()
else
- let g:compl_info = complete_info(g:compl_what)
+ let g:compl_info = g:compl_what->complete_info()
endif
return ''
endfunc
diff --git a/src/nvim/testdir/test_syntax.vim b/src/nvim/testdir/test_syntax.vim
index 875e23894f..2344bac498 100644
--- a/src/nvim/testdir/test_syntax.vim
+++ b/src/nvim/testdir/test_syntax.vim
@@ -546,8 +546,8 @@ func Test_synstack_synIDtrans()
call assert_equal([], synstack(1, 1))
norm f/
- call assert_equal(['cComment', 'cCommentStart'], map(synstack(line("."), col(".")), 'synIDattr(v:val, "name")'))
- call assert_equal(['Comment', 'Comment'], map(synstack(line("."), col(".")), 'synIDattr(synIDtrans(v:val), "name")'))
+ eval synstack(line("."), col("."))->map('synIDattr(v:val, "name")')->assert_equal(['cComment', 'cCommentStart'])
+ eval synstack(line("."), col("."))->map('synIDattr(synIDtrans(v:val), "name")')->assert_equal(['Comment', 'Comment'])
norm fA
call assert_equal(['cComment'], map(synstack(line("."), col(".")), 'synIDattr(v:val, "name")'))
diff --git a/src/nvim/testdir/test_system.vim b/src/nvim/testdir/test_system.vim
index 6bbe714d19..7b8ee778cc 100644
--- a/src/nvim/testdir/test_system.vim
+++ b/src/nvim/testdir/test_system.vim
@@ -7,10 +7,10 @@ func Test_System()
if !executable('echo') || !executable('cat') || !executable('wc')
return
endif
- let out = system('echo 123')
+ let out = 'echo 123'->system()
call assert_equal("123\n", out)
- let out = systemlist('echo 123')
+ let out = 'echo 123'->systemlist()
if &shell =~# 'cmd.exe$'
call assert_equal(["123\r"], out)
else
diff --git a/src/nvim/testdir/test_tagjump.vim b/src/nvim/testdir/test_tagjump.vim
index b6d9143bc9..0fa7f85f0d 100644
--- a/src/nvim/testdir/test_tagjump.vim
+++ b/src/nvim/testdir/test_tagjump.vim
@@ -548,6 +548,16 @@ func Test_tag_line_toolong()
call assert_equal('Xsomewhere', expand('%'))
call assert_equal(3, getcurpos()[1])
+ " expansion on command line works with long lines when &wildoptions contains
+ " 'tagfile'
+ set wildoptions=tagfile
+ call writefile([
+ \ 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa file /^pattern$/;" f'
+ \ ], 'Xtags')
+ call feedkeys(":tag \<Tab>", 'tx')
+ " Should not crash
+ call assert_true(v:true)
+
call delete('Xtags')
call delete('Xsomewhere')
set tags&
diff --git a/src/nvim/testdir/test_user_func.vim b/src/nvim/testdir/test_user_func.vim
index 7dcd92a54b..5231ef7b4f 100644
--- a/src/nvim/testdir/test_user_func.vim
+++ b/src/nvim/testdir/test_user_func.vim
@@ -47,7 +47,7 @@ func FuncWithRef(a)
endfunc
func Test_user_func()
- let g:FuncRef=function("FuncWithRef")
+ let g:FuncRef = function("FuncWithRef")
let g:counter = 0
inoremap <expr> ( ListItem()
inoremap <expr> [ ListReset()
@@ -62,6 +62,14 @@ func Test_user_func()
call assert_equal(9, g:retval)
call assert_equal(333, g:FuncRef(333))
+ let g:retval = "nop"
+ call assert_equal('xxx4asdf', "xxx"->Table(4, "asdf"))
+ call assert_equal('fail', 45->Compute(0, "retval"))
+ call assert_equal('nop', g:retval)
+ call assert_equal('ok', 45->Compute(5, "retval"))
+ call assert_equal(9, g:retval)
+ " call assert_equal(333, 333->g:FuncRef())
+
enew
normal oXX+-XX
@@ -150,6 +158,14 @@ func Test_default_arg()
\ execute('func Args2'))
endfunc
+func s:addFoo(lead)
+ return a:lead .. 'foo'
+endfunc
+
+func Test_user_method()
+ eval 'bar'->s:addFoo()->assert_equal('barfoo')
+endfunc
+
func Test_failed_call_in_try()
try | call UnknownFunc() | catch | endtry
endfunc
diff --git a/src/nvim/testdir/test_vimscript.vim b/src/nvim/testdir/test_vimscript.vim
index 5922660ef9..d5837e88c9 100644
--- a/src/nvim/testdir/test_vimscript.vim
+++ b/src/nvim/testdir/test_vimscript.vim
@@ -1372,6 +1372,7 @@ func Test_bitwise_functions()
" and
call assert_equal(127, and(127, 127))
call assert_equal(16, and(127, 16))
+ eval 127->and(16)->assert_equal(16)
call assert_equal(0, and(127, 128))
call assert_fails("call and(1.0, 1)", 'E805:')
call assert_fails("call and([], 1)", 'E745:')
@@ -1382,6 +1383,7 @@ func Test_bitwise_functions()
" or
call assert_equal(23, or(16, 7))
call assert_equal(15, or(8, 7))
+ eval 8->or(7)->assert_equal(15)
call assert_equal(123, or(0, 123))
call assert_fails("call or(1.0, 1)", 'E805:')
call assert_fails("call or([], 1)", 'E745:')
@@ -1392,6 +1394,7 @@ func Test_bitwise_functions()
" xor
call assert_equal(0, xor(127, 127))
call assert_equal(111, xor(127, 16))
+ eval 127->xor(16)->assert_equal(111)
call assert_equal(255, xor(127, 128))
call assert_fails("call xor(1.0, 1)", 'E805:')
call assert_fails("call xor([], 1)", 'E745:')
@@ -1401,6 +1404,7 @@ func Test_bitwise_functions()
call assert_fails("call xor(1, {})", 'E728:')
" invert
call assert_equal(65408, and(invert(127), 65535))
+ eval 127->invert()->and(65535)->assert_equal(65408)
call assert_equal(65519, and(invert(16), 65535))
call assert_equal(65407, and(invert(128), 65535))
call assert_fails("call invert(1.0)", 'E805:')
diff --git a/src/nvim/testdir/test_visual.vim b/src/nvim/testdir/test_visual.vim
index 9c62bdb16e..dbabdcf427 100644
--- a/src/nvim/testdir/test_visual.vim
+++ b/src/nvim/testdir/test_visual.vim
@@ -861,6 +861,15 @@ func Test_visual_block_mode()
set tabstop& shiftwidth&
endfunc
+func Test_visual_force_motion_feedkeys()
+ onoremap <expr> i- execute('let g:mode = mode(1)')
+ call feedkeys('dvi-', 'x')
+ call assert_equal('nov', g:mode)
+ call feedkeys('di-', 'x')
+ call assert_equal('no', g:mode)
+ ounmap i-
+endfunc
+
" Test block-insert using cursor keys for movement
func Test_visual_block_insert_cursor_keys()
new
diff --git a/src/nvim/undo.c b/src/nvim/undo.c
index e1a7dbb2d3..fb96d7e6ff 100644
--- a/src/nvim/undo.c
+++ b/src/nvim/undo.c
@@ -672,6 +672,7 @@ char *u_get_undo_file_name(const char *const buf_ffname, const bool reading)
#ifdef HAVE_READLINK
char fname_buf[MAXPATHL];
#endif
+ char *p;
if (ffname == NULL) {
return NULL;
@@ -704,6 +705,13 @@ char *u_get_undo_file_name(const char *const buf_ffname, const bool reading)
memmove(tail + tail_len + 1, ".un~", sizeof(".un~"));
} else {
dir_name[dir_len] = NUL;
+
+ // Remove trailing pathseps from directory name
+ p = &dir_name[dir_len - 1];
+ while (vim_ispathsep(*p)) {
+ *p-- = NUL;
+ }
+
bool has_directory = os_isdir((char_u *)dir_name);
if (!has_directory && *dirp == NUL && !reading) {
// Last directory in the list does not exist, create it.
@@ -720,7 +728,7 @@ char *u_get_undo_file_name(const char *const buf_ffname, const bool reading)
if (has_directory) {
if (munged_name == NULL) {
munged_name = xstrdup(ffname);
- for (char *p = munged_name; *p != NUL; MB_PTR_ADV(p)) {
+ for (p = munged_name; *p != NUL; MB_PTR_ADV(p)) {
if (vim_ispathsep(*p)) {
*p = '%';
}
diff --git a/test/functional/api/extmark_spec.lua b/test/functional/api/extmark_spec.lua
index d2b555ee5b..50b4b85d2a 100644
--- a/test/functional/api/extmark_spec.lua
+++ b/test/functional/api/extmark_spec.lua
@@ -12,6 +12,7 @@ local feed = helpers.feed
local clear = helpers.clear
local command = helpers.command
local meths = helpers.meths
+local assert_alive = helpers.assert_alive
local function expect(contents)
return eq(contents, helpers.curbuf_contents())
@@ -1381,13 +1382,13 @@ describe('API/extmarks', function()
end)
it('does not crash with append/delete/undo seqence', function()
- meths.exec([[
+ meths.exec([[
let ns = nvim_create_namespace('myplugin')
call nvim_buf_set_extmark(0, ns, 0, 0, {})
call append(0, '')
%delete
undo]],false)
- eq(2, meths.eval('1+1')) -- did not crash
+ assert_alive()
end)
it('works with left and right gravity', function()
diff --git a/test/functional/api/server_notifications_spec.lua b/test/functional/api/server_notifications_spec.lua
index e989034925..279ede81f7 100644
--- a/test/functional/api/server_notifications_spec.lua
+++ b/test/functional/api/server_notifications_spec.lua
@@ -6,6 +6,7 @@ local meths = helpers.meths
local exec_lua = helpers.exec_lua
local retry = helpers.retry
local isCI = helpers.isCI
+local assert_alive = helpers.assert_alive
describe('notify', function()
local channel
@@ -73,7 +74,7 @@ describe('notify', function()
nvim('subscribe', 'event1')
nvim('unsubscribe', 'doesnotexist')
nvim('unsubscribe', 'event1')
- eq(2, eval('1+1')) -- Still alive?
+ assert_alive()
end)
it('cancels stale events on channel close', function()
@@ -83,12 +84,13 @@ describe('notify', function()
end
if helpers.pending_win32(pending) then return end
local catchan = eval("jobstart(['cat'], {'rpc': v:true})")
- eq({id=catchan, stream='job', mode='rpc', client = {}}, exec_lua ([[
+ local catpath = eval('exepath("cat")')
+ eq({id=catchan, argv={catpath}, stream='job', mode='rpc', client = {}}, exec_lua ([[
vim.rpcnotify(..., "nvim_call_function", 'chanclose', {..., 'rpc'})
vim.rpcnotify(..., "nvim_subscribe", "daily_rant")
return vim.api.nvim_get_chan_info(...)
]], catchan))
- eq(2, eval('1+1')) -- Still alive?
+ assert_alive()
eq({false, 'Invalid channel: '..catchan},
exec_lua ([[ return {pcall(vim.rpcrequest, ..., 'nvim_eval', '1+1')}]], catchan))
retry(nil, 3000, function() eq({}, meths.get_chan_info(catchan)) end) -- cat be dead :(
diff --git a/test/functional/api/server_requests_spec.lua b/test/functional/api/server_requests_spec.lua
index 237a4b01e4..e408890906 100644
--- a/test/functional/api/server_requests_spec.lua
+++ b/test/functional/api/server_requests_spec.lua
@@ -11,6 +11,7 @@ local meths = helpers.meths
local spawn, merge_args = helpers.spawn, helpers.merge_args
local set_session = helpers.set_session
local pcall_err = helpers.pcall_err
+local assert_alive = helpers.assert_alive
describe('server -> client', function()
local cid
@@ -33,7 +34,7 @@ describe('server -> client', function()
call jobstop(ch1)
]])
- eq(2, eval("1+1")) -- Still alive?
+ assert_alive()
end)
describe('simple call', function()
@@ -158,7 +159,7 @@ describe('server -> client', function()
-- do some busywork, so the first request will return
-- before this one
for _ = 1, 5 do
- eq(2, eval("1+1"))
+ assert_alive()
end
eq(1, eval('rpcnotify('..cid..', "nested_done")'))
return 'done!'
diff --git a/test/functional/api/vim_spec.lua b/test/functional/api/vim_spec.lua
index 91d2745130..9aad8a1319 100644
--- a/test/functional/api/vim_spec.lua
+++ b/test/functional/api/vim_spec.lua
@@ -1,6 +1,8 @@
local helpers = require('test.functional.helpers')(after_each)
local Screen = require('test.functional.ui.screen')
+local fmt = string.format
+local assert_alive = helpers.assert_alive
local NIL = helpers.NIL
local clear, nvim, eq, neq = helpers.clear, helpers.nvim, helpers.eq, helpers.neq
local command = helpers.command
@@ -57,7 +59,7 @@ describe('API', function()
eq({'notification', 'nvim_error_event',
{error_types.Exception.id, 'Invalid method: nvim_bogus'}}, next_msg())
-- error didn't close channel.
- eq(2, eval('1+1'))
+ assert_alive()
end)
it('failed async request emits nvim_error_event', function()
@@ -67,7 +69,7 @@ describe('API', function()
{error_types.Exception.id, 'Vim:E492: Not an editor command: bogus'}},
next_msg())
-- error didn't close channel.
- eq(2, eval('1+1'))
+ assert_alive()
end)
it('does not set CA_COMMAND_BUSY #7254', function()
@@ -1326,10 +1328,10 @@ describe('API', function()
end)
end)
- describe('nvim_list_chans and nvim_get_chan_info', function()
+ describe('nvim_list_chans, nvim_get_chan_info', function()
before_each(function()
- command('autocmd ChanOpen * let g:opened_event = copy(v:event)')
- command('autocmd ChanInfo * let g:info_event = copy(v:event)')
+ command('autocmd ChanOpen * let g:opened_event = deepcopy(v:event)')
+ command('autocmd ChanInfo * let g:info_event = deepcopy(v:event)')
end)
local testinfo = {
stream = 'stdio',
@@ -1350,7 +1352,7 @@ describe('API', function()
eq({}, meths.get_chan_info(10))
end)
- it('works for stdio channel', function()
+ it('stream=stdio channel', function()
eq({[1]=testinfo,[2]=stderr}, meths.list_chans())
eq(testinfo, meths.get_chan_info(1))
eq(stderr, meths.get_chan_info(2))
@@ -1377,11 +1379,13 @@ describe('API', function()
eq(info, meths.get_chan_info(1))
end)
- it('works for job channel', function()
+ it('stream=job channel', function()
eq(3, eval("jobstart(['cat'], {'rpc': v:true})"))
+ local catpath = eval('exepath("cat")')
local info = {
stream='job',
id=3,
+ argv={ catpath },
mode='rpc',
client={},
}
@@ -1394,6 +1398,7 @@ describe('API', function()
info = {
stream='job',
id=3,
+ argv={ catpath },
mode='rpc',
client = {
name='amazing-cat',
@@ -1410,14 +1415,15 @@ describe('API', function()
pcall_err(eval, 'rpcrequest(3, "nvim_set_current_buf", -1)'))
end)
- it('works for :terminal channel', function()
- command(":terminal")
+ it('stream=job :terminal channel', function()
+ command(':terminal')
eq({id=1}, meths.get_current_buf())
- eq(3, meths.buf_get_option(1, "channel"))
+ eq(3, meths.buf_get_option(1, 'channel'))
local info = {
stream='job',
id=3,
+ argv={ eval('exepath(&shell)') },
mode='terminal',
buffer = 1,
pty='?',
@@ -1431,6 +1437,38 @@ describe('API', function()
info.buffer = {id=1}
eq({[1]=testinfo,[2]=stderr,[3]=info}, meths.list_chans())
eq(info, meths.get_chan_info(3))
+
+ -- :terminal with args + running process.
+ command(':exe "terminal" shellescape(v:progpath) "-u NONE -i NONE"')
+ eq(-1, eval('jobwait([&channel], 0)[0]')) -- Running?
+ local expected2 = {
+ stream = 'job',
+ id = 4,
+ argv = (
+ iswin() and {
+ eval('&shell'),
+ '/s',
+ '/c',
+ fmt('"%s -u NONE -i NONE"', eval('shellescape(v:progpath)')),
+ } or {
+ eval('&shell'),
+ eval('&shellcmdflag'),
+ fmt('%s -u NONE -i NONE', eval('shellescape(v:progpath)')),
+ }
+ ),
+ mode = 'terminal',
+ buffer = 2,
+ pty = '?',
+ }
+ local actual2 = eval('nvim_get_chan_info(&channel)')
+ expected2.pty = actual2.pty
+ eq(expected2, actual2)
+
+ -- :terminal with args + stopped process.
+ eq(1, eval('jobstop(&channel)'))
+ eval('jobwait([&channel], 1000)') -- Wait.
+ expected2.pty = (iswin() and '?' or '') -- pty stream was closed.
+ eq(expected2, eval('nvim_get_chan_info(&channel)'))
end)
end)
diff --git a/test/functional/core/exit_spec.lua b/test/functional/core/exit_spec.lua
index 230b7f8e01..5e569a01d6 100644
--- a/test/functional/core/exit_spec.lua
+++ b/test/functional/core/exit_spec.lua
@@ -1,5 +1,6 @@
local helpers = require('test.functional.helpers')(after_each)
+local assert_alive = helpers.assert_alive
local command = helpers.command
local feed_command = helpers.feed_command
local eval = helpers.eval
@@ -53,7 +54,7 @@ describe(':cquit', function()
if redir_msg then
eq('\n' .. redir_msg, redir_exec(cmdline))
poke_eventloop()
- eq(2, eval("1+1")) -- Still alive?
+ assert_alive()
else
funcs.system({nvim_prog, '-u', 'NONE', '-i', 'NONE', '--headless', '--cmd', cmdline})
eq(exit_code, eval('v:shell_error'))
diff --git a/test/functional/core/job_spec.lua b/test/functional/core/job_spec.lua
index c4745e636f..5e127bce26 100644
--- a/test/functional/core/job_spec.lua
+++ b/test/functional/core/job_spec.lua
@@ -5,6 +5,7 @@ local clear, eq, eval, exc_exec, feed_command, feed, insert, neq, next_msg, nvim
helpers.insert, helpers.neq, helpers.next_msg, helpers.nvim,
helpers.nvim_dir, helpers.ok, helpers.source,
helpers.write_file, helpers.mkdir, helpers.rmdir
+local assert_alive = helpers.assert_alive
local command = helpers.command
local funcs = helpers.funcs
local os_kill = helpers.os_kill
@@ -870,7 +871,7 @@ describe('jobs', function()
-- loop tick. This is also prevented by try-block, so feed must be used.
feed_command("call DoIt()")
feed('<cr>') -- press RETURN
- eq(2,eval('1+1'))
+ assert_alive()
end)
it('jobstop() kills entire process tree #6530', function()
diff --git a/test/functional/core/startup_spec.lua b/test/functional/core/startup_spec.lua
index 997e600671..7cddc72561 100644
--- a/test/functional/core/startup_spec.lua
+++ b/test/functional/core/startup_spec.lua
@@ -1,6 +1,7 @@
local helpers = require('test.functional.helpers')(after_each)
local Screen = require('test.functional.ui.screen')
+local assert_alive = helpers.assert_alive
local clear = helpers.clear
local command = helpers.command
local ok = helpers.ok
@@ -231,7 +232,7 @@ describe('startup', function()
it('does not crash if --embed is given twice', function()
clear{args={'--embed'}}
- eq(2, eval('1+1'))
+ assert_alive()
end)
it('does not crash when expanding cdpath during early_init', function()
@@ -247,9 +248,9 @@ describe('startup', function()
[[" -u NONE -i NONE --cmd "set noruler" --cmd "let g:foo = g:bar"')]])
screen:expect([[
^ |
+ |
Error detected while processing pre-vimrc command line: |
E121: Undefined variable: g:bar |
- E15: Invalid expression: g:bar |
Press ENTER or type command to continue |
|
]])
diff --git a/test/functional/eval/modeline_spec.lua b/test/functional/eval/modeline_spec.lua
index c5bb798f4a..b2346079a1 100644
--- a/test/functional/eval/modeline_spec.lua
+++ b/test/functional/eval/modeline_spec.lua
@@ -1,6 +1,6 @@
local helpers = require('test.functional.helpers')(after_each)
+local assert_alive = helpers.assert_alive
local clear, command, write_file = helpers.clear, helpers.command, helpers.write_file
-local eq, eval = helpers.eq, helpers.eval
describe("modeline", function()
local tempfile = helpers.tmpname()
@@ -14,6 +14,6 @@ describe("modeline", function()
write_file(tempfile, 'vim100000000000000000000000')
command('e! ' .. tempfile)
- eq(2, eval('1+1')) -- Still alive?
+ assert_alive()
end)
end)
diff --git a/test/functional/eval/null_spec.lua b/test/functional/eval/null_spec.lua
index b1ceff9115..f866aca3ed 100644
--- a/test/functional/eval/null_spec.lua
+++ b/test/functional/eval/null_spec.lua
@@ -53,7 +53,7 @@ describe('NULL', function()
-- Correct behaviour
null_expr_test('can be indexed with error message for empty list', 'L[0]',
- 'E684: list index out of range: 0\nE15: Invalid expression: L[0]', nil)
+ 'E684: list index out of range: 0', nil)
null_expr_test('can be splice-indexed', 'L[:]', 0, {})
null_expr_test('is not locked', 'islocked("v:_null_list")', 0, 0)
null_test('is accepted by :for', 'for x in L|throw x|endfor', 0)
@@ -68,7 +68,7 @@ describe('NULL', function()
null_expr_test('can be copied', 'copy(L)', 0, {})
null_expr_test('can be deepcopied', 'deepcopy(L)', 0, {})
null_expr_test('does not crash when indexed', 'L[1]',
- 'E684: list index out of range: 1\nE15: Invalid expression: L[1]', nil)
+ 'E684: list index out of range: 1', nil)
null_expr_test('does not crash call()', 'call("arglistid", L)', 0, 0)
null_expr_test('does not crash col()', 'col(L)', 0, 0)
null_expr_test('does not crash virtcol()', 'virtcol(L)', 0, 0)
@@ -135,7 +135,7 @@ describe('NULL', function()
end)
describe('dict', function()
it('does not crash when indexing NULL dict', function()
- eq('\nE716: Key not present in Dictionary: "test"\nE15: Invalid expression: v:_null_dict.test',
+ eq('\nE716: Key not present in Dictionary: "test"',
redir_exec('echo v:_null_dict.test'))
end)
null_expr_test('makes extend error out', 'extend(D, {})', 'E742: Cannot change value of extend() argument', 0)
diff --git a/test/functional/eval/system_spec.lua b/test/functional/eval/system_spec.lua
index c374baf695..24a1f05390 100644
--- a/test/functional/eval/system_spec.lua
+++ b/test/functional/eval/system_spec.lua
@@ -1,5 +1,6 @@
local helpers = require('test.functional.helpers')(after_each)
+local assert_alive = helpers.assert_alive
local nvim_dir = helpers.nvim_dir
local eq, call, clear, eval, feed_command, feed, nvim =
helpers.eq, helpers.call, helpers.clear, helpers.eval, helpers.feed_command,
@@ -302,7 +303,7 @@ describe('system()', function()
if v_errnum then
eq("E5677:", v_errnum)
end
- eq(2, eval("1+1")) -- Still alive?
+ assert_alive()
end)
end)
@@ -317,11 +318,11 @@ describe('system()', function()
if v_errnum then
eq("E5677:", v_errnum)
end
- eq(2, eval("1+1")) -- Still alive?
+ assert_alive()
end)
it('works with an empty string', function()
eq("test\n", eval('system("echo test", "")'))
- eq(2, eval("1+1")) -- Still alive?
+ assert_alive()
end)
end)
diff --git a/test/functional/ex_cmds/dict_notifications_spec.lua b/test/functional/ex_cmds/dict_notifications_spec.lua
index e5c9a20db3..21adcf37da 100644
--- a/test/functional/ex_cmds/dict_notifications_spec.lua
+++ b/test/functional/ex_cmds/dict_notifications_spec.lua
@@ -1,4 +1,5 @@
local helpers = require('test.functional.helpers')(after_each)
+local assert_alive = helpers.assert_alive
local clear, nvim, source = helpers.clear, helpers.nvim, helpers.source
local insert = helpers.insert
local eq, next_msg = helpers.eq, helpers.next_msg
@@ -325,7 +326,7 @@ describe('VimL dictionary notifications', function()
]])
command('call MakeWatch()')
- eq(2, eval('1+1')) -- Still alive?
+ assert_alive()
end)
end)
@@ -354,7 +355,7 @@ describe('VimL dictionary notifications', function()
command([[call dictwatcherdel(b:, 'changedtick', 'OnTickChanged')]])
insert('t');
- eq(2, eval('1+1')) -- Still alive?
+ assert_alive()
end)
it('does not cause use-after-free when unletting from callback', function()
diff --git a/test/functional/ex_cmds/swapfile_preserve_recover_spec.lua b/test/functional/ex_cmds/swapfile_preserve_recover_spec.lua
index f2a381869e..d91feb4bc1 100644
--- a/test/functional/ex_cmds/swapfile_preserve_recover_spec.lua
+++ b/test/functional/ex_cmds/swapfile_preserve_recover_spec.lua
@@ -3,6 +3,7 @@ local helpers = require('test.functional.helpers')(after_each)
local lfs = require('lfs')
local eq, eval, expect, source =
helpers.eq, helpers.eval, helpers.expect, helpers.source
+local assert_alive = helpers.assert_alive
local clear = helpers.clear
local command = helpers.command
local feed = helpers.feed
@@ -26,7 +27,7 @@ describe(':recover', function()
-- Also check filename ending with ".swp". #9504
eq('Vim(recover):E306: Cannot open '..swapname2,
pcall_err(command, 'recover '..swapname2)) -- Should not segfault. #2117
- eq(2, eval('1+1')) -- Still alive?
+ assert_alive()
end)
end)
diff --git a/test/functional/insert/ctrl_o_spec.lua b/test/functional/insert/ctrl_o_spec.lua
index 543d0a7d68..950ab24219 100644
--- a/test/functional/insert/ctrl_o_spec.lua
+++ b/test/functional/insert/ctrl_o_spec.lua
@@ -1,4 +1,5 @@
local helpers = require('test.functional.helpers')(after_each)
+local assert_alive = helpers.assert_alive
local clear = helpers.clear
local eq = helpers.eq
local eval = helpers.eval
@@ -45,7 +46,7 @@ describe('insert-mode Ctrl-O', function()
it("doesn't cancel Ctrl-O mode when processing event", function()
feed('iHello World<c-o>')
eq({mode='niI', blocking=false}, meths.get_mode()) -- fast event
- eq(2, eval('1+1')) -- causes K_EVENT key
+ assert_alive() -- causes K_EVENT key
eq({mode='niI', blocking=false}, meths.get_mode()) -- still in ctrl-o mode
feed('dd')
eq({mode='i', blocking=false}, meths.get_mode()) -- left ctrl-o mode
diff --git a/test/functional/legacy/assert_spec.lua b/test/functional/legacy/assert_spec.lua
index 515d6d91b8..c2b22472bf 100644
--- a/test/functional/legacy/assert_spec.lua
+++ b/test/functional/legacy/assert_spec.lua
@@ -26,6 +26,14 @@ describe('assert function:', function()
call('assert_beeps', 'normal 0')
expected_errors({'command did not beep: normal 0'})
end)
+
+ it('can be used as a method', function()
+ local tmpname = source [[
+ call assert_equal(0, 'normal h'->assert_beeps())
+ call assert_equal(1, 'normal 0'->assert_beeps())
+ ]]
+ expected_errors({tmpname .. ' line 2: command did not beep: normal 0'})
+ end)
end)
-- assert_equal({expected}, {actual}, [, {msg}])
@@ -133,6 +141,14 @@ describe('assert function:', function()
call('assert_false', {})
expected_errors({'Expected False but got []'})
end)
+
+ it('can be used as a method', function()
+ local tmpname = source [[
+ call assert_equal(0, v:false->assert_false())
+ call assert_equal(1, 123->assert_false())
+ ]]
+ expected_errors({tmpname .. ' line 2: Expected False but got 123'})
+ end)
end)
-- assert_true({actual}, [, {msg}])
@@ -148,6 +164,14 @@ describe('assert function:', function()
eq(1, call('assert_true', 1.5))
expected_errors({'Expected True but got 1.5'})
end)
+
+ it('can be used as a method', function()
+ local tmpname = source [[
+ call assert_equal(0, v:true->assert_true())
+ call assert_equal(1, 0->assert_true())
+ ]]
+ expected_errors({tmpname .. ' line 2: Expected True but got 0'})
+ end)
end)
describe('v:errors', function()
@@ -223,6 +247,15 @@ describe('assert function:', function()
call('assert_match', 'bar.*foo', 'foobar', 'wrong')
expected_errors({"wrong: Pattern 'bar.*foo' does not match 'foobar'"})
end)
+
+ it('can be used as a method', function()
+ local tmpname = source [[
+ call assert_equal(1, 'foobar'->assert_match('bar.*foo', 'wrong'))
+ ]]
+ expected_errors({
+ tmpname .. " line 1: wrong: Pattern 'bar.*foo' does not match 'foobar'"
+ })
+ end)
end)
-- assert_notmatch({pat}, {text}[, {msg}])
@@ -237,6 +270,13 @@ describe('assert function:', function()
call('assert_notmatch', 'foo', 'foobar')
expected_errors({"Pattern 'foo' does match 'foobar'"})
end)
+
+ it('can be used as a method', function()
+ local tmpname = source [[
+ call assert_equal(1, 'foobar'->assert_notmatch('foo'))
+ ]]
+ expected_errors({tmpname .. " line 1: Pattern 'foo' does match 'foobar'"})
+ end)
end)
-- assert_fails({cmd}, [, {error}])
@@ -267,6 +307,15 @@ describe('assert function:', function()
eq(1, eval([[assert_fails('echo', '', 'echo command')]]))
expected_errors({'command did not fail: echo command'})
end)
+
+ it('can be used as a method', function()
+ local tmpname = source [[
+ call assert_equal(1, 'echo'->assert_fails('', 'echo command'))
+ ]]
+ expected_errors({
+ tmpname .. ' line 1: command did not fail: echo command'
+ })
+ end)
end)
-- assert_inrange({lower}, {upper}, {actual}[, {msg}])
@@ -292,6 +341,15 @@ describe('assert function:', function()
eq('Vim(call):E119: Not enough arguments for function: assert_inrange',
exc_exec("call assert_inrange(1, 1)"))
end)
+
+ it('can be used as a method', function()
+ local tmpname = source [[
+ call assert_equal(0, 5->assert_inrange(5, 7))
+ call assert_equal(0, 7->assert_inrange(5, 7))
+ call assert_equal(1, 8->assert_inrange(5, 7))
+ ]]
+ expected_errors({tmpname .. ' line 3: Expected range 5 - 7, but got 8'})
+ end)
end)
-- assert_report({msg})
@@ -302,6 +360,13 @@ describe('assert function:', function()
command('call remove(v:errors, 0)')
expected_empty()
end)
+
+ it('can be used as a method', function()
+ local tmpname = source [[
+ call assert_equal(1, 'also wrong'->assert_report())
+ ]]
+ expected_errors({tmpname .. ' line 1: also wrong'})
+ end)
end)
-- assert_exception({cmd}, [, {error}])
diff --git a/test/functional/legacy/eval_spec.lua b/test/functional/legacy/eval_spec.lua
index ee9bd29fc4..3b407ce5f5 100644
--- a/test/functional/legacy/eval_spec.lua
+++ b/test/functional/legacy/eval_spec.lua
@@ -1,6 +1,7 @@
-- Test for various eval features.
local helpers = require('test.functional.helpers')(after_each)
+local assert_alive = helpers.assert_alive
local feed, insert, source = helpers.feed, helpers.insert, helpers.source
local clear, command, expect = helpers.clear, helpers.command, helpers.expect
local eq, eval, write_file = helpers.eq, helpers.eval, helpers.write_file
@@ -506,7 +507,7 @@ describe('eval', function()
command("call setreg('0',x)")
-- nvim didn't crash and "0 was emptied
- eq(2, eval("1+1"))
+ assert_alive()
eq({}, eval("getreg('0',1,1)"))
-- x is a mutable list
diff --git a/test/functional/lua/buffer_updates_spec.lua b/test/functional/lua/buffer_updates_spec.lua
index a5b613f0b2..073927bf22 100644
--- a/test/functional/lua/buffer_updates_spec.lua
+++ b/test/functional/lua/buffer_updates_spec.lua
@@ -978,6 +978,22 @@ describe('lua: nvim_buf_attach on_bytes', function()
}
end)
+ it("visual paste", function()
+ local check_events= setup_eventcheck(verify, { "aaa {", "b", "}" })
+ -- Setting up
+ feed[[jdd]]
+ check_events {
+ { "test1", "bytes", 1, 3, 1, 0, 6, 1, 0, 2, 0, 0, 0 };
+ }
+
+ -- Actually testing
+ feed[[v%p]]
+ check_events {
+ { "test1", "bytes", 1, 8, 0, 4, 4, 1, 1, 3, 0, 0, 0 };
+ { "test1", "bytes", 1, 8, 0, 4, 4, 0, 0, 0, 2, 0, 3 };
+ }
+ end)
+
it("nvim_buf_set_lines", function()
local check_events = setup_eventcheck(verify, {"AAA", "BBB"})
diff --git a/test/functional/lua/highlight_spec.lua b/test/functional/lua/highlight_spec.lua
new file mode 100644
index 0000000000..50eecb5d09
--- /dev/null
+++ b/test/functional/lua/highlight_spec.lua
@@ -0,0 +1,25 @@
+local helpers = require('test.functional.helpers')(after_each)
+local exec_lua = helpers.exec_lua
+local eq = helpers.eq
+local eval = helpers.eval
+local command = helpers.command
+local clear = helpers.clear
+
+describe('vim.highlight.on_yank', function()
+
+ before_each(function()
+ clear()
+ end)
+
+ it('does not show errors even if buffer is wiped before timeout', function()
+ command('new')
+ exec_lua[[
+ vim.highlight.on_yank({timeout = 10, on_macro = true, event = {operator = "y", regtype = "v"}})
+ vim.cmd('bwipeout!')
+ ]]
+ helpers.sleep(10)
+ helpers.feed('<cr>') -- avoid hang if error message exists
+ eq('', eval('v:errmsg'))
+ end)
+
+end)
diff --git a/test/functional/lua/luaeval_spec.lua b/test/functional/lua/luaeval_spec.lua
index 2ec48777fd..8ef77faa0f 100644
--- a/test/functional/lua/luaeval_spec.lua
+++ b/test/functional/lua/luaeval_spec.lua
@@ -481,6 +481,21 @@ describe('v:lua', function()
pcall_err(eval, 'v:lua.mymod.crashy()'))
end)
+ it('works when called as a method', function()
+ eq(123, eval('110->v:lua.foo(13)'))
+ eq(true, exec_lua([[return _G.val == nil]]))
+
+ eq(321, eval('300->v:lua.foo(21, "boop")'))
+ eq("boop", exec_lua([[return _G.val]]))
+
+ eq(NIL, eval('"there"->v:lua.mymod.noisy()'))
+ eq("hey there", meths.get_current_line())
+ eq({5, 10, 15, 20}, eval('[[1], [2, 3], [4]]->v:lua.vim.tbl_flatten()->map({_, v -> v * 5})'))
+
+ eq("Vim:E5108: Error executing lua [string \"<nvim>\"]:0: attempt to call global 'nonexistent' (a nil value)",
+ pcall_err(eval, '"huh?"->v:lua.mymod.crashy()'))
+ end)
+
it('works in :call', function()
command(":call v:lua.mymod.noisy('command')")
eq("hey command", meths.get_current_line())
@@ -518,8 +533,15 @@ describe('v:lua', function()
eq("Vim:E15: Invalid expression: v:['lua'].foo()", pcall_err(eval, "v:['lua'].foo()"))
eq("Vim(call):E461: Illegal variable name: v:['lua']", pcall_err(command, "call v:['lua'].baar()"))
+ eq("Vim:E117: Unknown function: v:lua", pcall_err(eval, "v:lua()"))
eq("Vim(let):E46: Cannot change read-only variable \"v:['lua']\"", pcall_err(command, "let v:['lua'] = 'xx'"))
eq("Vim(let):E46: Cannot change read-only variable \"v:lua\"", pcall_err(command, "let v:lua = 'xx'"))
+
+ eq("Vim:E107: Missing parentheses: v:lua.func", pcall_err(eval, "'bad'->v:lua.func"))
+ eq("Vim:E274: No white space allowed before parenthesis", pcall_err(eval, "'bad'->v:lua.func ()"))
+ eq("Vim:E107: Missing parentheses: v:lua", pcall_err(eval, "'bad'->v:lua"))
+ eq("Vim:E117: Unknown function: v:lua", pcall_err(eval, "'bad'->v:lua()"))
+ eq("Vim:E15: Invalid expression: v:lua.()", pcall_err(eval, "'bad'->v:lua.()"))
end)
end)
diff --git a/test/functional/lua/vim_spec.lua b/test/functional/lua/vim_spec.lua
index 4e2bed4deb..0ea914880f 100644
--- a/test/functional/lua/vim_spec.lua
+++ b/test/functional/lua/vim_spec.lua
@@ -17,6 +17,7 @@ local matches = helpers.matches
local source = helpers.source
local NIL = helpers.NIL
local retry = helpers.retry
+local next_msg = helpers.next_msg
before_each(clear)
@@ -2178,6 +2179,24 @@ describe('lua stdlib', function()
end)
end)
+ describe('vim.schedule_wrap', function()
+ it('preserves argument lists', function()
+ exec_lua [[
+ local fun = vim.schedule_wrap(function(kling, klang, klonk)
+ vim.rpcnotify(1, 'mayday_mayday', {a=kling, b=klang, c=klonk})
+ end)
+ fun("BOB", nil, "MIKE")
+ ]]
+ eq({'notification', 'mayday_mayday', {{a='BOB', c='MIKE'}}}, next_msg())
+
+ -- let's gooooo
+ exec_lua [[
+ vim.schedule_wrap(function(...) vim.rpcnotify(1, 'boogalo', select('#', ...)) end)(nil,nil,nil,nil)
+ ]]
+ eq({'notification', 'boogalo', {4}}, next_msg())
+ end)
+ end)
+
describe('vim.api.nvim_buf_call', function()
it('can access buf options', function()
local buf1 = meths.get_current_buf()
diff --git a/test/functional/options/defaults_spec.lua b/test/functional/options/defaults_spec.lua
index eb5e284385..6620c9acef 100644
--- a/test/functional/options/defaults_spec.lua
+++ b/test/functional/options/defaults_spec.lua
@@ -2,6 +2,7 @@ local helpers = require('test.functional.helpers')(after_each)
local Screen = require('test.functional.ui.screen')
+local assert_alive = helpers.assert_alive
local meths = helpers.meths
local command = helpers.command
local clear = helpers.clear
@@ -354,13 +355,13 @@ describe('XDG-based defaults', function()
.. ',' .. root_path .. ('/a'):rep(2048) .. '/nvim/after'
.. ',' .. root_path .. ('/x'):rep(4096) .. '/nvim/after'
):gsub('\\', '/')), (meths.get_option('runtimepath')):gsub('\\', '/'))
- eq('.,' .. root_path .. ('/X'):rep(4096).. '/' .. data_dir .. '/backup',
+ eq('.,' .. root_path .. ('/X'):rep(4096).. '/' .. data_dir .. '/backup//',
(meths.get_option('backupdir'):gsub('\\', '/')))
eq(root_path .. ('/X'):rep(4096) .. '/' .. data_dir .. '/swap//',
(meths.get_option('directory')):gsub('\\', '/'))
- eq(root_path .. ('/X'):rep(4096) .. '/' .. data_dir .. '/undo',
+ eq(root_path .. ('/X'):rep(4096) .. '/' .. data_dir .. '/undo//',
(meths.get_option('undodir')):gsub('\\', '/'))
- eq(root_path .. ('/X'):rep(4096) .. '/' .. data_dir .. '/view',
+ eq(root_path .. ('/X'):rep(4096) .. '/' .. data_dir .. '/view//',
(meths.get_option('viewdir')):gsub('\\', '/'))
end)
end)
@@ -404,13 +405,13 @@ describe('XDG-based defaults', function()
.. ',$XDG_DATA_DIRS/nvim/after'
.. ',$XDG_DATA_HOME/nvim/after'
):gsub('\\', '/')), (meths.get_option('runtimepath')):gsub('\\', '/'))
- eq(('.,$XDG_CONFIG_HOME/' .. data_dir .. '/backup'),
+ eq(('.,$XDG_CONFIG_HOME/' .. data_dir .. '/backup//'),
meths.get_option('backupdir'):gsub('\\', '/'))
eq(('$XDG_CONFIG_HOME/' .. data_dir .. '/swap//'),
meths.get_option('directory'):gsub('\\', '/'))
- eq(('$XDG_CONFIG_HOME/' .. data_dir .. '/undo'),
+ eq(('$XDG_CONFIG_HOME/' .. data_dir .. '/undo//'),
meths.get_option('undodir'):gsub('\\', '/'))
- eq(('$XDG_CONFIG_HOME/' .. data_dir .. '/view'),
+ eq(('$XDG_CONFIG_HOME/' .. data_dir .. '/view//'),
meths.get_option('viewdir'):gsub('\\', '/'))
meths.command('set all&')
eq(('$XDG_DATA_HOME/nvim'
@@ -424,13 +425,13 @@ describe('XDG-based defaults', function()
.. ',$XDG_DATA_DIRS/nvim/after'
.. ',$XDG_DATA_HOME/nvim/after'
):gsub('\\', '/'), (meths.get_option('runtimepath')):gsub('\\', '/'))
- eq(('.,$XDG_CONFIG_HOME/' .. data_dir .. '/backup'),
+ eq(('.,$XDG_CONFIG_HOME/' .. data_dir .. '/backup//'),
meths.get_option('backupdir'):gsub('\\', '/'))
eq(('$XDG_CONFIG_HOME/' .. data_dir .. '/swap//'),
meths.get_option('directory'):gsub('\\', '/'))
- eq(('$XDG_CONFIG_HOME/' .. data_dir .. '/undo'),
+ eq(('$XDG_CONFIG_HOME/' .. data_dir .. '/undo//'),
meths.get_option('undodir'):gsub('\\', '/'))
- eq(('$XDG_CONFIG_HOME/' .. data_dir .. '/view'),
+ eq(('$XDG_CONFIG_HOME/' .. data_dir .. '/view//'),
meths.get_option('viewdir'):gsub('\\', '/'))
end)
end)
@@ -483,13 +484,13 @@ describe('XDG-based defaults', function()
.. ',\\,-\\,-\\,' .. path_sep ..'nvim' .. path_sep ..'after'
.. ',\\, \\, \\,' .. path_sep ..'nvim' .. path_sep ..'after'
), meths.get_option('runtimepath'))
- eq('.,\\,=\\,=\\,' .. path_sep .. data_dir .. '' .. path_sep ..'backup',
+ eq('.,\\,=\\,=\\,' .. path_sep .. data_dir .. '' .. path_sep ..'backup' .. (path_sep):rep(2),
meths.get_option('backupdir'))
eq('\\,=\\,=\\,' .. path_sep ..'' .. data_dir .. '' .. path_sep ..'swap' .. (path_sep):rep(2),
meths.get_option('directory'))
- eq('\\,=\\,=\\,' .. path_sep ..'' .. data_dir .. '' .. path_sep ..'undo',
+ eq('\\,=\\,=\\,' .. path_sep ..'' .. data_dir .. '' .. path_sep ..'undo' .. (path_sep):rep(2),
meths.get_option('undodir'))
- eq('\\,=\\,=\\,' .. path_sep ..'' .. data_dir .. '' .. path_sep ..'view',
+ eq('\\,=\\,=\\,' .. path_sep ..'' .. data_dir .. '' .. path_sep ..'view' .. (path_sep):rep(2),
meths.get_option('viewdir'))
end)
end)
@@ -510,8 +511,7 @@ describe('stdpath()', function()
eq(datadir, funcs.fnamemodify(funcs.stdpath('data'), ':t'))
eq('table', type(funcs.stdpath('config_dirs')))
eq('table', type(funcs.stdpath('data_dirs')))
- -- Check for crash. #8393
- eq(2, eval('1+1'))
+ assert_alive() -- Check for crash. #8393
end)
context('returns a String', function()
diff --git a/test/functional/options/tabstop_spec.lua b/test/functional/options/tabstop_spec.lua
index dc3ba38438..e34f678650 100644
--- a/test/functional/options/tabstop_spec.lua
+++ b/test/functional/options/tabstop_spec.lua
@@ -1,9 +1,8 @@
local helpers = require('test.functional.helpers')(after_each)
+local assert_alive = helpers.assert_alive
local clear = helpers.clear
local feed = helpers.feed
-local eq = helpers.eq
-local eval = helpers.eval
describe("'tabstop' option", function()
before_each(function()
@@ -18,6 +17,6 @@ describe("'tabstop' option", function()
-- Set 'tabstop' to a very high value.
-- Use feed(), not command(), to provoke crash.
feed(':set tabstop=3000000000<CR>')
- eq(2, eval("1+1")) -- Still alive?
+ assert_alive()
end)
end)
diff --git a/test/functional/plugin/lsp_spec.lua b/test/functional/plugin/lsp_spec.lua
index aa2d8db206..16fe75d359 100644
--- a/test/functional/plugin/lsp_spec.lua
+++ b/test/functional/plugin/lsp_spec.lua
@@ -6,6 +6,7 @@ local buf_lines = helpers.buf_lines
local dedent = helpers.dedent
local exec_lua = helpers.exec_lua
local eq = helpers.eq
+local matches = helpers.matches
local pcall_err = helpers.pcall_err
local pesc = helpers.pesc
local insert = helpers.insert
@@ -1939,6 +1940,83 @@ describe('LSP', function()
end)
end)
+ describe('lsp.util.make_floating_popup_options', function()
+ before_each(function()
+ exec_lua [[
+ local bufnr = vim.uri_to_bufnr("file:///fake/uri")
+ local winheight = vim.fn.winheight(0)
+ for i = 1, winheight do
+ vim.api.nvim_buf_set_lines(bufnr, 0, 0, false, {''})
+ end
+ vim.api.nvim_win_set_buf(0, bufnr)
+ vim.api.nvim_win_set_cursor(0, {winheight, 0})
+ ]]
+ end)
+
+ local function popup_row(opts)
+ return exec_lua([[
+ return vim.lsp.util.make_floating_popup_options(...).row
+ ]], 2, 2, opts)
+ end
+
+ local err_pattern = "^Error executing lua: %.%.%./util%.lua:0: invalid floating preview border: .*%. :help vim%.api%.nvim_open_win%(%)$"
+
+ it('calculates default border height correctly', function()
+ eq(0, popup_row())
+ end)
+
+ it('calculates string border height correctly', function()
+ eq(0, popup_row({border = 'none'}))
+ eq(-2, popup_row({border = 'single'}))
+ eq(-2, popup_row({border = 'double'}))
+ eq(-2, popup_row({border = 'rounded'}))
+ eq(-2, popup_row({border = 'solid'}))
+ eq(-1, popup_row({border = 'shadow'}))
+ end)
+
+ it('error on invalid string border', function()
+ matches(err_pattern, pcall_err(popup_row, {border = ''}))
+ matches(err_pattern, pcall_err(popup_row, {border = 'invalid'}))
+ end)
+
+ it('error on invalid array border length', function()
+ matches(err_pattern, pcall_err(popup_row, {border = {}}))
+ matches(err_pattern, pcall_err(popup_row, {border = {'', '', ''}}))
+ matches(err_pattern, pcall_err(popup_row, {border = {'', '', '', '', ''}}))
+ end)
+
+ it('error on invalid array border member type', function()
+ matches(err_pattern, pcall_err(popup_row, {border = {0}}))
+ end)
+
+ it('calculates 8-array border height correctly', function()
+ eq(0, popup_row({border = {'', '', '', '', '', '', '', ''}}))
+ eq(-2, popup_row({border = {'', '~', '', '~', '', '~', '', '~'}}))
+ eq(-1, popup_row({border = {'', '', '', '~', '', '~', '', ''}}))
+ eq(0, popup_row({border = {'', '', '', {'~', 'NormalFloat'}, '', '', '', {'~', 'NormalFloat'}}}))
+ eq(-2, popup_row({border = {'', {'~', 'NormalFloat'}, '', '', '', {'~', 'NormalFloat'}, '', ''}}))
+ end)
+
+ it('calculates 4-array border height correctly', function()
+ eq(0, popup_row({border = {'', '', '', ''}}))
+ eq(-2, popup_row({border = {'', '~', '', '~'}}))
+ eq(0, popup_row({border = {'', '', '', {'~', 'NormalFloat'}}}))
+ eq(-2, popup_row({border = {'', {'~', 'NormalFloat'}, '', ''}}))
+ end)
+
+ it('calculates 2-array border height correctly', function()
+ eq(0, popup_row({border = {'', ''}}))
+ eq(-2, popup_row({border = {'', '~'}}))
+ eq(-2, popup_row({border = {'', {'~', 'NormalFloat'}}}))
+ end)
+
+ it('calculates 1-array border height correctly', function()
+ eq(0, popup_row({border = {''}}))
+ eq(-2, popup_row({border = {'~'}}))
+ eq(-2, popup_row({border = {{'~', 'NormalFloat'}}}))
+ end)
+ end)
+
describe('lsp.util._make_floating_popup_size', function()
before_each(function()
exec_lua [[ contents =
diff --git a/test/functional/provider/clipboard_spec.lua b/test/functional/provider/clipboard_spec.lua
index e5e21f11a6..986db96a18 100644
--- a/test/functional/provider/clipboard_spec.lua
+++ b/test/functional/provider/clipboard_spec.lua
@@ -653,14 +653,12 @@ describe('clipboard (with fake clipboard.vim)', function()
'',
'',
'E121: Undefined variable: doesnotexist',
- 'E15: Invalid expression: doesnotexist',
}, 'v'}, eval("g:test_clip['*']"))
feed_command(':echo "Howdy!"')
eq({{
'',
'',
'E121: Undefined variable: doesnotexist',
- 'E15: Invalid expression: doesnotexist',
'',
'Howdy!',
}, 'v'}, eval("g:test_clip['*']"))
diff --git a/test/functional/provider/python3_spec.lua b/test/functional/provider/python3_spec.lua
index d254edc7d5..d100db8de2 100644
--- a/test/functional/provider/python3_spec.lua
+++ b/test/functional/provider/python3_spec.lua
@@ -1,4 +1,5 @@
local helpers = require('test.functional.helpers')(after_each)
+local assert_alive = helpers.assert_alive
local eval, command, feed = helpers.eval, helpers.command, helpers.feed
local eq, clear, insert = helpers.eq, helpers.clear, helpers.insert
local expect, write_file = helpers.expect, helpers.write_file
@@ -116,6 +117,6 @@ describe('python3 provider', function()
feed_command("exe 'split' tempname()")
feed_command("bwipeout!")
feed_command('help help')
- eq(2, eval('1+1')) -- Still alive?
+ assert_alive()
end)
end)
diff --git a/test/functional/provider/ruby_spec.lua b/test/functional/provider/ruby_spec.lua
index 2729d8dfa2..fba96100fc 100644
--- a/test/functional/provider/ruby_spec.lua
+++ b/test/functional/provider/ruby_spec.lua
@@ -1,10 +1,10 @@
local helpers = require('test.functional.helpers')(after_each)
+local assert_alive = helpers.assert_alive
local clear = helpers.clear
local command = helpers.command
local curbufmeths = helpers.curbufmeths
local eq = helpers.eq
-local eval = helpers.eval
local exc_exec = helpers.exc_exec
local expect = helpers.expect
local feed = helpers.feed
@@ -107,7 +107,7 @@ describe('ruby provider', function()
helpers.add_builddir_to_rtp()
command([=[autocmd BufDelete * ruby VIM::evaluate('expand("<afile>")')]=])
feed_command('help help')
- eq(2, eval('1+1')) -- Still alive?
+ assert_alive()
end)
end)
diff --git a/test/functional/shada/history_spec.lua b/test/functional/shada/history_spec.lua
index 9291f5e100..84cc34c7cc 100644
--- a/test/functional/shada/history_spec.lua
+++ b/test/functional/shada/history_spec.lua
@@ -2,7 +2,7 @@
local helpers = require('test.functional.helpers')(after_each)
local nvim_command, funcs, meths, nvim_feed, eq =
helpers.command, helpers.funcs, helpers.meths, helpers.feed, helpers.eq
-local eval = helpers.eval
+local assert_alive = helpers.assert_alive
local shada_helpers = require('test.functional.shada.helpers')
local reset, clear = shada_helpers.reset, shada_helpers.clear
@@ -244,7 +244,7 @@ describe('ShaDa support code', function()
nvim_command('wshada')
nvim_command('set shada=\'10,:0')
nvim_command('wshada')
- eq(2, eval('1+1')) -- check nvim still running
+ assert_alive()
end)
end)
diff --git a/test/functional/terminal/buffer_spec.lua b/test/functional/terminal/buffer_spec.lua
index c61bf108cb..103ae59b8e 100644
--- a/test/functional/terminal/buffer_spec.lua
+++ b/test/functional/terminal/buffer_spec.lua
@@ -1,5 +1,6 @@
local helpers = require('test.functional.helpers')(after_each)
local thelpers = require('test.functional.terminal.helpers')
+local assert_alive = helpers.assert_alive
local feed, clear, nvim = helpers.feed, helpers.clear, helpers.nvim
local poke_eventloop = helpers.poke_eventloop
local eval, feed_command, source = helpers.eval, helpers.feed_command, helpers.source
@@ -7,6 +8,7 @@ local eq, neq = helpers.eq, helpers.neq
local write_file = helpers.write_file
local command= helpers.command
local exc_exec = helpers.exc_exec
+local matches = helpers.matches
describe(':terminal buffer', function()
local screen
@@ -255,8 +257,23 @@ describe(':terminal buffer', function()
command('bdelete!')
end)
- it('handles wqall', function()
+ it('requires bang (!) to close a running job #15402', function()
eq('Vim(wqall):E948: Job still running', exc_exec('wqall'))
+ for _, cmd in ipairs({ 'bdelete', '%bdelete', 'bwipeout', 'bunload' }) do
+ matches('^Vim%('..cmd:gsub('%%', '')..'%):E89: term://.*tty%-test.* will be killed %(add %! to override%)$',
+ exc_exec(cmd))
+ end
+ command('call jobstop(&channel)')
+ assert(0 >= eval('jobwait([&channel], 1000)[0]'))
+ command('bdelete')
+ end)
+
+ it('stops running jobs with :quit', function()
+ -- Open in a new window to avoid terminating the nvim instance
+ command('split')
+ command('terminal')
+ command('set nohidden')
+ command('quit')
end)
it('does not segfault when pasting empty buffer #13955', function()
@@ -284,7 +301,7 @@ describe('No heap-buffer-overflow when using', function()
feed('$')
-- Let termopen() modify the buffer
feed_command('call termopen("echo")')
- eq(2, eval('1+1')) -- check nvim still running
+ assert_alive()
feed_command('bdelete!')
end)
end)
@@ -294,6 +311,6 @@ describe('No heap-buffer-overflow when', function()
feed_command('set nowrap')
feed_command('autocmd TermOpen * startinsert')
feed_command('call feedkeys("4000ai\\<esc>:terminal!\\<cr>")')
- eq(2, eval('1+1'))
+ assert_alive()
end)
end)
diff --git a/test/functional/terminal/ex_terminal_spec.lua b/test/functional/terminal/ex_terminal_spec.lua
index 4b512605e1..707c355069 100644
--- a/test/functional/terminal/ex_terminal_spec.lua
+++ b/test/functional/terminal/ex_terminal_spec.lua
@@ -1,5 +1,6 @@
local helpers = require('test.functional.helpers')(after_each)
local Screen = require('test.functional.ui.screen')
+local assert_alive = helpers.assert_alive
local clear, poke_eventloop, nvim = helpers.clear, helpers.poke_eventloop, helpers.nvim
local nvim_dir, source, eq = helpers.nvim_dir, helpers.source, helpers.eq
local feed = helpers.feed
@@ -215,7 +216,7 @@ describe(':terminal (with fake shell)', function()
-- handler), :terminal cleanup is pending on the main-loop.
-- This write should be ignored (not crash, #5445).
feed('iiYYYYYYY')
- eq(2, eval("1+1")) -- Still alive?
+ assert_alive()
end)
it('works with findfile()', function()
diff --git a/test/functional/terminal/tui_spec.lua b/test/functional/terminal/tui_spec.lua
index 8a5dd7ef18..f7520b14d4 100644
--- a/test/functional/terminal/tui_spec.lua
+++ b/test/functional/terminal/tui_spec.lua
@@ -8,12 +8,12 @@ local helpers = require('test.functional.helpers')(after_each)
local uname = helpers.uname
local thelpers = require('test.functional.terminal.helpers')
local Screen = require('test.functional.ui.screen')
+local assert_alive = helpers.assert_alive
local eq = helpers.eq
local feed_command = helpers.feed_command
local feed_data = thelpers.feed_data
local clear = helpers.clear
local command = helpers.command
-local eval = helpers.eval
local nvim_dir = helpers.nvim_dir
local retry = helpers.retry
local nvim_prog = helpers.nvim_prog
@@ -82,7 +82,7 @@ describe('TUI', function()
command('call jobresize(b:terminal_job_id, 1, 4)')
screen:try_resize(57, 17)
command('call jobresize(b:terminal_job_id, 57, 17)')
- eq(2, eval("1+1")) -- Still alive?
+ assert_alive()
end)
it('accepts resize while pager is active', function()
diff --git a/test/functional/terminal/window_split_tab_spec.lua b/test/functional/terminal/window_split_tab_spec.lua
index 03bd336aec..188afa1e84 100644
--- a/test/functional/terminal/window_split_tab_spec.lua
+++ b/test/functional/terminal/window_split_tab_spec.lua
@@ -1,5 +1,6 @@
local helpers = require('test.functional.helpers')(after_each)
local thelpers = require('test.functional.terminal.helpers')
+local assert_alive = helpers.assert_alive
local clear = helpers.clear
local feed, nvim = helpers.feed, helpers.nvim
local feed_command = helpers.feed_command
@@ -33,7 +34,7 @@ describe(':terminal', function()
command('vsplit foo')
eq(3, eval("winnr('$')"))
feed('ZQ') -- Close split, should not crash. #7538
- eq(2, eval("1+1")) -- Still alive?
+ assert_alive()
end)
it('does not change size on WinEnter', function()
diff --git a/test/functional/ui/cursor_spec.lua b/test/functional/ui/cursor_spec.lua
index f75f700fb5..9c035c728b 100644
--- a/test/functional/ui/cursor_spec.lua
+++ b/test/functional/ui/cursor_spec.lua
@@ -212,10 +212,10 @@ describe('ui/cursor', function()
if m.blinkwait then m.blinkwait = 700 end
end
if m.hl_id then
- m.hl_id = 56
+ m.hl_id = 58
m.attr = {background = Screen.colors.DarkGray}
end
- if m.id_lm then m.id_lm = 57 end
+ if m.id_lm then m.id_lm = 59 end
end
-- Assert the new expectation.
diff --git a/test/functional/ui/float_spec.lua b/test/functional/ui/float_spec.lua
index be22d9a403..59ce7c82e2 100644
--- a/test/functional/ui/float_spec.lua
+++ b/test/functional/ui/float_spec.lua
@@ -5036,7 +5036,7 @@ describe('float window', function()
]])
end
- eq(2, eval('1+1'))
+ assert_alive()
end)
it("o (:only) non-float", function()
diff --git a/test/functional/ui/highlight_spec.lua b/test/functional/ui/highlight_spec.lua
index 499aeba6ec..c00d30fe32 100644
--- a/test/functional/ui/highlight_spec.lua
+++ b/test/functional/ui/highlight_spec.lua
@@ -1292,6 +1292,75 @@ describe("MsgSeparator highlight and msgsep fillchar", function()
end)
end)
+describe("'number' and 'relativenumber' highlight", function()
+ before_each(clear)
+
+ it('LineNr, LineNrAbove and LineNrBelow', function()
+ local screen = Screen.new(20,10)
+ screen:set_default_attr_ids({
+ [1] = {foreground = Screen.colors.Red},
+ [2] = {foreground = Screen.colors.Blue},
+ [3] = {foreground = Screen.colors.Green},
+ })
+ screen:attach()
+ command('set number relativenumber')
+ command('call setline(1, range(50))')
+ command('highlight LineNr guifg=Red')
+ feed('4j')
+ screen:expect([[
+ {1: 4 }0 |
+ {1: 3 }1 |
+ {1: 2 }2 |
+ {1: 1 }3 |
+ {1:5 }^4 |
+ {1: 1 }5 |
+ {1: 2 }6 |
+ {1: 3 }7 |
+ {1: 4 }8 |
+ |
+ ]])
+ command('highlight LineNrAbove guifg=Blue')
+ screen:expect([[
+ {2: 4 }0 |
+ {2: 3 }1 |
+ {2: 2 }2 |
+ {2: 1 }3 |
+ {1:5 }^4 |
+ {1: 1 }5 |
+ {1: 2 }6 |
+ {1: 3 }7 |
+ {1: 4 }8 |
+ |
+ ]])
+ command('highlight LineNrBelow guifg=Green')
+ screen:expect([[
+ {2: 4 }0 |
+ {2: 3 }1 |
+ {2: 2 }2 |
+ {2: 1 }3 |
+ {1:5 }^4 |
+ {3: 1 }5 |
+ {3: 2 }6 |
+ {3: 3 }7 |
+ {3: 4 }8 |
+ |
+ ]])
+ feed('3j')
+ screen:expect([[
+ {2: 7 }0 |
+ {2: 6 }1 |
+ {2: 5 }2 |
+ {2: 4 }3 |
+ {2: 3 }4 |
+ {2: 2 }5 |
+ {2: 1 }6 |
+ {1:8 }^7 |
+ {3: 1 }8 |
+ |
+ ]])
+ end)
+end)
+
describe("'winhighlight' highlight", function()
local screen
diff --git a/test/functional/ui/output_spec.lua b/test/functional/ui/output_spec.lua
index 3826707743..50e5dfac84 100644
--- a/test/functional/ui/output_spec.lua
+++ b/test/functional/ui/output_spec.lua
@@ -1,9 +1,9 @@
local Screen = require('test.functional.ui.screen')
local helpers = require('test.functional.helpers')(after_each)
local child_session = require('test.functional.terminal.helpers')
+local assert_alive = helpers.assert_alive
local mkdir, write_file, rmdir = helpers.mkdir, helpers.write_file, helpers.rmdir
local eq = helpers.eq
-local eval = helpers.eval
local feed = helpers.feed
local feed_command = helpers.feed_command
local iswin = helpers.iswin
@@ -86,12 +86,12 @@ describe("shell command :!", function()
it("cat a binary file #4142", function()
feed(":exe 'silent !cat '.shellescape(v:progpath)<CR>")
- eq(2, eval('1+1')) -- Still alive?
+ assert_alive()
end)
it([[display \x08 char #4142]], function()
feed(":silent !echo \08<CR>")
- eq(2, eval('1+1')) -- Still alive?
+ assert_alive()
end)
it('handles control codes', function()
diff --git a/test/functional/ui/popupmenu_spec.lua b/test/functional/ui/popupmenu_spec.lua
index 0944bfc21a..aeba049557 100644
--- a/test/functional/ui/popupmenu_spec.lua
+++ b/test/functional/ui/popupmenu_spec.lua
@@ -1,5 +1,6 @@
local helpers = require('test.functional.helpers')(after_each)
local Screen = require('test.functional.ui.screen')
+local assert_alive = helpers.assert_alive
local clear, feed = helpers.clear, helpers.feed
local source = helpers.source
local insert = helpers.insert
@@ -9,7 +10,6 @@ local funcs = helpers.funcs
local get_pathsep = helpers.get_pathsep
local eq = helpers.eq
local pcall_err = helpers.pcall_err
-local eval = helpers.eval
describe('ui/ext_popupmenu', function()
local screen
@@ -2211,6 +2211,6 @@ describe('builtin popupmenu', function()
feed('$i')
funcs.complete(col - max_len, items)
feed('<c-y>')
- eq(2, eval('1+1'))
+ assert_alive()
end)
end)
diff --git a/test/functional/viml/completion_spec.lua b/test/functional/viml/completion_spec.lua
index a4241fe5aa..befad29922 100644
--- a/test/functional/viml/completion_spec.lua
+++ b/test/functional/viml/completion_spec.lua
@@ -1,5 +1,6 @@
local helpers = require('test.functional.helpers')(after_each)
local Screen = require('test.functional.ui.screen')
+local assert_alive = helpers.assert_alive
local clear, feed = helpers.clear, helpers.feed
local eval, eq, neq = helpers.eval, helpers.eq, helpers.neq
local feed_command, source, expect = helpers.feed_command, helpers.source, helpers.expect
@@ -870,7 +871,7 @@ describe('completion', function()
{3:-- Keyword completion (^N^P) }{4:match 1 of 2} |
]])
- eval('1 + 1')
+ assert_alive()
-- popupmenu still visible
screen:expect{grid=[[
foobar fooegg |