aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ci/common/suite.sh1
-rw-r--r--runtime/autoload/health/provider.vim24
-rw-r--r--runtime/autoload/provider/pythonx.vim4
-rw-r--r--runtime/doc/api.txt75
-rw-r--r--runtime/doc/arabic.txt2
-rw-r--r--runtime/doc/builtin.txt29
-rw-r--r--runtime/doc/diagnostic.txt8
-rw-r--r--runtime/doc/eval.txt16
-rw-r--r--runtime/doc/index.txt3
-rw-r--r--runtime/doc/lsp.txt80
-rw-r--r--runtime/doc/lua.txt28
-rw-r--r--runtime/doc/options.txt28
-rw-r--r--runtime/doc/quickfix.txt13
-rw-r--r--runtime/doc/remote.txt2
-rw-r--r--runtime/doc/syntax.txt4
-rw-r--r--runtime/doc/tabpage.txt7
-rw-r--r--runtime/doc/treesitter.txt6
-rw-r--r--runtime/doc/usr_08.txt2
-rw-r--r--runtime/doc/vim_diff.txt8
-rw-r--r--runtime/doc/windows.txt2
-rw-r--r--runtime/filetype.lua38
-rw-r--r--runtime/filetype.vim2
-rw-r--r--runtime/lua/vim/_editor.lua104
-rw-r--r--runtime/lua/vim/filetype.lua3
-rw-r--r--runtime/lua/vim/keymap.lua4
-rw-r--r--runtime/lua/vim/lsp.lua2
-rw-r--r--runtime/lua/vim/shared.lua2
-rw-r--r--runtime/spell/cleanadd.vim32
-rwxr-xr-xscripts/gen_vimdoc.py71
-rwxr-xr-xscripts/vim-patch.sh4
-rwxr-xr-x[-rw-r--r--]src/nvim/CMakeLists.txt4
-rw-r--r--src/nvim/api/buffer.c3
-rw-r--r--src/nvim/api/deprecated.c3
-rw-r--r--src/nvim/api/extmark.c4
-rw-r--r--src/nvim/api/private/converter.c17
-rw-r--r--src/nvim/api/private/dispatch.c8
-rw-r--r--src/nvim/api/private/helpers.c11
-rw-r--r--src/nvim/api/tabpage.c6
-rw-r--r--src/nvim/api/ui_events.in.h4
-rw-r--r--src/nvim/api/vim.c52
-rw-r--r--src/nvim/api/win_config.c3
-rw-r--r--src/nvim/api/window.c2
-rw-r--r--src/nvim/autocmd.c120
-rw-r--r--src/nvim/buffer.c17
-rw-r--r--src/nvim/buffer_defs.h9
-rw-r--r--src/nvim/change.c80
-rw-r--r--src/nvim/channel.c16
-rw-r--r--src/nvim/channel.h1
-rw-r--r--src/nvim/charset.c50
-rw-r--r--src/nvim/cursor.c176
-rw-r--r--src/nvim/cursor_shape.c20
-rw-r--r--src/nvim/debugger.c30
-rw-r--r--src/nvim/decoration.c2
-rw-r--r--src/nvim/diff.c160
-rw-r--r--src/nvim/digraph.c48
-rw-r--r--src/nvim/edit.c9
-rw-r--r--src/nvim/eval.c858
-rw-r--r--src/nvim/eval/funcs.c1069
-rw-r--r--src/nvim/event/socket.c13
-rw-r--r--src/nvim/ex_cmds.c208
-rw-r--r--src/nvim/ex_cmds2.c53
-rw-r--r--src/nvim/ex_docmd.c32
-rw-r--r--src/nvim/ex_eval.c315
-rw-r--r--src/nvim/ex_getln.c9
-rw-r--r--src/nvim/ex_session.c4
-rw-r--r--src/nvim/fold.c402
-rw-r--r--src/nvim/generators/c_grammar.lua1
-rwxr-xr-x[-rw-r--r--]src/nvim/generators/gen_api_ui_events.lua74
-rw-r--r--src/nvim/getchar.c5
-rw-r--r--src/nvim/globals.h13
-rw-r--r--src/nvim/hardcopy.c1
-rw-r--r--src/nvim/highlight.c2
-rw-r--r--src/nvim/highlight_defs.h6
-rw-r--r--src/nvim/highlight_group.c2799
-rw-r--r--src/nvim/highlight_group.h19
-rw-r--r--src/nvim/indent.c13
-rw-r--r--src/nvim/lua/converter.c41
-rw-r--r--src/nvim/lua/executor.c17
-rw-r--r--src/nvim/main.c175
-rw-r--r--src/nvim/map.c1
-rw-r--r--src/nvim/map.h2
-rw-r--r--src/nvim/memory.c1
-rw-r--r--src/nvim/message.c323
-rw-r--r--src/nvim/mouse.c16
-rw-r--r--src/nvim/msgpack_rpc/channel.c3
-rw-r--r--src/nvim/normal.c11
-rw-r--r--src/nvim/option.c67
-rw-r--r--src/nvim/os/env.c4
-rw-r--r--src/nvim/os/pty_process_unix.c2
-rw-r--r--src/nvim/os/pty_process_win.c5
-rw-r--r--src/nvim/os/shell.c2
-rw-r--r--src/nvim/quickfix.c179
-rw-r--r--src/nvim/rbuffer.h14
-rw-r--r--src/nvim/screen.c452
-rw-r--r--src/nvim/screen.h18
-rw-r--r--src/nvim/search.c2
-rw-r--r--src/nvim/sign.c9
-rw-r--r--src/nvim/syntax.c2824
-rw-r--r--src/nvim/syntax.h6
-rw-r--r--src/nvim/syntax_defs.h16
-rw-r--r--src/nvim/tag.h10
-rw-r--r--src/nvim/terminal.c12
-rw-r--r--src/nvim/testdir/check.vim8
-rwxr-xr-xsrc/nvim/testdir/runnvim.sh4
-rw-r--r--src/nvim/testdir/test_cmdline.vim12
-rw-r--r--src/nvim/testdir/test_exit.vim22
-rw-r--r--src/nvim/testdir/test_filetype.vim2
-rw-r--r--src/nvim/testdir/test_functions.vim69
-rw-r--r--src/nvim/testdir/test_highlight.vim4
-rw-r--r--src/nvim/testdir/test_mksession.vim5
-rw-r--r--src/nvim/testdir/test_quickfix.vim145
-rw-r--r--src/nvim/testdir/test_tabpage.vim71
-rw-r--r--src/nvim/tui/input.c26
-rw-r--r--src/nvim/ui.c17
-rw-r--r--src/nvim/ui_client.c215
-rw-r--r--src/nvim/ui_client.h13
-rw-r--r--src/nvim/ui_compositor.c2
-rw-r--r--src/nvim/undo_defs.h6
-rw-r--r--src/nvim/viml/parser/parser.h6
-rw-r--r--src/nvim/window.c403
-rw-r--r--src/nvim/window.h12
-rw-r--r--test/functional/api/vim_spec.lua427
-rw-r--r--test/functional/core/channels_spec.lua21
-rw-r--r--test/functional/lua/overrides_spec.lua38
-rw-r--r--test/functional/lua/vim_spec.lua98
-rw-r--r--test/functional/provider/python3_spec.lua8
-rw-r--r--test/functional/terminal/channel_spec.lua87
-rw-r--r--test/functional/terminal/tui_spec.lua14
-rw-r--r--test/functional/ui/cursor_spec.lua4
-rw-r--r--test/functional/ui/global_statusline_spec.lua233
-rw-r--r--test/functional/ui/hlstate_spec.lua2
-rw-r--r--test/unit/viml/expressions/parser_spec.lua1
132 files changed, 7337 insertions, 6205 deletions
diff --git a/ci/common/suite.sh b/ci/common/suite.sh
index c0c470dce1..0320ac15c3 100644
--- a/ci/common/suite.sh
+++ b/ci/common/suite.sh
@@ -14,6 +14,7 @@ fail() {
local full_msg="$test_name :: $message"
echo "${full_msg}" >> "${FAIL_SUMMARY_FILE}"
echo "Failed: $full_msg"
+ FAILED=1
}
ended_successfully() {
diff --git a/runtime/autoload/health/provider.vim b/runtime/autoload/health/provider.vim
index 2f35179338..6022e05c22 100644
--- a/runtime/autoload/health/provider.vim
+++ b/runtime/autoload/health/provider.vim
@@ -301,7 +301,7 @@ function! s:check_python() abort
call health#report_info(printf('Using: g:%s = "%s"', host_prog_var, get(g:, host_prog_var)))
endif
- let [pyname, pythonx_errors] = provider#pythonx#Detect(3)
+ let [pyname, pythonx_warnings] = provider#pythonx#Detect(3)
if empty(pyname)
call health#report_warn('No Python executable found that can `import neovim`. '
@@ -311,8 +311,9 @@ function! s:check_python() abort
endif
" No Python executable could `import neovim`, or host_prog_var was used.
- if !empty(pythonx_errors)
- call health#report_error('Python provider error:', pythonx_errors)
+ if !empty(pythonx_warnings)
+ call health#report_warn(pythonx_warnings, ['See :help provider-python for more information.',
+ \ 'You may disable this provider (and warning) by adding `let g:loaded_python3_provider = 0` to your init.vim'])
elseif !empty(pyname) && empty(python_exe)
if !exists('g:'.host_prog_var)
@@ -573,7 +574,8 @@ function! s:check_ruby() abort
\ ['Run `gem install neovim` to ensure the neovim RubyGem is installed.',
\ 'Run `gem environment` to ensure the gem bin directory is in $PATH.',
\ 'If you are using rvm/rbenv/chruby, try "rehashing".',
- \ 'See :help g:ruby_host_prog for non-standard gem installations.'])
+ \ 'See :help g:ruby_host_prog for non-standard gem installations.',
+ \ 'You may disable this provider (and warning) by adding `let g:loaded_ruby_provider = 0` to your init.vim'])
return
endif
call health#report_info('Host: '. host)
@@ -634,7 +636,8 @@ function! s:check_node() abort
if empty(host)
call health#report_warn('Missing "neovim" npm (or yarn) package.',
\ ['Run in shell: npm install -g neovim',
- \ 'Run in shell (if you use yarn): yarn global add neovim'])
+ \ 'Run in shell (if you use yarn): yarn global add neovim',
+ \ 'You may disable this provider (and warning) by adding `let g:loaded_node_provider = 0` to your init.vim'])
return
endif
call health#report_info('Nvim node.js host: '. host)
@@ -683,14 +686,15 @@ function! s:check_perl() abort
return
endif
- let [perl_exec, perl_errors] = provider#perl#Detect()
+ let [perl_exec, perl_warnings] = provider#perl#Detect()
if empty(perl_exec)
- if !empty(perl_errors)
- call health#report_error('perl provider error:', perl_errors)
- else
+ if !empty(perl_warnings)
+ call health#report_warn(perl_warnings, ['See :help provider-perl for more information.',
+ \ 'You may disable this provider (and warning) by adding `let g:loaded_node_provider = 0` to your init.vim'])
+ else
call health#report_warn('No usable perl executable found')
endif
- return
+ return
endif
call health#report_info('perl executable: '. perl_exec)
diff --git a/runtime/autoload/provider/pythonx.vim b/runtime/autoload/provider/pythonx.vim
index 5b299b322c..048f898e62 100644
--- a/runtime/autoload/provider/pythonx.vim
+++ b/runtime/autoload/provider/pythonx.vim
@@ -56,7 +56,7 @@ function! provider#pythonx#DetectByModule(module, major_version) abort
endfor
" No suitable Python executable found.
- return ['', 'provider/pythonx: Could not load Python '.a:major_version.":\n".join(errors, "\n")]
+ return ['', 'Could not load Python '.a:major_version.":\n".join(errors, "\n")]
endfunction
" Returns array: [prog_exitcode, prog_version]
@@ -99,7 +99,7 @@ function! provider#pythonx#CheckForModule(prog, module, major_version) abort
endif
if prog_exitcode == 2
- return [0, prog_path.' does not have the "' . a:module . '" module. :help provider-python']
+ return [0, prog_path.' does not have the "' . a:module . '" module.']
elseif prog_exitcode == 127
" This can happen with pyenv's shims.
return [0, prog_path . ' does not exist: ' . prog_version]
diff --git a/runtime/doc/api.txt b/runtime/doc/api.txt
index eefe6e5a47..4af13a3bbf 100644
--- a/runtime/doc/api.txt
+++ b/runtime/doc/api.txt
@@ -594,7 +594,8 @@ nvim__id_float({flt}) *nvim__id_float()*
its argument.
nvim__inspect_cell({grid}, {row}, {col}) *nvim__inspect_cell()*
- TODO: Documentation
+ NB: if your UI doesn't use hlstate, this will not return
+ hlstate first time.
nvim__runtime_inspect() *nvim__runtime_inspect()*
TODO: Documentation
@@ -709,7 +710,7 @@ nvim_call_atomic({calls}) *nvim_call_atomic()*
be returned.
nvim_chan_send({chan}, {data}) *nvim_chan_send()*
- Send data to channel `id` . For a job, it writes it to the
+ Send data to channel `id`. For a job, it writes it to the
stdin of the process. For the stdio channel |channel-stdio|,
it writes to Nvim's stdout. For an internal terminal instance
(|nvim_open_term()|) it writes directly to terminal output.
@@ -849,7 +850,7 @@ nvim_exec_lua({code}, {args}) *nvim_exec_lua()*
inside the chunk. The chunk can return a value.
Only statements are executed. To evaluate an expression,
- prefix it with `return` : return my_function(...)
+ prefix it with `return`: return my_function(...)
Parameters: ~
{code} Lua code to execute
@@ -1132,13 +1133,13 @@ nvim_get_option_value({name}, {*opts}) *nvim_get_option_value()*
Option value
nvim_get_proc({pid}) *nvim_get_proc()*
- Gets info describing process `pid` .
+ Gets info describing process `pid`.
Return: ~
Map of process properties, or NIL if process not found.
nvim_get_proc_children({pid}) *nvim_get_proc_children()*
- Gets the immediate children of process `pid` .
+ Gets the immediate children of process `pid`.
Return: ~
Array of child process ids, empty if process not found.
@@ -1247,8 +1248,8 @@ nvim_input_mouse({button}, {action}, {modifier}, {grid}, {row}, {col})
nvim_list_bufs() *nvim_list_bufs()*
Gets the current list of buffer handles
- Includes unlisted (unloaded/deleted) buffers, like `:ls!` .
- Use |nvim_buf_is_loaded()| to check if a buffer is loaded.
+ Includes unlisted (unloaded/deleted) buffers, like `:ls!`. Use
+ |nvim_buf_is_loaded()| to check if a buffer is loaded.
Return: ~
List of buffer handles
@@ -1357,7 +1358,7 @@ nvim_paste({data}, {crlf}, {phase}) *nvim_paste()*
Errors ('nomodifiable', `vim.paste()` failure, …) are
reflected in `err` but do not affect the return value (which
- is strictly decided by `vim.paste()` ). On error, subsequent
+ is strictly decided by `vim.paste()`). On error, subsequent
calls are ignored ("drained") until the next paste is
initiated (phase 1 or -1).
@@ -1434,7 +1435,7 @@ nvim_select_popupmenu_item({item}, {insert}, {finish}, {opts})
{insert} Whether the selection should be inserted in the
buffer.
{finish} Finish the completion and dismiss the popupmenu.
- Implies `insert` .
+ Implies `insert`.
{opts} Optional parameters. Reserved for future use.
*nvim_set_client_info()*
@@ -1544,23 +1545,24 @@ nvim_set_current_win({window}) *nvim_set_current_win()*
{window} Window handle
nvim_set_hl({ns_id}, {name}, {*val}) *nvim_set_hl()*
- Set a highlight group.
-
- Parameters: ~
- {ns_id} number of namespace for this highlight. Use value
- 0 to set a highlight group in the global (
- `:highlight` ) namespace.
- {name} highlight group name, like ErrorMsg
- {val} highlight definition map, like
- |nvim_get_hl_by_name|. in addition the following
- keys are also recognized: `default` : don't
- override existing definition, like `hi default`
- `ctermfg` : sets foreground of cterm color
- `ctermbg` : sets background of cterm color
- `cterm` : cterm attribute map. sets attributed
- for cterm colors. similer to `hi cterm` Note: by
- default cterm attributes are same as attributes
- of gui color
+ Sets a highlight group.
+
+ Parameters: ~
+ {ns_id} Namespace id for this highlight
+ |nvim_create_namespace()|. Use 0 to set a
+ highlight group globally |:highlight|.
+ {name} Highlight group name, e.g. "ErrorMsg"
+ {val} Highlight definition map, like |synIDattr()|. In
+ addition, the following keys are recognized:
+ • default: Don't override existing definition
+ |:hi-default|
+ • ctermfg: Sets foreground of cterm color
+ |highlight-ctermfg|
+ • ctermbg: Sets background of cterm color
+ |highlight-ctermbg|
+ • cterm: cterm attribute map, like
+ |highlight-args|. Note: Attributes default to
+ those set for `gui` if not set.
nvim_set_keymap({mode}, {lhs}, {rhs}, {*opts}) *nvim_set_keymap()*
Sets a global |mapping| for the given mode.
@@ -1629,7 +1631,7 @@ nvim_set_vvar({name}, {value}) *nvim_set_vvar()*
{value} Variable value
nvim_strwidth({text}) *nvim_strwidth()*
- Calculates the number of display cells occupied by `text` .
+ Calculates the number of display cells occupied by `text`.
<Tab> counts as one cell.
Parameters: ~
@@ -1881,9 +1883,10 @@ nvim_buf_attach({buffer}, {send_buffer}, {opts}) *nvim_buf_attach()*
{buffer} Buffer handle, or 0 for current buffer
{send_buffer} True if the initial notification should
contain the whole buffer: first
- notification will be `nvim_buf_lines_event`
- . Else the first notification will be
- `nvim_buf_changedtick_event` . Not for Lua
+ notification will be
+ `nvim_buf_lines_event`. Else the first
+ notification will be
+ `nvim_buf_changedtick_event`. Not for Lua
callbacks.
{opts} Optional parameters.
• on_lines: Lua callback invoked on change.
@@ -1939,7 +1942,7 @@ nvim_buf_attach({buffer}, {send_buffer}, {opts}) *nvim_buf_attach()*
• utf_sizes: include UTF-32 and UTF-16 size
of the replaced region, as args to
- `on_lines` .
+ `on_lines`.
• preview: also attach to command preview
(i.e. 'inccommand') events.
@@ -2354,7 +2357,7 @@ nvim_buf_add_highlight({buffer}, {ns_id}, {hl_group}, {line}, {col_start},
namespace. All highlights in the same namespace can then be
cleared with single call to |nvim_buf_clear_namespace()|. If
the highlight never will be deleted by an API call, pass
- `ns_id = -1` .
+ `ns_id = -1`.
As a shorthand, `ns_id = 0` can be used to create a new
namespace for the highlight, the allocated id is then
@@ -2434,8 +2437,8 @@ nvim_buf_get_extmarks({buffer}, {ns_id}, {start}, {end}, {opts})
nvim_buf_get_extmarks(0, my_ns, [0,0], [-1,-1], {})
<
- If `end` is less than `start` , traversal works backwards.
- (Useful with `limit` , to get the first marks prior to a given
+ If `end` is less than `start`, traversal works backwards.
+ (Useful with `limit`, to get the first marks prior to a given
position.)
Example:
@@ -2782,7 +2785,7 @@ nvim_win_hide({window}) *nvim_win_hide()*
|:hide| with a |window-ID|).
Like |:hide| the buffer becomes hidden unless another window
- is editing it, or 'bufhidden' is `unload` , `delete` or `wipe`
+ is editing it, or 'bufhidden' is `unload`, `delete` or `wipe`
as opposed to |:close| or |nvim_win_close|, which will close
the buffer.
@@ -3030,7 +3033,7 @@ nvim_win_set_config({window}, {*config}) *nvim_win_set_config()*
layouts).
When reconfiguring a floating window, absent option keys will
- not be changed. `row` / `col` and `relative` must be
+ not be changed. `row`/`col` and `relative` must be
reconfigured together.
Parameters: ~
diff --git a/runtime/doc/arabic.txt b/runtime/doc/arabic.txt
index 5d3bf7a761..0df861111c 100644
--- a/runtime/doc/arabic.txt
+++ b/runtime/doc/arabic.txt
@@ -175,7 +175,7 @@ o Enable Arabic settings [short-cut]
vertical separator like "l" or "𝖨" may be used. It may also be
hidden by changing its color to the foreground color: >
:set fillchars=vert:l
- :hi VertSplit ctermbg=White
+ :hi WinSeparator ctermbg=White
< Note that this is a workaround, not a proper solution.
If, on the other hand, you'd like to be verbose and explicit and
diff --git a/runtime/doc/builtin.txt b/runtime/doc/builtin.txt
index ea7a53fa3b..9eec23b7b7 100644
--- a/runtime/doc/builtin.txt
+++ b/runtime/doc/builtin.txt
@@ -1284,7 +1284,7 @@ complete_info([{what}]) *complete_info()*
<
*confirm()*
confirm({msg} [, {choices} [, {default} [, {type}]]])
- Confirm() offers the user a dialog, from which a choice can be
+ confirm() offers the user a dialog, from which a choice can be
made. It returns the number of the choice. For the first
choice this is 1.
@@ -3039,10 +3039,16 @@ getloclist({nr} [, {what}]) *getloclist()*
If the optional {what} dictionary argument is supplied, then
returns the items listed in {what} as a dictionary. Refer to
|getqflist()| for the supported items in {what}.
- If {what} contains 'filewinid', then returns the id of the
- window used to display files from the location list. This
- field is applicable only when called from a location list
- window. See |location-list-file-window| for more details.
+
+ In addition to the items supported by |getqflist()| in {what},
+ the following item is supported by |getloclist()|:
+
+ filewinid id of the window used to display files
+ from the location list. This field is
+ applicable only when called from a
+ location list window. See
+ |location-list-file-window| for more
+ details.
Returns a |Dictionary| with default values if there is no
location list for the window {nr}.
@@ -3218,6 +3224,9 @@ getqflist([{what}]) *getqflist()*
nr get information for this quickfix list; zero
means the current quickfix list and "$" means
the last quickfix list
+ qfbufnr number of the buffer displayed in the quickfix
+ window. Returns 0 if the quickfix buffer is
+ not present. See |quickfix-buffer|.
size number of entries in the quickfix list
title get the list title |quickfix-title|
winid get the quickfix |window-ID|
@@ -3246,6 +3255,8 @@ getqflist([{what}]) *getqflist()*
items quickfix list entries. If not present, set to
an empty list.
nr quickfix list number. If not present, set to 0
+ qfbufnr number of the buffer displayed in the quickfix
+ window. If not present, set to 0.
size number of entries in the quickfix list. If not
present, set to 0.
title quickfix list title text. If not present, set
@@ -8092,15 +8103,15 @@ tabpagebuflist([{arg}]) *tabpagebuflist()*
tabpagenr([{arg}]) *tabpagenr()*
The result is a Number, which is the number of the current
tab page. The first tab page has number 1.
+
The optional argument {arg} supports the following values:
$ the number of the last tab page (the tab page
count).
- # the number of the last accessed tab page (where
- |g<Tab>| goes to). If there is no previous
- tab page, 0 is returned.
+ # the number of the last accessed tab page
+ (where |g<Tab>| goes to). If there is no
+ previous tab page, 0 is returned.
The number can be used with the |:tab| command.
-
tabpagewinnr({tabarg} [, {arg}]) *tabpagewinnr()*
Like |winnr()| but for tab page {tabarg}.
{tabarg} specifies the number of tab page to be used.
diff --git a/runtime/doc/diagnostic.txt b/runtime/doc/diagnostic.txt
index e33c786482..32936a7ee6 100644
--- a/runtime/doc/diagnostic.txt
+++ b/runtime/doc/diagnostic.txt
@@ -328,11 +328,11 @@ config({opts}, {namespace}) *vim.diagnostic.config()*
Note:
Each of the configuration options below accepts one of the
following:
- • `false` : Disable this feature
- • `true` : Enable this feature, use default settings.
- • `table` : Enable this feature with overrides. Use an
+ • `false`: Disable this feature
+ • `true`: Enable this feature, use default settings.
+ • `table`: Enable this feature with overrides. Use an
empty table to use default values.
- • `function` : Function with signature (namespace, bufnr)
+ • `function`: Function with signature (namespace, bufnr)
that returns any of the above.
Parameters: ~
diff --git a/runtime/doc/eval.txt b/runtime/doc/eval.txt
index 9fcdbe4cc3..ca2334500c 100644
--- a/runtime/doc/eval.txt
+++ b/runtime/doc/eval.txt
@@ -3225,14 +3225,14 @@ text...
commands are skipped.
When {pattern} is omitted all errors are caught.
Examples: >
- :catch /^Vim:Interrupt$/ " catch interrupts (CTRL-C)
- :catch /^Vim\%((\a\+)\)\=:E/ " catch all Vim errors
- :catch /^Vim\%((\a\+)\)\=:/ " catch errors and interrupts
- :catch /^Vim(write):/ " catch all errors in :write
- :catch /^Vim\%((\a\+)\)\=:E123/ " catch error E123
- :catch /my-exception/ " catch user exception
- :catch /.*/ " catch everything
- :catch " same as /.*/
+ :catch /^Vim:Interrupt$/ " catch interrupts (CTRL-C)
+ :catch /^Vim\%((\a\+)\)\=:E/ " catch all Vim errors
+ :catch /^Vim\%((\a\+)\)\=:/ " catch errors and interrupts
+ :catch /^Vim(write):/ " catch all errors in :write
+ :catch /^Vim\%((\a\+)\)\=:E123:/ " catch error E123
+ :catch /my-exception/ " catch user exception
+ :catch /.*/ " catch everything
+ :catch " same as /.*/
<
Another character can be used instead of / around the
{pattern}, so long as it does not have a special
diff --git a/runtime/doc/index.txt b/runtime/doc/index.txt
index d02ab1b759..572b4e3f93 100644
--- a/runtime/doc/index.txt
+++ b/runtime/doc/index.txt
@@ -431,6 +431,7 @@ tag char note action in Normal mode ~
|<C-LeftMouse>| <C-LeftMouse> ":ta" to the keyword at the mouse click
|<C-Right>| <C-Right> 1 same as "w"
|<C-RightMouse>| <C-RightMouse> same as "CTRL-T"
+|<C-Tab>| <C-Tab> same as "g<Tab>"
|<Del>| ["x]<Del> 2 same as "x"
|N<Del>| {count}<Del> remove the last digit from {count}
|<Down>| <Down> 1 same as "j"
@@ -577,7 +578,7 @@ tag command action in Normal mode ~
following the file name.
|CTRL-W_gt| CTRL-W g t same as `gt`: go to next tab page
|CTRL-W_gT| CTRL-W g T same as `gT`: go to previous tab page
-|CTRL-W_g<Tab>| CTRL-W g <Tab> same as `g<Tab>` : go to last accessed tab
+|CTRL-W_g<Tab>| CTRL-W g <Tab> same as |g<Tab>|: go to last accessed tab
page
|CTRL-W_h| CTRL-W h go to Nth left window (stop at first window)
|CTRL-W_i| CTRL-W i split window and jump to declaration of
diff --git a/runtime/doc/lsp.txt b/runtime/doc/lsp.txt
index 54c648e171..a9ebcd27ae 100644
--- a/runtime/doc/lsp.txt
+++ b/runtime/doc/lsp.txt
@@ -563,7 +563,7 @@ buf_request_all({bufnr}, {method}, {params}, {callback})
Return: ~
(function) A function that will cancel all requests which
- is the same as the one returned from `buf_request` .
+ is the same as the one returned from `buf_request`.
*vim.lsp.buf_request_sync()*
buf_request_sync({bufnr}, {method}, {params}, {timeout_ms})
@@ -600,9 +600,9 @@ client() *vim.lsp.client*
{handler} is not specified, If one is not found there,
then an error will occur. Returns: {status},
{[client_id]}. {status} is a boolean indicating if the
- notification was successful. If it is `false` , then it
+ notification was successful. If it is `false`, then it
will always be `false` (the client has shutdown). If
- {status} is `true` , the function returns {request_id} as
+ {status} is `true`, the function returns {request_id} as
the second result. You can use this with
`client.cancel_request(request_id)` to cancel the request.
• request_sync(method, params, timeout_ms, bufnr) Sends a
@@ -612,13 +612,13 @@ client() *vim.lsp.client*
`err` and `result` come from the |lsp-handler|. On
timeout, cancel or error, returns `(nil, err)` where `err`
is a string describing the failure reason. If the request
- was unsuccessful returns `nil` .
+ was unsuccessful returns `nil`.
• notify(method, params) Sends a notification to an LSP
server. Returns: a boolean to indicate if the notification
was successful. If it is false, then it will always be
false (the client has shutdown).
• cancel_request(id) Cancels a request with a given request
- id. Returns: same as `notify()` .
+ id. Returns: same as `notify()`.
• stop([force]) Stops a client, optionally with force. By
default, it will just ask the server to shutdown without
force. If you request to stop a client which has
@@ -639,14 +639,14 @@ client() *vim.lsp.client*
interaction with the client. See |vim.lsp.rpc.start()|.
• {offset_encoding} (string): The encoding used for
communicating with the server. You can modify this in the
- `config` 's `on_init` method before text is sent to the
+ `config`'s `on_init` method before text is sent to the
server.
• {handlers} (table): The handlers used by the client as
described in |lsp-handler|.
• {requests} (table): The current pending requests in flight
to the server. Entries are key-value pairs with the key
being the request ID while the value is a table with
- `type` , `bufnr` , and `method` key-value pairs. `type` is
+ `type`, `bufnr`, and `method` key-value pairs. `type` is
either "pending" for an active request, or "cancel" for a
cancel request.
• {config} (table): copy of the table that was passed by the
@@ -655,7 +655,7 @@ client() *vim.lsp.client*
sent on `initialize` describing the server's capabilities.
• {resolved_capabilities} (table): Normalized table of
capabilities that we have detected based on the initialize
- response from the server in `server_capabilities` .
+ response from the server in `server_capabilities`.
client_is_stopped({client_id}) *vim.lsp.client_is_stopped()*
Checks whether a client is stopped.
@@ -775,7 +775,7 @@ start_client({config}) *vim.lsp.start_client()*
initiates the LSP client.
{cmd_cwd} (string, default=|getcwd()|)
Directory to launch the `cmd`
- process. Not related to `root_dir` .
+ process. Not related to `root_dir`.
{cmd_env} (table) Environment flags to pass to
the LSP on spawn. Can be specified
using keys like a map or as a list
@@ -800,15 +800,15 @@ start_client({config}) *vim.lsp.start_client()*
its result.
• Note: To send an empty dictionary
use
- `{[vim.type_idx]=vim.types.dictionary}`
- , else it will be encoded as an
+ `{[vim.type_idx]=vim.types.dictionary}`,
+ else it will be encoded as an
array.
{handlers} Map of language server method names
to |lsp-handler|
{settings} Map with language server specific
settings. These are returned to the
language server if requested via
- `workspace/configuration` . Keys are
+ `workspace/configuration`. Keys are
case-sensitive.
{commands} table Table that maps string of
clientside commands to user-defined
@@ -821,7 +821,7 @@ start_client({config}) *vim.lsp.start_client()*
action, code lenses, ...) triggers
the command.
{init_options} Values to pass in the initialization
- request as `initializationOptions` .
+ request as `initializationOptions`.
See `initialize` in the LSP spec.
{name} (string, default=client-id) Name in
log messages.
@@ -976,7 +976,7 @@ code_action({context}) *vim.lsp.buf.code_action()*
• only: (string|nil) LSP `CodeActionKind` used
to filter the code actions. Most language
servers support values like `refactor` or
- `quickfix` .
+ `quickfix`.
See also: ~
https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_codeAction
@@ -1007,7 +1007,7 @@ definition() *vim.lsp.buf.definition()*
document_highlight() *vim.lsp.buf.document_highlight()*
Send request to the server to resolve document highlights for
the current text document position. This request can be
- triggered by a key mapping or by events such as `CursorHold` ,
+ triggered by a key mapping or by events such as `CursorHold`,
e.g.:
>
autocmd CursorHold <buffer> lua vim.lsp.buf.document_highlight()
@@ -1124,7 +1124,7 @@ range_code_action({context}, {start_pos}, {end_pos})
• only: (string|nil) LSP `CodeActionKind`
used to filter the code actions. Most
language servers support values like
- `refactor` or `quickfix` .
+ `refactor` or `quickfix`.
{start_pos} ({number, number}, optional) mark-indexed
position. Defaults to the start of the last
visual selection.
@@ -1246,8 +1246,8 @@ display({lenses}, {bufnr}, {client_id}) *vim.lsp.codelens.display()*
Display the lenses using virtual text
Parameters: ~
- {lenses} table of lenses to display ( `CodeLens[] |
- null` )
+ {lenses} table of lenses to display (`CodeLens[] |
+ null`)
{bufnr} number
{client_id} number
@@ -1259,7 +1259,7 @@ get({bufnr}) *vim.lsp.codelens.get()*
current buffer.
Return: ~
- table ( `CodeLens[]` )
+ table (`CodeLens[]`)
*vim.lsp.codelens.on_codelens()*
on_codelens({err}, {result}, {ctx}, {_})
@@ -1281,8 +1281,8 @@ save({lenses}, {bufnr}, {client_id}) *vim.lsp.codelens.save()*
Store lenses for a specific buffer and client
Parameters: ~
- {lenses} table of lenses to store ( `CodeLens[] |
- null` )
+ {lenses} table of lenses to store (`CodeLens[] |
+ null`)
{bufnr} number
{client_id} number
@@ -1333,7 +1333,7 @@ Lua module: vim.lsp.util *lsp-util*
*vim.lsp.util.apply_text_document_edit()*
apply_text_document_edit({text_document_edit}, {index}, {offset_encoding})
- Applies a `TextDocumentEdit` , which is a list of changes to a
+ Applies a `TextDocumentEdit`, which is a list of changes to a
single document.
Parameters: ~
@@ -1360,7 +1360,7 @@ apply_text_edits({text_edits}, {bufnr}, {offset_encoding})
*vim.lsp.util.apply_workspace_edit()*
apply_workspace_edit({workspace_edit}, {offset_encoding})
- Applies a `WorkspaceEdit` .
+ Applies a `WorkspaceEdit`.
Parameters: ~
{workspace_edit} table `WorkspaceEdit`
@@ -1408,13 +1408,13 @@ convert_input_to_markdown_lines({input}, {contents})
Converts any of `MarkedString` | `MarkedString[]` |
`MarkupContent` into a list of lines containing valid
markdown. Useful to populate the hover window for
- `textDocument/hover` , for parsing the result of
- `textDocument/signatureHelp` , and potentially others.
+ `textDocument/hover`, for parsing the result of
+ `textDocument/signatureHelp`, and potentially others.
Parameters: ~
- {input} ( `MarkedString` | `MarkedString[]` |
- `MarkupContent` )
- {contents} (table, optional, default `{}` ) List of
+ {input} (`MarkedString` | `MarkedString[]` |
+ `MarkupContent`)
+ {contents} (table, optional, default `{}`) List of
strings to extend with converted lines
Return: ~
@@ -1475,7 +1475,7 @@ jump_to_location({location}, {offset_encoding})
Jumps to a location.
Parameters: ~
- {location} table ( `Location` | `LocationLink` )
+ {location} table (`Location`|`LocationLink`)
{offset_encoding} string utf-8|utf-16|utf-32 (required)
Return: ~
@@ -1491,8 +1491,8 @@ locations_to_items({locations}, {offset_encoding})
|setqflist()| or |setloclist()|.
Parameters: ~
- {locations} table list of `Location` s or
- `LocationLink` s
+ {locations} table list of `Location`s or
+ `LocationLink`s
{offset_encoding} string offset_encoding for locations
utf-8|utf-16|utf-32
@@ -1526,7 +1526,7 @@ make_floating_popup_options({width}, {height}, {opts})
• border (string or table) override `border`
• focusable (string or table) override
`focusable`
- • zindex (string or table) override `zindex` ,
+ • zindex (string or table) override `zindex`,
defaults to 50
Return: ~
@@ -1566,7 +1566,7 @@ make_given_range_params({start_pos}, {end_pos}, {bufnr}, {offset_encoding})
Return: ~
{ textDocument = { uri = `current_file_uri` }, range = {
- start = `start_position` , end = `end_position` } }
+ start = `start_position`, end = `end_position` } }
*vim.lsp.util.make_position_params()*
make_position_params({window}, {offset_encoding})
@@ -1590,9 +1590,9 @@ make_position_params({window}, {offset_encoding})
make_range_params({window}, {offset_encoding})
Using the current position in the current buffer, creates an
object that can be used as a building block for several LSP
- requests, such as `textDocument/codeAction` ,
- `textDocument/colorPresentation` ,
- `textDocument/rangeFormatting` .
+ requests, such as `textDocument/codeAction`,
+ `textDocument/colorPresentation`,
+ `textDocument/rangeFormatting`.
Parameters: ~
{window} (optional, number): window handle or 0
@@ -1603,7 +1603,7 @@ make_range_params({window}, {offset_encoding})
Return: ~
{ textDocument = { uri = `current_file_uri` }, range = {
- start = `current_position` , end = `current_position` } }
+ start = `current_position`, end = `current_position` } }
*vim.lsp.util.make_text_document_params()*
make_text_document_params({bufnr})
@@ -1657,8 +1657,8 @@ open_floating_preview({contents}, {syntax}, {opts})
closes the floating window
• focusable: (boolean, default true) Make
float focusable
- • focus: (boolean, default true) If `true` ,
- and if {focusable} is also `true` , focus an
+ • focus: (boolean, default true) If `true`,
+ and if {focusable} is also `true`, focus an
existing floating window with the same
{focus_id}
@@ -1757,7 +1757,7 @@ text_document_completion_list_to_complete_items({result}, {prefix})
Parameters: ~
{result} The result of a `textDocument/completion` call,
e.g. from |vim.lsp.buf.completion()|, which may
- be one of `CompletionItem[]` , `CompletionList`
+ be one of `CompletionItem[]`, `CompletionList`
or `null`
{prefix} (string) the prefix to filter the completion
items
diff --git a/runtime/doc/lua.txt b/runtime/doc/lua.txt
index 11629332ae..93386ddfe9 100644
--- a/runtime/doc/lua.txt
+++ b/runtime/doc/lua.txt
@@ -1418,7 +1418,7 @@ deep_equal({a}, {b}) *vim.deep_equal()*
{b} second value
Return: ~
- `true` if values are equals, else `false` .
+ `true` if values are equals, else `false`.
deepcopy({orig}) *vim.deepcopy()*
Returns a deep copy of the given object. Non-table objects are
@@ -1435,7 +1435,7 @@ deepcopy({orig}) *vim.deepcopy()*
New table of copied keys and (nested) values.
endswith({s}, {suffix}) *vim.endswith()*
- Tests if `s` ends with `suffix` .
+ Tests if `s` ends with `suffix`.
Parameters: ~
{s} (string) a string
@@ -1539,7 +1539,7 @@ split({s}, {sep}, {kwargs}) *vim.split()*
|vim.gsplit()|
startswith({s}, {prefix}) *vim.startswith()*
- Tests if `s` starts with `prefix` .
+ Tests if `s` starts with `prefix`.
Parameters: ~
{s} (string) a string
@@ -1556,7 +1556,7 @@ tbl_add_reverse_lookup({o}) *vim.tbl_add_reverse_lookup()*
{o} table The table to add the reverse to.
tbl_contains({t}, {value}) *vim.tbl_contains()*
- Checks if a list-like (vector) table contains `value` .
+ Checks if a list-like (vector) table contains `value`.
Parameters: ~
{t} Table to check
@@ -1566,7 +1566,7 @@ tbl_contains({t}, {value}) *vim.tbl_contains()*
true if `t` contains `value`
tbl_count({t}) *vim.tbl_count()*
- Counts the number of non-nil values in table `t` .
+ Counts the number of non-nil values in table `t`.
>
vim.tbl_count({ a=1, b=2 }) => 2
@@ -1651,7 +1651,7 @@ tbl_islist({t}) *vim.tbl_islist()*
{t} Table
Return: ~
- `true` if array-like table, else `false` .
+ `true` if array-like table, else `false`.
tbl_keys({t}) *vim.tbl_keys()*
Return a list of all keys used in a table. However, the order
@@ -1813,7 +1813,7 @@ input({opts}, {on_confirm}) *vim.ui.input()*
Parameters: ~
{opts} table Additional options. See |input()|
• prompt (string|nil) Text of the prompt.
- Defaults to `Input:` .
+ Defaults to `Input:`.
• default (string|nil) Default reply to the
input
• completion (string|nil) Specifies type of
@@ -1856,16 +1856,16 @@ select({items}, {opts}, {on_choice}) *vim.ui.select()*
Defaults to `Select one of:`
• format_item (function item -> text)
Function to format an individual item from
- `items` . Defaults to `tostring` .
+ `items`. Defaults to `tostring`.
• kind (string|nil) Arbitrary hint string
indicating the item shape. Plugins
reimplementing `vim.ui.select` may wish to
use this to infer the structure or
- semantics of `items` , or the context in
+ semantics of `items`, or the context in
which select() was called.
{on_choice} function ((item|nil, idx|nil) -> ()) Called
once the user made a choice. `idx` is the
- 1-based index of `item` within `item` . `nil`
+ 1-based index of `item` within `item`. `nil`
if the user aborted the dialog.
@@ -1990,9 +1990,9 @@ set({mode}, {lhs}, {rhs}, {opts}) *vim.keymap.set()*
vim.keymap.set('n', 'asdf', require('jkl').my_fun)
<
- the require('jkl') gets evaluated during this call in order to
- access the function. If you want to avoid this cost at startup
- you can wrap it in a function, for example: >
+ the require('jkl )` gets evaluated during this call in order to access the
+ function. If you want to avoid this cost at startup you can
+ wrap it in a function, for example: >
vim.keymap.set('n', 'asdf', function() return require('jkl').my_fun() end)
<
@@ -2014,7 +2014,7 @@ set({mode}, {lhs}, {rhs}, {opts}) *vim.keymap.set()*
result of Lua expr maps.
• remap: (boolean) Make the mapping recursive.
This is the inverse of the "noremap" option from
- |nvim_set_keymap()|. Default `false` .
+ |nvim_set_keymap()|. Default `false`.
See also: ~
|nvim_set_keymap()|
diff --git a/runtime/doc/options.txt b/runtime/doc/options.txt
index 82214a2527..b2bbf5ddad 100644
--- a/runtime/doc/options.txt
+++ b/runtime/doc/options.txt
@@ -2441,7 +2441,14 @@ A jump table for the options with a short description can be found at |Q_op|.
item default Used for ~
stl:c ' ' or '^' statusline of the current window
stlnc:c ' ' or '=' statusline of the non-current windows
+ horiz:c '─' or '-' horizontal separators |:split|
+ horizup:c '┴' or '-' upwards facing horizontal separator
+ horizdown:c '┬' or '-' downwards facing horizontal separator
vert:c '│' or '|' vertical separators |:vsplit|
+ vertleft:c '┤' or '|' left facing vertical separator
+ vertright:c '├' or '|' right facing vertical separator
+ verthoriz:c '┼' or '+' overlapping vertical and horizontal
+ separator
fold:c '·' or '-' filling 'foldtext'
foldopen:c '-' mark the beginning of a fold
foldclose:c '+' show a closed fold
@@ -2454,8 +2461,13 @@ A jump table for the options with a short description can be found at |Q_op|.
"stlnc" the space will be used when there is highlighting, '^' or '='
otherwise.
- If 'ambiwidth' is "double" then "vert", "foldsep" and "fold" default to
- single-byte alternatives.
+ Note that "horiz", "horizup", "horizdown", "vertleft", "vertright" and
+ "verthoriz" are only used when 'laststatus' is 3, since only vertical
+ window separators are used otherwise.
+
+ If 'ambiwidth' is "double" then "horiz", "horizup", "horizdown",
+ "vert", "vertleft", "vertright", "verthoriz", "foldsep" and "fold"
+ default to single-byte alternatives.
Example: >
:set fillchars=stl:^,stlnc:=,vert:│,fold:·,diff:-
@@ -2469,7 +2481,13 @@ A jump table for the options with a short description can be found at |Q_op|.
item highlight group ~
stl:c StatusLine |hl-StatusLine|
stlnc:c StatusLineNC |hl-StatusLineNC|
- vert:c VertSplit |hl-VertSplit|
+ horiz:c WinSeparator |hl-WinSeparator|
+ horizup:c WinSeparator |hl-WinSeparator|
+ horizdown:c WinSeparator |hl-WinSeparator|
+ vert:c WinSeparator |hl-WinSeparator|
+ vertleft:c WinSeparator |hl-WinSeparator|
+ vertright:c WinSeparator |hl-WinSeparator|
+ verthoriz:c WinSeparator |hl-WinSeparator|
fold:c Folded |hl-Folded|
diff:c DiffDelete |hl-DiffDelete|
eob:c EndOfBuffer |hl-EndOfBuffer|
@@ -3652,6 +3670,8 @@ A jump table for the options with a short description can be found at |Q_op|.
0: never
1: only if there are at least two windows
2: always
+ 3: have a global statusline at the bottom instead of one for
+ each window
The screen looks nicer with a status line if you have several
windows, but it takes another screen line. |status-line|
@@ -5929,7 +5949,7 @@ A jump table for the options with a short description can be found at |Q_op|.
empty to avoid further errors. Otherwise screen updating would loop.
Note that the only effect of 'ruler' when this option is set (and
- 'laststatus' is 2) is controlling the output of |CTRL-G|.
+ 'laststatus' is 2 or 3) is controlling the output of |CTRL-G|.
field meaning ~
- Left justify the item. The default is right justified
diff --git a/runtime/doc/quickfix.txt b/runtime/doc/quickfix.txt
index 31a96298d2..8e91b101cd 100644
--- a/runtime/doc/quickfix.txt
+++ b/runtime/doc/quickfix.txt
@@ -571,6 +571,7 @@ location list.
second quickfix window. If [height] is given the
existing window will be resized to it.
+ *quickfix-buffer*
The window will contain a special buffer, with
'buftype' equal to "quickfix". Don't change this!
The window will have the w:quickfix_title variable set
@@ -579,7 +580,11 @@ location list.
status line if the value of 'statusline' is adjusted
properly. Whenever this buffer is modified by a
quickfix command or function, the |b:changedtick|
- variable is incremented.
+ variable is incremented. You can get the number of
+ this buffer using the getqflist() and getloclist()
+ functions by passing the 'qfbufnr' item. For a
+ location list, this buffer is wiped out when the
+ location list is removed.
*:lop* *:lopen*
:lop[en] [height] Open a window to show the location list for the
@@ -768,12 +773,18 @@ using these functions are below:
" get the quickfix list window id
:echo getqflist({'winid' : 0}).winid
+ " get the quickfix list window buffer number
+ :echo getqflist({'qfbufnr' : 0}).qfbufnr
+
" get the context of the current location list
:echo getloclist(0, {'context' : 0}).context
" get the location list window id of the third window
:echo getloclist(3, {'winid' : 0}).winid
+ " get the location list window buffer number of the third window
+ :echo getloclist(3, {'qfbufnr' : 0}).qfbufnr
+
" get the file window id of a location list window (winnr: 4)
:echo getloclist(4, {'filewinid' : 0}).filewinid
<
diff --git a/runtime/doc/remote.txt b/runtime/doc/remote.txt
index b8991be738..0c1e3438de 100644
--- a/runtime/doc/remote.txt
+++ b/runtime/doc/remote.txt
@@ -86,7 +86,7 @@ You can not put options there!
2. Missing functionality *E5600* *clientserver-missing*
Vim supports additional functionality in clientserver that's not yet
-implemented in Nvim. In particular, none of the 'wait' variants are supported
+implemented in Nvim. In particular, none of the "wait" variants are supported
yet. The following command line arguments are not yet available:
argument meaning ~
diff --git a/runtime/doc/syntax.txt b/runtime/doc/syntax.txt
index c5f93fd66f..0ff31e81ab 100644
--- a/runtime/doc/syntax.txt
+++ b/runtime/doc/syntax.txt
@@ -5119,8 +5119,8 @@ TermCursor cursor in a focused terminal
TermCursorNC cursor in an unfocused terminal
*hl-ErrorMsg*
ErrorMsg error messages on the command line
- *hl-VertSplit*
-VertSplit the column separating vertically split windows
+ *hl-WinSeparator*
+WinSeparator separators between window splits
*hl-Folded*
Folded line used for closed folds
*hl-FoldColumn*
diff --git a/runtime/doc/tabpage.txt b/runtime/doc/tabpage.txt
index 78b5101da7..f06a6bcc34 100644
--- a/runtime/doc/tabpage.txt
+++ b/runtime/doc/tabpage.txt
@@ -196,10 +196,6 @@ gt *i_CTRL-<PageDown>* *i_<C-PageDown>*
{count}<C-PageDown>
{count}gt Go to tab page {count}. The first tab page has number one.
-CTRL-<Tab> *CTRL-<Tab>*
-CTRL-W g<Tab> *g<Tab>* *CTRL-W_g<Tab>*
-g<Tab> Go to previous (last accessed) tab page.
-
:tabp[revious] *:tabp* *:tabprevious* *gT* *:tabN*
:tabN[ext] *:tabNext* *CTRL-<PageUp>*
<C-PageUp> *<C-PageUp>* *i_CTRL-<PageUp>* *i_<C-PageUp>*
@@ -219,6 +215,9 @@ gT Go to the previous tab page. Wraps around from the first one
*:tabl* *:tablast*
:tabl[ast] Go to the last tab page.
+<C-Tab> *CTRL-<Tab>* *<C-Tab>*
+CTRL-W g<Tab> *g<Tab>* *CTRL-W_g<Tab>*
+g<Tab> Go to the last accessed tab page.
Other commands:
*:tabs*
diff --git a/runtime/doc/treesitter.txt b/runtime/doc/treesitter.txt
index 02be20c5e8..a9d9f81849 100644
--- a/runtime/doc/treesitter.txt
+++ b/runtime/doc/treesitter.txt
@@ -468,7 +468,7 @@ parse_query({lang}, {query}) *parse_query()*
Exposes `info` and `captures` with additional context about {query}.
• `captures` contains the list of unique capture names defined
- in {query}. - `info.captures` also points to `captures` .
+ in {query}. -`info.captures` also points to `captures`.
• `info.patterns` contains information about predicates.
Parameters: ~
@@ -528,8 +528,8 @@ Query:iter_matches({self}, {node}, {source}, {start}, {stop})
a table mapping capture indices to nodes, and metadata from
any directives processing the match. If the query has more
than one pattern the capture table might be sparse, and e.g.
- `pairs()` method should be used over `ipairs` . Here an
- example iterating over all captures in every match:
+ `pairs()` method should be used over `ipairs`. Here an example
+ iterating over all captures in every match:
>
for pattern, match, metadata in cquery:iter_matches(tree:root(), bufnr, first, last) do
diff --git a/runtime/doc/usr_08.txt b/runtime/doc/usr_08.txt
index 8ccaa73006..1d20913a14 100644
--- a/runtime/doc/usr_08.txt
+++ b/runtime/doc/usr_08.txt
@@ -482,6 +482,8 @@ statusline:
0 never
1 only when there are split windows (the default)
2 always
+ 3 have a global statusline at the bottom instead of one for each
+ window
Many commands that edit another file have a variant that splits the window.
For Command-line commands this is done by prepending an "s". For example:
diff --git a/runtime/doc/vim_diff.txt b/runtime/doc/vim_diff.txt
index 5ea6a9c5dd..9ca5faf112 100644
--- a/runtime/doc/vim_diff.txt
+++ b/runtime/doc/vim_diff.txt
@@ -84,7 +84,7 @@ Nvim creates the following default mappings at |startup|. You can disable any
of these in your config by simply removing the mapping, e.g. ":unmap Y".
>
nnoremap Y y$
- nnoremap <C-L> <Cmd>nohlsearch<Bar>diffupdate<CR><C-L>
+ nnoremap <C-L> <Cmd>nohlsearch<Bar>diffupdate<Bar>normal! <C-L><CR>
inoremap <C-U> <C-G>u<C-U>
inoremap <C-W> <C-G>u<C-W>
<
@@ -211,6 +211,7 @@ Highlight groups:
|hl-Substitute|
|hl-TermCursor|
|hl-TermCursorNC|
+ |hl-WinSeparator| highlights window separators
|hl-Whitespace| highlights 'listchars' whitespace
Input/Mappings:
@@ -227,9 +228,11 @@ Options:
'cpoptions' flags: |cpo-_|
'display' flags: "msgsep" minimizes scrolling when showing messages
'guicursor' works in the terminal
- 'fillchars' flags: "msgsep" (see 'display')
+ 'fillchars' flags: "msgsep" (see 'display'), "horiz", "horizup",
+ "horizdown", "vertleft", "vertright", "verthoriz"
'foldcolumn' supports up to 9 dynamic/fixed columns
'inccommand' shows interactive results for |:substitute|-like commands
+ 'laststatus' global statusline support
'pumblend' pseudo-transparent popupmenu
'scrollback'
'signcolumn' supports up to 9 dynamic/fixed columns
@@ -348,6 +351,7 @@ Highlight groups:
|hl-ColorColumn|, |hl-CursorColumn| are lower priority than most other
groups
|hl-CursorLine| is low-priority unless foreground color is set
+ *hl-VertSplit* superseded by |hl-WinSeparator|
Macro/|recording| behavior
Replay of a macro recorded during :lmap produces the same actions as when it
diff --git a/runtime/doc/windows.txt b/runtime/doc/windows.txt
index bd29cd1d7a..cd5425336f 100644
--- a/runtime/doc/windows.txt
+++ b/runtime/doc/windows.txt
@@ -104,6 +104,8 @@ when the last window also has a status line:
'laststatus' = 0 never a status line
'laststatus' = 1 status line if there is more than one window
'laststatus' = 2 always a status line
+ 'laststatus' = 3 have a global statusline at the bottom instead
+ of one for each window
You can change the contents of the status line with the 'statusline' option.
This option can be local to the window, so that you can have a different
diff --git a/runtime/filetype.lua b/runtime/filetype.lua
index 74e427c358..8224b79534 100644
--- a/runtime/filetype.lua
+++ b/runtime/filetype.lua
@@ -7,26 +7,36 @@ if vim.g.do_filetype_lua ~= 1 then
return
end
--- TODO: Remove vim.cmd once Lua autocommands land
-vim.cmd [[
-augroup filetypedetect
-au BufRead,BufNewFile * call v:lua.vim.filetype.match(expand('<afile>'))
+vim.api.nvim_create_augroup("filetypedetect", {clear = false})
+
+vim.api.nvim_create_autocmd({"BufRead", "BufNewFile"}, {
+ group = "filetypedetect",
+ callback = function()
+ vim.filetype.match(vim.fn.expand("<afile>"))
+ end,
+})
-" These *must* be sourced after the autocommand above is created
+-- These *must* be sourced after the autocommand above is created
+vim.cmd [[
runtime! ftdetect/*.vim
runtime! ftdetect/*.lua
+]]
-" Set a marker so that the ftdetect scripts are not sourced a second time by filetype.vim
-let g:did_load_ftdetect = 1
+-- Set a marker so that the ftdetect scripts are not sourced a second time by filetype.vim
+vim.g.did_load_ftdetect = 1
-" If filetype.vim is disabled, set up the autocmd to use scripts.vim
-if exists('did_load_filetypes')
- au BufRead,BufNewFile * if !did_filetype() && expand('<amatch>') !~ g:ft_ignore_pat | runtime! scripts.vim | endif
- au StdinReadPost * if !did_filetype() | runtime! scripts.vim | endif
-endif
+-- If filetype.vim is disabled, set up the autocmd to use scripts.vim
+if vim.g.did_load_filetypes then
+ vim.api.nvim_create_autocmd({"BufRead", "BufNewFile"}, {
+ group = "filetypedetect",
+ command = "if !did_filetype() && expand('<amatch>') !~ g:ft_ignore_pat | runtime! scripts.vim | endif",
+ })
-augroup END
-]]
+ vim.api.nvim_create_autocmd("StdinReadPost", {
+ group = "filetypedetect",
+ command = "if !did_filetype() | runtime! scripts.vim | endif",
+ })
+end
if not vim.g.ft_ignore_pat then
vim.g.ft_ignore_pat = "\\.\\(Z\\|gz\\|bz2\\|zip\\|tgz\\)$"
diff --git a/runtime/filetype.vim b/runtime/filetype.vim
index 8114ad4092..9df89674e3 100644
--- a/runtime/filetype.vim
+++ b/runtime/filetype.vim
@@ -664,7 +664,7 @@ au BufNewFile,BufRead *.fs call dist#ft#FTfs()
au BufNewFile,BufRead *.fsi,*.fsx setf fsharp
" GDB command files
-au BufNewFile,BufRead .gdbinit,gdbinit setf gdb
+au BufNewFile,BufRead .gdbinit,gdbinit,.gdbearlyinit,gdbearlyinit,*.gdb setf gdb
" GDMO
au BufNewFile,BufRead *.mo,*.gdmo setf gdmo
diff --git a/runtime/lua/vim/_editor.lua b/runtime/lua/vim/_editor.lua
index a0c60a7dcf..d4db4850bd 100644
--- a/runtime/lua/vim/_editor.lua
+++ b/runtime/lua/vim/_editor.lua
@@ -128,7 +128,7 @@ local function inspect(object, options) -- luacheck: no unused
end
do
- local tdots, tick, got_line1 = 0, 0, false
+ local tdots, tick, got_line1, undo_started, trailing_nl = 0, 0, false, false, false
--- Paste handler, invoked by |nvim_paste()| when a conforming UI
--- (such as the |TUI|) pastes text into the editor.
@@ -156,44 +156,80 @@ do
--- - 3: ends the paste (exactly once)
---@returns false if client should cancel the paste.
function vim.paste(lines, phase)
- local call = vim.api.nvim_call_function
local now = vim.loop.now()
- local mode = call('mode', {}):sub(1,1)
- if phase < 2 then -- Reset flags.
- tdots, tick, got_line1 = now, 0, false
- elseif mode ~= 'c' then
+ local is_first_chunk = phase < 2
+ local is_last_chunk = phase == -1 or phase == 3
+ if is_first_chunk then -- Reset flags.
+ tdots, tick, got_line1, undo_started, trailing_nl = now, 0, false, false, false
+ end
+ if #lines == 0 then
+ lines = {''}
+ end
+ if #lines == 1 and lines[1] == '' and not is_last_chunk then
+ -- An empty chunk can cause some edge cases in streamed pasting,
+ -- so don't do anything unless it is the last chunk.
+ return true
+ end
+ -- Note: mode doesn't always start with "c" in cmdline mode, so use getcmdtype() instead.
+ if vim.fn.getcmdtype() ~= '' then -- cmdline-mode: paste only 1 line.
+ if not got_line1 then
+ got_line1 = (#lines > 1)
+ vim.api.nvim_set_option('paste', true) -- For nvim_input().
+ -- Escape "<" and control characters
+ local line1 = lines[1]:gsub('<', '<lt>'):gsub('(%c)', '\022%1')
+ vim.api.nvim_input(line1)
+ vim.api.nvim_set_option('paste', false)
+ end
+ return true
+ end
+ local mode = vim.api.nvim_get_mode().mode
+ if undo_started then
vim.api.nvim_command('undojoin')
end
- if mode == 'c' and not got_line1 then -- cmdline-mode: paste only 1 line.
- got_line1 = (#lines > 1)
- vim.api.nvim_set_option('paste', true) -- For nvim_input().
- local line1 = lines[1]:gsub('<', '<lt>'):gsub('[\r\n\012\027]', ' ') -- Scrub.
- vim.api.nvim_input(line1)
- vim.api.nvim_set_option('paste', false)
- elseif mode ~= 'c' then
- if phase < 2 and mode:find('^[vV\22sS\19]') then
- vim.api.nvim_command([[exe "normal! \<Del>"]])
- vim.api.nvim_put(lines, 'c', false, true)
- elseif phase < 2 and not mode:find('^[iRt]') then
- vim.api.nvim_put(lines, 'c', true, true)
- -- XXX: Normal-mode: workaround bad cursor-placement after first chunk.
- vim.api.nvim_command('normal! a')
- elseif phase < 2 and mode == 'R' then
- local nchars = 0
- for _, line in ipairs(lines) do
- nchars = nchars + line:len()
+ if mode:find('^i') or mode:find('^n?t') then -- Insert mode or Terminal buffer
+ vim.api.nvim_put(lines, 'c', false, true)
+ elseif phase < 2 and mode:find('^R') and not mode:find('^Rv') then -- Replace mode
+ -- TODO: implement Replace mode streamed pasting
+ -- TODO: support Virtual Replace mode
+ local nchars = 0
+ for _, line in ipairs(lines) do
+ nchars = nchars + line:len()
+ end
+ local row, col = unpack(vim.api.nvim_win_get_cursor(0))
+ local bufline = vim.api.nvim_buf_get_lines(0, row-1, row, true)[1]
+ local firstline = lines[1]
+ firstline = bufline:sub(1, col)..firstline
+ lines[1] = firstline
+ lines[#lines] = lines[#lines]..bufline:sub(col + nchars + 1, bufline:len())
+ vim.api.nvim_buf_set_lines(0, row-1, row, false, lines)
+ elseif mode:find('^[nvV\22sS\19]') then -- Normal or Visual or Select mode
+ if mode:find('^n') then -- Normal mode
+ -- When there was a trailing new line in the previous chunk,
+ -- the cursor is on the first character of the next line,
+ -- so paste before the cursor instead of after it.
+ vim.api.nvim_put(lines, 'c', not trailing_nl, false)
+ else -- Visual or Select mode
+ vim.api.nvim_command([[exe "silent normal! \<Del>"]])
+ local del_start = vim.fn.getpos("'[")
+ local cursor_pos = vim.fn.getpos('.')
+ if mode:find('^[VS]') then -- linewise
+ if cursor_pos[2] < del_start[2] then -- replacing lines at eof
+ -- create a new line
+ vim.api.nvim_put({''}, 'l', true, true)
+ end
+ vim.api.nvim_put(lines, 'c', false, false)
+ else
+ -- paste after cursor when replacing text at eol, otherwise paste before cursor
+ vim.api.nvim_put(lines, 'c', cursor_pos[3] < del_start[3], false)
end
- local row, col = unpack(vim.api.nvim_win_get_cursor(0))
- local bufline = vim.api.nvim_buf_get_lines(0, row-1, row, true)[1]
- local firstline = lines[1]
- firstline = bufline:sub(1, col)..firstline
- lines[1] = firstline
- lines[#lines] = lines[#lines]..bufline:sub(col + nchars + 1, bufline:len())
- vim.api.nvim_buf_set_lines(0, row-1, row, false, lines)
- else
- vim.api.nvim_put(lines, 'c', false, true)
end
+ -- put cursor at the end of the text instead of one character after it
+ vim.fn.setpos('.', vim.fn.getpos("']"))
+ trailing_nl = lines[#lines] == ''
+ else -- Don't know what to do in other modes
+ return false
end
+ undo_started = true
if phase ~= -1 and (now - tdots >= 100) then
local dots = ('.'):rep(tick % 4)
tdots = now
@@ -202,7 +238,7 @@ do
-- message when there are zero dots.
vim.api.nvim_command(('echo "%s"'):format(dots))
end
- if phase == -1 or phase == 3 then
+ if is_last_chunk then
vim.api.nvim_command('redraw'..(tick > 1 and '|echo ""' or ''))
end
return true -- Paste will not continue if not returning `true`.
diff --git a/runtime/lua/vim/filetype.lua b/runtime/lua/vim/filetype.lua
index f5e4dabfb6..b356f5e3dc 100644
--- a/runtime/lua/vim/filetype.lua
+++ b/runtime/lua/vim/filetype.lua
@@ -225,6 +225,7 @@ local extension = {
fsi = "fsharp",
fsx = "fsharp",
fusion = "fusion",
+ gdb = "gdb",
gdmo = "gdmo",
mo = "gdmo",
tres = "gdresource",
@@ -919,6 +920,8 @@ local filename = {
mtab = "fstab",
[".gdbinit"] = "gdb",
gdbinit = "gdb",
+ [".gdbearlyinit"] = "gdb",
+ gdbearlyinit = "gdb",
["lltxxxxx.txt"] = "gedcom",
["TAG_EDITMSG"] = "gitcommit",
["MERGE_MSG"] = "gitcommit",
diff --git a/runtime/lua/vim/keymap.lua b/runtime/lua/vim/keymap.lua
index 7f12372502..1be40b0081 100644
--- a/runtime/lua/vim/keymap.lua
+++ b/runtime/lua/vim/keymap.lua
@@ -25,8 +25,8 @@ local keymap = {}
--- vim.keymap.set('n', 'asdf', require('jkl').my_fun)
--- </pre>
---
---- the `require('jkl')` gets evaluated during this call in order to access the function. If you want to
---- avoid this cost at startup you can wrap it in a function, for example:
+--- the ``require('jkl')`` gets evaluated during this call in order to access the function.
+--- If you want to avoid this cost at startup you can wrap it in a function, for example:
--- <pre>
--- vim.keymap.set('n', 'asdf', function() return require('jkl').my_fun() end)
--- </pre>
diff --git a/runtime/lua/vim/lsp.lua b/runtime/lua/vim/lsp.lua
index 8d11b4621c..105e7c4621 100644
--- a/runtime/lua/vim/lsp.lua
+++ b/runtime/lua/vim/lsp.lua
@@ -1689,7 +1689,7 @@ end
---
--- Currently only supports a single client. This can be set via
--- `setlocal formatexpr=v:lua.vim.lsp.formatexpr()` but will typically or in `on_attach`
---- via `vim.api.nvim_buf_set_option(bufnr, 'formatexpr', 'v:lua.vim.lsp.formatexpr(#{timeout_ms:250})')`.
+--- via ``vim.api.nvim_buf_set_option(bufnr, 'formatexpr', 'v:lua.vim.lsp.formatexpr(#{timeout_ms:250})')``.
---
---@param opts table options for customizing the formatting expression which takes the
--- following optional keys:
diff --git a/runtime/lua/vim/shared.lua b/runtime/lua/vim/shared.lua
index 8124b23eb1..3eb332279a 100644
--- a/runtime/lua/vim/shared.lua
+++ b/runtime/lua/vim/shared.lua
@@ -331,7 +331,7 @@ end
--- Add the reverse lookup values to an existing table.
--- For example:
---- `tbl_add_reverse_lookup { A = 1 } == { [1] = 'A', A = 1 }`
+--- ``tbl_add_reverse_lookup { A = 1 } == { [1] = 'A', A = 1 }``
--
--Do note that it *modifies* the input.
---@param o table The table to add the reverse to.
diff --git a/runtime/spell/cleanadd.vim b/runtime/spell/cleanadd.vim
new file mode 100644
index 0000000000..6dc0692186
--- /dev/null
+++ b/runtime/spell/cleanadd.vim
@@ -0,0 +1,32 @@
+" Vim script to clean the ll.xxxxx.add files of commented out entries
+" Author: Antonio Colombo, Bram Moolenaar
+" Last Update: 2008 Jun 3
+
+" Time in seconds after last time an ll.xxxxx.add file was updated
+" Default is one second.
+" If you invoke this script often set it to something bigger, e.g. 60 * 60
+" (one hour)
+if !exists("g:spell_clean_limit")
+ let g:spell_clean_limit = 1
+endif
+
+" Loop over all the runtime/spell/*.add files.
+" Delete all comment lines, except the ones starting with ##.
+for s:fname in split(globpath(&rtp, "spell/*.add"), "\n")
+ if filewritable(s:fname) && localtime() - getftime(s:fname) > g:spell_clean_limit
+ if exists('*fnameescape')
+ let s:f = fnameescape(s:fname)
+ else
+ let s:f = escape(s:fname, ' \|<')
+ endif
+ silent exe "tab split " . s:f
+ echo "Processing" s:f
+ silent! g/^#[^#]/d
+ silent update
+ close
+ unlet s:f
+ endif
+endfor
+unlet s:fname
+
+echo "Done"
diff --git a/scripts/gen_vimdoc.py b/scripts/gen_vimdoc.py
index af49d57492..7152f1005f 100755
--- a/scripts/gen_vimdoc.py
+++ b/scripts/gen_vimdoc.py
@@ -84,8 +84,6 @@ CONFIG = {
'api': {
'mode': 'c',
'filename': 'api.txt',
- # String used to find the start of the generated part of the doc.
- 'section_start_token': '*api-global*',
# Section ordering.
'section_order': [
'vim.c',
@@ -98,8 +96,8 @@ CONFIG = {
'autocmd.c',
'ui.c',
],
- # List of files/directories for doxygen to read, separated by blanks
- 'files': os.path.join(base_dir, 'src/nvim/api'),
+ # List of files/directories for doxygen to read, relative to `base_dir`
+ 'files': ['src/nvim/api'],
# file patterns used by doxygen
'file_patterns': '*.h *.c',
# Only function with this prefix are considered
@@ -122,7 +120,6 @@ CONFIG = {
'lua': {
'mode': 'lua',
'filename': 'lua.txt',
- 'section_start_token': '*lua-vim*',
'section_order': [
'_editor.lua',
'shared.lua',
@@ -131,14 +128,14 @@ CONFIG = {
'filetype.lua',
'keymap.lua',
],
- 'files': ' '.join([
- os.path.join(base_dir, 'runtime/lua/vim/_editor.lua'),
- os.path.join(base_dir, 'runtime/lua/vim/shared.lua'),
- os.path.join(base_dir, 'runtime/lua/vim/uri.lua'),
- os.path.join(base_dir, 'runtime/lua/vim/ui.lua'),
- os.path.join(base_dir, 'runtime/lua/vim/filetype.lua'),
- os.path.join(base_dir, 'runtime/lua/vim/keymap.lua'),
- ]),
+ 'files': [
+ 'runtime/lua/vim/_editor.lua',
+ 'runtime/lua/vim/shared.lua',
+ 'runtime/lua/vim/uri.lua',
+ 'runtime/lua/vim/ui.lua',
+ 'runtime/lua/vim/filetype.lua',
+ 'runtime/lua/vim/keymap.lua',
+ ],
'file_patterns': '*.lua',
'fn_name_prefix': '',
'section_name': {
@@ -171,7 +168,6 @@ CONFIG = {
'lsp': {
'mode': 'lua',
'filename': 'lsp.txt',
- 'section_start_token': '*lsp-core*',
'section_order': [
'lsp.lua',
'buf.lua',
@@ -185,10 +181,10 @@ CONFIG = {
'sync.lua',
'protocol.lua',
],
- 'files': ' '.join([
- os.path.join(base_dir, 'runtime/lua/vim/lsp'),
- os.path.join(base_dir, 'runtime/lua/vim/lsp.lua'),
- ]),
+ 'files': [
+ 'runtime/lua/vim/lsp',
+ 'runtime/lua/vim/lsp.lua',
+ ],
'file_patterns': '*.lua',
'fn_name_prefix': '',
'section_name': {'lsp.lua': 'lsp'},
@@ -214,11 +210,10 @@ CONFIG = {
'diagnostic': {
'mode': 'lua',
'filename': 'diagnostic.txt',
- 'section_start_token': '*diagnostic-api*',
'section_order': [
'diagnostic.lua',
],
- 'files': os.path.join(base_dir, 'runtime/lua/vim/diagnostic.lua'),
+ 'files': ['runtime/lua/vim/diagnostic.lua'],
'file_patterns': '*.lua',
'fn_name_prefix': '',
'section_name': {'diagnostic.lua': 'diagnostic'},
@@ -231,7 +226,6 @@ CONFIG = {
'treesitter': {
'mode': 'lua',
'filename': 'treesitter.txt',
- 'section_start_token': '*lua-treesitter-core*',
'section_order': [
'treesitter.lua',
'language.lua',
@@ -239,10 +233,10 @@ CONFIG = {
'highlighter.lua',
'languagetree.lua',
],
- 'files': ' '.join([
- os.path.join(base_dir, 'runtime/lua/vim/treesitter.lua'),
- os.path.join(base_dir, 'runtime/lua/vim/treesitter/'),
- ]),
+ 'files': [
+ 'runtime/lua/vim/treesitter.lua',
+ 'runtime/lua/vim/treesitter/',
+ ],
'file_patterns': '*.lua',
'fn_name_prefix': '',
'section_name': {},
@@ -349,14 +343,6 @@ def self_or_child(n):
return n.childNodes[0]
-def clean_text(text):
- """Cleans text.
-
- Only cleans superfluous whitespace at the moment.
- """
- return ' '.join(text.split()).strip()
-
-
def clean_lines(text):
"""Removes superfluous lines.
@@ -377,12 +363,12 @@ def get_text(n, preformatted=False):
if n.nodeName == 'computeroutput':
for node in n.childNodes:
text += get_text(node)
- return '`{}` '.format(text)
+ return '`{}`'.format(text)
for node in n.childNodes:
if node.nodeType == node.TEXT_NODE:
- text += node.data if preformatted else clean_text(node.data)
+ text += node.data
elif node.nodeType == node.ELEMENT_NODE:
- text += ' ' + get_text(node, preformatted)
+ text += get_text(node, preformatted)
return text
@@ -849,7 +835,9 @@ def extract_from_xml(filename, target, width):
'seealso': [],
}
if fmt_vimhelp:
- fn['desc_node'] = desc # HACK :(
+ # HACK :(
+ fn['desc_node'] = desc
+ fn['brief_desc_node'] = brief_desc
for m in paras:
if 'text' in m:
@@ -897,6 +885,8 @@ def fmt_doxygen_xml_as_vimhelp(filename, target):
# Generate Vim :help for parameters.
if fn['desc_node']:
doc = fmt_node_as_vimhelp(fn['desc_node'])
+ if not doc and fn['brief_desc_node']:
+ doc = fmt_node_as_vimhelp(fn['brief_desc_node'])
if not doc:
doc = 'TODO: Documentation'
@@ -1006,7 +996,8 @@ def main(config, args):
stderr=(subprocess.STDOUT if debug else subprocess.DEVNULL))
p.communicate(
config.format(
- input=CONFIG[target]['files'],
+ input=' '.join(
+ [f'"{file}"' for file in CONFIG[target]['files']]),
output=output_dir,
filter=filter_cmd,
file_patterns=CONFIG[target]['file_patterns'])
@@ -1096,6 +1087,7 @@ def main(config, args):
raise RuntimeError(
'found new modules "{}"; update the "section_order" map'.format(
set(sections).difference(CONFIG[target]['section_order'])))
+ first_section_tag = sections[CONFIG[target]['section_order'][0]][1]
docs = ''
@@ -1121,7 +1113,8 @@ def main(config, args):
doc_file = os.path.join(base_dir, 'runtime', 'doc',
CONFIG[target]['filename'])
- delete_lines_below(doc_file, CONFIG[target]['section_start_token'])
+ if os.path.exists(doc_file):
+ delete_lines_below(doc_file, first_section_tag)
with open(doc_file, 'ab') as fp:
fp.write(docs.encode('utf8'))
diff --git a/scripts/vim-patch.sh b/scripts/vim-patch.sh
index 591c658e6b..c68ab3a751 100755
--- a/scripts/vim-patch.sh
+++ b/scripts/vim-patch.sh
@@ -236,6 +236,10 @@ preprocess_patch() {
LC_ALL=C sed -e 's/\( [ab]\/src\/nvim\)\/session\(\.[ch]\)/\1\/ex_session\2/g' \
"$file" > "$file".tmp && mv "$file".tmp "$file"
+ # Rename highlight.c to highlight_group.c
+ LC_ALL=C sed -e 's/\( [ab]\/src\/nvim\)\/highlight\(\.[ch]\)/\1\/highlight_group\2/g' \
+ "$file" > "$file".tmp && mv "$file".tmp "$file"
+
# Rename test_urls.vim to check_urls.vim
LC_ALL=C sed -e 's@\( [ab]\)/runtime/doc/test\(_urls.vim\)@\1/scripts/check\2@g' \
"$file" > "$file".tmp && mv "$file".tmp "$file"
diff --git a/src/nvim/CMakeLists.txt b/src/nvim/CMakeLists.txt
index 96e5d1e77c..8e17f94abc 100644..100755
--- a/src/nvim/CMakeLists.txt
+++ b/src/nvim/CMakeLists.txt
@@ -39,6 +39,7 @@ set(GENERATED_UI_EVENTS ${GENERATED_DIR}/ui_events.generated.h)
set(GENERATED_UI_EVENTS_CALL ${GENERATED_DIR}/ui_events_call.generated.h)
set(GENERATED_UI_EVENTS_REMOTE ${GENERATED_DIR}/ui_events_remote.generated.h)
set(GENERATED_UI_EVENTS_BRIDGE ${GENERATED_DIR}/ui_events_bridge.generated.h)
+set(GENERATED_UI_EVENTS_CLIENT ${GENERATED_DIR}/ui_events_client.generated.h)
set(GENERATED_UI_EVENTS_METADATA ${GENERATED_DIR}/api/private/ui_events_metadata.generated.h)
set(GENERATED_EX_CMDS_ENUM ${GENERATED_INCLUDES_DIR}/ex_cmds_enum.generated.h)
set(GENERATED_EX_CMDS_DEFS ${GENERATED_DIR}/ex_cmds_defs.generated.h)
@@ -271,6 +272,7 @@ foreach(sfile ${NVIM_SOURCES}
"${GENERATED_UI_EVENTS_REMOTE}"
"${GENERATED_UI_EVENTS_BRIDGE}"
"${GENERATED_KEYSETS}"
+ "${GENERATED_UI_EVENTS_CLIENT}"
)
get_filename_component(full_d ${sfile} PATH)
file(RELATIVE_PATH d "${CMAKE_CURRENT_LIST_DIR}" "${full_d}")
@@ -368,6 +370,7 @@ add_custom_command(
${GENERATED_UI_EVENTS_REMOTE}
${GENERATED_UI_EVENTS_BRIDGE}
${GENERATED_UI_EVENTS_METADATA}
+ ${GENERATED_UI_EVENTS_CLIENT}
COMMAND ${LUA_PRG} ${API_UI_EVENTS_GENERATOR} ${CMAKE_CURRENT_LIST_DIR}
${CMAKE_CURRENT_LIST_DIR}/api/ui_events.in.h
${GENERATED_UI_EVENTS}
@@ -375,6 +378,7 @@ add_custom_command(
${GENERATED_UI_EVENTS_REMOTE}
${GENERATED_UI_EVENTS_BRIDGE}
${GENERATED_UI_EVENTS_METADATA}
+ ${GENERATED_UI_EVENTS_CLIENT}
DEPENDS
${API_UI_EVENTS_GENERATOR}
${GENERATOR_C_GRAMMAR}
diff --git a/src/nvim/api/buffer.c b/src/nvim/api/buffer.c
index a3af51008f..9f0cadd5ce 100644
--- a/src/nvim/api/buffer.c
+++ b/src/nvim/api/buffer.c
@@ -597,12 +597,11 @@ void nvim_buf_set_text(uint64_t channel_id, Buffer buffer, Integer start_row, In
if (start_row == end_row) {
old_byte = (bcount_t)end_col - start_col;
} else {
- const char *bufline;
old_byte += (bcount_t)strlen(str_at_start) - start_col;
for (int64_t i = 1; i < end_row - start_row; i++) {
int64_t lnum = start_row + i;
- bufline = (char *)ml_get_buf(buf, lnum, false);
+ const char *bufline = (char *)ml_get_buf(buf, lnum, false);
old_byte += (bcount_t)(strlen(bufline))+1;
}
old_byte += (bcount_t)end_col+1;
diff --git a/src/nvim/api/deprecated.c b/src/nvim/api/deprecated.c
index d2013c597c..6a41df0aa9 100644
--- a/src/nvim/api/deprecated.c
+++ b/src/nvim/api/deprecated.c
@@ -51,11 +51,10 @@ Integer nvim_buf_get_number(Buffer buffer, Error *err)
FUNC_API_SINCE(1)
FUNC_API_DEPRECATED_SINCE(2)
{
- Integer rv = 0;
buf_T *buf = find_buffer_by_handle(buffer, err);
if (!buf) {
- return rv;
+ return 0;
}
return buf->b_fnum;
diff --git a/src/nvim/api/extmark.c b/src/nvim/api/extmark.c
index e355f82f4d..c02688a815 100644
--- a/src/nvim/api/extmark.c
+++ b/src/nvim/api/extmark.c
@@ -10,10 +10,10 @@
#include "nvim/api/private/helpers.h"
#include "nvim/decoration_provider.h"
#include "nvim/extmark.h"
+#include "nvim/highlight_group.h"
#include "nvim/lua/executor.h"
#include "nvim/memline.h"
#include "nvim/screen.h"
-#include "nvim/syntax.h"
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "api/extmark.c.generated.h"
@@ -856,7 +856,7 @@ Integer nvim_buf_add_highlight(Buffer buffer, Integer ns_id, String hl_group, In
int hl_id = 0;
if (hl_group.size > 0) {
- hl_id = syn_check_group(hl_group.data, (int)hl_group.size);
+ hl_id = syn_check_group(hl_group.data, hl_group.size);
} else {
return ns_id;
}
diff --git a/src/nvim/api/private/converter.c b/src/nvim/api/private/converter.c
index 49e3cf7df7..82ec1ad0d8 100644
--- a/src/nvim/api/private/converter.c
+++ b/src/nvim/api/private/converter.c
@@ -64,7 +64,14 @@ typedef struct {
#define TYPVAL_ENCODE_CONV_FUNC_START(tv, fun) \
do { \
- TYPVAL_ENCODE_CONV_NIL(tv); \
+ ufunc_T *fp = find_func(fun); \
+ assert(fp != NULL); \
+ if (fp->uf_cb == nlua_CFunction_func_call) { \
+ LuaRef ref = api_new_luaref(((LuaCFunctionState *)fp->uf_cb_state)->lua_callable.func_ref); \
+ kvi_push(edata->stack, LUAREF_OBJ(ref)); \
+ } else { \
+ TYPVAL_ENCODE_CONV_NIL(tv); \
+ } \
goto typval_encode_stop_converting_one_item; \
} while (0)
@@ -231,14 +238,6 @@ static inline void typval_encode_dict_end(EncodedData *const edata)
/// @return The converted value
Object vim_to_object(typval_T *obj)
{
- if (obj->v_type == VAR_FUNC) {
- ufunc_T *fp = find_func(obj->vval.v_string);
- assert(fp != NULL);
- if (fp->uf_cb == nlua_CFunction_func_call) {
- LuaRef ref = api_new_luaref(((LuaCFunctionState *)fp->uf_cb_state)->lua_callable.func_ref);
- return LUAREF_OBJ(ref);
- }
- }
EncodedData edata;
kvi_init(edata.stack);
const int evo_ret = encode_vim_to_object(&edata, obj,
diff --git a/src/nvim/api/private/dispatch.c b/src/nvim/api/private/dispatch.c
index f670f06357..ba2e560d63 100644
--- a/src/nvim/api/private/dispatch.c
+++ b/src/nvim/api/private/dispatch.c
@@ -30,6 +30,7 @@
#include "nvim/api/vimscript.h"
#include "nvim/api/win_config.h"
#include "nvim/api/window.h"
+#include "nvim/ui_client.h"
static Map(String, MsgpackRpcRequestHandler) methods = MAP_INIT;
@@ -38,6 +39,13 @@ static void msgpack_rpc_add_method_handler(String method, MsgpackRpcRequestHandl
map_put(String, MsgpackRpcRequestHandler)(&methods, method, handler);
}
+void msgpack_rpc_add_redraw(void)
+{
+ msgpack_rpc_add_method_handler(STATIC_CSTR_AS_STRING("redraw"),
+ (MsgpackRpcRequestHandler) { .fn = ui_client_handle_redraw,
+ .fast = true });
+}
+
/// @param name API method name
/// @param name_len name size (includes terminating NUL)
MsgpackRpcRequestHandler msgpack_rpc_get_handler_for(const char *name, size_t name_len,
diff --git a/src/nvim/api/private/helpers.c b/src/nvim/api/private/helpers.c
index 8056950e26..88954a1aa2 100644
--- a/src/nvim/api/private/helpers.c
+++ b/src/nvim/api/private/helpers.c
@@ -22,6 +22,7 @@
#include "nvim/extmark.h"
#include "nvim/fileio.h"
#include "nvim/getchar.h"
+#include "nvim/highlight_group.h"
#include "nvim/lib/kvec.h"
#include "nvim/lua/executor.h"
#include "nvim/map.h"
@@ -32,7 +33,6 @@
#include "nvim/msgpack_rpc/helpers.h"
#include "nvim/option.h"
#include "nvim/option_defs.h"
-#include "nvim/syntax.h"
#include "nvim/ui.h"
#include "nvim/version.h"
#include "nvim/vim.h"
@@ -111,7 +111,7 @@ bool try_leave(const TryState *const tstate, Error *const err)
/// try_enter()/try_leave() pair should be used instead.
void try_start(void)
{
- ++trylevel;
+ trylevel++;
}
/// End try block, set the error message if any and return true if an error
@@ -1037,8 +1037,7 @@ static void set_option_value_for(char *key, int numval, char *stringval, int opt
aco_save_T aco;
try_start();
- switch (opt_type)
- {
+ switch (opt_type) {
case SREQ_WIN:
if (switch_win_noblock(&switchwin, (win_T *)from, win_find_tabpage((win_T *)from), true)
== FAIL) {
@@ -1294,7 +1293,7 @@ int object_to_hl_id(Object obj, const char *what, Error *err)
{
if (obj.type == kObjectTypeString) {
String str = obj.data.string;
- return str.size ? syn_check_group(str.data, (int)str.size) : 0;
+ return str.size ? syn_check_group(str.data, str.size) : 0;
} else if (obj.type == kObjectTypeInteger) {
return MAX((int)obj.data.integer, 0);
} else {
@@ -1328,7 +1327,7 @@ HlMessage parse_hl_msg(Array chunks, Error *err)
String hl = chunk.items[1].data.string;
if (hl.size > 0) {
// TODO(bfredl): use object_to_hl_id and allow integer
- int hl_id = syn_check_group(hl.data, (int)hl.size);
+ int hl_id = syn_check_group(hl.data, hl.size);
attr = hl_id > 0 ? syn_id2attr(hl_id) : 0;
}
}
diff --git a/src/nvim/api/tabpage.c b/src/nvim/api/tabpage.c
index 14b6be8eeb..b994d18c43 100644
--- a/src/nvim/api/tabpage.c
+++ b/src/nvim/api/tabpage.c
@@ -102,11 +102,10 @@ void nvim_tabpage_del_var(Tabpage tabpage, String name, Error *err)
Window nvim_tabpage_get_win(Tabpage tabpage, Error *err)
FUNC_API_SINCE(1)
{
- Window rv = 0;
tabpage_T *tab = find_tab_by_handle(tabpage, err);
if (!tab || !valid_tabpage(tab)) {
- return rv;
+ return 0;
}
if (tab == curtab) {
@@ -130,11 +129,10 @@ Window nvim_tabpage_get_win(Tabpage tabpage, Error *err)
Integer nvim_tabpage_get_number(Tabpage tabpage, Error *err)
FUNC_API_SINCE(1)
{
- Integer rv = 0;
tabpage_T *tab = find_tab_by_handle(tabpage, err);
if (!tab) {
- return rv;
+ return 0;
}
return tabpage_index(tab);
diff --git a/src/nvim/api/ui_events.in.h b/src/nvim/api/ui_events.in.h
index 03fe5c5058..db348359eb 100644
--- a/src/nvim/api/ui_events.in.h
+++ b/src/nvim/api/ui_events.in.h
@@ -78,13 +78,13 @@ void hl_attr_define(Integer id, HlAttrs rgb_attrs, HlAttrs cterm_attrs,
void hl_group_set(String name, Integer id)
FUNC_API_SINCE(6) FUNC_API_BRIDGE_IMPL;
void grid_resize(Integer grid, Integer width, Integer height)
- FUNC_API_SINCE(5) FUNC_API_REMOTE_IMPL FUNC_API_COMPOSITOR_IMPL;
+ FUNC_API_SINCE(5) FUNC_API_REMOTE_IMPL FUNC_API_COMPOSITOR_IMPL FUNC_API_CLIENT_IMPL;
void grid_clear(Integer grid)
FUNC_API_SINCE(5) FUNC_API_REMOTE_IMPL;
void grid_cursor_goto(Integer grid, Integer row, Integer col)
FUNC_API_SINCE(5) FUNC_API_REMOTE_IMPL FUNC_API_COMPOSITOR_IMPL;
void grid_line(Integer grid, Integer row, Integer col_start, Array data)
- FUNC_API_SINCE(5) FUNC_API_REMOTE_ONLY;
+ FUNC_API_SINCE(5) FUNC_API_REMOTE_ONLY FUNC_API_CLIENT_IMPL;
void grid_scroll(Integer grid, Integer top, Integer bot,
Integer left, Integer right, Integer rows, Integer cols)
FUNC_API_SINCE(5) FUNC_API_REMOTE_IMPL FUNC_API_COMPOSITOR_IMPL;
diff --git a/src/nvim/api/vim.c b/src/nvim/api/vim.c
index b691dee2ef..bdeac1a9f4 100644
--- a/src/nvim/api/vim.c
+++ b/src/nvim/api/vim.c
@@ -35,6 +35,7 @@
#include "nvim/globals.h"
#include "nvim/highlight.h"
#include "nvim/highlight_defs.h"
+#include "nvim/highlight_group.h"
#include "nvim/lua/executor.h"
#include "nvim/mark.h"
#include "nvim/memline.h"
@@ -50,7 +51,6 @@
#include "nvim/popupmnu.h"
#include "nvim/screen.h"
#include "nvim/state.h"
-#include "nvim/syntax.h"
#include "nvim/types.h"
#include "nvim/ui.h"
#include "nvim/vim.h"
@@ -112,7 +112,7 @@ Dictionary nvim_get_hl_by_id(Integer hl_id, Boolean rgb, Error *err)
Integer nvim_get_hl_id_by_name(String name)
FUNC_API_SINCE(7)
{
- return syn_check_group(name.data, (int)name.size);
+ return syn_check_group(name.data, name.size);
}
Dictionary nvim__get_hl_defs(Integer ns_id, Error *err)
@@ -123,33 +123,31 @@ Dictionary nvim__get_hl_defs(Integer ns_id, Error *err)
abort();
}
-/// Set a highlight group.
+/// Sets a highlight group.
///
-/// Note: unlike the `:highlight` command which can update a highlight group,
+/// Note: Unlike the `:highlight` command which can update a highlight group,
/// this function completely replaces the definition. For example:
-/// `nvim_set_hl(0, 'Visual', {})` will clear the highlight group 'Visual'.
-///
-/// @param ns_id number of namespace for this highlight. Use value 0
-/// to set a highlight group in the global (`:highlight`)
-/// namespace.
-/// @param name highlight group name, like ErrorMsg
-/// @param val highlight definition map, like |nvim_get_hl_by_name|.
-/// in addition the following keys are also recognized:
-/// `default`: don't override existing definition,
-/// like `hi default`
-/// `ctermfg`: sets foreground of cterm color
-/// `ctermbg`: sets background of cterm color
-/// `cterm` : cterm attribute map. sets attributed for
-/// cterm colors. similer to `hi cterm`
-/// Note: by default cterm attributes are
-/// same as attributes of gui color
+/// ``nvim_set_hl(0, 'Visual', {})`` will clear the highlight group 'Visual'.
+///
+/// @param ns_id Namespace id for this highlight |nvim_create_namespace()|.
+/// Use 0 to set a highlight group globally |:highlight|.
+/// @param name Highlight group name, e.g. "ErrorMsg"
+/// @param val Highlight definition map, like |synIDattr()|. In
+/// addition, the following keys are recognized:
+/// - default: Don't override existing definition |:hi-default|
+/// - ctermfg: Sets foreground of cterm color |highlight-ctermfg|
+/// - ctermbg: Sets background of cterm color |highlight-ctermbg|
+/// - cterm: cterm attribute map, like
+/// |highlight-args|.
+/// Note: Attributes default to those set for `gui`
+/// if not set.
/// @param[out] err Error details, if any
///
// TODO(bfredl): val should take update vs reset flag
void nvim_set_hl(Integer ns_id, String name, Dict(highlight) *val, Error *err)
FUNC_API_SINCE(7)
{
- int hl_id = syn_check_group(name.data, (int)name.size);
+ int hl_id = syn_check_group(name.data, name.size);
int link_id = -1;
HlAttrs attrs = dict2hlattrs(val, true, &link_id, err);
@@ -221,7 +219,7 @@ void nvim_feedkeys(String keys, String mode, Boolean escape_ks)
bool execute = false;
bool dangerous = false;
- for (size_t i = 0; i < mode.size; ++i) {
+ for (size_t i = 0; i < mode.size; i++) {
switch (mode.data[i]) {
case 'n':
remap = false; break;
@@ -1140,6 +1138,7 @@ Integer nvim_open_term(Buffer buffer, DictionaryOf(LuaRef) opts, Error *err)
TerminalOptions topts;
Channel *chan = channel_alloc(kChannelStreamInternal);
chan->stream.internal.cb = cb;
+ chan->stream.internal.closed = false;
topts.data = chan;
// NB: overridden in terminal_check_size if a window is already
// displaying the buffer
@@ -1881,7 +1880,7 @@ static void write_msg(String message, bool to_err)
} \
line_buf[pos++] = message.data[i];
- ++no_wait_return;
+ no_wait_return++;
for (uint32_t i = 0; i < message.size; i++) {
if (got_int) {
break;
@@ -1892,7 +1891,7 @@ static void write_msg(String message, bool to_err)
PUSH_CHAR(i, out_pos, out_line_buf, msg);
}
}
- --no_wait_return;
+ no_wait_return--;
msg_end();
}
@@ -1997,9 +1996,8 @@ Array nvim_get_proc_children(Integer pid, Error *err)
DLOG("fallback to vim._os_proc_children()");
Array a = ARRAY_DICT_INIT;
ADD(a, INTEGER_OBJ(pid));
- String s = cstr_to_string("return vim._os_proc_children(...)");
+ String s = STATIC_CSTR_AS_STRING("return vim._os_proc_children(...)");
Object o = nlua_exec(s, a, err);
- api_free_string(s);
api_free_array(a);
if (o.type == kObjectTypeArray) {
rvobj = o.data.array;
@@ -2331,7 +2329,7 @@ Dictionary nvim_eval_statusline(String str, Dict(eval_statusline) *opts, Error *
maxwidth = (int)opts->maxwidth.data.integer;
} else {
- maxwidth = use_tabline ? Columns : wp->w_width;
+ maxwidth = (use_tabline || global_stl_height() > 0) ? Columns : wp->w_width;
}
char buf[MAXPATHL];
diff --git a/src/nvim/api/win_config.c b/src/nvim/api/win_config.c
index ceb7f71423..b0267f5ed0 100644
--- a/src/nvim/api/win_config.c
+++ b/src/nvim/api/win_config.c
@@ -10,6 +10,7 @@
#include "nvim/api/private/helpers.h"
#include "nvim/api/win_config.h"
#include "nvim/ascii.h"
+#include "nvim/highlight_group.h"
#include "nvim/option.h"
#include "nvim/screen.h"
#include "nvim/strings.h"
@@ -131,7 +132,7 @@
/// An empty string can be used to turn off a specific border, for instance,
/// [ "", "", "", ">", "", "", "", "<" ]
/// will only make vertical borders but not horizontal ones.
-/// By default, `FloatBorder` highlight is used, which links to `VertSplit`
+/// By default, `FloatBorder` highlight is used, which links to `WinSeparator`
/// when not defined. It could also be specified by character:
/// [ {"+", "MyCorner"}, {"x", "MyBorder"} ].
/// - noautocmd: If true then no buffer-related autocommand events such as
diff --git a/src/nvim/api/window.c b/src/nvim/api/window.c
index 9c473ff724..be43708604 100644
--- a/src/nvim/api/window.c
+++ b/src/nvim/api/window.c
@@ -71,7 +71,7 @@ ArrayOf(Integer, 2) nvim_win_get_cursor(Window window, Error *err)
}
/// Sets the (1,0)-indexed cursor position in the window. |api-indexing|
-/// Unlike |win_execute()| this scrolls the window.
+/// This scrolls the window even if it is not the current one.
///
/// @param window Window handle, or 0 for current window
/// @param pos (row, col) tuple representing the new position
diff --git a/src/nvim/autocmd.c b/src/nvim/autocmd.c
index dfcdfd8203..df336d8703 100644
--- a/src/nvim/autocmd.c
+++ b/src/nvim/autocmd.c
@@ -137,8 +137,6 @@ static inline const char *get_deleted_augroup(void) FUNC_ATTR_ALWAYS_INLINE
// Show the autocommands for one AutoPat.
static void aupat_show(AutoPat *ap)
{
- AutoCmd *ac;
-
// Check for "got_int" (here and at various places below), which is set
// when "q" has been hit for the "--more--" prompt
if (got_int) {
@@ -153,7 +151,7 @@ static void aupat_show(AutoPat *ap)
msg_col = 4;
msg_outtrans(ap->pat);
- for (ac = ap->cmds; ac != NULL; ac = ac->next) {
+ for (AutoCmd *ac = ap->cmds; ac != NULL; ac = ac->next) {
// skip removed commands
if (aucmd_exec_is_deleted(ac->exec)) {
continue;
@@ -278,9 +276,6 @@ static void aucmd_del(AutoCmd *ac)
/// This is only done when not executing autocommands.
static void au_cleanup(void)
{
- AutoPat *ap;
- AutoPat **prev_ap;
-
if (autocmd_busy || !au_need_clean) {
return;
}
@@ -288,8 +283,8 @@ static void au_cleanup(void)
// Loop over all events.
FOR_ALL_AUEVENTS(event) {
// Loop over all autocommand patterns.
- prev_ap = &(first_autopat[(int)event]);
- for (ap = *prev_ap; ap != NULL; ap = *prev_ap) {
+ AutoPat **prev_ap = &(first_autopat[(int)event]);
+ for (AutoPat *ap = *prev_ap; ap != NULL; ap = *prev_ap) {
bool has_cmd = false;
// Loop over all commands for this pattern.
@@ -351,10 +346,8 @@ AutoPat *au_get_autopat_for_event(event_T event)
// autocmds.
void aubuflocal_remove(buf_T *buf)
{
- AutoPatCmd *apc;
-
// invalidate currently executing autocommands
- for (apc = active_apc_list; apc; apc = apc->next) {
+ for (AutoPatCmd *apc = active_apc_list; apc; apc = apc->next) {
if (buf->b_fnum == apc->arg_bufnr) {
apc->arg_bufnr = 0;
}
@@ -404,7 +397,7 @@ int augroup_add(char *name)
}
/// Delete the augroup that matches name.
-/// @param stupid_legacy_mode bool: This paremeter determines whether to run the augroup
+/// @param stupid_legacy_mode bool: This parameter determines whether to run the augroup
/// deletion in the same fashion as `:augroup! {name}` where if there are any remaining
/// autocmds left in the augroup, it will change the name of the augroup to `--- DELETED ---`
/// but leave the autocmds existing. These are _separate_ augroups, so if you do this for
@@ -586,13 +579,12 @@ event_T event_name2nr(const char_u *start, char_u **end)
{
const char_u *p;
int i;
- int len;
// the event name ends with end of line, '|', a blank or a comma
for (p = start; *p && !ascii_iswhite(*p) && *p != ',' && *p != '|'; p++) {
}
for (i = 0; event_names[i].name != NULL; i++) {
- len = (int)event_names[i].len;
+ int len = (int)event_names[i].len;
if (len == p - start && STRNICMP(event_names[i].name, start, len) == 0) {
break;
}
@@ -615,9 +607,7 @@ event_T event_name2nr(const char_u *start, char_u **end)
const char *event_nr2name(event_T event)
FUNC_ATTR_NONNULL_RET FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_CONST
{
- int i;
-
- for (i = 0; event_names[i].name != NULL; i++) {
+ for (int i = 0; event_names[i].name != NULL; i++) {
if (event_names[i].event == event) {
return event_names[i].name;
}
@@ -670,11 +660,8 @@ int check_ei(void)
// Returns the old value of 'eventignore' in allocated memory.
char_u *au_event_disable(char *what)
{
- char_u *new_ei;
- char_u *save_ei;
-
- save_ei = vim_strsave(p_ei);
- new_ei = vim_strnsave(p_ei, STRLEN(p_ei) + STRLEN(what));
+ char_u *save_ei = vim_strsave(p_ei);
+ char_u *new_ei = vim_strnsave(p_ei, STRLEN(p_ei) + STRLEN(what));
if (*what == ',' && *p_ei == NUL) {
STRCPY(new_ei, what + 1);
} else {
@@ -729,7 +716,6 @@ void au_event_restore(char_u *old_ei)
void do_autocmd(char_u *arg_in, int forceit)
{
char_u *arg = arg_in;
- char_u *pat;
char_u *envpat = NULL;
char_u *cmd;
int need_free = false;
@@ -747,7 +733,7 @@ void do_autocmd(char_u *arg_in, int forceit)
// Scan over the events.
// If we find an illegal name, return here, don't do anything.
- pat = arg_event_skip(arg, group != AUGROUP_ALL);
+ char_u *pat = arg_event_skip(arg, group != AUGROUP_ALL);
if (pat == NULL) {
return;
}
@@ -877,8 +863,6 @@ int do_autocmd_event(event_T event, char_u *pat, bool once, int nested, char_u *
AutoPat *ap;
AutoPat **prev_ap;
int findgroup;
- int patlen;
- int is_buflocal;
int buflocal_nr;
char_u buflocal_pat[BUFLOCAL_PAT_LEN]; // for "<buffer=X>"
@@ -897,10 +881,10 @@ int do_autocmd_event(event_T event, char_u *pat, bool once, int nested, char_u *
}
// Loop through all the specified patterns.
- patlen = (int)aucmd_pattern_length(pat);
+ int patlen = (int)aucmd_pattern_length(pat);
while (patlen) {
// detect special <buffer[=X]> buffer-local patterns
- is_buflocal = aupat_is_buflocal(pat, patlen);
+ int is_buflocal = aupat_is_buflocal(pat, patlen);
if (is_buflocal) {
buflocal_nr = aupat_get_buflocal_nr(pat, patlen);
@@ -968,9 +952,6 @@ int autocmd_register(int64_t id, event_T event, char_u *pat, int patlen, int gro
AutoPat *ap;
AutoPat **prev_ap;
AutoCmd *ac;
- AutoCmd **prev_ac;
- int is_buflocal;
- int buflocal_nr;
int findgroup;
char_u buflocal_pat[BUFLOCAL_PAT_LEN]; // for "<buffer=X>"
@@ -986,8 +967,8 @@ int autocmd_register(int64_t id, event_T event, char_u *pat, int patlen, int gro
// detect special <buffer[=X]> buffer-local patterns
- is_buflocal = aupat_is_buflocal(pat, patlen);
- buflocal_nr = 0;
+ int is_buflocal = aupat_is_buflocal(pat, patlen);
+ int buflocal_nr = 0;
if (is_buflocal) {
buflocal_nr = aupat_get_buflocal_nr(pat, patlen);
@@ -1083,7 +1064,7 @@ int autocmd_register(int64_t id, event_T event, char_u *pat, int patlen, int gro
}
// Add the autocmd at the end of the AutoCmd list.
- prev_ac = &(ap->cmds);
+ AutoCmd **prev_ac = &(ap->cmds);
while ((ac = *prev_ac) != NULL) {
prev_ac = &ac->next;
}
@@ -1160,16 +1141,14 @@ char_u *aucmd_next_pattern(char_u *pat, size_t patlen)
/// @param do_msg give message for no matching autocmds?
int do_doautocmd(char_u *arg, bool do_msg, bool *did_something)
{
- char_u *fname;
int nothing_done = true;
- int group;
if (did_something != NULL) {
*did_something = false;
}
// Check for a legal group name. If not, use AUGROUP_ALL.
- group = arg_augroup_get(&arg);
+ int group = arg_augroup_get(&arg);
if (*arg == '*') {
emsg(_("E217: Can't execute autocommands for ALL events"));
@@ -1178,7 +1157,7 @@ int do_doautocmd(char_u *arg, bool do_msg, bool *did_something)
// Scan over the events.
// If we find an illegal name, return here, don't do anything.
- fname = arg_event_skip(arg, group != AUGROUP_ALL);
+ char_u *fname = arg_event_skip(arg, group != AUGROUP_ALL);
if (fname == NULL) {
return FAIL;
}
@@ -1542,11 +1521,9 @@ bool has_cursorhold(void) FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT
/// Return true if the CursorHold/CursorHoldI event can be triggered.
bool trigger_cursorhold(void) FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT
{
- int state;
-
if (!did_cursorhold && has_cursorhold() && reg_recording == 0
&& typebuf.tb_len == 0 && !ins_compl_active()) {
- state = get_real_state();
+ int state = get_real_state();
if (state == NORMAL_BUSY || (state & INSERT) != 0) {
return true;
}
@@ -1570,19 +1547,8 @@ bool apply_autocmds_group(event_T event, char_u *fname, char_u *fname_io, bool f
buf_T *buf, exarg_T *eap)
{
char_u *sfname = NULL; // short file name
- char_u *tail;
- bool save_changed;
- buf_T *old_curbuf;
bool retval = false;
- char_u *save_sourcing_name;
- linenr_T save_sourcing_lnum;
- char_u *save_autocmd_fname;
- int save_autocmd_bufnr;
- char_u *save_autocmd_match;
- int save_autocmd_busy;
- int save_autocmd_nested;
static int nesting = 0;
- AutoPatCmd patcmd;
AutoPat *ap;
char_u *save_cmdarg;
long save_cmdbang;
@@ -1639,13 +1605,13 @@ bool apply_autocmds_group(event_T event, char_u *fname, char_u *fname_io, bool f
}
// Save the autocmd_* variables and info about the current buffer.
- save_autocmd_fname = autocmd_fname;
- save_autocmd_bufnr = autocmd_bufnr;
- save_autocmd_match = autocmd_match;
- save_autocmd_busy = autocmd_busy;
- save_autocmd_nested = autocmd_nested;
- save_changed = curbuf->b_changed;
- old_curbuf = curbuf;
+ char_u *save_autocmd_fname = autocmd_fname;
+ int save_autocmd_bufnr = autocmd_bufnr;
+ char_u *save_autocmd_match = autocmd_match;
+ int save_autocmd_busy = autocmd_busy;
+ int save_autocmd_nested = autocmd_nested;
+ bool save_changed = curbuf->b_changed;
+ buf_T *old_curbuf = curbuf;
// Set the file name to be used for <afile>.
// Make a copy to avoid that changing a buffer name or directory makes it
@@ -1738,9 +1704,9 @@ bool apply_autocmds_group(event_T event, char_u *fname, char_u *fname_io, bool f
// Don't redraw while doing autocommands.
RedrawingDisabled++;
- save_sourcing_name = sourcing_name;
+ char_u *save_sourcing_name = sourcing_name;
sourcing_name = NULL; // don't free this one
- save_sourcing_lnum = sourcing_lnum;
+ linenr_T save_sourcing_lnum = sourcing_lnum;
sourcing_lnum = 0; // no line number here
const sctx_T save_current_sctx = current_sctx;
@@ -1773,9 +1739,10 @@ bool apply_autocmds_group(event_T event, char_u *fname, char_u *fname_io, bool f
did_filetype = true;
}
- tail = path_tail(fname);
+ char_u *tail = path_tail(fname);
// Find first autocommand that matches
+ AutoPatCmd patcmd;
patcmd.curpat = first_autopat[(int)event];
patcmd.nextcmd = NULL;
patcmd.group = group;
@@ -2009,7 +1976,6 @@ char_u *getnextac(int c, void *cookie, int indent, bool do_concat)
AutoPatCmd *acp = (AutoPatCmd *)cookie;
char_u *retval;
- AutoCmd *ac;
// Can be called again after returning the last line.
if (acp->curpat == NULL) {
@@ -2046,7 +2012,7 @@ char_u *getnextac(int c, void *cookie, int indent, bool do_concat)
}
}
- ac = acp->nextcmd;
+ AutoCmd *ac = acp->nextcmd;
if (p_verbose >= 9) {
verbose_enter_scroll();
@@ -2099,12 +2065,10 @@ char_u *getnextac(int c, void *cookie, int indent, bool do_concat)
/// @param buf buffer the file is open in
bool has_autocmd(event_T event, char_u *sfname, buf_T *buf) FUNC_ATTR_WARN_UNUSED_RESULT
{
- AutoPat *ap;
- char_u *fname;
char_u *tail = path_tail(sfname);
bool retval = false;
- fname = (char_u *)FullName_save((char *)sfname, false);
+ char_u *fname = (char_u *)FullName_save((char *)sfname, false);
if (fname == NULL) {
return false;
}
@@ -2117,7 +2081,7 @@ bool has_autocmd(event_T event, char_u *sfname, buf_T *buf) FUNC_ATTR_WARN_UNUSE
forward_slash(fname);
#endif
- for (ap = first_autopat[(int)event]; ap != NULL; ap = ap->next) {
+ for (AutoPat *ap = first_autopat[(int)event]; ap != NULL; ap = ap->next) {
if (ap->pat != NULL && ap->cmds != NULL
&& (ap->buflocal_nr == 0
? match_file_pat(NULL,
@@ -2153,13 +2117,10 @@ char_u *expand_get_augroup_name(expand_T *xp, int idx)
/// @param doautocmd true for :doauto*, false for :autocmd
char_u *set_context_in_autocmd(expand_T *xp, char_u *arg, int doautocmd)
{
- char_u *p;
- int group;
-
// check for a group name, skip it if present
autocmd_include_groups = false;
- p = arg;
- group = arg_augroup_get(&arg);
+ char_u *p = arg;
+ int group = arg_augroup_get(&arg);
// If there only is a group name that's what we expand.
if (*arg == NUL && group != AUGROUP_ALL && !ascii_iswhite(arg[-1])) {
@@ -2205,7 +2166,6 @@ char_u *expand_get_event_name(expand_T *xp, int idx)
// xp is a required parameter to be used with ExpandGeneric
(void)xp;
-
// List group names
char *name = augroup_name(idx + 1);
if (name != NULL) {
@@ -2247,10 +2207,7 @@ bool autocmd_supported(const char *const event)
/// @param arg autocommand string
bool au_exists(const char *const arg) FUNC_ATTR_WARN_UNUSED_RESULT
{
- event_T event;
- AutoPat *ap;
buf_T *buflocal_buf = NULL;
- int group;
bool retval = false;
// Make a copy so that we can change the '#' chars to a NUL.
@@ -2261,7 +2218,7 @@ bool au_exists(const char *const arg) FUNC_ATTR_WARN_UNUSED_RESULT
}
// First, look for an autocmd group name.
- group = augroup_find(arg_save);
+ int group = augroup_find(arg_save);
char *event_name;
if (group == AUGROUP_ERROR) {
// Didn't match a group name, assume the first argument is an event.
@@ -2285,7 +2242,7 @@ bool au_exists(const char *const arg) FUNC_ATTR_WARN_UNUSED_RESULT
char *pattern = p; // "pattern" is NULL when there is no pattern.
// Find the index (enum) for the event name.
- event = event_name2nr((char_u *)event_name, (char_u **)&p);
+ event_T event = event_name2nr((char_u *)event_name, (char_u **)&p);
// return false if the event name is not recognized
if (event == NUM_EVENTS) {
@@ -2295,7 +2252,7 @@ bool au_exists(const char *const arg) FUNC_ATTR_WARN_UNUSED_RESULT
// Find the first autocommand for this event.
// If there isn't any, return false;
// If there is one and no pattern given, return true;
- ap = first_autopat[(int)event];
+ AutoPat *ap = first_autopat[(int)event];
if (ap == NULL) {
goto theend;
}
@@ -2535,7 +2492,6 @@ static char_u *arg_event_skip(char_u *arg, int have_group)
// Returns the group ID or AUGROUP_ALL.
static int arg_augroup_get(char_u **argp)
{
- char_u *group_name;
char_u *p;
char_u *arg = *argp;
int group = AUGROUP_ALL;
@@ -2543,7 +2499,7 @@ static int arg_augroup_get(char_u **argp)
for (p = arg; *p && !ascii_iswhite(*p) && *p != '|'; p++) {
}
if (p > arg) {
- group_name = vim_strnsave(arg, (size_t)(p - arg));
+ char_u *group_name = vim_strnsave(arg, (size_t)(p - arg));
group = augroup_find((char *)group_name);
if (group == AUGROUP_ERROR) {
group = AUGROUP_ALL; // no match, use all groups
diff --git a/src/nvim/buffer.c b/src/nvim/buffer.c
index 402bd2c6de..1293edb1da 100644
--- a/src/nvim/buffer.c
+++ b/src/nvim/buffer.c
@@ -51,6 +51,7 @@
#include "nvim/getchar.h"
#include "nvim/hashtab.h"
#include "nvim/highlight.h"
+#include "nvim/highlight_group.h"
#include "nvim/indent.h"
#include "nvim/indent_c.h"
#include "nvim/main.h"
@@ -4947,8 +4948,8 @@ void ex_buffer_all(exarg_T *eap)
wpnext = wp->w_next;
if ((wp->w_buffer->b_nwindows > 1
|| ((cmdmod.split & WSP_VERT)
- ? wp->w_height + wp->w_status_height < Rows - p_ch
- - tabline_height()
+ ? wp->w_height + wp->w_hsep_height + wp->w_status_height < Rows - p_ch
+ - tabline_height() - global_stl_height()
: wp->w_width != Columns)
|| (had_tab > 0 && wp != firstwin))
&& !ONE_WINDOW
@@ -5333,16 +5334,12 @@ bool buf_hide(const buf_T *const buf)
char_u *buf_spname(buf_T *buf)
{
if (bt_quickfix(buf)) {
- win_T *win;
- tabpage_T *tp;
-
- // For location list window, w_llist_ref points to the location list.
- // For quickfix window, w_llist_ref is NULL.
- if (find_win_for_buf(buf, &win, &tp) && win->w_llist_ref != NULL) {
- return (char_u *)_(msg_loclist);
- } else {
+ // Differentiate between the quickfix and location list buffers using
+ // the buffer number stored in the global quickfix stack.
+ if (buf->b_fnum == qf_stack_get_bufnr()) {
return (char_u *)_(msg_qflist);
}
+ return (char_u *)_(msg_loclist);
}
// There is no _file_ when 'buftype' is "nofile", b_sfname
// contains the name as specified by the user.
diff --git a/src/nvim/buffer_defs.h b/src/nvim/buffer_defs.h
index 7acb646980..f9541a55a3 100644
--- a/src/nvim/buffer_defs.h
+++ b/src/nvim/buffer_defs.h
@@ -1232,7 +1232,13 @@ struct window_S {
struct {
int stl;
int stlnc;
+ int horiz;
+ int horizup;
+ int horizdown;
int vert;
+ int vertleft;
+ int vertright;
+ int verthoriz;
int fold;
int foldopen; ///< when fold is open
int foldclosed; ///< when fold is closed
@@ -1278,7 +1284,8 @@ struct window_S {
int w_status_height; // number of status lines (0 or 1)
int w_wincol; // Leftmost column of window in screen.
int w_width; // Width of window, excluding separation.
- int w_vsep_width; // Number of separator columns (0 or 1).
+ int w_hsep_height; // Number of horizontal separator rows (0 or 1)
+ int w_vsep_width; // Number of vertical separator columns (0 or 1).
pos_save_T w_save_cursor; // backup of cursor pos and topline
// inner size of window, which can be overridden by external UI
diff --git a/src/nvim/change.c b/src/nvim/change.c
index 736867b6d3..6c3dbf72e4 100644
--- a/src/nvim/change.c
+++ b/src/nvim/change.c
@@ -42,7 +42,7 @@
/// Careful: may trigger autocommands that reload the buffer.
void change_warning(buf_T *buf, int col)
{
- static char *w_readonly = N_("W10: Warning: Changing a readonly file");
+ static const char *w_readonly = N_("W10: Warning: Changing a readonly file");
if (buf->b_did_warn == false
&& curbufIsChanged() == 0
@@ -140,10 +140,6 @@ void changed_internal(void)
/// Careful: may trigger autocommands that reload the buffer.
static void changed_common(linenr_T lnum, colnr_T col, linenr_T lnume, long xtra)
{
- int i;
- pos_T *p;
- int add;
-
// mark the buffer as modified
changed();
@@ -158,13 +154,14 @@ static void changed_common(linenr_T lnum, colnr_T col, linenr_T lnume, long xtra
// Create a new entry if a new undo-able change was started or we
// don't have an entry yet.
if (curbuf->b_new_change || curbuf->b_changelistlen == 0) {
+ int add;
if (curbuf->b_changelistlen == 0) {
add = true;
} else {
// Don't create a new entry when the line number is the same
// as the last one and the column is not too far away. Avoids
// creating many entries for typing "xxxxx".
- p = &curbuf->b_changelist[curbuf->b_changelistlen - 1].mark;
+ pos_T *p = &curbuf->b_changelist[curbuf->b_changelistlen - 1].mark;
if (p->lnum != lnum) {
add = true;
} else {
@@ -243,7 +240,7 @@ static void changed_common(linenr_T lnum, colnr_T col, linenr_T lnume, long xtra
// If the changed line is in a range of previously folded lines,
// compare with the first line in that range.
if (wp->w_cursor.lnum <= lnum) {
- i = find_wl_entry(wp, lnum);
+ int i = find_wl_entry(wp, lnum);
if (i >= 0 && wp->w_cursor.lnum > wp->w_lines[i].wl_lnum) {
changed_line_abv_curs_win(wp);
}
@@ -264,7 +261,7 @@ static void changed_common(linenr_T lnum, colnr_T col, linenr_T lnume, long xtra
// For entries below the change: Correct the lnums for
// inserted/deleted lines. Makes it possible to stop displaying
// after the change.
- for (i = 0; i < wp->w_lines_valid; i++) {
+ for (int i = 0; i < wp->w_lines_valid; i++) {
if (wp->w_lines[i].wl_valid) {
if (wp->w_lines[i].wl_lnum >= lnum) {
if (wp->w_lines[i].wl_lnum < lnume) {
@@ -352,12 +349,10 @@ void changed_bytes(linenr_T lnum, colnr_T col)
// Diff highlighting in other diff windows may need to be updated too.
if (curwin->w_p_diff) {
- linenr_T wlnum;
-
FOR_ALL_WINDOWS_IN_TAB(wp, curtab) {
if (wp->w_p_diff && wp != curwin) {
redraw_later(wp, VALID);
- wlnum = diff_lnum_win(lnum, wp);
+ linenr_T wlnum = diff_lnum_win(lnum, wp);
if (wlnum > 0) {
changedOneline(wp->w_buffer, wlnum);
}
@@ -413,7 +408,7 @@ void deleted_lines(linenr_T lnum, long count)
/// be triggered to display the cursor.
void deleted_lines_mark(linenr_T lnum, long count)
{
- // if we deleted the entire buffer, we need to implicity add a new empty line
+ // if we deleted the entire buffer, we need to implicitly add a new empty line
bool made_empty = (count > 0) && curbuf->b_ml.ml_flags & ML_EMPTY;
mark_adjust(lnum, (linenr_T)(lnum + count - 1), (long)MAXLNUM,
@@ -673,21 +668,18 @@ void ins_char_bytes(char_u *buf, size_t charlen)
/// Caller must have prepared for undo.
void ins_str(char_u *s)
{
- char_u *oldp, *newp;
int newlen = (int)STRLEN(s);
- int oldlen;
- colnr_T col;
linenr_T lnum = curwin->w_cursor.lnum;
if (virtual_active() && curwin->w_cursor.coladd > 0) {
coladvance_force(getviscol());
}
- col = curwin->w_cursor.col;
- oldp = ml_get(lnum);
- oldlen = (int)STRLEN(oldp);
+ colnr_T col = curwin->w_cursor.col;
+ char_u *oldp = ml_get(lnum);
+ int oldlen = (int)STRLEN(oldp);
- newp = (char_u *)xmalloc((size_t)oldlen + (size_t)newlen + 1);
+ char_u *newp = (char_u *)xmalloc((size_t)oldlen + (size_t)newlen + 1);
if (col > 0) {
memmove(newp, oldp, (size_t)col);
}
@@ -719,13 +711,9 @@ int del_char(bool fixpos)
int del_chars(long count, int fixpos)
{
int bytes = 0;
- long i;
- char_u *p;
- int l;
-
- p = get_cursor_pos_ptr();
- for (i = 0; i < count && *p != NUL; i++) {
- l = utfc_ptr2len(p);
+ char_u *p = get_cursor_pos_ptr();
+ for (long i = 0; i < count && *p != NUL; i++) {
+ int l = utfc_ptr2len(p);
bytes += l;
p += l;
}
@@ -768,12 +756,11 @@ int del_bytes(colnr_T count, bool fixpos_arg, bool use_delcombine)
if (p_deco && use_delcombine
&& utfc_ptr2len(oldp + col) >= count) {
int cc[MAX_MCO];
- int n;
(void)utfc_ptr2char(oldp + col, cc);
if (cc[0] != NUL) {
// Find the last composing char, there can be several.
- n = col;
+ int n = col;
do {
col = n;
count = utf_ptr2len(oldp + n);
@@ -828,23 +815,18 @@ int copy_indent(int size, char_u *src)
{
char_u *p = NULL;
char_u *line = NULL;
- char_u *s;
- int todo;
int ind_len;
int line_len = 0;
int tab_pad;
- int ind_done;
- int round;
- int ind_col;
// Round 1: compute the number of characters needed for the indent
// Round 2: copy the characters.
- for (round = 1; round <= 2; round++) {
- todo = size;
+ for (int round = 1; round <= 2; round++) {
+ int todo = size;
ind_len = 0;
- ind_done = 0;
- ind_col = 0;
- s = src;
+ int ind_done = 0;
+ int ind_col = 0;
+ char_u *s = src;
// Count/copy the usable portion of the source line.
while (todo > 0 && ascii_iswhite(*s)) {
@@ -1065,7 +1047,6 @@ int open_line(int dir, int flags, int second_line_indent, bool *did_do_comment)
if (!trunc_line && do_si && *saved_line != NUL
&& (p_extra == NULL || first_char != '{')) {
char_u *ptr;
- char_u last_char;
old_cursor = curwin->w_cursor;
ptr = saved_line;
@@ -1075,8 +1056,7 @@ int open_line(int dir, int flags, int second_line_indent, bool *did_do_comment)
lead_len = 0;
}
if (dir == FORWARD) {
- // Skip preprocessor directives, unless they are
- // recognised as comments.
+ // Skip preprocessor directives, unless they are recognised as comments.
if (lead_len == 0 && ptr[0] == '#') {
while (ptr[0] == '#' && curwin->w_cursor.lnum > 1) {
ptr = ml_get(--curwin->w_cursor.lnum);
@@ -1119,7 +1099,7 @@ int open_line(int dir, int flags, int second_line_indent, bool *did_do_comment)
while (p > ptr && ascii_iswhite(*p)) {
p--;
}
- last_char = *p;
+ char_u last_char = *p;
// find the character just before the '{' or ';'
if (last_char == '{' || last_char == ';') {
@@ -1896,10 +1876,8 @@ void del_lines(long nlines, bool undo)
/// If "include_space" is set, include trailing whitespace while calculating the length.
int get_leader_len(char_u *line, char_u **flags, bool backward, bool include_space)
{
- int i, j;
- int result;
+ int j;
int got_com = false;
- int found_one;
char_u part_buf[COM_MAX_LEN]; // buffer for one option part
char_u *string; // pointer to comment string
char_u *list;
@@ -1907,7 +1885,8 @@ int get_leader_len(char_u *line, char_u **flags, bool backward, bool include_spa
char_u *prev_list;
char_u *saved_flags = NULL;
- result = i = 0;
+ int result = 0;
+ int i = 0;
while (ascii_iswhite(line[i])) { // leading white space is ignored
i++;
}
@@ -1915,7 +1894,7 @@ int get_leader_len(char_u *line, char_u **flags, bool backward, bool include_spa
// Repeat to match several nested comment strings.
while (line[i] != NUL) {
// scan through the 'comments' option for a match
- found_one = false;
+ int found_one = false;
for (list = curbuf->b_p_com; *list;) {
// Get one option part into part_buf[]. Advance "list" to next
// one. Put "string" at start of string.
@@ -2041,20 +2020,19 @@ int get_leader_len(char_u *line, char_u **flags, bool backward, bool include_spa
int get_last_leader_offset(char_u *line, char_u **flags)
{
int result = -1;
- int i, j;
+ int j;
int lower_check_bound = 0;
char_u *string;
char_u *com_leader;
char_u *com_flags;
char_u *list;
- int found_one;
char_u part_buf[COM_MAX_LEN]; // buffer for one option part
// Repeat to match several nested comment strings.
- i = (int)STRLEN(line);
+ int i = (int)STRLEN(line);
while (--i >= lower_check_bound) {
// scan through the 'comments' option for a match
- found_one = false;
+ int found_one = false;
for (list = curbuf->b_p_com; *list;) {
char_u *flags_save = list;
diff --git a/src/nvim/channel.c b/src/nvim/channel.c
index d79c0acc4a..f87b3a2f8f 100644
--- a/src/nvim/channel.c
+++ b/src/nvim/channel.c
@@ -138,8 +138,14 @@ bool channel_close(uint64_t id, ChannelPart part, const char **error)
*error = (const char *)e_invstream;
return false;
}
- api_free_luaref(chan->stream.internal.cb);
- chan->stream.internal.cb = LUA_NOREF;
+ if (chan->term) {
+ api_free_luaref(chan->stream.internal.cb);
+ chan->stream.internal.cb = LUA_NOREF;
+ chan->stream.internal.closed = true;
+ terminal_close(chan->term, 0);
+ } else {
+ channel_decref(chan);
+ }
break;
default:
@@ -536,7 +542,11 @@ size_t channel_send(uint64_t id, char *data, size_t len, bool data_owned, const
}
if (chan->streamtype == kChannelStreamInternal) {
- if (!chan->term) {
+ if (chan->is_rpc) {
+ *error = _("Can't send raw data to rpc channel");
+ goto retfree;
+ }
+ if (!chan->term || chan->stream.internal.closed) {
*error = _("Can't send data to closed stream");
goto retfree;
}
diff --git a/src/nvim/channel.h b/src/nvim/channel.h
index 50d6b3600a..5cec5731eb 100644
--- a/src/nvim/channel.h
+++ b/src/nvim/channel.h
@@ -44,6 +44,7 @@ typedef struct {
typedef struct {
LuaRef cb;
+ bool closed;
} InternalState;
typedef struct {
diff --git a/src/nvim/charset.c b/src/nvim/charset.c
index 3383dd2a76..986a89b0a5 100644
--- a/src/nvim/charset.c
+++ b/src/nvim/charset.c
@@ -159,7 +159,7 @@ int buf_init_chartab(buf_T *buf, int global)
if ((*p == '^') && (p[1] != NUL)) {
tilde = true;
- ++p;
+ p++;
}
if (ascii_isdigit(*p)) {
@@ -170,7 +170,7 @@ int buf_init_chartab(buf_T *buf, int global)
c2 = -1;
if ((*p == '-') && (p[1] != NUL)) {
- ++p;
+ p++;
if (ascii_isdigit(*p)) {
c2 = getdigits_int((char_u **)&p, true, 0);
@@ -243,7 +243,7 @@ int buf_init_chartab(buf_T *buf, int global)
}
}
}
- ++c;
+ c++;
}
c = *p;
@@ -268,15 +268,12 @@ int buf_init_chartab(buf_T *buf, int global)
/// @param bufsize
void trans_characters(char_u *buf, int bufsize)
{
- int len; // length of string needing translation
- int room; // room in buffer after string
- char_u *trs; // translated character
- int trs_len; // length of trs[]
-
- len = (int)STRLEN(buf);
- room = bufsize - len;
+ char_u *trs; // translated character
+ int len = (int)STRLEN(buf); // length of string needing translation
+ int room = bufsize - len; // room in buffer after string
while (*buf != 0) {
+ int trs_len; // length of trs[]
// Assume a multi-byte character doesn't need translation.
if ((trs_len = utfc_ptr2len(buf)) > 1) {
len -= trs_len;
@@ -292,7 +289,7 @@ void trans_characters(char_u *buf, int bufsize)
memmove(buf + trs_len, buf + 1, (size_t)len);
}
memmove(buf, trs, (size_t)trs_len);
- --len;
+ len--;
}
buf += trs_len;
}
@@ -873,14 +870,11 @@ bool vim_isprintc_strict(int c)
bool in_win_border(win_T *wp, colnr_T vcol)
FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ARG(1)
{
- int width1; // width of first line (after line number)
- int width2; // width of further lines
-
if (wp->w_width_inner == 0) {
// there is no border
return false;
}
- width1 = wp->w_width_inner - win_col_off(wp);
+ int width1 = wp->w_width_inner - win_col_off(wp); // width of first line (after line number)
if ((int)vcol < width1 - 1) {
return false;
@@ -889,7 +883,7 @@ bool in_win_border(win_T *wp, colnr_T vcol)
if ((int)vcol == width1 - 1) {
return true;
}
- width2 = width1 + win_col_off2(wp);
+ int width2 = width1 + win_col_off2(wp); // width of further lines
if (width2 <= 0) {
return false;
@@ -911,18 +905,15 @@ bool in_win_border(win_T *wp, colnr_T vcol)
/// @param end
void getvcol(win_T *wp, pos_T *pos, colnr_T *start, colnr_T *cursor, colnr_T *end)
{
- colnr_T vcol;
char_u *ptr; // points to current char
char_u *posptr; // points to char at pos->col
- char_u *line; // start of the line
int incr;
int head;
long *vts = wp->w_buffer->b_p_vts_array;
int ts = (int)wp->w_buffer->b_p_ts;
- int c;
- vcol = 0;
- line = ptr = ml_get_buf(wp->w_buffer, pos->lnum, false);
+ colnr_T vcol = 0;
+ char_u *line = ptr = ml_get_buf(wp->w_buffer, pos->lnum, false); // start of the line
if (pos->col == MAXCOL) {
// continue until the NUL
@@ -949,7 +940,7 @@ void getvcol(win_T *wp, pos_T *pos, colnr_T *start, colnr_T *cursor, colnr_T *en
&& !wp->w_p_bri) {
for (;;) {
head = 0;
- c = *ptr;
+ int c = *ptr;
// make sure we don't go past the end of the line
if (c == NUL) {
@@ -1066,19 +1057,16 @@ colnr_T getvcol_nolist(pos_T *posp)
void getvvcol(win_T *wp, pos_T *pos, colnr_T *start, colnr_T *cursor, colnr_T *end)
{
colnr_T col;
- colnr_T coladd;
- colnr_T endadd;
- char_u *ptr;
if (virtual_active()) {
// For virtual mode, only want one value
getvcol(wp, pos, &col, NULL, NULL);
- coladd = pos->coladd;
- endadd = 0;
+ colnr_T coladd = pos->coladd;
+ colnr_T endadd = 0;
// Cannot put the cursor on part of a wide character.
- ptr = ml_get_buf(wp->w_buffer, pos->lnum, false);
+ char_u *ptr = ml_get_buf(wp->w_buffer, pos->lnum, false);
if (pos->col < (colnr_T)STRLEN(ptr)) {
int c = utf_ptr2char(ptr + pos->col);
@@ -1314,9 +1302,9 @@ char_u *skiptowhite_esc(char_u *p)
{
while (*p != ' ' && *p != '\t' && *p != NUL) {
if (((*p == '\\') || (*p == Ctrl_V)) && (*(p + 1) != NUL)) {
- ++p;
+ p++;
}
- ++p;
+ p++;
}
return p;
}
@@ -1686,7 +1674,7 @@ bool rem_backslash(const char_u *str)
/// @param p
void backslash_halve(char_u *p)
{
- for (; *p; ++p) {
+ for (; *p; p++) {
if (rem_backslash(p)) {
STRMOVE(p, p + 1);
}
diff --git a/src/nvim/cursor.c b/src/nvim/cursor.c
index 55f55a46b2..d924119fdf 100644
--- a/src/nvim/cursor.c
+++ b/src/nvim/cursor.c
@@ -25,9 +25,7 @@
# include "cursor.c.generated.h"
#endif
-/*
- * Get the screen position of the cursor.
- */
+/// @return the screen position of the cursor.
int getviscol(void)
{
colnr_T x;
@@ -36,9 +34,7 @@ int getviscol(void)
return (int)x;
}
-/*
- * Get the screen position of character col with a coladd in the cursor line.
- */
+/// @return the screen position of character col with a coladd in the cursor line.
int getviscol2(colnr_T col, colnr_T coladd)
{
colnr_T x;
@@ -51,11 +47,9 @@ int getviscol2(colnr_T col, colnr_T coladd)
return (int)x;
}
-/*
- * Go to column "wcol", and add/insert white space as necessary to get the
- * cursor in that column.
- * The caller must have saved the cursor line for undo!
- */
+/// Go to column "wcol", and add/insert white space as necessary to get the
+/// cursor in that column.
+/// The caller must have saved the cursor line for undo!
int coladvance_force(colnr_T wcol)
{
int rc = coladvance2(&curwin->w_cursor, true, false, wcol);
@@ -70,15 +64,13 @@ int coladvance_force(colnr_T wcol)
return rc;
}
-/*
- * Try to advance the Cursor to the specified screen column.
- * If virtual editing: fine tune the cursor position.
- * Note that all virtual positions off the end of a line should share
- * a curwin->w_cursor.col value (n.b. this is equal to STRLEN(line)),
- * beginning at coladd 0.
- *
- * return OK if desired column is reached, FAIL if not
- */
+/// Try to advance the Cursor to the specified screen column.
+/// If virtual editing: fine tune the cursor position.
+/// Note that all virtual positions off the end of a line should share
+/// a curwin->w_cursor.col value (n.b. this is equal to STRLEN(line)),
+/// beginning at coladd 0.
+///
+/// @return OK if desired column is reached, FAIL if not
int coladvance(colnr_T wcol)
{
int rc = getvpos(&curwin->w_cursor, wcol);
@@ -100,19 +92,16 @@ static int coladvance2(pos_T *pos, bool addspaces, bool finetune, colnr_T wcol_a
{
colnr_T wcol = wcol_arg;
int idx;
- char_u *ptr;
- char_u *line;
colnr_T col = 0;
- int csize = 0;
- int one_more;
int head = 0;
- one_more = (State & INSERT)
- || (State & TERM_FOCUS)
- || restart_edit != NUL
- || (VIsual_active && *p_sel != 'o')
- || ((get_ve_flags() & VE_ONEMORE) && wcol < MAXCOL);
- line = ml_get_buf(curbuf, pos->lnum, false);
+ int one_more = (State & INSERT)
+ || (State & TERM_FOCUS)
+ || restart_edit != NUL
+ || (VIsual_active && *p_sel != 'o')
+ || ((get_ve_flags() & VE_ONEMORE) && wcol < MAXCOL);
+
+ char_u *line = ml_get_buf(curbuf, pos->lnum, false);
if (wcol >= MAXCOL) {
idx = (int)STRLEN(line) - 1 + one_more;
@@ -121,11 +110,12 @@ static int coladvance2(pos_T *pos, bool addspaces, bool finetune, colnr_T wcol_a
if ((addspaces || finetune) && !VIsual_active) {
curwin->w_curswant = linetabsize(line) + one_more;
if (curwin->w_curswant > 0) {
- --curwin->w_curswant;
+ curwin->w_curswant--;
}
}
} else {
int width = curwin->w_width_inner - win_col_off(curwin);
+ int csize = 0;
if (finetune
&& curwin->w_p_wrap
@@ -139,15 +129,15 @@ static int coladvance2(pos_T *pos, bool addspaces, bool finetune, colnr_T wcol_a
if (wcol / width > (colnr_T)csize / width
&& ((State & INSERT) == 0 || (int)wcol > csize + 1)) {
- /* In case of line wrapping don't move the cursor beyond the
- * right screen edge. In Insert mode allow going just beyond
- * the last character (like what happens when typing and
- * reaching the right window edge). */
+ // In case of line wrapping don't move the cursor beyond the
+ // right screen edge. In Insert mode allow going just beyond
+ // the last character (like what happens when typing and
+ // reaching the right window edge).
wcol = (csize / width + 1) * width - 1;
}
}
- ptr = line;
+ char_u *ptr = line;
while (col <= wcol && *ptr != NUL) {
// Count a tab for what it's worth (if list mode not on)
csize = win_lbr_chartabsize(curwin, line, ptr, col, &head);
@@ -155,12 +145,10 @@ static int coladvance2(pos_T *pos, bool addspaces, bool finetune, colnr_T wcol_a
col += csize;
}
idx = (int)(ptr - line);
- /*
- * Handle all the special cases. The virtual_active() check
- * is needed to ensure that a virtual position off the end of
- * a line has the correct indexing. The one_more comparison
- * replaces an explicit add of one_more later on.
- */
+ // Handle all the special cases. The virtual_active() check
+ // is needed to ensure that a virtual position off the end of
+ // a line has the correct indexing. The one_more comparison
+ // replaces an explicit add of one_more later on.
if (col > wcol || (!virtual_active() && one_more == 0)) {
idx -= 1;
// Don't count the chars from 'showbreak'.
@@ -172,8 +160,7 @@ static int coladvance2(pos_T *pos, bool addspaces, bool finetune, colnr_T wcol_a
&& addspaces
&& wcol >= 0
&& ((col != wcol && col != wcol + 1) || csize > 1)) {
- /* 'virtualedit' is set: The difference between wcol and col is
- * filled with spaces. */
+ // 'virtualedit' is set: The difference between wcol and col is filled with spaces.
if (line[idx] == NUL) {
// Append spaces
@@ -256,29 +243,23 @@ static int coladvance2(pos_T *pos, bool addspaces, bool finetune, colnr_T wcol_a
return OK;
}
-/*
- * Return in "pos" the position of the cursor advanced to screen column "wcol".
- * return OK if desired column is reached, FAIL if not
- */
+/// Return in "pos" the position of the cursor advanced to screen column "wcol".
+///
+/// @return OK if desired column is reached, FAIL if not
int getvpos(pos_T *pos, colnr_T wcol)
{
return coladvance2(pos, false, virtual_active(), wcol);
}
-/*
- * Increment the cursor position. See inc() for return values.
- */
+/// Increment the cursor position. See inc() for return values.
int inc_cursor(void)
{
return inc(&curwin->w_cursor);
}
-/*
- * dec(p)
- *
- * Decrement the line pointer 'p' crossing line boundaries as necessary.
- * Return 1 when crossing a line, -1 when at start of file, 0 otherwise.
- */
+/// Decrement the line pointer 'p' crossing line boundaries as necessary.
+///
+/// @return 1 when crossing a line, -1 when at start of file, 0 otherwise.
int dec_cursor(void)
{
return dec(&curwin->w_cursor);
@@ -314,34 +295,29 @@ linenr_T get_cursor_rel_lnum(win_T *wp, linenr_T lnum)
return (lnum < cursor) ? -retval : retval;
}
-// Make sure "pos.lnum" and "pos.col" are valid in "buf".
-// This allows for the col to be on the NUL byte.
+/// Make sure "pos.lnum" and "pos.col" are valid in "buf".
+/// This allows for the col to be on the NUL byte.
void check_pos(buf_T *buf, pos_T *pos)
{
- char_u *line;
- colnr_T len;
-
if (pos->lnum > buf->b_ml.ml_line_count) {
pos->lnum = buf->b_ml.ml_line_count;
}
if (pos->col > 0) {
- line = ml_get_buf(buf, pos->lnum, false);
- len = (colnr_T)STRLEN(line);
+ char_u *line = ml_get_buf(buf, pos->lnum, false);
+ colnr_T len = (colnr_T)STRLEN(line);
if (pos->col > len) {
pos->col = len;
}
}
}
-/*
- * Make sure curwin->w_cursor.lnum is valid.
- */
+/// Make sure curwin->w_cursor.lnum is valid.
void check_cursor_lnum(void)
{
if (curwin->w_cursor.lnum > curbuf->b_ml.ml_line_count) {
- /* If there is a closed fold at the end of the file, put the cursor in
- * its first line. Otherwise in the last line. */
+ // If there is a closed fold at the end of the file, put the cursor in
+ // its first line. Otherwise in the last line.
if (!hasFolding(curbuf->b_ml.ml_line_count,
&curwin->w_cursor.lnum, NULL)) {
curwin->w_cursor.lnum = curbuf->b_ml.ml_line_count;
@@ -352,9 +328,7 @@ void check_cursor_lnum(void)
}
}
-/*
- * Make sure curwin->w_cursor.col is valid.
- */
+/// Make sure curwin->w_cursor.col is valid.
void check_cursor_col(void)
{
check_cursor_col_win(curwin);
@@ -364,19 +338,18 @@ void check_cursor_col(void)
/// @see mb_check_adjust_col
void check_cursor_col_win(win_T *win)
{
- colnr_T len;
colnr_T oldcol = win->w_cursor.col;
colnr_T oldcoladd = win->w_cursor.col + win->w_cursor.coladd;
unsigned int cur_ve_flags = get_ve_flags();
- len = (colnr_T)STRLEN(ml_get_buf(win->w_buffer, win->w_cursor.lnum, false));
+ colnr_T len = (colnr_T)STRLEN(ml_get_buf(win->w_buffer, win->w_cursor.lnum, false));
if (len == 0) {
win->w_cursor.col = 0;
} else if (win->w_cursor.col >= len) {
- /* Allow cursor past end-of-line when:
- * - in Insert mode or restarting Insert mode
- * - in Visual mode and 'selection' isn't "old"
- * - 'virtualedit' is set */
+ // Allow cursor past end-of-line when:
+ // - in Insert mode or restarting Insert mode
+ // - in Visual mode and 'selection' isn't "old"
+ // - 'virtualedit' is set */
if ((State & INSERT) || restart_edit
|| (VIsual_active && *p_sel != 'o')
|| (cur_ve_flags & VE_ONEMORE)
@@ -419,32 +392,27 @@ void check_cursor_col_win(win_T *win)
}
}
-/*
- * make sure curwin->w_cursor in on a valid character
- */
+/// Make sure curwin->w_cursor in on a valid character
void check_cursor(void)
{
check_cursor_lnum();
check_cursor_col();
}
-/*
- * Make sure curwin->w_cursor is not on the NUL at the end of the line.
- * Allow it when in Visual mode and 'selection' is not "old".
- */
+/// Make sure curwin->w_cursor is not on the NUL at the end of the line.
+/// Allow it when in Visual mode and 'selection' is not "old".
void adjust_cursor_col(void)
{
if (curwin->w_cursor.col > 0
&& (!VIsual_active || *p_sel == 'o')
&& gchar_cursor() == NUL) {
- --curwin->w_cursor.col;
+ curwin->w_cursor.col--;
}
}
-/*
- * When curwin->w_leftcol has changed, adjust the cursor position.
- * Return true if the cursor was moved.
- */
+/// When curwin->w_leftcol has changed, adjust the cursor position.
+///
+/// @return true if the cursor was moved.
bool leftcol_changed(void)
{
// TODO(hinidu): I think it should be colnr_T or int, but p_siso is long.
@@ -457,10 +425,8 @@ bool leftcol_changed(void)
lastcol = curwin->w_leftcol + curwin->w_width_inner - curwin_col_off() - 1;
validate_virtcol();
- /*
- * If the cursor is right or left of the screen, move it to last or first
- * character.
- */
+ // If the cursor is right or left of the screen, move it to last or first
+ // character.
if (curwin->w_virtcol > (colnr_T)(lastcol - p_siso)) {
retval = true;
coladvance((colnr_T)(lastcol - p_siso));
@@ -469,11 +435,9 @@ bool leftcol_changed(void)
coladvance((colnr_T)(curwin->w_leftcol + p_siso));
}
- /*
- * If the start of the character under the cursor is not on the screen,
- * advance the cursor one more char. If this fails (last char of the
- * line) adjust the scrolling.
- */
+ // If the start of the character under the cursor is not on the screen,
+ // advance the cursor one more char. If this fails (last char of the
+ // line) adjust the scrolling.
getvvcol(curwin, &curwin->w_cursor, &s, NULL, &e);
if (e > (colnr_T)lastcol) {
retval = true;
@@ -498,27 +462,21 @@ int gchar_cursor(void)
return utf_ptr2char(get_cursor_pos_ptr());
}
-/*
- * Write a character at the current cursor position.
- * It is directly written into the block.
- */
+/// Write a character at the current cursor position.
+/// It is directly written into the block.
void pchar_cursor(char_u c)
{
*(ml_get_buf(curbuf, curwin->w_cursor.lnum, true)
+ curwin->w_cursor.col) = c;
}
-/*
- * Return pointer to cursor line.
- */
+/// @return pointer to cursor line.
char_u *get_cursor_line_ptr(void)
{
return ml_get_buf(curbuf, curwin->w_cursor.lnum, false);
}
-/*
- * Return pointer to cursor position.
- */
+/// @return pointer to cursor position.
char_u *get_cursor_pos_ptr(void)
{
return ml_get_buf(curbuf, curwin->w_cursor.lnum, false) +
diff --git a/src/nvim/cursor_shape.c b/src/nvim/cursor_shape.c
index 6b0a5dfe12..0e4a4bcfb0 100644
--- a/src/nvim/cursor_shape.c
+++ b/src/nvim/cursor_shape.c
@@ -9,8 +9,8 @@
#include "nvim/charset.h"
#include "nvim/cursor_shape.h"
#include "nvim/ex_getln.h"
+#include "nvim/highlight_group.h"
#include "nvim/strings.h"
-#include "nvim/syntax.h"
#include "nvim/ui.h"
#include "nvim/vim.h"
@@ -74,8 +74,7 @@ Array mode_style_array(void)
PUT(dic, "hl_id", INTEGER_OBJ(cur->id));
PUT(dic, "id_lm", INTEGER_OBJ(cur->id_lm));
PUT(dic, "attr_id", INTEGER_OBJ(cur->id ? syn_id2attr(cur->id) : 0));
- PUT(dic, "attr_id_lm", INTEGER_OBJ(cur->id_lm ? syn_id2attr(cur->id_lm)
- : 0));
+ PUT(dic, "attr_id_lm", INTEGER_OBJ(cur->id_lm ? syn_id2attr(cur->id_lm) : 0));
}
PUT(dic, "name", STRING_OBJ(cstr_to_string(cur->full_name)));
PUT(dic, "short_name", STRING_OBJ(cstr_to_string(cur->name)));
@@ -95,7 +94,6 @@ Array mode_style_array(void)
/// @returns error message for an illegal option, NULL otherwise.
char *parse_shape_opt(int what)
{
- char_u *modep;
char_u *colonp;
char_u *commap;
char_u *slashp;
@@ -120,7 +118,7 @@ char *parse_shape_opt(int what)
}
}
// Repeat for all comma separated parts.
- modep = p_guicursor;
+ char_u *modep = p_guicursor;
while (modep != NULL && *modep != NUL) {
colonp = vim_strchr(modep, ':');
commap = vim_strchr(modep, ',');
@@ -147,7 +145,7 @@ char *parse_shape_opt(int what)
if (len == 1 && TOLOWER_ASC(modep[0]) == 'a') {
all_idx = SHAPE_IDX_COUNT - 1;
} else {
- for (idx = 0; idx < SHAPE_IDX_COUNT; ++idx) {
+ for (idx = 0; idx < SHAPE_IDX_COUNT; idx++) {
if (STRNICMP(modep, shape_table[idx].name, len) == 0) {
break;
}
@@ -170,9 +168,7 @@ char *parse_shape_opt(int what)
// Parse the part after the colon
for (p = colonp + 1; *p && *p != ',';) {
{
- /*
- * First handle the ones with a number argument.
- */
+ // First handle the ones with a number argument.
i = *p;
len = 0;
if (STRNICMP(p, "ver", 3) == 0) {
@@ -230,11 +226,11 @@ char *parse_shape_opt(int what)
slashp = vim_strchr(p, '/');
if (slashp != NULL && slashp < endp) {
// "group/langmap_group"
- i = syn_check_group((char *)p, (int)(slashp - p));
+ i = syn_check_group((char *)p, (size_t)(slashp - p));
p = slashp + 1;
}
if (round == 2) {
- shape_table[idx].id = syn_check_group((char *)p, (int)(endp - p));
+ shape_table[idx].id = syn_check_group((char *)p, (size_t)(endp - p));
shape_table[idx].id_lm = shape_table[idx].id;
if (slashp != NULL && slashp < endp) {
shape_table[idx].id = i;
@@ -245,7 +241,7 @@ char *parse_shape_opt(int what)
} // if (what != SHAPE_MOUSE)
if (*p == '-') {
- ++p;
+ p++;
}
}
}
diff --git a/src/nvim/debugger.c b/src/nvim/debugger.c
index b48a3155b6..cd823546b4 100644
--- a/src/nvim/debugger.c
+++ b/src/nvim/debugger.c
@@ -58,7 +58,6 @@ void do_debug(char_u *cmd)
tasave_T typeaheadbuf;
bool typeahead_saved = false;
int save_ignore_script = 0;
- int save_ex_normal_busy;
int n;
char_u *cmdline = NULL;
char_u *p;
@@ -117,7 +116,7 @@ void do_debug(char_u *cmd)
// with the commands being executed. Reset "ex_normal_busy" to avoid
// the side effects of using ":normal". Save the stuff buffer and make
// it empty. Set ignore_script to avoid reading from script input.
- save_ex_normal_busy = ex_normal_busy;
+ int save_ex_normal_busy = ex_normal_busy;
ex_normal_busy = 0;
if (!debug_greedy) {
save_typeahead(&typeaheadbuf);
@@ -390,11 +389,10 @@ static char_u *debug_skipped_name;
/// Called from do_one_cmd() before executing a command.
void dbg_check_breakpoint(exarg_T *eap)
{
- char *p;
-
debug_skipped = false;
if (debug_breakpoint_name != NULL) {
if (!eap->skip) {
+ char *p;
// replace K_SNR with "<SNR>"
if (debug_breakpoint_name[0] == K_SPECIAL
&& debug_breakpoint_name[1] == KS_EXTRA
@@ -430,12 +428,10 @@ void dbg_check_breakpoint(exarg_T *eap)
/// @return true when the debug mode is entered this time.
bool dbg_check_skipped(exarg_T *eap)
{
- int prev_got_int;
-
if (debug_skipped) {
// Save the value of got_int and reset it. We don't want a previous
// interruption cause flushing the input buffer.
- prev_got_int = got_int;
+ int prev_got_int = got_int;
got_int = false;
debug_breakpoint_name = debug_skipped_name;
// eap->skip is true
@@ -482,12 +478,11 @@ static int dbg_parsearg(char_u *arg, garray_T *gap)
{
char_u *p = arg;
char_u *q;
- struct debuggy *bp;
bool here = false;
ga_grow(gap, 1);
- bp = &DEBUGGY(gap, gap->ga_len);
+ struct debuggy *bp = &DEBUGGY(gap, gap->ga_len);
// Find "func" or "file".
if (STRNCMP(p, "func", 4) == 0) {
@@ -564,16 +559,13 @@ static int dbg_parsearg(char_u *arg, garray_T *gap)
/// ":breakadd". Also used for ":profile".
void ex_breakadd(exarg_T *eap)
{
- struct debuggy *bp;
- garray_T *gap;
-
- gap = &dbg_breakp;
+ garray_T *gap = &dbg_breakp;
if (eap->cmdidx == CMD_profile) {
gap = &prof_ga;
}
if (dbg_parsearg(eap->arg, gap) == OK) {
- bp = &DEBUGGY(gap, gap->ga_len);
+ struct debuggy *bp = &DEBUGGY(gap, gap->ga_len);
bp->dbg_forceit = eap->forceit;
if (bp->dbg_type != DBG_EXPR) {
@@ -616,20 +608,18 @@ void ex_debuggreedy(exarg_T *eap)
void ex_breakdel(exarg_T *eap)
{
struct debuggy *bp, *bpi;
- int nr;
int todel = -1;
bool del_all = false;
linenr_T best_lnum = 0;
- garray_T *gap;
+ garray_T *gap = &dbg_breakp;
- gap = &dbg_breakp;
if (eap->cmdidx == CMD_profdel) {
gap = &prof_ga;
}
if (ascii_isdigit(*eap->arg)) {
// ":breakdel {nr}"
- nr = atoi((char *)eap->arg);
+ int nr = atoi((char *)eap->arg);
for (int i = 0; i < gap->ga_len; i++) {
if (DEBUGGY(gap, i).dbg_nr == nr) {
todel = i;
@@ -693,13 +683,11 @@ void ex_breakdel(exarg_T *eap)
/// ":breaklist".
void ex_breaklist(exarg_T *eap)
{
- struct debuggy *bp;
-
if (GA_EMPTY(&dbg_breakp)) {
msg(_("No breakpoints defined"));
} else {
for (int i = 0; i < dbg_breakp.ga_len; i++) {
- bp = &BREAKP(i);
+ struct debuggy *bp = &BREAKP(i);
if (bp->dbg_type == DBG_FILE) {
home_replace(NULL, bp->dbg_name, NameBuff, MAXPATHL, true);
}
diff --git a/src/nvim/decoration.c b/src/nvim/decoration.c
index 94bf1feeee..fb709d12ff 100644
--- a/src/nvim/decoration.c
+++ b/src/nvim/decoration.c
@@ -5,10 +5,10 @@
#include "nvim/decoration.h"
#include "nvim/extmark.h"
#include "nvim/highlight.h"
+#include "nvim/highlight_group.h"
#include "nvim/lua/executor.h"
#include "nvim/move.h"
#include "nvim/screen.h"
-#include "nvim/syntax.h"
#include "nvim/vim.h"
#ifdef INCLUDE_GENERATED_DECLARATIONS
diff --git a/src/nvim/diff.c b/src/nvim/diff.c
index 80bd3229c6..1b8a9f41e9 100644
--- a/src/nvim/diff.c
+++ b/src/nvim/diff.c
@@ -166,8 +166,7 @@ void diff_buf_add(buf_T *buf)
return;
}
- int i;
- for (i = 0; i < DB_COUNT; ++i) {
+ for (int i = 0; i < DB_COUNT; i++) {
if (curtab->tp_diffbuf[i] == NULL) {
curtab->tp_diffbuf[i] = buf;
curtab->tp_diff_invalid = true;
@@ -201,7 +200,7 @@ static void diff_buf_clear(void)
static int diff_buf_idx(buf_T *buf)
{
int idx;
- for (idx = 0; idx < DB_COUNT; ++idx) {
+ for (idx = 0; idx < DB_COUNT; idx++) {
if (curtab->tp_diffbuf[idx] == buf) {
break;
}
@@ -218,7 +217,7 @@ static int diff_buf_idx(buf_T *buf)
static int diff_buf_idx_tp(buf_T *buf, tabpage_T *tp)
{
int idx;
- for (idx = 0; idx < DB_COUNT; ++idx) {
+ for (idx = 0; idx < DB_COUNT; idx++) {
if (tp->tp_diffbuf[idx] == buf) {
break;
}
@@ -304,7 +303,6 @@ static void diff_mark_adjust_tp(tabpage_T *tp, int idx, linenr_T line1, linenr_T
diff_T *dprev = NULL;
diff_T *dp = tp->tp_first_diff;
- linenr_T last;
linenr_T lnum_deleted = line1; // lnum of remaining deletion
int n;
int off;
@@ -323,7 +321,7 @@ static void diff_mark_adjust_tp(tabpage_T *tp, int idx, linenr_T line1, linenr_T
dnext->df_lnum[idx] = line1;
dnext->df_count[idx] = inserted;
int i;
- for (i = 0; i < DB_COUNT; ++i) {
+ for (i = 0; i < DB_COUNT; i++) {
if ((tp->tp_diffbuf[i] != NULL) && (i != idx)) {
if (dprev == NULL) {
dnext->df_lnum[i] = line1;
@@ -354,7 +352,7 @@ static void diff_mark_adjust_tp(tabpage_T *tp, int idx, linenr_T line1, linenr_T
// 3 5 6
// compute last line of this change
- last = dp->df_lnum[idx] + dp->df_count[idx] - 1;
+ linenr_T last = dp->df_lnum[idx] + dp->df_count[idx] - 1;
// 1. change completely above line1: nothing to do
if (last >= line1 - 1) {
@@ -421,7 +419,7 @@ static void diff_mark_adjust_tp(tabpage_T *tp, int idx, linenr_T line1, linenr_T
}
int i;
- for (i = 0; i < DB_COUNT; ++i) {
+ for (i = 0; i < DB_COUNT; i++) {
if ((tp->tp_diffbuf[i] != NULL) && (i != idx)) {
dp->df_lnum[i] -= off;
dp->df_count[i] += n;
@@ -442,7 +440,7 @@ static void diff_mark_adjust_tp(tabpage_T *tp, int idx, linenr_T line1, linenr_T
// Check if inserted lines are equal, may reduce the size of the
// diff.
//
- // TODO: also check for equal lines in the middle and perhaps split
+ // TODO(unknown): also check for equal lines in the middle and perhaps split
// the block.
diff_check_unchanged(tp, dp);
}
@@ -453,7 +451,7 @@ static void diff_mark_adjust_tp(tabpage_T *tp, int idx, linenr_T line1, linenr_T
if ((dprev != NULL)
&& (dprev->df_lnum[idx] + dprev->df_count[idx] == dp->df_lnum[idx])) {
int i;
- for (i = 0; i < DB_COUNT; ++i) {
+ for (i = 0; i < DB_COUNT; i++) {
if (tp->tp_diffbuf[i] != NULL) {
dprev->df_count[i] += dp->df_count[i];
}
@@ -474,7 +472,7 @@ static void diff_mark_adjust_tp(tabpage_T *tp, int idx, linenr_T line1, linenr_T
while (dp != NULL) {
// All counts are zero, remove this entry.
int i;
- for (i = 0; i < DB_COUNT; ++i) {
+ for (i = 0; i < DB_COUNT; i++) {
if ((tp->tp_diffbuf[i] != NULL) && (dp->df_count[i] != 0)) {
break;
}
@@ -542,7 +540,7 @@ static void diff_check_unchanged(tabpage_T *tp, diff_T *dp)
// Find the first buffers, use it as the original, compare the other
// buffer lines against this one.
int i_org;
- for (i_org = 0; i_org < DB_COUNT; ++i_org) {
+ for (i_org = 0; i_org < DB_COUNT; i_org++) {
if (tp->tp_diffbuf[i_org] != NULL) {
break;
}
@@ -574,7 +572,7 @@ static void diff_check_unchanged(tabpage_T *tp, diff_T *dp)
false));
int i_new;
- for (i_new = i_org + 1; i_new < DB_COUNT; ++i_new) {
+ for (i_new = i_org + 1; i_new < DB_COUNT; i_new++) {
if (tp->tp_diffbuf[i_new] == NULL) {
continue;
}
@@ -602,7 +600,7 @@ static void diff_check_unchanged(tabpage_T *tp, diff_T *dp)
}
// Line matched in all buffers, remove it from the diff.
- for (i_new = i_org; i_new < DB_COUNT; ++i_new) {
+ for (i_new = i_org; i_new < DB_COUNT; i_new++) {
if (tp->tp_diffbuf[i_new] != NULL) {
if (dir == FORWARD) {
dp->df_lnum[i_new]++;
@@ -628,8 +626,7 @@ static void diff_check_unchanged(tabpage_T *tp, diff_T *dp)
/// @return OK if the diff block doesn't contain invalid line numbers.
static int diff_check_sanity(tabpage_T *tp, diff_T *dp)
{
- int i;
- for (i = 0; i < DB_COUNT; ++i) {
+ for (int i = 0; i < DB_COUNT; i++) {
if (tp->tp_diffbuf[i] != NULL) {
if (dp->df_lnum[i] + dp->df_count[i] - 1
> tp->tp_diffbuf[i]->b_ml.ml_line_count) {
@@ -719,16 +716,13 @@ static void clear_diffout(diffout_T *dout)
/// @return FAIL for failure.
static int diff_write_buffer(buf_T *buf, diffin_T *din)
{
- linenr_T lnum;
- char_u *s;
long len = 0;
- char_u *ptr;
// xdiff requires one big block of memory with all the text.
- for (lnum = 1; lnum <= buf->b_ml.ml_line_count; lnum++) {
+ for (linenr_T lnum = 1; lnum <= buf->b_ml.ml_line_count; lnum++) {
len += (long)STRLEN(ml_get_buf(buf, lnum, false)) + 1;
}
- ptr = try_malloc(len);
+ char_u *ptr = try_malloc(len);
if (ptr == NULL) {
// Allocating memory failed. This can happen, because we try to read
// the whole buffer text into memory. Set the failed flag, the diff
@@ -746,8 +740,8 @@ static int diff_write_buffer(buf_T *buf, diffin_T *din)
din->din_mmfile.size = len;
len = 0;
- for (lnum = 1; lnum <= buf->b_ml.ml_line_count; lnum++) {
- for (s = ml_get_buf(buf, lnum, false); *s != NUL;) {
+ for (linenr_T lnum = 1; lnum <= buf->b_ml.ml_line_count; lnum++) {
+ for (char_u *s = ml_get_buf(buf, lnum, false); *s != NUL;) {
if (diff_flags & DIFF_ICASE) {
char_u cbuf[MB_MAXBYTES + 1];
@@ -811,9 +805,6 @@ static int diff_write(buf_T *buf, diffin_T *din)
/// @param eap can be NULL
static void diff_try_update(diffio_T *dio, int idx_orig, exarg_T *eap)
{
- buf_T *buf;
- int idx_new;
-
if (dio->dio_internal) {
ga_init(&dio->dio_diff.dout_ga, sizeof(char *), 1000);
} else {
@@ -833,9 +824,11 @@ static void diff_try_update(diffio_T *dio, int idx_orig, exarg_T *eap)
goto theend;
}
+ buf_T *buf;
+
// :diffupdate!
if (eap != NULL && eap->forceit) {
- for (idx_new = idx_orig; idx_new < DB_COUNT; idx_new++) {
+ for (int idx_new = idx_orig; idx_new < DB_COUNT; idx_new++) {
buf = curtab->tp_diffbuf[idx_new];
if (buf_valid(buf)) {
buf_check_timestamp(buf);
@@ -850,7 +843,7 @@ static void diff_try_update(diffio_T *dio, int idx_orig, exarg_T *eap)
}
// Make a difference between the first buffer and every other.
- for (idx_new = idx_orig + 1; idx_new < DB_COUNT; idx_new++) {
+ for (int idx_new = idx_orig + 1; idx_new < DB_COUNT; idx_new++) {
buf = curtab->tp_diffbuf[idx_new];
if (buf == NULL || buf->b_ml.ml_mfp == NULL) {
continue; // skip buffer that isn't loaded
@@ -893,10 +886,8 @@ int diff_internal(void)
///
static int diff_internal_failed(void)
{
- int idx;
-
// Only need to do something when there is another buffer.
- for (idx = 0; idx < DB_COUNT; idx++) {
+ for (int idx = 0; idx < DB_COUNT; idx++) {
if (curtab->tp_diffbuf[idx] != NULL
&& curtab->tp_diffbuf[idx]->b_diff_failed) {
return true;
@@ -927,7 +918,7 @@ void ex_diffupdate(exarg_T *eap)
// Use the first buffer as the original text.
int idx_orig;
- for (idx_orig = 0; idx_orig < DB_COUNT; ++idx_orig) {
+ for (idx_orig = 0; idx_orig < DB_COUNT; idx_orig++) {
if (curtab->tp_diffbuf[idx_orig] != NULL) {
break;
}
@@ -939,7 +930,7 @@ void ex_diffupdate(exarg_T *eap)
// Only need to do something when there is another buffer.
int idx_new;
- for (idx_new = idx_orig + 1; idx_new < DB_COUNT; ++idx_new) {
+ for (idx_new = idx_orig + 1; idx_new < DB_COUNT; idx_new++) {
if (curtab->tp_diffbuf[idx_new] != NULL) {
break;
}
@@ -1659,7 +1650,7 @@ static void diff_read(int idx_orig, int idx_new, diffio_T *dio)
off = dp->df_lnum[idx_orig] - hunk->lnum_orig;
if (off > 0) {
- for (i = idx_orig; i < idx_new; ++i) {
+ for (i = idx_orig; i < idx_new; i++) {
if (curtab->tp_diffbuf[i] != NULL) {
dp->df_lnum[i] -= off;
}
@@ -1693,7 +1684,7 @@ static void diff_read(int idx_orig, int idx_new, diffio_T *dio)
off = 0;
}
- for (i = idx_orig; i < idx_new; ++i) {
+ for (i = idx_orig; i < idx_new; i++) {
if (curtab->tp_diffbuf[i] != NULL) {
dp->df_count[i] = dpl->df_lnum[i] + dpl->df_count[i]
- dp->df_lnum[i] + off;
@@ -1721,7 +1712,7 @@ static void diff_read(int idx_orig, int idx_new, diffio_T *dio)
// Set values for other buffers, these must be equal to the
// original buffer, otherwise there would have been a change
// already.
- for (i = idx_orig + 1; i < idx_new; ++i) {
+ for (i = idx_orig + 1; i < idx_new; i++) {
if (curtab->tp_diffbuf[i] != NULL) {
diff_copy_entry(dprev, dp, idx_orig, i);
}
@@ -1775,9 +1766,8 @@ static void diff_copy_entry(diff_T *dprev, diff_T *dp, int idx_orig, int idx_new
void diff_clear(tabpage_T *tp)
FUNC_ATTR_NONNULL_ALL
{
- diff_T *p;
diff_T *next_p;
- for (p = tp->tp_first_diff; p != NULL; p = next_p) {
+ for (diff_T *p = tp->tp_first_diff; p != NULL; p = next_p) {
next_p = p->df_next;
xfree(p);
}
@@ -1799,12 +1789,8 @@ void diff_clear(tabpage_T *tp)
/// @return diff status.
int diff_check(win_T *wp, linenr_T lnum)
{
- int idx; // index in tp_diffbuf[] for this buffer
diff_T *dp;
- int maxcount;
- int i;
buf_T *buf = wp->w_buffer;
- int cmp;
if (curtab->tp_diff_invalid) {
// update after a big change
@@ -1821,7 +1807,7 @@ int diff_check(win_T *wp, linenr_T lnum)
return 0;
}
- idx = diff_buf_idx(buf);
+ int idx = diff_buf_idx(buf); // index in tp_diffbuf[] for this buffer
if (idx == DB_COUNT) {
// no diffs for buffer "buf"
@@ -1850,9 +1836,9 @@ int diff_check(win_T *wp, linenr_T lnum)
// Changed or inserted line. If the other buffers have a count of
// zero, the lines were inserted. If the other buffers have the same
// count, check if the lines are identical.
- cmp = false;
+ int cmp = false;
- for (i = 0; i < DB_COUNT; ++i) {
+ for (int i = 0; i < DB_COUNT; i++) {
if ((i != idx) && (curtab->tp_diffbuf[i] != NULL)) {
if (dp->df_count[i] == 0) {
zero = true;
@@ -1869,7 +1855,7 @@ int diff_check(win_T *wp, linenr_T lnum)
if (cmp) {
// Compare all lines. If they are equal the lines were inserted
// in some buffers, deleted in others, but not changed.
- for (i = 0; i < DB_COUNT; ++i) {
+ for (int i = 0; i < DB_COUNT; i++) {
if ((i != idx)
&& (curtab->tp_diffbuf[i] != NULL)
&& (dp->df_count[i] != 0)) {
@@ -1898,8 +1884,8 @@ int diff_check(win_T *wp, linenr_T lnum)
// Insert filler lines above the line just below the change. Will return
// 0 when this buf had the max count.
- maxcount = 0;
- for (i = 0; i < DB_COUNT; ++i) {
+ int maxcount = 0;
+ for (int i = 0; i < DB_COUNT; i++) {
if ((curtab->tp_diffbuf[i] != NULL) && (dp->df_count[i] > maxcount)) {
maxcount = dp->df_count[i];
}
@@ -2030,8 +2016,6 @@ void diff_set_topline(win_T *fromwin, win_T *towin)
buf_T *frombuf = fromwin->w_buffer;
linenr_T lnum = fromwin->w_topline;
diff_T *dp;
- int max_count;
- int i;
int fromidx = diff_buf_idx(frombuf);
if (fromidx == DB_COUNT) {
@@ -2071,9 +2055,9 @@ void diff_set_topline(win_T *fromwin, win_T *towin)
if (lnum >= dp->df_lnum[fromidx]) {
// Inside a change: compute filler lines. With three or more
// buffers we need to know the largest count.
- max_count = 0;
+ int max_count = 0;
- for (i = 0; i < DB_COUNT; ++i) {
+ for (int i = 0; i < DB_COUNT; i++) {
if ((curtab->tp_diffbuf[i] != NULL) && (max_count < dp->df_count[i])) {
max_count = dp->df_count[i];
}
@@ -2219,7 +2203,7 @@ int diffopt_changed(void)
}
if (*p == ',') {
- ++p;
+ p++;
}
}
@@ -2322,7 +2306,7 @@ bool diff_find_change(win_T *wp, linenr_T lnum, int *startp, int *endp)
int off = lnum - dp->df_lnum[idx];
int i;
- for (i = 0; i < DB_COUNT; ++i) {
+ for (i = 0; i < DB_COUNT; i++) {
if ((curtab->tp_diffbuf[i] != NULL) && (i != idx)) {
// Skip lines that are not in the other change (filler lines).
if (off >= dp->df_count[i]) {
@@ -2421,7 +2405,6 @@ bool diff_infold(win_T *wp, linenr_T lnum)
FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ARG(1)
{
bool other = false;
- diff_T *dp;
// Return if 'diff' isn't set.
if (!wp->w_p_diff) {
@@ -2430,7 +2413,7 @@ bool diff_infold(win_T *wp, linenr_T lnum)
int idx = -1;
int i;
- for (i = 0; i < DB_COUNT; ++i) {
+ for (i = 0; i < DB_COUNT; i++) {
if (curtab->tp_diffbuf[i] == wp->w_buffer) {
idx = i;
} else if (curtab->tp_diffbuf[i] != NULL) {
@@ -2453,7 +2436,7 @@ bool diff_infold(win_T *wp, linenr_T lnum)
return true;
}
- for (dp = curtab->tp_first_diff; dp != NULL; dp = dp->df_next) {
+ for (diff_T *dp = curtab->tp_first_diff; dp != NULL; dp = dp->df_next) {
// If this change is below the line there can't be any further match.
if (dp->df_lnum[idx] - diff_context > lnum) {
break;
@@ -2480,7 +2463,7 @@ void nv_diffgetput(bool put, size_t count)
if (count == 0) {
ea.arg = (char_u *)"";
} else {
- vim_snprintf(buf, 30, "%zu", count);
+ vim_snprintf(buf, sizeof(buf), "%zu", count);
ea.arg = (char_u *)buf;
}
@@ -2505,7 +2488,6 @@ void ex_diffgetput(exarg_T *eap)
int count;
linenr_T off = 0;
diff_T *dp;
- diff_T *dprev;
diff_T *dfree;
int i;
int added;
@@ -2529,7 +2511,7 @@ void ex_diffgetput(exarg_T *eap)
if (*eap->arg == NUL) {
// No argument: Find the other buffer in the list of diff buffers.
- for (idx_other = 0; idx_other < DB_COUNT; ++idx_other) {
+ for (idx_other = 0; idx_other < DB_COUNT; idx_other++) {
if ((curtab->tp_diffbuf[idx_other] != curbuf)
&& (curtab->tp_diffbuf[idx_other] != NULL)) {
if ((eap->cmdidx != CMD_diffput)
@@ -2550,7 +2532,7 @@ void ex_diffgetput(exarg_T *eap)
}
// Check that there isn't a third buffer in the list
- for (i = idx_other + 1; i < DB_COUNT; ++i) {
+ for (i = idx_other + 1; i < DB_COUNT; i++) {
if ((curtab->tp_diffbuf[i] != curbuf)
&& (curtab->tp_diffbuf[i] != NULL)
&& ((eap->cmdidx != CMD_diffput)
@@ -2567,7 +2549,7 @@ void ex_diffgetput(exarg_T *eap)
p--;
}
- for (i = 0; ascii_isdigit(eap->arg[i]) && eap->arg + i < p; ++i) {
+ for (i = 0; ascii_isdigit(eap->arg[i]) && eap->arg + i < p; i++) {
}
if (eap->arg + i == p) {
@@ -2610,9 +2592,9 @@ void ex_diffgetput(exarg_T *eap)
&& (eap->line1 == curbuf->b_ml.ml_line_count)
&& (diff_check(curwin, eap->line1) == 0)
&& ((eap->line1 == 1) || (diff_check(curwin, eap->line1 - 1) == 0))) {
- ++eap->line2;
+ eap->line2++;
} else if (eap->line1 > 0) {
- --eap->line1;
+ eap->line1--;
}
}
@@ -2641,7 +2623,7 @@ void ex_diffgetput(exarg_T *eap)
}
}
- dprev = NULL;
+ diff_T *dprev = NULL;
for (dp = curtab->tp_first_diff; dp != NULL;) {
if (dp->df_lnum[idx_cur] > eap->line2 + off) {
@@ -2703,14 +2685,14 @@ void ex_diffgetput(exarg_T *eap)
buf_empty = buf_is_empty(curbuf);
added = 0;
- for (i = 0; i < count; ++i) {
+ for (i = 0; i < count; i++) {
// remember deleting the last line of the buffer
buf_empty = curbuf->b_ml.ml_line_count == 1;
ml_delete(lnum, false);
added--;
}
- for (i = 0; i < dp->df_count[idx_from] - start_skip - end_skip; ++i) {
+ for (i = 0; i < dp->df_count[idx_from] - start_skip - end_skip; i++) {
linenr_T nr = dp->df_lnum[idx_from] + start_skip + i;
if (nr > curtab->tp_diffbuf[idx_from]->b_ml.ml_line_count) {
break;
@@ -2732,7 +2714,7 @@ void ex_diffgetput(exarg_T *eap)
if ((start_skip == 0) && (end_skip == 0)) {
// Check if there are any other buffers and if the diff is
// equal in them.
- for (i = 0; i < DB_COUNT; ++i) {
+ for (i = 0; i < DB_COUNT; i++) {
if ((curtab->tp_diffbuf[i] != NULL)
&& (i != idx_from)
&& (i != idx_to)
@@ -2835,7 +2817,7 @@ theend:
static void diff_fold_update(diff_T *dp, int skip_idx)
{
FOR_ALL_WINDOWS_IN_TAB(wp, curtab) {
- for (int i = 0; i < DB_COUNT; ++i) {
+ for (int i = 0; i < DB_COUNT; i++) {
if ((curtab->tp_diffbuf[i] == wp->w_buffer) && (i != skip_idx)) {
foldUpdate(wp, dp->df_lnum[i], dp->df_lnum[i] + dp->df_count[i]);
}
@@ -2924,13 +2906,10 @@ int diff_move_to(int dir, long count)
/// "buf1" in diff mode.
static linenr_T diff_get_corresponding_line_int(buf_T *buf1, linenr_T lnum1)
{
- int idx1;
- int idx2;
- diff_T *dp;
int baseline = 0;
- idx1 = diff_buf_idx(buf1);
- idx2 = diff_buf_idx(curbuf);
+ int idx1 = diff_buf_idx(buf1);
+ int idx2 = diff_buf_idx(curbuf);
if ((idx1 == DB_COUNT)
|| (idx2 == DB_COUNT)
@@ -2948,7 +2927,7 @@ static linenr_T diff_get_corresponding_line_int(buf_T *buf1, linenr_T lnum1)
return lnum1;
}
- for (dp = curtab->tp_first_diff; dp != NULL; dp = dp->df_next) {
+ for (diff_T *dp = curtab->tp_first_diff; dp != NULL; dp = dp->df_next) {
if (dp->df_lnum[idx1] > lnum1) {
return lnum1 - baseline;
}
@@ -3004,11 +2983,8 @@ linenr_T diff_get_corresponding_line(buf_T *buf1, linenr_T lnum1)
linenr_T diff_lnum_win(linenr_T lnum, win_T *wp)
{
diff_T *dp;
- int idx;
- int i;
- linenr_T n;
- idx = diff_buf_idx(curbuf);
+ int idx = diff_buf_idx(curbuf);
if (idx == DB_COUNT) {
// safety check
@@ -3034,14 +3010,14 @@ linenr_T diff_lnum_win(linenr_T lnum, win_T *wp)
}
// Find index for "wp".
- i = diff_buf_idx(wp->w_buffer);
+ int i = diff_buf_idx(wp->w_buffer);
if (i == DB_COUNT) {
// safety check
return (linenr_T)0;
}
- n = lnum + (dp->df_lnum[i] - dp->df_lnum[idx]);
+ linenr_T n = lnum + (dp->df_lnum[i] - dp->df_lnum[idx]);
if (n > dp->df_lnum[i] + dp->df_count[i]) {
n = dp->df_lnum[i] + dp->df_count[i];
}
@@ -3054,16 +3030,14 @@ linenr_T diff_lnum_win(linenr_T lnum, win_T *wp)
///
static int parse_diff_ed(char_u *line, diffhunk_T *hunk)
{
- char_u *p;
- long f1, l1, f2, l2;
- int difftype;
+ long l1, l2;
// The line must be one of three formats:
// change: {first}[,{last}]c{first}[,{last}]
// append: {first}a{first}[,{last}]
// delete: {first}[,{last}]d{first}
- p = line;
- f1 = getdigits(&p, true, 0);
+ char_u *p = line;
+ long f1 = getdigits(&p, true, 0);
if (*p == ',') {
p++;
l1 = getdigits(&p, true, 0);
@@ -3073,8 +3047,8 @@ static int parse_diff_ed(char_u *line, diffhunk_T *hunk)
if (*p != 'a' && *p != 'c' && *p != 'd') {
return FAIL; // invalid diff format
}
- difftype = *p++;
- f2 = getdigits(&p, true, 0);
+ int difftype = *p++;
+ long f2 = getdigits(&p, true, 0);
if (*p == ',') {
p++;
l2 = getdigits(&p, true, 0);
@@ -3108,14 +3082,14 @@ static int parse_diff_ed(char_u *line, diffhunk_T *hunk)
///
static int parse_diff_unified(char_u *line, diffhunk_T *hunk)
{
- char_u *p;
- long oldline, oldcount, newline, newcount;
-
// Parse unified diff hunk header:
// @@ -oldline,oldcount +newline,newcount @@
- p = line;
+ char_u *p = line;
if (*p++ == '@' && *p++ == '@' && *p++ == ' ' && *p++ == '-') {
- oldline = getdigits(&p, true, 0);
+ long oldcount;
+ long newline;
+ long newcount;
+ long oldline = getdigits(&p, true, 0);
if (*p == ',') {
p++;
oldcount = getdigits(&p, true, 0);
diff --git a/src/nvim/digraph.c b/src/nvim/digraph.c
index 8eda173cac..6e5389c979 100644
--- a/src/nvim/digraph.c
+++ b/src/nvim/digraph.c
@@ -1506,7 +1506,6 @@ char_u *get_digraph_for_char(int val_arg)
/// @returns composed character, or NUL when ESC was used.
int get_digraph(bool cmdline)
{
- int cc;
no_mapping++;
int c = plain_vgetc();
no_mapping--;
@@ -1526,7 +1525,7 @@ int get_digraph(bool cmdline)
add_to_showcmd(c);
}
no_mapping++;
- cc = plain_vgetc();
+ int cc = plain_vgetc();
no_mapping--;
if (cc != ESC) {
@@ -1555,24 +1554,24 @@ static int getexactdigraph(int char1, int char2, bool meta_char)
// Search user digraphs first.
digr_T *dp = (digr_T *)user_digraphs.ga_data;
- for (int i = 0; i < user_digraphs.ga_len; ++i) {
+ for (int i = 0; i < user_digraphs.ga_len; i++) {
if (((int)dp->char1 == char1) && ((int)dp->char2 == char2)) {
retval = dp->result;
break;
}
- ++dp;
+ dp++;
}
// Search default digraphs.
if (retval == 0) {
dp = digraphdefault;
- for (int i = 0; dp->char1 != 0; ++i) {
+ for (int i = 0; dp->char1 != 0; i++) {
if (((int)dp->char1 == char1) && ((int)dp->char2 == char2)) {
retval = dp->result;
break;
}
- ++dp;
+ dp++;
}
}
@@ -1614,17 +1613,14 @@ int getdigraph(int char1, int char2, bool meta_char)
/// @param str
void putdigraph(char_u *str)
{
- char_u char1, char2;
- digr_T *dp;
-
while (*str != NUL) {
str = skipwhite(str);
if (*str == NUL) {
return;
}
- char1 = *str++;
- char2 = *str++;
+ char_u char1 = *str++;
+ char_u char2 = *str++;
if (char2 == 0) {
emsg(_(e_invarg));
@@ -1644,15 +1640,15 @@ void putdigraph(char_u *str)
int n = getdigits_int(&str, true, 0);
// If the digraph already exists, replace the result.
- dp = (digr_T *)user_digraphs.ga_data;
+ digr_T *dp = (digr_T *)user_digraphs.ga_data;
int i;
- for (i = 0; i < user_digraphs.ga_len; ++i) {
+ for (i = 0; i < user_digraphs.ga_len; i++) {
if (((int)dp->char1 == char1) && ((int)dp->char2 == char2)) {
dp->result = n;
break;
}
- ++dp;
+ dp++;
}
// Add a new digraph to the table.
@@ -1677,14 +1673,13 @@ static void digraph_header(const char *msg)
void listdigraphs(bool use_headers)
{
- digr_T *dp;
result_T previous = 0;
msg_putchar('\n');
- dp = digraphdefault;
+ digr_T *dp = digraphdefault;
- for (int i = 0; dp->char1 != NUL && !got_int; ++i) {
+ for (int i = 0; dp->char1 != NUL && !got_int; i++) {
digr_T tmp;
// May need to convert the result to 'encoding'.
@@ -1749,11 +1744,7 @@ static void printdigraph(const digr_T *dp, result_T *previous)
FUNC_ATTR_NONNULL_ARG(1)
{
char_u buf[30];
- char_u *p;
-
- int list_width;
-
- list_width = 13;
+ int list_width = 13;
if (dp->result != 0) {
if (previous != NULL) {
@@ -1780,7 +1771,7 @@ static void printdigraph(const digr_T *dp, result_T *previous)
}
}
- p = &buf[0];
+ char_u *p = &buf[0];
*p++ = dp->char1;
*p++ = dp->char2;
*p++ = ' ';
@@ -1863,8 +1854,6 @@ char *keymap_init(void)
/// @param eap
void ex_loadkeymap(exarg_T *eap)
{
- char_u *line;
- char_u *p;
char_u *s;
#define KMAP_LLEN 200 // max length of "to" and "from" together
@@ -1887,13 +1876,13 @@ void ex_loadkeymap(exarg_T *eap)
// Get each line of the sourced file, break at the end.
for (;;) {
- line = eap->getline(0, eap->cookie, 0, true);
+ char_u *line = eap->getline(0, eap->cookie, 0, true);
if (line == NULL) {
break;
}
- p = skipwhite(line);
+ char_u *p = skipwhite(line);
if ((*p != '"') && (*p != NUL)) {
kmap_T *kp = GA_APPEND_VIA_PTR(kmap_T, &curbuf->b_kmap_ga);
@@ -1911,7 +1900,7 @@ void ex_loadkeymap(exarg_T *eap)
}
xfree(kp->from);
xfree(kp->to);
- --curbuf->b_kmap_ga.ga_len;
+ curbuf->b_kmap_ga.ga_len--;
}
}
xfree(line);
@@ -1946,7 +1935,6 @@ static void keymap_unload(void)
{
char_u buf[KMAP_MAXLEN + 10];
char_u *save_cpo = p_cpo;
- kmap_T *kp;
if (!(curbuf->b_kmap_state & KEYMAP_LOADED)) {
return;
@@ -1956,7 +1944,7 @@ static void keymap_unload(void)
p_cpo = (char_u *)"C";
// clear the ":lmap"s
- kp = (kmap_T *)curbuf->b_kmap_ga.ga_data;
+ kmap_T *kp = (kmap_T *)curbuf->b_kmap_ga.ga_data;
for (int i = 0; i < curbuf->b_kmap_ga.ga_len; i++) {
vim_snprintf((char *)buf, sizeof(buf), "<buffer> %s", kp[i].from);
diff --git a/src/nvim/edit.c b/src/nvim/edit.c
index 095e082f61..c087948810 100644
--- a/src/nvim/edit.c
+++ b/src/nvim/edit.c
@@ -26,6 +26,7 @@
#include "nvim/fileio.h"
#include "nvim/fold.h"
#include "nvim/getchar.h"
+#include "nvim/highlight_group.h"
#include "nvim/indent.h"
#include "nvim/indent_c.h"
#include "nvim/keymap.h"
@@ -5116,10 +5117,10 @@ static int ins_complete(int c, bool enable_pum)
|| ctrl_x_mode == CTRL_X_PATH_PATTERNS
|| ctrl_x_mode == CTRL_X_PATH_DEFINES) {
if (compl_startpos.lnum != curwin->w_cursor.lnum) {
- /* line (probably) wrapped, set compl_startpos to the
- * first non_blank in the line, if it is not a wordchar
- * include it to get a better pattern, but then we don't
- * want the "\\<" prefix, check it bellow */
+ // line (probably) wrapped, set compl_startpos to the
+ // first non_blank in the line, if it is not a wordchar
+ // include it to get a better pattern, but then we don't
+ // want the "\\<" prefix, check it below.
compl_col = (colnr_T)getwhitecols(line);
compl_startpos.col = compl_col;
compl_startpos.lnum = curwin->w_cursor.lnum;
diff --git a/src/nvim/eval.c b/src/nvim/eval.c
index 83223cdd5c..af7c3d4985 100644
--- a/src/nvim/eval.c
+++ b/src/nvim/eval.c
@@ -33,6 +33,7 @@
#include "nvim/ex_session.h"
#include "nvim/fileio.h"
#include "nvim/getchar.h"
+#include "nvim/highlight_group.h"
#include "nvim/lua/executor.h"
#include "nvim/mark.h"
#include "nvim/memline.h"
@@ -331,7 +332,7 @@ void restore_v_event(dict_T *v_event, save_v_event_T *sve)
}
}
-// Return "n1" divided by "n2", taking care of dividing by zero.
+/// @return "n1" divided by "n2", taking care of dividing by zero.
varnumber_T num_divide(varnumber_T n1, varnumber_T n2)
FUNC_ATTR_CONST FUNC_ATTR_WARN_UNUSED_RESULT
{
@@ -352,7 +353,7 @@ varnumber_T num_divide(varnumber_T n1, varnumber_T n2)
return result;
}
-// Return "n1" modulus "n2", taking care of dividing by zero.
+/// @return "n1" modulus "n2", taking care of dividing by zero.
varnumber_T num_modulus(varnumber_T n1, varnumber_T n2)
FUNC_ATTR_CONST FUNC_ATTR_WARN_UNUSED_RESULT
{
@@ -360,9 +361,7 @@ varnumber_T num_modulus(varnumber_T n1, varnumber_T n2)
return (n2 == 0) ? 0 : (n1 % n2);
}
-/*
- * Initialize the global and v: variables.
- */
+/// Initialize the global and v: variables.
void eval_init(void)
{
vimvars[VV_VERSION].vv_nr = VIM_VERSION_100;
@@ -502,10 +501,8 @@ void eval_clear(void)
#endif
-/*
- * Set an internal variable to a string value. Creates the variable if it does
- * not already exist.
- */
+/// Set an internal variable to a string value. Creates the variable if it does
+/// not already exist.
void set_internal_string_var(const char *name, char_u *value)
FUNC_ATTR_NONNULL_ARG(1)
{
@@ -523,9 +520,10 @@ static char_u *redir_endp = NULL;
static char_u *redir_varname = NULL;
/// Start recording command output to a variable
-/// Returns OK if successfully completed the setup. FAIL otherwise.
///
/// @param append append to an existing variable
+///
+/// @return OK if successfully completed the setup. FAIL otherwise.
int var_redir_start(char_u *name, int append)
{
int save_emsg;
@@ -586,15 +584,13 @@ int var_redir_start(char_u *name, int append)
return OK;
}
-/*
- * Append "value[value_len]" to the variable set by var_redir_start().
- * The actual appending is postponed until redirection ends, because the value
- * appended may in fact be the string we write to, changing it may cause freed
- * memory to be used:
- * :redir => foo
- * :let foo
- * :redir END
- */
+/// Append "value[value_len]" to the variable set by var_redir_start().
+/// The actual appending is postponed until redirection ends, because the value
+/// appended may in fact be the string we write to, changing it may cause freed
+/// memory to be used:
+/// :redir => foo
+/// :let foo
+/// :redir END
void var_redir_str(char_u *value, int value_len)
{
int len;
@@ -614,10 +610,8 @@ void var_redir_str(char_u *value, int value_len)
redir_ga.ga_len += len;
}
-/*
- * Stop redirecting command output to a variable.
- * Frees the allocated memory.
- */
+/// Stop redirecting command output to a variable.
+/// Frees the allocated memory.
void var_redir_stop(void)
{
typval_T tv;
@@ -744,7 +738,7 @@ int eval_to_bool(char_u *arg, bool *error, char_u **nextcmd, int skip)
return retval;
}
-// Call eval1() and give an error message if not done at a lower level.
+/// Call eval1() and give an error message if not done at a lower level.
static int eval1_emsg(char_u **arg, typval_T *rettv, bool evaluate)
FUNC_ATTR_NONNULL_ARG(1, 2)
{
@@ -767,8 +761,8 @@ static int eval1_emsg(char_u **arg, typval_T *rettv, bool evaluate)
return ret;
}
-/// @return whether a typval is a valid expression to pass to eval_expr_typval()
-/// or eval_expr_to_bool(). An empty string returns false;
+/// @return whether a typval is a valid expression to pass to eval_expr_typval()
+/// or eval_expr_to_bool(). An empty string returns false;
bool eval_expr_valid_arg(const typval_T *const tv)
FUNC_ATTR_NONNULL_ALL FUNC_ATTR_CONST
{
@@ -867,10 +861,9 @@ char *eval_to_string_skip(const char *arg, const char **nextcmd, const bool skip
return retval;
}
-/*
- * Skip over an expression at "*pp".
- * Return FAIL for an error, OK otherwise.
- */
+/// Skip over an expression at "*pp".
+///
+/// @return FAIL for an error, OK otherwise.
int skip_expr(char_u **pp)
{
typval_T rettv;
@@ -917,10 +910,10 @@ char_u *eval_to_string(char_u *arg, char_u **nextcmd, bool convert)
return (char_u *)retval;
}
-/*
- * Call eval_to_string() without using current local variables and using
- * textlock. When "use_sandbox" is TRUE use the sandbox.
- */
+/// Call eval_to_string() without using current local variables and using
+/// textlock.
+///
+/// @param use_sandbox when TRUE, use the sandbox.
char_u *eval_to_string_safe(char_u *arg, char_u **nextcmd, int use_sandbox)
{
char_u *retval;
@@ -940,11 +933,10 @@ char_u *eval_to_string_safe(char_u *arg, char_u **nextcmd, int use_sandbox)
return retval;
}
-/*
- * Top level evaluation function, returning a number.
- * Evaluates "expr" silently.
- * Returns -1 for an error.
- */
+/// Top level evaluation function, returning a number.
+/// Evaluates "expr" silently.
+///
+/// @return -1 for an error.
varnumber_T eval_to_number(char_u *expr)
{
typval_T rettv;
@@ -964,9 +956,10 @@ varnumber_T eval_to_number(char_u *expr)
return retval;
}
-// Top level evaluation function.
-// Returns an allocated typval_T with the result.
-// Returns NULL when there is an error.
+/// Top level evaluation function.
+///
+/// @return an allocated typval_T with the result or
+/// NULL when there is an error.
typval_T *eval_expr(char_u *arg)
{
typval_T *tv = xmalloc(sizeof(*tv));
@@ -976,11 +969,9 @@ typval_T *eval_expr(char_u *arg)
return tv;
}
-/*
- * Prepare v: variable "idx" to be used.
- * Save the current typeval in "save_tv".
- * When not used yet add the variable to the v: hashtable.
- */
+/// Prepare v: variable "idx" to be used.
+/// Save the current typeval in "save_tv".
+/// When not used yet add the variable to the v: hashtable.
void prepare_vimvar(int idx, typval_T *save_tv)
{
*save_tv = vimvars[idx].vv_tv;
@@ -989,10 +980,8 @@ void prepare_vimvar(int idx, typval_T *save_tv)
}
}
-/*
- * Restore v: variable "idx" to typeval "save_tv".
- * When no longer defined, remove the variable from the v: hashtable.
- */
+/// Restore v: variable "idx" to typeval "save_tv".
+/// When no longer defined, remove the variable from the v: hashtable.
void restore_vimvar(int idx, typval_T *save_tv)
{
hashitem_T *hi;
@@ -1019,11 +1008,10 @@ void find_win_for_curbuf(void)
}
}
-/*
- * Evaluate an expression to a list with suggestions.
- * For the "expr:" part of 'spellsuggest'.
- * Returns NULL when there is an error.
- */
+/// Evaluate an expression to a list with suggestions.
+/// For the "expr:" part of 'spellsuggest'.
+///
+/// @return NULL when there is an error.
list_T *eval_spell_expr(char_u *badword, char_u *expr)
{
typval_T save_val;
@@ -1087,7 +1075,7 @@ int get_spellword(list_T *const list, const char **ret_word)
// Uses argv[0] to argv[argc-1] for the function arguments. argv[argc]
// should have type VAR_UNKNOWN.
//
-// Return OK or FAIL.
+// @return OK or FAIL.
int call_vim_function(const char_u *func, int argc, typval_T *argv, typval_T *rettv)
FUNC_ATTR_NONNULL_ALL
{
@@ -1225,10 +1213,8 @@ void prof_child_exit(proftime_T *tm)
}
-/*
- * Evaluate 'foldexpr'. Returns the foldlevel, and any character preceding
- * it in "*cp". Doesn't give error messages.
- */
+/// Evaluate 'foldexpr'. Returns the foldlevel, and any character preceding
+/// it in "*cp". Doesn't give error messages.
int eval_foldexpr(char_u *arg, int *cp)
{
typval_T tv;
@@ -1269,26 +1255,27 @@ int eval_foldexpr(char_u *arg, int *cp)
return (int)retval;
}
-// ":cons[t] var = expr1" define constant
-// ":cons[t] [name1, name2, ...] = expr1" define constants unpacking list
-// ":cons[t] [name, ..., ; lastname] = expr" define constants unpacking list
+/// ":cons[t] var = expr1" define constant
+/// ":cons[t] [name1, name2, ...] = expr1" define constants unpacking list
+/// ":cons[t] [name, ..., ; lastname] = expr" define constants unpacking list
void ex_const(exarg_T *eap)
{
ex_let_const(eap, true);
}
-// Get a list of lines from a HERE document. The here document is a list of
-// lines surrounded by a marker.
-// cmd << {marker}
-// {line1}
-// {line2}
-// ....
-// {marker}
-//
-// The {marker} is a string. If the optional 'trim' word is supplied before the
-// marker, then the leading indentation before the lines (matching the
-// indentation in the 'cmd' line) is stripped.
-// Returns a List with {lines} or NULL.
+/// Get a list of lines from a HERE document. The here document is a list of
+/// lines surrounded by a marker.
+/// cmd << {marker}
+/// {line1}
+/// {line2}
+/// ....
+/// {marker}
+///
+/// The {marker} is a string. If the optional 'trim' word is supplied before the
+/// marker, then the leading indentation before the lines (matching the
+/// indentation in the 'cmd' line) is stripped.
+///
+/// @return a List with {lines} or NULL.
static list_T *heredoc_get(exarg_T *eap, char_u *cmd)
{
char_u *marker;
@@ -1386,18 +1373,18 @@ static list_T *heredoc_get(exarg_T *eap, char_u *cmd)
return l;
}
-// ":let" list all variable values
-// ":let var1 var2" list variable values
-// ":let var = expr" assignment command.
-// ":let var += expr" assignment command.
-// ":let var -= expr" assignment command.
-// ":let var *= expr" assignment command.
-// ":let var /= expr" assignment command.
-// ":let var %= expr" assignment command.
-// ":let var .= expr" assignment command.
-// ":let var ..= expr" assignment command.
-// ":let [var1, var2] = expr" unpack list.
-// ":let [name, ..., ; lastname] = expr" unpack list.
+/// ":let" list all variable values
+/// ":let var1 var2" list variable values
+/// ":let var = expr" assignment command.
+/// ":let var += expr" assignment command.
+/// ":let var -= expr" assignment command.
+/// ":let var *= expr" assignment command.
+/// ":let var /= expr" assignment command.
+/// ":let var %= expr" assignment command.
+/// ":let var .= expr" assignment command.
+/// ":let var ..= expr" assignment command.
+/// ":let [var1, var2] = expr" unpack list.
+/// ":let [name, ..., ; lastname] = expr" unpack list.
void ex_let(exarg_T *eap)
{
ex_let_const(eap, false);
@@ -1578,13 +1565,12 @@ static int ex_let_vars(char_u *arg_start, typval_T *tv, int copy, int semicolon,
return OK;
}
-/*
- * Skip over assignable variable "var" or list of variables "[var, var]".
- * Used for ":let varvar = expr" and ":for varvar in expr".
- * For "[var, var]" increment "*var_count" for each variable.
- * for "[var, var; var]" set "semicolon".
- * Return NULL for an error.
- */
+/// Skip over assignable variable "var" or list of variables "[var, var]".
+/// Used for ":let varvar = expr" and ":for varvar in expr".
+/// For "[var, var]" increment "*var_count" for each variable.
+/// for "[var, var; var]" set "semicolon".
+///
+/// @return NULL for an error.
static const char_u *skip_var_list(const char_u *arg, int *var_count, int *semicolon)
{
const char_u *p;
@@ -1622,10 +1608,8 @@ static const char_u *skip_var_list(const char_u *arg, int *var_count, int *semic
}
}
-/*
- * Skip one (assignable) variable name, including @r, $VAR, &option, d.key,
- * l[idx].
- */
+/// Skip one (assignable) variable name, including @r, $VAR, &option, d.key,
+/// l[idx].
static const char_u *skip_var_one(const char_u *arg)
{
if (*arg == '@' && arg[1] != NUL) {
@@ -1635,10 +1619,9 @@ static const char_u *skip_var_one(const char_u *arg)
NULL, NULL, FNE_INCL_BR | FNE_CHECK_START);
}
-/*
- * List variables for hashtab "ht" with prefix "prefix".
- * If "empty" is TRUE also list NULL strings as empty strings.
- */
+/// List variables for hashtab "ht" with prefix "prefix".
+///
+/// @param empty if TRUE also list NULL strings as empty strings.
void list_hashtable_vars(hashtab_T *ht, const char *prefix, int empty, int *first)
{
hashitem_T *hi;
@@ -1667,47 +1650,37 @@ void list_hashtable_vars(hashtab_T *ht, const char *prefix, int empty, int *firs
}
}
-/*
- * List global variables.
- */
+/// List global variables.
static void list_glob_vars(int *first)
{
list_hashtable_vars(&globvarht, "", true, first);
}
-/*
- * List buffer variables.
- */
+/// List buffer variables.
static void list_buf_vars(int *first)
{
list_hashtable_vars(&curbuf->b_vars->dv_hashtab, "b:", true, first);
}
-/*
- * List window variables.
- */
+/// List window variables.
static void list_win_vars(int *first)
{
list_hashtable_vars(&curwin->w_vars->dv_hashtab, "w:", true, first);
}
-/*
- * List tab page variables.
- */
+/// List tab page variables.
static void list_tab_vars(int *first)
{
list_hashtable_vars(&curtab->tp_vars->dv_hashtab, "t:", true, first);
}
-/*
- * List Vim variables.
- */
+/// List Vim variables.
static void list_vim_vars(int *first)
{
list_hashtable_vars(&vimvarht, "v:", false, first);
}
-// List script-local variables, if there is a script.
+/// List script-local variables, if there is a script.
static void list_script_vars(int *first)
{
if (current_sctx.sc_sid > 0 && current_sctx.sc_sid <= ga_scripts.ga_len) {
@@ -1715,9 +1688,7 @@ static void list_script_vars(int *first)
}
}
-/*
- * List variables in "arg".
- */
+/// List variables in "arg".
static const char *list_arg_vars(exarg_T *eap, const char *arg, int *first)
{
int error = FALSE;
@@ -2380,9 +2351,7 @@ char_u *get_lval(char_u *const name, typval_T *const rettv, lval_T *const lp, co
// TODO(ZyX-I): move to eval/executor
-/*
- * Clear lval "lp" that was filled by get_lval().
- */
+/// Clear lval "lp" that was filled by get_lval().
void clear_lval(lval_T *lp)
{
xfree(lp->ll_exp_name);
@@ -2391,12 +2360,11 @@ void clear_lval(lval_T *lp)
// TODO(ZyX-I): move to eval/executor
-/*
- * Set a variable that was parsed by get_lval() to "rettv".
- * "endp" points to just after the parsed name.
- * "op" is NULL, "+" for "+=", "-" for "-=", "*" for "*=", "/" for "/=",
- * "%" for "%=", "." for ".=" or "=" for "=".
- */
+/// Set a variable that was parsed by get_lval() to "rettv".
+///
+/// @param endp points to just after the parsed name.
+/// @param op NULL, "+" for "+=", "-" for "-=", "*" for "*=", "/" for "/=",
+/// "%" for "%=", "." for ".=" or "=" for "=".
static void set_var_lval(lval_T *lp, char_u *endp, typval_T *rettv, int copy, const bool is_const,
const char *op)
{
@@ -2599,12 +2567,12 @@ notify:
// TODO(ZyX-I): move to eval/ex_cmds
-/*
- * Evaluate the expression used in a ":for var in expr" command.
- * "arg" points to "var".
- * Set "*errp" to TRUE for an error, FALSE otherwise;
- * Return a pointer that holds the info. Null when there is an error.
- */
+/// Evaluate the expression used in a ":for var in expr" command.
+/// "arg" points to "var".
+///
+/// @param[out] *errp set to TRUE for an error, FALSE otherwise;
+///
+/// @return a pointer that holds the info. Null when there is an error.
void *eval_for_line(const char_u *arg, bool *errp, char_u **nextcmdp, int skip)
{
forinfo_T *fi = xcalloc(1, sizeof(forinfo_T));
@@ -2676,12 +2644,11 @@ void *eval_for_line(const char_u *arg, bool *errp, char_u **nextcmdp, int skip)
// TODO(ZyX-I): move to eval/ex_cmds
-/*
- * Use the first item in a ":for" list. Advance to the next.
- * Assign the values to the variable (list). "arg" points to the first one.
- * Return TRUE when a valid item was found, FALSE when at end of list or
- * something wrong.
- */
+/// Use the first item in a ":for" list. Advance to the next.
+/// Assign the values to the variable (list). "arg" points to the first one.
+///
+/// @return true when a valid item was found, false when at end of list or
+/// something wrong.
bool next_for_item(void *fi_void, char_u *arg)
{
forinfo_T *fi = (forinfo_T *)fi_void;
@@ -2727,9 +2694,7 @@ bool next_for_item(void *fi_void, char_u *arg)
// TODO(ZyX-I): move to eval/ex_cmds
-/*
- * Free the structure used to store info used by ":for".
- */
+/// Free the structure used to store info used by ":for".
void free_for_info(void *fi_void)
{
forinfo_T *fi = (forinfo_T *)fi_void;
@@ -3178,9 +3143,7 @@ static int do_lock_var(lval_T *lp, char_u *name_end FUNC_ATTR_UNUSED, exarg_T *e
return ret;
}
-/*
- * Delete all "menutrans_" variables.
- */
+/// Delete all "menutrans_" variables.
void del_menutrans_vars(void)
{
hash_lock(&globvarht);
@@ -3202,9 +3165,7 @@ void del_menutrans_vars(void)
static char_u *varnamebuf = NULL;
static size_t varnamebuflen = 0;
-/*
- * Function to concatenate a prefix and a variable name.
- */
+/// Function to concatenate a prefix and a variable name.
char_u *cat_prefix_varname(int prefix, const char_u *name)
FUNC_ATTR_NONNULL_ALL
{
@@ -3222,10 +3183,8 @@ char_u *cat_prefix_varname(int prefix, const char_u *name)
return varnamebuf;
}
-/*
- * Function given to ExpandGeneric() to obtain the list of user defined
- * (global/buffer/window/built-in) variable names.
- */
+/// Function given to ExpandGeneric() to obtain the list of user defined
+/// (global/buffer/window/built-in) variable names.
char_u *get_user_var_name(expand_T *xp, int idx)
{
static size_t gdone;
@@ -3257,9 +3216,7 @@ char_u *get_user_var_name(expand_T *xp, int idx)
}
// b: variables
- // In cmdwin, the alternative buffer should be used.
- hashtab_T *ht
- = is_in_cmdwin() ? &prevwin->w_buffer->b_vars->dv_hashtab : &curbuf->b_vars->dv_hashtab;
+ const hashtab_T *ht = &prevwin_curwin()->w_buffer->b_vars->dv_hashtab;
if (bdone < ht->ht_used) {
if (bdone++ == 0) {
hi = ht->ht_array;
@@ -3273,8 +3230,7 @@ char_u *get_user_var_name(expand_T *xp, int idx)
}
// w: variables
- // In cmdwin, the alternative window should be used.
- ht = is_in_cmdwin() ? &prevwin->w_vars->dv_hashtab : &curwin->w_vars->dv_hashtab;
+ ht = &prevwin_curwin()->w_vars->dv_hashtab;
if (wdone < ht->ht_used) {
if (wdone++ == 0) {
hi = ht->ht_array;
@@ -3313,8 +3269,9 @@ char_u *get_user_var_name(expand_T *xp, int idx)
// TODO(ZyX-I): move to eval/expressions
-/// Return TRUE if "pat" matches "text".
/// Does not use 'cpo' and always uses 'magic'.
+///
+/// @return TRUE if "pat" matches "text".
static int pattern_match(char_u *pat, char_u *text, bool ic)
{
int matches = 0;
@@ -3335,10 +3292,10 @@ static int pattern_match(char_u *pat, char_u *text, bool ic)
/// 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)
@@ -3399,13 +3356,12 @@ static int eval_func(char_u **const arg, char_u *const name, const int name_len,
* VAR_UNKNOWN. The function still returns FAIL for a syntax error.
*/
-/*
- * Handle zero level expression.
- * This calls eval1() and handles error message and nextcmd.
- * Put the result in "rettv" when returning OK and "evaluate" is TRUE.
- * Note: "rettv.v_lock" is not set.
- * Return OK or FAIL.
- */
+/// Handle zero level expression.
+/// This calls eval1() and handles error message and nextcmd.
+/// Put the result in "rettv" when returning OK and "evaluate" is TRUE.
+/// Note: "rettv.v_lock" is not set.
+///
+/// @return OK or FAIL.
int eval0(char_u *arg, typval_T *rettv, char_u **nextcmd, int evaluate)
{
int ret;
@@ -3438,17 +3394,15 @@ int eval0(char_u *arg, typval_T *rettv, char_u **nextcmd, int evaluate)
// TODO(ZyX-I): move to eval/expressions
-/*
- * Handle top level expression:
- * expr2 ? expr1 : expr1
- *
- * "arg" must point to the first non-white of the expression.
- * "arg" is advanced to the next non-white after the recognized expression.
- *
- * Note: "rettv.v_lock" is not set.
- *
- * Return OK or FAIL.
- */
+/// Handle top level expression:
+/// expr2 ? expr1 : expr1
+///
+/// "arg" must point to the first non-white of the expression.
+/// "arg" is advanced to the next non-white after the recognized expression.
+///
+/// Note: "rettv.v_lock" is not set.
+///
+/// @return OK or FAIL.
int eval1(char_u **arg, typval_T *rettv, int evaluate)
{
int result;
@@ -3514,15 +3468,13 @@ int eval1(char_u **arg, typval_T *rettv, int evaluate)
// TODO(ZyX-I): move to eval/expressions
-/*
- * Handle first level expression:
- * expr2 || expr2 || expr2 logical OR
- *
- * "arg" must point to the first non-white of the expression.
- * "arg" is advanced to the next non-white after the recognized expression.
- *
- * Return OK or FAIL.
- */
+/// Handle first level expression:
+/// expr2 || expr2 || expr2 logical OR
+///
+/// "arg" must point to the first non-white of the expression.
+/// "arg" is advanced to the next non-white after the recognized expression.
+///
+/// @return OK or FAIL.
static int eval2(char_u **arg, typval_T *rettv, int evaluate)
{
typval_T var2;
@@ -3585,15 +3537,13 @@ static int eval2(char_u **arg, typval_T *rettv, int evaluate)
// TODO(ZyX-I): move to eval/expressions
-/*
- * Handle second level expression:
- * expr3 && expr3 && expr3 logical AND
- *
- * "arg" must point to the first non-white of the expression.
- * "arg" is advanced to the next non-white after the recognized expression.
- *
- * Return OK or FAIL.
- */
+/// Handle second level expression:
+/// expr3 && expr3 && expr3 logical AND
+///
+/// @param arg must point to the first non-white of the expression.
+/// `arg` is advanced to the next non-white after the recognized expression.
+///
+/// @return OK or FAIL.
static int eval3(char_u **arg, typval_T *rettv, int evaluate)
{
typval_T var2;
@@ -3656,24 +3606,22 @@ static int eval3(char_u **arg, typval_T *rettv, int evaluate)
// TODO(ZyX-I): move to eval/expressions
-/*
- * Handle third level expression:
- * var1 == var2
- * var1 =~ var2
- * var1 != var2
- * var1 !~ var2
- * var1 > var2
- * var1 >= var2
- * var1 < var2
- * var1 <= var2
- * var1 is var2
- * var1 isnot var2
- *
- * "arg" must point to the first non-white of the expression.
- * "arg" is advanced to the next non-white after the recognized expression.
- *
- * Return OK or FAIL.
- */
+/// Handle third level expression:
+/// var1 == var2
+/// var1 =~ var2
+/// var1 != var2
+/// var1 !~ var2
+/// var1 > var2
+/// var1 >= var2
+/// var1 < var2
+/// var1 <= var2
+/// var1 is var2
+/// var1 isnot var2
+///
+/// "arg" must point to the first non-white of the expression.
+/// "arg" is advanced to the next non-white after the recognized expression.
+///
+/// @return OK or FAIL.
static int eval4(char_u **arg, typval_T *rettv, int evaluate)
{
typval_T var2;
@@ -3767,18 +3715,16 @@ static int eval4(char_u **arg, typval_T *rettv, int evaluate)
// TODO(ZyX-I): move to eval/expressions
-/*
- * Handle fourth level expression:
- * + number addition
- * - number subtraction
- * . string concatenation
- * .. string concatenation
- *
- * "arg" must point to the first non-white of the expression.
- * "arg" is advanced to the next non-white after the recognized expression.
- *
- * Return OK or FAIL.
- */
+/// Handle fourth level expression:
+/// + number addition
+/// - number subtraction
+/// . string concatenation
+/// .. string concatenation
+///
+/// @param arg must point to the first non-white of the expression.
+/// `arg` is advanced to the next non-white after the recognized expression.
+///
+/// @return OK or FAIL.
static int eval5(char_u **arg, typval_T *rettv, int evaluate)
{
typval_T var2;
@@ -4324,7 +4270,8 @@ static int eval7(char_u **arg, typval_T *rettv, int evaluate, int want_string)
/// 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.
+///
+/// @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
@@ -4378,7 +4325,7 @@ static int eval7_leader(typval_T *const rettv, const char_u *const start_leader,
/// @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.
+/// @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)
@@ -4426,9 +4373,13 @@ static int call_func_rettv(char_u **const arg, typval_T *const rettv, const bool
}
/// 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 ')'.
+/// @param *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
@@ -4465,8 +4416,10 @@ static int eval_lambda(char_u **const arg, typval_T *const rettv, const bool eva
}
/// Evaluate "->method()" or "->v:lua.method()".
-/// @note "*arg" points to the '-'.
-/// @return FAIL or OK. "*arg" is advanced to after the ')'.
+///
+/// @param *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
@@ -4539,9 +4492,10 @@ static int eval_method(char_u **const arg, typval_T *const rettv, const bool eva
/// Evaluate an "[expr]" or "[expr:expr]" index. Also "dict.key".
/// "*arg" points to the '[' or '.'.
-/// Returns FAIL or OK. "*arg" is advanced to after the ']'.
///
/// @param verbose give error messages
+///
+/// @returns FAIL or OK. "*arg" is advanced to after the ']'.
static int eval_index(char_u **arg, typval_T *rettv, int evaluate, int verbose)
{
bool empty1 = false;
@@ -4846,12 +4800,12 @@ static int eval_index(char_u **arg, typval_T *rettv, int evaluate, int verbose)
/// Get an option value
///
-/// @param[in,out] arg Points to the '&' or '+' before the option name. Is
+/// @param[in,out] arg Points to the '&' or '+' before the option name. Is
/// advanced to the character after the option name.
-/// @param[out] rettv Location where result is saved.
-/// @param[in] evaluate If not true, rettv is not populated.
+/// @param[out] rettv Location where result is saved.
+/// @param[in] evaluate If not true, rettv is not populated.
///
-/// @return OK or FAIL.
+/// @return OK or FAIL.
int get_option_tv(const char **const arg, typval_T *const rettv, const bool evaluate)
FUNC_ATTR_NONNULL_ARG(1)
{
@@ -4910,10 +4864,9 @@ int get_option_tv(const char **const arg, typval_T *const rettv, const bool eval
return ret;
}
-/*
- * Allocate a variable for a string constant.
- * Return OK or FAIL.
- */
+/// Allocate a variable for a string constant.
+///
+/// @return OK or FAIL.
static int get_string_tv(char_u **arg, typval_T *rettv, int evaluate)
{
char_u *p;
@@ -5050,10 +5003,9 @@ static int get_string_tv(char_u **arg, typval_T *rettv, int evaluate)
return OK;
}
-/*
- * Allocate a variable for a 'str''ing' constant.
- * Return OK or FAIL.
- */
+/// Allocate a variable for a 'str''ing' constant.
+///
+/// @return OK or FAIL.
static int get_lit_string_tv(char_u **arg, typval_T *rettv, int evaluate)
{
char_u *p;
@@ -5106,7 +5058,7 @@ static int get_lit_string_tv(char_u **arg, typval_T *rettv, int evaluate)
return OK;
}
-/// @return the function name of the partial.
+/// @return the function name of the partial.
char_u *partial_name(partial_T *pt)
{
if (pt->pt_name != NULL) {
@@ -5145,7 +5097,8 @@ void partial_unref(partial_T *pt)
}
/// Allocate a variable for a List and fill it from "*arg".
-/// Return OK or FAIL.
+///
+/// @return OK or FAIL.
static int get_list_tv(char_u **arg, typval_T *rettv, int evaluate)
{
list_T *l = NULL;
@@ -5283,7 +5236,8 @@ int get_copyID(void)
/// Do garbage collection for lists and dicts.
///
/// @param testing true if called from test_garbagecollect_now().
-/// @returns true if some memory was freed.
+///
+/// @return true if some memory was freed.
bool garbage_collect(bool testing)
{
bool abort = false;
@@ -5461,10 +5415,11 @@ bool garbage_collect(bool testing)
/// Free lists and dictionaries that are no longer referenced.
///
-/// @note This function may only be called from garbage_collect().
+/// @note This function may only be called from garbage_collect().
///
-/// @param copyID Free lists/dictionaries that don't have this ID.
-/// @return true, if something was freed.
+/// @param copyID Free lists/dictionaries that don't have this ID.
+///
+/// @return true, if something was freed.
static int free_unref_items(int copyID)
{
bool did_free = false;
@@ -5699,7 +5654,7 @@ bool set_ref_in_item(typval_T *tv, int copyID, ht_stack_T **ht_stack, list_stack
/// Mark all lists and dicts referenced in given mark
///
-/// @returns true if setting references failed somehow.
+/// @return true if setting references failed somehow.
static inline bool set_ref_in_fmark(fmark_T fm, int copyID)
FUNC_ATTR_WARN_UNUSED_RESULT
{
@@ -5713,7 +5668,7 @@ static inline bool set_ref_in_fmark(fmark_T fm, int copyID)
/// Mark all lists and dicts referenced in given list and the list itself
///
-/// @returns true if setting references failed somehow.
+/// @return true if setting references failed somehow.
static inline bool set_ref_list(list_T *list, int copyID)
FUNC_ATTR_WARN_UNUSED_RESULT
{
@@ -5729,7 +5684,7 @@ static inline bool set_ref_list(list_T *list, int copyID)
/// Mark all lists and dicts referenced in given dict and the dict itself
///
-/// @returns true if setting references failed somehow.
+/// @return true if setting references failed somehow.
static inline bool set_ref_dict(dict_T *dict, int copyID)
FUNC_ATTR_WARN_UNUSED_RESULT
{
@@ -5744,8 +5699,9 @@ static inline bool set_ref_dict(dict_T *dict, int copyID)
}
-// Get the key for *{key: val} into "tv" and advance "arg".
-// Return FAIL when there is no valid key.
+/// Get the key for *{key: val} into "tv" and advance "arg".
+///
+/// @return FAIL when there is no valid key.
static int get_literal_key(char_u **arg, typval_T *tv)
FUNC_ATTR_NONNULL_ALL
{
@@ -5763,9 +5719,10 @@ static int get_literal_key(char_u **arg, typval_T *tv)
return OK;
}
-// Allocate a variable for a Dictionary and fill it from "*arg".
-// "literal" is true for *{key: val}
-// Return OK or FAIL. Returns NOTDONE for {expr}.
+/// Allocate a variable for a Dictionary and fill it from "*arg".
+/// "literal" is true for *{key: val}
+///
+/// @return OK or FAIL. Returns NOTDONE for {expr}.
static int dict_get_tv(char_u **arg, typval_T *rettv, int evaluate, bool literal)
{
dict_T *d = NULL;
@@ -5875,10 +5832,10 @@ failret:
/// This uses strtod(). setlocale(LC_NUMERIC, "C") has been used earlier to
/// make sure this always uses a decimal point.
///
-/// @param[in] text String to convert.
-/// @param[out] ret_value Location where conversion result is saved.
+/// @param[in] text String to convert.
+/// @param[out] ret_value Location where conversion result is saved.
///
-/// @return Length of the text that was consumed.
+/// @return Length of the text that was consumed.
size_t string2float(const char *const text, float_T *const ret_value)
FUNC_ATTR_NONNULL_ALL
{
@@ -5905,9 +5862,9 @@ size_t string2float(const char *const text, float_T *const ret_value)
///
/// If the environment variable was not set, silently assume it is empty.
///
-/// @param arg Points to the '$'. It is advanced to after the name.
-/// @return FAIL if the name is invalid.
+/// @param arg Points to the '$'. It is advanced to after the name.
///
+/// @return FAIL if the name is invalid.
static int get_env_tv(char_u **arg, typval_T *rettv, int evaluate)
{
char_u *name;
@@ -5956,7 +5913,7 @@ void get_arglist_as_rettv(aentry_T *arglist, int argcount, typval_T *rettv)
}
}
-// Prepare "gap" for an assert error and add the sourcing position.
+/// Prepare "gap" for an assert error and add the sourcing position.
void prepare_assert_error(garray_T *gap)
{
char buf[NUMBUFLEN];
@@ -5977,8 +5934,8 @@ void prepare_assert_error(garray_T *gap)
}
}
-// Append "p[clen]" to "gap", escaping unprintable characters.
-// Changes NL to \n, CR to \r, etc.
+/// Append "p[clen]" to "gap", escaping unprintable characters.
+/// Changes NL to \n, CR to \r, etc.
static void ga_concat_esc(garray_T *gap, const char_u *p, int clen)
FUNC_ATTR_NONNULL_ALL
{
@@ -6016,8 +5973,8 @@ static void ga_concat_esc(garray_T *gap, const char_u *p, int clen)
}
}
-// Append "str" to "gap", escaping unprintable characters.
-// Changes NL to \n, CR to \r, etc.
+/// Append "str" to "gap", escaping unprintable characters.
+/// Changes NL to \n, CR to \r, etc.
static void ga_concat_shorten_esc(garray_T *gap, const char_u *str)
FUNC_ATTR_NONNULL_ARG(1)
{
@@ -6051,7 +6008,7 @@ static void ga_concat_shorten_esc(garray_T *gap, const char_u *str)
}
}
-// Fill "gap" with information about an assert error.
+/// Fill "gap" with information about an assert error.
void fill_assert_error(garray_T *gap, typval_T *opt_msg_tv, char_u *exp_str, typval_T *exp_tv,
typval_T *got_tv, assert_type_T atype)
{
@@ -6094,7 +6051,7 @@ void fill_assert_error(garray_T *gap, typval_T *opt_msg_tv, char_u *exp_str, typ
}
}
-// Add an assert error to v:errors.
+/// Add an assert error to v:errors.
void assert_error(garray_T *gap)
{
struct vimvar *vp = &vimvars[VV_ERRORS];
@@ -6268,7 +6225,7 @@ int assert_inrange(typval_T *argvars)
return 0;
}
-// Common for assert_true() and assert_false().
+/// Common for assert_true() and assert_false().
int assert_bool(typval_T *argvars, bool is_true)
FUNC_ATTR_NONNULL_ALL
{
@@ -6436,15 +6393,13 @@ win_T *find_win_by_nr_or_id(typval_T *vp)
int nr = (int)tv_get_number_chk(vp, NULL);
if (nr >= LOWEST_WIN_ID) {
- return win_id2wp(vp);
+ return win_id2wp(tv_get_number(vp));
}
return find_win_by_nr(vp, NULL);
}
-/*
- * Implementation of map() and filter().
- */
+/// Implementation of map() and filter().
void filter_map(typval_T *argvars, typval_T *rettv, int map)
{
typval_T *expr;
@@ -6806,7 +6761,7 @@ theend:
xfree(trans_name);
}
-/// Returns buffer options, variables and other attributes in a dictionary.
+/// @return buffer options, variables and other attributes in a dictionary.
dict_T *get_buffer_info(buf_T *buf)
{
dict_T *const dict = tv_dict_alloc();
@@ -6850,12 +6805,12 @@ dict_T *get_buffer_info(buf_T *buf)
///
/// @note Unlike tv_get_lnum(), this one supports only "$" special string.
///
-/// @param[in] tv Object to get value from. Is expected to be a number or
+/// @param[in] tv Object to get value from. Is expected to be a number or
/// a special string "$".
-/// @param[in] buf Buffer to take last line number from in case tv is "$". May
-/// be NULL, in this case "$" results in zero return.
+/// @param[in] buf Buffer to take last line number from in case tv is "$". May
+/// be NULL, in this case "$" results in zero return.
///
-/// @return Line number or 0 in case of error.
+/// @return Line number or 0 in case of error.
linenr_T tv_get_lnum_buf(const typval_T *const tv, const buf_T *const buf)
FUNC_ATTR_NONNULL_ARG(1) FUNC_ATTR_WARN_UNUSED_RESULT
{
@@ -6891,8 +6846,8 @@ void get_qf_loc_list(int is_qf, win_T *wp, typval_T *what_arg, typval_T *rettv)
}
}
-/// Returns information (variables, options, etc.) about a tab page
-/// as a dictionary.
+/// @return information (variables, options, etc.) about a tab page
+/// as a dictionary.
dict_T *get_tabpage_info(tabpage_T *tp, int tp_idx)
{
dict_T *const dict = tv_dict_alloc();
@@ -6911,7 +6866,7 @@ dict_T *get_tabpage_info(tabpage_T *tp, int tp_idx)
return dict;
}
-/// Returns information about a window as a dictionary.
+/// @return information about a window as a dictionary.
dict_T *get_win_info(win_T *wp, int16_t tpnr, int16_t winnr)
{
dict_T *const dict = tv_dict_alloc();
@@ -7064,12 +7019,10 @@ void getwinvar(typval_T *argvars, typval_T *rettv, int off)
}
}
-/*
- * This function is used by f_input() and f_inputdialog() functions. The third
- * argument to f_input() specifies the type of completion to use at the
- * prompt. The third argument to f_inputdialog() specifies the value to return
- * when the user cancels the prompt.
- */
+/// This function is used by f_input() and f_inputdialog() functions. The third
+/// argument to f_input() specifies the type of completion to use at the
+/// prompt. The third argument to f_inputdialog() specifies the value to return
+/// when the user cancels the prompt.
void get_user_input(const typval_T *const argvars, typval_T *const rettv, const bool inputdialog,
const bool secret)
FUNC_ATTR_NONNULL_ALL
@@ -7201,10 +7154,10 @@ void get_user_input(const typval_T *const argvars, typval_T *const rettv, const
/// Turn a dictionary into a list
///
-/// @param[in] tv Dictionary to convert. Is checked for actually being
-/// a dictionary, will give an error if not.
-/// @param[out] rettv Location where result will be saved.
-/// @param[in] what What to save in rettv.
+/// @param[in] tv Dictionary to convert. Is checked for actually being
+/// a dictionary, will give an error if not.
+/// @param[out] rettv Location where result will be saved.
+/// @param[in] what What to save in rettv.
void dict_list(typval_T *const tv, typval_T *const rettv, const DictListType what)
{
if (tv->v_type != VAR_DICT) {
@@ -7257,7 +7210,7 @@ void dict_list(typval_T *const tv, typval_T *const rettv, const DictListType wha
/// @param[out] cmd Returns the command or executable name.
/// @param[out] executable Returns `false` if argv[0] is not executable.
///
-/// @returns Result of `shell_build_argv()` if `cmd_tv` is a String.
+/// @return Result of `shell_build_argv()` if `cmd_tv` is a String.
/// Else, string values of `cmd_tv` copied to a (char **) list with
/// argv[0] resolved to full path ($PATHEXT-resolved on Windows).
char **tv_to_argv(typval_T *cmd_tv, const char **cmd, bool *executable)
@@ -7321,10 +7274,10 @@ char **tv_to_argv(typval_T *cmd_tv, const char **cmd, bool *executable)
/// Fill a dictionary with all applicable maparg() like dictionaries
///
-/// @param dict The dictionary to be filled
-/// @param mp The maphash that contains the mapping information
-/// @param buffer_value The "buffer" value
-/// @param compatible True for compatible with old maparg() dict
+/// @param dict The dictionary to be filled
+/// @param mp The maphash that contains the mapping information
+/// @param buffer_value The "buffer" value
+/// @param compatible True for compatible with old maparg() dict
void mapblock_fill_dict(dict_T *const dict, const mapblock_T *const mp, long buffer_value,
bool compatible)
FUNC_ATTR_NONNULL_ALL
@@ -7621,7 +7574,7 @@ static list_T *string_to_list(const char *str, size_t len, const bool keepempty)
return list;
}
-// os_system wrapper. Handles 'verbose', :profile, and v:shell_error.
+/// os_system wrapper. Handles 'verbose', :profile, and v:shell_error.
void get_system_output_as_rettv(typval_T *argvars, typval_T *rettv, bool retlist)
{
proftime_T wait_time;
@@ -7886,7 +7839,7 @@ void add_timer_info_all(typval_T *rettv)
})
}
-// invoked on the main loop
+/// invoked on the main loop
void timer_due_cb(TimeWatcher *tw, void *data)
{
timer_T *timer = (timer_T *)data;
@@ -7972,8 +7925,8 @@ void timer_stop(timer_T *timer)
time_watcher_close(&timer->tw, timer_close_cb);
}
-// This will be run on the main loop after the last timer_due_cb, so at this
-// point it is safe to free the callback.
+/// This will be run on the main loop after the last timer_due_cb, so at this
+/// point it is safe to free the callback.
static void timer_close_cb(TimeWatcher *tw, void *data)
{
timer_T *timer = (timer_T *)data;
@@ -8235,8 +8188,10 @@ int buf_byteidx_to_charidx(buf_T *buf, int lnum, int byteidx)
}
/// Convert the specified character index of line 'lnum' in buffer 'buf' to a
-/// byte index. Works only for loaded buffers. Returns -1 on failure.
+/// byte index. Works only for loaded buffers.
/// The index of the first byte and the first character is zero.
+///
+/// @return -1 on failure.
int buf_charidx_to_byteidx(buf_T *buf, int lnum, int charidx)
{
if (buf == NULL || buf->b_ml.ml_mfp == NULL) {
@@ -8400,8 +8355,9 @@ pos_T *var2fpos(const typval_T *const tv, const bool dollar_lnum, int *const ret
/// When "fnump" is NULL there is no file number, only 3 items.
/// Note that the column is passed on as-is, the caller may want to decrement
/// it to use 1 for the first column.
-/// Return FAIL when conversion is not possible, doesn't check the position for
-/// validity.
+///
+/// @return FAIL when conversion is not possible, doesn't check the position for
+/// validity.
int list2fpos(typval_T *arg, pos_T *posp, int *fnump, colnr_T *curswantp, bool charcol)
{
list_T *l;
@@ -8463,11 +8419,10 @@ int list2fpos(typval_T *arg, pos_T *posp, int *fnump, colnr_T *curswantp, bool c
return OK;
}
-/*
- * Get the length of an environment variable name.
- * Advance "arg" to the first character after the name.
- * Return 0 for error.
- */
+/// Get the length of an environment variable name.
+/// Advance "arg" to the first character after the name.
+///
+/// @return 0 for error.
static int get_env_len(const char_u **arg)
{
int len;
@@ -8484,9 +8439,11 @@ static int get_env_len(const char_u **arg)
return len;
}
-// Get the length of the name of a function or internal variable.
-// "arg" is advanced to the first non-white character after the name.
-// Return 0 if something is wrong.
+/// Get the length of the name of a function or internal variable.
+///
+/// @param arg is advanced to the first non-white character after the name.
+///
+/// @return 0 if something is wrong.
int get_id_len(const char **const arg)
{
int len;
@@ -8514,15 +8471,15 @@ int get_id_len(const char **const arg)
return len;
}
-/*
- * Get the length of the name of a variable or function.
- * Only the name is recognized, does not handle ".key" or "[idx]".
- * "arg" is advanced to the first non-white character after the name.
- * Return -1 if curly braces expansion failed.
- * Return 0 if something else is wrong.
- * If the name contains 'magic' {}'s, expand them and return the
- * expanded name in an allocated string via 'alias' - caller must free.
- */
+/// Get the length of the name of a variable or function.
+/// Only the name is recognized, does not handle ".key" or "[idx]".
+///
+/// @param arg is advanced to the first non-white character after the name.
+/// If the name contains 'magic' {}'s, expand them and return the
+/// expanded name in an allocated string via 'alias' - caller must free.
+///
+/// @return -1 if curly braces expansion failed or
+/// 0 if something else is wrong.
int get_name_len(const char **const arg, char **alias, bool evaluate, bool verbose)
{
int len;
@@ -8579,12 +8536,15 @@ int get_name_len(const char **const arg, char **alias, bool evaluate, bool verbo
return len;
}
-// Find the end of a variable or function name, taking care of magic braces.
-// If "expr_start" is not NULL then "expr_start" and "expr_end" are set to the
-// start and end of the first magic braces item.
-// "flags" can have FNE_INCL_BR and FNE_CHECK_START.
-// Return a pointer to just after the name. Equal to "arg" if there is no
-// valid name.
+/// Find the end of a variable or function name, taking care of magic braces.
+///
+/// @param expr_start if not NULL, then `expr_start` and `expr_end` are set to the
+/// start and end of the first magic braces item.
+///
+/// @param flags can have FNE_INCL_BR and FNE_CHECK_START.
+///
+/// @return a pointer to just after the name. Equal to "arg" if there is no
+/// valid name.
const char_u *find_name_end(const char_u *arg, const char_u **expr_start, const char_u **expr_end,
int flags)
{
@@ -8662,19 +8622,17 @@ const char_u *find_name_end(const char_u *arg, const char_u **expr_start, const
return p;
}
-/*
- * Expands out the 'magic' {}'s in a variable/function name.
- * Note that this can call itself recursively, to deal with
- * constructs like foo{bar}{baz}{bam}
- * The four pointer arguments point to "foo{expre}ss{ion}bar"
- * "in_start" ^
- * "expr_start" ^
- * "expr_end" ^
- * "in_end" ^
- *
- * Returns a new allocated string, which the caller must free.
- * Returns NULL for failure.
- */
+/// Expands out the 'magic' {}'s in a variable/function name.
+/// Note that this can call itself recursively, to deal with
+/// constructs like foo{bar}{baz}{bam}
+/// The four pointer arguments point to "foo{expre}ss{ion}bar"
+/// "in_start" ^
+/// "expr_start" ^
+/// "expr_end" ^
+/// "in_end" ^
+///
+/// @return a new allocated string, which the caller must free or
+/// NULL for failure.
static char_u *make_expanded_name(const char_u *in_start, char_u *expr_start, char_u *expr_end,
char_u *in_end)
{
@@ -8721,44 +8679,36 @@ static char_u *make_expanded_name(const char_u *in_start, char_u *expr_start, ch
return retval;
}
-/*
- * Return TRUE if character "c" can be used in a variable or function name.
- * Does not include '{' or '}' for magic braces.
- */
+/// @return TRUE if character "c" can be used in a variable or function name.
+/// Does not include '{' or '}' for magic braces.
int eval_isnamec(int c)
{
return ASCII_ISALNUM(c) || c == '_' || c == ':' || c == AUTOLOAD_CHAR;
}
-/*
- * Return TRUE if character "c" can be used as the first character in a
- * variable or function name (excluding '{' and '}').
- */
+/// @return TRUE if character "c" can be used as the first character in a
+/// variable or function name (excluding '{' and '}').
int eval_isnamec1(int c)
{
return ASCII_ISALPHA(c) || c == '_';
}
-/*
- * Get number v: variable value.
- */
+/// Get number v: variable value.
varnumber_T get_vim_var_nr(int idx) FUNC_ATTR_PURE
{
return vimvars[idx].vv_nr;
}
-// Get string v: variable value. Uses a static buffer, can only be used once.
-// If the String variable has never been set, return an empty string.
-// Never returns NULL;
+/// Get string v: variable value. Uses a static buffer, can only be used once.
+/// If the String variable has never been set, return an empty string.
+/// Never returns NULL;
char_u *get_vim_var_str(int idx) FUNC_ATTR_PURE FUNC_ATTR_NONNULL_RET
{
return (char_u *)tv_get_string(&vimvars[idx].vv_tv);
}
-/*
- * Get List v: variable value. Caller must take care of reference count when
- * needed.
- */
+/// Get List v: variable value. Caller must take care of reference count when
+/// needed.
list_T *get_vim_var_list(int idx) FUNC_ATTR_PURE
{
return vimvars[idx].vv_list;
@@ -8771,9 +8721,7 @@ dict_T *get_vim_var_dict(int idx) FUNC_ATTR_PURE
return vimvars[idx].vv_dict;
}
-/*
- * Set v:char to character "c".
- */
+/// Set v:char to character "c".
void set_vim_var_char(int c)
{
char buf[MB_MAXBYTES + 1];
@@ -8782,10 +8730,9 @@ void set_vim_var_char(int c)
set_vim_var_string(VV_CHAR, buf, -1);
}
-/*
- * Set v:count to "count" and v:count1 to "count1".
- * When "set_prevcount" is TRUE first set v:prevcount from v:count.
- */
+/// Set v:count to "count" and v:count1 to "count1".
+///
+/// @param set_prevcount if TRUE, first set v:prevcount from v:count.
void set_vcount(long count, long count1, int set_prevcount)
{
if (set_prevcount) {
@@ -8893,9 +8840,7 @@ void set_argv_var(char **argv, int argc)
set_vim_var_list(VV_ARGV, l);
}
-/*
- * Set v:register if needed.
- */
+/// Set v:register if needed.
void set_reg_var(int c)
{
char regname;
@@ -8911,12 +8856,10 @@ void set_reg_var(int c)
}
}
-/*
- * Get or set v:exception. If "oldval" == NULL, return the current value.
- * Otherwise, restore the value to "oldval" and return NULL.
- * Must always be called in pairs to save and restore v:exception! Does not
- * take care of memory allocations.
- */
+/// Get or set v:exception. If "oldval" == NULL, return the current value.
+/// Otherwise, restore the value to "oldval" and return NULL.
+/// Must always be called in pairs to save and restore v:exception! Does not
+/// take care of memory allocations.
char_u *v_exception(char_u *oldval)
{
if (oldval == NULL) {
@@ -8927,12 +8870,10 @@ char_u *v_exception(char_u *oldval)
return NULL;
}
-/*
- * Get or set v:throwpoint. If "oldval" == NULL, return the current value.
- * Otherwise, restore the value to "oldval" and return NULL.
- * Must always be called in pairs to save and restore v:throwpoint! Does not
- * take care of memory allocations.
- */
+/// Get or set v:throwpoint. If "oldval" == NULL, return the current value.
+/// Otherwise, restore the value to "oldval" and return NULL.
+/// Must always be called in pairs to save and restore v:throwpoint! Does not
+/// take care of memory allocations.
char_u *v_throwpoint(char_u *oldval)
{
if (oldval == NULL) {
@@ -8943,12 +8884,10 @@ char_u *v_throwpoint(char_u *oldval)
return NULL;
}
-/*
- * Set v:cmdarg.
- * If "eap" != NULL, use "eap" to generate the value and return the old value.
- * If "oldarg" != NULL, restore the value to "oldarg" and return NULL.
- * Must always be called in pairs!
- */
+/// Set v:cmdarg.
+/// If "eap" != NULL, use "eap" to generate the value and return the old value.
+/// If "oldarg" != NULL, restore the value to "oldarg" and return NULL.
+/// Must always be called in pairs!
char_u *set_cmdarg(exarg_T *eap, char_u *oldarg)
{
char_u *oldval = vimvars[VV_CMDARG].vv_str;
@@ -9213,11 +9152,12 @@ void set_selfdict(typval_T *const rettv, dict_T *const selfdict)
make_partial(selfdict, rettv);
}
-// Find variable "name" in the list of variables.
-// Return a pointer to it if found, NULL if not found.
-// Careful: "a:0" variables don't have a name.
-// When "htp" is not NULL we are writing to the variable, set "htp" to the
-// hashtab_T used.
+/// Find variable "name" in the list of variables.
+/// Careful: "a:0" variables don't have a name.
+/// When "htp" is not NULL we are writing to the variable, set "htp" to the
+/// hashtab_T used.
+///
+/// @return a pointer to it if found, NULL if not found.
dictitem_T *find_var(const char *const name, const size_t name_len, hashtab_T **htp,
int no_autoload)
{
@@ -9415,11 +9355,10 @@ hashtab_T *find_var_ht(const char *name, const size_t name_len, const char **var
return find_var_ht_dict(name, name_len, varname, &d);
}
-/*
- * Get the string value of a (global/local) variable.
- * Note: see tv_get_string() for how long the pointer remains valid.
- * Returns NULL when it doesn't exist.
- */
+/// @return the string value of a (global/local) variable or
+/// NULL when it doesn't exist.
+///
+/// @see tv_get_string() for how long the pointer remains valid.
char_u *get_var_value(const char *const name)
{
dictitem_T *v;
@@ -9431,10 +9370,8 @@ char_u *get_var_value(const char *const name)
return (char_u *)tv_get_string(&v->di_tv);
}
-/*
- * Allocate a new hashtab for a sourced script. It will be used while
- * sourcing this script and when executing functions defined in the script.
- */
+/// Allocate a new hashtab for a sourced script. It will be used while
+/// sourcing this script and when executing functions defined in the script.
void new_script_vars(scid_T id)
{
hashtab_T *ht;
@@ -9462,10 +9399,8 @@ void new_script_vars(scid_T id)
}
}
-/*
- * Initialize dictionary "dict" as a scope and set variable "dict_var" to
- * point to it.
- */
+/// Initialize dictionary "dict" as a scope and set variable "dict_var" to
+/// point to it.
void init_var_dict(dict_T *dict, ScopeDictDictItem *dict_var, int scope)
{
hash_init(&dict->dv_hashtab);
@@ -9481,9 +9416,7 @@ void init_var_dict(dict_T *dict, ScopeDictDictItem *dict_var, int scope)
QUEUE_INIT(&dict->watchers);
}
-/*
- * Unreference a dictionary initialized by init_var_dict().
- */
+/// Unreference a dictionary initialized by init_var_dict().
void unref_var_dict(dict_T *dict)
{
/* Now the dict needs to be freed if no one else is using it, go back to
@@ -9492,19 +9425,15 @@ void unref_var_dict(dict_T *dict)
tv_dict_unref(dict);
}
-/*
- * Clean up a list of internal variables.
- * Frees all allocated variables and the value they contain.
- * Clears hashtab "ht", does not free it.
- */
+/// Clean up a list of internal variables.
+/// Frees all allocated variables and the value they contain.
+/// Clears hashtab "ht", does not free it.
void vars_clear(hashtab_T *ht)
{
vars_clear_ext(ht, TRUE);
}
-/*
- * Like vars_clear(), but only free the value if "free_val" is TRUE.
- */
+/// Like vars_clear(), but only free the value if "free_val" is TRUE.
void vars_clear_ext(hashtab_T *ht, int free_val)
{
int todo;
@@ -9533,10 +9462,8 @@ void vars_clear_ext(hashtab_T *ht, int free_val)
ht->ht_used = 0;
}
-/*
- * Delete a variable from hashtab "ht" at item "hi".
- * Clear the variable value and free the dictitem.
- */
+/// Delete a variable from hashtab "ht" at item "hi".
+/// Clear the variable value and free the dictitem.
static void delete_var(hashtab_T *ht, hashitem_T *hi)
{
dictitem_T *di = TV_DICT_HI2DI(hi);
@@ -9546,9 +9473,7 @@ static void delete_var(hashtab_T *ht, hashitem_T *hi)
xfree(di);
}
-/*
- * List the value of one internal variable.
- */
+/// List the value of one internal variable.
static void list_one_var(dictitem_T *v, const char *prefix, int *first)
{
char *const s = encode_tv2echo(&v->di_tv, NULL);
@@ -9981,11 +9906,9 @@ int var_item_copy(const vimconv_T *const conv, typval_T *const from, typval_T *c
return ret;
}
-/*
- * ":echo expr1 ..." print each argument separated with a space, add a
- * newline at the end.
- * ":echon expr1 ..." print each argument plain.
- */
+/// ":echo expr1 ..." print each argument separated with a space, add a
+/// newline at the end.
+/// ":echon expr1 ..." print each argument plain.
void ex_echo(exarg_T *eap)
{
char_u *arg = eap->arg;
@@ -10059,21 +9982,17 @@ void ex_echo(exarg_T *eap)
}
}
-/*
- * ":echohl {name}".
- */
+/// ":echohl {name}".
void ex_echohl(exarg_T *eap)
{
echo_attr = syn_name2attr(eap->arg);
}
-/*
- * ":execute expr1 ..." execute the result of an expression.
- * ":echomsg expr1 ..." Print a message
- * ":echoerr expr1 ..." Print an error
- * Each gets spaces around each argument and a newline at the end for
- * echo commands
- */
+/// ":execute expr1 ..." execute the result of an expression.
+/// ":echomsg expr1 ..." Print a message
+/// ":echoerr expr1 ..." Print an error
+/// Each gets spaces around each argument and a newline at the end for
+/// echo commands
void ex_execute(exarg_T *eap)
{
char_u *arg = eap->arg;
@@ -10150,12 +10069,12 @@ void ex_execute(exarg_T *eap)
eap->nextcmd = check_nextcmd(arg);
}
-/*
- * Skip over the name of an option: "&option", "&g:option" or "&l:option".
- * "arg" points to the "&" or '+' when called, to "option" when returning.
- * Returns NULL when no option name found. Otherwise pointer to the char
- * after the option name.
- */
+/// Skip over the name of an option: "&option", "&g:option" or "&l:option".
+///
+/// @param arg points to the "&" or '+' when called, to "option" when returning.
+///
+/// @return NULL when no option name found. Otherwise pointer to the char
+/// after the option name.
static const char *find_option_end(const char **const arg, int *const opt_flags)
{
const char *p = *arg;
@@ -10218,9 +10137,7 @@ void func_do_profile(ufunc_T *fp)
fp->uf_profiling = TRUE;
}
-/*
- * Dump the profiling results for all functions in file "fd".
- */
+/// Dump the profiling results for all functions in file "fd".
void func_dump_profile(FILE *fd)
{
hashitem_T *hi;
@@ -10340,9 +10257,7 @@ static void prof_func_line(FILE *fd, int count, proftime_T *total, proftime_T *s
}
}
-/*
- * Compare function for total time sorting.
- */
+/// Compare function for total time sorting.
static int prof_total_cmp(const void *s1, const void *s2)
{
ufunc_T *p1 = *(ufunc_T **)s1;
@@ -10350,9 +10265,7 @@ static int prof_total_cmp(const void *s1, const void *s2)
return profile_cmp(p1->uf_tm_total, p2->uf_tm_total);
}
-/*
- * Compare function for self time sorting.
- */
+/// Compare function for self time sorting.
static int prof_self_cmp(const void *s1, const void *s2)
{
ufunc_T *p1 = *(ufunc_T **)s1;
@@ -10434,12 +10347,10 @@ bool script_autoload(const char *const name, const size_t name_len, const bool r
return ret;
}
-/*
- * Called when starting to read a function line.
- * "sourcing_lnum" must be correct!
- * When skipping lines it may not actually be executed, but we won't find out
- * until later and we need to store the time now.
- */
+/// Called when starting to read a function line.
+/// "sourcing_lnum" must be correct!
+/// When skipping lines it may not actually be executed, but we won't find out
+/// until later and we need to store the time now.
void func_line_start(void *cookie)
{
funccall_T *fcp = (funccall_T *)cookie;
@@ -10459,9 +10370,7 @@ void func_line_start(void *cookie)
}
}
-/*
- * Called when actually executing a function line.
- */
+/// Called when actually executing a function line.
void func_line_exec(void *cookie)
{
funccall_T *fcp = (funccall_T *)cookie;
@@ -10472,9 +10381,7 @@ void func_line_exec(void *cookie)
}
}
-/*
- * Called when done with a function line.
- */
+/// Called when done with a function line.
void func_line_end(void *cookie)
{
funccall_T *fcp = (funccall_T *)cookie;
@@ -10609,10 +10516,8 @@ int store_session_globals(FILE *fd)
return OK;
}
-/*
- * Display script name where an item was last set.
- * Should only be invoked when 'verbose' is non-zero.
- */
+/// Display script name where an item was last set.
+/// Should only be invoked when 'verbose' is non-zero.
void last_set_msg(sctx_T script_ctx)
{
const LastSet last_set = (LastSet){
@@ -10965,7 +10870,8 @@ repeat:
/// Perform a substitution on "str" with pattern "pat" and substitute "sub".
/// When "sub" is NULL "expr" is used, must be a VAR_FUNC or VAR_PARTIAL.
/// "flags" can be "g" to do a global substitute.
-/// Returns an allocated string, NULL for error.
+///
+/// @return an allocated string, NULL for error.
char_u *do_string_sub(char_u *str, char_u *pat, char_u *sub, typval_T *expr, char_u *flags)
{
int sublen;
@@ -11301,7 +11207,7 @@ void invoke_prompt_callback(void)
tv_clear(&rettv);
}
-// Return true When the interrupt callback was invoked.
+/// @return true when the interrupt callback was invoked.
bool invoke_prompt_interrupt(void)
{
typval_T rettv;
diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c
index 85c49c20e7..6e98f229b2 100644
--- a/src/nvim/eval/funcs.c
+++ b/src/nvim/eval/funcs.c
@@ -31,6 +31,7 @@
#include "nvim/fileio.h"
#include "nvim/fold.h"
#include "nvim/globals.h"
+#include "nvim/highlight_group.h"
#include "nvim/if_cscope.h"
#include "nvim/indent.h"
#include "nvim/indent_c.h"
@@ -175,7 +176,7 @@ char_u *get_expr_name(expand_T *xp, int idx)
///
/// @param[in] name Name of the function.
///
-/// Returns pointer to the function definition or NULL if not found.
+/// @return pointer to the function definition or NULL if not found.
const VimLFuncDef *find_internal_func(const char *const name)
FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_PURE FUNC_ATTR_NONNULL_ALL
{
@@ -229,9 +230,7 @@ int call_internal_method(const char_u *const fname, const int argcount, typval_T
return ERROR_NONE;
}
-/*
- * Return TRUE for a non-zero Number and a non-empty String.
- */
+/// @return TRUE for a non-zero Number and a non-empty String.
static int non_zero_arg(typval_T *argvars)
{
return ((argvars[0].v_type == VAR_NUMBER
@@ -243,11 +242,11 @@ static int non_zero_arg(typval_T *argvars)
&& *argvars[0].vval.v_string != NUL));
}
-// Apply a floating point C function on a typval with one float_T.
-//
-// Some versions of glibc on i386 have an optimization that makes it harder to
-// call math functions indirectly from inside an inlined function, causing
-// compile-time errors. Avoid `inline` in that case. #3072
+/// Apply a floating point C function on a typval with one float_T.
+///
+/// Some versions of glibc on i386 have an optimization that makes it harder to
+/// call math functions indirectly from inside an inlined function, causing
+/// compile-time errors. Avoid `inline` in that case. #3072
static void float_op_wrapper(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
float_T f;
@@ -293,9 +292,7 @@ end:
api_clear_error(&err);
}
-/*
- * "abs(expr)" function
- */
+/// "abs(expr)" function
static void f_abs(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
if (argvars[0].v_type == VAR_FLOAT) {
@@ -315,9 +312,7 @@ static void f_abs(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
}
-/*
- * "add(list, item)" function
- */
+/// "add(list, item)" function
static void f_add(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
rettv->vval.v_number = 1; // Default: failed.
@@ -345,9 +340,7 @@ static void f_add(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
}
-/*
- * "and(expr, expr)" function
- */
+/// "and(expr, expr)" function
static void f_and(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
rettv->vval.v_number = tv_get_number_chk(&argvars[0], NULL)
@@ -363,7 +356,7 @@ static void f_api_info(typval_T *argvars, typval_T *rettv, FunPtr fptr)
api_free_dictionary(metadata);
}
-// "append(lnum, string/list)" function
+/// "append(lnum, string/list)" function
static void f_append(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
const linenr_T lnum = tv_get_lnum(&argvars[0]);
@@ -371,7 +364,7 @@ static void f_append(typval_T *argvars, typval_T *rettv, FunPtr fptr)
set_buffer_lines(curbuf, lnum, true, &argvars[1], rettv);
}
-// "appendbufline(buf, lnum, string/list)" function
+/// "appendbufline(buf, lnum, string/list)" function
static void f_appendbufline(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
buf_T *const buf = tv_get_buf(&argvars[0], false);
@@ -403,9 +396,7 @@ static void f_argc(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
}
-/*
- * "argidx()" function
- */
+/// "argidx()" function
static void f_argidx(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
rettv->vval.v_number = curwin->w_arg_idx;
@@ -421,9 +412,7 @@ static void f_arglistid(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
}
-/*
- * "argv(nr)" function
- */
+/// "argv(nr)" function
static void f_argv(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
aentry_T *arglist = NULL;
@@ -458,31 +447,31 @@ static void f_argv(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
}
-// "assert_beeps(cmd [, error])" function
+/// "assert_beeps(cmd [, error])" function
static void f_assert_beeps(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
rettv->vval.v_number = assert_beeps(argvars, false);
}
-// "assert_nobeep(cmd [, error])" function
+/// "assert_nobeep(cmd [, error])" function
static void f_assert_nobeep(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
rettv->vval.v_number = assert_beeps(argvars, true);
}
-// "assert_equal(expected, actual[, msg])" function
+/// "assert_equal(expected, actual[, msg])" function
static void f_assert_equal(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
rettv->vval.v_number = assert_equal_common(argvars, ASSERT_EQUAL);
}
-// "assert_equalfile(fname-one, fname-two[, msg])" function
+/// "assert_equalfile(fname-one, fname-two[, msg])" function
static void f_assert_equalfile(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
rettv->vval.v_number = assert_equalfile(argvars);
}
-// "assert_notequal(expected, actual[, msg])" function
+/// "assert_notequal(expected, actual[, msg])" function
static void f_assert_notequal(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
rettv->vval.v_number = assert_equal_common(argvars, ASSERT_NOTEQUAL);
@@ -536,15 +525,13 @@ static void f_assert_notmatch(typval_T *argvars, typval_T *rettv, FunPtr fptr)
rettv->vval.v_number = assert_match_common(argvars, ASSERT_NOTMATCH);
}
-// "assert_true(actual[, msg])" function
+/// "assert_true(actual[, msg])" function
static void f_assert_true(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
rettv->vval.v_number = assert_bool(argvars, true);
}
-/*
- * "atan2()" function
- */
+/// "atan2()" function
static void f_atan2(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
float_T fx;
@@ -558,27 +545,21 @@ static void f_atan2(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
}
-/*
- * "browse(save, title, initdir, default)" function
- */
+/// "browse(save, title, initdir, default)" function
static void f_browse(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
rettv->vval.v_string = NULL;
rettv->v_type = VAR_STRING;
}
-/*
- * "browsedir(title, initdir)" function
- */
+/// "browsedir(title, initdir)" function
static void f_browsedir(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
f_browse(argvars, rettv, NULL);
}
-/*
- * Find a buffer by number or exact name.
- */
+/// Find a buffer by number or exact name.
static buf_T *find_buffer(typval_T *avar)
{
buf_T *buf = NULL;
@@ -605,7 +586,7 @@ static buf_T *find_buffer(typval_T *avar)
return buf;
}
-// "bufadd(expr)" function
+/// "bufadd(expr)" function
static void f_bufadd(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
char_u *name = (char_u *)tv_get_string(&argvars[0]);
@@ -613,17 +594,13 @@ static void f_bufadd(typval_T *argvars, typval_T *rettv, FunPtr fptr)
rettv->vval.v_number = buflist_add(*name == NUL ? NULL : name, 0);
}
-/*
- * "bufexists(expr)" function
- */
+/// "bufexists(expr)" function
static void f_bufexists(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
rettv->vval.v_number = (find_buffer(&argvars[0]) != NULL);
}
-/*
- * "buflisted(expr)" function
- */
+/// "buflisted(expr)" function
static void f_buflisted(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
buf_T *buf;
@@ -632,7 +609,7 @@ static void f_buflisted(typval_T *argvars, typval_T *rettv, FunPtr fptr)
rettv->vval.v_number = (buf != NULL && buf->b_p_bl);
}
-// "bufload(expr)" function
+/// "bufload(expr)" function
static void f_bufload(typval_T *argvars, typval_T *unused, FunPtr fptr)
{
buf_T *buf = get_buf_arg(&argvars[0]);
@@ -647,9 +624,7 @@ static void f_bufload(typval_T *argvars, typval_T *unused, FunPtr fptr)
}
}
-/*
- * "bufloaded(expr)" function
- */
+/// "bufloaded(expr)" function
static void f_bufloaded(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
buf_T *buf;
@@ -658,9 +633,7 @@ static void f_bufloaded(typval_T *argvars, typval_T *rettv, FunPtr fptr)
rettv->vval.v_number = (buf != NULL && buf->b_ml.ml_mfp != NULL);
}
-/*
- * "bufname(expr)" function
- */
+/// "bufname(expr)" function
static void f_bufname(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
const buf_T *buf;
@@ -676,9 +649,7 @@ static void f_bufname(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
}
-/*
- * "bufnr(expr)" function
- */
+/// "bufnr(expr)" function
static void f_bufnr(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
const buf_T *buf;
@@ -750,9 +721,7 @@ static void f_bufwinnr(typval_T *argvars, typval_T *rettv, FunPtr fptr)
buf_win_common(argvars, rettv, true);
}
-/*
- * Get buffer by number or pattern.
- */
+/// Get buffer by number or pattern.
buf_T *tv_get_buf(typval_T *tv, int curtab_only)
{
char_u *name = tv->vval.v_string;
@@ -820,9 +789,7 @@ buf_T *get_buf_arg(typval_T *arg)
return buf;
}
-/*
- * "byte2line(byte)" function
- */
+/// "byte2line(byte)" function
static void f_byte2line(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
long boff = tv_get_number(&argvars[0]) - 1;
@@ -857,17 +824,13 @@ static void byteidx(typval_T *argvars, typval_T *rettv, int comp)
rettv->vval.v_number = (varnumber_T)(t - str);
}
-/*
- * "byteidx()" function
- */
+/// "byteidx()" function
static void f_byteidx(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
byteidx(argvars, rettv, FALSE);
}
-/*
- * "byteidxcomp()" function
- */
+/// "byteidxcomp()" function
static void f_byteidxcomp(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
byteidx(argvars, rettv, TRUE);
@@ -919,15 +882,13 @@ static void f_call(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
}
-/*
- * "changenr()" function
- */
+/// "changenr()" function
static void f_changenr(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
rettv->vval.v_number = curbuf->b_u_seq_cur;
}
-// "chanclose(id[, stream])" function
+/// "chanclose(id[, stream])" function
static void f_chanclose(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
rettv->v_type = VAR_NUMBER;
@@ -966,7 +927,7 @@ static void f_chanclose(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
}
-// "chansend(id, data)" function
+/// "chansend(id, data)" function
static void f_chansend(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
rettv->v_type = VAR_NUMBER;
@@ -1007,9 +968,7 @@ static void f_chansend(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
}
-/*
- * "char2nr(string)" function
- */
+/// "char2nr(string)" function
static void f_char2nr(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
if (argvars[1].v_type != VAR_UNKNOWN) {
@@ -1021,9 +980,10 @@ static void f_char2nr(typval_T *argvars, typval_T *rettv, FunPtr fptr)
rettv->vval.v_number = utf_ptr2char((const char_u *)tv_get_string(&argvars[0]));
}
-/// Get the current cursor column and store it in 'rettv'. If 'charcol' is true,
-/// returns the character index of the column. Otherwise, returns the byte index
-/// of the column.
+/// Get the current cursor column and store it in 'rettv'.
+///
+/// @return the character index of the column if 'charcol' is true,
+/// otherwise the byte index of the column.
static void get_col(typval_T *argvars, typval_T *rettv, bool charcol)
{
colnr_T col = 0;
@@ -1064,7 +1024,7 @@ static void f_charcol(typval_T *argvars, typval_T *rettv, FunPtr fptr)
get_col(argvars, rettv, true);
}
-// "charidx()" function
+/// "charidx()" function
static void f_charidx(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
rettv->vval.v_number = -1;
@@ -1110,7 +1070,7 @@ static void f_charidx(typval_T *argvars, typval_T *rettv, FunPtr fptr)
rettv->vval.v_number = len > 0 ? len - 1 : 0;
}
-// "chdir(dir)" function
+/// "chdir(dir)" function
static void f_chdir(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
char_u *cwd;
@@ -1147,9 +1107,7 @@ static void f_chdir(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
}
-/*
- * "cindent(lnum)" function
- */
+/// "cindent(lnum)" function
static void f_cindent(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
pos_T pos;
@@ -1180,9 +1138,7 @@ static win_T *get_optional_window(typval_T *argvars, int idx)
return win;
}
-/*
- * "clearmatches()" function
- */
+/// "clearmatches()" function
static void f_clearmatches(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
win_T *win = get_optional_window(argvars, 0);
@@ -1198,9 +1154,7 @@ static void f_col(typval_T *argvars, typval_T *rettv, FunPtr fptr)
get_col(argvars, rettv, false);
}
-/*
- * "complete()" function
- */
+/// "complete()" function
static void f_complete(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
if ((State & INSERT) == 0) {
@@ -1227,17 +1181,13 @@ static void f_complete(typval_T *argvars, typval_T *rettv, FunPtr fptr)
set_completion(startcol - 1, argvars[1].vval.v_list);
}
-/*
- * "complete_add()" function
- */
+/// "complete_add()" function
static void f_complete_add(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
rettv->vval.v_number = ins_compl_add_tv(&argvars[0], 0, false);
}
-/*
- * "complete_check()" function
- */
+/// "complete_check()" function
static void f_complete_check(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
int saved = RedrawingDisabled;
@@ -1248,7 +1198,7 @@ static void f_complete_check(typval_T *argvars, typval_T *rettv, FunPtr fptr)
RedrawingDisabled = saved;
}
-// "complete_info()" function
+/// "complete_info()" function
static void f_complete_info(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
tv_dict_alloc_ret(rettv);
@@ -1265,9 +1215,7 @@ static void f_complete_info(typval_T *argvars, typval_T *rettv, FunPtr fptr)
get_complete_info(what_list, rettv->vval.v_dict);
}
-/*
- * "confirm(message, buttons[, default [, type]])" function
- */
+/// "confirm(message, buttons[, default [, type]])" function
static void f_confirm(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
char buf[NUMBUFLEN];
@@ -1322,17 +1270,13 @@ static void f_confirm(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
}
-/*
- * "copy()" function
- */
+/// "copy()" function
static void f_copy(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
var_item_copy(NULL, &argvars[0], rettv, false, 0);
}
-/*
- * "count()" function
- */
+/// "count()" function
static void f_count(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
long n = 0;
@@ -1423,11 +1367,9 @@ static void f_count(typval_T *argvars, typval_T *rettv, FunPtr fptr)
rettv->vval.v_number = n;
}
-/*
- * "cscope_connection([{num} , {dbpath} [, {prepend}]])" function
- *
- * Checks the existence of a cscope connection.
- */
+/// "cscope_connection([{num} , {dbpath} [, {prepend}]])" function
+///
+/// Checks the existence of a cscope connection.
static void f_cscope_connection(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
int num = 0;
@@ -1559,7 +1501,7 @@ static void f_ctxsize(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// Set the cursor position.
-/// If 'charcol' is true, then use the column number as a character offet.
+/// If 'charcol' is true, then use the column number as a character offset.
/// Otherwise use the column number as a byte offset.
static void set_cursorpos(typval_T *argvars, typval_T *rettv, bool charcol)
{
@@ -1622,13 +1564,14 @@ static void set_cursorpos(typval_T *argvars, typval_T *rettv, bool charcol)
/// "cursor(list)"
///
/// Moves the cursor to the specified line and column.
-/// Returns 0 when the position could be set, -1 otherwise.
+///
+/// @return 0 when the position could be set, -1 otherwise.
static void f_cursor(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
set_cursorpos(argvars, rettv, false);
}
-// "debugbreak()" function
+/// "debugbreak()" function
static void f_debugbreak(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
int pid;
@@ -1652,7 +1595,7 @@ static void f_debugbreak(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
}
-// "deepcopy()" function
+/// "deepcopy()" function
static void f_deepcopy(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
int noref = 0;
@@ -1669,7 +1612,7 @@ static void f_deepcopy(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
}
-// "delete()" function
+/// "delete()" function
static void f_delete(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
rettv->vval.v_number = -1;
@@ -1705,7 +1648,7 @@ static void f_delete(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
}
-// dictwatcheradd(dict, key, funcref) function
+/// dictwatcheradd(dict, key, funcref) function
static void f_dictwatcheradd(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
if (check_secure()) {
@@ -1743,7 +1686,7 @@ static void f_dictwatcheradd(typval_T *argvars, typval_T *rettv, FunPtr fptr)
callback);
}
-// dictwatcherdel(dict, key, funcref) function
+/// dictwatcherdel(dict, key, funcref) function
static void f_dictwatcherdel(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
if (check_secure()) {
@@ -1852,25 +1795,19 @@ static void f_deletebufline(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
}
-/*
- * "did_filetype()" function
- */
+/// "did_filetype()" function
static void f_did_filetype(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
rettv->vval.v_number = did_filetype;
}
-/*
- * "diff_filler()" function
- */
+/// "diff_filler()" function
static void f_diff_filler(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
rettv->vval.v_number = MAX(0, diff_check(curwin, tv_get_lnum(argvars)));
}
-/*
- * "diff_hlID()" function
- */
+/// "diff_hlID()" function
static void f_diff_hlID(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
linenr_T lnum = tv_get_lnum(argvars);
@@ -1922,9 +1859,7 @@ static void f_diff_hlID(typval_T *argvars, typval_T *rettv, FunPtr fptr)
rettv->vval.v_number = hlID == (hlf_T)0 ? 0 : (int)(hlID + 1);
}
-/*
- * "empty({expr})" function
- */
+/// "empty({expr})" function
static void f_empty(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
bool n = true;
@@ -2021,9 +1956,7 @@ static void f_environ(typval_T *argvars, typval_T *rettv, FunPtr fptr)
os_free_fullenv(env);
}
-/*
- * "escape({string}, {chars})" function
- */
+/// "escape({string}, {chars})" function
static void f_escape(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
char buf[NUMBUFLEN];
@@ -2047,9 +1980,7 @@ static void f_getenv(typval_T *argvars, typval_T *rettv, FunPtr fptr)
rettv->v_type = VAR_STRING;
}
-/*
- * "eval()" function
- */
+/// "eval()" function
static void f_eval(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
const char *s = tv_get_string_chk(&argvars[0]);
@@ -2070,17 +2001,13 @@ static void f_eval(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
}
-/*
- * "eventhandler()" function
- */
+/// "eventhandler()" function
static void f_eventhandler(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
rettv->vval.v_number = vgetc_busy;
}
-/*
- * "executable()" function
- */
+/// "executable()" function
static void f_executable(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
if (tv_check_for_string(&argvars[0]) == FAIL) {
@@ -2188,21 +2115,22 @@ static void execute_common(typval_T *argvars, typval_T *rettv, FunPtr fptr, int
capture_ga = save_capture_ga;
}
-// "execute(command)" function
+/// "execute(command)" function
static void f_execute(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
execute_common(argvars, rettv, fptr, 0);
}
-// "win_execute(win_id, command)" function
+/// "win_execute(win_id, command)" function
static void f_win_execute(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
- tabpage_T *tp;
- win_T *wp = win_id2wp_tp(argvars, &tp);
// Return an empty string if something fails.
rettv->v_type = VAR_STRING;
rettv->vval.v_string = NULL;
+ int id = tv_get_number(argvars);
+ tabpage_T *tp;
+ win_T *wp = win_id2wp_tp(id, &tp);
if (wp != NULL && tp != NULL) {
WIN_EXECUTE(wp, tp, execute_common(argvars, rettv, fptr, 1));
}
@@ -2223,9 +2151,7 @@ static void f_exepath(typval_T *argvars, typval_T *rettv, FunPtr fptr)
rettv->vval.v_string = (char_u *)path;
}
-/*
- * "exists()" function
- */
+/// "exists()" function
static void f_exists(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
int n = false;
@@ -2265,9 +2191,7 @@ static void f_exists(typval_T *argvars, typval_T *rettv, FunPtr fptr)
rettv->vval.v_number = n;
}
-/*
- * "expand()" function
- */
+/// "expand()" function
static void f_expand(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
size_t len;
@@ -2352,8 +2276,8 @@ static void f_menu_get(typval_T *argvars, typval_T *rettv, FunPtr fptr)
menu_get((char_u *)tv_get_string(&argvars[0]), modes, rettv->vval.v_list);
}
-// "expandcmd()" function
-// Expand all the special characters in a command string.
+/// "expandcmd()" function
+/// Expand all the special characters in a command string.
static void f_expandcmd(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
char *errormsg = NULL;
@@ -2413,10 +2337,8 @@ static void f_flatten(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
}
-/*
- * "extend(list, list [, idx])" function
- * "extend(dict, dict [, action])" function
- */
+/// "extend(list, list [, idx])" function
+/// "extend(dict, dict [, action])" function
static void f_extend(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
const char *const arg_errmsg = N_("extend() argument");
@@ -2493,9 +2415,7 @@ static void f_extend(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
}
-/*
- * "feedkeys()" function
- */
+/// "feedkeys()" function
static void f_feedkeys(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
// This is not allowed in the sandbox. If the commands would still be
@@ -2524,10 +2444,9 @@ static void f_filereadable(typval_T *argvars, typval_T *rettv, FunPtr fptr)
(*p && !os_isdir((const char_u *)p) && os_file_is_readable(p));
}
-/*
- * Return 0 for not writable, 1 for writable file, 2 for a dir which we have
- * rights to write into.
- */
+/// @return 0 for not writable
+/// 1 for writable file
+/// 2 for a dir which we have rights to write into.
static void f_filewritable(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
const char *filename = tv_get_string(&argvars[0]);
@@ -2594,33 +2513,25 @@ static void findfilendir(typval_T *argvars, typval_T *rettv, int find_what)
}
-/*
- * "filter()" function
- */
+/// "filter()" function
static void f_filter(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
filter_map(argvars, rettv, FALSE);
}
-/*
- * "finddir({fname}[, {path}[, {count}]])" function
- */
+/// "finddir({fname}[, {path}[, {count}]])" function
static void f_finddir(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
findfilendir(argvars, rettv, FINDFILE_DIR);
}
-/*
- * "findfile({fname}[, {path}[, {count}]])" function
- */
+/// "findfile({fname}[, {path}[, {count}]])" function
static void f_findfile(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
findfilendir(argvars, rettv, FINDFILE_FILE);
}
-/*
- * "float2nr({float})" function
- */
+/// "float2nr({float})" function
static void f_float2nr(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
float_T f;
@@ -2636,9 +2547,7 @@ static void f_float2nr(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
}
-/*
- * "fmod()" function
- */
+/// "fmod()" function
static void f_fmod(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
float_T fx;
@@ -2652,18 +2561,14 @@ static void f_fmod(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
}
-/*
- * "fnameescape({string})" function
- */
+/// "fnameescape({string})" function
static void f_fnameescape(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
rettv->vval.v_string = (char_u *)vim_strsave_fnameescape(tv_get_string(&argvars[0]), false);
rettv->v_type = VAR_STRING;
}
-/*
- * "fnamemodify({fname}, {mods})" function
- */
+/// "fnamemodify({fname}, {mods})" function
static void f_fnamemodify(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
char_u *fbuf = NULL;
@@ -2692,9 +2597,7 @@ static void f_fnamemodify(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
-/*
- * "foldclosed()" function
- */
+/// "foldclosed()" function
static void foldclosed_both(typval_T *argvars, typval_T *rettv, int end)
{
const linenr_T lnum = tv_get_lnum(argvars);
@@ -2713,25 +2616,19 @@ static void foldclosed_both(typval_T *argvars, typval_T *rettv, int end)
rettv->vval.v_number = -1;
}
-/*
- * "foldclosed()" function
- */
+/// "foldclosed()" function
static void f_foldclosed(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
foldclosed_both(argvars, rettv, FALSE);
}
-/*
- * "foldclosedend()" function
- */
+/// "foldclosedend()" function
static void f_foldclosedend(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
foldclosed_both(argvars, rettv, TRUE);
}
-/*
- * "foldlevel()" function
- */
+/// "foldlevel()" function
static void f_foldlevel(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
const linenr_T lnum = tv_get_lnum(argvars);
@@ -2740,9 +2637,7 @@ static void f_foldlevel(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
}
-/*
- * "foldtext()" function
- */
+/// "foldtext()" function
static void f_foldtext(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
linenr_T foldstart;
@@ -2795,9 +2690,7 @@ static void f_foldtext(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
}
-/*
- * "foldtextresult(lnum)" function
- */
+/// "foldtextresult(lnum)" function
static void f_foldtextresult(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
char_u *text;
@@ -2828,9 +2721,7 @@ static void f_foldtextresult(typval_T *argvars, typval_T *rettv, FunPtr fptr)
entered = false;
}
-/*
- * "foreground()" function
- */
+/// "foreground()" function
static void f_foreground(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
}
@@ -2857,9 +2748,7 @@ static void f_garbagecollect(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
}
-/*
- * "get()" function
- */
+/// "get()" function
static void f_get(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
listitem_T *li;
@@ -3019,12 +2908,12 @@ static void f_getbufinfo(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
}
-/*
- * Get line or list of lines from buffer "buf" into "rettv".
- * Return a range (from start to end) of lines in rettv from the specified
- * buffer.
- * If 'retlist' is TRUE, then the lines are returned as a Vim List.
- */
+/// Get line or list of lines from buffer "buf" into "rettv".
+///
+/// @param retlist if TRUE, then the lines are returned as a Vim List.
+///
+/// @return range (from start to end) of lines in rettv from the specified
+/// buffer.
static void get_buffer_lines(buf_T *buf, linenr_T start, linenr_T end, int retlist, typval_T *rettv)
{
rettv->v_type = (retlist ? VAR_LIST : VAR_STRING);
@@ -3057,9 +2946,7 @@ static void get_buffer_lines(buf_T *buf, linenr_T start, linenr_T end, int retli
}
}
-/*
- * "getbufline()" function
- */
+/// "getbufline()" function
static void f_getbufline(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
buf_T *const buf = tv_get_buf_from_arg(&argvars[0]);
@@ -3072,9 +2959,7 @@ static void f_getbufline(typval_T *argvars, typval_T *rettv, FunPtr fptr)
get_buffer_lines(buf, lnum, end, true, rettv);
}
-/*
- * "getbufvar()" function
- */
+/// "getbufvar()" function
static void f_getbufvar(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
bool done = false;
@@ -3134,7 +3019,7 @@ f_getbufvar_end:
}
}
-// "getchangelist()" function
+/// "getchangelist()" function
static void f_getchangelist(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
tv_list_alloc_ret(rettv, 2);
@@ -3174,7 +3059,7 @@ static void f_getchangelist(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
}
-// "getchar()" and "getcharstr()" functions
+/// "getchar()" and "getcharstr()" functions
static void getchar_common(typval_T *argvars, typval_T *rettv)
FUNC_ATTR_NONNULL_ALL
{
@@ -3276,13 +3161,13 @@ static void getchar_common(typval_T *argvars, typval_T *rettv)
}
}
-// "getchar()" function
+/// "getchar()" function
static void f_getchar(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
getchar_common(argvars, rettv);
}
-// "getcharstr()" function
+/// "getcharstr()" function
static void f_getcharstr(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
getchar_common(argvars, rettv);
@@ -3302,9 +3187,7 @@ static void f_getcharstr(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
}
-/*
- * "getcharmod()" function
- */
+/// "getcharmod()" function
static void f_getcharmod(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
rettv->vval.v_number = mod_mask;
@@ -3371,9 +3254,7 @@ static void f_getcharpos(typval_T *argvars, typval_T *rettv, FunPtr fptr)
getpos_both(argvars, rettv, false, true);
}
-/*
- * "getcharsearch()" function
- */
+/// "getcharsearch()" function
static void f_getcharsearch(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
tv_dict_alloc_ret(rettv);
@@ -3385,26 +3266,20 @@ static void f_getcharsearch(typval_T *argvars, typval_T *rettv, FunPtr fptr)
tv_dict_add_nr(dict, S_LEN("until"), last_csearch_until());
}
-/*
- * "getcmdline()" function
- */
+/// "getcmdline()" function
static void f_getcmdline(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
rettv->v_type = VAR_STRING;
rettv->vval.v_string = get_cmdline_str();
}
-/*
- * "getcmdpos()" function
- */
+/// "getcmdpos()" function
static void f_getcmdpos(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
rettv->vval.v_number = get_cmdline_pos() + 1;
}
-/*
- * "getcmdtype()" function
- */
+/// "getcmdtype()" function
static void f_getcmdtype(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
rettv->v_type = VAR_STRING;
@@ -3412,9 +3287,7 @@ static void f_getcmdtype(typval_T *argvars, typval_T *rettv, FunPtr fptr)
rettv->vval.v_string[0] = get_cmdline_type();
}
-/*
- * "getcmdwintype()" function
- */
+/// "getcmdwintype()" function
static void f_getcmdwintype(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
rettv->v_type = VAR_STRING;
@@ -3423,7 +3296,7 @@ static void f_getcmdwintype(typval_T *argvars, typval_T *rettv, FunPtr fptr)
rettv->vval.v_string[0] = cmdwin_type;
}
-// "getcompletion()" function
+/// "getcompletion()" function
static void f_getcompletion(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
char_u *pat;
@@ -3622,18 +3495,14 @@ static void f_getcwd(typval_T *argvars, typval_T *rettv, FunPtr fptr)
xfree(cwd);
}
-/*
- * "getfontname()" function
- */
+/// "getfontname()" function
static void f_getfontname(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
rettv->v_type = VAR_STRING;
rettv->vval.v_string = NULL;
}
-/*
- * "getfperm({fname})" function
- */
+/// "getfperm({fname})" function
static void f_getfperm(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
char *perm = NULL;
@@ -3653,9 +3522,7 @@ static void f_getfperm(typval_T *argvars, typval_T *rettv, FunPtr fptr)
rettv->vval.v_string = (char_u *)perm;
}
-/*
- * "getfsize({fname})" function
- */
+/// "getfsize({fname})" function
static void f_getfsize(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
const char *fname = tv_get_string(&argvars[0]);
@@ -3680,9 +3547,7 @@ static void f_getfsize(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
}
-/*
- * "getftime({fname})" function
- */
+/// "getftime({fname})" function
static void f_getftime(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
const char *fname = tv_get_string(&argvars[0]);
@@ -3695,9 +3560,7 @@ static void f_getftime(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
}
-/*
- * "getftype({fname})" function
- */
+/// "getftype({fname})" function
static void f_getftype(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
char_u *type = NULL;
@@ -3731,7 +3594,7 @@ static void f_getftype(typval_T *argvars, typval_T *rettv, FunPtr fptr)
rettv->vval.v_string = type;
}
-// "getjumplist()" function
+/// "getjumplist()" function
static void f_getjumplist(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
tv_list_alloc_ret(rettv, kListLenMayKnow);
@@ -3762,9 +3625,7 @@ static void f_getjumplist(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
}
-/*
- * "getline(lnum, [end])" function
- */
+/// "getline(lnum, [end])" function
static void f_getline(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
linenr_T end;
@@ -3808,9 +3669,7 @@ static void f_getmarklist(typval_T *argvars, typval_T *rettv, FunPtr fptr)
get_buf_local_marks(buf, rettv->vval.v_list);
}
-/*
- * "getmatches()" function
- */
+/// "getmatches()" function
static void f_getmatches(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
matchitem_T *cur;
@@ -3865,7 +3724,7 @@ static void f_getmatches(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
}
-// "getmousepos()" function
+/// "getmousepos()" function
static void f_getmousepos(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
dict_T *d;
@@ -3876,7 +3735,7 @@ static void f_getmousepos(typval_T *argvars, typval_T *rettv, FunPtr fptr)
varnumber_T winid = 0;
varnumber_T winrow = 0;
varnumber_T wincol = 0;
- linenr_T line = 0;
+ linenr_T lnum = 0;
varnumber_T column = 0;
tv_dict_alloc_ret(rettv);
@@ -3887,7 +3746,7 @@ static void f_getmousepos(typval_T *argvars, typval_T *rettv, FunPtr fptr)
wp = mouse_find_win(&grid, &row, &col);
if (wp != NULL) {
- int height = wp->w_height + wp->w_status_height;
+ int height = wp->w_height + wp->w_hsep_height + wp->w_status_height;
// The height is adjusted by 1 when there is a bottom border. This is not
// necessary for a top border since `row` starts at -1 in that case.
if (row < height + wp->w_border_adj[2]) {
@@ -3895,18 +3754,8 @@ static void f_getmousepos(typval_T *argvars, typval_T *rettv, FunPtr fptr)
winrow = row + 1 + wp->w_border_adj[0]; // Adjust by 1 for top border
wincol = col + 1 + wp->w_border_adj[3]; // Adjust by 1 for left border
if (row >= 0 && row < wp->w_height && col >= 0 && col < wp->w_width) {
- char_u *p;
- int count;
-
- mouse_comp_pos(wp, &row, &col, &line);
-
- // limit to text length plus one
- p = ml_get_buf(wp->w_buffer, line, false);
- count = (int)STRLEN(p);
- if (col > count) {
- col = count;
- }
-
+ (void)mouse_comp_pos(wp, &row, &col, &lnum);
+ col = vcol2col(wp, lnum, col);
column = col + 1;
}
}
@@ -3914,13 +3763,11 @@ static void f_getmousepos(typval_T *argvars, typval_T *rettv, FunPtr fptr)
tv_dict_add_nr(d, S_LEN("winid"), winid);
tv_dict_add_nr(d, S_LEN("winrow"), winrow);
tv_dict_add_nr(d, S_LEN("wincol"), wincol);
- tv_dict_add_nr(d, S_LEN("line"), (varnumber_T)line);
+ tv_dict_add_nr(d, S_LEN("line"), (varnumber_T)lnum);
tv_dict_add_nr(d, S_LEN("column"), column);
}
-/*
- * "getpid()" function
- */
+/// "getpid()" function
static void f_getpid(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
rettv->vval.v_number = os_get_pid();
@@ -4057,9 +3904,7 @@ static void f_gettabinfo(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
}
-/*
- * "gettabvar()" function
- */
+/// "gettabvar()" function
static void f_gettabvar(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
bool done = false;
@@ -4097,15 +3942,13 @@ static void f_gettabvar(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
}
-/*
- * "gettabwinvar()" function
- */
+/// "gettabwinvar()" function
static void f_gettabwinvar(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
getwinvar(argvars, rettv, 1);
}
-// "gettagstack()" function
+/// "gettagstack()" function
static void f_gettagstack(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
win_T *wp = curwin; // default is current window
@@ -4130,7 +3973,7 @@ static void f_getwininfo(typval_T *argvars, typval_T *rettv, FunPtr fptr)
tv_list_alloc_ret(rettv, kListLenMayKnow);
if (argvars[0].v_type != VAR_UNKNOWN) {
- wparg = win_id2wp(argvars);
+ wparg = win_id2wp(tv_get_number(&argvars[0]));
if (wparg == NULL) {
return;
}
@@ -4157,12 +4000,12 @@ static void f_getwininfo(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
}
-// Dummy timer callback. Used by f_wait().
+/// Dummy timer callback. Used by f_wait().
static void dummy_timer_due_cb(TimeWatcher *tw, void *data)
{
}
-// Dummy timer close callback. Used by f_wait().
+/// Dummy timer close callback. Used by f_wait().
static void dummy_timer_close_cb(TimeWatcher *tw, void *data)
{
xfree(tw);
@@ -4225,7 +4068,7 @@ static void f_wait(typval_T *argvars, typval_T *rettv, FunPtr fptr)
time_watcher_close(tw, dummy_timer_close_cb);
}
-// "win_screenpos()" function
+/// "win_screenpos()" function
static void f_win_screenpos(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
tv_list_alloc_ret(rettv, 2);
@@ -4234,9 +4077,7 @@ static void f_win_screenpos(typval_T *argvars, typval_T *rettv, FunPtr fptr)
tv_list_append_number(rettv->vval.v_list, wp == NULL ? 0 : wp->w_wincol + 1);
}
-//
-// Move the window wp into a new split of targetwin in a given direction
-//
+/// Move the window wp into a new split of targetwin in a given direction
static void win_move_into_split(win_T *wp, win_T *targetwin, int size, int flags)
{
int dir;
@@ -4274,7 +4115,7 @@ static void win_move_into_split(win_T *wp, win_T *targetwin, int size, int flags
}
}
-// "win_splitmove()" function
+/// "win_splitmove()" function
static void f_win_splitmove(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
win_T *wp;
@@ -4314,7 +4155,7 @@ static void f_win_splitmove(typval_T *argvars, typval_T *rettv, FunPtr fptr)
win_move_into_split(wp, targetwin, size, flags);
}
-// "getwinpos({timeout})" function
+/// "getwinpos({timeout})" function
static void f_getwinpos(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
tv_list_alloc_ret(rettv, 2);
@@ -4322,17 +4163,13 @@ static void f_getwinpos(typval_T *argvars, typval_T *rettv, FunPtr fptr)
tv_list_append_number(rettv->vval.v_list, -1);
}
-/*
- * "getwinposx()" function
- */
+/// "getwinposx()" function
static void f_getwinposx(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
rettv->vval.v_number = -1;
}
-/*
- * "getwinposy()" function
- */
+/// "getwinposy()" function
static void f_getwinposy(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
rettv->vval.v_number = -1;
@@ -4344,9 +4181,7 @@ static void f_getwinvar(typval_T *argvars, typval_T *rettv, FunPtr fptr)
getwinvar(argvars, rettv, 0);
}
-/*
- * "glob()" function
- */
+/// "glob()" function
static void f_glob(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
int options = WILD_SILENT|WILD_USE_NL;
@@ -4444,7 +4279,7 @@ static void f_globpath(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
}
-// "glob2regpat()" function
+/// "glob2regpat()" function
static void f_glob2regpat(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
const char *const pat = tv_get_string_chk(&argvars[0]); // NULL on type error
@@ -4780,9 +4615,7 @@ static void f_haslocaldir(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
}
-/*
- * "hasmapto()" function
- */
+/// "hasmapto()" function
static void f_hasmapto(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
const char *mode;
@@ -4805,9 +4638,7 @@ static void f_hasmapto(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
}
-/*
- * "histadd()" function
- */
+/// "histadd()" function
static void f_histadd(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
HistoryType histype;
@@ -4830,9 +4661,7 @@ static void f_histadd(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
}
-/*
- * "histdel()" function
- */
+/// "histdel()" function
static void f_histdel(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
int n;
@@ -4855,9 +4684,7 @@ static void f_histdel(typval_T *argvars, typval_T *rettv, FunPtr fptr)
rettv->vval.v_number = n;
}
-/*
- * "histget()" function
- */
+/// "histget()" function
static void f_histget(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
HistoryType type;
@@ -4879,9 +4706,7 @@ static void f_histget(typval_T *argvars, typval_T *rettv, FunPtr fptr)
rettv->v_type = VAR_STRING;
}
-/*
- * "histnr()" function
- */
+/// "histnr()" function
static void f_histnr(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
const char *const history = tv_get_string_chk(&argvars[0]);
@@ -4894,25 +4719,19 @@ static void f_histnr(typval_T *argvars, typval_T *rettv, FunPtr fptr)
rettv->vval.v_number = i;
}
-/*
- * "highlightID(name)" function
- */
+/// "highlightID(name)" function
static void f_hlID(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
rettv->vval.v_number = syn_name2id(tv_get_string(&argvars[0]));
}
-/*
- * "highlight_exists()" function
- */
+/// "highlight_exists()" function
static void f_hlexists(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
rettv->vval.v_number = highlight_exists(tv_get_string(&argvars[0]));
}
-/*
- * "hostname()" function
- */
+/// "hostname()" function
static void f_hostname(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
char hostname[256];
@@ -4922,9 +4741,7 @@ static void f_hostname(typval_T *argvars, typval_T *rettv, FunPtr fptr)
rettv->vval.v_string = vim_strsave((char_u *)hostname);
}
-/*
- * iconv() function
- */
+/// iconv() function
static void f_iconv(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
vimconv_T vimconv;
@@ -4952,9 +4769,7 @@ static void f_iconv(typval_T *argvars, typval_T *rettv, FunPtr fptr)
xfree(to);
}
-/*
- * "indent()" function
- */
+/// "indent()" function
static void f_indent(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
const linenr_T lnum = tv_get_lnum(argvars);
@@ -4965,9 +4780,7 @@ static void f_indent(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
}
-/*
- * "index()" function
- */
+/// "index()" function
static void f_index(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
long idx = 0;
@@ -5041,26 +4854,20 @@ static void f_index(typval_T *argvars, typval_T *rettv, FunPtr fptr)
static bool inputsecret_flag = false;
-/*
- * "input()" function
- * Also handles inputsecret() when inputsecret is set.
- */
+/// "input()" function
+/// Also handles inputsecret() when inputsecret is set.
static void f_input(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
get_user_input(argvars, rettv, FALSE, inputsecret_flag);
}
-/*
- * "inputdialog()" function
- */
+/// "inputdialog()" function
static void f_inputdialog(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
get_user_input(argvars, rettv, TRUE, inputsecret_flag);
}
-/*
- * "inputlist()" function
- */
+/// "inputlist()" function
static void f_inputlist(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
int selected;
@@ -5126,9 +4933,7 @@ static void f_inputsecret(typval_T *argvars, typval_T *rettv, FunPtr fptr)
inputsecret_flag = false;
}
-/*
- * "insert()" function
- */
+/// "insert()" function
static void f_insert(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
list_T *l;
@@ -5200,32 +5005,26 @@ static void f_insert(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
}
-// "interrupt()" function
+/// "interrupt()" function
static void f_interrupt(typval_T *argvars FUNC_ATTR_UNUSED, typval_T *rettv FUNC_ATTR_UNUSED,
FunPtr fptr FUNC_ATTR_UNUSED)
{
got_int = true;
}
-/*
- * "invert(expr)" function
- */
+/// "invert(expr)" function
static void f_invert(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
rettv->vval.v_number = ~tv_get_number_chk(&argvars[0], NULL);
}
-/*
- * "isdirectory()" function
- */
+/// "isdirectory()" function
static void f_isdirectory(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
rettv->vval.v_number = os_isdir((const char_u *)tv_get_string(&argvars[0]));
}
-/*
- * "islocked()" function
- */
+/// "islocked()" function
static void f_islocked(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
lval_T lv;
@@ -5268,7 +5067,7 @@ static void f_islocked(typval_T *argvars, typval_T *rettv, FunPtr fptr)
clear_lval(&lv);
}
-// "isinf()" function
+/// "isinf()" function
static void f_isinf(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
if (argvars[0].v_type == VAR_FLOAT
@@ -5277,7 +5076,7 @@ static void f_isinf(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
}
-// "isnan()" function
+/// "isnan()" function
static void f_isnan(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
rettv->vval.v_number = argvars[0].v_type == VAR_FLOAT
@@ -5295,15 +5094,13 @@ static void f_id(typval_T *argvars, typval_T *rettv, FunPtr fptr)
dummy_ap, argvars);
}
-/*
- * "items(dict)" function
- */
+/// "items(dict)" function
static void f_items(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
dict_list(argvars, rettv, 2);
}
-// "jobpid(id)" function
+/// "jobpid(id)" function
static void f_jobpid(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
rettv->v_type = VAR_NUMBER;
@@ -5327,7 +5124,7 @@ static void f_jobpid(typval_T *argvars, typval_T *rettv, FunPtr fptr)
rettv->vval.v_number = proc->pid;
}
-// "jobresize(job, width, height)" function
+/// "jobresize(job, width, height)" function
static void f_jobresize(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
rettv->v_type = VAR_NUMBER;
@@ -5474,7 +5271,7 @@ static dict_T *create_environment(const dictitem_T *job_env, const bool clear_en
return env;
}
-// "jobstart()" function
+/// "jobstart()" function
static void f_jobstart(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
rettv->v_type = VAR_NUMBER;
@@ -5595,7 +5392,7 @@ static void f_jobstart(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
}
-// "jobstop()" function
+/// "jobstop()" function
static void f_jobstop(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
rettv->v_type = VAR_NUMBER;
@@ -5628,7 +5425,7 @@ static void f_jobstop(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
}
-// "jobwait(ids[, timeout])" function
+/// "jobwait(ids[, timeout])" function
static void f_jobwait(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
rettv->v_type = VAR_NUMBER;
@@ -5727,9 +5524,7 @@ static void f_jobwait(typval_T *argvars, typval_T *rettv, FunPtr fptr)
rettv->vval.v_list = rv;
}
-/*
- * "join()" function
- */
+/// "join()" function
static void f_join(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
if (argvars[0].v_type != VAR_LIST) {
@@ -5794,17 +5589,13 @@ static void f_json_encode(typval_T *argvars, typval_T *rettv, FunPtr fptr)
rettv->vval.v_string = (char_u *)encode_tv2json(&argvars[0], NULL);
}
-/*
- * "keys()" function
- */
+/// "keys()" function
static void f_keys(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
dict_list(argvars, rettv, 0);
}
-/*
- * "last_buffer_nr()" function.
- */
+/// "last_buffer_nr()" function.
static void f_last_buffer_nr(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
int n = 0;
@@ -5818,9 +5609,7 @@ static void f_last_buffer_nr(typval_T *argvars, typval_T *rettv, FunPtr fptr)
rettv->vval.v_number = n;
}
-/*
- * "len()" function
- */
+/// "len()" function
static void f_len(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
switch (argvars[0].v_type) {
@@ -5893,23 +5682,19 @@ static void libcall_common(typval_T *argvars, typval_T *rettv, int out_type)
}
}
-/*
- * "libcall()" function
- */
+/// "libcall()" function
static void f_libcall(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
libcall_common(argvars, rettv, VAR_STRING);
}
-/*
- * "libcallnr()" function
- */
+/// "libcallnr()" function
static void f_libcallnr(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
libcall_common(argvars, rettv, VAR_NUMBER);
}
-// "line(string, [winid])" function
+/// "line(string, [winid])" function
static void f_line(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
linenr_T lnum = 0;
@@ -5917,10 +5702,10 @@ static void f_line(typval_T *argvars, typval_T *rettv, FunPtr fptr)
int fnum;
if (argvars[1].v_type != VAR_UNKNOWN) {
- tabpage_T *tp;
-
// use window specified in the second argument
- win_T *wp = win_id2wp_tp(&argvars[1], &tp);
+ int id = (int)tv_get_number(&argvars[1]);
+ tabpage_T *tp;
+ win_T *wp = win_id2wp_tp(id, &tp);
if (wp != NULL && tp != NULL) {
switchwin_T switchwin;
if (switch_win_noblock(&switchwin, wp, tp, true) == OK) {
@@ -5940,9 +5725,7 @@ static void f_line(typval_T *argvars, typval_T *rettv, FunPtr fptr)
rettv->vval.v_number = lnum;
}
-/*
- * "line2byte(lnum)" function
- */
+/// "line2byte(lnum)" function
static void f_line2byte(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
const linenr_T lnum = tv_get_lnum(argvars);
@@ -5956,9 +5739,7 @@ static void f_line2byte(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
}
-/*
- * "lispindent(lnum)" function
- */
+/// "lispindent(lnum)" function
static void f_lispindent(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
const pos_T pos = curwin->w_cursor;
@@ -5972,7 +5753,7 @@ static void f_lispindent(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
}
-// "list2str()" function
+/// "list2str()" function
static void f_list2str(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
garray_T ga;
@@ -6001,9 +5782,7 @@ static void f_list2str(typval_T *argvars, typval_T *rettv, FunPtr fptr)
rettv->vval.v_string = ga.ga_data;
}
-/*
- * "localtime()" function
- */
+/// "localtime()" function
static void f_localtime(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
rettv->vval.v_number = (varnumber_T)time(NULL);
@@ -6089,25 +5868,19 @@ static void f_luaeval(typval_T *argvars, typval_T *rettv, FunPtr fptr)
nlua_typval_eval(cstr_as_string((char *)str), &argvars[1], rettv);
}
-/*
- * "map()" function
- */
+/// "map()" function
static void f_map(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
filter_map(argvars, rettv, TRUE);
}
-/*
- * "maparg()" function
- */
+/// "maparg()" function
static void f_maparg(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
get_maparg(argvars, rettv, TRUE);
}
-/*
- * "mapcheck()" function
- */
+/// "mapcheck()" function
static void f_mapcheck(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
get_maparg(argvars, rettv, FALSE);
@@ -6329,17 +6102,13 @@ theend:
p_cpo = save_cpo;
}
-/*
- * "match()" function
- */
+/// "match()" function
static void f_match(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
find_some_match(argvars, rettv, kSomeMatch);
}
-/*
- * "matchadd()" function
- */
+/// "matchadd()" function
static void f_matchadd(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
char grpbuf[NUMBUFLEN];
@@ -6431,9 +6200,7 @@ static void f_matchaddpos(typval_T *argvars, typval_T *rettv, FunPtr fptr)
rettv->vval.v_number = match_add(win, group, NULL, prio, id, l, conceal_char);
}
-/*
- * "matcharg()" function
- */
+/// "matcharg()" function
static void f_matcharg(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
const int id = tv_get_number(&argvars[0]);
@@ -6456,9 +6223,7 @@ static void f_matcharg(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
}
-/*
- * "matchdelete()" function
- */
+/// "matchdelete()" function
static void f_matchdelete(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
win_T *win = get_optional_window(argvars, 1);
@@ -6470,25 +6235,19 @@ static void f_matchdelete(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
}
-/*
- * "matchend()" function
- */
+/// "matchend()" function
static void f_matchend(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
find_some_match(argvars, rettv, kSomeMatchEnd);
}
-/*
- * "matchlist()" function
- */
+/// "matchlist()" function
static void f_matchlist(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
find_some_match(argvars, rettv, kSomeMatchList);
}
-/*
- * "matchstr()" function
- */
+/// "matchstr()" function
static void f_matchstr(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
find_some_match(argvars, rettv, kSomeMatchStr);
@@ -6549,25 +6308,19 @@ static void max_min(const typval_T *const tv, typval_T *const rettv, const bool
rettv->vval.v_number = n;
}
-/*
- * "max()" function
- */
+/// "max()" function
static void f_max(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
max_min(argvars, rettv, TRUE);
}
-/*
- * "min()" function
- */
+/// "min()" function
static void f_min(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
max_min(argvars, rettv, FALSE);
}
-/*
- * "mkdir()" function
- */
+/// "mkdir()" function
static void f_mkdir(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
int prot = 0755; // -V536
@@ -6782,9 +6535,7 @@ static void f_msgpackparse(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
}
-/*
- * "nextnonblank()" function
- */
+/// "nextnonblank()" function
static void f_nextnonblank(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
linenr_T lnum;
@@ -6801,9 +6552,7 @@ static void f_nextnonblank(typval_T *argvars, typval_T *rettv, FunPtr fptr)
rettv->vval.v_number = lnum;
}
-/*
- * "nr2char()" function
- */
+/// "nr2char()" function
static void f_nr2char(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
if (argvars[1].v_type != VAR_UNKNOWN) {
@@ -6834,18 +6583,14 @@ static void f_nr2char(typval_T *argvars, typval_T *rettv, FunPtr fptr)
rettv->vval.v_string = xmemdupz(buf, (size_t)len);
}
-/*
- * "or(expr, expr)" function
- */
+/// "or(expr, expr)" function
static void f_or(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
rettv->vval.v_number = tv_get_number_chk(&argvars[0], NULL)
| tv_get_number_chk(&argvars[1], NULL);
}
-/*
- * "pathshorten()" function
- */
+/// "pathshorten()" function
static void f_pathshorten(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
int trim_len = 1;
@@ -6867,9 +6612,7 @@ static void f_pathshorten(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
}
-/*
- * "pow()" function
- */
+/// "pow()" function
static void f_pow(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
float_T fx;
@@ -6883,9 +6626,7 @@ static void f_pow(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
}
-/*
- * "prevnonblank()" function
- */
+/// "prevnonblank()" function
static void f_prevnonblank(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
linenr_T lnum = tv_get_lnum(argvars);
@@ -6899,9 +6640,7 @@ static void f_prevnonblank(typval_T *argvars, typval_T *rettv, FunPtr fptr)
rettv->vval.v_number = lnum;
}
-/*
- * "printf()" function
- */
+/// "printf()" function
static void f_printf(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
rettv->v_type = VAR_STRING;
@@ -6924,7 +6663,7 @@ static void f_printf(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
}
-// "prompt_setcallback({buffer}, {callback})" function
+/// "prompt_setcallback({buffer}, {callback})" function
static void f_prompt_setcallback(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
buf_T *buf;
@@ -6948,7 +6687,7 @@ static void f_prompt_setcallback(typval_T *argvars, typval_T *rettv, FunPtr fptr
buf->b_prompt_callback = prompt_callback;
}
-// "prompt_setinterrupt({buffer}, {callback})" function
+/// "prompt_setinterrupt({buffer}, {callback})" function
static void f_prompt_setinterrupt(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
buf_T *buf;
@@ -6992,7 +6731,7 @@ static void f_prompt_getprompt(typval_T *argvars, typval_T *rettv, FunPtr fptr)
rettv->vval.v_string = vim_strsave(buf_prompt_text(buf));
}
-// "prompt_setprompt({buffer}, {text})" function
+/// "prompt_setprompt({buffer}, {text})" function
static void f_prompt_setprompt(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
buf_T *buf;
@@ -7011,16 +6750,14 @@ static void f_prompt_setprompt(typval_T *argvars, typval_T *rettv, FunPtr fptr)
buf->b_prompt_text = vim_strsave(text);
}
-// "pum_getpos()" function
+/// "pum_getpos()" function
static void f_pum_getpos(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
tv_dict_alloc_ret(rettv);
pum_set_event_info(rettv->vval.v_dict);
}
-/*
- * "pumvisible()" function
- */
+/// "pumvisible()" function
static void f_pumvisible(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
if (pum_visible()) {
@@ -7198,15 +6935,13 @@ static void f_perleval(typval_T *argvars, typval_T *rettv, FunPtr fptr)
script_host_eval("perl", argvars, rettv);
}
-// "rubyeval()" function
+/// "rubyeval()" function
static void f_rubyeval(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
script_host_eval("ruby", argvars, rettv);
}
-/*
- * "range()" function
- */
+/// "range()" function
static void f_range(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
varnumber_T start;
@@ -7241,7 +6976,7 @@ static void f_range(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
}
-// Evaluate "expr" for readdir().
+/// Evaluate "expr" for readdir().
static varnumber_T readdir_checkitem(typval_T *expr, const char *name)
{
typval_T save_val;
@@ -7272,7 +7007,7 @@ theend:
return retval;
}
-// "readdir()" function
+/// "readdir()" function
static void f_readdir(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
typval_T *expr;
@@ -7328,9 +7063,7 @@ static void f_readdir(typval_T *argvars, typval_T *rettv, FunPtr fptr)
ga_clear_strings(&ga);
}
-/*
- * "readfile()" function
- */
+/// "readfile()" function
static void f_readfile(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
bool binary = false;
@@ -7564,13 +7297,13 @@ static void f_getreginfo(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
}
-// "reg_executing()" function
+/// "reg_executing()" function
static void f_reg_executing(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
return_register(reg_executing, rettv);
}
-// "reg_recording()" function
+/// "reg_recording()" function
static void f_reg_recording(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
return_register(reg_recording, rettv);
@@ -7672,9 +7405,7 @@ static void f_reltimestr(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
}
-/*
- * "remove()" function
- */
+/// "remove()" function
static void f_remove(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
list_T *l;
@@ -7808,9 +7539,7 @@ static void f_remove(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
}
-/*
- * "rename({from}, {to})" function
- */
+/// "rename({from}, {to})" function
static void f_rename(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
if (check_secure()) {
@@ -7822,9 +7551,7 @@ static void f_rename(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
}
-/*
- * "repeat()" function
- */
+/// "repeat()" function
static void f_repeat(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
varnumber_T n = tv_get_number(&argvars[1]);
@@ -7861,9 +7588,7 @@ static void f_repeat(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
}
-/*
- * "resolve()" function
- */
+/// "resolve()" function
static void f_resolve(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
rettv->v_type = VAR_STRING;
@@ -8032,9 +7757,7 @@ static void f_resolve(typval_T *argvars, typval_T *rettv, FunPtr fptr)
simplify_filename(rettv->vval.v_string);
}
-/*
- * "reverse({list})" function
- */
+/// "reverse({list})" function
static void f_reverse(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
if (argvars[0].v_type == VAR_BLOB) {
@@ -8059,7 +7782,7 @@ static void f_reverse(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
}
-/// "reduce(list, { accumlator, element -> value } [, initial])" function
+/// "reduce(list, { accumulator, element -> value } [, initial])" function
static void f_reduce(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
if (argvars[0].v_type != VAR_LIST && argvars[0].v_type != VAR_BLOB) {
@@ -8164,11 +7887,10 @@ static void f_reduce(typval_T *argvars, typval_T *rettv, FunPtr fptr)
#define SP_END 0x40 ///< leave cursor at end of match
#define SP_COLUMN 0x80 ///< start at cursor column
-/*
- * Get flags for a search function.
- * Possibly sets "p_ws".
- * Returns BACKWARD, FORWARD or zero (for an error).
- */
+/// Get flags for a search function.
+/// Possibly sets "p_ws".
+///
+/// @return BACKWARD, FORWARD or zero (for an error).
static int get_search_arg(typval_T *varp, int *flagsp)
{
int dir = FORWARD;
@@ -8226,7 +7948,7 @@ static int get_search_arg(typval_T *varp, int *flagsp)
return dir;
}
-// Shared by search() and searchpos() functions.
+/// Shared by search() and searchpos() functions.
static int search_cmn(typval_T *argvars, pos_T *match_pos, int *flagsp)
{
int flags;
@@ -8362,7 +8084,7 @@ theend:
return retval;
}
-// "rpcnotify()" function
+/// "rpcnotify()" function
static void f_rpcnotify(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
rettv->v_type = VAR_NUMBER;
@@ -8397,7 +8119,7 @@ static void f_rpcnotify(typval_T *argvars, typval_T *rettv, FunPtr fptr)
rettv->vval.v_number = 1;
}
-// "rpcrequest()" function
+/// "rpcrequest()" function
static void f_rpcrequest(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
rettv->v_type = VAR_NUMBER;
@@ -8495,7 +8217,7 @@ end:
api_clear_error(&err);
}
-// "rpcstart()" function (DEPRECATED)
+/// "rpcstart()" function (DEPRECATED)
static void f_rpcstart(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
rettv->v_type = VAR_NUMBER;
@@ -8562,7 +8284,7 @@ static void f_rpcstart(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
}
-// "rpcstop()" function
+/// "rpcstop()" function
static void f_rpcstop(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
rettv->v_type = VAR_NUMBER;
@@ -8592,7 +8314,7 @@ static void f_rpcstop(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
}
-// "screenattr()" function
+/// "screenattr()" function
static void f_screenattr(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
int c;
@@ -8610,7 +8332,7 @@ static void f_screenattr(typval_T *argvars, typval_T *rettv, FunPtr fptr)
rettv->vval.v_number = c;
}
-// "screenchar()" function
+/// "screenchar()" function
static void f_screenchar(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
int c;
@@ -8628,7 +8350,7 @@ static void f_screenchar(typval_T *argvars, typval_T *rettv, FunPtr fptr)
rettv->vval.v_number = c;
}
-// "screenchars()" function
+/// "screenchars()" function
static void f_screenchars(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
int row = tv_get_number_chk(&argvars[0], NULL) - 1;
@@ -8653,9 +8375,9 @@ static void f_screenchars(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
}
-// "screencol()" function
-//
-// First column is 1 to be consistent with virtcol().
+/// "screencol()" function
+///
+/// First column is 1 to be consistent with virtcol().
static void f_screencol(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
rettv->vval.v_number = ui_current_col() + 1;
@@ -8687,13 +8409,13 @@ static void f_screenpos(typval_T *argvars, typval_T *rettv, FunPtr fptr)
tv_dict_add_nr(dict, S_LEN("endcol"), ecol);
}
-// "screenrow()" function
+/// "screenrow()" function
static void f_screenrow(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
rettv->vval.v_number = ui_current_row() + 1;
}
-// "screenstring()" function
+/// "screenstring()" function
static void f_screenstring(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
rettv->vval.v_string = NULL;
@@ -8709,7 +8431,7 @@ static void f_screenstring(typval_T *argvars, typval_T *rettv, FunPtr fptr)
rettv->vval.v_string = vim_strsave(grid->chars[grid->line_offset[row] + col]);
}
-// "search()" function
+/// "search()" function
static void f_search(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
int flags = 0;
@@ -8717,9 +8439,7 @@ static void f_search(typval_T *argvars, typval_T *rettv, FunPtr fptr)
rettv->vval.v_number = search_cmn(argvars, NULL, &flags);
}
-/*
- * "searchdecl()" function
- */
+/// "searchdecl()" function
static void f_searchdecl(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
int locally = 1;
@@ -8741,9 +8461,7 @@ static void f_searchdecl(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
}
-/*
- * Used by searchpair() and searchpairpos()
- */
+/// Used by searchpair() and searchpairpos()
static int searchpair_cmn(typval_T *argvars, pos_T *match_pos)
{
bool save_p_ws = p_ws;
@@ -8817,17 +8535,13 @@ theend:
return retval;
}
-/*
- * "searchpair()" function
- */
+/// "searchpair()" function
static void f_searchpair(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
rettv->vval.v_number = searchpair_cmn(argvars, NULL);
}
-/*
- * "searchpairpos()" function
- */
+/// "searchpairpos()" function
static void f_searchpairpos(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
pos_T match_pos;
@@ -9013,9 +8727,7 @@ long do_searchpair(const char *spat, const char *mpat, const char *epat, int dir
return retval;
}
-/*
- * "searchpos()" function
- */
+/// "searchpos()" function
static void f_searchpos(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
pos_T match_pos;
@@ -9129,9 +8841,7 @@ static void f_setbufline(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
}
-/*
- * "setbufvar()" function
- */
+/// "setbufvar()" function
static void f_setbufvar(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
if (check_secure()
@@ -9176,7 +8886,7 @@ static void f_setbufvar(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
/// Set the cursor or mark position.
-/// If 'charpos' is TRUE, then use the column number as a character offet.
+/// If 'charpos' is TRUE, then use the column number as a character offset.
/// Otherwise use the column number as a byte offset.
static void set_position(typval_T *argvars, typval_T *rettv, bool charpos)
{
@@ -9248,9 +8958,7 @@ static void f_setcharsearch(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
}
-/*
- * "setcmdpos()" function
- */
+/// "setcmdpos()" function
static void f_setcmdpos(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
const int pos = (int)tv_get_number(&argvars[0]) - 1;
@@ -9312,9 +9020,7 @@ static void f_setfperm(typval_T *argvars, typval_T *rettv, FunPtr fptr)
rettv->vval.v_number = os_setperm(fname, mode) == OK;
}
-/*
- * "setline()" function
- */
+/// "setline()" function
static void f_setline(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
linenr_T lnum = tv_get_lnum(&argvars[0]);
@@ -9402,9 +9108,7 @@ skip_args:
recursive--;
}
-/*
- * "setloclist()" function
- */
+/// "setloclist()" function
static void f_setloclist(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
win_T *win;
@@ -9417,9 +9121,7 @@ static void f_setloclist(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
}
-/*
- * "setmatches()" function
- */
+/// "setmatches()" function
static void f_setmatches(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
dict_T *d;
@@ -9528,9 +9230,7 @@ static void f_setpos(typval_T *argvars, typval_T *rettv, FunPtr fptr)
set_position(argvars, rettv, false);
}
-/*
- * "setqflist()" function
- */
+/// "setqflist()" function
static void f_setqflist(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
set_qf_ll_list(NULL, argvars, rettv);
@@ -9566,9 +9266,7 @@ static int get_yank_type(char_u **const pp, MotionType *const yank_type, long *c
return OK;
}
-/*
- * "setreg()" function
- */
+/// "setreg()" function
static void f_setreg(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
bool append = false;
@@ -9712,9 +9410,7 @@ free_lstval:
}
}
-/*
- * "settabvar()" function
- */
+/// "settabvar()" function
static void f_settabvar(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
rettv->vval.v_number = 0;
@@ -9745,15 +9441,13 @@ static void f_settabvar(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
}
-/*
- * "settabwinvar()" function
- */
+/// "settabwinvar()" function
static void f_settabwinvar(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
setwinvar(argvars, rettv, 1);
}
-// "settagstack()" function
+/// "settagstack()" function
static void f_settagstack(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
static char *e_invact2 = N_("E962: Invalid action: '%s'");
@@ -9806,9 +9500,7 @@ static void f_settagstack(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
}
-/*
- * "setwinvar()" function
- */
+/// "setwinvar()" function
static void f_setwinvar(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
setwinvar(argvars, rettv, 0);
@@ -9825,9 +9517,7 @@ static void f_sha256(typval_T *argvars, typval_T *rettv, FunPtr fptr)
rettv->v_type = VAR_STRING;
}
-/*
- * "shellescape({string})" function
- */
+/// "shellescape({string})" function
static void f_shellescape(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
const bool do_special = non_zero_arg(&argvars[1]);
@@ -9838,9 +9528,7 @@ static void f_shellescape(typval_T *argvars, typval_T *rettv, FunPtr fptr)
rettv->v_type = VAR_STRING;
}
-/*
- * shiftwidth() function
- */
+/// shiftwidth() function
static void f_shiftwidth(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
rettv->vval.v_number = 0;
@@ -10124,9 +9812,7 @@ static void f_sign_unplacelist(typval_T *argvars, typval_T *rettv, FunPtr fptr)
});
}
-/*
- * "simplify()" function
- */
+/// "simplify()" function
static void f_simplify(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
const char *const p = tv_get_string(&argvars[0]);
@@ -10203,9 +9889,7 @@ static sortinfo_T *sortinfo = NULL;
#define ITEM_COMPARE_FAIL 999
-/*
- * Compare functions for f_sort() and f_uniq() below.
- */
+/// Compare functions for f_sort() and f_uniq() below.
static int item_compare(const void *s1, const void *s2, bool keep_zero)
{
ListSortItem *const si1 = (ListSortItem *)s1;
@@ -10369,9 +10053,7 @@ static int item_compare2_not_keeping_zero(const void *s1, const void *s2)
return item_compare2(s1, s2, false);
}
-/*
- * "sort({list})" function
- */
+/// "sort({list})" function
static void do_sort_uniq(typval_T *argvars, typval_T *rettv, bool sort)
{
ListSortItem *ptrs;
@@ -10564,7 +10246,7 @@ static void f_uniq(typval_T *argvars, typval_T *rettv, FunPtr fptr)
do_sort_uniq(argvars, rettv, false);
}
-// "reltimefloat()" function
+/// "reltimefloat()" function
static void f_reltimefloat(typval_T *argvars, typval_T *rettv, FunPtr fptr)
FUNC_ATTR_NONNULL_ALL
{
@@ -10577,9 +10259,7 @@ static void f_reltimefloat(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
}
-/*
- * "soundfold({word})" function
- */
+/// "soundfold({word})" function
static void f_soundfold(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
rettv->v_type = VAR_STRING;
@@ -10587,9 +10267,7 @@ static void f_soundfold(typval_T *argvars, typval_T *rettv, FunPtr fptr)
rettv->vval.v_string = (char_u *)eval_soundfold(s);
}
-/*
- * "spellbadword()" function
- */
+/// "spellbadword()" function
static void f_spellbadword(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
const char *word = "";
@@ -10648,9 +10326,7 @@ static void f_spellbadword(typval_T *argvars, typval_T *rettv, FunPtr fptr)
NULL), -1);
}
-/*
- * "spellsuggest()" function
- */
+/// "spellsuggest()" function
static void f_spellsuggest(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
bool typeerr = false;
@@ -10805,9 +10481,7 @@ static void f_stdpath(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
}
-/*
- * "str2float()" function
- */
+/// "str2float()" function
static void f_str2float(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
char_u *p = skipwhite((const char_u *)tv_get_string(&argvars[0]));
@@ -10823,7 +10497,7 @@ static void f_str2float(typval_T *argvars, typval_T *rettv, FunPtr fptr)
rettv->v_type = VAR_FLOAT;
}
-// "str2list()" function
+/// "str2list()" function
static void f_str2list(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
tv_list_alloc_ret(rettv, kListLenUnknown);
@@ -10834,7 +10508,7 @@ static void f_str2list(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
}
-// "str2nr()" function
+/// "str2nr()" function
static void f_str2nr(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
int base = 10;
@@ -10877,9 +10551,7 @@ static void f_str2nr(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
}
-/*
- * "strftime({format}[, {time}])" function
- */
+/// "strftime({format}[, {time}])" function
static void f_strftime(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
time_t seconds;
@@ -10931,7 +10603,7 @@ static void f_strftime(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
}
-// "strgetchar()" function
+/// "strgetchar()" function
static void f_strgetchar(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
rettv->vval.v_number = -1;
@@ -10959,9 +10631,7 @@ static void f_strgetchar(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
}
-/*
- * "stridx()" function
- */
+/// "stridx()" function
static void f_stridx(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
rettv->vval.v_number = -1;
@@ -10993,26 +10663,20 @@ static void f_stridx(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
}
-/*
- * "string()" function
- */
+/// "string()" function
static void f_string(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
rettv->v_type = VAR_STRING;
rettv->vval.v_string = (char_u *)encode_tv2string(&argvars[0], NULL);
}
-/*
- * "strlen()" function
- */
+/// "strlen()" function
static void f_strlen(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
rettv->vval.v_number = (varnumber_T)strlen(tv_get_string(&argvars[0]));
}
-/*
- * "strchars()" function
- */
+/// "strchars()" function
static void f_strchars(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
const char *s = tv_get_string(&argvars[0]);
@@ -11035,9 +10699,7 @@ static void f_strchars(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
}
-/*
- * "strdisplaywidth()" function
- */
+/// "strdisplaywidth()" function
static void f_strdisplaywidth(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
const char *const s = tv_get_string(&argvars[0]);
@@ -11050,9 +10712,7 @@ static void f_strdisplaywidth(typval_T *argvars, typval_T *rettv, FunPtr fptr)
rettv->vval.v_number = (varnumber_T)(linetabsize_col(col, (char_u *)s) - col);
}
-/*
- * "strwidth()" function
- */
+/// "strwidth()" function
static void f_strwidth(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
const char *const s = tv_get_string(&argvars[0]);
@@ -11060,7 +10720,7 @@ static void f_strwidth(typval_T *argvars, typval_T *rettv, FunPtr fptr)
rettv->vval.v_number = (varnumber_T)mb_string2cells((const char_u *)s);
}
-// "strcharpart()" function
+/// "strcharpart()" function
static void f_strcharpart(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
const char *const p = tv_get_string(&argvars[0]);
@@ -11114,9 +10774,7 @@ static void f_strcharpart(typval_T *argvars, typval_T *rettv, FunPtr fptr)
rettv->vval.v_string = (char_u *)xstrndup(p + nbyte, (size_t)len);
}
-/*
- * "strpart()" function
- */
+/// "strpart()" function
static void f_strpart(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
bool error = false;
@@ -11162,7 +10820,7 @@ static void f_strpart(typval_T *argvars, typval_T *rettv, FunPtr fptr)
rettv->vval.v_string = (char_u *)xmemdupz(p + n, (size_t)len);
}
-// "strptime({format}, {timestring})" function
+/// "strptime({format}, {timestring})" function
static void f_strptime(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
char fmt_buf[NUMBUFLEN];
@@ -11194,9 +10852,7 @@ static void f_strptime(typval_T *argvars, typval_T *rettv, FunPtr fptr)
xfree(enc);
}
-/*
- * "strridx()" function
- */
+/// "strridx()" function
static void f_strridx(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
char buf[NUMBUFLEN];
@@ -11239,18 +10895,14 @@ static void f_strridx(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
}
-/*
- * "strtrans()" function
- */
+/// "strtrans()" function
static void f_strtrans(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
rettv->v_type = VAR_STRING;
rettv->vval.v_string = (char_u *)transstr(tv_get_string(&argvars[0]), true);
}
-/*
- * "submatch()" function
- */
+/// "submatch()" function
static void f_submatch(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
bool error = false;
@@ -11281,9 +10933,7 @@ static void f_submatch(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
}
-/*
- * "substitute()" function
- */
+/// "substitute()" function
static void f_substitute(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
char patbuf[NUMBUFLEN];
@@ -11352,9 +11002,7 @@ static void f_synID(typval_T *argvars, typval_T *rettv, FunPtr fptr)
rettv->vval.v_number = id;
}
-/*
- * "synIDattr(id, what [, mode])" function
- */
+/// "synIDattr(id, what [, mode])" function
static void f_synIDattr(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
const int id = (int)tv_get_number(&argvars[0]);
@@ -11430,9 +11078,7 @@ static void f_synIDattr(typval_T *argvars, typval_T *rettv, FunPtr fptr)
rettv->vval.v_string = (char_u *)(p == NULL ? p : xstrdup(p));
}
-/*
- * "synIDtrans(id)" function
- */
+/// "synIDtrans(id)" function
static void f_synIDtrans(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
int id = tv_get_number(&argvars[0]);
@@ -11446,9 +11092,7 @@ static void f_synIDtrans(typval_T *argvars, typval_T *rettv, FunPtr fptr)
rettv->vval.v_number = id;
}
-/*
- * "synconcealed(lnum, col)" function
- */
+/// "synconcealed(lnum, col)" function
static void f_synconcealed(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
int syntax_flags = 0;
@@ -11490,9 +11134,7 @@ static void f_synconcealed(typval_T *argvars, typval_T *rettv, FunPtr fptr)
tv_list_append_number(rettv->vval.v_list, matchid);
}
-/*
- * "synstack(lnum, col)" function
- */
+/// "synstack(lnum, col)" function
static void f_synstack(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
tv_list_set_ret(rettv, NULL);
@@ -11528,9 +11170,7 @@ static void f_systemlist(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
-/*
- * "tabpagebuflist()" function
- */
+/// "tabpagebuflist()" function
static void f_tabpagebuflist(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
win_T *wp = NULL;
@@ -11552,9 +11192,7 @@ static void f_tabpagebuflist(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
}
-/*
- * "tabpagenr()" function
- */
+/// "tabpagenr()" function
static void f_tabpagenr(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
int nr = 1;
@@ -11566,9 +11204,7 @@ static void f_tabpagenr(typval_T *argvars, typval_T *rettv, FunPtr fptr)
if (strcmp(arg, "$") == 0) {
nr = tabpage_index(NULL) - 1;
} else if (strcmp(arg, "#") == 0) {
- nr = valid_tabpage(lastused_tabpage)
- ? tabpage_index(lastused_tabpage)
- : nr;
+ nr = valid_tabpage(lastused_tabpage) ? tabpage_index(lastused_tabpage) : 0;
} else {
semsg(_(e_invexpr2), arg);
}
@@ -11580,9 +11216,7 @@ static void f_tabpagenr(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
-/*
- * Common code for tabpagewinnr() and winnr().
- */
+/// Common code for tabpagewinnr() and winnr().
static int get_winnr(tabpage_T *tp, typval_T *argvar)
{
win_T *twin;
@@ -11647,9 +11281,7 @@ static int get_winnr(tabpage_T *tp, typval_T *argvar)
return nr;
}
-/*
- * "tabpagewinnr()" function
- */
+/// "tabpagewinnr()" function
static void f_tabpagewinnr(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
int nr = 1;
@@ -11662,9 +11294,7 @@ static void f_tabpagewinnr(typval_T *argvars, typval_T *rettv, FunPtr fptr)
rettv->vval.v_number = nr;
}
-/*
- * "tagfiles()" function
- */
+/// "tagfiles()" function
static void f_tagfiles(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
char *fname;
@@ -11683,9 +11313,7 @@ static void f_tagfiles(typval_T *argvars, typval_T *rettv, FunPtr fptr)
xfree(fname);
}
-/*
- * "taglist()" function
- */
+/// "taglist()" function
static void f_taglist(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
const char *const tag_pattern = tv_get_string(&argvars[0]);
@@ -11703,16 +11331,14 @@ static void f_taglist(typval_T *argvars, typval_T *rettv, FunPtr fptr)
(char_u *)tag_pattern, (char_u *)fname);
}
-/*
- * "tempname()" function
- */
+/// "tempname()" function
static void f_tempname(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
rettv->v_type = VAR_STRING;
rettv->vval.v_string = vim_tempname();
}
-// "termopen(cmd[, cwd])" function
+/// "termopen(cmd[, cwd])" function
static void f_termopen(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
if (check_secure()) {
@@ -11825,7 +11451,7 @@ static void f_termopen(typval_T *argvars, typval_T *rettv, FunPtr fptr)
channel_create_event(chan, NULL);
}
-// "test_garbagecollect_now()" function
+/// "test_garbagecollect_now()" function
static void f_test_garbagecollect_now(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
// This is dangerous, any Lists and Dicts used internally may be freed
@@ -11833,7 +11459,7 @@ static void f_test_garbagecollect_now(typval_T *argvars, typval_T *rettv, FunPtr
garbage_collect(true);
}
-// "test_write_list_log()" function
+/// "test_write_list_log()" function
static void f_test_write_list_log(typval_T *const argvars, typval_T *const rettv, FunPtr fptr)
{
const char *const fname = tv_get_string_chk(&argvars[0]);
@@ -11916,7 +11542,7 @@ static void f_timer_start(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
-// "timer_stop(timerid)" function
+/// "timer_stop(timerid)" function
static void f_timer_stop(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
if (argvars[0].v_type != VAR_NUMBER) {
@@ -11937,9 +11563,7 @@ static void f_timer_stopall(typval_T *argvars, typval_T *unused, FunPtr fptr)
timer_stop_all();
}
-/*
- * "tolower(string)" function
- */
+/// "tolower(string)" function
static void f_tolower(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
rettv->v_type = VAR_STRING;
@@ -11947,9 +11571,7 @@ static void f_tolower(typval_T *argvars, typval_T *rettv, FunPtr fptr)
false);
}
-/*
- * "toupper(string)" function
- */
+/// "toupper(string)" function
static void f_toupper(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
rettv->v_type = VAR_STRING;
@@ -11957,9 +11579,7 @@ static void f_toupper(typval_T *argvars, typval_T *rettv, FunPtr fptr)
true);
}
-/*
- * "tr(string, fromstr, tostr)" function
- */
+/// "tr(string, fromstr, tostr)" function
static void f_tr(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
char buf[NUMBUFLEN];
@@ -12039,7 +11659,7 @@ error:
return;
}
-// "trim({expr})" function
+/// "trim({expr})" function
static void f_trim(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
char buf1[NUMBUFLEN];
@@ -12122,9 +11742,7 @@ static void f_trim(typval_T *argvars, typval_T *rettv, FunPtr fptr)
rettv->vval.v_string = vim_strnsave(head, tail - head);
}
-/*
- * "type(expr)" function
- */
+/// "type(expr)" function
static void f_type(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
int n = -1;
@@ -12156,9 +11774,7 @@ static void f_type(typval_T *argvars, typval_T *rettv, FunPtr fptr)
rettv->vval.v_number = n;
}
-/*
- * "undofile(name)" function
- */
+/// "undofile(name)" function
static void f_undofile(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
rettv->v_type = VAR_STRING;
@@ -12177,9 +11793,7 @@ static void f_undofile(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
}
-/*
- * "undotree()" function
- */
+/// "undotree()" function
static void f_undotree(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
tv_dict_alloc_ret(rettv);
@@ -12197,17 +11811,13 @@ static void f_undotree(typval_T *argvars, typval_T *rettv, FunPtr fptr)
tv_dict_add_list(dict, S_LEN("entries"), u_eval_tree(curbuf->b_u_oldhead));
}
-/*
- * "values(dict)" function
- */
+/// "values(dict)" function
static void f_values(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
dict_list(argvars, rettv, 1);
}
-/*
- * "virtcol(string)" function
- */
+/// "virtcol(string)" function
static void f_virtcol(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
colnr_T vcol = 0;
@@ -12233,9 +11843,7 @@ static void f_virtcol(typval_T *argvars, typval_T *rettv, FunPtr fptr)
rettv->vval.v_number = vcol;
}
-/*
- * "visualmode()" function
- */
+/// "visualmode()" function
static void f_visualmode(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
char_u str[2];
@@ -12251,9 +11859,7 @@ static void f_visualmode(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
}
-/*
- * "wildmenumode()" function
- */
+/// "wildmenumode()" function
static void f_wildmenumode(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
if (wild_menu_showing || ((State & CMDLINE) && pum_visible())) {
@@ -12367,9 +11973,7 @@ static void f_winbufnr(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
}
-/*
- * "wincol()" function
- */
+/// "wincol()" function
static void f_wincol(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
validate_cursor();
@@ -12387,7 +11991,7 @@ static void f_winheight(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
}
-// "winlayout()" function
+/// "winlayout()" function
static void f_winlayout(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
tabpage_T *tp;
@@ -12406,18 +12010,14 @@ static void f_winlayout(typval_T *argvars, typval_T *rettv, FunPtr fptr)
get_framelayout(tp->tp_topframe, rettv->vval.v_list, true);
}
-/*
- * "winline()" function
- */
+/// "winline()" function
static void f_winline(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
validate_cursor();
rettv->vval.v_number = curwin->w_wrow + 1;
}
-/*
- * "winnr()" function
- */
+/// "winnr()" function
static void f_winnr(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
int nr = 1;
@@ -12426,9 +12026,7 @@ static void f_winnr(typval_T *argvars, typval_T *rettv, FunPtr fptr)
rettv->vval.v_number = nr;
}
-/*
- * "winrestcmd()" function
- */
+/// "winrestcmd()" function
static void f_winrestcmd(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
garray_T ga;
@@ -12455,9 +12053,7 @@ static void f_winrestcmd(typval_T *argvars, typval_T *rettv, FunPtr fptr)
rettv->v_type = VAR_STRING;
}
-/*
- * "winrestview()" function
- */
+/// "winrestview()" function
static void f_winrestview(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
dict_T *dict;
@@ -12508,9 +12104,7 @@ static void f_winrestview(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
}
-/*
- * "winsaveview()" function
- */
+/// "winsaveview()" function
static void f_winsaveview(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
dict_T *dict;
@@ -12541,7 +12135,7 @@ static void f_winwidth(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
}
-// "windowsversion()" function
+/// "windowsversion()" function
static void f_windowsversion(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
rettv->v_type = VAR_STRING;
@@ -12632,9 +12226,8 @@ static void f_writefile(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
}
}
-/*
- * "xor(expr, expr)" function
- */
+
+/// "xor(expr, expr)" function
static void f_xor(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
rettv->vval.v_number = tv_get_number_chk(&argvars[0], NULL)
diff --git a/src/nvim/event/socket.c b/src/nvim/event/socket.c
index 7948a7be83..c20716496f 100644
--- a/src/nvim/event/socket.c
+++ b/src/nvim/event/socket.c
@@ -53,10 +53,8 @@ int socket_watcher_init(Loop *loop, SocketWatcher *watcher, const char *endpoint
uv_getaddrinfo_t request;
int retval = uv_getaddrinfo(&loop->uv, &request, NULL, addr, port,
- &(struct addrinfo){
- .ai_family = AF_UNSPEC,
- .ai_socktype = SOCK_STREAM,
- });
+ &(struct addrinfo){ .ai_family = AF_UNSPEC,
+ .ai_socktype = SOCK_STREAM, });
if (retval != 0) {
ELOG("Host lookup failed: %s", endpoint);
return retval;
@@ -103,10 +101,9 @@ int socket_watcher_start(SocketWatcher *watcher, int backlog, socket_cb cb)
// contain 0 in this case, unless uv_tcp_getsockname() is used first.
uv_tcp_getsockname(&watcher->uv.tcp.handle, (struct sockaddr *)&sas,
&(int){ sizeof(sas) });
- uint16_t port = (uint16_t)(
- (sas.ss_family == AF_INET)
- ? (STRUCT_CAST(struct sockaddr_in, &sas))->sin_port
- : (STRUCT_CAST(struct sockaddr_in6, &sas))->sin6_port);
+ uint16_t port = (uint16_t)((sas.ss_family == AF_INET)
+ ? (STRUCT_CAST(struct sockaddr_in, &sas))->sin_port
+ : (STRUCT_CAST(struct sockaddr_in6, &sas))->sin6_port);
// v:servername uses the string from watcher->addr
size_t len = strlen(watcher->addr);
snprintf(watcher->addr+len, sizeof(watcher->addr)-len, ":%" PRIu16,
diff --git a/src/nvim/ex_cmds.c b/src/nvim/ex_cmds.c
index c7910e148d..ff803c3553 100644
--- a/src/nvim/ex_cmds.c
+++ b/src/nvim/ex_cmds.c
@@ -38,6 +38,7 @@
#include "nvim/garray.h"
#include "nvim/getchar.h"
#include "nvim/highlight.h"
+#include "nvim/highlight_group.h"
#include "nvim/indent.h"
#include "nvim/input.h"
#include "nvim/log.h"
@@ -225,9 +226,7 @@ void do_ascii(const exarg_T *const eap)
msg((char *)IObuff);
}
-/*
- * ":left", ":center" and ":right": align text.
- */
+/// ":left", ":center" and ":right": align text.
void ex_align(exarg_T *eap)
{
pos_T save_curpos;
@@ -324,9 +323,7 @@ void ex_align(exarg_T *eap)
beginline(BL_WHITE | BL_FIX);
}
-/*
- * Get the length of the current line, excluding trailing white space.
- */
+/// @return the length of the current line, excluding trailing white space.
static int linelen(int *has_tab)
{
char_u *line;
@@ -452,7 +449,7 @@ static int sort_compare(const void *s1, const void *s2)
return result;
}
-// ":sort".
+/// ":sort".
void ex_sort(exarg_T *eap)
{
regmatch_T regmatch;
@@ -723,9 +720,7 @@ sortend:
}
}
-/*
- * ":retab".
- */
+/// ":retab".
void ex_retab(exarg_T *eap)
{
linenr_T lnum;
@@ -907,11 +902,9 @@ void ex_retab(exarg_T *eap)
u_clearline();
}
-/*
- * :move command - move lines line1-line2 to line dest
- *
- * return FAIL for failure, OK otherwise
- */
+/// :move command - move lines line1-line2 to line dest
+///
+/// @return FAIL for failure, OK otherwise
int do_move(linenr_T line1, linenr_T line2, linenr_T dest)
{
char_u *str;
@@ -1062,9 +1055,7 @@ int do_move(linenr_T line1, linenr_T line2, linenr_T dest)
return OK;
}
-/*
- * ":copy"
- */
+/// ":copy"
void ex_copy(linenr_T line1, linenr_T line2, linenr_T n)
{
linenr_T count;
@@ -1132,11 +1123,9 @@ void free_prev_shellcmd(void)
#endif
-/*
- * Handle the ":!cmd" command. Also for ":r !cmd" and ":w !cmd"
- * Bangs in the argument are replaced with the previously entered command.
- * Remember the argument.
- */
+/// Handle the ":!cmd" command. Also for ":r !cmd" and ":w !cmd"
+/// Bangs in the argument are replaced with the previously entered command.
+/// Remember the argument.
void do_bang(int addr_count, exarg_T *eap, bool forceit, bool do_in, bool do_out)
FUNC_ATTR_NONNULL_ALL
{
@@ -1684,9 +1673,7 @@ void print_line_no_prefix(linenr_T lnum, int use_number, int list)
msg_prt_line(ml_get(lnum), list);
}
-/*
- * Print a text line. Also in silent mode ("ex -s").
- */
+/// Print a text line. Also in silent mode ("ex -s").
void print_line(linenr_T lnum, int use_number, int list)
{
int save_silent = silent_mode;
@@ -1754,9 +1741,7 @@ int rename_buffer(char_u *new_fname)
return OK;
}
-/*
- * ":file[!] [fname]".
- */
+/// ":file[!] [fname]".
void ex_file(exarg_T *eap)
{
// ":0file" removes the file name. Check for illegal uses ":3file",
@@ -1782,9 +1767,7 @@ void ex_file(exarg_T *eap)
}
}
-/*
- * ":update".
- */
+/// ":update".
void ex_update(exarg_T *eap)
{
if (curbufIsChanged()) {
@@ -1792,9 +1775,7 @@ void ex_update(exarg_T *eap)
}
}
-/*
- * ":write" and ":saveas".
- */
+/// ":write" and ":saveas".
void ex_write(exarg_T *eap)
{
if (eap->cmdidx == CMD_saveas) {
@@ -1810,14 +1791,12 @@ void ex_write(exarg_T *eap)
}
}
-/*
- * write current buffer to file 'eap->arg'
- * if 'eap->append' is TRUE, append to the file
- *
- * if *eap->arg == NUL write to current file
- *
- * return FAIL for failure, OK otherwise
- */
+/// write current buffer to file 'eap->arg'
+/// if 'eap->append' is TRUE, append to the file
+///
+/// if *eap->arg == NUL write to current file
+///
+/// @return FAIL for failure, OK otherwise
int do_write(exarg_T *eap)
{
int other;
@@ -2070,9 +2049,7 @@ int check_overwrite(exarg_T *eap, buf_T *buf, char_u *fname, char_u *ffname, int
return OK;
}
-/*
- * Handle ":wnext", ":wNext" and ":wprevious" commands.
- */
+/// Handle ":wnext", ":wNext" and ":wprevious" commands.
void ex_wnext(exarg_T *eap)
{
int i;
@@ -2089,9 +2066,7 @@ void ex_wnext(exarg_T *eap)
}
}
-/*
- * ":wall", ":wqall" and ":xall": Write all changed files (and exit).
- */
+/// ":wall", ":wqall" and ":xall": Write all changed files (and exit).
void do_wqall(exarg_T *eap)
{
int error = 0;
@@ -2149,8 +2124,9 @@ void do_wqall(exarg_T *eap)
}
}
-// Check the 'write' option.
-// Return true and give a message when it's not st.
+/// Check the 'write' option.
+///
+/// @return true and give a message when it's not st.
bool not_writing(void)
{
if (p_write) {
@@ -2160,11 +2136,9 @@ bool not_writing(void)
return true;
}
-/*
- * Check if a buffer is read-only (either 'readonly' option is set or file is
- * read-only). Ask for overruling in a dialog. Return TRUE and give an error
- * message when the buffer is readonly.
- */
+/// Check if a buffer is read-only (either 'readonly' option is set or file is
+/// read-only). Ask for overruling in a dialog. Return TRUE and give an error
+/// message when the buffer is readonly.
static int check_readonly(int *forceit, buf_T *buf)
{
// Handle a file being readonly when the 'readonly' option is set or when
@@ -2205,15 +2179,16 @@ static int check_readonly(int *forceit, buf_T *buf)
return FALSE;
}
-// Try to abandon the current file and edit a new or existing file.
-// "fnum" is the number of the file, if zero use "ffname_arg"/"sfname_arg".
-// "lnum" is the line number for the cursor in the new file (if non-zero).
-//
-// Return:
-// GETFILE_ERROR for "normal" error,
-// GETFILE_NOT_WRITTEN for "not written" error,
-// GETFILE_SAME_FILE for success
-// GETFILE_OPEN_OTHER for successfully opening another file.
+/// Try to abandon the current file and edit a new or existing file.
+///
+/// @param fnum the number of the file, if zero use "ffname_arg"/"sfname_arg".
+/// @param lnum the line number for the cursor in the new file (if non-zero).
+///
+/// @return:
+/// GETFILE_ERROR for "normal" error,
+/// GETFILE_NOT_WRITTEN for "not written" error,
+/// GETFILE_SAME_FILE for success
+/// GETFILE_OPEN_OTHER for successfully opening another file.
int getfile(int fnum, char_u *ffname_arg, char_u *sfname_arg, int setpm, linenr_T lnum, int forceit)
{
char_u *ffname = ffname_arg;
@@ -2934,9 +2909,7 @@ static void delbuf_msg(char_u *name)
static int append_indent = 0; // autoindent for first line
-/*
- * ":insert" and ":append", also used by ":change"
- */
+/// ":insert" and ":append", also used by ":change"
void ex_append(exarg_T *eap)
{
char_u *theline;
@@ -3078,9 +3051,7 @@ void ex_append(exarg_T *eap)
ex_no_reprint = true;
}
-/*
- * ":change"
- */
+/// ":change"
void ex_change(exarg_T *eap)
{
linenr_T lnum;
@@ -3247,9 +3218,9 @@ void ex_z(exarg_T *eap)
ex_no_reprint = true;
}
-// Check if the secure flag is set (.exrc or .vimrc in current directory).
-// If so, give an error message and return true.
-// Otherwise, return false.
+/// @return true if the secure flag is set (.exrc or .vimrc in current directory)
+/// and also give an error message.
+/// Otherwise, return false.
bool check_secure(void)
{
if (secure) {
@@ -4533,22 +4504,20 @@ static void global_exe_one(char_u *const cmd, const linenr_T lnum)
}
}
-/*
- * Execute a global command of the form:
- *
- * g/pattern/X : execute X on all lines where pattern matches
- * v/pattern/X : execute X on all lines where pattern does not match
- *
- * where 'X' is an EX command
- *
- * The command character (as well as the trailing slash) is optional, and
- * is assumed to be 'p' if missing.
- *
- * This is implemented in two passes: first we scan the file for the pattern and
- * set a mark for each line that (not) matches. Secondly we execute the command
- * for each line that has a mark. This is required because after deleting
- * lines we do not know where to search for the next match.
- */
+/// Execute a global command of the form:
+///
+/// g/pattern/X : execute X on all lines where pattern matches
+/// v/pattern/X : execute X on all lines where pattern does not match
+///
+/// where 'X' is an EX command
+///
+/// The command character (as well as the trailing slash) is optional, and
+/// is assumed to be 'p' if missing.
+///
+/// This is implemented in two passes: first we scan the file for the pattern and
+/// set a mark for each line that (not) matches. Secondly we execute the command
+/// for each line that has a mark. This is required because after deleting
+/// lines we do not know where to search for the next match.
void ex_global(exarg_T *eap)
{
linenr_T lnum; // line number according to old situation
@@ -4764,9 +4733,7 @@ bool prepare_tagpreview(bool undo_sync)
}
-/*
- * ":help": open a read-only window on a help file
- */
+/// ":help": open a read-only window on a help file
void ex_help(exarg_T *eap)
{
char_u *arg;
@@ -4949,11 +4916,10 @@ erret:
}
-/*
- * In an argument search for a language specifiers in the form "@xx".
- * Changes the "@" to NUL if found, and returns a pointer to "xx".
- * Returns NULL if not found.
- */
+/// In an argument search for a language specifiers in the form "@xx".
+/// Changes the "@" to NUL if found, and returns a pointer to "xx".
+///
+/// @return NULL if not found.
char_u *check_help_lang(char_u *arg)
{
int len = (int)STRLEN(arg);
@@ -5019,10 +4985,8 @@ int help_heuristic(char_u *matched_string, int offset, int wrong_case)
return (int)(100 * num_letters + STRLEN(matched_string) + offset);
}
-/*
- * Compare functions for qsort() below, that checks the help heuristics number
- * that has been put after the tagname by find_tags().
- */
+/// Compare functions for qsort() below, that checks the help heuristics number
+/// that has been put after the tagname by find_tags().
static int help_compare(const void *s1, const void *s2)
{
char *p1;
@@ -5033,10 +4997,10 @@ static int help_compare(const void *s1, const void *s2)
return strcmp(p1, p2);
}
-// Find all help tags matching "arg", sort them and return in matches[], with
-// the number of matches in num_matches.
-// The matches will be sorted with a "best" match algorithm.
-// When "keep_lang" is true try keeping the language of the current buffer.
+/// Find all help tags matching "arg", sort them and return in matches[], with
+/// the number of matches in num_matches.
+/// The matches will be sorted with a "best" match algorithm.
+/// When "keep_lang" is true try keeping the language of the current buffer.
int find_help_tags(const char_u *arg, int *num_matches, char_u ***matches, bool keep_lang)
{
int i;
@@ -5308,10 +5272,8 @@ static void prepare_help_buffer(void)
set_buflisted(FALSE);
}
-/*
- * After reading a help file: May cleanup a help buffer when syntax
- * highlighting is not used.
- */
+/// After reading a help file: May cleanup a help buffer when syntax
+/// highlighting is not used.
void fix_help_buffer(void)
{
linenr_T lnum;
@@ -5507,17 +5469,13 @@ void fix_help_buffer(void)
}
}
-/*
- * ":exusage"
- */
+/// ":exusage"
void ex_exusage(exarg_T *eap)
{
do_cmdline_cmd("help ex-cmd-index");
}
-/*
- * ":viusage"
- */
+/// ":viusage"
void ex_viusage(exarg_T *eap)
{
do_cmdline_cmd("help normal-index");
@@ -5826,9 +5784,7 @@ static void helptags_cb(char_u *fname, void *cookie)
do_helptags(fname, *(bool *)cookie, true);
}
-/*
- * ":helptags"
- */
+/// ":helptags"
void ex_helptags(exarg_T *eap)
{
expand_T xpc;
@@ -5857,9 +5813,7 @@ void ex_helptags(exarg_T *eap)
}
}
-/*
- * ":helpclose": Close one help window
- */
+/// ":helpclose": Close one help window
void ex_helpclose(exarg_T *eap)
{
FOR_ALL_WINDOWS_IN_TAB(win, curtab) {
@@ -5873,7 +5827,7 @@ void ex_helpclose(exarg_T *eap)
/// Tries to enter to an existing window of given buffer. If no existing buffer
/// is found, creates a new split.
///
-/// Returns OK/FAIL.
+/// @return OK/FAIL.
int sub_preview_win(buf_T *preview_buf)
{
if (preview_buf != NULL) {
@@ -6115,9 +6069,11 @@ void ex_substitute(exarg_T *eap)
/// Skip over the pattern argument of ":vimgrep /pat/[g][j]".
/// Put the start of the pattern in "*s", unless "s" is NULL.
-/// If "flags" is not NULL put the flags in it: VGR_GLOBAL, VGR_NOJUMP.
-/// If "s" is not NULL terminate the pattern with a NUL.
-/// Return a pointer to the char just past the pattern plus flags.
+///
+/// @param flags if not NULL, put the flags in it: VGR_GLOBAL, VGR_NOJUMP.
+/// @param s if not NULL, terminate the pattern with a NUL.
+///
+/// @return a pointer to the char just past the pattern plus flags.
char_u *skip_vimgrep_pat(char_u *p, char_u **s, int *flags)
{
int c;
diff --git a/src/nvim/ex_cmds2.c b/src/nvim/ex_cmds2.c
index 5c040adc1c..fe1dec7298 100644
--- a/src/nvim/ex_cmds2.c
+++ b/src/nvim/ex_cmds2.c
@@ -436,8 +436,8 @@ static void script_dump_profile(FILE *fd)
}
}
-/// Return true when a function defined in the current script should be
-/// profiled.
+/// @return true when a function defined in the current script should be
+/// profiled.
bool prof_def_func(void)
{
if (current_sctx.sc_sid > 0) {
@@ -492,7 +492,7 @@ void autowrite_all(void)
}
}
-/// Return true if buffer was changed and cannot be abandoned.
+/// @return true if buffer was changed and cannot be abandoned.
/// For flags use the CCGD_ values.
bool check_changed(buf_T *buf, int flags)
{
@@ -616,7 +616,7 @@ bool dialog_close_terminal(buf_T *buf)
return ret == VIM_YES;
}
-/// Return true if the buffer "buf" can be abandoned, either by making it
+/// @return true if the buffer "buf" can be abandoned, either by making it
/// hidden, autowriting it or unloading it.
bool can_abandon(buf_T *buf, int forceit)
{
@@ -771,8 +771,8 @@ theend:
return ret;
}
-/// Return FAIL if there is no file name, OK if there is one.
-/// Give error message for FAIL.
+/// @return FAIL if there is no file name, OK if there is one.
+/// Give error message for FAIL.
int check_fname(void)
{
if (curbuf->b_ffname == NULL) {
@@ -784,7 +784,7 @@ int check_fname(void)
/// Flush the contents of a buffer, unless it has no file name.
///
-/// @return FAIL for failure, OK otherwise
+/// @return FAIL for failure, OK otherwise
int buf_write_all(buf_T *buf, int forceit)
{
int retval;
@@ -808,7 +808,8 @@ int buf_write_all(buf_T *buf, int forceit)
/// Isolate one argument, taking backticks.
/// Changes the argument in-place, puts a NUL after it. Backticks remain.
-/// Return a pointer to the start of the next argument.
+///
+/// @return a pointer to the start of the next argument.
static char_u *do_one_arg(char_u *str)
{
char_u *p;
@@ -859,7 +860,7 @@ static void get_arglist(garray_T *gap, char_u *str, int escaped)
/// Parse a list of arguments (file names), expand them and return in
/// "fnames[fcountp]". When "wig" is true, removes files matching 'wildignore'.
///
-/// @return FAIL or OK.
+/// @return FAIL or OK.
int get_arglist_exp(char_u *str, int *fcountp, char_u ***fnamesp, bool wig)
{
garray_T ga;
@@ -889,7 +890,7 @@ int get_arglist_exp(char_u *str, int *fcountp, char_u ***fnamesp, bool wig)
/// 0 means before first one
/// @param will_edit will edit added argument
///
-/// @return FAIL for failure, OK otherwise.
+/// @return FAIL for failure, OK otherwise.
static int do_arglist(char_u *str, int what, int after, bool will_edit)
FUNC_ATTR_NONNULL_ALL
{
@@ -988,8 +989,8 @@ static void alist_check_arg_idx(void)
}
}
-/// Return true if window "win" is editing the file at the current argument
-/// index.
+/// @return true if window "win" is editing the file at the current argument
+/// index.
static bool editing_arg_idx(win_T *win)
{
return !(win->w_arg_idx >= WARGCOUNT(win)
@@ -1717,13 +1718,13 @@ linenr_T *source_breakpoint(void *cookie)
return &((struct source_cookie *)cookie)->breakpoint;
}
-/// Return the address holding the debug tick for a source cookie.
+/// @return the address holding the debug tick for a source cookie.
int *source_dbg_tick(void *cookie)
{
return &((struct source_cookie *)cookie)->dbg_tick;
}
-/// Return the nesting level for a source cookie.
+/// @return the nesting level for a source cookie.
int source_level(void *cookie)
{
return ((struct source_cookie *)cookie)->level;
@@ -1788,7 +1789,8 @@ static char_u *get_str_line(int c, void *cookie, int indent, bool do_concat)
///
/// @param name File name of the script. NULL for anonymous :source.
/// @param[out] sid_out SID of the new item.
-/// @return pointer to the created script item.
+///
+/// @return pointer to the created script item.
scriptitem_T *new_script_item(char_u *const name, scid_T *const sid_out)
{
static scid_T last_current_SID = 0;
@@ -1896,7 +1898,7 @@ int do_source_str(const char *cmd, const char *traceback_name)
/// @param check_other check for .vimrc and _vimrc
/// @param is_vimrc DOSO_ value
///
-/// @return FAIL if file could not be opened, OK otherwise
+/// @return FAIL if file could not be opened, OK otherwise
int do_source(char *fname, int check_other, int is_vimrc)
{
struct source_cookie cookie;
@@ -2145,6 +2147,7 @@ theend:
/// Check if fname was sourced before to finds its SID.
/// If it's new, generate a new SID.
+///
/// @param[in] fname file path of script
/// @param[out] ret_sctx sctx of this script
scriptitem_T *get_current_script_id(char_u *fname, sctx_T *ret_sctx)
@@ -2614,9 +2617,9 @@ void do_finish(exarg_T *eap, int reanimate)
}
-/// Return true when a sourced file had the ":finish" command: Don't give error
-/// message for missing ":endif".
-/// Return false when not sourcing a file.
+/// @return true when a sourced file had the ":finish" command: Don't give error
+/// message for missing ":endif".
+/// false when not sourcing a file.
bool source_finished(LineGetter fgetline, void *cookie)
{
return getline_equal(fgetline, cookie, getsourceline)
@@ -2653,8 +2656,8 @@ static char *get_locale_val(int what)
}
#endif
-// Return true when "lang" starts with a valid language name.
-// Rejects NULL, empty string, "C", "C.UTF-8" and others.
+/// @return true when "lang" starts with a valid language name.
+/// Rejects NULL, empty string, "C", "C.UTF-8" and others.
static bool is_valid_mess_lang(char *lang)
{
return lang != NULL && ASCII_ISALPHA(lang[0]) && ASCII_ISALPHA(lang[1]);
@@ -2757,11 +2760,10 @@ void set_lang_var(void)
}
#ifdef HAVE_WORKING_LIBINTL
-///
+
/// ":language": Set the language (locale).
///
/// @param eap
-///
void ex_language(exarg_T *eap)
{
char *loc;
@@ -2870,8 +2872,9 @@ static char_u **locales = NULL; // Array of all available locales
# ifndef WIN32
static bool did_init_locales = false;
-/// Return an array of strings for all available locales + NULL for the
-/// last element. Return NULL in case of error.
+/// @return an array of strings for all available locales + NULL for the
+/// last element or,
+/// NULL in case of error.
static char_u **find_locales(void)
{
garray_T locales_ga;
diff --git a/src/nvim/ex_docmd.c b/src/nvim/ex_docmd.c
index 63dc1e539e..c6089562f3 100644
--- a/src/nvim/ex_docmd.c
+++ b/src/nvim/ex_docmd.c
@@ -38,6 +38,7 @@
#include "nvim/getchar.h"
#include "nvim/globals.h"
#include "nvim/hardcopy.h"
+#include "nvim/highlight_group.h"
#include "nvim/if_cscope.h"
#include "nvim/input.h"
#include "nvim/keymap.h"
@@ -2036,6 +2037,18 @@ doend:
return ea.nextcmd;
}
+static char ex_error_buf[MSG_BUF_LEN];
+
+/// @return an error message with argument included.
+/// Uses a static buffer, only the last error will be kept.
+/// "msg" will be translated, caller should use N_().
+char *ex_errmsg(const char *const msg, const char_u *const arg)
+ FUNC_ATTR_NONNULL_ALL
+{
+ vim_snprintf(ex_error_buf, MSG_BUF_LEN, _(msg), arg);
+ return ex_error_buf;
+}
+
// Parse and skip over command modifiers:
// - update eap->cmd
// - store flags in "cmdmod".
@@ -2704,7 +2717,7 @@ static char_u *find_ucmd(exarg_T *eap, char_u *p, int *full, expand_T *xp, int *
// only full match global is accepted.
// Look for buffer-local user commands first, then global ones.
- gap = is_in_cmdwin() ? &prevwin->w_buffer->b_ucmds : &curbuf->b_ucmds;
+ gap = &prevwin_curwin()->w_buffer->b_ucmds;
for (;;) {
for (j = 0; j < gap->ga_len; j++) {
uc = USER_CMD_GA(gap, j);
@@ -4861,7 +4874,13 @@ static int get_tabpage_arg(exarg_T *eap)
if (STRCMP(p, "$") == 0) {
tab_number = LAST_TAB_NR;
} else if (STRCMP(p, "#") == 0) {
- tab_number = tabpage_index(lastused_tabpage);
+ if (valid_tabpage(lastused_tabpage)) {
+ tab_number = tabpage_index(lastused_tabpage);
+ } else {
+ eap->errmsg = ex_errmsg(e_invargval, eap->arg);
+ tab_number = 0;
+ goto theend;
+ }
} else if (p == p_save || *p_save == '-' || *p != NUL
|| tab_number > LAST_TAB_NR) {
// No numbers as argument.
@@ -5378,7 +5397,7 @@ static void uc_list(char_u *name, size_t name_len)
uint32_t a;
// In cmdwin, the alternative buffer should be used.
- garray_T *gap = is_in_cmdwin() ? &prevwin->w_buffer->b_ucmds : &curbuf->b_ucmds;
+ const garray_T *gap = &prevwin_curwin()->w_buffer->b_ucmds;
for (;;) {
for (i = 0; i < gap->ga_len; i++) {
cmd = USER_CMD_GA(gap, i);
@@ -6357,7 +6376,7 @@ char_u *get_user_commands(expand_T *xp FUNC_ATTR_UNUSED, int idx)
FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT
{
// In cmdwin, the alternative buffer should be used.
- const buf_T *const buf = is_in_cmdwin() ? prevwin->w_buffer : curbuf;
+ const buf_T *const buf = prevwin_curwin()->w_buffer;
if (idx < buf->b_ucmds.ga_len) {
return USER_CMD_GA(&buf->b_ucmds, idx)->uc_name;
@@ -6379,7 +6398,8 @@ static char_u *get_user_command_name(int idx, int cmdidx)
}
if (cmdidx == CMD_USER_BUF) {
// In cmdwin, the alternative buffer should be used.
- buf_T *buf = is_in_cmdwin() ? prevwin->w_buffer : curbuf;
+ const buf_T *const buf = prevwin_curwin()->w_buffer;
+
if (idx < buf->b_ucmds.ga_len) {
return USER_CMD_GA(&buf->b_ucmds, idx)->uc_name;
}
@@ -9636,7 +9656,7 @@ static void ex_filetype(exarg_T *eap)
/// Source ftplugin.vim and indent.vim to create the necessary FileType
/// autocommands. We do this separately from filetype.vim so that these
-/// autocommands will always fire first (and thus can be overriden) while still
+/// autocommands will always fire first (and thus can be overridden) while still
/// allowing general filetype detection to be disabled in the user's init file.
void filetype_plugin_enable(void)
{
diff --git a/src/nvim/ex_eval.c b/src/nvim/ex_eval.c
index 25b6aa7d8a..3c7c635d98 100644
--- a/src/nvim/ex_eval.c
+++ b/src/nvim/ex_eval.c
@@ -88,27 +88,26 @@
*/
static int cause_abort = FALSE;
-// Return true when immediately aborting on error, or when an interrupt
-// occurred or an exception was thrown but not caught. Use for ":{range}call"
-// to check whether an aborted function that does not handle a range itself
-// should be called again for the next line in the range. Also used for
-// cancelling expression evaluation after a function call caused an immediate
-// abort. Note that the first emsg() call temporarily resets "force_abort"
-// until the throw point for error messages has been reached. That is, during
-// cancellation of an expression evaluation after an aborting function call or
-// due to a parsing error, aborting() always returns the same value.
-// "got_int" is also set by calling interrupt().
+/// @return true when immediately aborting on error, or when an interrupt
+/// occurred or an exception was thrown but not caught.
+///
+/// Use for ":{range}call" to check whether an aborted function that does not
+/// handle a range itself should be called again for the next line in the range.
+/// Also used for cancelling expression evaluation after a function call caused
+/// an immediate abort. Note that the first emsg() call temporarily resets
+/// "force_abort" until the throw point for error messages has been reached.
+/// That is, during cancellation of an expression evaluation after an aborting
+/// function call or due to a parsing error, aborting() always returns the same
+/// value. "got_int" is also set by calling interrupt().
int aborting(void)
{
return (did_emsg && force_abort) || got_int || current_exception;
}
-/*
- * The value of "force_abort" is temporarily reset by the first emsg() call
- * during an expression evaluation, and "cause_abort" is used instead. It might
- * be necessary to restore "force_abort" even before the throw point for the
- * error message has been reached. update_force_abort() should be called then.
- */
+/// The value of "force_abort" is temporarily reset by the first emsg() call
+/// during an expression evaluation, and "cause_abort" is used instead. It might
+/// be necessary to restore "force_abort" even before the throw point for the
+/// error message has been reached. update_force_abort() should be called then.
void update_force_abort(void)
{
if (cause_abort) {
@@ -116,23 +115,19 @@ void update_force_abort(void)
}
}
-/*
- * Return TRUE if a command with a subcommand resulting in "retcode" should
- * abort the script processing. Can be used to suppress an autocommand after
- * execution of a failing subcommand as long as the error message has not been
- * displayed and actually caused the abortion.
- */
+/// @return TRUE if a command with a subcommand resulting in "retcode" should
+/// abort the script processing. Can be used to suppress an autocommand after
+/// execution of a failing subcommand as long as the error message has not been
+/// displayed and actually caused the abortion.
int should_abort(int retcode)
{
return (retcode == FAIL && trylevel != 0 && !emsg_silent) || aborting();
}
-/*
- * Return TRUE if a function with the "abort" flag should not be considered
- * ended on an error. This means that parsing commands is continued in order
- * to find finally clauses to be executed, and that some errors in skipped
- * commands are still reported.
- */
+/// @return TRUE if a function with the "abort" flag should not be considered
+/// ended on an error. This means that parsing commands is continued in order
+/// to find finally clauses to be executed, and that some errors in skipped
+/// commands are still reported.
int aborted_in_try(void)
{
// This function is only called after an error. In this case, "force_abort"
@@ -140,13 +135,15 @@ int aborted_in_try(void)
return force_abort;
}
-// cause_errthrow(): Cause a throw of an error exception if appropriate.
-// Return true if the error message should not be displayed by emsg().
-// Sets "ignore", if the emsg() call should be ignored completely.
-//
-// When several messages appear in the same command, the first is usually the
-// most specific one and used as the exception value. The "severe" flag can be
-// set to true, if a later but severer message should be used instead.
+/// cause_errthrow(): Cause a throw of an error exception if appropriate.
+///
+/// @return true if the error message should not be displayed by emsg().
+///
+/// Sets "ignore", if the emsg() call should be ignored completely.
+///
+/// When several messages appear in the same command, the first is usually the
+/// most specific one and used as the exception value. The "severe" flag can be
+/// set to true, if a later but severer message should be used instead.
bool cause_errthrow(const char_u *mesg, bool severe, bool *ignore)
FUNC_ATTR_NONNULL_ALL
{
@@ -279,9 +276,7 @@ bool cause_errthrow(const char_u *mesg, bool severe, bool *ignore)
}
}
-/*
- * Free a "msg_list" and the messages it contains.
- */
+/// Free a "msg_list" and the messages it contains.
static void free_msglist(struct msglist *l)
{
struct msglist *messages, *next;
@@ -295,21 +290,17 @@ static void free_msglist(struct msglist *l)
}
}
-/*
- * Free global "*msg_list" and the messages it contains, then set "*msg_list"
- * to NULL.
- */
+/// Free global "*msg_list" and the messages it contains, then set "*msg_list"
+/// to NULL.
void free_global_msglist(void)
{
free_msglist(*msg_list);
*msg_list = NULL;
}
-/*
- * Throw the message specified in the call to cause_errthrow() above as an
- * error exception. If cstack is NULL, postpone the throw until do_cmdline()
- * has returned (see do_one_cmd()).
- */
+/// Throw the message specified in the call to cause_errthrow() above as an
+/// error exception. If cstack is NULL, postpone the throw until do_cmdline()
+/// has returned (see do_one_cmd()).
void do_errthrow(cstack_T *cstack, char_u *cmdname)
{
/*
@@ -339,11 +330,11 @@ void do_errthrow(cstack_T *cstack, char_u *cmdname)
*msg_list = NULL;
}
-/*
- * do_intthrow(): Replace the current exception by an interrupt or interrupt
- * exception if appropriate. Return TRUE if the current exception is discarded,
- * FALSE otherwise.
- */
+/// do_intthrow(): Replace the current exception by an interrupt or interrupt
+/// exception if appropriate.
+///
+/// @return TRUE if the current exception is discarded or,
+/// FALSE otherwise.
int do_intthrow(cstack_T *cstack)
{
// If no interrupt occurred or no try conditional is active and no exception
@@ -386,7 +377,7 @@ int do_intthrow(cstack_T *cstack)
return true;
}
-// Get an exception message that is to be stored in current_exception->value.
+/// Get an exception message that is to be stored in current_exception->value.
char *get_exception_string(void *value, except_type_T type, char_u *cmdname, int *should_free)
{
char *ret, *mesg;
@@ -445,10 +436,12 @@ char *get_exception_string(void *value, except_type_T type, char_u *cmdname, int
}
-// Throw a new exception. Return FAIL when out of memory or it was tried to
-// throw an illegal user exception. "value" is the exception string for a
-// user or interrupt exception, or points to a message list in case of an
-// error exception.
+/// Throw a new exception. "value" is the exception string for a
+/// user or interrupt exception, or points to a message list in case of an
+/// error exception.
+///
+/// @return FAIL when out of memory or it was tried to throw an illegal user
+/// exception.
static int throw_exception(void *value, except_type_T type, char_u *cmdname)
{
except_T *excp;
@@ -524,10 +517,8 @@ fail:
return FAIL;
}
-/*
- * Discard an exception. "was_finished" is set when the exception has been
- * caught and the catch clause has been ended normally.
- */
+/// Discard an exception. "was_finished" is set when the exception has been
+/// caught and the catch clause has been ended normally.
static void discard_exception(except_T *excp, bool was_finished)
{
char_u *saved_IObuff;
@@ -579,9 +570,7 @@ static void discard_exception(except_T *excp, bool was_finished)
xfree(excp);
}
-/*
- * Discard the exception currently being thrown.
- */
+/// Discard the exception currently being thrown.
void discard_current_exception(void)
{
if (current_exception != NULL) {
@@ -592,9 +581,7 @@ void discard_current_exception(void)
need_rethrow = false;
}
-/*
- * Put an exception on the caught stack.
- */
+/// Put an exception on the caught stack.
static void catch_exception(except_T *excp)
{
excp->caught = caught_stack;
@@ -640,9 +627,7 @@ static void catch_exception(except_T *excp)
}
}
-/*
- * Remove an exception from the caught stack.
- */
+/// Remove an exception from the caught stack.
static void finish_exception(except_T *excp)
{
if (excp != caught_stack) {
@@ -682,13 +667,11 @@ static void finish_exception(except_T *excp)
#define RP_RESUME 1
#define RP_DISCARD 2
-/*
- * Report information about something pending in a finally clause if required by
- * the 'verbose' option or when debugging. "action" tells whether something is
- * made pending or something pending is resumed or discarded. "pending" tells
- * what is pending. "value" specifies the return value for a pending ":return"
- * or the exception value for a pending exception.
- */
+/// Report information about something pending in a finally clause if required by
+/// the 'verbose' option or when debugging. "action" tells whether something is
+/// made pending or something pending is resumed or discarded. "pending" tells
+/// what is pending. "value" specifies the return value for a pending ":return"
+/// or the exception value for a pending exception.
static void report_pending(int action, int pending, void *value)
{
char *mesg;
@@ -764,10 +747,8 @@ static void report_pending(int action, int pending, void *value)
}
}
-/*
- * If something is made pending in a finally clause, report it if required by
- * the 'verbose' option or when debugging.
- */
+/// If something is made pending in a finally clause, report it if required by
+/// the 'verbose' option or when debugging.
void report_make_pending(int pending, void *value)
{
if (p_verbose >= 14 || debug_break_level > 0) {
@@ -781,10 +762,8 @@ void report_make_pending(int pending, void *value)
}
}
-/*
- * If something pending in a finally clause is resumed at the ":endtry", report
- * it if required by the 'verbose' option or when debugging.
- */
+/// If something pending in a finally clause is resumed at the ":endtry", report
+/// it if required by the 'verbose' option or when debugging.
void report_resume_pending(int pending, void *value)
{
if (p_verbose >= 14 || debug_break_level > 0) {
@@ -798,10 +777,8 @@ void report_resume_pending(int pending, void *value)
}
}
-/*
- * If something pending in a finally clause is discarded, report it if required
- * by the 'verbose' option or when debugging.
- */
+/// If something pending in a finally clause is discarded, report it if required
+/// by the 'verbose' option or when debugging.
void report_discard_pending(int pending, void *value)
{
if (p_verbose >= 14 || debug_break_level > 0) {
@@ -815,7 +792,7 @@ void report_discard_pending(int pending, void *value)
}
}
-// ":eval".
+/// Handle ":eval".
void ex_eval(exarg_T *eap)
{
typval_T tv;
@@ -825,9 +802,7 @@ void ex_eval(exarg_T *eap)
}
}
-/*
- * ":if".
- */
+/// Handle ":if".
void ex_if(exarg_T *eap)
{
int skip;
@@ -856,9 +831,7 @@ void ex_if(exarg_T *eap)
}
}
-/*
- * ":endif".
- */
+/// Handle ":endif".
void ex_endif(exarg_T *eap)
{
did_endif = true;
@@ -883,9 +856,7 @@ void ex_endif(exarg_T *eap)
}
}
-/*
- * ":else" and ":elseif".
- */
+/// Handle ":else" and ":elseif".
void ex_else(exarg_T *eap)
{
int result;
@@ -958,9 +929,7 @@ void ex_else(exarg_T *eap)
}
}
-/*
- * Handle ":while" and ":for".
- */
+/// Handle ":while" and ":for".
void ex_while(exarg_T *eap)
{
bool error;
@@ -1041,9 +1010,7 @@ void ex_while(exarg_T *eap)
}
}
-/*
- * ":continue"
- */
+/// Handle ":continue"
void ex_continue(exarg_T *eap)
{
int idx;
@@ -1075,9 +1042,7 @@ void ex_continue(exarg_T *eap)
}
}
-/*
- * ":break"
- */
+/// Handle ":break"
void ex_break(exarg_T *eap)
{
int idx;
@@ -1098,9 +1063,7 @@ void ex_break(exarg_T *eap)
}
}
-/*
- * ":endwhile" and ":endfor"
- */
+/// Handle ":endwhile" and ":endfor"
void ex_endwhile(exarg_T *eap)
{
cstack_T *const cstack = eap->cstack;
@@ -1175,9 +1138,7 @@ void ex_endwhile(exarg_T *eap)
}
-/*
- * ":throw expr"
- */
+/// Handle ":throw expr"
void ex_throw(exarg_T *eap)
{
const char *arg = (const char *)eap->arg;
@@ -1202,11 +1163,9 @@ void ex_throw(exarg_T *eap)
}
}
-/*
- * Throw the current exception through the specified cstack. Common routine
- * for ":throw" (user exception) and error and interrupt exceptions. Also
- * used for rethrowing an uncaught exception.
- */
+/// Throw the current exception through the specified cstack. Common routine
+/// for ":throw" (user exception) and error and interrupt exceptions. Also
+/// used for rethrowing an uncaught exception.
void do_throw(cstack_T *cstack)
{
int idx;
@@ -1263,9 +1222,7 @@ void do_throw(cstack_T *cstack)
}
}
-/*
- * ":try"
- */
+/// Handle ":try"
void ex_try(exarg_T *eap)
{
int skip;
@@ -1315,9 +1272,7 @@ void ex_try(exarg_T *eap)
}
}
-/*
- * ":catch /{pattern}/" and ":catch"
- */
+/// Handle ":catch /{pattern}/" and ":catch"
void ex_catch(exarg_T *eap)
{
int idx = 0;
@@ -1471,9 +1426,7 @@ void ex_catch(exarg_T *eap)
}
}
-/*
- * ":finally"
- */
+/// Handle ":finally"
void ex_finally(exarg_T *eap)
{
int idx;
@@ -1595,9 +1548,7 @@ void ex_finally(exarg_T *eap)
}
}
-/*
- * ":endtry"
- */
+/// Handle ":endtry"
void ex_endtry(exarg_T *eap)
{
int idx;
@@ -1784,14 +1735,12 @@ void ex_endtry(exarg_T *eap)
* error/interrupt/exception state.
*/
-/*
- * This function works a bit like ex_finally() except that there was not
- * actually an extra try block around the part that failed and an error or
- * interrupt has not (yet) been converted to an exception. This function
- * saves the error/interrupt/ exception state and prepares for the call to
- * do_cmdline() that is going to be made for the cleanup autocommand
- * execution.
- */
+/// This function works a bit like ex_finally() except that there was not
+/// actually an extra try block around the part that failed and an error or
+/// interrupt has not (yet) been converted to an exception. This function
+/// saves the error/interrupt/ exception state and prepares for the call to
+/// do_cmdline() that is going to be made for the cleanup autocommand
+/// execution.
void enter_cleanup(cleanup_T *csp)
{
int pending = CSTP_NONE;
@@ -1834,21 +1783,19 @@ void enter_cleanup(cleanup_T *csp)
}
}
-/*
- * See comment above enter_cleanup() for how this function is used.
- *
- * This function is a bit like ex_endtry() except that there was not actually
- * an extra try block around the part that failed and an error or interrupt
- * had not (yet) been converted to an exception when the cleanup autocommand
- * sequence was invoked.
- *
- * This function has to be called with the address of the cleanup_T structure
- * filled by enter_cleanup() as an argument; it restores the error/interrupt/
- * exception state saved by that function - except there was an aborting
- * error, an interrupt or an uncaught exception during execution of the
- * cleanup autocommands. In the latter case, the saved error/interrupt/
- * exception state is discarded.
- */
+/// This function is a bit like ex_endtry() except that there was not actually
+/// an extra try block around the part that failed and an error or interrupt
+/// had not (yet) been converted to an exception when the cleanup autocommand
+/// sequence was invoked.
+///
+/// See comment above enter_cleanup() for how this function is used.
+///
+/// This function has to be called with the address of the cleanup_T structure
+/// filled by enter_cleanup() as an argument; it restores the error/interrupt/
+/// exception state saved by that function - except there was an aborting
+/// error, an interrupt or an uncaught exception during execution of the
+/// cleanup autocommands. In the latter case, the saved error/interrupt/
+/// exception state is discarded.
void leave_cleanup(cleanup_T *csp)
{
int pending = csp->pending;
@@ -1913,22 +1860,25 @@ void leave_cleanup(cleanup_T *csp)
}
-/*
- * Make conditionals inactive and discard what's pending in finally clauses
- * until the conditional type searched for or a try conditional not in its
- * finally clause is reached. If this is in an active catch clause, finish
- * the caught exception.
- * Return the cstack index where the search stopped.
- * Values used for "searched_cond" are (CSF_WHILE | CSF_FOR) or CSF_TRY or 0,
- * the latter meaning the innermost try conditional not in its finally clause.
- * "inclusive" tells whether the conditional searched for should be made
- * inactive itself (a try conditional not in its finally clause possibly find
- * before is always made inactive). If "inclusive" is TRUE and
- * "searched_cond" is CSF_TRY|CSF_SILENT, the saved former value of
- * "emsg_silent", if reset when the try conditional finally reached was
- * entered, is restored (used by ex_endtry()). This is normally done only
- * when such a try conditional is left.
- */
+/// Make conditionals inactive and discard what's pending in finally clauses
+/// until the conditional type searched for or a try conditional not in its
+/// finally clause is reached. If this is in an active catch clause, finish
+/// the caught exception.
+///
+///
+/// @param searched_cond Possible values are (CSF_WHILE | CSF_FOR) or CSF_TRY or 0,
+/// the latter meaning the innermost try conditional not
+/// in its finally clause.
+/// @param inclusive tells whether the conditional searched for should be made
+/// inactive itself (a try conditional not in its finally
+/// clause possibly find before is always made inactive).
+///
+/// If "inclusive" is TRUE and "searched_cond" is CSF_TRY|CSF_SILENT, the saved
+/// former value of "emsg_silent", if reset when the try conditional finally
+/// reached was entered, is restored (used by ex_endtry()). This is normally
+/// done only when such a try conditional is left.
+///
+/// @return the cstack index where the search stopped.
int cleanup_conditionals(cstack_T *cstack, int searched_cond, int inclusive)
{
int idx;
@@ -2037,9 +1987,7 @@ int cleanup_conditionals(cstack_T *cstack, int searched_cond, int inclusive)
return idx;
}
-/*
- * Return an appropriate error message for a missing endwhile/endfor/endif.
- */
+/// @return an appropriate error message for a missing endwhile/endfor/endif.
static char *get_end_emsg(cstack_T *cstack)
{
if (cstack->cs_flags[cstack->cs_idx] & CSF_WHILE) {
@@ -2052,13 +2000,11 @@ static char *get_end_emsg(cstack_T *cstack)
}
-/*
- * Rewind conditionals until index "idx" is reached. "cond_type" and
- * "cond_level" specify a conditional type and the address of a level variable
- * which is to be decremented with each skipped conditional of the specified
- * type.
- * Also free "for info" structures where needed.
- */
+/// Rewind conditionals until index "idx" is reached. "cond_type" and
+/// "cond_level" specify a conditional type and the address of a level variable
+/// which is to be decremented with each skipped conditional of the specified
+/// type.
+/// Also free "for info" structures where needed.
void rewind_conditionals(cstack_T *cstack, int idx, int cond_type, int *cond_level)
{
while (cstack->cs_idx > idx) {
@@ -2072,17 +2018,13 @@ void rewind_conditionals(cstack_T *cstack, int idx, int cond_type, int *cond_lev
}
}
-/*
- * ":endfunction" when not after a ":function"
- */
+/// Handle ":endfunction" when not after a ":function"
void ex_endfunction(exarg_T *eap)
{
emsg(_("E193: :endfunction not inside a function"));
}
-/*
- * Return TRUE if the string "p" looks like a ":while" or ":for" command.
- */
+/// @return TRUE if the string "p" looks like a ":while" or ":for" command.
int has_loop_cmd(char_u *p)
{
int len;
@@ -2104,4 +2046,3 @@ int has_loop_cmd(char_u *p)
}
return FALSE;
}
-
diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c
index 30287cd6f2..84fca137d2 100644
--- a/src/nvim/ex_getln.c
+++ b/src/nvim/ex_getln.c
@@ -35,6 +35,7 @@
#include "nvim/getchar.h"
#include "nvim/highlight.h"
#include "nvim/highlight_defs.h"
+#include "nvim/highlight_group.h"
#include "nvim/if_cscope.h"
#include "nvim/indent.h"
#include "nvim/keymap.h"
@@ -231,7 +232,7 @@ static int compl_selected;
/// |:checkhealth| completion items
///
-/// Regenerates on every new command line prompt, to accomodate changes on the
+/// Regenerates on every new command line prompt, to accommodate changes on the
/// runtime files.
typedef struct {
garray_T names; // healthcheck names
@@ -632,7 +633,7 @@ static void may_do_incsearch_highlighting(int firstc, long count, incsearch_stat
validate_cursor();
// May redraw the status line to show the cursor position.
- if (p_ru && curwin->w_status_height > 0) {
+ if (p_ru && (curwin->w_status_height > 0 || global_stl_height() > 0)) {
curwin->w_redr_status = true;
}
@@ -3631,7 +3632,7 @@ void compute_cmdrow(void)
} else {
win_T *wp = lastwin_nofloating();
cmdline_row = wp->w_winrow + wp->w_height
- + wp->w_status_height;
+ + wp->w_hsep_height + wp->w_status_height + global_stl_height();
}
lines_left = cmdline_row;
}
@@ -6589,7 +6590,7 @@ static int open_cmdwin(void)
/// @return true if in the cmdwin, not editing the command line.
bool is_in_cmdwin(void)
- FUNC_ATTR_PURE
+ FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT
{
return cmdwin_type != 0 && get_cmdline_type() == NUL;
}
diff --git a/src/nvim/ex_session.c b/src/nvim/ex_session.c
index ca07174543..0e2b7c0ece 100644
--- a/src/nvim/ex_session.c
+++ b/src/nvim/ex_session.c
@@ -72,7 +72,7 @@ static int ses_winsizes(FILE *fd, int restore_size, win_T *tab_firstwin)
n++;
// restore height when not full height
- if (wp->w_height + wp->w_status_height < topframe->fr_height
+ if (wp->w_height + wp->w_hsep_height + wp->w_status_height < topframe->fr_height
&& (fprintf(fd,
"exe '%dresize ' . ((&lines * %" PRId64
" + %" PRId64 ") / %" PRId64 ")\n",
@@ -365,7 +365,7 @@ static int put_view(FILE *fd, win_T *wp, int add_edit, unsigned *flagp, int curr
// edit that buffer, to not lose folding information (:edit resets
// folds in other buffers)
if (fprintf(fd,
- "if bufexists(\"%s\") | buffer %s | else | edit %s | endif\n"
+ "if bufexists(fnamemodify(\"%s\", \":p\")) | buffer %s | else | edit %s | endif\n"
// Fixup :terminal buffer name. #7836
"if &buftype ==# 'terminal'\n"
" silent file %s\n"
diff --git a/src/nvim/fold.c b/src/nvim/fold.c
index 546345eeac..54430d46af 100644
--- a/src/nvim/fold.c
+++ b/src/nvim/fold.c
@@ -121,9 +121,7 @@ static size_t foldendmarkerlen;
// Exported folding functions. {{{1
// copyFoldingState() {{{2
-/*
- * Copy that folding state from window "wp_from" to window "wp_to".
- */
+/// Copy that folding state from window "wp_from" to window "wp_to".
void copyFoldingState(win_T *wp_from, win_T *wp_to)
{
wp_to->w_fold_manual = wp_from->w_fold_manual;
@@ -132,9 +130,7 @@ void copyFoldingState(win_T *wp_from, win_T *wp_to)
}
// hasAnyFolding() {{{2
-/*
- * Return TRUE if there may be folded lines in the current window.
- */
+/// @return TRUE if there may be folded lines in the current window.
int hasAnyFolding(win_T *win)
{
// very simple now, but can become more complex later
@@ -259,9 +255,7 @@ bool hasFoldingWin(win_T *const win, const linenr_T lnum, linenr_T *const firstp
}
// foldLevel() {{{2
-/*
- * Return fold level at line number "lnum" in the current window.
- */
+/// @return fold level at line number "lnum" in the current window.
int foldLevel(linenr_T lnum)
{
// While updating the folds lines between invalid_top and invalid_bot have
@@ -283,15 +277,16 @@ int foldLevel(linenr_T lnum)
}
// lineFolded() {{{2
-// Low level function to check if a line is folded. Doesn't use any caching.
-// Return true if line is folded.
-// Return false if line is not folded.
+/// Low level function to check if a line is folded. Doesn't use any caching.
+///
+/// @return true if line is folded or,
+/// false if line is not folded.
bool lineFolded(win_T *const win, const linenr_T lnum)
{
return fold_info(win, lnum).fi_lines != 0;
}
-/// fold_info() {{{2
+// fold_info() {{{2
///
/// Count the number of lines that are folded at line number "lnum".
/// Normally "lnum" is the first line of a possible fold, and the returned
@@ -316,61 +311,49 @@ foldinfo_T fold_info(win_T *win, linenr_T lnum)
}
// foldmethodIsManual() {{{2
-/*
- * Return TRUE if 'foldmethod' is "manual"
- */
+/// @return TRUE if 'foldmethod' is "manual"
int foldmethodIsManual(win_T *wp)
{
return wp->w_p_fdm[3] == 'u';
}
// foldmethodIsIndent() {{{2
-/*
- * Return TRUE if 'foldmethod' is "indent"
- */
+/// @return TRUE if 'foldmethod' is "indent"
int foldmethodIsIndent(win_T *wp)
{
return wp->w_p_fdm[0] == 'i';
}
// foldmethodIsExpr() {{{2
-/*
- * Return TRUE if 'foldmethod' is "expr"
- */
+/// @return TRUE if 'foldmethod' is "expr"
int foldmethodIsExpr(win_T *wp)
{
return wp->w_p_fdm[1] == 'x';
}
// foldmethodIsMarker() {{{2
-/*
- * Return TRUE if 'foldmethod' is "marker"
- */
+/// @return TRUE if 'foldmethod' is "marker"
int foldmethodIsMarker(win_T *wp)
{
return wp->w_p_fdm[2] == 'r';
}
// foldmethodIsSyntax() {{{2
-/*
- * Return TRUE if 'foldmethod' is "syntax"
- */
+/// @return TRUE if 'foldmethod' is "syntax"
int foldmethodIsSyntax(win_T *wp)
{
return wp->w_p_fdm[0] == 's';
}
// foldmethodIsDiff() {{{2
-/*
- * Return TRUE if 'foldmethod' is "diff"
- */
+/// @return TRUE if 'foldmethod' is "diff"
int foldmethodIsDiff(win_T *wp)
{
return wp->w_p_fdm[0] == 'd';
}
// closeFold() {{{2
-/// Close fold for current window at line "lnum".
+/// Close fold for current window at position "pos".
/// Repeat "count" times.
void closeFold(pos_T pos, long count)
{
@@ -378,9 +361,7 @@ void closeFold(pos_T pos, long count)
}
// closeFoldRecurse() {{{2
-/*
- * Close fold for current window at line "lnum" recursively.
- */
+/// Close fold for current window at position `pos` recursively.
void closeFoldRecurse(pos_T pos)
{
(void)setManualFold(pos, false, true, NULL);
@@ -427,28 +408,22 @@ void opFoldRange(pos_T firstpos, pos_T lastpos, int opening, int recurse, int ha
}
// openFold() {{{2
-/*
- * Open fold for current window at line "lnum".
- * Repeat "count" times.
- */
+/// Open fold for current window at position "pos".
+/// Repeat "count" times.
void openFold(pos_T pos, long count)
{
setFoldRepeat(pos, count, true);
}
// openFoldRecurse() {{{2
-/*
- * Open fold for current window at line "lnum" recursively.
- */
+/// Open fold for current window at position `pos` recursively.
void openFoldRecurse(pos_T pos)
{
(void)setManualFold(pos, true, true, NULL);
}
// foldOpenCursor() {{{2
-/*
- * Open folds until the cursor line is not in a closed fold.
- */
+/// Open folds until the cursor line is not in a closed fold.
void foldOpenCursor(void)
{
int done;
@@ -466,9 +441,7 @@ void foldOpenCursor(void)
}
// newFoldLevel() {{{2
-/*
- * Set new foldlevel for current window.
- */
+/// Set new foldlevel for current window.
void newFoldLevel(void)
{
newFoldLevelWin(curwin);
@@ -505,9 +478,7 @@ static void newFoldLevelWin(win_T *wp)
}
// foldCheckClose() {{{2
-/*
- * Apply 'foldlevel' to all folds that don't contain the cursor.
- */
+/// Apply 'foldlevel' to all folds that don't contain the cursor.
void foldCheckClose(void)
{
if (*p_fcl != NUL) { // can only be "all" right now
@@ -543,8 +514,8 @@ static int checkCloseRec(garray_T *gap, linenr_T lnum, int level)
}
// foldCreateAllowed() {{{2
-/// Return TRUE if it's allowed to manually create or delete a fold.
-/// Give an error message and return FALSE if not.
+/// @return TRUE if it's allowed to manually create or delete a fold or,
+/// give an error message and return FALSE if not.
int foldManualAllowed(bool create)
{
if (foldmethodIsManual(curwin) || foldmethodIsMarker(curwin)) {
@@ -790,9 +761,7 @@ void deleteFold(win_T *const wp, const linenr_T start, const linenr_T end, const
}
// clearFolding() {{{2
-/*
- * Remove all folding for window "win".
- */
+/// Remove all folding for window "win".
void clearFolding(win_T *win)
{
deleteFoldRecurse(win->w_buffer, &win->w_folds);
@@ -800,12 +769,10 @@ void clearFolding(win_T *win)
}
// foldUpdate() {{{2
-/*
- * Update folds for changes in the buffer of a window.
- * Note that inserted/deleted lines must have already been taken care of by
- * calling foldMarkAdjust().
- * The changes in lines from top to bot (inclusive).
- */
+/// Update folds for changes in the buffer of a window.
+/// Note that inserted/deleted lines must have already been taken care of by
+/// calling foldMarkAdjust().
+/// The changes in lines from top to bot (inclusive).
void foldUpdate(win_T *wp, linenr_T top, linenr_T bot)
{
if (compl_busy || State & INSERT) {
@@ -856,12 +823,10 @@ void foldUpdateAfterInsert(void)
}
// foldUpdateAll() {{{2
-/*
- * Update all lines in a window for folding.
- * Used when a fold setting changes or after reloading the buffer.
- * The actual updating is postponed until fold info is used, to avoid doing
- * every time a setting is changed or a syntax item is added.
- */
+/// Update all lines in a window for folding.
+/// Used when a fold setting changes or after reloading the buffer.
+/// The actual updating is postponed until fold info is used, to avoid doing
+/// every time a setting is changed or a syntax item is added.
void foldUpdateAll(win_T *win)
{
win->w_foldinvalid = true;
@@ -992,21 +957,18 @@ int foldMoveTo(const bool updown, const int dir, const long count)
}
// foldInitWin() {{{2
-/*
- * Init the fold info in a new window.
- */
+/// Init the fold info in a new window.
void foldInitWin(win_T *new_win)
{
ga_init(&new_win->w_folds, (int)sizeof(fold_T), 10);
}
// find_wl_entry() {{{2
-/*
- * Find an entry in the win->w_lines[] array for buffer line "lnum".
- * Only valid entries are considered (for entries where wl_valid is FALSE the
- * line number can be wrong).
- * Returns index of entry or -1 if not found.
- */
+/// Find an entry in the win->w_lines[] array for buffer line "lnum".
+/// Only valid entries are considered (for entries where wl_valid is FALSE the
+/// line number can be wrong).
+///
+/// @return index of entry or -1 if not found.
int find_wl_entry(win_T *win, linenr_T lnum)
{
int i;
@@ -1025,9 +987,7 @@ int find_wl_entry(win_T *win, linenr_T lnum)
}
// foldAdjustVisual() {{{2
-/*
- * Adjust the Visual area to include any fold at the start or end completely.
- */
+/// Adjust the Visual area to include any fold at the start or end completely.
void foldAdjustVisual(void)
{
pos_T *start, *end;
@@ -1059,9 +1019,7 @@ void foldAdjustVisual(void)
}
// cursor_foldstart() {{{2
-/*
- * Move the cursor to the first line of a closed fold.
- */
+/// Move the cursor to the first line of a closed fold.
void foldAdjustCursor(void)
{
(void)hasFolding(curwin->w_cursor.lnum, &curwin->w_cursor.lnum, NULL);
@@ -1069,9 +1027,7 @@ void foldAdjustCursor(void)
// Internal functions for "fold_T" {{{1
// cloneFoldGrowArray() {{{2
-/*
- * Will "clone" (i.e deep copy) a garray_T of folds.
- */
+/// Will "clone" (i.e deep copy) a garray_T of folds.
void cloneFoldGrowArray(garray_T *from, garray_T *to)
{
fold_T *from_p;
@@ -1143,9 +1099,7 @@ static bool foldFind(const garray_T *gap, linenr_T lnum, fold_T **fpp)
}
// foldLevelWin() {{{2
-/*
- * Return fold level at line number "lnum" in window "wp".
- */
+/// @return fold level at line number "lnum" in window "wp".
static int foldLevelWin(win_T *wp, linenr_T lnum)
{
fold_T *fp;
@@ -1169,9 +1123,7 @@ static int foldLevelWin(win_T *wp, linenr_T lnum)
}
// checkupdate() {{{2
-/*
- * Check if the folds in window "wp" are invalid and update them if needed.
- */
+/// Check if the folds in window "wp" are invalid and update them if needed.
static void checkupdate(win_T *wp)
{
if (wp->w_foldinvalid) {
@@ -1181,10 +1133,8 @@ static void checkupdate(win_T *wp)
}
// setFoldRepeat() {{{2
-/*
- * Open or close fold for current window at line "lnum".
- * Repeat "count" times.
- */
+/// Open or close fold for current window at position `pos`.
+/// Repeat "count" times.
static void setFoldRepeat(pos_T pos, long count, int do_open)
{
int done;
@@ -1204,7 +1154,6 @@ static void setFoldRepeat(pos_T pos, long count, int do_open)
}
// setManualFold() {{{2
-///
/// Open or close the fold in the current window which contains "lnum".
/// Also does this for other windows in diff mode when needed.
///
@@ -1344,9 +1293,7 @@ static linenr_T setManualFoldWin(win_T *wp, linenr_T lnum, int opening, int recu
}
// foldOpenNested() {{{2
-/*
- * Open all nested folds in fold "fpr" recursively.
- */
+/// Open all nested folds in fold "fpr" recursively.
static void foldOpenNested(fold_T *fpr)
{
fold_T *fp;
@@ -1359,9 +1306,10 @@ static void foldOpenNested(fold_T *fpr)
}
// deleteFoldEntry() {{{2
-// Delete fold "idx" from growarray "gap".
-// When "recursive" is true also delete all the folds contained in it.
-// When "recursive" is false contained folds are moved one level up.
+/// Delete fold "idx" from growarray "gap".
+///
+/// @param recursive when true, also delete all the folds contained in it.
+/// when false, contained folds are moved one level up.
static void deleteFoldEntry(win_T *const wp, garray_T *const gap, const int idx,
const bool recursive)
{
@@ -1408,9 +1356,7 @@ static void deleteFoldEntry(win_T *const wp, garray_T *const gap, const int idx,
}
// deleteFoldRecurse() {{{2
-/*
- * Delete nested folds in a fold.
- */
+/// Delete nested folds in a fold.
void deleteFoldRecurse(buf_T *bp, garray_T *gap)
{
#define DELETE_FOLD_NESTED(fd) deleteFoldRecurse(bp, &((fd)->fd_nested))
@@ -1418,9 +1364,7 @@ void deleteFoldRecurse(buf_T *bp, garray_T *gap)
}
// foldMarkAdjust() {{{2
-/*
- * Update line numbers of folds for inserted/deleted lines.
- */
+/// Update line numbers of folds for inserted/deleted lines.
void foldMarkAdjust(win_T *wp, linenr_T line1, linenr_T line2, long amount, long amount_after)
{
// If deleting marks from line1 to line2, but not deleting all those
@@ -1538,10 +1482,8 @@ static void foldMarkAdjustRecurse(win_T *wp, garray_T *gap, linenr_T line1, line
}
// getDeepestNesting() {{{2
-/*
- * Get the lowest 'foldlevel' value that makes the deepest nested fold in the
- * current window open.
- */
+/// Get the lowest 'foldlevel' value that makes the deepest nested fold in
+/// window `wp`.
int getDeepestNesting(win_T *wp)
{
checkupdate(wp);
@@ -1633,7 +1575,7 @@ static void checkSmall(win_T *const wp, fold_T *const fp, const linenr_T lnum_of
}
// setSmallMaybe() {{{2
-// Set small flags in "gap" to kNone.
+/// Set small flags in "gap" to kNone.
static void setSmallMaybe(garray_T *gap)
{
fold_T *fp = (fold_T *)gap->ga_data;
@@ -1643,10 +1585,8 @@ static void setSmallMaybe(garray_T *gap)
}
// foldCreateMarkers() {{{2
-/*
- * Create a fold from line "start" to line "end" (inclusive) in the current
- * window by adding markers.
- */
+/// Create a fold from line "start" to line "end" (inclusive) in window `wp`
+/// by adding markers.
static void foldCreateMarkers(win_T *wp, pos_T start, pos_T end)
{
buf_T *buf = wp->w_buffer;
@@ -1672,9 +1612,7 @@ static void foldCreateMarkers(win_T *wp, pos_T start, pos_T end)
}
// foldAddMarker() {{{2
-/*
- * Add "marker[markerlen]" in 'commentstring' to line "lnum".
- */
+/// Add "marker[markerlen]" in 'commentstring' to position `pos`.
static void foldAddMarker(buf_T *buf, pos_T pos, const char_u *marker, size_t markerlen)
{
char_u *cms = buf->b_p_cms;
@@ -1731,11 +1669,10 @@ static void deleteFoldMarkers(win_T *wp, fold_T *fp, int recursive, linenr_T lnu
}
// foldDelMarker() {{{2
-//
-// Delete marker "marker[markerlen]" at the end of line "lnum".
-// Delete 'commentstring' if it matches.
-// If the marker is not found, there is no error message. Could be a missing
-// close-marker.
+/// Delete marker "marker[markerlen]" at the end of line "lnum".
+/// Delete 'commentstring' if it matches.
+/// If the marker is not found, there is no error message. Could be a missing
+/// close-marker.
static void foldDelMarker(buf_T *buf, linenr_T lnum, char_u *marker, size_t markerlen)
{
char_u *newline;
@@ -1892,9 +1829,7 @@ char_u *get_foldtext(win_T *wp, linenr_T lnum, linenr_T lnume, foldinfo_T foldin
}
// foldtext_cleanup() {{{2
-/*
- * Remove 'foldmarker' and 'commentstring' from "str" (in-place).
- */
+/// Remove 'foldmarker' and 'commentstring' from "str" (in-place).
void foldtext_cleanup(char_u *str)
{
char_u *s;
@@ -1974,10 +1909,8 @@ void foldtext_cleanup(char_u *str)
// Function declarations. {{{2
// foldUpdateIEMS() {{{2
-/*
- * Update the folding for window "wp", at least from lines "top" to "bot".
- * IEMS = "Indent Expr Marker Syntax"
- */
+/// Update the folding for window "wp", at least from lines "top" to "bot".
+/// IEMS = "Indent Expr Marker Syntax"
static void foldUpdateIEMS(win_T *const wp, linenr_T top, linenr_T bot)
{
fline_T fline;
@@ -2640,9 +2573,7 @@ static linenr_T foldUpdateIEMSRecurse(garray_T *const gap, const int level,
}
// foldInsert() {{{2
-/*
- * Insert a new fold in "gap" at position "i".
- */
+/// Insert a new fold in "gap" at position "i".
static void foldInsert(garray_T *gap, int i)
{
fold_T *fp;
@@ -2658,13 +2589,11 @@ static void foldInsert(garray_T *gap, int i)
}
// foldSplit() {{{2
-/*
- * Split the "i"th fold in "gap", which starts before "top" and ends below
- * "bot" in two pieces, one ending above "top" and the other starting below
- * "bot".
- * The caller must first have taken care of any nested folds from "top" to
- * "bot"!
- */
+/// Split the "i"th fold in "gap", which starts before "top" and ends below
+/// "bot" in two pieces, one ending above "top" and the other starting below
+/// "bot".
+/// The caller must first have taken care of any nested folds from "top" to
+/// "bot"!
static void foldSplit(buf_T *buf, garray_T *const gap, const int i, const linenr_T top,
const linenr_T bot)
{
@@ -2704,24 +2633,22 @@ static void foldSplit(buf_T *buf, garray_T *const gap, const int i, const linenr
}
// foldRemove() {{{2
-/*
- * Remove folds within the range "top" to and including "bot".
- * Check for these situations:
- * 1 2 3
- * 1 2 3
- * top 2 3 4 5
- * 2 3 4 5
- * bot 2 3 4 5
- * 3 5 6
- * 3 5 6
- *
- * 1: not changed
- * 2: truncate to stop above "top"
- * 3: split in two parts, one stops above "top", other starts below "bot".
- * 4: deleted
- * 5: made to start below "bot".
- * 6: not changed
- */
+/// Remove folds within the range "top" to and including "bot".
+/// Check for these situations:
+/// 1 2 3
+/// 1 2 3
+/// top 2 3 4 5
+/// 2 3 4 5
+/// bot 2 3 4 5
+/// 3 5 6
+/// 3 5 6
+///
+/// 1: not changed
+/// 2: truncate to stop above "top"
+/// 3: split in two parts, one stops above "top", other starts below "bot".
+/// 4: deleted
+/// 5: made to start below "bot".
+/// 6: not changed
static void foldRemove(win_T *const wp, garray_T *gap, linenr_T top, linenr_T bot)
{
fold_T *fp = NULL;
@@ -2786,35 +2713,35 @@ static void foldReverseOrder(garray_T *gap, const linenr_T start_arg, const line
}
// foldMoveRange() {{{2
-// Move folds within the inclusive range "line1" to "line2" to after "dest"
-// require "line1" <= "line2" <= "dest"
-//
-// There are the following situations for the first fold at or below line1 - 1.
-// 1 2 3 4
-// 1 2 3 4
-// line1 2 3 4
-// 2 3 4 5 6 7
-// line2 3 4 5 6 7
-// 3 4 6 7 8 9
-// dest 4 7 8 9
-// 4 7 8 10
-// 4 7 8 10
-//
-// In the following descriptions, "moved" means moving in the buffer, *and* in
-// the fold array.
-// Meanwhile, "shifted" just means moving in the buffer.
-// 1. not changed
-// 2. truncated above line1
-// 3. length reduced by line2 - line1, folds starting between the end of 3 and
-// dest are truncated and shifted up
-// 4. internal folds moved (from [line1, line2] to dest)
-// 5. moved to dest.
-// 6. truncated below line2 and moved.
-// 7. length reduced by line2 - dest, folds starting between line2 and dest are
-// removed, top is moved down by move_len.
-// 8. truncated below dest and shifted up.
-// 9. shifted up
-// 10. not changed
+/// Move folds within the inclusive range "line1" to "line2" to after "dest"
+/// require "line1" <= "line2" <= "dest"
+///
+/// There are the following situations for the first fold at or below line1 - 1.
+/// 1 2 3 4
+/// 1 2 3 4
+/// line1 2 3 4
+/// 2 3 4 5 6 7
+/// line2 3 4 5 6 7
+/// 3 4 6 7 8 9
+/// dest 4 7 8 9
+/// 4 7 8 10
+/// 4 7 8 10
+///
+/// In the following descriptions, "moved" means moving in the buffer, *and* in
+/// the fold array.
+/// Meanwhile, "shifted" just means moving in the buffer.
+/// 1. not changed
+/// 2. truncated above line1
+/// 3. length reduced by line2 - line1, folds starting between the end of 3 and
+/// dest are truncated and shifted up
+/// 4. internal folds moved (from [line1, line2] to dest)
+/// 5. moved to dest.
+/// 6. truncated below line2 and moved.
+/// 7. length reduced by line2 - dest, folds starting between line2 and dest are
+/// removed, top is moved down by move_len.
+/// 8. truncated below dest and shifted up.
+/// 9. shifted up
+/// 10. not changed
static void truncate_fold(win_T *const wp, fold_T *fp, linenr_T end)
{
// I want to stop *at here*, foldRemove() stops *above* top
@@ -2929,13 +2856,11 @@ void foldMoveRange(win_T *const wp, garray_T *gap, const linenr_T line1, const l
#undef FOLD_INDEX
// foldMerge() {{{2
-/*
- * Merge two adjacent folds (and the nested ones in them).
- * This only works correctly when the folds are really adjacent! Thus "fp1"
- * must end just above "fp2".
- * The resulting fold is "fp1", nested folds are moved from "fp2" to "fp1".
- * Fold entry "fp2" in "gap" is deleted.
- */
+/// Merge two adjacent folds (and the nested ones in them).
+/// This only works correctly when the folds are really adjacent! Thus "fp1"
+/// must end just above "fp2".
+/// The resulting fold is "fp1", nested folds are moved from "fp2" to "fp1".
+/// Fold entry "fp2" in "gap" is deleted.
static void foldMerge(win_T *const wp, fold_T *fp1, garray_T *gap, fold_T *fp2)
{
fold_T *fp3;
@@ -2968,11 +2893,10 @@ static void foldMerge(win_T *const wp, fold_T *fp1, garray_T *gap, fold_T *fp2)
}
// foldlevelIndent() {{{2
-/*
- * Low level function to get the foldlevel for the "indent" method.
- * Doesn't use any caching.
- * Returns a level of -1 if the foldlevel depends on surrounding lines.
- */
+/// Low level function to get the foldlevel for the "indent" method.
+/// Doesn't use any caching.
+///
+/// @return a level of -1 if the foldlevel depends on surrounding lines.
static void foldlevelIndent(fline_T *flp)
{
char_u *s;
@@ -3000,10 +2924,8 @@ static void foldlevelIndent(fline_T *flp)
}
// foldlevelDiff() {{{2
-/*
- * Low level function to get the foldlevel for the "diff" method.
- * Doesn't use any caching.
- */
+/// Low level function to get the foldlevel for the "diff" method.
+/// Doesn't use any caching.
static void foldlevelDiff(fline_T *flp)
{
if (diff_infold(flp->wp, flp->lnum + flp->off)) {
@@ -3014,11 +2936,10 @@ static void foldlevelDiff(fline_T *flp)
}
// foldlevelExpr() {{{2
-/*
- * Low level function to get the foldlevel for the "expr" method.
- * Doesn't use any caching.
- * Returns a level of -1 if the foldlevel depends on surrounding lines.
- */
+/// Low level function to get the foldlevel for the "expr" method.
+/// Doesn't use any caching.
+///
+/// @return a level of -1 if the foldlevel depends on surrounding lines.
static void foldlevelExpr(fline_T *flp)
{
win_T *win;
@@ -3113,11 +3034,9 @@ static void foldlevelExpr(fline_T *flp)
}
// parseMarker() {{{2
-/*
- * Parse 'foldmarker' and set "foldendmarker", "foldstartmarkerlen" and
- * "foldendmarkerlen".
- * Relies on the option value to have been checked for correctness already.
- */
+/// Parse 'foldmarker' and set "foldendmarker", "foldstartmarkerlen" and
+/// "foldendmarkerlen".
+/// Relies on the option value to have been checked for correctness already.
static void parseMarker(win_T *wp)
{
foldendmarker = vim_strchr(wp->w_p_fmr, ',');
@@ -3126,15 +3045,13 @@ static void parseMarker(win_T *wp)
}
// foldlevelMarker() {{{2
-/*
- * Low level function to get the foldlevel for the "marker" method.
- * "foldendmarker", "foldstartmarkerlen" and "foldendmarkerlen" must have been
- * set before calling this.
- * Requires that flp->lvl is set to the fold level of the previous line!
- * Careful: This means you can't call this function twice on the same line.
- * Doesn't use any caching.
- * Sets flp->start when a start marker was found.
- */
+/// Low level function to get the foldlevel for the "marker" method.
+/// "foldendmarker", "foldstartmarkerlen" and "foldendmarkerlen" must have been
+/// set before calling this.
+/// Requires that flp->lvl is set to the fold level of the previous line!
+/// Careful: This means you can't call this function twice on the same line.
+/// Doesn't use any caching.
+/// Sets flp->start when a start marker was found.
static void foldlevelMarker(fline_T *flp)
{
char_u *startmarker;
@@ -3205,10 +3122,8 @@ static void foldlevelMarker(fline_T *flp)
}
// foldlevelSyntax() {{{2
-/*
- * Low level function to get the foldlevel for the "syntax" method.
- * Doesn't use any caching.
- */
+/// Low level function to get the foldlevel for the "syntax" method.
+/// Doesn't use any caching.
static void foldlevelSyntax(fline_T *flp)
{
linenr_T lnum = flp->lnum + flp->off;
@@ -3228,11 +3143,9 @@ static void foldlevelSyntax(fline_T *flp)
// functions for storing the fold state in a View {{{1
// put_folds() {{{2
-
-/*
- * Write commands to "fd" to restore the manual folds in window "wp".
- * Return FAIL if writing fails.
- */
+/// Write commands to "fd" to restore the manual folds in window "wp".
+///
+/// @return FAIL if writing fails.
int put_folds(FILE *fd, win_T *wp)
{
if (foldmethodIsManual(wp)) {
@@ -3252,10 +3165,9 @@ int put_folds(FILE *fd, win_T *wp)
}
// put_folds_recurse() {{{2
-/*
- * Write commands to "fd" to recreate manually created folds.
- * Returns FAIL when writing failed.
- */
+/// Write commands to "fd" to recreate manually created folds.
+///
+/// @return FAIL when writing failed.
static int put_folds_recurse(FILE *fd, garray_T *gap, linenr_T off)
{
fold_T *fp = (fold_T *)gap->ga_data;
@@ -3276,10 +3188,9 @@ static int put_folds_recurse(FILE *fd, garray_T *gap, linenr_T off)
}
// put_foldopen_recurse() {{{2
-/*
- * Write commands to "fd" to open and close manually opened/closed folds.
- * Returns FAIL when writing failed.
- */
+/// Write commands to "fd" to open and close manually opened/closed folds.
+///
+/// @return FAIL when writing failed.
static int put_foldopen_recurse(FILE *fd, win_T *wp, garray_T *gap, linenr_T off)
{
int level;
@@ -3325,10 +3236,9 @@ static int put_foldopen_recurse(FILE *fd, win_T *wp, garray_T *gap, linenr_T off
}
// put_fold_open_close() {{{2
-/*
- * Write the open or close command to "fd".
- * Returns FAIL when writing failed.
- */
+/// Write the open or close command to "fd".
+///
+/// @return FAIL when writing failed.
static int put_fold_open_close(FILE *fd, fold_T *fp, linenr_T off)
{
if (fprintf(fd, "%" PRId64, (int64_t)(fp->fd_top + off)) < 0
diff --git a/src/nvim/generators/c_grammar.lua b/src/nvim/generators/c_grammar.lua
index f35817c466..70a7be86b5 100644
--- a/src/nvim/generators/c_grammar.lua
+++ b/src/nvim/generators/c_grammar.lua
@@ -49,6 +49,7 @@ local c_proto = Ct(
(fill * Cg((P('FUNC_API_REMOTE_IMPL') * Cc(true)), 'remote_impl') ^ -1) *
(fill * Cg((P('FUNC_API_BRIDGE_IMPL') * Cc(true)), 'bridge_impl') ^ -1) *
(fill * Cg((P('FUNC_API_COMPOSITOR_IMPL') * Cc(true)), 'compositor_impl') ^ -1) *
+ (fill * Cg((P('FUNC_API_CLIENT_IMPL') * Cc(true)), 'client_impl') ^ -1) *
fill * P(';')
)
diff --git a/src/nvim/generators/gen_api_ui_events.lua b/src/nvim/generators/gen_api_ui_events.lua
index 3cb117d8b5..5e70442dce 100644..100755
--- a/src/nvim/generators/gen_api_ui_events.lua
+++ b/src/nvim/generators/gen_api_ui_events.lua
@@ -3,13 +3,14 @@ local mpack = require('mpack')
local nvimdir = arg[1]
package.path = nvimdir .. '/?.lua;' .. package.path
-assert(#arg == 7)
+assert(#arg == 8)
local input = io.open(arg[2], 'rb')
local proto_output = io.open(arg[3], 'wb')
local call_output = io.open(arg[4], 'wb')
local remote_output = io.open(arg[5], 'wb')
local bridge_output = io.open(arg[6], 'wb')
local metadata_output = io.open(arg[7], 'wb')
+local client_output = io.open(arg[8], 'wb')
local c_grammar = require('generators.c_grammar')
local events = c_grammar.grammar:match(input:read('*all'))
@@ -50,6 +51,52 @@ local function write_arglist(output, ev, need_copy)
end
end
+local function call_ui_event_method(output, ev)
+ output:write('void ui_client_event_'..ev.name..'(Array args)\n{\n')
+
+ local hlattrs_args_count = 0
+ if #ev.parameters > 0 then
+ output:write(' if (args.size < '..(#ev.parameters))
+ for j = 1, #ev.parameters do
+ local kind = ev.parameters[j][1]
+ if kind ~= "Object" then
+ if kind == 'HlAttrs' then kind = 'Dictionary' end
+ output:write('\n || args.items['..(j-1)..'].type != kObjectType'..kind..'')
+ end
+ end
+ output:write(') {\n')
+ output:write(' ELOG("Error handling ui event \''..ev.name..'\'");\n')
+ output:write(' return;\n')
+ output:write(' }\n')
+ end
+
+ for j = 1, #ev.parameters do
+ local param = ev.parameters[j]
+ local kind = param[1]
+ output:write(' '..kind..' arg_'..j..' = ')
+ if kind == 'HlAttrs' then
+ -- The first HlAttrs argument is rgb_attrs and second is cterm_attrs
+ output:write('ui_client_dict2hlattrs(args.items['..(j-1)..'].data.dictionary, '..(hlattrs_args_count == 0 and 'true' or 'false')..');\n')
+ hlattrs_args_count = hlattrs_args_count + 1
+ elseif kind == 'Object' then
+ output:write('args.items['..(j-1)..'];\n')
+ else
+ output:write('args.items['..(j-1)..'].data.'..string.lower(kind)..';\n')
+ end
+ end
+
+ output:write(' ui_call_'..ev.name..'(')
+ for j = 1, #ev.parameters do
+ output:write('arg_'..j)
+ if j ~= #ev.parameters then
+ output:write(', ')
+ end
+ end
+ output:write(');\n')
+
+ output:write('}\n\n')
+end
+
for i = 1, #events do
local ev = events[i]
assert(ev.return_type == 'void')
@@ -160,12 +207,35 @@ for i = 1, #events do
call_output:write(";\n")
call_output:write("}\n\n")
end
+
+ if (not ev.remote_only) and (not ev.noexport) and (not ev.client_impl) then
+ call_ui_event_method(client_output, ev)
+ end
end
+-- Generate the map_init method for client handlers
+client_output:write([[
+void ui_client_methods_table_init(void)
+{
+
+]])
+
+for i = 1, #events do
+ local fn = events[i]
+ if (not fn.noexport) and ((not fn.remote_only) or fn.client_impl) then
+ client_output:write(' add_ui_client_event_handler('..
+ '(String) {.data = "'..fn.name..'", '..
+ '.size = sizeof("'..fn.name..'") - 1}, '..
+ '(UIClientHandler) ui_client_event_'..fn.name..');\n')
+ end
+end
+
+client_output:write('\n}\n\n')
+
proto_output:close()
call_output:close()
remote_output:close()
-bridge_output:close()
+client_output:close()
-- don't expose internal attributes like "impl_name" in public metadata
local exported_attributes = {'name', 'parameters',
diff --git a/src/nvim/getchar.c b/src/nvim/getchar.c
index 299456f688..3ec5d24753 100644
--- a/src/nvim/getchar.c
+++ b/src/nvim/getchar.c
@@ -842,7 +842,10 @@ static void init_typebuf(void)
void init_default_mappings(void)
{
add_map((char_u *)"Y y$", NORMAL, true);
- add_map((char_u *)"<C-L> <Cmd>nohlsearch<Bar>diffupdate<CR><C-L>", NORMAL, true);
+
+ // Use normal! <C-L> to prevent inserting raw <C-L> when using i_<C-O>
+ // See https://github.com/neovim/neovim/issues/17473
+ add_map((char_u *)"<C-L> <Cmd>nohlsearch<Bar>diffupdate<Bar>normal! <C-L><CR>", NORMAL, true);
add_map((char_u *)"<C-U> <C-G>u<C-U>", INSERT, true);
add_map((char_u *)"<C-W> <C-G>u<C-W>", INSERT, true);
}
diff --git a/src/nvim/globals.h b/src/nvim/globals.h
index 35ad57906b..605a2183f3 100644
--- a/src/nvim/globals.h
+++ b/src/nvim/globals.h
@@ -342,6 +342,9 @@ EXTERN sctx_T current_sctx INIT(= { 0 COMMA 0 COMMA 0 });
// ID of the current channel making a client API call
EXTERN uint64_t current_channel_id INIT(= 0);
+// ID of the client channel. Used by ui client
+EXTERN uint64_t ui_client_channel_id INIT(= 0);
+
EXTERN bool did_source_packages INIT(= false);
// Scope information for the code that indirectly triggered the current
@@ -358,6 +361,11 @@ EXTERN int provider_call_nesting INIT(= 0);
EXTERN int t_colors INIT(= 256); // int value of T_CCO
+// Flags to indicate an additional string for highlight name completion.
+EXTERN int include_none INIT(= 0); // when 1 include "None"
+EXTERN int include_default INIT(= 0); // when 1 include "default"
+EXTERN int include_link INIT(= 0); // when 2 include "link" and "clear"
+
// When highlight_match is true, highlight a match, starting at the cursor
// position. Search_match_lines is the number of lines after the match (0 for
// a match within one line), search_match_endcol the column number of the
@@ -445,10 +453,11 @@ EXTERN int aucmd_win_used INIT(= false); // aucmd_win is being used
EXTERN frame_T *topframe; // top of the window frame tree
// Tab pages are alternative topframes. "first_tabpage" points to the first
-// one in the list, "curtab" is the current one.
+// one in the list, "curtab" is the current one. "lastused_tabpage" is the
+// last used one.
EXTERN tabpage_T *first_tabpage;
-EXTERN tabpage_T *lastused_tabpage;
EXTERN tabpage_T *curtab;
+EXTERN tabpage_T *lastused_tabpage;
EXTERN bool redraw_tabline INIT(= false); // need to redraw tabline
// Iterates over all tabs in the tab list
diff --git a/src/nvim/hardcopy.c b/src/nvim/hardcopy.c
index 93c8c53e33..575b239f5a 100644
--- a/src/nvim/hardcopy.c
+++ b/src/nvim/hardcopy.c
@@ -22,6 +22,7 @@
#include "nvim/fileio.h"
#include "nvim/garray.h"
#include "nvim/hardcopy.h"
+#include "nvim/highlight_group.h"
#include "nvim/mbyte.h"
#include "nvim/memline.h"
#include "nvim/memory.h"
diff --git a/src/nvim/highlight.c b/src/nvim/highlight.c
index abbda1e9fa..7d91f38d56 100644
--- a/src/nvim/highlight.c
+++ b/src/nvim/highlight.c
@@ -8,13 +8,13 @@
#include "nvim/decoration_provider.h"
#include "nvim/highlight.h"
#include "nvim/highlight_defs.h"
+#include "nvim/highlight_group.h"
#include "nvim/lua/executor.h"
#include "nvim/map.h"
#include "nvim/message.h"
#include "nvim/option.h"
#include "nvim/popupmnu.h"
#include "nvim/screen.h"
-#include "nvim/syntax.h"
#include "nvim/ui.h"
#include "nvim/vim.h"
diff --git a/src/nvim/highlight_defs.h b/src/nvim/highlight_defs.h
index dcfb9358bb..e0ee649013 100644
--- a/src/nvim/highlight_defs.h
+++ b/src/nvim/highlight_defs.h
@@ -74,7 +74,8 @@ typedef enum {
HLF_R, // return to continue message and yes/no questions
HLF_S, // status lines
HLF_SNC, // status lines of not-current windows
- HLF_C, // column to separate vertically split windows
+ HLF_C, // window split separators
+ HLF_VSP, // VertSplit
HLF_T, // Titles for output from ":set all", ":autocmd" etc.
HLF_V, // Visual mode
HLF_VNC, // Visual mode, autoselecting and not clipboard owner
@@ -133,10 +134,11 @@ EXTERN const char *hlf_names[] INIT(= {
[HLF_R] = "Question",
[HLF_S] = "StatusLine",
[HLF_SNC] = "StatusLineNC",
- [HLF_C] = "VertSplit",
+ [HLF_C] = "WinSeparator",
[HLF_T] = "Title",
[HLF_V] = "Visual",
[HLF_VNC] = "VisualNC",
+ [HLF_VSP] = "VertSplit",
[HLF_W] = "WarningMsg",
[HLF_WM] = "WildMenu",
[HLF_FL] = "Folded",
diff --git a/src/nvim/highlight_group.c b/src/nvim/highlight_group.c
new file mode 100644
index 0000000000..f342ada3db
--- /dev/null
+++ b/src/nvim/highlight_group.c
@@ -0,0 +1,2799 @@
+// This is an open source non-commercial project. Dear PVS-Studio, please check
+// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+
+// highlight_group.c: code for managing highlight groups
+
+#include "nvim/autocmd.h"
+#include "nvim/api/private/helpers.h"
+#include "nvim/charset.h"
+#include "nvim/cursor_shape.h"
+#include "nvim/ex_docmd.h"
+#include "nvim/garray.h"
+#include "nvim/highlight.h"
+#include "nvim/highlight_group.h"
+#include "nvim/lua/executor.h"
+#include "nvim/map.h"
+#include "nvim/option.h"
+#include "nvim/runtime.h"
+#include "nvim/screen.h"
+
+/// \addtogroup SG_SET
+/// @{
+#define SG_CTERM 2 // cterm has been set
+#define SG_GUI 4 // gui has been set
+#define SG_LINK 8 // link has been set
+/// @}
+
+#define MAX_SYN_NAME 200
+
+// builtin |highlight-groups|
+static garray_T highlight_ga = GA_EMPTY_INIT_VALUE;
+
+Map(cstr_t, int) highlight_unames = MAP_INIT;
+
+/// The "term", "cterm" and "gui" arguments can be any combination of the
+/// following names, separated by commas (but no spaces!).
+static char *(hl_name_table[]) =
+ { "bold", "standout", "underline", "underlineline", "undercurl", "underdot",
+ "underdash", "italic", "reverse", "inverse", "strikethrough", "nocombine", "NONE" };
+static int hl_attr_table[] =
+ { HL_BOLD, HL_STANDOUT, HL_UNDERLINE, HL_UNDERLINELINE, HL_UNDERCURL, HL_UNDERDOT, HL_UNDERDASH,
+ HL_ITALIC, HL_INVERSE, HL_INVERSE, HL_STRIKETHROUGH, HL_NOCOMBINE, 0 };
+
+/// Structure that stores information about a highlight group.
+/// The ID of a highlight group is also called group ID. It is the index in
+/// the highlight_ga array PLUS ONE.
+typedef struct {
+ char_u *sg_name; ///< highlight group name
+ char *sg_name_u; ///< uppercase of sg_name
+ bool sg_cleared; ///< "hi clear" was used
+ int sg_attr; ///< Screen attr @see ATTR_ENTRY
+ int sg_link; ///< link to this highlight group ID
+ int sg_deflink; ///< default link; restored in highlight_clear()
+ int sg_set; ///< combination of flags in \ref SG_SET
+ sctx_T sg_deflink_sctx; ///< script where the default link was set
+ sctx_T sg_script_ctx; ///< script in which the group was last set
+ // for terminal UIs
+ int sg_cterm; ///< "cterm=" highlighting attr
+ ///< (combination of \ref HlAttrFlags)
+ int sg_cterm_fg; ///< terminal fg color number + 1
+ int sg_cterm_bg; ///< terminal bg color number + 1
+ bool sg_cterm_bold; ///< bold attr was set for light color
+ // for RGB UIs
+ int sg_gui; ///< "gui=" highlighting attributes
+ ///< (combination of \ref HlAttrFlags)
+ RgbValue sg_rgb_fg; ///< RGB foreground color
+ RgbValue sg_rgb_bg; ///< RGB background color
+ RgbValue sg_rgb_sp; ///< RGB special color
+ char *sg_rgb_fg_name; ///< RGB foreground color name
+ char *sg_rgb_bg_name; ///< RGB background color name
+ char *sg_rgb_sp_name; ///< RGB special color name
+
+ int sg_blend; ///< blend level (0-100 inclusive), -1 if unset
+} HlGroup;
+
+#ifdef INCLUDE_GENERATED_DECLARATIONS
+# include "highlight_group.c.generated.h"
+#endif
+
+static inline HlGroup *HL_TABLE(void)
+{
+ return ((HlGroup *)((highlight_ga.ga_data)));
+}
+
+// The default highlight groups. These are compiled-in for fast startup and
+// they still work when the runtime files can't be found.
+//
+// When making changes here, also change runtime/colors/default.vim!
+
+static const char *highlight_init_both[] = {
+ "Conceal ctermbg=DarkGrey ctermfg=LightGrey guibg=DarkGrey guifg=LightGrey",
+ "Cursor guibg=fg guifg=bg",
+ "lCursor guibg=fg guifg=bg",
+ "DiffText cterm=bold ctermbg=Red gui=bold guibg=Red",
+ "ErrorMsg ctermbg=DarkRed ctermfg=White guibg=Red guifg=White",
+ "IncSearch cterm=reverse gui=reverse",
+ "ModeMsg cterm=bold gui=bold",
+ "NonText ctermfg=Blue gui=bold guifg=Blue",
+ "Normal cterm=NONE gui=NONE",
+ "PmenuSbar ctermbg=Grey guibg=Grey",
+ "StatusLine cterm=reverse,bold gui=reverse,bold",
+ "StatusLineNC cterm=reverse gui=reverse",
+ "TabLineFill cterm=reverse gui=reverse",
+ "TabLineSel cterm=bold gui=bold",
+ "TermCursor cterm=reverse gui=reverse",
+ "VertSplit cterm=reverse gui=reverse",
+ "WildMenu ctermbg=Yellow ctermfg=Black guibg=Yellow guifg=Black",
+ "default link WinSeparator VertSplit",
+ "default link EndOfBuffer NonText",
+ "default link LineNrAbove LineNr",
+ "default link LineNrBelow LineNr",
+ "default link QuickFixLine Search",
+ "default link CursorLineSign SignColumn",
+ "default link CursorLineFold FoldColumn",
+ "default link Substitute Search",
+ "default link Whitespace NonText",
+ "default link MsgSeparator StatusLine",
+ "default link NormalFloat Pmenu",
+ "default link FloatBorder WinSeparator",
+ "default FloatShadow blend=80 guibg=Black",
+ "default FloatShadowThrough blend=100 guibg=Black",
+ "RedrawDebugNormal cterm=reverse gui=reverse",
+ "RedrawDebugClear ctermbg=Yellow guibg=Yellow",
+ "RedrawDebugComposed ctermbg=Green guibg=Green",
+ "RedrawDebugRecompose ctermbg=Red guibg=Red",
+ "Error term=reverse cterm=NONE ctermfg=White ctermbg=Red gui=NONE guifg=White guibg=Red",
+ "Todo term=standout cterm=NONE ctermfg=Black ctermbg=Yellow gui=NONE guifg=Blue guibg=Yellow",
+ "default link String Constant",
+ "default link Character Constant",
+ "default link Number Constant",
+ "default link Boolean Constant",
+ "default link Float Number",
+ "default link Function Identifier",
+ "default link Conditional Statement",
+ "default link Repeat Statement",
+ "default link Label Statement",
+ "default link Operator Statement",
+ "default link Keyword Statement",
+ "default link Exception Statement",
+ "default link Include PreProc",
+ "default link Define PreProc",
+ "default link Macro PreProc",
+ "default link PreCondit PreProc",
+ "default link StorageClass Type",
+ "default link Structure Type",
+ "default link Typedef Type",
+ "default link Tag Special",
+ "default link SpecialChar Special",
+ "default link Delimiter Special",
+ "default link SpecialComment Special",
+ "default link Debug Special",
+ "default DiagnosticError ctermfg=1 guifg=Red",
+ "default DiagnosticWarn ctermfg=3 guifg=Orange",
+ "default DiagnosticInfo ctermfg=4 guifg=LightBlue",
+ "default DiagnosticHint ctermfg=7 guifg=LightGrey",
+ "default DiagnosticUnderlineError cterm=underline gui=underline guisp=Red",
+ "default DiagnosticUnderlineWarn cterm=underline gui=underline guisp=Orange",
+ "default DiagnosticUnderlineInfo cterm=underline gui=underline guisp=LightBlue",
+ "default DiagnosticUnderlineHint cterm=underline gui=underline guisp=LightGrey",
+ "default link DiagnosticVirtualTextError DiagnosticError",
+ "default link DiagnosticVirtualTextWarn DiagnosticWarn",
+ "default link DiagnosticVirtualTextInfo DiagnosticInfo",
+ "default link DiagnosticVirtualTextHint DiagnosticHint",
+ "default link DiagnosticFloatingError DiagnosticError",
+ "default link DiagnosticFloatingWarn DiagnosticWarn",
+ "default link DiagnosticFloatingInfo DiagnosticInfo",
+ "default link DiagnosticFloatingHint DiagnosticHint",
+ "default link DiagnosticSignError DiagnosticError",
+ "default link DiagnosticSignWarn DiagnosticWarn",
+ "default link DiagnosticSignInfo DiagnosticInfo",
+ "default link DiagnosticSignHint DiagnosticHint",
+ NULL
+};
+
+// Default colors only used with a light background.
+static const char *highlight_init_light[] = {
+ "ColorColumn ctermbg=LightRed guibg=LightRed",
+ "CursorColumn ctermbg=LightGrey guibg=Grey90",
+ "CursorLine cterm=underline guibg=Grey90",
+ "CursorLineNr cterm=underline ctermfg=Brown gui=bold guifg=Brown",
+ "DiffAdd ctermbg=LightBlue guibg=LightBlue",
+ "DiffChange ctermbg=LightMagenta guibg=LightMagenta",
+ "DiffDelete ctermfg=Blue ctermbg=LightCyan gui=bold guifg=Blue guibg=LightCyan",
+ "Directory ctermfg=DarkBlue guifg=Blue",
+ "FoldColumn ctermbg=Grey ctermfg=DarkBlue guibg=Grey guifg=DarkBlue",
+ "Folded ctermbg=Grey ctermfg=DarkBlue guibg=LightGrey guifg=DarkBlue",
+ "LineNr ctermfg=Brown guifg=Brown",
+ "MatchParen ctermbg=Cyan guibg=Cyan",
+ "MoreMsg ctermfg=DarkGreen gui=bold guifg=SeaGreen",
+ "Pmenu ctermbg=LightMagenta ctermfg=Black guibg=LightMagenta",
+ "PmenuSel ctermbg=LightGrey ctermfg=Black guibg=Grey",
+ "PmenuThumb ctermbg=Black guibg=Black",
+ "Question ctermfg=DarkGreen gui=bold guifg=SeaGreen",
+ "Search ctermbg=Yellow ctermfg=NONE guibg=Yellow guifg=NONE",
+ "SignColumn ctermbg=Grey ctermfg=DarkBlue guibg=Grey guifg=DarkBlue",
+ "SpecialKey ctermfg=DarkBlue guifg=Blue",
+ "SpellBad ctermbg=LightRed guisp=Red gui=undercurl",
+ "SpellCap ctermbg=LightBlue guisp=Blue gui=undercurl",
+ "SpellLocal ctermbg=Cyan guisp=DarkCyan gui=undercurl",
+ "SpellRare ctermbg=LightMagenta guisp=Magenta gui=undercurl",
+ "TabLine cterm=underline ctermfg=black ctermbg=LightGrey gui=underline guibg=LightGrey",
+ "Title ctermfg=DarkMagenta gui=bold guifg=Magenta",
+ "Visual guibg=LightGrey",
+ "WarningMsg ctermfg=DarkRed guifg=Red",
+ "Comment term=bold cterm=NONE ctermfg=DarkBlue ctermbg=NONE gui=NONE guifg=Blue guibg=NONE",
+ "Constant term=underline cterm=NONE ctermfg=DarkRed ctermbg=NONE gui=NONE guifg=Magenta guibg=NONE",
+ "Special term=bold cterm=NONE ctermfg=DarkMagenta ctermbg=NONE gui=NONE guifg=#6a5acd guibg=NONE",
+ "Identifier term=underline cterm=NONE ctermfg=DarkCyan ctermbg=NONE gui=NONE guifg=DarkCyan guibg=NONE",
+ "Statement term=bold cterm=NONE ctermfg=Brown ctermbg=NONE gui=bold guifg=Brown guibg=NONE",
+ "PreProc term=underline cterm=NONE ctermfg=DarkMagenta ctermbg=NONE gui=NONE guifg=#6a0dad guibg=NONE",
+ "Type term=underline cterm=NONE ctermfg=DarkGreen ctermbg=NONE gui=bold guifg=SeaGreen guibg=NONE",
+ "Underlined term=underline cterm=underline ctermfg=DarkMagenta gui=underline guifg=SlateBlue",
+ "Ignore term=NONE cterm=NONE ctermfg=white ctermbg=NONE gui=NONE guifg=bg guibg=NONE",
+ NULL
+};
+
+// Default colors only used with a dark background.
+static const char *highlight_init_dark[] = {
+ "ColorColumn ctermbg=DarkRed guibg=DarkRed",
+ "CursorColumn ctermbg=DarkGrey guibg=Grey40",
+ "CursorLine cterm=underline guibg=Grey40",
+ "CursorLineNr cterm=underline ctermfg=Yellow gui=bold guifg=Yellow",
+ "DiffAdd ctermbg=DarkBlue guibg=DarkBlue",
+ "DiffChange ctermbg=DarkMagenta guibg=DarkMagenta",
+ "DiffDelete ctermfg=Blue ctermbg=DarkCyan gui=bold guifg=Blue guibg=DarkCyan",
+ "Directory ctermfg=LightCyan guifg=Cyan",
+ "FoldColumn ctermbg=DarkGrey ctermfg=Cyan guibg=Grey guifg=Cyan",
+ "Folded ctermbg=DarkGrey ctermfg=Cyan guibg=DarkGrey guifg=Cyan",
+ "LineNr ctermfg=Yellow guifg=Yellow",
+ "MatchParen ctermbg=DarkCyan guibg=DarkCyan",
+ "MoreMsg ctermfg=LightGreen gui=bold guifg=SeaGreen",
+ "Pmenu ctermbg=Magenta ctermfg=Black guibg=Magenta",
+ "PmenuSel ctermbg=Black ctermfg=DarkGrey guibg=DarkGrey",
+ "PmenuThumb ctermbg=White guibg=White",
+ "Question ctermfg=LightGreen gui=bold guifg=Green",
+ "Search ctermbg=Yellow ctermfg=Black guibg=Yellow guifg=Black",
+ "SignColumn ctermbg=DarkGrey ctermfg=Cyan guibg=Grey guifg=Cyan",
+ "SpecialKey ctermfg=LightBlue guifg=Cyan",
+ "SpellBad ctermbg=Red guisp=Red gui=undercurl",
+ "SpellCap ctermbg=Blue guisp=Blue gui=undercurl",
+ "SpellLocal ctermbg=Cyan guisp=Cyan gui=undercurl",
+ "SpellRare ctermbg=Magenta guisp=Magenta gui=undercurl",
+ "TabLine cterm=underline ctermfg=white ctermbg=DarkGrey gui=underline guibg=DarkGrey",
+ "Title ctermfg=LightMagenta gui=bold guifg=Magenta",
+ "Visual guibg=DarkGrey",
+ "WarningMsg ctermfg=LightRed guifg=Red",
+ "Comment term=bold cterm=NONE ctermfg=Cyan ctermbg=NONE gui=NONE guifg=#80a0ff guibg=NONE",
+ "Constant term=underline cterm=NONE ctermfg=Magenta ctermbg=NONE gui=NONE guifg=#ffa0a0 guibg=NONE",
+ "Special term=bold cterm=NONE ctermfg=LightRed ctermbg=NONE gui=NONE guifg=Orange guibg=NONE",
+ "Identifier term=underline cterm=bold ctermfg=Cyan ctermbg=NONE gui=NONE guifg=#40ffff guibg=NONE",
+ "Statement term=bold cterm=NONE ctermfg=Yellow ctermbg=NONE gui=bold guifg=#ffff60 guibg=NONE",
+ "PreProc term=underline cterm=NONE ctermfg=LightBlue ctermbg=NONE gui=NONE guifg=#ff80ff guibg=NONE",
+ "Type term=underline cterm=NONE ctermfg=LightGreen ctermbg=NONE gui=bold guifg=#60ff60 guibg=NONE",
+ "Underlined term=underline cterm=underline ctermfg=LightBlue gui=underline guifg=#80a0ff",
+ "Ignore term=NONE cterm=NONE ctermfg=black ctermbg=NONE gui=NONE guifg=bg guibg=NONE",
+ NULL
+};
+
+const char *const highlight_init_cmdline[] = {
+ // XXX When modifying a list modify it in both valid and invalid halves.
+ // TODO(ZyX-I): merge valid and invalid groups via a macros.
+
+ // NvimInternalError should appear only when highlighter has a bug.
+ "NvimInternalError ctermfg=Red ctermbg=Red guifg=Red guibg=Red",
+
+ // Highlight groups (links) used by parser:
+
+ "default link NvimAssignment Operator",
+ "default link NvimPlainAssignment NvimAssignment",
+ "default link NvimAugmentedAssignment NvimAssignment",
+ "default link NvimAssignmentWithAddition NvimAugmentedAssignment",
+ "default link NvimAssignmentWithSubtraction NvimAugmentedAssignment",
+ "default link NvimAssignmentWithConcatenation NvimAugmentedAssignment",
+
+ "default link NvimOperator Operator",
+
+ "default link NvimUnaryOperator NvimOperator",
+ "default link NvimUnaryPlus NvimUnaryOperator",
+ "default link NvimUnaryMinus NvimUnaryOperator",
+ "default link NvimNot NvimUnaryOperator",
+
+ "default link NvimBinaryOperator NvimOperator",
+ "default link NvimComparison NvimBinaryOperator",
+ "default link NvimComparisonModifier NvimComparison",
+ "default link NvimBinaryPlus NvimBinaryOperator",
+ "default link NvimBinaryMinus NvimBinaryOperator",
+ "default link NvimConcat NvimBinaryOperator",
+ "default link NvimConcatOrSubscript NvimConcat",
+ "default link NvimOr NvimBinaryOperator",
+ "default link NvimAnd NvimBinaryOperator",
+ "default link NvimMultiplication NvimBinaryOperator",
+ "default link NvimDivision NvimBinaryOperator",
+ "default link NvimMod NvimBinaryOperator",
+
+ "default link NvimTernary NvimOperator",
+ "default link NvimTernaryColon NvimTernary",
+
+ "default link NvimParenthesis Delimiter",
+ "default link NvimLambda NvimParenthesis",
+ "default link NvimNestingParenthesis NvimParenthesis",
+ "default link NvimCallingParenthesis NvimParenthesis",
+
+ "default link NvimSubscript NvimParenthesis",
+ "default link NvimSubscriptBracket NvimSubscript",
+ "default link NvimSubscriptColon NvimSubscript",
+ "default link NvimCurly NvimSubscript",
+
+ "default link NvimContainer NvimParenthesis",
+ "default link NvimDict NvimContainer",
+ "default link NvimList NvimContainer",
+
+ "default link NvimIdentifier Identifier",
+ "default link NvimIdentifierScope NvimIdentifier",
+ "default link NvimIdentifierScopeDelimiter NvimIdentifier",
+ "default link NvimIdentifierName NvimIdentifier",
+ "default link NvimIdentifierKey NvimIdentifier",
+
+ "default link NvimColon Delimiter",
+ "default link NvimComma Delimiter",
+ "default link NvimArrow Delimiter",
+
+ "default link NvimRegister SpecialChar",
+ "default link NvimNumber Number",
+ "default link NvimFloat NvimNumber",
+ "default link NvimNumberPrefix Type",
+
+ "default link NvimOptionSigil Type",
+ "default link NvimOptionName NvimIdentifier",
+ "default link NvimOptionScope NvimIdentifierScope",
+ "default link NvimOptionScopeDelimiter NvimIdentifierScopeDelimiter",
+
+ "default link NvimEnvironmentSigil NvimOptionSigil",
+ "default link NvimEnvironmentName NvimIdentifier",
+
+ "default link NvimString String",
+ "default link NvimStringBody NvimString",
+ "default link NvimStringQuote NvimString",
+ "default link NvimStringSpecial SpecialChar",
+
+ "default link NvimSingleQuote NvimStringQuote",
+ "default link NvimSingleQuotedBody NvimStringBody",
+ "default link NvimSingleQuotedQuote NvimStringSpecial",
+
+ "default link NvimDoubleQuote NvimStringQuote",
+ "default link NvimDoubleQuotedBody NvimStringBody",
+ "default link NvimDoubleQuotedEscape NvimStringSpecial",
+
+ "default link NvimFigureBrace NvimInternalError",
+ "default link NvimSingleQuotedUnknownEscape NvimInternalError",
+
+ "default link NvimSpacing Normal",
+
+ // NvimInvalid groups:
+
+ "default link NvimInvalidSingleQuotedUnknownEscape NvimInternalError",
+
+ "default link NvimInvalid Error",
+
+ "default link NvimInvalidAssignment NvimInvalid",
+ "default link NvimInvalidPlainAssignment NvimInvalidAssignment",
+ "default link NvimInvalidAugmentedAssignment NvimInvalidAssignment",
+ "default link NvimInvalidAssignmentWithAddition NvimInvalidAugmentedAssignment",
+ "default link NvimInvalidAssignmentWithSubtraction NvimInvalidAugmentedAssignment",
+ "default link NvimInvalidAssignmentWithConcatenation NvimInvalidAugmentedAssignment",
+
+ "default link NvimInvalidOperator NvimInvalid",
+
+ "default link NvimInvalidUnaryOperator NvimInvalidOperator",
+ "default link NvimInvalidUnaryPlus NvimInvalidUnaryOperator",
+ "default link NvimInvalidUnaryMinus NvimInvalidUnaryOperator",
+ "default link NvimInvalidNot NvimInvalidUnaryOperator",
+
+ "default link NvimInvalidBinaryOperator NvimInvalidOperator",
+ "default link NvimInvalidComparison NvimInvalidBinaryOperator",
+ "default link NvimInvalidComparisonModifier NvimInvalidComparison",
+ "default link NvimInvalidBinaryPlus NvimInvalidBinaryOperator",
+ "default link NvimInvalidBinaryMinus NvimInvalidBinaryOperator",
+ "default link NvimInvalidConcat NvimInvalidBinaryOperator",
+ "default link NvimInvalidConcatOrSubscript NvimInvalidConcat",
+ "default link NvimInvalidOr NvimInvalidBinaryOperator",
+ "default link NvimInvalidAnd NvimInvalidBinaryOperator",
+ "default link NvimInvalidMultiplication NvimInvalidBinaryOperator",
+ "default link NvimInvalidDivision NvimInvalidBinaryOperator",
+ "default link NvimInvalidMod NvimInvalidBinaryOperator",
+
+ "default link NvimInvalidTernary NvimInvalidOperator",
+ "default link NvimInvalidTernaryColon NvimInvalidTernary",
+
+ "default link NvimInvalidDelimiter NvimInvalid",
+
+ "default link NvimInvalidParenthesis NvimInvalidDelimiter",
+ "default link NvimInvalidLambda NvimInvalidParenthesis",
+ "default link NvimInvalidNestingParenthesis NvimInvalidParenthesis",
+ "default link NvimInvalidCallingParenthesis NvimInvalidParenthesis",
+
+ "default link NvimInvalidSubscript NvimInvalidParenthesis",
+ "default link NvimInvalidSubscriptBracket NvimInvalidSubscript",
+ "default link NvimInvalidSubscriptColon NvimInvalidSubscript",
+ "default link NvimInvalidCurly NvimInvalidSubscript",
+
+ "default link NvimInvalidContainer NvimInvalidParenthesis",
+ "default link NvimInvalidDict NvimInvalidContainer",
+ "default link NvimInvalidList NvimInvalidContainer",
+
+ "default link NvimInvalidValue NvimInvalid",
+
+ "default link NvimInvalidIdentifier NvimInvalidValue",
+ "default link NvimInvalidIdentifierScope NvimInvalidIdentifier",
+ "default link NvimInvalidIdentifierScopeDelimiter NvimInvalidIdentifier",
+ "default link NvimInvalidIdentifierName NvimInvalidIdentifier",
+ "default link NvimInvalidIdentifierKey NvimInvalidIdentifier",
+
+ "default link NvimInvalidColon NvimInvalidDelimiter",
+ "default link NvimInvalidComma NvimInvalidDelimiter",
+ "default link NvimInvalidArrow NvimInvalidDelimiter",
+
+ "default link NvimInvalidRegister NvimInvalidValue",
+ "default link NvimInvalidNumber NvimInvalidValue",
+ "default link NvimInvalidFloat NvimInvalidNumber",
+ "default link NvimInvalidNumberPrefix NvimInvalidNumber",
+
+ "default link NvimInvalidOptionSigil NvimInvalidIdentifier",
+ "default link NvimInvalidOptionName NvimInvalidIdentifier",
+ "default link NvimInvalidOptionScope NvimInvalidIdentifierScope",
+ "default link NvimInvalidOptionScopeDelimiter NvimInvalidIdentifierScopeDelimiter",
+
+ "default link NvimInvalidEnvironmentSigil NvimInvalidOptionSigil",
+ "default link NvimInvalidEnvironmentName NvimInvalidIdentifier",
+
+ // Invalid string bodies and specials are still highlighted as valid ones to
+ // minimize the red area.
+ "default link NvimInvalidString NvimInvalidValue",
+ "default link NvimInvalidStringBody NvimStringBody",
+ "default link NvimInvalidStringQuote NvimInvalidString",
+ "default link NvimInvalidStringSpecial NvimStringSpecial",
+
+ "default link NvimInvalidSingleQuote NvimInvalidStringQuote",
+ "default link NvimInvalidSingleQuotedBody NvimInvalidStringBody",
+ "default link NvimInvalidSingleQuotedQuote NvimInvalidStringSpecial",
+
+ "default link NvimInvalidDoubleQuote NvimInvalidStringQuote",
+ "default link NvimInvalidDoubleQuotedBody NvimInvalidStringBody",
+ "default link NvimInvalidDoubleQuotedEscape NvimInvalidStringSpecial",
+ "default link NvimInvalidDoubleQuotedUnknownEscape NvimInvalidValue",
+
+ "default link NvimInvalidFigureBrace NvimInvalidDelimiter",
+
+ "default link NvimInvalidSpacing ErrorMsg",
+
+ // Not actually invalid, but we highlight user that he is doing something
+ // wrong.
+ "default link NvimDoubleQuotedUnknownEscape NvimInvalidValue",
+ NULL,
+};
+
+/// Returns the number of highlight groups.
+int highlight_num_groups(void)
+{
+ return highlight_ga.ga_len;
+}
+
+/// Returns the name of a highlight group.
+char_u *highlight_group_name(int id)
+{
+ return HL_TABLE()[id].sg_name;
+}
+
+/// Returns the ID of the link to a highlight group.
+int highlight_link_id(int id)
+{
+ return HL_TABLE()[id].sg_link;
+}
+
+/// Create default links for Nvim* highlight groups used for cmdline coloring
+void syn_init_cmdline_highlight(bool reset, bool init)
+{
+ for (size_t i = 0; highlight_init_cmdline[i] != NULL; i++) {
+ do_highlight(highlight_init_cmdline[i], reset, init);
+ }
+}
+
+/// Load colors from a file if "g:colors_name" is set, otherwise load builtin
+/// colors
+///
+/// @param both include groups where 'bg' doesn't matter
+/// @param reset clear groups first
+void init_highlight(bool both, bool reset)
+{
+ static int had_both = false;
+
+ // Try finding the color scheme file. Used when a color file was loaded
+ // and 'background' or 't_Co' is changed.
+ char_u *p = get_var_value("g:colors_name");
+ if (p != NULL) {
+ // Value of g:colors_name could be freed in load_colors() and make
+ // p invalid, so copy it.
+ char_u *copy_p = vim_strsave(p);
+ bool okay = load_colors(copy_p);
+ xfree(copy_p);
+ if (okay) {
+ return;
+ }
+ }
+
+ // Didn't use a color file, use the compiled-in colors.
+ if (both) {
+ had_both = true;
+ const char *const *const pp = highlight_init_both;
+ for (size_t i = 0; pp[i] != NULL; i++) {
+ do_highlight(pp[i], reset, true);
+ }
+ } else if (!had_both) {
+ // Don't do anything before the call with both == true from main().
+ // Not everything has been setup then, and that call will overrule
+ // everything anyway.
+ return;
+ }
+
+ const char *const *const pp = ((*p_bg == 'l')
+ ? highlight_init_light
+ : highlight_init_dark);
+ for (size_t i = 0; pp[i] != NULL; i++) {
+ do_highlight(pp[i], reset, true);
+ }
+
+ // Reverse looks ugly, but grey may not work for 8 colors. Thus let it
+ // depend on the number of colors available.
+ // With 8 colors brown is equal to yellow, need to use black for Search fg
+ // to avoid Statement highlighted text disappears.
+ // Clear the attributes, needed when changing the t_Co value.
+ if (t_colors > 8) {
+ do_highlight((*p_bg == 'l'
+ ? "Visual cterm=NONE ctermbg=LightGrey"
+ : "Visual cterm=NONE ctermbg=DarkGrey"), false, true);
+ } else {
+ do_highlight("Visual cterm=reverse ctermbg=NONE", false, true);
+ if (*p_bg == 'l') {
+ do_highlight("Search ctermfg=black", false, true);
+ }
+ }
+
+ syn_init_cmdline_highlight(false, false);
+}
+
+/// Load color file "name".
+/// Return OK for success, FAIL for failure.
+int load_colors(char_u *name)
+{
+ char_u *buf;
+ int retval = FAIL;
+ static bool recursive = false;
+
+ // When being called recursively, this is probably because setting
+ // 'background' caused the highlighting to be reloaded. This means it is
+ // working, thus we should return OK.
+ if (recursive) {
+ return OK;
+ }
+
+ recursive = true;
+ size_t buflen = STRLEN(name) + 12;
+ buf = xmalloc(buflen);
+ apply_autocmds(EVENT_COLORSCHEMEPRE, name, curbuf->b_fname, false, curbuf);
+ snprintf((char *)buf, buflen, "colors/%s.vim", name);
+ retval = source_runtime((char *)buf, DIP_START + DIP_OPT);
+ if (retval == FAIL) {
+ snprintf((char *)buf, buflen, "colors/%s.lua", name);
+ retval = source_runtime((char *)buf, DIP_START + DIP_OPT);
+ }
+ xfree(buf);
+ apply_autocmds(EVENT_COLORSCHEME, name, curbuf->b_fname, false, curbuf);
+
+ recursive = false;
+
+ return retval;
+}
+
+static char *(color_names[28]) = {
+ "Black", "DarkBlue", "DarkGreen", "DarkCyan",
+ "DarkRed", "DarkMagenta", "Brown", "DarkYellow",
+ "Gray", "Grey", "LightGray", "LightGrey",
+ "DarkGray", "DarkGrey",
+ "Blue", "LightBlue", "Green", "LightGreen",
+ "Cyan", "LightCyan", "Red", "LightRed", "Magenta",
+ "LightMagenta", "Yellow", "LightYellow", "White", "NONE"
+};
+// indices:
+// 0, 1, 2, 3,
+// 4, 5, 6, 7,
+// 8, 9, 10, 11,
+// 12, 13,
+// 14, 15, 16, 17,
+// 18, 19, 20, 21, 22,
+// 23, 24, 25, 26, 27
+static int color_numbers_16[28] = { 0, 1, 2, 3,
+ 4, 5, 6, 6,
+ 7, 7, 7, 7,
+ 8, 8,
+ 9, 9, 10, 10,
+ 11, 11, 12, 12, 13,
+ 13, 14, 14, 15, -1 };
+// for xterm with 88 colors...
+static int color_numbers_88[28] = { 0, 4, 2, 6,
+ 1, 5, 32, 72,
+ 84, 84, 7, 7,
+ 82, 82,
+ 12, 43, 10, 61,
+ 14, 63, 9, 74, 13,
+ 75, 11, 78, 15, -1 };
+// for xterm with 256 colors...
+static int color_numbers_256[28] = { 0, 4, 2, 6,
+ 1, 5, 130, 3,
+ 248, 248, 7, 7,
+ 242, 242,
+ 12, 81, 10, 121,
+ 14, 159, 9, 224, 13,
+ 225, 11, 229, 15, -1 };
+// for terminals with less than 16 colors...
+static int color_numbers_8[28] = { 0, 4, 2, 6,
+ 1, 5, 3, 3,
+ 7, 7, 7, 7,
+ 0+8, 0+8,
+ 4+8, 4+8, 2+8, 2+8,
+ 6+8, 6+8, 1+8, 1+8, 5+8,
+ 5+8, 3+8, 3+8, 7+8, -1 };
+
+// Lookup the "cterm" value to be used for color with index "idx" in
+// color_names[].
+// "boldp" will be set to TRUE or FALSE for a foreground color when using 8
+// colors, otherwise it will be unchanged.
+int lookup_color(const int idx, const bool foreground, TriState *const boldp)
+{
+ int color = color_numbers_16[idx];
+
+ // Use the _16 table to check if it's a valid color name.
+ if (color < 0) {
+ return -1;
+ }
+
+ if (t_colors == 8) {
+ // t_Co is 8: use the 8 colors table
+ color = color_numbers_8[idx];
+ if (foreground) {
+ // set/reset bold attribute to get light foreground
+ // colors (on some terminals, e.g. "linux")
+ if (color & 8) {
+ *boldp = kTrue;
+ } else {
+ *boldp = kFalse;
+ }
+ }
+ color &= 7; // truncate to 8 colors
+ } else if (t_colors == 16) {
+ color = color_numbers_8[idx];
+ } else if (t_colors == 88) {
+ color = color_numbers_88[idx];
+ } else if (t_colors >= 256) {
+ color = color_numbers_256[idx];
+ }
+ return color;
+}
+
+void set_hl_group(int id, HlAttrs attrs, Dict(highlight) *dict, int link_id)
+{
+ int idx = id - 1; // Index is ID minus one.
+
+ bool is_default = attrs.rgb_ae_attr & HL_DEFAULT;
+
+ // Return if "default" was used and the group already has settings
+ if (is_default && hl_has_settings(idx, true)) {
+ return;
+ }
+
+ HlGroup *g = &HL_TABLE()[idx];
+
+ if (link_id > 0) {
+ g->sg_cleared = false;
+ g->sg_link = link_id;
+ g->sg_script_ctx = current_sctx;
+ g->sg_script_ctx.sc_lnum += sourcing_lnum;
+ g->sg_set |= SG_LINK;
+ if (is_default) {
+ g->sg_deflink = link_id;
+ g->sg_deflink_sctx = current_sctx;
+ g->sg_deflink_sctx.sc_lnum += sourcing_lnum;
+ }
+ return;
+ }
+
+ g->sg_cleared = false;
+ g->sg_link = 0;
+ g->sg_gui = attrs.rgb_ae_attr;
+
+ g->sg_rgb_fg = attrs.rgb_fg_color;
+ g->sg_rgb_bg = attrs.rgb_bg_color;
+ g->sg_rgb_sp = attrs.rgb_sp_color;
+
+ struct {
+ char **dest; RgbValue val; Object name;
+ } cattrs[] = {
+ { &g->sg_rgb_fg_name, g->sg_rgb_fg, HAS_KEY(dict->fg) ? dict->fg : dict->foreground },
+ { &g->sg_rgb_bg_name, g->sg_rgb_bg, HAS_KEY(dict->bg) ? dict->bg : dict->background },
+ { &g->sg_rgb_sp_name, g->sg_rgb_sp, HAS_KEY(dict->sp) ? dict->sp : dict->special },
+ { NULL, -1, NIL },
+ };
+
+ char hex_name[8];
+ char *name;
+
+ for (int j = 0; cattrs[j].dest; j++) {
+ if (cattrs[j].val < 0) {
+ XFREE_CLEAR(*cattrs[j].dest);
+ continue;
+ }
+
+ if (cattrs[j].name.type == kObjectTypeString && cattrs[j].name.data.string.size) {
+ name = cattrs[j].name.data.string.data;
+ } else {
+ snprintf(hex_name, sizeof(hex_name), "#%06x", cattrs[j].val);
+ name = hex_name;
+ }
+
+ if (!*cattrs[j].dest
+ || STRCMP(*cattrs[j].dest, name) != 0) {
+ xfree(*cattrs[j].dest);
+ *cattrs[j].dest = xstrdup(name);
+ }
+ }
+
+ g->sg_cterm = attrs.cterm_ae_attr;
+ g->sg_cterm_bg = attrs.cterm_bg_color;
+ g->sg_cterm_fg = attrs.cterm_fg_color;
+ g->sg_cterm_bold = g->sg_cterm & HL_BOLD;
+ g->sg_blend = attrs.hl_blend;
+
+ g->sg_script_ctx = current_sctx;
+ g->sg_script_ctx.sc_lnum += sourcing_lnum;
+
+ // 'Normal' is special
+ if (STRCMP(g->sg_name_u, "NORMAL") == 0) {
+ cterm_normal_fg_color = g->sg_cterm_fg;
+ cterm_normal_bg_color = g->sg_cterm_bg;
+ normal_fg = g->sg_rgb_fg;
+ normal_bg = g->sg_rgb_bg;
+ normal_sp = g->sg_rgb_sp;
+ ui_default_colors_set();
+ } else {
+ g->sg_attr = hl_get_syn_attr(0, id, attrs);
+
+ // a cursor style uses this syn_id, make sure its attribute is updated.
+ if (cursor_mode_uses_syn_id(id)) {
+ ui_mode_info_set();
+ }
+ }
+}
+
+/// Handle ":highlight" command
+///
+/// When using ":highlight clear" this is called recursively for each group with
+/// forceit and init being both true.
+///
+/// @param[in] line Command arguments.
+/// @param[in] forceit True when bang is given, allows to link group even if
+/// it has its own settings.
+/// @param[in] init True when initializing.
+void do_highlight(const char *line, const bool forceit, const bool init)
+ FUNC_ATTR_NONNULL_ALL
+{
+ const char *name_end;
+ const char *linep;
+ const char *key_start;
+ const char *arg_start;
+ int off;
+ int len;
+ int attr;
+ int id;
+ int idx;
+ HlGroup item_before;
+ bool did_change = false;
+ bool dodefault = false;
+ bool doclear = false;
+ bool dolink = false;
+ bool error = false;
+ int color;
+ bool is_normal_group = false; // "Normal" group
+ bool did_highlight_changed = false;
+
+ // If no argument, list current highlighting.
+ if (ends_excmd((uint8_t)(*line))) {
+ for (int i = 1; i <= highlight_ga.ga_len && !got_int; i++) {
+ // TODO(brammool): only call when the group has attributes set
+ highlight_list_one(i);
+ }
+ return;
+ }
+
+ // Isolate the name.
+ name_end = (const char *)skiptowhite((const char_u *)line);
+ linep = (const char *)skipwhite((const char_u *)name_end);
+
+ // Check for "default" argument.
+ if (strncmp(line, "default", (size_t)(name_end - line)) == 0) {
+ dodefault = true;
+ line = linep;
+ name_end = (const char *)skiptowhite((const char_u *)line);
+ linep = (const char *)skipwhite((const char_u *)name_end);
+ }
+
+ // Check for "clear" or "link" argument.
+ if (strncmp(line, "clear", (size_t)(name_end - line)) == 0) {
+ doclear = true;
+ } else if (strncmp(line, "link", (size_t)(name_end - line)) == 0) {
+ dolink = true;
+ }
+
+ // ":highlight {group-name}": list highlighting for one group.
+ if (!doclear && !dolink && ends_excmd((uint8_t)(*linep))) {
+ id = syn_name2id_len((const char_u *)line, (size_t)(name_end - line));
+ if (id == 0) {
+ semsg(_("E411: highlight group not found: %s"), line);
+ } else {
+ highlight_list_one(id);
+ }
+ return;
+ }
+
+ // Handle ":highlight link {from} {to}" command.
+ if (dolink) {
+ const char *from_start = linep;
+ const char *from_end;
+ const char *to_start;
+ const char *to_end;
+ int from_id;
+ int to_id;
+ HlGroup *hlgroup = NULL;
+
+ from_end = (const char *)skiptowhite((const char_u *)from_start);
+ to_start = (const char *)skipwhite((const char_u *)from_end);
+ to_end = (const char *)skiptowhite((const char_u *)to_start);
+
+ if (ends_excmd((uint8_t)(*from_start))
+ || ends_excmd((uint8_t)(*to_start))) {
+ semsg(_("E412: Not enough arguments: \":highlight link %s\""),
+ from_start);
+ return;
+ }
+
+ if (!ends_excmd(*skipwhite((const char_u *)to_end))) {
+ semsg(_("E413: Too many arguments: \":highlight link %s\""), from_start);
+ return;
+ }
+
+ from_id = syn_check_group(from_start, (size_t)(from_end - from_start));
+ if (strncmp(to_start, "NONE", 4) == 0) {
+ to_id = 0;
+ } else {
+ to_id = syn_check_group(to_start, (size_t)(to_end - to_start));
+ }
+
+ if (from_id > 0) {
+ hlgroup = &HL_TABLE()[from_id - 1];
+ if (dodefault && (forceit || hlgroup->sg_deflink == 0)) {
+ hlgroup->sg_deflink = to_id;
+ hlgroup->sg_deflink_sctx = current_sctx;
+ hlgroup->sg_deflink_sctx.sc_lnum += sourcing_lnum;
+ nlua_set_sctx(&hlgroup->sg_deflink_sctx);
+ }
+ }
+
+ if (from_id > 0 && (!init || hlgroup->sg_set == 0)) {
+ // Don't allow a link when there already is some highlighting
+ // for the group, unless '!' is used
+ if (to_id > 0 && !forceit && !init
+ && hl_has_settings(from_id - 1, dodefault)) {
+ if (sourcing_name == NULL && !dodefault) {
+ emsg(_("E414: group has settings, highlight link ignored"));
+ }
+ } else if (hlgroup->sg_link != to_id
+ || hlgroup->sg_script_ctx.sc_sid != current_sctx.sc_sid
+ || hlgroup->sg_cleared) {
+ if (!init) {
+ hlgroup->sg_set |= SG_LINK;
+ }
+ hlgroup->sg_link = to_id;
+ hlgroup->sg_script_ctx = current_sctx;
+ hlgroup->sg_script_ctx.sc_lnum += sourcing_lnum;
+ nlua_set_sctx(&hlgroup->sg_script_ctx);
+ hlgroup->sg_cleared = false;
+ redraw_all_later(SOME_VALID);
+
+ // Only call highlight changed() once after multiple changes
+ need_highlight_changed = true;
+ }
+ }
+
+ return;
+ }
+
+ if (doclear) {
+ // ":highlight clear [group]" command.
+ line = linep;
+ if (ends_excmd((uint8_t)(*line))) {
+ do_unlet(S_LEN("colors_name"), true);
+ restore_cterm_colors();
+
+ // Clear all default highlight groups and load the defaults.
+ for (int j = 0; j < highlight_ga.ga_len; j++) {
+ highlight_clear(j);
+ }
+ init_highlight(true, true);
+ highlight_changed();
+ redraw_all_later(NOT_VALID);
+ return;
+ }
+ name_end = (const char *)skiptowhite((const char_u *)line);
+ linep = (const char *)skipwhite((const char_u *)name_end);
+ }
+
+ // Find the group name in the table. If it does not exist yet, add it.
+ id = syn_check_group(line, (size_t)(name_end - line));
+ if (id == 0) { // Failed (out of memory).
+ return;
+ }
+ idx = id - 1; // Index is ID minus one.
+
+ // Return if "default" was used and the group already has settings
+ if (dodefault && hl_has_settings(idx, true)) {
+ return;
+ }
+
+ // Make a copy so we can check if any attribute actually changed
+ item_before = HL_TABLE()[idx];
+ is_normal_group = (STRCMP(HL_TABLE()[idx].sg_name_u, "NORMAL") == 0);
+
+ // Clear the highlighting for ":hi clear {group}" and ":hi clear".
+ if (doclear || (forceit && init)) {
+ highlight_clear(idx);
+ if (!doclear) {
+ HL_TABLE()[idx].sg_set = 0;
+ }
+ }
+
+ char *key = NULL;
+ char *arg = NULL;
+ if (!doclear) {
+ while (!ends_excmd((uint8_t)(*linep))) {
+ key_start = linep;
+ if (*linep == '=') {
+ semsg(_("E415: unexpected equal sign: %s"), key_start);
+ error = true;
+ break;
+ }
+
+ // Isolate the key ("term", "ctermfg", "ctermbg", "font", "guifg",
+ // "guibg" or "guisp").
+ while (*linep && !ascii_iswhite(*linep) && *linep != '=') {
+ linep++;
+ }
+ xfree(key);
+ key = (char *)vim_strnsave_up((const char_u *)key_start,
+ (size_t)(linep - key_start));
+ linep = (const char *)skipwhite((const char_u *)linep);
+
+ if (strcmp(key, "NONE") == 0) {
+ if (!init || HL_TABLE()[idx].sg_set == 0) {
+ if (!init) {
+ HL_TABLE()[idx].sg_set |= SG_CTERM+SG_GUI;
+ }
+ highlight_clear(idx);
+ }
+ continue;
+ }
+
+ // Check for the equal sign.
+ if (*linep != '=') {
+ semsg(_("E416: missing equal sign: %s"), key_start);
+ error = true;
+ break;
+ }
+ linep++;
+
+ // Isolate the argument.
+ linep = (const char *)skipwhite((const char_u *)linep);
+ if (*linep == '\'') { // guifg='color name'
+ arg_start = ++linep;
+ linep = strchr(linep, '\'');
+ if (linep == NULL) {
+ semsg(_(e_invarg2), key_start);
+ error = true;
+ break;
+ }
+ } else {
+ arg_start = linep;
+ linep = (const char *)skiptowhite((const char_u *)linep);
+ }
+ if (linep == arg_start) {
+ semsg(_("E417: missing argument: %s"), key_start);
+ error = true;
+ break;
+ }
+ xfree(arg);
+ arg = xstrndup(arg_start, (size_t)(linep - arg_start));
+
+ if (*linep == '\'') {
+ linep++;
+ }
+
+ // Store the argument.
+ if (strcmp(key, "TERM") == 0
+ || strcmp(key, "CTERM") == 0
+ || strcmp(key, "GUI") == 0) {
+ attr = 0;
+ off = 0;
+ int i;
+ while (arg[off] != NUL) {
+ for (i = ARRAY_SIZE(hl_attr_table); --i >= 0;) {
+ len = (int)STRLEN(hl_name_table[i]);
+ if (STRNICMP(arg + off, hl_name_table[i], len) == 0) {
+ attr |= hl_attr_table[i];
+ off += len;
+ break;
+ }
+ }
+ if (i < 0) {
+ semsg(_("E418: Illegal value: %s"), arg);
+ error = true;
+ break;
+ }
+ if (arg[off] == ',') { // Another one follows.
+ off++;
+ }
+ }
+ if (error) {
+ break;
+ }
+ if (*key == 'C') {
+ if (!init || !(HL_TABLE()[idx].sg_set & SG_CTERM)) {
+ if (!init) {
+ HL_TABLE()[idx].sg_set |= SG_CTERM;
+ }
+ HL_TABLE()[idx].sg_cterm = attr;
+ HL_TABLE()[idx].sg_cterm_bold = false;
+ }
+ } else if (*key == 'G') {
+ if (!init || !(HL_TABLE()[idx].sg_set & SG_GUI)) {
+ if (!init) {
+ HL_TABLE()[idx].sg_set |= SG_GUI;
+ }
+ HL_TABLE()[idx].sg_gui = attr;
+ }
+ }
+ } else if (STRCMP(key, "FONT") == 0) {
+ // in non-GUI fonts are simply ignored
+ } else if (STRCMP(key, "CTERMFG") == 0 || STRCMP(key, "CTERMBG") == 0) {
+ if (!init || !(HL_TABLE()[idx].sg_set & SG_CTERM)) {
+ if (!init) {
+ HL_TABLE()[idx].sg_set |= SG_CTERM;
+ }
+
+ // When setting the foreground color, and previously the "bold"
+ // flag was set for a light color, reset it now
+ if (key[5] == 'F' && HL_TABLE()[idx].sg_cterm_bold) {
+ HL_TABLE()[idx].sg_cterm &= ~HL_BOLD;
+ HL_TABLE()[idx].sg_cterm_bold = false;
+ }
+
+ if (ascii_isdigit(*arg)) {
+ color = atoi(arg);
+ } else if (STRICMP(arg, "fg") == 0) {
+ if (cterm_normal_fg_color) {
+ color = cterm_normal_fg_color - 1;
+ } else {
+ emsg(_("E419: FG color unknown"));
+ error = true;
+ break;
+ }
+ } else if (STRICMP(arg, "bg") == 0) {
+ if (cterm_normal_bg_color > 0) {
+ color = cterm_normal_bg_color - 1;
+ } else {
+ emsg(_("E420: BG color unknown"));
+ error = true;
+ break;
+ }
+ } else {
+ // Reduce calls to STRICMP a bit, it can be slow.
+ off = TOUPPER_ASC(*arg);
+ int i;
+ for (i = ARRAY_SIZE(color_names); --i >= 0;) {
+ if (off == color_names[i][0]
+ && STRICMP(arg + 1, color_names[i] + 1) == 0) {
+ break;
+ }
+ }
+ if (i < 0) {
+ semsg(_("E421: Color name or number not recognized: %s"),
+ key_start);
+ error = true;
+ break;
+ }
+
+ TriState bold = kNone;
+ color = lookup_color(i, key[5] == 'F', &bold);
+
+ // set/reset bold attribute to get light foreground
+ // colors (on some terminals, e.g. "linux")
+ if (bold == kTrue) {
+ HL_TABLE()[idx].sg_cterm |= HL_BOLD;
+ HL_TABLE()[idx].sg_cterm_bold = true;
+ } else if (bold == kFalse) {
+ HL_TABLE()[idx].sg_cterm &= ~HL_BOLD;
+ }
+ }
+ // Add one to the argument, to avoid zero. Zero is used for
+ // "NONE", then "color" is -1.
+ if (key[5] == 'F') {
+ HL_TABLE()[idx].sg_cterm_fg = color + 1;
+ if (is_normal_group) {
+ cterm_normal_fg_color = color + 1;
+ }
+ } else {
+ HL_TABLE()[idx].sg_cterm_bg = color + 1;
+ if (is_normal_group) {
+ cterm_normal_bg_color = color + 1;
+ if (!ui_rgb_attached()) {
+ if (color >= 0) {
+ int dark = -1;
+
+ if (t_colors < 16) {
+ dark = (color == 0 || color == 4);
+ } else if (color < 16) {
+ // Limit the heuristic to the standard 16 colors
+ dark = (color < 7 || color == 8);
+ }
+ // Set the 'background' option if the value is
+ // wrong.
+ if (dark != -1
+ && dark != (*p_bg == 'd')
+ && !option_was_set("bg")) {
+ set_option_value("bg", 0L, (dark ? "dark" : "light"), 0);
+ reset_option_was_set("bg");
+ }
+ }
+ }
+ }
+ }
+ }
+ } else if (strcmp(key, "GUIFG") == 0) {
+ char **namep = &HL_TABLE()[idx].sg_rgb_fg_name;
+
+ if (!init || !(HL_TABLE()[idx].sg_set & SG_GUI)) {
+ if (!init) {
+ HL_TABLE()[idx].sg_set |= SG_GUI;
+ }
+
+ if (*namep == NULL || STRCMP(*namep, arg) != 0) {
+ xfree(*namep);
+ if (strcmp(arg, "NONE") != 0) {
+ *namep = xstrdup(arg);
+ HL_TABLE()[idx].sg_rgb_fg = name_to_color(arg);
+ } else {
+ *namep = NULL;
+ HL_TABLE()[idx].sg_rgb_fg = -1;
+ }
+ did_change = true;
+ }
+ }
+
+ if (is_normal_group) {
+ normal_fg = HL_TABLE()[idx].sg_rgb_fg;
+ }
+ } else if (STRCMP(key, "GUIBG") == 0) {
+ char **const namep = &HL_TABLE()[idx].sg_rgb_bg_name;
+
+ if (!init || !(HL_TABLE()[idx].sg_set & SG_GUI)) {
+ if (!init) {
+ HL_TABLE()[idx].sg_set |= SG_GUI;
+ }
+
+ if (*namep == NULL || STRCMP(*namep, arg) != 0) {
+ xfree(*namep);
+ if (STRCMP(arg, "NONE") != 0) {
+ *namep = xstrdup(arg);
+ HL_TABLE()[idx].sg_rgb_bg = name_to_color(arg);
+ } else {
+ *namep = NULL;
+ HL_TABLE()[idx].sg_rgb_bg = -1;
+ }
+ did_change = true;
+ }
+ }
+
+ if (is_normal_group) {
+ normal_bg = HL_TABLE()[idx].sg_rgb_bg;
+ }
+ } else if (strcmp(key, "GUISP") == 0) {
+ char **const namep = &HL_TABLE()[idx].sg_rgb_sp_name;
+
+ if (!init || !(HL_TABLE()[idx].sg_set & SG_GUI)) {
+ if (!init) {
+ HL_TABLE()[idx].sg_set |= SG_GUI;
+ }
+
+ if (*namep == NULL || STRCMP(*namep, arg) != 0) {
+ xfree(*namep);
+ if (strcmp(arg, "NONE") != 0) {
+ *namep = xstrdup(arg);
+ HL_TABLE()[idx].sg_rgb_sp = name_to_color(arg);
+ } else {
+ *namep = NULL;
+ HL_TABLE()[idx].sg_rgb_sp = -1;
+ }
+ did_change = true;
+ }
+ }
+
+ if (is_normal_group) {
+ normal_sp = HL_TABLE()[idx].sg_rgb_sp;
+ }
+ } else if (strcmp(key, "START") == 0 || strcmp(key, "STOP") == 0) {
+ // Ignored for now
+ } else if (strcmp(key, "BLEND") == 0) {
+ if (strcmp(arg, "NONE") != 0) {
+ HL_TABLE()[idx].sg_blend = (int)strtol(arg, NULL, 10);
+ } else {
+ HL_TABLE()[idx].sg_blend = -1;
+ }
+ } else {
+ semsg(_("E423: Illegal argument: %s"), key_start);
+ error = true;
+ break;
+ }
+ HL_TABLE()[idx].sg_cleared = false;
+
+ // When highlighting has been given for a group, don't link it.
+ if (!init || !(HL_TABLE()[idx].sg_set & SG_LINK)) {
+ HL_TABLE()[idx].sg_link = 0;
+ }
+
+ // Continue with next argument.
+ linep = (const char *)skipwhite((const char_u *)linep);
+ }
+ }
+
+ // If there is an error, and it's a new entry, remove it from the table.
+ if (error && idx == highlight_ga.ga_len) {
+ syn_unadd_group();
+ } else {
+ if (!error && is_normal_group) {
+ // Need to update all groups, because they might be using "bg" and/or
+ // "fg", which have been changed now.
+ highlight_attr_set_all();
+
+ if (!ui_has(kUILinegrid) && starting == 0) {
+ // Older UIs assume that we clear the screen after normal group is
+ // changed
+ ui_refresh();
+ } else {
+ // TUI and newer UIs will repaint the screen themselves. NOT_VALID
+ // redraw below will still handle usages of guibg=fg etc.
+ ui_default_colors_set();
+ }
+ did_highlight_changed = true;
+ redraw_all_later(NOT_VALID);
+ } else {
+ set_hl_attr(idx);
+ }
+ HL_TABLE()[idx].sg_script_ctx = current_sctx;
+ HL_TABLE()[idx].sg_script_ctx.sc_lnum += sourcing_lnum;
+ nlua_set_sctx(&HL_TABLE()[idx].sg_script_ctx);
+ }
+ xfree(key);
+ xfree(arg);
+
+ // Only call highlight_changed() once, after a sequence of highlight
+ // commands, and only if an attribute actually changed
+ if ((did_change
+ || memcmp(&HL_TABLE()[idx], &item_before, sizeof(item_before)) != 0)
+ && !did_highlight_changed) {
+ // Do not trigger a redraw when highlighting is changed while
+ // redrawing. This may happen when evaluating 'statusline' changes the
+ // StatusLine group.
+ if (!updating_screen) {
+ redraw_all_later(NOT_VALID);
+ }
+ need_highlight_changed = true;
+ }
+}
+
+#if defined(EXITFREE)
+void free_highlight(void)
+{
+ for (int i = 0; i < highlight_ga.ga_len; i++) {
+ highlight_clear(i);
+ xfree(HL_TABLE()[i].sg_name);
+ xfree(HL_TABLE()[i].sg_name_u);
+ }
+ ga_clear(&highlight_ga);
+ map_destroy(cstr_t, int)(&highlight_unames);
+}
+
+#endif
+
+/// Reset the cterm colors to what they were before Vim was started, if
+/// possible. Otherwise reset them to zero.
+void restore_cterm_colors(void)
+{
+ normal_fg = -1;
+ normal_bg = -1;
+ normal_sp = -1;
+ cterm_normal_fg_color = 0;
+ cterm_normal_bg_color = 0;
+}
+
+/// @param check_link if true also check for an existing link.
+///
+/// @return TRUE if highlight group "idx" has any settings.
+static int hl_has_settings(int idx, bool check_link)
+{
+ return HL_TABLE()[idx].sg_cleared == 0
+ && (HL_TABLE()[idx].sg_attr != 0
+ || HL_TABLE()[idx].sg_cterm_fg != 0
+ || HL_TABLE()[idx].sg_cterm_bg != 0
+ || HL_TABLE()[idx].sg_rgb_fg_name != NULL
+ || HL_TABLE()[idx].sg_rgb_bg_name != NULL
+ || HL_TABLE()[idx].sg_rgb_sp_name != NULL
+ || (check_link && (HL_TABLE()[idx].sg_set & SG_LINK)));
+}
+
+/// Clear highlighting for one group.
+static void highlight_clear(int idx)
+{
+ HL_TABLE()[idx].sg_cleared = true;
+
+ HL_TABLE()[idx].sg_attr = 0;
+ HL_TABLE()[idx].sg_cterm = 0;
+ HL_TABLE()[idx].sg_cterm_bold = false;
+ HL_TABLE()[idx].sg_cterm_fg = 0;
+ HL_TABLE()[idx].sg_cterm_bg = 0;
+ HL_TABLE()[idx].sg_gui = 0;
+ HL_TABLE()[idx].sg_rgb_fg = -1;
+ HL_TABLE()[idx].sg_rgb_bg = -1;
+ HL_TABLE()[idx].sg_rgb_sp = -1;
+ XFREE_CLEAR(HL_TABLE()[idx].sg_rgb_fg_name);
+ XFREE_CLEAR(HL_TABLE()[idx].sg_rgb_bg_name);
+ XFREE_CLEAR(HL_TABLE()[idx].sg_rgb_sp_name);
+ HL_TABLE()[idx].sg_blend = -1;
+ // Restore default link and context if they exist. Otherwise clears.
+ HL_TABLE()[idx].sg_link = HL_TABLE()[idx].sg_deflink;
+ // Since we set the default link, set the location to where the default
+ // link was set.
+ HL_TABLE()[idx].sg_script_ctx = HL_TABLE()[idx].sg_deflink_sctx;
+}
+
+/// \addtogroup LIST_XXX
+/// @{
+#define LIST_ATTR 1
+#define LIST_STRING 2
+#define LIST_INT 3
+/// @}
+
+static void highlight_list_one(const int id)
+{
+ const HlGroup *sgp = &HL_TABLE()[id - 1]; // index is ID minus one
+ bool didh = false;
+
+ if (message_filtered(sgp->sg_name)) {
+ return;
+ }
+
+ didh = highlight_list_arg(id, didh, LIST_ATTR,
+ sgp->sg_cterm, NULL, "cterm");
+ didh = highlight_list_arg(id, didh, LIST_INT,
+ sgp->sg_cterm_fg, NULL, "ctermfg");
+ didh = highlight_list_arg(id, didh, LIST_INT,
+ sgp->sg_cterm_bg, NULL, "ctermbg");
+
+ didh = highlight_list_arg(id, didh, LIST_ATTR,
+ sgp->sg_gui, NULL, "gui");
+ didh = highlight_list_arg(id, didh, LIST_STRING,
+ 0, sgp->sg_rgb_fg_name, "guifg");
+ didh = highlight_list_arg(id, didh, LIST_STRING,
+ 0, sgp->sg_rgb_bg_name, "guibg");
+ didh = highlight_list_arg(id, didh, LIST_STRING,
+ 0, sgp->sg_rgb_sp_name, "guisp");
+
+ didh = highlight_list_arg(id, didh, LIST_INT,
+ sgp->sg_blend+1, NULL, "blend");
+
+ if (sgp->sg_link && !got_int) {
+ (void)syn_list_header(didh, 0, id, true);
+ didh = true;
+ msg_puts_attr("links to", HL_ATTR(HLF_D));
+ msg_putchar(' ');
+ msg_outtrans(HL_TABLE()[HL_TABLE()[id - 1].sg_link - 1].sg_name);
+ }
+
+ if (!didh) {
+ highlight_list_arg(id, didh, LIST_STRING, 0, "cleared", "");
+ }
+ if (p_verbose > 0) {
+ last_set_msg(sgp->sg_script_ctx);
+ }
+}
+
+Dictionary get_global_hl_defs(void)
+{
+ Dictionary rv = ARRAY_DICT_INIT;
+ for (int i = 1; i <= highlight_ga.ga_len && !got_int; i++) {
+ Dictionary attrs = ARRAY_DICT_INIT;
+ HlGroup *h = &HL_TABLE()[i - 1];
+ if (h->sg_attr > 0) {
+ attrs = hlattrs2dict(syn_attr2entry(h->sg_attr), true);
+ } else if (h->sg_link > 0) {
+ const char *link = (const char *)HL_TABLE()[h->sg_link - 1].sg_name;
+ PUT(attrs, "link", STRING_OBJ(cstr_to_string(link)));
+ }
+ PUT(rv, (const char *)h->sg_name, DICTIONARY_OBJ(attrs));
+ }
+
+ return rv;
+}
+
+/// Outputs a highlight when doing ":hi MyHighlight"
+///
+/// @param type one of \ref LIST_XXX
+/// @param iarg integer argument used if \p type == LIST_INT
+/// @param sarg string used if \p type == LIST_STRING
+static bool highlight_list_arg(const int id, bool didh, const int type, int iarg, char *const sarg,
+ const char *const name)
+{
+ char buf[100];
+
+ if (got_int) {
+ return false;
+ }
+ if (type == LIST_STRING ? (sarg != NULL) : (iarg != 0)) {
+ char *ts = buf;
+ if (type == LIST_INT) {
+ snprintf((char *)buf, sizeof(buf), "%d", iarg - 1);
+ } else if (type == LIST_STRING) {
+ ts = sarg;
+ } else { // type == LIST_ATTR
+ buf[0] = NUL;
+ for (int i = 0; hl_attr_table[i] != 0; i++) {
+ if (iarg & hl_attr_table[i]) {
+ if (buf[0] != NUL) {
+ xstrlcat(buf, ",", 100);
+ }
+ xstrlcat(buf, hl_name_table[i], 100);
+ iarg &= ~hl_attr_table[i]; // don't want "inverse"
+ }
+ }
+ }
+
+ (void)syn_list_header(didh, (int)(vim_strsize((char_u *)ts) + (int)STRLEN(name)
+ + 1), id, false);
+ didh = true;
+ if (!got_int) {
+ if (*name != NUL) {
+ msg_puts_attr(name, HL_ATTR(HLF_D));
+ msg_puts_attr("=", HL_ATTR(HLF_D));
+ }
+ msg_outtrans((char_u *)ts);
+ }
+ }
+ return didh;
+}
+
+/// Check whether highlight group has attribute
+///
+/// @param[in] id Highlight group to check.
+/// @param[in] flag Attribute to check.
+/// @param[in] modec 'g' for GUI, 'c' for term.
+///
+/// @return "1" if highlight group has attribute, NULL otherwise.
+const char *highlight_has_attr(const int id, const int flag, const int modec)
+ FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_PURE
+{
+ int attr;
+
+ if (id <= 0 || id > highlight_ga.ga_len) {
+ return NULL;
+ }
+
+ if (modec == 'g') {
+ attr = HL_TABLE()[id - 1].sg_gui;
+ } else {
+ attr = HL_TABLE()[id - 1].sg_cterm;
+ }
+
+ return (attr & flag) ? "1" : NULL;
+}
+
+/// Return color name of the given highlight group
+///
+/// @param[in] id Highlight group to work with.
+/// @param[in] what What to return: one of "font", "fg", "bg", "sp", "fg#",
+/// "bg#" or "sp#".
+/// @param[in] modec 'g' for GUI, 'c' for cterm and 't' for term.
+///
+/// @return color name, possibly in a static buffer. Buffer will be overwritten
+/// on next highlight_color() call. May return NULL.
+const char *highlight_color(const int id, const char *const what, const int modec)
+ FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ALL
+{
+ static char name[20];
+ int n;
+ bool fg = false;
+ bool sp = false;
+ bool font = false;
+
+ if (id <= 0 || id > highlight_ga.ga_len) {
+ return NULL;
+ }
+
+ if (TOLOWER_ASC(what[0]) == 'f' && TOLOWER_ASC(what[1]) == 'g') {
+ fg = true;
+ } else if (TOLOWER_ASC(what[0]) == 'f' && TOLOWER_ASC(what[1]) == 'o'
+ && TOLOWER_ASC(what[2]) == 'n' && TOLOWER_ASC(what[3]) == 't') {
+ font = true;
+ } else if (TOLOWER_ASC(what[0]) == 's' && TOLOWER_ASC(what[1]) == 'p') {
+ sp = true;
+ } else if (!(TOLOWER_ASC(what[0]) == 'b' && TOLOWER_ASC(what[1]) == 'g')) {
+ return NULL;
+ }
+ if (modec == 'g') {
+ if (what[2] == '#' && ui_rgb_attached()) {
+ if (fg) {
+ n = HL_TABLE()[id - 1].sg_rgb_fg;
+ } else if (sp) {
+ n = HL_TABLE()[id - 1].sg_rgb_sp;
+ } else {
+ n = HL_TABLE()[id - 1].sg_rgb_bg;
+ }
+ if (n < 0 || n > 0xffffff) {
+ return NULL;
+ }
+ snprintf(name, sizeof(name), "#%06x", n);
+ return name;
+ }
+ if (fg) {
+ return (const char *)HL_TABLE()[id - 1].sg_rgb_fg_name;
+ }
+ if (sp) {
+ return (const char *)HL_TABLE()[id - 1].sg_rgb_sp_name;
+ }
+ return (const char *)HL_TABLE()[id - 1].sg_rgb_bg_name;
+ }
+ if (font || sp) {
+ return NULL;
+ }
+ if (modec == 'c') {
+ if (fg) {
+ n = HL_TABLE()[id - 1].sg_cterm_fg - 1;
+ } else {
+ n = HL_TABLE()[id - 1].sg_cterm_bg - 1;
+ }
+ if (n < 0) {
+ return NULL;
+ }
+ snprintf(name, sizeof(name), "%d", n);
+ return name;
+ }
+ // term doesn't have color.
+ return NULL;
+}
+
+/// Output the syntax list header.
+///
+/// @param did_header did header already
+/// @param outlen length of string that comes
+/// @param id highlight group id
+/// @param force_newline always start a new line
+/// @return true when started a new line.
+bool syn_list_header(const bool did_header, const int outlen, const int id,
+ bool force_newline)
+{
+ int endcol = 19;
+ bool newline = true;
+ int name_col = 0;
+ bool adjust = true;
+
+ if (!did_header) {
+ msg_putchar('\n');
+ if (got_int) {
+ return true;
+ }
+ msg_outtrans(HL_TABLE()[id - 1].sg_name);
+ name_col = msg_col;
+ endcol = 15;
+ } else if ((ui_has(kUIMessages) || msg_silent) && !force_newline) {
+ msg_putchar(' ');
+ adjust = false;
+ } else if (msg_col + outlen + 1 >= Columns || force_newline) {
+ msg_putchar('\n');
+ if (got_int) {
+ return true;
+ }
+ } else {
+ if (msg_col >= endcol) { // wrap around is like starting a new line
+ newline = false;
+ }
+ }
+
+ if (adjust) {
+ if (msg_col >= endcol) {
+ // output at least one space
+ endcol = msg_col + 1;
+ }
+
+ msg_advance(endcol);
+ }
+
+ // Show "xxx" with the attributes.
+ if (!did_header) {
+ if (endcol == Columns - 1 && endcol <= name_col) {
+ msg_putchar(' ');
+ }
+ msg_puts_attr("xxx", syn_id2attr(id));
+ msg_putchar(' ');
+ }
+
+ return newline;
+}
+
+/// Set the attribute numbers for a highlight group.
+/// Called after one of the attributes has changed.
+/// @param idx corrected highlight index
+static void set_hl_attr(int idx)
+{
+ HlAttrs at_en = HLATTRS_INIT;
+ HlGroup *sgp = HL_TABLE() + idx;
+
+ at_en.cterm_ae_attr = (int16_t)sgp->sg_cterm;
+ at_en.cterm_fg_color = sgp->sg_cterm_fg;
+ at_en.cterm_bg_color = sgp->sg_cterm_bg;
+ at_en.rgb_ae_attr = (int16_t)sgp->sg_gui;
+ // FIXME(tarruda): The "unset value" for rgb is -1, but since hlgroup is
+ // initialized with 0(by garray functions), check for sg_rgb_{f,b}g_name
+ // before setting attr_entry->{f,g}g_color to a other than -1
+ at_en.rgb_fg_color = sgp->sg_rgb_fg_name ? sgp->sg_rgb_fg : -1;
+ at_en.rgb_bg_color = sgp->sg_rgb_bg_name ? sgp->sg_rgb_bg : -1;
+ at_en.rgb_sp_color = sgp->sg_rgb_sp_name ? sgp->sg_rgb_sp : -1;
+ at_en.hl_blend = sgp->sg_blend;
+
+ sgp->sg_attr = hl_get_syn_attr(0, idx+1, at_en);
+
+ // a cursor style uses this syn_id, make sure its attribute is updated.
+ if (cursor_mode_uses_syn_id(idx+1)) {
+ ui_mode_info_set();
+ }
+}
+
+int syn_name2id(const char *name)
+ FUNC_ATTR_NONNULL_ALL
+{
+ return syn_name2id_len((char_u *)name, STRLEN(name));
+}
+
+/// Lookup a highlight group name and return its ID.
+///
+/// @param highlight name e.g. 'Cursor', 'Normal'
+/// @return the highlight id, else 0 if \p name does not exist
+int syn_name2id_len(const char_u *name, size_t len)
+ FUNC_ATTR_NONNULL_ALL
+{
+ char name_u[MAX_SYN_NAME + 1];
+
+ if (len == 0 || len > MAX_SYN_NAME) {
+ return 0;
+ }
+
+ // Avoid using stricmp() too much, it's slow on some systems */
+ // Avoid alloc()/free(), these are slow too.
+ memcpy(name_u, name, len);
+ name_u[len] = '\0';
+ vim_strup((char_u *)name_u);
+
+ // map_get(..., int) returns 0 when no key is present, which is
+ // the expected value for missing highlight group.
+ return map_get(cstr_t, int)(&highlight_unames, name_u);
+}
+
+/// Lookup a highlight group name and return its attributes.
+/// Return zero if not found.
+int syn_name2attr(const char_u *name)
+ FUNC_ATTR_NONNULL_ALL
+{
+ int id = syn_name2id((char *)name);
+
+ if (id != 0) {
+ return syn_id2attr(id);
+ }
+ return 0;
+}
+
+/// Return TRUE if highlight group "name" exists.
+int highlight_exists(const char *name)
+{
+ return syn_name2id(name) > 0;
+}
+
+/// Return the name of highlight group "id".
+/// When not a valid ID return an empty string.
+char_u *syn_id2name(int id)
+{
+ if (id <= 0 || id > highlight_ga.ga_len) {
+ return (char_u *)"";
+ }
+ return HL_TABLE()[id - 1].sg_name;
+}
+
+/// Find highlight group name in the table and return its ID.
+/// If it doesn't exist yet, a new entry is created.
+///
+/// @param pp Highlight group name
+/// @param len length of \p pp
+///
+/// @return 0 for failure else the id of the group
+int syn_check_group(const char *name, size_t len)
+{
+ if (len > MAX_SYN_NAME) {
+ emsg(_(e_highlight_group_name_too_long));
+ return 0;
+ }
+ int id = syn_name2id_len((char_u *)name, len);
+ if (id == 0) { // doesn't exist yet
+ return syn_add_group(vim_strnsave((char_u *)name, len));
+ }
+ return id;
+}
+
+/// Add new highlight group and return its ID.
+///
+/// @param name must be an allocated string, it will be consumed.
+/// @return 0 for failure, else the allocated group id
+/// @see syn_check_group syn_unadd_group
+static int syn_add_group(char_u *name)
+{
+ char_u *p;
+
+ // Check that the name is ASCII letters, digits and underscore.
+ for (p = name; *p != NUL; p++) {
+ if (!vim_isprintc(*p)) {
+ emsg(_("E669: Unprintable character in group name"));
+ xfree(name);
+ return 0;
+ } else if (!ASCII_ISALNUM(*p) && *p != '_') {
+ // This is an error, but since there previously was no check only give a warning.
+ msg_source(HL_ATTR(HLF_W));
+ msg(_("W18: Invalid character in group name"));
+ break;
+ }
+ }
+
+ // First call for this growarray: init growing array.
+ if (highlight_ga.ga_data == NULL) {
+ highlight_ga.ga_itemsize = sizeof(HlGroup);
+ ga_set_growsize(&highlight_ga, 10);
+ }
+
+ if (highlight_ga.ga_len >= MAX_HL_ID) {
+ emsg(_("E849: Too many highlight and syntax groups"));
+ xfree(name);
+ return 0;
+ }
+
+ char *const name_up = (char *)vim_strsave_up(name);
+
+ // Append another syntax_highlight entry.
+ HlGroup *hlgp = GA_APPEND_VIA_PTR(HlGroup, &highlight_ga);
+ memset(hlgp, 0, sizeof(*hlgp));
+ hlgp->sg_name = name;
+ hlgp->sg_rgb_bg = -1;
+ hlgp->sg_rgb_fg = -1;
+ hlgp->sg_rgb_sp = -1;
+ hlgp->sg_blend = -1;
+ hlgp->sg_name_u = name_up;
+
+ int id = highlight_ga.ga_len; // ID is index plus one
+
+ map_put(cstr_t, int)(&highlight_unames, name_up, id);
+
+ return id;
+}
+
+/// When, just after calling syn_add_group(), an error is discovered, this
+/// function deletes the new name.
+static void syn_unadd_group(void)
+{
+ highlight_ga.ga_len--;
+ HlGroup *item = &HL_TABLE()[highlight_ga.ga_len];
+ map_del(cstr_t, int)(&highlight_unames, item->sg_name_u);
+ xfree(item->sg_name);
+ xfree(item->sg_name_u);
+}
+
+/// Translate a group ID to highlight attributes.
+/// @see syn_attr2entry
+int syn_id2attr(int hl_id)
+{
+ hl_id = syn_get_final_id(hl_id);
+ HlGroup *sgp = &HL_TABLE()[hl_id - 1]; // index is ID minus one
+
+ int attr = ns_get_hl(-1, hl_id, false, sgp->sg_set);
+ if (attr >= 0) {
+ return attr;
+ }
+ return sgp->sg_attr;
+}
+
+/// Translate a group ID to the final group ID (following links).
+int syn_get_final_id(int hl_id)
+{
+ int count;
+
+ if (hl_id > highlight_ga.ga_len || hl_id < 1) {
+ return 0; // Can be called from eval!!
+ }
+
+ // Follow links until there is no more.
+ // Look out for loops! Break after 100 links.
+ for (count = 100; --count >= 0;) {
+ HlGroup *sgp = &HL_TABLE()[hl_id - 1]; // index is ID minus one
+
+ // ACHTUNG: when using "tmp" attribute (no link) the function might be
+ // called twice. it needs be smart enough to remember attr only to
+ // syn_id2attr time
+ int check = ns_get_hl(-1, hl_id, true, sgp->sg_set);
+ if (check == 0) {
+ return hl_id; // how dare! it broke the link!
+ } else if (check > 0) {
+ hl_id = check;
+ continue;
+ }
+
+
+ if (sgp->sg_link == 0 || sgp->sg_link > highlight_ga.ga_len) {
+ break;
+ }
+ hl_id = sgp->sg_link;
+ }
+
+ return hl_id;
+}
+
+/// Refresh the color attributes of all highlight groups.
+void highlight_attr_set_all(void)
+{
+ for (int idx = 0; idx < highlight_ga.ga_len; idx++) {
+ HlGroup *sgp = &HL_TABLE()[idx];
+ if (sgp->sg_rgb_bg_name != NULL) {
+ sgp->sg_rgb_bg = name_to_color(sgp->sg_rgb_bg_name);
+ }
+ if (sgp->sg_rgb_fg_name != NULL) {
+ sgp->sg_rgb_fg = name_to_color(sgp->sg_rgb_fg_name);
+ }
+ if (sgp->sg_rgb_sp_name != NULL) {
+ sgp->sg_rgb_sp = name_to_color(sgp->sg_rgb_sp_name);
+ }
+ set_hl_attr(idx);
+ }
+}
+
+// Apply difference between User[1-9] and HLF_S to HLF_SNC.
+static void combine_stl_hlt(int id, int id_S, int id_alt, int hlcnt, int i, int hlf, int *table)
+ FUNC_ATTR_NONNULL_ALL
+{
+ HlGroup *const hlt = HL_TABLE();
+
+ if (id_alt == 0) {
+ memset(&hlt[hlcnt + i], 0, sizeof(HlGroup));
+ hlt[hlcnt + i].sg_cterm = highlight_attr[hlf];
+ hlt[hlcnt + i].sg_gui = highlight_attr[hlf];
+ } else {
+ memmove(&hlt[hlcnt + i], &hlt[id_alt - 1], sizeof(HlGroup));
+ }
+ hlt[hlcnt + i].sg_link = 0;
+
+ hlt[hlcnt + i].sg_cterm ^= hlt[id - 1].sg_cterm ^ hlt[id_S - 1].sg_cterm;
+ if (hlt[id - 1].sg_cterm_fg != hlt[id_S - 1].sg_cterm_fg) {
+ hlt[hlcnt + i].sg_cterm_fg = hlt[id - 1].sg_cterm_fg;
+ }
+ if (hlt[id - 1].sg_cterm_bg != hlt[id_S - 1].sg_cterm_bg) {
+ hlt[hlcnt + i].sg_cterm_bg = hlt[id - 1].sg_cterm_bg;
+ }
+ hlt[hlcnt + i].sg_gui ^= hlt[id - 1].sg_gui ^ hlt[id_S - 1].sg_gui;
+ if (hlt[id - 1].sg_rgb_fg != hlt[id_S - 1].sg_rgb_fg) {
+ hlt[hlcnt + i].sg_rgb_fg = hlt[id - 1].sg_rgb_fg;
+ }
+ if (hlt[id - 1].sg_rgb_bg != hlt[id_S - 1].sg_rgb_bg) {
+ hlt[hlcnt + i].sg_rgb_bg = hlt[id - 1].sg_rgb_bg;
+ }
+ if (hlt[id - 1].sg_rgb_sp != hlt[id_S - 1].sg_rgb_sp) {
+ hlt[hlcnt + i].sg_rgb_sp = hlt[id - 1].sg_rgb_sp;
+ }
+ highlight_ga.ga_len = hlcnt + i + 1;
+ set_hl_attr(hlcnt + i); // At long last we can apply
+ table[i] = syn_id2attr(hlcnt + i + 1);
+}
+
+/// Translate highlight groups into attributes in highlight_attr[] and set up
+/// the user highlights User1..9. A set of corresponding highlights to use on
+/// top of HLF_SNC is computed. Called only when nvim starts and upon first
+/// screen redraw after any :highlight command.
+void highlight_changed(void)
+{
+ int id;
+ char userhl[30]; // use 30 to avoid compiler warning
+ int id_S = -1;
+ int id_SNC = 0;
+ int hlcnt;
+
+ need_highlight_changed = false;
+
+ /// Translate builtin highlight groups into attributes for quick lookup.
+ for (int hlf = 0; hlf < HLF_COUNT; hlf++) {
+ id = syn_check_group(hlf_names[hlf], STRLEN(hlf_names[hlf]));
+ if (id == 0) {
+ abort();
+ }
+ int final_id = syn_get_final_id(id);
+ if (hlf == HLF_SNC) {
+ id_SNC = final_id;
+ } else if (hlf == HLF_S) {
+ id_S = final_id;
+ }
+
+ highlight_attr[hlf] = hl_get_ui_attr(hlf, final_id,
+ hlf == HLF_INACTIVE);
+
+ if (highlight_attr[hlf] != highlight_attr_last[hlf]) {
+ if (hlf == HLF_MSG) {
+ clear_cmdline = true;
+ }
+ ui_call_hl_group_set(cstr_as_string((char *)hlf_names[hlf]),
+ highlight_attr[hlf]);
+ highlight_attr_last[hlf] = highlight_attr[hlf];
+ }
+ }
+
+ //
+ // Setup the user highlights
+ //
+ // Temporarily utilize 10 more hl entries:
+ // 9 for User1-User9 combined with StatusLineNC
+ // 1 for StatusLine default
+ // Must to be in there simultaneously in case of table overflows in
+ // get_attr_entry()
+ ga_grow(&highlight_ga, 10);
+ hlcnt = highlight_ga.ga_len;
+ if (id_S == -1) {
+ // Make sure id_S is always valid to simplify code below. Use the last entry
+ memset(&HL_TABLE()[hlcnt + 9], 0, sizeof(HlGroup));
+ id_S = hlcnt + 10;
+ }
+ for (int i = 0; i < 9; i++) {
+ snprintf(userhl, sizeof(userhl), "User%d", i + 1);
+ id = syn_name2id(userhl);
+ if (id == 0) {
+ highlight_user[i] = 0;
+ highlight_stlnc[i] = 0;
+ } else {
+ highlight_user[i] = syn_id2attr(id);
+ combine_stl_hlt(id, id_S, id_SNC, hlcnt, i, HLF_SNC, highlight_stlnc);
+ }
+ }
+ highlight_ga.ga_len = hlcnt;
+}
+
+/// Handle command line completion for :highlight command.
+void set_context_in_highlight_cmd(expand_T *xp, const char *arg)
+{
+ // Default: expand group names.
+ xp->xp_context = EXPAND_HIGHLIGHT;
+ xp->xp_pattern = (char_u *)arg;
+ include_link = 2;
+ include_default = 1;
+
+ // (part of) subcommand already typed
+ if (*arg != NUL) {
+ const char *p = (const char *)skiptowhite((const char_u *)arg);
+ if (*p != NUL) { // Past "default" or group name.
+ include_default = 0;
+ if (strncmp("default", arg, (unsigned)(p - arg)) == 0) {
+ arg = (const char *)skipwhite((const char_u *)p);
+ xp->xp_pattern = (char_u *)arg;
+ p = (const char *)skiptowhite((const char_u *)arg);
+ }
+ if (*p != NUL) { // past group name
+ include_link = 0;
+ if (arg[1] == 'i' && arg[0] == 'N') {
+ highlight_list();
+ }
+ if (strncmp("link", arg, (unsigned)(p - arg)) == 0
+ || strncmp("clear", arg, (unsigned)(p - arg)) == 0) {
+ xp->xp_pattern = skipwhite((const char_u *)p);
+ p = (const char *)skiptowhite(xp->xp_pattern);
+ if (*p != NUL) { // Past first group name.
+ xp->xp_pattern = skipwhite((const char_u *)p);
+ p = (const char *)skiptowhite(xp->xp_pattern);
+ }
+ }
+ if (*p != NUL) { // Past group name(s).
+ xp->xp_context = EXPAND_NOTHING;
+ }
+ }
+ }
+ }
+}
+
+/// List highlighting matches in a nice way.
+static void highlight_list(void)
+{
+ int i;
+
+ for (i = 10; --i >= 0;) {
+ highlight_list_two(i, HL_ATTR(HLF_D));
+ }
+ for (i = 40; --i >= 0;) {
+ highlight_list_two(99, 0);
+ }
+}
+
+static void highlight_list_two(int cnt, int attr)
+{
+ msg_puts_attr(&("N \bI \b! \b"[cnt / 11]), attr);
+ msg_clr_eos();
+ ui_flush();
+ os_delay(cnt == 99 ? 40L : (uint64_t)cnt * 50L, false);
+}
+
+/// Function given to ExpandGeneric() to obtain the list of group names.
+const char *get_highlight_name(expand_T *const xp, int idx)
+ FUNC_ATTR_WARN_UNUSED_RESULT
+{
+ return get_highlight_name_ext(xp, idx, true);
+}
+
+/// Obtain a highlight group name.
+///
+/// @param skip_cleared if true don't return a cleared entry.
+const char *get_highlight_name_ext(expand_T *xp, int idx, bool skip_cleared)
+ FUNC_ATTR_WARN_UNUSED_RESULT
+{
+ if (idx < 0) {
+ return NULL;
+ }
+
+ // Items are never removed from the table, skip the ones that were cleared.
+ if (skip_cleared && idx < highlight_ga.ga_len && HL_TABLE()[idx].sg_cleared) {
+ return "";
+ }
+
+ if (idx == highlight_ga.ga_len && include_none != 0) {
+ return "none";
+ } else if (idx == highlight_ga.ga_len + include_none
+ && include_default != 0) {
+ return "default";
+ } else if (idx == highlight_ga.ga_len + include_none + include_default
+ && include_link != 0) {
+ return "link";
+ } else if (idx == highlight_ga.ga_len + include_none + include_default + 1
+ && include_link != 0) {
+ return "clear";
+ } else if (idx >= highlight_ga.ga_len) {
+ return NULL;
+ }
+ return (const char *)HL_TABLE()[idx].sg_name;
+}
+
+color_name_table_T color_name_table[] = {
+ // Colors from rgb.txt
+ { "AliceBlue", RGB_(0xf0, 0xf8, 0xff) },
+ { "AntiqueWhite", RGB_(0xfa, 0xeb, 0xd7) },
+ { "AntiqueWhite1", RGB_(0xff, 0xef, 0xdb) },
+ { "AntiqueWhite2", RGB_(0xee, 0xdf, 0xcc) },
+ { "AntiqueWhite3", RGB_(0xcd, 0xc0, 0xb0) },
+ { "AntiqueWhite4", RGB_(0x8b, 0x83, 0x78) },
+ { "Aqua", RGB_(0x00, 0xff, 0xff) },
+ { "Aquamarine", RGB_(0x7f, 0xff, 0xd4) },
+ { "Aquamarine1", RGB_(0x7f, 0xff, 0xd4) },
+ { "Aquamarine2", RGB_(0x76, 0xee, 0xc6) },
+ { "Aquamarine3", RGB_(0x66, 0xcd, 0xaa) },
+ { "Aquamarine4", RGB_(0x45, 0x8b, 0x74) },
+ { "Azure", RGB_(0xf0, 0xff, 0xff) },
+ { "Azure1", RGB_(0xf0, 0xff, 0xff) },
+ { "Azure2", RGB_(0xe0, 0xee, 0xee) },
+ { "Azure3", RGB_(0xc1, 0xcd, 0xcd) },
+ { "Azure4", RGB_(0x83, 0x8b, 0x8b) },
+ { "Beige", RGB_(0xf5, 0xf5, 0xdc) },
+ { "Bisque", RGB_(0xff, 0xe4, 0xc4) },
+ { "Bisque1", RGB_(0xff, 0xe4, 0xc4) },
+ { "Bisque2", RGB_(0xee, 0xd5, 0xb7) },
+ { "Bisque3", RGB_(0xcd, 0xb7, 0x9e) },
+ { "Bisque4", RGB_(0x8b, 0x7d, 0x6b) },
+ { "Black", RGB_(0x00, 0x00, 0x00) },
+ { "BlanchedAlmond", RGB_(0xff, 0xeb, 0xcd) },
+ { "Blue", RGB_(0x00, 0x00, 0xff) },
+ { "Blue1", RGB_(0x0, 0x0, 0xff) },
+ { "Blue2", RGB_(0x0, 0x0, 0xee) },
+ { "Blue3", RGB_(0x0, 0x0, 0xcd) },
+ { "Blue4", RGB_(0x0, 0x0, 0x8b) },
+ { "BlueViolet", RGB_(0x8a, 0x2b, 0xe2) },
+ { "Brown", RGB_(0xa5, 0x2a, 0x2a) },
+ { "Brown1", RGB_(0xff, 0x40, 0x40) },
+ { "Brown2", RGB_(0xee, 0x3b, 0x3b) },
+ { "Brown3", RGB_(0xcd, 0x33, 0x33) },
+ { "Brown4", RGB_(0x8b, 0x23, 0x23) },
+ { "BurlyWood", RGB_(0xde, 0xb8, 0x87) },
+ { "Burlywood1", RGB_(0xff, 0xd3, 0x9b) },
+ { "Burlywood2", RGB_(0xee, 0xc5, 0x91) },
+ { "Burlywood3", RGB_(0xcd, 0xaa, 0x7d) },
+ { "Burlywood4", RGB_(0x8b, 0x73, 0x55) },
+ { "CadetBlue", RGB_(0x5f, 0x9e, 0xa0) },
+ { "CadetBlue1", RGB_(0x98, 0xf5, 0xff) },
+ { "CadetBlue2", RGB_(0x8e, 0xe5, 0xee) },
+ { "CadetBlue3", RGB_(0x7a, 0xc5, 0xcd) },
+ { "CadetBlue4", RGB_(0x53, 0x86, 0x8b) },
+ { "ChartReuse", RGB_(0x7f, 0xff, 0x00) },
+ { "Chartreuse1", RGB_(0x7f, 0xff, 0x0) },
+ { "Chartreuse2", RGB_(0x76, 0xee, 0x0) },
+ { "Chartreuse3", RGB_(0x66, 0xcd, 0x0) },
+ { "Chartreuse4", RGB_(0x45, 0x8b, 0x0) },
+ { "Chocolate", RGB_(0xd2, 0x69, 0x1e) },
+ { "Chocolate1", RGB_(0xff, 0x7f, 0x24) },
+ { "Chocolate2", RGB_(0xee, 0x76, 0x21) },
+ { "Chocolate3", RGB_(0xcd, 0x66, 0x1d) },
+ { "Chocolate4", RGB_(0x8b, 0x45, 0x13) },
+ { "Coral", RGB_(0xff, 0x7f, 0x50) },
+ { "Coral1", RGB_(0xff, 0x72, 0x56) },
+ { "Coral2", RGB_(0xee, 0x6a, 0x50) },
+ { "Coral3", RGB_(0xcd, 0x5b, 0x45) },
+ { "Coral4", RGB_(0x8b, 0x3e, 0x2f) },
+ { "CornFlowerBlue", RGB_(0x64, 0x95, 0xed) },
+ { "Cornsilk", RGB_(0xff, 0xf8, 0xdc) },
+ { "Cornsilk1", RGB_(0xff, 0xf8, 0xdc) },
+ { "Cornsilk2", RGB_(0xee, 0xe8, 0xcd) },
+ { "Cornsilk3", RGB_(0xcd, 0xc8, 0xb1) },
+ { "Cornsilk4", RGB_(0x8b, 0x88, 0x78) },
+ { "Crimson", RGB_(0xdc, 0x14, 0x3c) },
+ { "Cyan", RGB_(0x00, 0xff, 0xff) },
+ { "Cyan1", RGB_(0x0, 0xff, 0xff) },
+ { "Cyan2", RGB_(0x0, 0xee, 0xee) },
+ { "Cyan3", RGB_(0x0, 0xcd, 0xcd) },
+ { "Cyan4", RGB_(0x0, 0x8b, 0x8b) },
+ { "DarkBlue", RGB_(0x00, 0x00, 0x8b) },
+ { "DarkCyan", RGB_(0x00, 0x8b, 0x8b) },
+ { "DarkGoldenRod", RGB_(0xb8, 0x86, 0x0b) },
+ { "DarkGoldenrod1", RGB_(0xff, 0xb9, 0xf) },
+ { "DarkGoldenrod2", RGB_(0xee, 0xad, 0xe) },
+ { "DarkGoldenrod3", RGB_(0xcd, 0x95, 0xc) },
+ { "DarkGoldenrod4", RGB_(0x8b, 0x65, 0x8) },
+ { "DarkGray", RGB_(0xa9, 0xa9, 0xa9) },
+ { "DarkGreen", RGB_(0x00, 0x64, 0x00) },
+ { "DarkGrey", RGB_(0xa9, 0xa9, 0xa9) },
+ { "DarkKhaki", RGB_(0xbd, 0xb7, 0x6b) },
+ { "DarkMagenta", RGB_(0x8b, 0x00, 0x8b) },
+ { "DarkOliveGreen", RGB_(0x55, 0x6b, 0x2f) },
+ { "DarkOliveGreen1", RGB_(0xca, 0xff, 0x70) },
+ { "DarkOliveGreen2", RGB_(0xbc, 0xee, 0x68) },
+ { "DarkOliveGreen3", RGB_(0xa2, 0xcd, 0x5a) },
+ { "DarkOliveGreen4", RGB_(0x6e, 0x8b, 0x3d) },
+ { "DarkOrange", RGB_(0xff, 0x8c, 0x00) },
+ { "DarkOrange1", RGB_(0xff, 0x7f, 0x0) },
+ { "DarkOrange2", RGB_(0xee, 0x76, 0x0) },
+ { "DarkOrange3", RGB_(0xcd, 0x66, 0x0) },
+ { "DarkOrange4", RGB_(0x8b, 0x45, 0x0) },
+ { "DarkOrchid", RGB_(0x99, 0x32, 0xcc) },
+ { "DarkOrchid1", RGB_(0xbf, 0x3e, 0xff) },
+ { "DarkOrchid2", RGB_(0xb2, 0x3a, 0xee) },
+ { "DarkOrchid3", RGB_(0x9a, 0x32, 0xcd) },
+ { "DarkOrchid4", RGB_(0x68, 0x22, 0x8b) },
+ { "DarkRed", RGB_(0x8b, 0x00, 0x00) },
+ { "DarkSalmon", RGB_(0xe9, 0x96, 0x7a) },
+ { "DarkSeaGreen", RGB_(0x8f, 0xbc, 0x8f) },
+ { "DarkSeaGreen1", RGB_(0xc1, 0xff, 0xc1) },
+ { "DarkSeaGreen2", RGB_(0xb4, 0xee, 0xb4) },
+ { "DarkSeaGreen3", RGB_(0x9b, 0xcd, 0x9b) },
+ { "DarkSeaGreen4", RGB_(0x69, 0x8b, 0x69) },
+ { "DarkSlateBlue", RGB_(0x48, 0x3d, 0x8b) },
+ { "DarkSlateGray", RGB_(0x2f, 0x4f, 0x4f) },
+ { "DarkSlateGray1", RGB_(0x97, 0xff, 0xff) },
+ { "DarkSlateGray2", RGB_(0x8d, 0xee, 0xee) },
+ { "DarkSlateGray3", RGB_(0x79, 0xcd, 0xcd) },
+ { "DarkSlateGray4", RGB_(0x52, 0x8b, 0x8b) },
+ { "DarkSlateGrey", RGB_(0x2f, 0x4f, 0x4f) },
+ { "DarkTurquoise", RGB_(0x00, 0xce, 0xd1) },
+ { "DarkViolet", RGB_(0x94, 0x00, 0xd3) },
+ { "DarkYellow", RGB_(0xbb, 0xbb, 0x00) },
+ { "DeepPink", RGB_(0xff, 0x14, 0x93) },
+ { "DeepPink1", RGB_(0xff, 0x14, 0x93) },
+ { "DeepPink2", RGB_(0xee, 0x12, 0x89) },
+ { "DeepPink3", RGB_(0xcd, 0x10, 0x76) },
+ { "DeepPink4", RGB_(0x8b, 0xa, 0x50) },
+ { "DeepSkyBlue", RGB_(0x00, 0xbf, 0xff) },
+ { "DeepSkyBlue1", RGB_(0x0, 0xbf, 0xff) },
+ { "DeepSkyBlue2", RGB_(0x0, 0xb2, 0xee) },
+ { "DeepSkyBlue3", RGB_(0x0, 0x9a, 0xcd) },
+ { "DeepSkyBlue4", RGB_(0x0, 0x68, 0x8b) },
+ { "DimGray", RGB_(0x69, 0x69, 0x69) },
+ { "DimGrey", RGB_(0x69, 0x69, 0x69) },
+ { "DodgerBlue", RGB_(0x1e, 0x90, 0xff) },
+ { "DodgerBlue1", RGB_(0x1e, 0x90, 0xff) },
+ { "DodgerBlue2", RGB_(0x1c, 0x86, 0xee) },
+ { "DodgerBlue3", RGB_(0x18, 0x74, 0xcd) },
+ { "DodgerBlue4", RGB_(0x10, 0x4e, 0x8b) },
+ { "Firebrick", RGB_(0xb2, 0x22, 0x22) },
+ { "Firebrick1", RGB_(0xff, 0x30, 0x30) },
+ { "Firebrick2", RGB_(0xee, 0x2c, 0x2c) },
+ { "Firebrick3", RGB_(0xcd, 0x26, 0x26) },
+ { "Firebrick4", RGB_(0x8b, 0x1a, 0x1a) },
+ { "FloralWhite", RGB_(0xff, 0xfa, 0xf0) },
+ { "ForestGreen", RGB_(0x22, 0x8b, 0x22) },
+ { "Fuchsia", RGB_(0xff, 0x00, 0xff) },
+ { "Gainsboro", RGB_(0xdc, 0xdc, 0xdc) },
+ { "GhostWhite", RGB_(0xf8, 0xf8, 0xff) },
+ { "Gold", RGB_(0xff, 0xd7, 0x00) },
+ { "Gold1", RGB_(0xff, 0xd7, 0x0) },
+ { "Gold2", RGB_(0xee, 0xc9, 0x0) },
+ { "Gold3", RGB_(0xcd, 0xad, 0x0) },
+ { "Gold4", RGB_(0x8b, 0x75, 0x0) },
+ { "GoldenRod", RGB_(0xda, 0xa5, 0x20) },
+ { "Goldenrod1", RGB_(0xff, 0xc1, 0x25) },
+ { "Goldenrod2", RGB_(0xee, 0xb4, 0x22) },
+ { "Goldenrod3", RGB_(0xcd, 0x9b, 0x1d) },
+ { "Goldenrod4", RGB_(0x8b, 0x69, 0x14) },
+ { "Gray", RGB_(0x80, 0x80, 0x80) },
+ { "Gray0", RGB_(0x0, 0x0, 0x0) },
+ { "Gray1", RGB_(0x3, 0x3, 0x3) },
+ { "Gray10", RGB_(0x1a, 0x1a, 0x1a) },
+ { "Gray100", RGB_(0xff, 0xff, 0xff) },
+ { "Gray11", RGB_(0x1c, 0x1c, 0x1c) },
+ { "Gray12", RGB_(0x1f, 0x1f, 0x1f) },
+ { "Gray13", RGB_(0x21, 0x21, 0x21) },
+ { "Gray14", RGB_(0x24, 0x24, 0x24) },
+ { "Gray15", RGB_(0x26, 0x26, 0x26) },
+ { "Gray16", RGB_(0x29, 0x29, 0x29) },
+ { "Gray17", RGB_(0x2b, 0x2b, 0x2b) },
+ { "Gray18", RGB_(0x2e, 0x2e, 0x2e) },
+ { "Gray19", RGB_(0x30, 0x30, 0x30) },
+ { "Gray2", RGB_(0x5, 0x5, 0x5) },
+ { "Gray20", RGB_(0x33, 0x33, 0x33) },
+ { "Gray21", RGB_(0x36, 0x36, 0x36) },
+ { "Gray22", RGB_(0x38, 0x38, 0x38) },
+ { "Gray23", RGB_(0x3b, 0x3b, 0x3b) },
+ { "Gray24", RGB_(0x3d, 0x3d, 0x3d) },
+ { "Gray25", RGB_(0x40, 0x40, 0x40) },
+ { "Gray26", RGB_(0x42, 0x42, 0x42) },
+ { "Gray27", RGB_(0x45, 0x45, 0x45) },
+ { "Gray28", RGB_(0x47, 0x47, 0x47) },
+ { "Gray29", RGB_(0x4a, 0x4a, 0x4a) },
+ { "Gray3", RGB_(0x8, 0x8, 0x8) },
+ { "Gray30", RGB_(0x4d, 0x4d, 0x4d) },
+ { "Gray31", RGB_(0x4f, 0x4f, 0x4f) },
+ { "Gray32", RGB_(0x52, 0x52, 0x52) },
+ { "Gray33", RGB_(0x54, 0x54, 0x54) },
+ { "Gray34", RGB_(0x57, 0x57, 0x57) },
+ { "Gray35", RGB_(0x59, 0x59, 0x59) },
+ { "Gray36", RGB_(0x5c, 0x5c, 0x5c) },
+ { "Gray37", RGB_(0x5e, 0x5e, 0x5e) },
+ { "Gray38", RGB_(0x61, 0x61, 0x61) },
+ { "Gray39", RGB_(0x63, 0x63, 0x63) },
+ { "Gray4", RGB_(0xa, 0xa, 0xa) },
+ { "Gray40", RGB_(0x66, 0x66, 0x66) },
+ { "Gray41", RGB_(0x69, 0x69, 0x69) },
+ { "Gray42", RGB_(0x6b, 0x6b, 0x6b) },
+ { "Gray43", RGB_(0x6e, 0x6e, 0x6e) },
+ { "Gray44", RGB_(0x70, 0x70, 0x70) },
+ { "Gray45", RGB_(0x73, 0x73, 0x73) },
+ { "Gray46", RGB_(0x75, 0x75, 0x75) },
+ { "Gray47", RGB_(0x78, 0x78, 0x78) },
+ { "Gray48", RGB_(0x7a, 0x7a, 0x7a) },
+ { "Gray49", RGB_(0x7d, 0x7d, 0x7d) },
+ { "Gray5", RGB_(0xd, 0xd, 0xd) },
+ { "Gray50", RGB_(0x7f, 0x7f, 0x7f) },
+ { "Gray51", RGB_(0x82, 0x82, 0x82) },
+ { "Gray52", RGB_(0x85, 0x85, 0x85) },
+ { "Gray53", RGB_(0x87, 0x87, 0x87) },
+ { "Gray54", RGB_(0x8a, 0x8a, 0x8a) },
+ { "Gray55", RGB_(0x8c, 0x8c, 0x8c) },
+ { "Gray56", RGB_(0x8f, 0x8f, 0x8f) },
+ { "Gray57", RGB_(0x91, 0x91, 0x91) },
+ { "Gray58", RGB_(0x94, 0x94, 0x94) },
+ { "Gray59", RGB_(0x96, 0x96, 0x96) },
+ { "Gray6", RGB_(0xf, 0xf, 0xf) },
+ { "Gray60", RGB_(0x99, 0x99, 0x99) },
+ { "Gray61", RGB_(0x9c, 0x9c, 0x9c) },
+ { "Gray62", RGB_(0x9e, 0x9e, 0x9e) },
+ { "Gray63", RGB_(0xa1, 0xa1, 0xa1) },
+ { "Gray64", RGB_(0xa3, 0xa3, 0xa3) },
+ { "Gray65", RGB_(0xa6, 0xa6, 0xa6) },
+ { "Gray66", RGB_(0xa8, 0xa8, 0xa8) },
+ { "Gray67", RGB_(0xab, 0xab, 0xab) },
+ { "Gray68", RGB_(0xad, 0xad, 0xad) },
+ { "Gray69", RGB_(0xb0, 0xb0, 0xb0) },
+ { "Gray7", RGB_(0x12, 0x12, 0x12) },
+ { "Gray70", RGB_(0xb3, 0xb3, 0xb3) },
+ { "Gray71", RGB_(0xb5, 0xb5, 0xb5) },
+ { "Gray72", RGB_(0xb8, 0xb8, 0xb8) },
+ { "Gray73", RGB_(0xba, 0xba, 0xba) },
+ { "Gray74", RGB_(0xbd, 0xbd, 0xbd) },
+ { "Gray75", RGB_(0xbf, 0xbf, 0xbf) },
+ { "Gray76", RGB_(0xc2, 0xc2, 0xc2) },
+ { "Gray77", RGB_(0xc4, 0xc4, 0xc4) },
+ { "Gray78", RGB_(0xc7, 0xc7, 0xc7) },
+ { "Gray79", RGB_(0xc9, 0xc9, 0xc9) },
+ { "Gray8", RGB_(0x14, 0x14, 0x14) },
+ { "Gray80", RGB_(0xcc, 0xcc, 0xcc) },
+ { "Gray81", RGB_(0xcf, 0xcf, 0xcf) },
+ { "Gray82", RGB_(0xd1, 0xd1, 0xd1) },
+ { "Gray83", RGB_(0xd4, 0xd4, 0xd4) },
+ { "Gray84", RGB_(0xd6, 0xd6, 0xd6) },
+ { "Gray85", RGB_(0xd9, 0xd9, 0xd9) },
+ { "Gray86", RGB_(0xdb, 0xdb, 0xdb) },
+ { "Gray87", RGB_(0xde, 0xde, 0xde) },
+ { "Gray88", RGB_(0xe0, 0xe0, 0xe0) },
+ { "Gray89", RGB_(0xe3, 0xe3, 0xe3) },
+ { "Gray9", RGB_(0x17, 0x17, 0x17) },
+ { "Gray90", RGB_(0xe5, 0xe5, 0xe5) },
+ { "Gray91", RGB_(0xe8, 0xe8, 0xe8) },
+ { "Gray92", RGB_(0xeb, 0xeb, 0xeb) },
+ { "Gray93", RGB_(0xed, 0xed, 0xed) },
+ { "Gray94", RGB_(0xf0, 0xf0, 0xf0) },
+ { "Gray95", RGB_(0xf2, 0xf2, 0xf2) },
+ { "Gray96", RGB_(0xf5, 0xf5, 0xf5) },
+ { "Gray97", RGB_(0xf7, 0xf7, 0xf7) },
+ { "Gray98", RGB_(0xfa, 0xfa, 0xfa) },
+ { "Gray99", RGB_(0xfc, 0xfc, 0xfc) },
+ { "Green", RGB_(0x00, 0x80, 0x00) },
+ { "Green1", RGB_(0x0, 0xff, 0x0) },
+ { "Green2", RGB_(0x0, 0xee, 0x0) },
+ { "Green3", RGB_(0x0, 0xcd, 0x0) },
+ { "Green4", RGB_(0x0, 0x8b, 0x0) },
+ { "GreenYellow", RGB_(0xad, 0xff, 0x2f) },
+ { "Grey", RGB_(0x80, 0x80, 0x80) },
+ { "Grey0", RGB_(0x0, 0x0, 0x0) },
+ { "Grey1", RGB_(0x3, 0x3, 0x3) },
+ { "Grey10", RGB_(0x1a, 0x1a, 0x1a) },
+ { "Grey100", RGB_(0xff, 0xff, 0xff) },
+ { "Grey11", RGB_(0x1c, 0x1c, 0x1c) },
+ { "Grey12", RGB_(0x1f, 0x1f, 0x1f) },
+ { "Grey13", RGB_(0x21, 0x21, 0x21) },
+ { "Grey14", RGB_(0x24, 0x24, 0x24) },
+ { "Grey15", RGB_(0x26, 0x26, 0x26) },
+ { "Grey16", RGB_(0x29, 0x29, 0x29) },
+ { "Grey17", RGB_(0x2b, 0x2b, 0x2b) },
+ { "Grey18", RGB_(0x2e, 0x2e, 0x2e) },
+ { "Grey19", RGB_(0x30, 0x30, 0x30) },
+ { "Grey2", RGB_(0x5, 0x5, 0x5) },
+ { "Grey20", RGB_(0x33, 0x33, 0x33) },
+ { "Grey21", RGB_(0x36, 0x36, 0x36) },
+ { "Grey22", RGB_(0x38, 0x38, 0x38) },
+ { "Grey23", RGB_(0x3b, 0x3b, 0x3b) },
+ { "Grey24", RGB_(0x3d, 0x3d, 0x3d) },
+ { "Grey25", RGB_(0x40, 0x40, 0x40) },
+ { "Grey26", RGB_(0x42, 0x42, 0x42) },
+ { "Grey27", RGB_(0x45, 0x45, 0x45) },
+ { "Grey28", RGB_(0x47, 0x47, 0x47) },
+ { "Grey29", RGB_(0x4a, 0x4a, 0x4a) },
+ { "Grey3", RGB_(0x8, 0x8, 0x8) },
+ { "Grey30", RGB_(0x4d, 0x4d, 0x4d) },
+ { "Grey31", RGB_(0x4f, 0x4f, 0x4f) },
+ { "Grey32", RGB_(0x52, 0x52, 0x52) },
+ { "Grey33", RGB_(0x54, 0x54, 0x54) },
+ { "Grey34", RGB_(0x57, 0x57, 0x57) },
+ { "Grey35", RGB_(0x59, 0x59, 0x59) },
+ { "Grey36", RGB_(0x5c, 0x5c, 0x5c) },
+ { "Grey37", RGB_(0x5e, 0x5e, 0x5e) },
+ { "Grey38", RGB_(0x61, 0x61, 0x61) },
+ { "Grey39", RGB_(0x63, 0x63, 0x63) },
+ { "Grey4", RGB_(0xa, 0xa, 0xa) },
+ { "Grey40", RGB_(0x66, 0x66, 0x66) },
+ { "Grey41", RGB_(0x69, 0x69, 0x69) },
+ { "Grey42", RGB_(0x6b, 0x6b, 0x6b) },
+ { "Grey43", RGB_(0x6e, 0x6e, 0x6e) },
+ { "Grey44", RGB_(0x70, 0x70, 0x70) },
+ { "Grey45", RGB_(0x73, 0x73, 0x73) },
+ { "Grey46", RGB_(0x75, 0x75, 0x75) },
+ { "Grey47", RGB_(0x78, 0x78, 0x78) },
+ { "Grey48", RGB_(0x7a, 0x7a, 0x7a) },
+ { "Grey49", RGB_(0x7d, 0x7d, 0x7d) },
+ { "Grey5", RGB_(0xd, 0xd, 0xd) },
+ { "Grey50", RGB_(0x7f, 0x7f, 0x7f) },
+ { "Grey51", RGB_(0x82, 0x82, 0x82) },
+ { "Grey52", RGB_(0x85, 0x85, 0x85) },
+ { "Grey53", RGB_(0x87, 0x87, 0x87) },
+ { "Grey54", RGB_(0x8a, 0x8a, 0x8a) },
+ { "Grey55", RGB_(0x8c, 0x8c, 0x8c) },
+ { "Grey56", RGB_(0x8f, 0x8f, 0x8f) },
+ { "Grey57", RGB_(0x91, 0x91, 0x91) },
+ { "Grey58", RGB_(0x94, 0x94, 0x94) },
+ { "Grey59", RGB_(0x96, 0x96, 0x96) },
+ { "Grey6", RGB_(0xf, 0xf, 0xf) },
+ { "Grey60", RGB_(0x99, 0x99, 0x99) },
+ { "Grey61", RGB_(0x9c, 0x9c, 0x9c) },
+ { "Grey62", RGB_(0x9e, 0x9e, 0x9e) },
+ { "Grey63", RGB_(0xa1, 0xa1, 0xa1) },
+ { "Grey64", RGB_(0xa3, 0xa3, 0xa3) },
+ { "Grey65", RGB_(0xa6, 0xa6, 0xa6) },
+ { "Grey66", RGB_(0xa8, 0xa8, 0xa8) },
+ { "Grey67", RGB_(0xab, 0xab, 0xab) },
+ { "Grey68", RGB_(0xad, 0xad, 0xad) },
+ { "Grey69", RGB_(0xb0, 0xb0, 0xb0) },
+ { "Grey7", RGB_(0x12, 0x12, 0x12) },
+ { "Grey70", RGB_(0xb3, 0xb3, 0xb3) },
+ { "Grey71", RGB_(0xb5, 0xb5, 0xb5) },
+ { "Grey72", RGB_(0xb8, 0xb8, 0xb8) },
+ { "Grey73", RGB_(0xba, 0xba, 0xba) },
+ { "Grey74", RGB_(0xbd, 0xbd, 0xbd) },
+ { "Grey75", RGB_(0xbf, 0xbf, 0xbf) },
+ { "Grey76", RGB_(0xc2, 0xc2, 0xc2) },
+ { "Grey77", RGB_(0xc4, 0xc4, 0xc4) },
+ { "Grey78", RGB_(0xc7, 0xc7, 0xc7) },
+ { "Grey79", RGB_(0xc9, 0xc9, 0xc9) },
+ { "Grey8", RGB_(0x14, 0x14, 0x14) },
+ { "Grey80", RGB_(0xcc, 0xcc, 0xcc) },
+ { "Grey81", RGB_(0xcf, 0xcf, 0xcf) },
+ { "Grey82", RGB_(0xd1, 0xd1, 0xd1) },
+ { "Grey83", RGB_(0xd4, 0xd4, 0xd4) },
+ { "Grey84", RGB_(0xd6, 0xd6, 0xd6) },
+ { "Grey85", RGB_(0xd9, 0xd9, 0xd9) },
+ { "Grey86", RGB_(0xdb, 0xdb, 0xdb) },
+ { "Grey87", RGB_(0xde, 0xde, 0xde) },
+ { "Grey88", RGB_(0xe0, 0xe0, 0xe0) },
+ { "Grey89", RGB_(0xe3, 0xe3, 0xe3) },
+ { "Grey9", RGB_(0x17, 0x17, 0x17) },
+ { "Grey90", RGB_(0xe5, 0xe5, 0xe5) },
+ { "Grey91", RGB_(0xe8, 0xe8, 0xe8) },
+ { "Grey92", RGB_(0xeb, 0xeb, 0xeb) },
+ { "Grey93", RGB_(0xed, 0xed, 0xed) },
+ { "Grey94", RGB_(0xf0, 0xf0, 0xf0) },
+ { "Grey95", RGB_(0xf2, 0xf2, 0xf2) },
+ { "Grey96", RGB_(0xf5, 0xf5, 0xf5) },
+ { "Grey97", RGB_(0xf7, 0xf7, 0xf7) },
+ { "Grey98", RGB_(0xfa, 0xfa, 0xfa) },
+ { "Grey99", RGB_(0xfc, 0xfc, 0xfc) },
+ { "Honeydew", RGB_(0xf0, 0xff, 0xf0) },
+ { "Honeydew1", RGB_(0xf0, 0xff, 0xf0) },
+ { "Honeydew2", RGB_(0xe0, 0xee, 0xe0) },
+ { "Honeydew3", RGB_(0xc1, 0xcd, 0xc1) },
+ { "Honeydew4", RGB_(0x83, 0x8b, 0x83) },
+ { "HotPink", RGB_(0xff, 0x69, 0xb4) },
+ { "HotPink1", RGB_(0xff, 0x6e, 0xb4) },
+ { "HotPink2", RGB_(0xee, 0x6a, 0xa7) },
+ { "HotPink3", RGB_(0xcd, 0x60, 0x90) },
+ { "HotPink4", RGB_(0x8b, 0x3a, 0x62) },
+ { "IndianRed", RGB_(0xcd, 0x5c, 0x5c) },
+ { "IndianRed1", RGB_(0xff, 0x6a, 0x6a) },
+ { "IndianRed2", RGB_(0xee, 0x63, 0x63) },
+ { "IndianRed3", RGB_(0xcd, 0x55, 0x55) },
+ { "IndianRed4", RGB_(0x8b, 0x3a, 0x3a) },
+ { "Indigo", RGB_(0x4b, 0x00, 0x82) },
+ { "Ivory", RGB_(0xff, 0xff, 0xf0) },
+ { "Ivory1", RGB_(0xff, 0xff, 0xf0) },
+ { "Ivory2", RGB_(0xee, 0xee, 0xe0) },
+ { "Ivory3", RGB_(0xcd, 0xcd, 0xc1) },
+ { "Ivory4", RGB_(0x8b, 0x8b, 0x83) },
+ { "Khaki", RGB_(0xf0, 0xe6, 0x8c) },
+ { "Khaki1", RGB_(0xff, 0xf6, 0x8f) },
+ { "Khaki2", RGB_(0xee, 0xe6, 0x85) },
+ { "Khaki3", RGB_(0xcd, 0xc6, 0x73) },
+ { "Khaki4", RGB_(0x8b, 0x86, 0x4e) },
+ { "Lavender", RGB_(0xe6, 0xe6, 0xfa) },
+ { "LavenderBlush", RGB_(0xff, 0xf0, 0xf5) },
+ { "LavenderBlush1", RGB_(0xff, 0xf0, 0xf5) },
+ { "LavenderBlush2", RGB_(0xee, 0xe0, 0xe5) },
+ { "LavenderBlush3", RGB_(0xcd, 0xc1, 0xc5) },
+ { "LavenderBlush4", RGB_(0x8b, 0x83, 0x86) },
+ { "LawnGreen", RGB_(0x7c, 0xfc, 0x00) },
+ { "LemonChiffon", RGB_(0xff, 0xfa, 0xcd) },
+ { "LemonChiffon1", RGB_(0xff, 0xfa, 0xcd) },
+ { "LemonChiffon2", RGB_(0xee, 0xe9, 0xbf) },
+ { "LemonChiffon3", RGB_(0xcd, 0xc9, 0xa5) },
+ { "LemonChiffon4", RGB_(0x8b, 0x89, 0x70) },
+ { "LightBlue", RGB_(0xad, 0xd8, 0xe6) },
+ { "LightBlue1", RGB_(0xbf, 0xef, 0xff) },
+ { "LightBlue2", RGB_(0xb2, 0xdf, 0xee) },
+ { "LightBlue3", RGB_(0x9a, 0xc0, 0xcd) },
+ { "LightBlue4", RGB_(0x68, 0x83, 0x8b) },
+ { "LightCoral", RGB_(0xf0, 0x80, 0x80) },
+ { "LightCyan", RGB_(0xe0, 0xff, 0xff) },
+ { "LightCyan1", RGB_(0xe0, 0xff, 0xff) },
+ { "LightCyan2", RGB_(0xd1, 0xee, 0xee) },
+ { "LightCyan3", RGB_(0xb4, 0xcd, 0xcd) },
+ { "LightCyan4", RGB_(0x7a, 0x8b, 0x8b) },
+ { "LightGoldenrod", RGB_(0xee, 0xdd, 0x82) },
+ { "LightGoldenrod1", RGB_(0xff, 0xec, 0x8b) },
+ { "LightGoldenrod2", RGB_(0xee, 0xdc, 0x82) },
+ { "LightGoldenrod3", RGB_(0xcd, 0xbe, 0x70) },
+ { "LightGoldenrod4", RGB_(0x8b, 0x81, 0x4c) },
+ { "LightGoldenRodYellow", RGB_(0xfa, 0xfa, 0xd2) },
+ { "LightGray", RGB_(0xd3, 0xd3, 0xd3) },
+ { "LightGreen", RGB_(0x90, 0xee, 0x90) },
+ { "LightGrey", RGB_(0xd3, 0xd3, 0xd3) },
+ { "LightMagenta", RGB_(0xff, 0xbb, 0xff) },
+ { "LightPink", RGB_(0xff, 0xb6, 0xc1) },
+ { "LightPink1", RGB_(0xff, 0xae, 0xb9) },
+ { "LightPink2", RGB_(0xee, 0xa2, 0xad) },
+ { "LightPink3", RGB_(0xcd, 0x8c, 0x95) },
+ { "LightPink4", RGB_(0x8b, 0x5f, 0x65) },
+ { "LightRed", RGB_(0xff, 0xbb, 0xbb) },
+ { "LightSalmon", RGB_(0xff, 0xa0, 0x7a) },
+ { "LightSalmon1", RGB_(0xff, 0xa0, 0x7a) },
+ { "LightSalmon2", RGB_(0xee, 0x95, 0x72) },
+ { "LightSalmon3", RGB_(0xcd, 0x81, 0x62) },
+ { "LightSalmon4", RGB_(0x8b, 0x57, 0x42) },
+ { "LightSeaGreen", RGB_(0x20, 0xb2, 0xaa) },
+ { "LightSkyBlue", RGB_(0x87, 0xce, 0xfa) },
+ { "LightSkyBlue1", RGB_(0xb0, 0xe2, 0xff) },
+ { "LightSkyBlue2", RGB_(0xa4, 0xd3, 0xee) },
+ { "LightSkyBlue3", RGB_(0x8d, 0xb6, 0xcd) },
+ { "LightSkyBlue4", RGB_(0x60, 0x7b, 0x8b) },
+ { "LightSlateBlue", RGB_(0x84, 0x70, 0xff) },
+ { "LightSlateGray", RGB_(0x77, 0x88, 0x99) },
+ { "LightSlateGrey", RGB_(0x77, 0x88, 0x99) },
+ { "LightSteelBlue", RGB_(0xb0, 0xc4, 0xde) },
+ { "LightSteelBlue1", RGB_(0xca, 0xe1, 0xff) },
+ { "LightSteelBlue2", RGB_(0xbc, 0xd2, 0xee) },
+ { "LightSteelBlue3", RGB_(0xa2, 0xb5, 0xcd) },
+ { "LightSteelBlue4", RGB_(0x6e, 0x7b, 0x8b) },
+ { "LightYellow", RGB_(0xff, 0xff, 0xe0) },
+ { "LightYellow1", RGB_(0xff, 0xff, 0xe0) },
+ { "LightYellow2", RGB_(0xee, 0xee, 0xd1) },
+ { "LightYellow3", RGB_(0xcd, 0xcd, 0xb4) },
+ { "LightYellow4", RGB_(0x8b, 0x8b, 0x7a) },
+ { "Lime", RGB_(0x00, 0xff, 0x00) },
+ { "LimeGreen", RGB_(0x32, 0xcd, 0x32) },
+ { "Linen", RGB_(0xfa, 0xf0, 0xe6) },
+ { "Magenta", RGB_(0xff, 0x00, 0xff) },
+ { "Magenta1", RGB_(0xff, 0x0, 0xff) },
+ { "Magenta2", RGB_(0xee, 0x0, 0xee) },
+ { "Magenta3", RGB_(0xcd, 0x0, 0xcd) },
+ { "Magenta4", RGB_(0x8b, 0x0, 0x8b) },
+ { "Maroon", RGB_(0x80, 0x00, 0x00) },
+ { "Maroon1", RGB_(0xff, 0x34, 0xb3) },
+ { "Maroon2", RGB_(0xee, 0x30, 0xa7) },
+ { "Maroon3", RGB_(0xcd, 0x29, 0x90) },
+ { "Maroon4", RGB_(0x8b, 0x1c, 0x62) },
+ { "MediumAquamarine", RGB_(0x66, 0xcd, 0xaa) },
+ { "MediumBlue", RGB_(0x00, 0x00, 0xcd) },
+ { "MediumOrchid", RGB_(0xba, 0x55, 0xd3) },
+ { "MediumOrchid1", RGB_(0xe0, 0x66, 0xff) },
+ { "MediumOrchid2", RGB_(0xd1, 0x5f, 0xee) },
+ { "MediumOrchid3", RGB_(0xb4, 0x52, 0xcd) },
+ { "MediumOrchid4", RGB_(0x7a, 0x37, 0x8b) },
+ { "MediumPurple", RGB_(0x93, 0x70, 0xdb) },
+ { "MediumPurple1", RGB_(0xab, 0x82, 0xff) },
+ { "MediumPurple2", RGB_(0x9f, 0x79, 0xee) },
+ { "MediumPurple3", RGB_(0x89, 0x68, 0xcd) },
+ { "MediumPurple4", RGB_(0x5d, 0x47, 0x8b) },
+ { "MediumSeaGreen", RGB_(0x3c, 0xb3, 0x71) },
+ { "MediumSlateBlue", RGB_(0x7b, 0x68, 0xee) },
+ { "MediumSpringGreen", RGB_(0x00, 0xfa, 0x9a) },
+ { "MediumTurquoise", RGB_(0x48, 0xd1, 0xcc) },
+ { "MediumVioletRed", RGB_(0xc7, 0x15, 0x85) },
+ { "MidnightBlue", RGB_(0x19, 0x19, 0x70) },
+ { "MintCream", RGB_(0xf5, 0xff, 0xfa) },
+ { "MistyRose", RGB_(0xff, 0xe4, 0xe1) },
+ { "MistyRose1", RGB_(0xff, 0xe4, 0xe1) },
+ { "MistyRose2", RGB_(0xee, 0xd5, 0xd2) },
+ { "MistyRose3", RGB_(0xcd, 0xb7, 0xb5) },
+ { "MistyRose4", RGB_(0x8b, 0x7d, 0x7b) },
+ { "Moccasin", RGB_(0xff, 0xe4, 0xb5) },
+ { "NavajoWhite", RGB_(0xff, 0xde, 0xad) },
+ { "NavajoWhite1", RGB_(0xff, 0xde, 0xad) },
+ { "NavajoWhite2", RGB_(0xee, 0xcf, 0xa1) },
+ { "NavajoWhite3", RGB_(0xcd, 0xb3, 0x8b) },
+ { "NavajoWhite4", RGB_(0x8b, 0x79, 0x5e) },
+ { "Navy", RGB_(0x00, 0x00, 0x80) },
+ { "NavyBlue", RGB_(0x0, 0x0, 0x80) },
+ { "OldLace", RGB_(0xfd, 0xf5, 0xe6) },
+ { "Olive", RGB_(0x80, 0x80, 0x00) },
+ { "OliveDrab", RGB_(0x6b, 0x8e, 0x23) },
+ { "OliveDrab1", RGB_(0xc0, 0xff, 0x3e) },
+ { "OliveDrab2", RGB_(0xb3, 0xee, 0x3a) },
+ { "OliveDrab3", RGB_(0x9a, 0xcd, 0x32) },
+ { "OliveDrab4", RGB_(0x69, 0x8b, 0x22) },
+ { "Orange", RGB_(0xff, 0xa5, 0x00) },
+ { "Orange1", RGB_(0xff, 0xa5, 0x0) },
+ { "Orange2", RGB_(0xee, 0x9a, 0x0) },
+ { "Orange3", RGB_(0xcd, 0x85, 0x0) },
+ { "Orange4", RGB_(0x8b, 0x5a, 0x0) },
+ { "OrangeRed", RGB_(0xff, 0x45, 0x00) },
+ { "OrangeRed1", RGB_(0xff, 0x45, 0x0) },
+ { "OrangeRed2", RGB_(0xee, 0x40, 0x0) },
+ { "OrangeRed3", RGB_(0xcd, 0x37, 0x0) },
+ { "OrangeRed4", RGB_(0x8b, 0x25, 0x0) },
+ { "Orchid", RGB_(0xda, 0x70, 0xd6) },
+ { "Orchid1", RGB_(0xff, 0x83, 0xfa) },
+ { "Orchid2", RGB_(0xee, 0x7a, 0xe9) },
+ { "Orchid3", RGB_(0xcd, 0x69, 0xc9) },
+ { "Orchid4", RGB_(0x8b, 0x47, 0x89) },
+ { "PaleGoldenRod", RGB_(0xee, 0xe8, 0xaa) },
+ { "PaleGreen", RGB_(0x98, 0xfb, 0x98) },
+ { "PaleGreen1", RGB_(0x9a, 0xff, 0x9a) },
+ { "PaleGreen2", RGB_(0x90, 0xee, 0x90) },
+ { "PaleGreen3", RGB_(0x7c, 0xcd, 0x7c) },
+ { "PaleGreen4", RGB_(0x54, 0x8b, 0x54) },
+ { "PaleTurquoise", RGB_(0xaf, 0xee, 0xee) },
+ { "PaleTurquoise1", RGB_(0xbb, 0xff, 0xff) },
+ { "PaleTurquoise2", RGB_(0xae, 0xee, 0xee) },
+ { "PaleTurquoise3", RGB_(0x96, 0xcd, 0xcd) },
+ { "PaleTurquoise4", RGB_(0x66, 0x8b, 0x8b) },
+ { "PaleVioletRed", RGB_(0xdb, 0x70, 0x93) },
+ { "PaleVioletRed1", RGB_(0xff, 0x82, 0xab) },
+ { "PaleVioletRed2", RGB_(0xee, 0x79, 0x9f) },
+ { "PaleVioletRed3", RGB_(0xcd, 0x68, 0x89) },
+ { "PaleVioletRed4", RGB_(0x8b, 0x47, 0x5d) },
+ { "PapayaWhip", RGB_(0xff, 0xef, 0xd5) },
+ { "PeachPuff", RGB_(0xff, 0xda, 0xb9) },
+ { "PeachPuff1", RGB_(0xff, 0xda, 0xb9) },
+ { "PeachPuff2", RGB_(0xee, 0xcb, 0xad) },
+ { "PeachPuff3", RGB_(0xcd, 0xaf, 0x95) },
+ { "PeachPuff4", RGB_(0x8b, 0x77, 0x65) },
+ { "Peru", RGB_(0xcd, 0x85, 0x3f) },
+ { "Pink", RGB_(0xff, 0xc0, 0xcb) },
+ { "Pink1", RGB_(0xff, 0xb5, 0xc5) },
+ { "Pink2", RGB_(0xee, 0xa9, 0xb8) },
+ { "Pink3", RGB_(0xcd, 0x91, 0x9e) },
+ { "Pink4", RGB_(0x8b, 0x63, 0x6c) },
+ { "Plum", RGB_(0xdd, 0xa0, 0xdd) },
+ { "Plum1", RGB_(0xff, 0xbb, 0xff) },
+ { "Plum2", RGB_(0xee, 0xae, 0xee) },
+ { "Plum3", RGB_(0xcd, 0x96, 0xcd) },
+ { "Plum4", RGB_(0x8b, 0x66, 0x8b) },
+ { "PowderBlue", RGB_(0xb0, 0xe0, 0xe6) },
+ { "Purple", RGB_(0x80, 0x00, 0x80) },
+ { "Purple1", RGB_(0x9b, 0x30, 0xff) },
+ { "Purple2", RGB_(0x91, 0x2c, 0xee) },
+ { "Purple3", RGB_(0x7d, 0x26, 0xcd) },
+ { "Purple4", RGB_(0x55, 0x1a, 0x8b) },
+ { "RebeccaPurple", RGB_(0x66, 0x33, 0x99) },
+ { "Red", RGB_(0xff, 0x00, 0x00) },
+ { "Red1", RGB_(0xff, 0x0, 0x0) },
+ { "Red2", RGB_(0xee, 0x0, 0x0) },
+ { "Red3", RGB_(0xcd, 0x0, 0x0) },
+ { "Red4", RGB_(0x8b, 0x0, 0x0) },
+ { "RosyBrown", RGB_(0xbc, 0x8f, 0x8f) },
+ { "RosyBrown1", RGB_(0xff, 0xc1, 0xc1) },
+ { "RosyBrown2", RGB_(0xee, 0xb4, 0xb4) },
+ { "RosyBrown3", RGB_(0xcd, 0x9b, 0x9b) },
+ { "RosyBrown4", RGB_(0x8b, 0x69, 0x69) },
+ { "RoyalBlue", RGB_(0x41, 0x69, 0xe1) },
+ { "RoyalBlue1", RGB_(0x48, 0x76, 0xff) },
+ { "RoyalBlue2", RGB_(0x43, 0x6e, 0xee) },
+ { "RoyalBlue3", RGB_(0x3a, 0x5f, 0xcd) },
+ { "RoyalBlue4", RGB_(0x27, 0x40, 0x8b) },
+ { "SaddleBrown", RGB_(0x8b, 0x45, 0x13) },
+ { "Salmon", RGB_(0xfa, 0x80, 0x72) },
+ { "Salmon1", RGB_(0xff, 0x8c, 0x69) },
+ { "Salmon2", RGB_(0xee, 0x82, 0x62) },
+ { "Salmon3", RGB_(0xcd, 0x70, 0x54) },
+ { "Salmon4", RGB_(0x8b, 0x4c, 0x39) },
+ { "SandyBrown", RGB_(0xf4, 0xa4, 0x60) },
+ { "SeaGreen", RGB_(0x2e, 0x8b, 0x57) },
+ { "SeaGreen1", RGB_(0x54, 0xff, 0x9f) },
+ { "SeaGreen2", RGB_(0x4e, 0xee, 0x94) },
+ { "SeaGreen3", RGB_(0x43, 0xcd, 0x80) },
+ { "SeaGreen4", RGB_(0x2e, 0x8b, 0x57) },
+ { "SeaShell", RGB_(0xff, 0xf5, 0xee) },
+ { "Seashell1", RGB_(0xff, 0xf5, 0xee) },
+ { "Seashell2", RGB_(0xee, 0xe5, 0xde) },
+ { "Seashell3", RGB_(0xcd, 0xc5, 0xbf) },
+ { "Seashell4", RGB_(0x8b, 0x86, 0x82) },
+ { "Sienna", RGB_(0xa0, 0x52, 0x2d) },
+ { "Sienna1", RGB_(0xff, 0x82, 0x47) },
+ { "Sienna2", RGB_(0xee, 0x79, 0x42) },
+ { "Sienna3", RGB_(0xcd, 0x68, 0x39) },
+ { "Sienna4", RGB_(0x8b, 0x47, 0x26) },
+ { "Silver", RGB_(0xc0, 0xc0, 0xc0) },
+ { "SkyBlue", RGB_(0x87, 0xce, 0xeb) },
+ { "SkyBlue1", RGB_(0x87, 0xce, 0xff) },
+ { "SkyBlue2", RGB_(0x7e, 0xc0, 0xee) },
+ { "SkyBlue3", RGB_(0x6c, 0xa6, 0xcd) },
+ { "SkyBlue4", RGB_(0x4a, 0x70, 0x8b) },
+ { "SlateBlue", RGB_(0x6a, 0x5a, 0xcd) },
+ { "SlateBlue1", RGB_(0x83, 0x6f, 0xff) },
+ { "SlateBlue2", RGB_(0x7a, 0x67, 0xee) },
+ { "SlateBlue3", RGB_(0x69, 0x59, 0xcd) },
+ { "SlateBlue4", RGB_(0x47, 0x3c, 0x8b) },
+ { "SlateGray", RGB_(0x70, 0x80, 0x90) },
+ { "SlateGray1", RGB_(0xc6, 0xe2, 0xff) },
+ { "SlateGray2", RGB_(0xb9, 0xd3, 0xee) },
+ { "SlateGray3", RGB_(0x9f, 0xb6, 0xcd) },
+ { "SlateGray4", RGB_(0x6c, 0x7b, 0x8b) },
+ { "SlateGrey", RGB_(0x70, 0x80, 0x90) },
+ { "Snow", RGB_(0xff, 0xfa, 0xfa) },
+ { "Snow1", RGB_(0xff, 0xfa, 0xfa) },
+ { "Snow2", RGB_(0xee, 0xe9, 0xe9) },
+ { "Snow3", RGB_(0xcd, 0xc9, 0xc9) },
+ { "Snow4", RGB_(0x8b, 0x89, 0x89) },
+ { "SpringGreen", RGB_(0x00, 0xff, 0x7f) },
+ { "SpringGreen1", RGB_(0x0, 0xff, 0x7f) },
+ { "SpringGreen2", RGB_(0x0, 0xee, 0x76) },
+ { "SpringGreen3", RGB_(0x0, 0xcd, 0x66) },
+ { "SpringGreen4", RGB_(0x0, 0x8b, 0x45) },
+ { "SteelBlue", RGB_(0x46, 0x82, 0xb4) },
+ { "SteelBlue1", RGB_(0x63, 0xb8, 0xff) },
+ { "SteelBlue2", RGB_(0x5c, 0xac, 0xee) },
+ { "SteelBlue3", RGB_(0x4f, 0x94, 0xcd) },
+ { "SteelBlue4", RGB_(0x36, 0x64, 0x8b) },
+ { "Tan", RGB_(0xd2, 0xb4, 0x8c) },
+ { "Tan1", RGB_(0xff, 0xa5, 0x4f) },
+ { "Tan2", RGB_(0xee, 0x9a, 0x49) },
+ { "Tan3", RGB_(0xcd, 0x85, 0x3f) },
+ { "Tan4", RGB_(0x8b, 0x5a, 0x2b) },
+ { "Teal", RGB_(0x00, 0x80, 0x80) },
+ { "Thistle", RGB_(0xd8, 0xbf, 0xd8) },
+ { "Thistle1", RGB_(0xff, 0xe1, 0xff) },
+ { "Thistle2", RGB_(0xee, 0xd2, 0xee) },
+ { "Thistle3", RGB_(0xcd, 0xb5, 0xcd) },
+ { "Thistle4", RGB_(0x8b, 0x7b, 0x8b) },
+ { "Tomato", RGB_(0xff, 0x63, 0x47) },
+ { "Tomato1", RGB_(0xff, 0x63, 0x47) },
+ { "Tomato2", RGB_(0xee, 0x5c, 0x42) },
+ { "Tomato3", RGB_(0xcd, 0x4f, 0x39) },
+ { "Tomato4", RGB_(0x8b, 0x36, 0x26) },
+ { "Turquoise", RGB_(0x40, 0xe0, 0xd0) },
+ { "Turquoise1", RGB_(0x0, 0xf5, 0xff) },
+ { "Turquoise2", RGB_(0x0, 0xe5, 0xee) },
+ { "Turquoise3", RGB_(0x0, 0xc5, 0xcd) },
+ { "Turquoise4", RGB_(0x0, 0x86, 0x8b) },
+ { "Violet", RGB_(0xee, 0x82, 0xee) },
+ { "VioletRed", RGB_(0xd0, 0x20, 0x90) },
+ { "VioletRed1", RGB_(0xff, 0x3e, 0x96) },
+ { "VioletRed2", RGB_(0xee, 0x3a, 0x8c) },
+ { "VioletRed3", RGB_(0xcd, 0x32, 0x78) },
+ { "VioletRed4", RGB_(0x8b, 0x22, 0x52) },
+ { "WebGray", RGB_(0x80, 0x80, 0x80) },
+ { "WebGreen", RGB_(0x0, 0x80, 0x0) },
+ { "WebGrey", RGB_(0x80, 0x80, 0x80) },
+ { "WebMaroon", RGB_(0x80, 0x0, 0x0) },
+ { "WebPurple", RGB_(0x80, 0x0, 0x80) },
+ { "Wheat", RGB_(0xf5, 0xde, 0xb3) },
+ { "Wheat1", RGB_(0xff, 0xe7, 0xba) },
+ { "Wheat2", RGB_(0xee, 0xd8, 0xae) },
+ { "Wheat3", RGB_(0xcd, 0xba, 0x96) },
+ { "Wheat4", RGB_(0x8b, 0x7e, 0x66) },
+ { "White", RGB_(0xff, 0xff, 0xff) },
+ { "WhiteSmoke", RGB_(0xf5, 0xf5, 0xf5) },
+ { "X11Gray", RGB_(0xbe, 0xbe, 0xbe) },
+ { "X11Green", RGB_(0x0, 0xff, 0x0) },
+ { "X11Grey", RGB_(0xbe, 0xbe, 0xbe) },
+ { "X11Maroon", RGB_(0xb0, 0x30, 0x60) },
+ { "X11Purple", RGB_(0xa0, 0x20, 0xf0) },
+ { "Yellow", RGB_(0xff, 0xff, 0x00) },
+ { "Yellow1", RGB_(0xff, 0xff, 0x0) },
+ { "Yellow2", RGB_(0xee, 0xee, 0x0) },
+ { "Yellow3", RGB_(0xcd, 0xcd, 0x0) },
+ { "Yellow4", RGB_(0x8b, 0x8b, 0x0) },
+ { "YellowGreen", RGB_(0x9a, 0xcd, 0x32) },
+ { NULL, 0 },
+};
+
+/// Translate to RgbValue if \p name is an hex value (e.g. #XXXXXX),
+/// else look into color_name_table to translate a color name to its
+/// hex value
+///
+/// @param[in] name string value to convert to RGB
+/// return the hex value or -1 if could not find a correct value
+RgbValue name_to_color(const char *name)
+{
+ if (name[0] == '#' && isxdigit(name[1]) && isxdigit(name[2])
+ && isxdigit(name[3]) && isxdigit(name[4]) && isxdigit(name[5])
+ && isxdigit(name[6]) && name[7] == NUL) {
+ // rgb hex string
+ return (RgbValue)strtol((char *)(name + 1), NULL, 16);
+ } else if (!STRICMP(name, "bg") || !STRICMP(name, "background")) {
+ return normal_bg;
+ } else if (!STRICMP(name, "fg") || !STRICMP(name, "foreground")) {
+ return normal_fg;
+ }
+
+ for (int i = 0; color_name_table[i].name != NULL; i++) {
+ if (!STRICMP(name, color_name_table[i].name)) {
+ return color_name_table[i].color;
+ }
+ }
+
+ return -1;
+}
+
+int name_to_ctermcolor(const char *name)
+{
+ int i;
+ int off = TOUPPER_ASC(*name);
+ for (i = ARRAY_SIZE(color_names); --i >= 0;) {
+ if (off == color_names[i][0]
+ && STRICMP(name+1, color_names[i]+1) == 0) {
+ break;
+ }
+ }
+ if (i < 0) {
+ return -1;
+ }
+ TriState bold = kNone;
+ return lookup_color(i, false, &bold);
+}
diff --git a/src/nvim/highlight_group.h b/src/nvim/highlight_group.h
new file mode 100644
index 0000000000..325113a4ab
--- /dev/null
+++ b/src/nvim/highlight_group.h
@@ -0,0 +1,19 @@
+#ifndef NVIM_HIGHLIGHT_GROUP_H
+#define NVIM_HIGHLIGHT_GROUP_H
+
+#include "nvim/types.h"
+#include "nvim/eval.h"
+
+#define MAX_HL_ID 20000 // maximum value for a highlight ID.
+
+typedef struct {
+ char *name;
+ RgbValue color;
+} color_name_table_T;
+extern color_name_table_T color_name_table[];
+
+#ifdef INCLUDE_GENERATED_DECLARATIONS
+# include "highlight_group.h.generated.h"
+#endif
+
+#endif // NVIM_HIGHLIGHT_GROUP_H
diff --git a/src/nvim/indent.c b/src/nvim/indent.c
index 8cc5bc2436..59ba2c92f7 100644
--- a/src/nvim/indent.c
+++ b/src/nvim/indent.c
@@ -70,7 +70,7 @@ int get_indent_str(const char_u *ptr, int ts, bool list)
{
int count = 0;
- for (; *ptr; ++ptr) {
+ for (; *ptr; ptr++) {
// Count a tab for what it is worth.
if (*ptr == TAB) {
if (!list || curwin->w_p_lcs_chars.tab1) {
@@ -442,10 +442,9 @@ int get_breakindent_win(win_T *wp, char_u *line)
static long *prev_vts = NULL; // Cached vartabs values.
int bri = 0;
// window width minus window margin space, i.e. what rests for text
- const int eff_wwidth = wp->w_width_inner
- - ((wp->w_p_nu || wp->w_p_rnu)
- && (vim_strchr(p_cpo, CPO_NUMCOL) == NULL)
- ? number_width(wp) + 1 : 0);
+ const int eff_wwidth = wp->w_width_inner -
+ ((wp->w_p_nu || wp->w_p_rnu)
+ && (vim_strchr(p_cpo, CPO_NUMCOL) == NULL) ? number_width(wp) + 1 : 0);
// used cached indent, unless pointer or 'tabstop' changed
if (prev_line != line || prev_ts != wp->w_buffer->b_p_ts
@@ -512,7 +511,7 @@ int inindent(int extra)
char_u *ptr;
colnr_T col;
- for (col = 0, ptr = get_cursor_line_ptr(); ascii_iswhite(*ptr); ++col) {
+ for (col = 0, ptr = get_cursor_line_ptr(); ascii_iswhite(*ptr); col++) {
ptr++;
}
@@ -630,7 +629,7 @@ int get_lisp_indent(void)
continue;
}
- for (that = get_cursor_line_ptr(); *that != NUL; ++that) {
+ for (that = get_cursor_line_ptr(); *that != NUL; that++) {
if (*that == ';') {
while (*(that + 1) != NUL) {
that++;
diff --git a/src/nvim/lua/converter.c b/src/nvim/lua/converter.c
index 2b54e56df1..0bb224c729 100644
--- a/src/nvim/lua/converter.c
+++ b/src/nvim/lua/converter.c
@@ -286,9 +286,7 @@ bool nlua_pop_typval(lua_State *lstate, typval_T *ret_tv)
break;
case LUA_TBOOLEAN:
cur.tv->v_type = VAR_BOOL;
- cur.tv->vval.v_bool = (lua_toboolean(lstate, -1)
- ? kBoolVarTrue
- : kBoolVarFalse);
+ cur.tv->vval.v_bool = (lua_toboolean(lstate, -1) ? kBoolVarTrue : kBoolVarFalse);
break;
case LUA_TSTRING: {
size_t len;
@@ -478,7 +476,13 @@ static bool typval_conv_special = false;
#define TYPVAL_ENCODE_CONV_FUNC_START(tv, fun) \
do { \
- TYPVAL_ENCODE_CONV_NIL(tv); \
+ ufunc_T *fp = find_func(fun); \
+ assert(fp != NULL); \
+ if (fp->uf_cb == nlua_CFunction_func_call) { \
+ nlua_pushref(lstate, ((LuaCFunctionState *)fp->uf_cb_state)->lua_callable.func_ref); \
+ } else { \
+ TYPVAL_ENCODE_CONV_NIL(tv); \
+ } \
goto typval_encode_stop_converting_one_item; \
} while (0)
@@ -551,8 +555,8 @@ static bool typval_conv_special = false;
const MPConvStackVal mpval = kv_A(*mpstack, backref - 1); \
if (mpval.type == conv_type) { \
if (conv_type == kMPConvDict \
- ? (void *)mpval.data.d.dict == (void *)(val) \
- : (void *)mpval.data.l.list == (void *)(val)) { \
+ ? (void *)mpval.data.d.dict == (void *)(val) \
+ : (void *)mpval.data.l.list == (void *)(val)) { \
lua_pushvalue(lstate, \
-((int)((kv_size(*mpstack) - backref + 1) * 2))); \
break; \
@@ -617,14 +621,6 @@ bool nlua_push_typval(lua_State *lstate, typval_T *const tv, bool special)
semsg(_("E1502: Lua failed to grow stack to %i"), initial_size + 4);
return false;
}
- if (tv->v_type == VAR_FUNC) {
- ufunc_T *fp = find_func(tv->vval.v_string);
- assert(fp != NULL);
- if (fp->uf_cb == nlua_CFunction_func_call) {
- nlua_pushref(lstate, ((LuaCFunctionState *)fp->uf_cb_state)->lua_callable.func_ref);
- return true;
- }
- }
if (encode_vim_to_lua(lstate, tv, "nlua_push_typval argument") == FAIL) {
return false;
}
@@ -1133,10 +1129,7 @@ Object nlua_pop_Object(lua_State *const lstate, bool ref, Error *const err)
case LUA_TSTRING: {
size_t len;
const char *s = lua_tolstring(lstate, -1, &len);
- *cur.obj = STRING_OBJ(((String) {
- .data = xmemdupz(s, len),
- .size = len,
- }));
+ *cur.obj = STRING_OBJ(((String) { .data = xmemdupz(s, len), .size = len }));
break;
}
case LUA_TNUMBER: {
@@ -1154,11 +1147,7 @@ Object nlua_pop_Object(lua_State *const lstate, bool ref, Error *const err)
switch (table_props.type) {
case kObjectTypeArray:
- *cur.obj = ARRAY_OBJ(((Array) {
- .items = NULL,
- .size = 0,
- .capacity = 0,
- }));
+ *cur.obj = ARRAY_OBJ(((Array) { .items = NULL, .size = 0, .capacity = 0 }));
if (table_props.maxidx != 0) {
cur.obj->data.array.items =
xcalloc(table_props.maxidx,
@@ -1169,11 +1158,7 @@ Object nlua_pop_Object(lua_State *const lstate, bool ref, Error *const err)
}
break;
case kObjectTypeDictionary:
- *cur.obj = DICTIONARY_OBJ(((Dictionary) {
- .items = NULL,
- .size = 0,
- .capacity = 0,
- }));
+ *cur.obj = DICTIONARY_OBJ(((Dictionary) { .items = NULL, .size = 0, .capacity = 0 }));
if (table_props.string_keys_num != 0) {
cur.obj->data.dictionary.items =
xcalloc(table_props.string_keys_num,
diff --git a/src/nvim/lua/executor.c b/src/nvim/lua/executor.c
index 054f6c9483..21625854fb 100644
--- a/src/nvim/lua/executor.c
+++ b/src/nvim/lua/executor.c
@@ -92,7 +92,22 @@ static void nlua_error(lua_State *const lstate, const char *const msg)
FUNC_ATTR_NONNULL_ALL
{
size_t len;
- const char *const str = lua_tolstring(lstate, -1, &len);
+ const char *str = NULL;
+
+ if (luaL_getmetafield(lstate, -1, "__tostring")) {
+ if (lua_isfunction(lstate, -1) && luaL_callmeta(lstate, -2, "__tostring")) {
+ // call __tostring, convert the result and pop result.
+ str = lua_tolstring(lstate, -1, &len);
+ lua_pop(lstate, 1);
+ }
+ // pop __tostring.
+ lua_pop(lstate, 1);
+ }
+
+ if (!str) {
+ // defer to lua default conversion, this will render tables as [NULL].
+ str = lua_tolstring(lstate, -1, &len);
+ }
msg_ext_set_kind("lua_error");
semsg_multiline(msg, (int)len, str);
diff --git a/src/nvim/main.c b/src/nvim/main.c
index 230be9d9b9..dec1ae93e7 100644
--- a/src/nvim/main.c
+++ b/src/nvim/main.c
@@ -25,10 +25,12 @@
#include "nvim/getchar.h"
#include "nvim/hashtab.h"
#include "nvim/highlight.h"
+#include "nvim/highlight_group.h"
#include "nvim/iconv.h"
#include "nvim/if_cscope.h"
#include "nvim/lua/executor.h"
#include "nvim/main.h"
+#include "nvim/ui_client.h"
#include "nvim/vim.h"
#ifdef HAVE_LOCALE_H
# include <locale.h>
@@ -111,7 +113,6 @@ static const char *err_too_many_args = N_("Too many edit arguments");
static const char *err_extra_cmd =
N_("Too many \"+command\", \"-c command\" or \"--cmd command\" arguments");
-
void event_init(void)
{
loop_init(&main_loop, NULL);
@@ -269,8 +270,7 @@ int main(int argc, char **argv)
server_init(params.listen_addr);
if (params.remote) {
- handle_remote_client(&params, params.remote,
- params.server_addr, argc, argv);
+ remote_request(&params, params.remote, params.server_addr, argc, argv);
}
if (GARGCOUNT > 0) {
@@ -344,6 +344,12 @@ int main(int argc, char **argv)
TIME_MSG("init screen for UI");
}
+ if (ui_client_channel_id) {
+ ui_client_init(ui_client_channel_id);
+ ui_client_execute(ui_client_channel_id);
+ abort(); // unreachable
+ }
+
init_default_mappings(); // Default mappings.
TIME_MSG("init default mappings");
@@ -807,91 +813,114 @@ static void init_locale(void)
}
#endif
+
+static uint64_t server_connect(char *server_addr, const char **errmsg)
+{
+ if (server_addr == NULL) {
+ *errmsg = "no address specified";
+ return 0;
+ }
+ CallbackReader on_data = CALLBACK_READER_INIT;
+ const char *error = NULL;
+ bool is_tcp = strrchr(server_addr, ':') ? true : false;
+ // connected to channel
+ uint64_t chan = channel_connect(is_tcp, server_addr, true, on_data, 50, &error);
+ if (error) {
+ *errmsg = error;
+ return 0;
+ }
+ return chan;
+}
+
/// Handle remote subcommands
-static void handle_remote_client(mparm_T *params, int remote_args,
- char *server_addr, int argc, char **argv)
+static void remote_request(mparm_T *params, int remote_args,
+ char *server_addr, int argc, char **argv)
{
- Object rvobj = OBJECT_INIT;
- rvobj.data.dictionary = (Dictionary)ARRAY_DICT_INIT;
- rvobj.type = kObjectTypeDictionary;
- CallbackReader on_data = CALLBACK_READER_INIT;
- const char *connect_error = NULL;
- uint64_t rc_id = 0;
- if (server_addr != NULL) {
- rc_id = channel_connect(false, server_addr, true, on_data, 50, &connect_error);
+ const char *connect_error = NULL;
+ uint64_t chan = server_connect(server_addr, &connect_error);
+ Object rvobj = OBJECT_INIT;
+
+ if (strequal(argv[remote_args], "--remote-ui-test")) {
+ if (!chan) {
+ emsg(connect_error);
+ exit(1);
}
- int t_argc = remote_args;
- Array args = ARRAY_DICT_INIT;
- String arg_s;
- for (; t_argc < argc; t_argc++) {
- arg_s = cstr_to_string(argv[t_argc]);
- ADD(args, STRING_OBJ(arg_s));
- }
+ ui_client_channel_id = chan;
+ return;
+ }
- Error err = ERROR_INIT;
- Array a = ARRAY_DICT_INIT;
- ADD(a, INTEGER_OBJ((int)rc_id));
- ADD(a, CSTR_TO_OBJ(server_addr));
- ADD(a, CSTR_TO_OBJ(connect_error));
- ADD(a, ARRAY_OBJ(args));
- String s = STATIC_CSTR_AS_STRING("return vim._cs_remote(...)");
- Object o = nlua_exec(s, a, &err);
- api_free_array(a);
- if (ERROR_SET(&err)) {
- mch_errmsg(err.msg);
- mch_errmsg("\n");
- os_exit(2);
- }
+ Array args = ARRAY_DICT_INIT;
+ String arg_s;
+ for (int t_argc = remote_args; t_argc < argc; t_argc++) {
+ arg_s = cstr_to_string(argv[t_argc]);
+ ADD(args, STRING_OBJ(arg_s));
+ }
- if (o.type == kObjectTypeDictionary) {
- rvobj.data.dictionary = o.data.dictionary;
- } else {
- mch_errmsg("vim._cs_remote returned unexpected value\n");
- os_exit(2);
- }
+ Error err = ERROR_INIT;
+ Array a = ARRAY_DICT_INIT;
+ ADD(a, INTEGER_OBJ((int)chan));
+ ADD(a, CSTR_TO_OBJ(server_addr));
+ ADD(a, CSTR_TO_OBJ(connect_error));
+ ADD(a, ARRAY_OBJ(args));
+ String s = STATIC_CSTR_AS_STRING("return vim._cs_remote(...)");
+ Object o = nlua_exec(s, a, &err);
+ api_free_array(a);
+ if (ERROR_SET(&err)) {
+ mch_errmsg(err.msg);
+ mch_errmsg("\n");
+ os_exit(2);
+ }
- TriState should_exit = kNone;
- TriState tabbed = kNone;
+ if (o.type == kObjectTypeDictionary) {
+ rvobj.data.dictionary = o.data.dictionary;
+ } else {
+ mch_errmsg("vim._cs_remote returned unexpected value\n");
+ os_exit(2);
+ }
- for (size_t i = 0; i < rvobj.data.dictionary.size ; i++) {
- if (strcmp(rvobj.data.dictionary.items[i].key.data, "errmsg") == 0) {
- if (rvobj.data.dictionary.items[i].value.type != kObjectTypeString) {
- mch_errmsg("vim._cs_remote returned an unexpected type for 'errmsg'\n");
- os_exit(2);
- }
- mch_errmsg(rvobj.data.dictionary.items[i].value.data.string.data);
- mch_errmsg("\n");
+ TriState should_exit = kNone;
+ TriState tabbed = kNone;
+
+ for (size_t i = 0; i < rvobj.data.dictionary.size ; i++) {
+ if (strcmp(rvobj.data.dictionary.items[i].key.data, "errmsg") == 0) {
+ if (rvobj.data.dictionary.items[i].value.type != kObjectTypeString) {
+ mch_errmsg("vim._cs_remote returned an unexpected type for 'errmsg'\n");
os_exit(2);
- } else if (strcmp(rvobj.data.dictionary.items[i].key.data, "tabbed") == 0) {
- if (rvobj.data.dictionary.items[i].value.type != kObjectTypeBoolean) {
- mch_errmsg("vim._cs_remote returned an unexpected type for 'tabbed'\n");
- os_exit(2);
- }
- tabbed = rvobj.data.dictionary.items[i].value.data.boolean ? kTrue : kFalse;
- } else if (strcmp(rvobj.data.dictionary.items[i].key.data, "should_exit") == 0) {
- if (rvobj.data.dictionary.items[i].value.type != kObjectTypeBoolean) {
- mch_errmsg("vim._cs_remote returned an unexpected type for 'should_exit'\n");
- os_exit(2);
- }
- should_exit = rvobj.data.dictionary.items[i].value.data.boolean ? kTrue : kFalse;
}
- }
- if (should_exit == kNone || tabbed == kNone) {
- mch_errmsg("vim._cs_remote didn't return a value for should_exit or tabbed, bailing\n");
+ mch_errmsg(rvobj.data.dictionary.items[i].value.data.string.data);
+ mch_errmsg("\n");
os_exit(2);
+ } else if (strcmp(rvobj.data.dictionary.items[i].key.data, "tabbed") == 0) {
+ if (rvobj.data.dictionary.items[i].value.type != kObjectTypeBoolean) {
+ mch_errmsg("vim._cs_remote returned an unexpected type for 'tabbed'\n");
+ os_exit(2);
+ }
+ tabbed = rvobj.data.dictionary.items[i].value.data.boolean ? kTrue : kFalse;
+ } else if (strcmp(rvobj.data.dictionary.items[i].key.data, "should_exit") == 0) {
+ if (rvobj.data.dictionary.items[i].value.type != kObjectTypeBoolean) {
+ mch_errmsg("vim._cs_remote returned an unexpected type for 'should_exit'\n");
+ os_exit(2);
+ }
+ should_exit = rvobj.data.dictionary.items[i].value.data.boolean ? kTrue : kFalse;
}
- api_free_object(o);
+ }
+ if (should_exit == kNone || tabbed == kNone) {
+ mch_errmsg("vim._cs_remote didn't return a value for should_exit or tabbed, bailing\n");
+ os_exit(2);
+ }
+ api_free_object(o);
- if (should_exit == kTrue) {
- os_exit(0);
- }
- if (tabbed == kTrue) {
- params->window_count = argc - remote_args - 1;
- params->window_layout = WIN_TABS;
- }
+ if (should_exit == kTrue) {
+ os_exit(0);
+ }
+ if (tabbed == kTrue) {
+ params->window_count = argc - remote_args - 1;
+ params->window_layout = WIN_TABS;
+ }
}
+
/// Decides whether text (as opposed to commands) will be read from stdin.
/// @see EDIT_STDIN
static bool edit_stdin(bool explicit, mparm_T *parmp)
diff --git a/src/nvim/map.c b/src/nvim/map.c
index 4e39eb8c07..b3f48ad5d6 100644
--- a/src/nvim/map.c
+++ b/src/nvim/map.c
@@ -179,6 +179,7 @@ MAP_IMPL(HlEntry, int, DEFAULT_INITIALIZER)
MAP_IMPL(String, handle_T, 0)
MAP_IMPL(String, int, DEFAULT_INITIALIZER)
MAP_IMPL(int, String, DEFAULT_INITIALIZER)
+MAP_IMPL(String, UIClientHandler, NULL)
MAP_IMPL(ColorKey, ColorItem, COLOR_ITEM_INITIALIZER)
diff --git a/src/nvim/map.h b/src/nvim/map.h
index 00f72386a7..693ef50127 100644
--- a/src/nvim/map.h
+++ b/src/nvim/map.h
@@ -8,6 +8,7 @@
#include "nvim/extmark_defs.h"
#include "nvim/highlight_defs.h"
#include "nvim/map_defs.h"
+#include "nvim/ui_client.h"
#if defined(__NetBSD__)
# undef uint64_t
@@ -48,6 +49,7 @@ MAP_DECLS(HlEntry, int)
MAP_DECLS(String, handle_T)
MAP_DECLS(String, int)
MAP_DECLS(int, String)
+MAP_DECLS(String, UIClientHandler)
MAP_DECLS(ColorKey, ColorItem)
diff --git a/src/nvim/memory.c b/src/nvim/memory.c
index d68ca6b62e..6cdc4f1fde 100644
--- a/src/nvim/memory.c
+++ b/src/nvim/memory.c
@@ -13,6 +13,7 @@
#include "nvim/decoration_provider.h"
#include "nvim/eval.h"
#include "nvim/highlight.h"
+#include "nvim/highlight_group.h"
#include "nvim/lua/executor.h"
#include "nvim/memfile.h"
#include "nvim/memory.h"
diff --git a/src/nvim/message.c b/src/nvim/message.c
index b39450cdc6..b3fefbc0f4 100644
--- a/src/nvim/message.c
+++ b/src/nvim/message.c
@@ -206,11 +206,10 @@ void msg_grid_validate(void)
}
}
-/*
- * msg(s) - displays the string 's' on the status line
- * When terminal not initialized (yet) mch_errmsg(..) is used.
- * return TRUE if wait_return not called
- */
+/// Displays the string 's' on the status line
+/// When terminal not initialized (yet) mch_errmsg(..) is used.
+///
+/// @return TRUE if wait_return not called
int msg(char *s)
{
return msg_attr_keep(s, 0, false, false);
@@ -232,7 +231,7 @@ int msg_attr(const char *s, const int attr)
return msg_attr_keep(s, attr, false, false);
}
-/// similar to msg_outtrans_attr, but support newlines and tabs.
+/// Similar to msg_outtrans_attr, but support newlines and tabs.
void msg_multiline_attr(const char *s, int attr, bool check_int, bool *need_clear)
FUNC_ATTR_NONNULL_ALL
{
@@ -339,7 +338,8 @@ bool msg_attr_keep(const char *s, int attr, bool keep, bool multiline)
}
/// Truncate a string such that it can be printed without causing a scroll.
-/// Returns an allocated string or NULL when no truncating is done.
+///
+/// @return an allocated string or NULL when no truncating is done.
///
/// @param force always truncate
char_u *msg_strtrunc(char_u *s, int force)
@@ -371,10 +371,8 @@ char_u *msg_strtrunc(char_u *s, int force)
return buf;
}
-/*
- * Truncate a string "s" to "buf" with cell width "room".
- * "s" and "buf" may be equal.
- */
+/// Truncate a string "s" to "buf" with cell width "room".
+/// "s" and "buf" may be equal.
void trunc_string(char_u *s, char_u *buf, int room_in, int buflen)
{
size_t room = room_in - 3; // "..." takes 3 chars
@@ -498,19 +496,15 @@ int smsg_attr_keep(int attr, const char *s, ...)
static int last_sourcing_lnum = 0;
static char_u *last_sourcing_name = NULL;
-/*
- * Reset the last used sourcing name/lnum. Makes sure it is displayed again
- * for the next error message;
- */
+/// Reset the last used sourcing name/lnum. Makes sure it is displayed again
+/// for the next error message;
void reset_last_sourcing(void)
{
XFREE_CLEAR(last_sourcing_name);
last_sourcing_lnum = 0;
}
-/*
- * Return TRUE if "sourcing_name" differs from "last_sourcing_name".
- */
+/// @return TRUE if "sourcing_name" differs from "last_sourcing_name".
static int other_sourcing_name(void)
{
if (sourcing_name != NULL) {
@@ -560,11 +554,9 @@ static char *get_emsg_lnum(void)
return NULL;
}
-/*
- * Display name and line number for the source of an error.
- * Remember the file name and line number, so that for the next error the info
- * is only displayed if it changed.
- */
+/// Display name and line number for the source of an error.
+/// Remember the file name and line number, so that for the next error the info
+/// is only displayed if it changed.
void msg_source(int attr)
{
no_wait_return++;
@@ -592,12 +584,10 @@ void msg_source(int attr)
--no_wait_return;
}
-/*
- * Return TRUE if not giving error messages right now:
- * If "emsg_off" is set: no error messages at the moment.
- * If "msg" is in 'debug': do error message but without side effects.
- * If "emsg_skip" is set: never do error messages.
- */
+/// @return TRUE if not giving error messages right now:
+/// If "emsg_off" is set: no error messages at the moment.
+/// If "msg" is in 'debug': do error message but without side effects.
+/// If "emsg_skip" is set: never do error messages.
int emsg_not_now(void)
{
if ((emsg_off > 0 && vim_strchr(p_debug, 'm') == NULL
@@ -840,10 +830,11 @@ void msg_schedule_semsg(const char *const fmt, ...)
multiqueue_put(main_loop.events, msg_semsg_event, 1, s);
}
-// Like msg(), but truncate to a single line if p_shm contains 't', or when
-// "force" is true. This truncates in another way as for normal messages.
-// Careful: The string may be changed by msg_may_trunc()!
-// Returns a pointer to the printed message, if wait_return() not called.
+/// Like msg(), but truncate to a single line if p_shm contains 't', or when
+/// "force" is true. This truncates in another way as for normal messages.
+/// Careful: The string may be changed by msg_may_trunc()!
+///
+/// @return a pointer to the printed message, if wait_return() not called.
char *msg_trunc_attr(char *s, bool force, int attr)
{
int n;
@@ -863,11 +854,11 @@ char *msg_trunc_attr(char *s, bool force, int attr)
return NULL;
}
-/*
- * Check if message "s" should be truncated at the start (for filenames).
- * Return a pointer to where the truncated message starts.
- * Note: May change the message by replacing a character with '<'.
- */
+/// Check if message "s" should be truncated at the start (for filenames).
+///
+/// @return a pointer to where the truncated message starts.
+///
+/// @note: May change the message by replacing a character with '<'.
char_u *msg_may_trunc(bool force, char_u *s)
{
int room;
@@ -967,10 +958,9 @@ static void add_msg_hist(const char *s, int len, int attr, bool multiline)
msg_hist_len++;
}
-/*
- * Delete the first (oldest) message from the history.
- * Returns FAIL if there are no messages.
- */
+/// Delete the first (oldest) message from the history.
+///
+/// @return FAIL if there are no messages.
int delete_first_msg(void)
{
struct msg_hist *p;
@@ -1056,10 +1046,8 @@ void ex_messages(void *const eap_p)
}
}
-/*
- * Call this after prompting the user. This will avoid a hit-return message
- * and a delay.
- */
+/// Call this after prompting the user. This will avoid a hit-return message
+/// and a delay.
void msg_end_prompt(void)
{
msg_ext_clear_later();
@@ -1073,9 +1061,9 @@ void msg_end_prompt(void)
/// Wait for the user to hit a key (normally Enter)
///
-/// If 'redraw' is true, redraw the entire screen NOT_VALID
-/// If 'redraw' is false, do a normal redraw
-/// If 'redraw' is -1, don't redraw at all
+/// @param redraw if true, redraw the entire screen NOT_VALID
+/// if false, do a normal redraw
+/// if -1, don't redraw at all
void wait_return(int redraw)
{
int c;
@@ -1265,9 +1253,7 @@ void wait_return(int redraw)
}
}
-/*
- * Write the hit-return prompt.
- */
+/// Write the hit-return prompt.
static void hit_return_msg(void)
{
int save_p_more = p_more;
@@ -1288,9 +1274,7 @@ static void hit_return_msg(void)
p_more = save_p_more;
}
-/*
- * Set "keep_msg" to "s". Free the old value and check for NULL pointer.
- */
+/// Set "keep_msg" to "s". Free the old value and check for NULL pointer.
void set_keep_msg(char *s, int attr)
{
xfree(keep_msg);
@@ -1357,9 +1341,7 @@ void msg_ext_set_kind(const char *msg_kind)
msg_ext_kind = msg_kind;
}
-/*
- * Prepare for outputting characters in the command line.
- */
+/// Prepare for outputting characters in the command line.
void msg_start(void)
{
int did_return = false;
@@ -1406,9 +1388,7 @@ void msg_start(void)
}
}
-/*
- * Note that the current msg position is where messages start.
- */
+/// Note that the current msg position is where messages start.
void msg_starthere(void)
{
lines_left = cmdline_row;
@@ -1462,12 +1442,11 @@ static void msg_home_replace_attr(char_u *fname, int attr)
xfree(name);
}
-/*
- * Output 'len' characters in 'str' (including NULs) with translation
- * if 'len' is -1, output up to a NUL character.
- * Use attributes 'attr'.
- * Return the number of characters it takes on the screen.
- */
+/// Output 'len' characters in 'str' (including NULs) with translation
+/// if 'len' is -1, output up to a NUL character.
+/// Use attributes 'attr'.
+///
+/// @return the number of characters it takes on the screen.
int msg_outtrans(char_u *str)
{
return msg_outtrans_attr(str, 0);
@@ -1483,10 +1462,10 @@ int msg_outtrans_len(const char_u *str, int len)
return msg_outtrans_len_attr(str, len, 0);
}
-/*
- * Output one character at "p". Return pointer to the next character.
- * Handles multi-byte characters.
- */
+/// Output one character at "p".
+/// Handles multi-byte characters.
+///
+/// @return pointer to the next character.
char_u *msg_outtrans_one(char_u *p, int attr)
{
int l;
@@ -1752,9 +1731,7 @@ void str2specialbuf(const char *sp, char *buf, size_t len)
*buf = NUL;
}
-/*
- * print line for :print or :list command
- */
+/// print line for :print or :list command
void msg_prt_line(char_u *s, int list)
{
int c;
@@ -1903,8 +1880,9 @@ void msg_prt_line(char_u *s, int list)
msg_clr_eos();
}
-// Use grid_puts() to output one multi-byte character.
-// Return the pointer "s" advanced to the next character.
+/// Use grid_puts() to output one multi-byte character.
+///
+/// @return the pointer "s" advanced to the next character.
static char_u *screen_puts_mbyte(char_u *s, int l, int attr)
{
int cw;
@@ -1936,10 +1914,8 @@ static char_u *screen_puts_mbyte(char_u *s, int l, int attr)
return s + l;
}
-/*
- * Output a string to the screen at position msg_row, msg_col.
- * Update msg_row and msg_col for the next message.
- */
+/// Output a string to the screen at position msg_row, msg_col.
+/// Update msg_row and msg_col for the next message.
void msg_puts(const char *s)
{
msg_puts_attr(s, 0);
@@ -1950,11 +1926,9 @@ void msg_puts_title(const char *s)
msg_puts_attr(s, HL_ATTR(HLF_T));
}
-/*
- * Show a message in such a way that it always fits in the line. Cut out a
- * part in the middle and replace it with "..." when necessary.
- * Does not handle multi-byte characters!
- */
+/// Show a message in such a way that it always fits in the line. Cut out a
+/// part in the middle and replace it with "..." when necessary.
+/// Does not handle multi-byte characters!
void msg_outtrans_long_attr(char_u *longstr, int attr)
{
msg_outtrans_long_len_attr(longstr, (int)STRLEN(longstr), attr);
@@ -1974,9 +1948,7 @@ void msg_outtrans_long_len_attr(char_u *longstr, int len, int attr)
msg_outtrans_len_attr(longstr + len - slen, slen, attr);
}
-/*
- * Basic function for writing a message with highlight attributes.
- */
+/// Basic function for writing a message with highlight attributes.
void msg_puts_attr(const char *const s, const int attr)
{
msg_puts_attr_len(s, -1, attr);
@@ -2078,10 +2050,8 @@ static void msg_ext_emit_chunk(void)
ADD(msg_ext_chunks, ARRAY_OBJ(chunk));
}
-/*
- * The display part of msg_puts_attr_len().
- * May be called recursively to display scroll-back text.
- */
+/// The display part of msg_puts_attr_len().
+/// May be called recursively to display scroll-back text.
static void msg_puts_display(const char_u *str, int maxlen, int attr, int recurse)
{
const char_u *s = str;
@@ -2286,8 +2256,8 @@ static void msg_puts_display(const char_u *str, int maxlen, int attr, int recurs
msg_check();
}
-/// Return true when ":filter pattern" was used and "msg" does not match
-/// "pattern".
+/// @return true when ":filter pattern" was used and "msg" does not match
+/// "pattern".
bool message_filtered(char_u *msg)
{
if (cmdmod.filter_regmatch.regprog == NULL) {
@@ -2419,9 +2389,7 @@ void msg_reset_scroll(void)
msg_scrolled_at_flush = 0;
}
-/*
- * Increment "msg_scrolled".
- */
+/// Increment "msg_scrolled".
static void inc_msg_scrolled(void)
{
if (*get_vim_var_str(VV_SCROLLSTART) == NUL) {
@@ -2500,9 +2468,7 @@ static void store_sb_text(char_u **sb_str, char_u *s, int attr, int *sb_col, int
*sb_col = 0;
}
-/*
- * Finished showing messages, clear the scroll-back text on the next message.
- */
+/// Finished showing messages, clear the scroll-back text on the next message.
void may_clear_sb_text(void)
{
do_clear_sb_text = SB_CLEAR_ALL;
@@ -2545,9 +2511,7 @@ void clear_sb_text(int all)
}
}
-/*
- * "g<" command.
- */
+/// "g<" command.
void show_sb_text(void)
{
msgchunk_T *mp;
@@ -2563,9 +2527,7 @@ void show_sb_text(void)
}
}
-/*
- * Move to the start of screen line in already displayed text.
- */
+/// Move to the start of screen line in already displayed text.
static msgchunk_T *msg_sb_start(msgchunk_T *mps)
{
msgchunk_T *mp = mps;
@@ -2576,9 +2538,7 @@ static msgchunk_T *msg_sb_start(msgchunk_T *mps)
return mp;
}
-/*
- * Mark the last message chunk as finishing the line.
- */
+/// Mark the last message chunk as finishing the line.
void msg_sb_eol(void)
{
if (last_msgchunk != NULL) {
@@ -2586,10 +2546,9 @@ void msg_sb_eol(void)
}
}
-/*
- * Display a screen line from previously displayed text at row "row".
- * Returns a pointer to the text for the next line (can be NULL).
- */
+/// Display a screen line from previously displayed text at row "row".
+///
+/// @return a pointer to the text for the next line (can be NULL).
static msgchunk_T *disp_sb_line(int row, msgchunk_T *smp)
{
msgchunk_T *mp = smp;
@@ -2612,9 +2571,7 @@ static msgchunk_T *disp_sb_line(int row, msgchunk_T *smp)
return mp->sb_next;
}
-/*
- * Output any postponed text for msg_puts_attr_len().
- */
+/// Output any postponed text for msg_puts_attr_len().
static void t_puts(int *t_col, const char_u *t_s, const char_u *s, int attr)
{
attr = hl_combine_attr(HL_ATTR(HLF_MSG), attr);
@@ -2635,9 +2592,9 @@ static void t_puts(int *t_col, const char_u *t_s, const char_u *s, int attr)
}
}
-// Returns TRUE when messages should be printed to stdout/stderr:
-// - "batch mode" ("silent mode", -es/-Es)
-// - no UI and not embedded
+/// @return TRUE when messages should be printed to stdout/stderr:
+/// - "batch mode" ("silent mode", -es/-Es)
+/// - no UI and not embedded
int msg_use_printf(void)
{
return !embedded_mode && !ui_active();
@@ -2698,13 +2655,12 @@ static void msg_puts_printf(const char *str, const ptrdiff_t maxlen)
msg_didout = true; // assume that line is not empty
}
-/*
- * Show the more-prompt and handle the user response.
- * This takes care of scrolling back and displaying previously displayed text.
- * When at hit-enter prompt "typed_char" is the already typed character,
- * otherwise it's NUL.
- * Returns TRUE when jumping ahead to "confirm_msg_tail".
- */
+/// Show the more-prompt and handle the user response.
+/// This takes care of scrolling back and displaying previously displayed text.
+/// When at hit-enter prompt "typed_char" is the already typed character,
+/// otherwise it's NUL.
+///
+/// @return TRUE when jumping ahead to "confirm_msg_tail".
static int do_more_prompt(int typed_char)
{
static bool entered = false;
@@ -2962,7 +2918,7 @@ void mch_errmsg(char *str)
}
}
-// Give a message. To be used when the UI is not initialized yet.
+/// Give a message. To be used when the UI is not initialized yet.
void mch_msg(char *str)
{
assert(str != NULL);
@@ -2977,10 +2933,8 @@ void mch_msg(char *str)
}
#endif // WIN32
-/*
- * Put a character on the screen at the current message position and advance
- * to the next position. Only for printable ASCII!
- */
+/// Put a character on the screen at the current message position and advance
+/// to the next position. Only for printable ASCII!
static void msg_screen_putchar(int c, int attr)
{
attr = hl_combine_attr(HL_ATTR(HLF_MSG), attr);
@@ -3013,10 +2967,8 @@ void msg_moremsg(int full)
}
}
-/*
- * Repeat the message for the current mode: ASKMORE, EXTERNCMD, CONFIRM or
- * exmode_active.
- */
+/// Repeat the message for the current mode: ASKMORE, EXTERNCMD, CONFIRM or
+/// exmode_active.
void repeat_message(void)
{
if (State == ASKMORE) {
@@ -3041,10 +2993,8 @@ void repeat_message(void)
}
}
-/*
- * Clear from current message position to end of screen.
- * Skip this when ":silent" was used, no need to clear for redirection.
- */
+/// Clear from current message position to end of screen.
+/// Skip this when ":silent" was used, no need to clear for redirection.
void msg_clr_eos(void)
{
if (msg_silent == 0) {
@@ -3052,11 +3002,9 @@ void msg_clr_eos(void)
}
}
-/*
- * Clear from current message position to end of screen.
- * Note: msg_col is not updated, so we remember the end of the message
- * for msg_check().
- */
+/// Clear from current message position to end of screen.
+/// Note: msg_col is not updated, so we remember the end of the message
+/// for msg_check().
void msg_clr_eos_force(void)
{
if (ui_has(kUIMessages)) {
@@ -3083,9 +3031,7 @@ void msg_clr_eos_force(void)
}
}
-/*
- * Clear the command line.
- */
+/// Clear the command line.
void msg_clr_cmdline(void)
{
msg_row = cmdline_row;
@@ -3093,11 +3039,10 @@ void msg_clr_cmdline(void)
msg_clr_eos_force();
}
-/*
- * end putting a message on the screen
- * call wait_return if the message does not fit in the available space
- * return TRUE if wait_return not called.
- */
+/// end putting a message on the screen
+/// call wait_return if the message does not fit in the available space
+///
+/// @return TRUE if wait_return not called.
int msg_end(void)
{
/*
@@ -3187,10 +3132,8 @@ bool msg_ext_is_visible(void)
return ui_has(kUIMessages) && msg_ext_visible > 0;
}
-/*
- * If the written message runs into the shown command or ruler, we have to
- * wait for hit-return and redraw the window later.
- */
+/// If the written message runs into the shown command or ruler, we have to
+/// wait for hit-return and redraw the window later.
void msg_check(void)
{
if (ui_has(kUIMessages)) {
@@ -3202,10 +3145,9 @@ void msg_check(void)
}
}
-/*
- * May write a string to the redirection file.
- * When "maxlen" is -1 write the whole string, otherwise up to "maxlen" bytes.
- */
+/// May write a string to the redirection file.
+///
+/// @param maxlen if -1, write the whole string, otherwise up to "maxlen" bytes.
static void redir_write(const char *const str, const ptrdiff_t maxlen)
{
const char_u *s = (char_u *)str;
@@ -3290,10 +3232,8 @@ int redirecting(void)
|| redir_reg || redir_vname || capture_ga != NULL;
}
-/*
- * Before giving verbose message.
- * Must always be called paired with verbose_leave()!
- */
+/// Before giving verbose message.
+/// Must always be called paired with verbose_leave()!
void verbose_enter(void)
{
if (*p_vfile != NUL) {
@@ -3301,10 +3241,8 @@ void verbose_enter(void)
}
}
-/*
- * After giving verbose message.
- * Must always be called paired with verbose_enter()!
- */
+/// After giving verbose message.
+/// Must always be called paired with verbose_enter()!
void verbose_leave(void)
{
if (*p_vfile != NUL) {
@@ -3314,9 +3252,7 @@ void verbose_leave(void)
}
}
-/*
- * Like verbose_enter() and set msg_scroll when displaying the message.
- */
+/// Like verbose_enter() and set msg_scroll when displaying the message.
void verbose_enter_scroll(void)
{
if (*p_vfile != NUL) {
@@ -3327,9 +3263,7 @@ void verbose_enter_scroll(void)
}
}
-/*
- * Like verbose_leave() and set cmdline_row when displaying the message.
- */
+/// Like verbose_leave() and set cmdline_row when displaying the message.
void verbose_leave_scroll(void)
{
if (*p_vfile != NUL) {
@@ -3341,9 +3275,7 @@ void verbose_leave_scroll(void)
}
}
-/*
- * Called when 'verbosefile' is set: stop writing to the file.
- */
+/// Called when 'verbosefile' is set: stop writing to the file.
void verbose_stop(void)
{
if (verbose_fd != NULL) {
@@ -3353,10 +3285,9 @@ void verbose_stop(void)
verbose_did_open = FALSE;
}
-/*
- * Open the file 'verbosefile'.
- * Return FAIL or OK.
- */
+/// Open the file 'verbosefile'.
+///
+/// @return FAIL or OK.
int verbose_open(void)
{
if (verbose_fd == NULL && !verbose_did_open) {
@@ -3372,10 +3303,8 @@ int verbose_open(void)
return OK;
}
-/*
- * Give a warning message (for searching).
- * Use 'w' highlighting and may repeat the message after redrawing
- */
+/// Give a warning message (for searching).
+/// Use 'w' highlighting and may repeat the message after redrawing
void give_warning(char_u *message, bool hl) FUNC_ATTR_NONNULL_ARG(1)
{
// Don't do this for ":silent".
@@ -3414,9 +3343,7 @@ void give_warning2(char_u *const message, char_u *const a1, bool hl)
give_warning(IObuff, hl);
}
-/*
- * Advance msg cursor to column "col".
- */
+/// Advance msg cursor to column "col".
void msg_advance(int col)
{
if (msg_silent != 0) { // nothing to advance to
@@ -3626,15 +3553,13 @@ static char_u *console_dialog_alloc(const char_u *message, char_u *buttons, bool
return xmalloc(lenhotkey);
}
-/*
- * Format the dialog string, and display it at the bottom of
- * the screen. Return a string of hotkey chars (if defined) for
- * each 'button'. If a button has no hotkey defined, the first character of
- * the button is used.
- * The hotkeys can be multi-byte characters, but without combining chars.
- *
- * Returns an allocated string with hotkeys.
- */
+/// Format the dialog string, and display it at the bottom of
+/// the screen. Return a string of hotkey chars (if defined) for
+/// each 'button'. If a button has no hotkey defined, the first character of
+/// the button is used.
+/// The hotkeys can be multi-byte characters, but without combining chars.
+///
+/// @return an allocated string with hotkeys.
static char_u *msg_show_console_dialog(char_u *message, char_u *buttons, int dfltbutton)
FUNC_ATTR_NONNULL_RET
{
@@ -3727,9 +3652,7 @@ static void copy_hotkeys_and_msg(const char_u *message, char_u *buttons, int def
*msgp = NUL;
}
-/*
- * Display the ":confirm" message. Also called when screen resized.
- */
+/// Display the ":confirm" message. Also called when screen resized.
void display_confirm_msg(void)
{
// Avoid that 'q' at the more prompt truncates the message here.
diff --git a/src/nvim/mouse.c b/src/nvim/mouse.c
index 5d007fb173..6b27ce9d7b 100644
--- a/src/nvim/mouse.c
+++ b/src/nvim/mouse.c
@@ -535,6 +535,22 @@ static win_T *mouse_find_grid_win(int *gridp, int *rowp, int *colp)
return NULL;
}
+/// Convert a virtual (screen) column to a character column.
+/// The first column is one.
+colnr_T vcol2col(win_T *const wp, const linenr_T lnum, const colnr_T vcol)
+ FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT
+{
+ // try to advance to the specified column
+ char_u *ptr = ml_get_buf(wp->w_buffer, lnum, false);
+ char_u *const line = ptr;
+ colnr_T count = 0;
+ while (count < vcol && *ptr != NUL) {
+ count += win_lbr_chartabsize(wp, line, ptr, count, NULL);
+ MB_PTR_ADV(ptr);
+ }
+ return (colnr_T)(ptr - line);
+}
+
/// Set UI mouse depending on current mode and 'mouse'.
///
/// Emits mouse_on/mouse_off UI event (unless 'mouse' is empty).
diff --git a/src/nvim/msgpack_rpc/channel.c b/src/nvim/msgpack_rpc/channel.c
index 299651ee97..48ecd5d0ea 100644
--- a/src/nvim/msgpack_rpc/channel.c
+++ b/src/nvim/msgpack_rpc/channel.c
@@ -547,7 +547,8 @@ void rpc_close(Channel *channel)
channel->rpc.closed = true;
channel_decref(channel);
- if (channel->streamtype == kChannelStreamStdio) {
+ if (channel->streamtype == kChannelStreamStdio
+ || channel->id == ui_client_channel_id) {
multiqueue_put(main_loop.fast_events, exit_event, 0);
}
}
diff --git a/src/nvim/normal.c b/src/nvim/normal.c
index 0e5e0ab403..f402865d2d 100644
--- a/src/nvim/normal.c
+++ b/src/nvim/normal.c
@@ -5869,7 +5869,7 @@ static void nv_gomark(cmdarg_T *cap)
}
}
-// Handle CTRL-O, CTRL-I, "g;", "g,", and "CTRL-Tab" commands.
+/// Handle CTRL-O, CTRL-I, "g;", "g,", and "CTRL-Tab" commands.
static void nv_pcmark(cmdarg_T *cap)
{
pos_T *pos;
@@ -5878,7 +5878,9 @@ static void nv_pcmark(cmdarg_T *cap)
if (!checkclearopq(cap->oap)) {
if (cap->cmdchar == TAB && mod_mask == MOD_MASK_CTRL) {
- goto_tabpage_lastused();
+ if (!goto_tabpage_lastused()) {
+ clearopbeep(cap->oap);
+ }
return;
}
if (cap->cmdchar == 'g') {
@@ -6642,9 +6644,10 @@ static void nv_g_cmd(cmdarg_T *cap)
goto_tabpage(-(int)cap->count1);
}
break;
+
case TAB:
- if (!checkclearop(oap)) {
- goto_tabpage_lastused();
+ if (!checkclearop(oap) && !goto_tabpage_lastused()) {
+ clearopbeep(oap);
}
break;
diff --git a/src/nvim/option.c b/src/nvim/option.c
index 191b635dc0..ffd009be89 100644
--- a/src/nvim/option.c
+++ b/src/nvim/option.c
@@ -47,6 +47,7 @@
#include "nvim/getchar.h"
#include "nvim/hardcopy.h"
#include "nvim/highlight.h"
+#include "nvim/highlight_group.h"
#include "nvim/indent_c.h"
#include "nvim/keymap.h"
#include "nvim/macros.h"
@@ -2910,7 +2911,7 @@ ambw_end:
|| check_opt_strings(curbuf->b_p_bt, p_buftype_values, false) != OK) {
errmsg = e_invarg;
} else {
- if (curwin->w_status_height) {
+ if (curwin->w_status_height || global_stl_height()) {
curwin->w_redr_status = true;
redraw_later(curwin, VALID);
}
@@ -3553,16 +3554,22 @@ static char *set_chars_option(win_T *wp, char_u **varp, bool set)
struct chars_tab *tab;
struct chars_tab fcs_tab[] = {
- { &wp->w_p_fcs_chars.stl, "stl", ' ' },
- { &wp->w_p_fcs_chars.stlnc, "stlnc", ' ' },
- { &wp->w_p_fcs_chars.vert, "vert", 9474 }, // │
- { &wp->w_p_fcs_chars.fold, "fold", 183 }, // ·
- { &wp->w_p_fcs_chars.foldopen, "foldopen", '-' },
- { &wp->w_p_fcs_chars.foldclosed, "foldclose", '+' },
- { &wp->w_p_fcs_chars.foldsep, "foldsep", 9474 }, // │
- { &wp->w_p_fcs_chars.diff, "diff", '-' },
- { &wp->w_p_fcs_chars.msgsep, "msgsep", ' ' },
- { &wp->w_p_fcs_chars.eob, "eob", '~' },
+ { &wp->w_p_fcs_chars.stl, "stl", ' ' },
+ { &wp->w_p_fcs_chars.stlnc, "stlnc", ' ' },
+ { &wp->w_p_fcs_chars.horiz, "horiz", 9472 }, // ─
+ { &wp->w_p_fcs_chars.horizup, "horizup", 9524 }, // ┴
+ { &wp->w_p_fcs_chars.horizdown, "horizdown", 9516 }, // ┬
+ { &wp->w_p_fcs_chars.vert, "vert", 9474 }, // │
+ { &wp->w_p_fcs_chars.vertleft, "vertleft", 9508 }, // ┤
+ { &wp->w_p_fcs_chars.vertright, "vertright", 9500 }, // ├
+ { &wp->w_p_fcs_chars.verthoriz, "verthoriz", 9532 }, // ┼
+ { &wp->w_p_fcs_chars.fold, "fold", 183 }, // ·
+ { &wp->w_p_fcs_chars.foldopen, "foldopen", '-' },
+ { &wp->w_p_fcs_chars.foldclosed, "foldclose", '+' },
+ { &wp->w_p_fcs_chars.foldsep, "foldsep", 9474 }, // │
+ { &wp->w_p_fcs_chars.diff, "diff", '-' },
+ { &wp->w_p_fcs_chars.msgsep, "msgsep", ' ' },
+ { &wp->w_p_fcs_chars.eob, "eob", '~' },
};
struct chars_tab lcs_tab[] = {
{ &wp->w_p_lcs_chars.eol, "eol", NUL },
@@ -3589,15 +3596,17 @@ static char *set_chars_option(win_T *wp, char_u **varp, bool set)
varp = &p_fcs;
}
if (*p_ambw == 'd') {
- // XXX: If ambiwidth=double then "|" and "·" take 2 columns, which is
- // forbidden (TUI limitation?). Set old defaults.
- fcs_tab[2].def = '|';
- fcs_tab[6].def = '|';
- fcs_tab[3].def = '-';
- } else {
- fcs_tab[2].def = 9474; // │
- fcs_tab[6].def = 9474; // │
- fcs_tab[3].def = 183; // ·
+ // XXX: If ambiwidth=double then some characters take 2 columns,
+ // which is forbidden (TUI limitation?). Set old defaults.
+ fcs_tab[2].def = '-';
+ fcs_tab[3].def = '-';
+ fcs_tab[4].def = '-';
+ fcs_tab[5].def = '|';
+ fcs_tab[6].def = '|';
+ fcs_tab[7].def = '|';
+ fcs_tab[8].def = '+';
+ fcs_tab[9].def = '-';
+ fcs_tab[12].def = '|';
}
}
@@ -3845,7 +3854,7 @@ static bool parse_winhl_opt(win_T *wp)
size_t nlen = (size_t)(colon-p);
char *hi = colon+1;
char *commap = xstrchrnul(hi, ',');
- int len = (int)(commap-hi);
+ size_t len = (size_t)(commap-hi);
int hl_id = len ? syn_check_group(hi, len) : -1;
if (strncmp("Normal", p, nlen) == 0) {
@@ -4475,6 +4484,20 @@ static char *set_num_option(int opt_idx, char_u *varp, long value, char *errbuf,
// 'winminwidth'
win_setminwidth();
} else if (pp == &p_ls) {
+ // When switching to global statusline, decrease topframe height
+ // Also clear the cmdline to remove the ruler if there is one
+ if (value == 3 && old_value != 3) {
+ frame_new_height(topframe, topframe->fr_height - STATUS_HEIGHT, false, false);
+ (void)win_comp_pos();
+ clear_cmdline = true;
+ }
+ // When switching from global statusline, increase height of topframe by STATUS_HEIGHT
+ // in order to to re-add the space that was previously taken by the global statusline
+ if (old_value == 3 && value != 3) {
+ frame_new_height(topframe, topframe->fr_height + STATUS_HEIGHT, false, false);
+ (void)win_comp_pos();
+ }
+
last_status(false); // (re)set last window status line.
} else if (pp == &p_stal) {
// (re)set tab page line
@@ -5646,7 +5669,7 @@ static int put_setbool(FILE *fd, char *cmd, char *name, int value)
void comp_col(void)
{
- int last_has_status = (p_ls == 2 || (p_ls == 1 && !ONE_WINDOW));
+ int last_has_status = (p_ls > 1 || (p_ls == 1 && !ONE_WINDOW));
sc_col = 0;
ru_col = 0;
diff --git a/src/nvim/os/env.c b/src/nvim/os/env.c
index e9868d6b61..b738d36234 100644
--- a/src/nvim/os/env.c
+++ b/src/nvim/os/env.c
@@ -720,7 +720,7 @@ void expand_env_esc(char_u *restrict srcp, char_u *restrict dst, int dstlen, boo
&& dst[-1] != ':'
#endif
&& vim_ispathsep(*tail)) {
- ++tail;
+ tail++;
}
dst += c;
src = tail;
@@ -738,7 +738,7 @@ void expand_env_esc(char_u *restrict srcp, char_u *restrict dst, int dstlen, boo
at_start = false;
if (src[0] == '\\' && src[1] != NUL) {
*dst++ = *src++;
- --dstlen;
+ dstlen--;
} else if ((src[0] == ' ' || src[0] == ',') && !one) {
at_start = true;
}
diff --git a/src/nvim/os/pty_process_unix.c b/src/nvim/os/pty_process_unix.c
index 58cb1b8f84..4a49c0b162 100644
--- a/src/nvim/os/pty_process_unix.c
+++ b/src/nvim/os/pty_process_unix.c
@@ -86,7 +86,7 @@ static int openpty(int *amaster, int *aslave, char *name, struct termios *termp,
ioctl(slave, I_PUSH, "ptem");
// ldterm provides most of the termio terminal interface
ioctl(slave, I_PUSH, "ldterm");
- // ttcompat compatability with older terminal ioctls
+ // ttcompat compatibility with older terminal ioctls
ioctl(slave, I_PUSH, "ttcompat");
if (termp) {
diff --git a/src/nvim/os/pty_process_win.c b/src/nvim/os/pty_process_win.c
index 99231968a2..4fb9e30a96 100644
--- a/src/nvim/os/pty_process_win.c
+++ b/src/nvim/os/pty_process_win.c
@@ -58,8 +58,7 @@ int pty_process_spawn(PtyProcess *ptyproc)
if (os_has_conpty_working()) {
if ((conpty_object =
- os_conpty_init(&in_name, &out_name,
- ptyproc->width, ptyproc->height)) != NULL) {
+ os_conpty_init(&in_name, &out_name, ptyproc->width, ptyproc->height)) != NULL) {
ptyproc->type = kConpty;
}
}
@@ -308,7 +307,7 @@ static void pty_process_finish2(PtyProcess *ptyproc)
/// Build the command line to pass to CreateProcessW.
///
/// @param[in] argv Array with string arguments.
-/// @param[out] cmd_line Location where saved builded cmd line.
+/// @param[out] cmd_line Location where saved built cmd line.
///
/// @returns zero on success, or error code of MultiByteToWideChar function.
///
diff --git a/src/nvim/os/shell.c b/src/nvim/os/shell.c
index 656e059303..5680cdbe42 100644
--- a/src/nvim/os/shell.c
+++ b/src/nvim/os/shell.c
@@ -1229,7 +1229,7 @@ static void read_input(DynamicBuffer *buf)
dynamic_buffer_ensure(buf, buf->len + 1);
buf->data[buf->len++] = NL;
}
- ++lnum;
+ lnum++;
if (lnum > curbuf->b_op_end.lnum) {
break;
}
diff --git a/src/nvim/quickfix.c b/src/nvim/quickfix.c
index bddbd04af9..d868fe8284 100644
--- a/src/nvim/quickfix.c
+++ b/src/nvim/quickfix.c
@@ -22,6 +22,7 @@
#include "nvim/ex_getln.h"
#include "nvim/fileio.h"
#include "nvim/fold.h"
+#include "nvim/highlight_group.h"
#include "nvim/mark.h"
#include "nvim/mbyte.h"
#include "nvim/memline.h"
@@ -39,7 +40,6 @@
#include "nvim/screen.h"
#include "nvim/search.h"
#include "nvim/strings.h"
-#include "nvim/syntax.h"
#include "nvim/ui.h"
#include "nvim/vim.h"
#include "nvim/window.h"
@@ -75,6 +75,7 @@ struct qfline_S {
// There is a stack of error lists.
#define LISTCOUNT 10
#define INVALID_QFIDX (-1)
+#define INVALID_QFBUFNR (0)
/// Quickfix list type.
typedef enum
@@ -126,6 +127,7 @@ struct qf_info_S {
int qf_curlist; // current error list
qf_list_T qf_lists[LISTCOUNT];
qfltype_T qfl_type; // type of list
+ int qf_bufnr; // quickfix window buffer number
};
static qf_info_T ql_info; // global quickfix list
@@ -1703,6 +1705,28 @@ static void locstack_queue_delreq(qf_info_T *qi)
qf_delq_head = q;
}
+/// Return the global quickfix stack window buffer number.
+int qf_stack_get_bufnr(void)
+{
+ return ql_info.qf_bufnr;
+}
+
+/// Wipe the quickfix window buffer (if present) for the specified
+/// quickfix/location list.
+static void wipe_qf_buffer(qf_info_T *qi)
+ FUNC_ATTR_NONNULL_ALL
+{
+ if (qi->qf_bufnr != INVALID_QFBUFNR) {
+ buf_T *const qfbuf = buflist_findnr(qi->qf_bufnr);
+ if (qfbuf != NULL && qfbuf->b_nwindows == 0) {
+ // If the quickfix buffer is not loaded in any window, then
+ // wipe the buffer.
+ close_buffer(NULL, qfbuf, DOBUF_WIPE, false);
+ qi->qf_bufnr = INVALID_QFBUFNR;
+ }
+ }
+}
+
/// Free a location list stack
static void ll_free_all(qf_info_T **pqi)
{
@@ -1715,19 +1739,23 @@ static void ll_free_all(qf_info_T **pqi)
}
*pqi = NULL; // Remove reference to this list
+ // If the location list is still in use, then queue the delete request
+ // to be processed later.
+ if (quickfix_busy > 0) {
+ locstack_queue_delreq(qi);
+ return;
+ }
+
qi->qf_refcount--;
if (qi->qf_refcount < 1) {
// No references to this location list.
- // If the location list is still in use, then queue the delete request
- // to be processed later.
- if (quickfix_busy > 0) {
- locstack_queue_delreq(qi);
- } else {
- for (i = 0; i < qi->qf_listcount; i++) {
- qf_free(qf_get_list(qi, i));
- }
- xfree(qi);
+ // If the quickfix window buffer is loaded, then wipe it
+ wipe_qf_buffer(qi);
+
+ for (i = 0; i < qi->qf_listcount; i++) {
+ qf_free(qf_get_list(qi, i));
}
+ xfree(qi);
}
}
@@ -1885,6 +1913,7 @@ static qf_info_T *qf_alloc_stack(qfltype_T qfltype)
qf_info_T *qi = xcalloc(1, sizeof(qf_info_T));
qi->qf_refcount++;
qi->qfl_type = qfltype;
+ qi->qf_bufnr = INVALID_QFBUFNR;
return qi;
}
@@ -2446,7 +2475,7 @@ static qfline_T *qf_get_entry(qf_list_T *qfl, int errornr, int dir, int *new_qfi
return qf_ptr;
}
-// Find a window displaying a Vim help file.
+// Find a window displaying a Vim help file in the current tab page.
static win_T *qf_find_help_win(void)
FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT
{
@@ -2520,8 +2549,9 @@ static int jump_to_help_window(qf_info_T *qi, bool newwin, int *opened_window)
return OK;
}
-// Find a non-quickfix window using the given location list.
-// Returns NULL if a matching window is not found.
+/// Find a non-quickfix window using the given location list stack in the
+/// current tabpage.
+/// Returns NULL if a matching window is not found.
static win_T *qf_find_win_with_loclist(const qf_info_T *ll)
FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT
{
@@ -2533,7 +2563,7 @@ static win_T *qf_find_win_with_loclist(const qf_info_T *ll)
return NULL;
}
-// Find a window containing a normal buffer
+/// Find a window containing a normal buffer in the current tab page.
static win_T *qf_find_win_with_normal_buf(void)
FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT
{
@@ -2589,7 +2619,7 @@ static void qf_goto_win_with_ll_file(win_T *use_win, int qf_fnum, qf_info_T *ll_
win_T *win = use_win;
if (win == NULL) {
- // Find the window showing the selected file
+ // Find the window showing the selected file in the current tab page.
FOR_ALL_WINDOWS_IN_TAB(win2, curtab) {
if (win2->w_buffer->b_fnum == qf_fnum) {
win = win2;
@@ -2721,7 +2751,7 @@ static int qf_jump_to_usable_window(int qf_fnum, bool newwin, int *opened_window
}
/// Edit the selected file or help file.
-static int qf_jump_edit_buffer(qf_info_T *qi, qfline_T *qf_ptr, int forceit, win_T *oldwin,
+static int qf_jump_edit_buffer(qf_info_T *qi, qfline_T *qf_ptr, int forceit, int prev_winid,
int *opened_window)
{
qf_list_T *qfl = qf_get_curlist(qi);
@@ -2740,7 +2770,7 @@ static int qf_jump_edit_buffer(qf_info_T *qi, qfline_T *qf_ptr, int forceit, win
} else {
retval = do_ecmd(qf_ptr->qf_fnum, NULL, NULL, NULL, (linenr_T)1,
ECMD_HIDE + ECMD_SET_HELP,
- oldwin == curwin ? curwin : NULL);
+ prev_winid == curwin->handle ? curwin : NULL);
}
} else {
retval = buflist_getfile(qf_ptr->qf_fnum, (linenr_T)1,
@@ -2748,10 +2778,13 @@ static int qf_jump_edit_buffer(qf_info_T *qi, qfline_T *qf_ptr, int forceit, win
}
// If a location list, check whether the associated window is still
// present.
- if (qfl_type == QFLT_LOCATION && !win_valid_any_tab(oldwin)) {
- emsg(_("E924: Current window was closed"));
- *opened_window = false;
- return NOTDONE;
+ if (qfl_type == QFLT_LOCATION) {
+ win_T *wp = win_id2wp(prev_winid);
+ if (wp == NULL && curwin->w_llist != qi) {
+ emsg(_("E924: Current window was closed"));
+ *opened_window = false;
+ return NOTDONE;
+ }
}
if (qfl_type == QFLT_QUICKFIX && !qflist_valid(NULL, save_qfid)) {
@@ -2906,7 +2939,7 @@ static int qf_jump_open_window(qf_info_T *qi, qfline_T *qf_ptr, bool newwin, int
/// NOTDONE if the quickfix/location list is freed by an autocmd when opening
/// the file.
static int qf_jump_to_buffer(qf_info_T *qi, int qf_index, qfline_T *qf_ptr, int forceit,
- win_T *oldwin, int *opened_window, int openfold, int print_message)
+ int prev_winid, int *opened_window, int openfold, int print_message)
{
buf_T *old_curbuf;
linenr_T old_lnum;
@@ -2918,7 +2951,7 @@ static int qf_jump_to_buffer(qf_info_T *qi, int qf_index, qfline_T *qf_ptr, int
old_lnum = curwin->w_cursor.lnum;
if (qf_ptr->qf_fnum != 0) {
- retval = qf_jump_edit_buffer(qi, qf_ptr, forceit, oldwin,
+ retval = qf_jump_edit_buffer(qi, qf_ptr, forceit, prev_winid,
opened_window);
if (retval != OK) {
return retval;
@@ -2967,8 +3000,8 @@ static void qf_jump_newwin(qf_info_T *qi, int dir, int errornr, int forceit, boo
int old_qf_index;
char_u *old_swb = p_swb;
unsigned old_swb_flags = swb_flags;
+ int prev_winid;
int opened_window = false;
- win_T *oldwin = curwin;
int print_message = true;
const bool old_KeyTyped = KeyTyped; // getting file may reset it
int retval = OK;
@@ -2982,6 +3015,8 @@ static void qf_jump_newwin(qf_info_T *qi, int dir, int errornr, int forceit, boo
return;
}
+ incr_quickfix_busy();
+
qfl = qf_get_curlist(qi);
qf_ptr = qfl->qf_ptr;
@@ -3004,6 +3039,8 @@ static void qf_jump_newwin(qf_info_T *qi, int dir, int errornr, int forceit, boo
print_message = false;
}
+ prev_winid = curwin->handle;
+
retval = qf_jump_open_window(qi, qf_ptr, newwin, &opened_window);
if (retval == FAIL) {
goto failed;
@@ -3012,7 +3049,7 @@ static void qf_jump_newwin(qf_info_T *qi, int dir, int errornr, int forceit, boo
goto theend;
}
- retval = qf_jump_to_buffer(qi, qf_index, qf_ptr, forceit, oldwin,
+ retval = qf_jump_to_buffer(qi, qf_index, qf_ptr, forceit, prev_winid,
&opened_window, old_KeyTyped, print_message);
if (retval == NOTDONE) {
// Quickfix/location list is freed by an autocmd
@@ -3037,12 +3074,13 @@ theend:
qfl->qf_ptr = qf_ptr;
qfl->qf_index = qf_index;
}
- if (p_swb != old_swb && p_swb == empty_option && opened_window) {
+ if (p_swb != old_swb && p_swb == empty_option) {
// Restore old 'switchbuf' value, but not when an autocommand or
// modeline has changed the value.
p_swb = old_swb;
swb_flags = old_swb_flags;
}
+ decr_quickfix_busy();
}
@@ -3597,7 +3635,7 @@ static int qf_goto_cwindow(const qf_info_T *qi, bool resize, int sz, bool vertsp
win_setwidth(sz);
}
} else if (sz != win->w_height
- && (win->w_height + win->w_status_height + tabline_height()
+ && (win->w_height + win->w_hsep_height + win->w_status_height + tabline_height()
< cmdline_row)) {
win_setheight(sz);
}
@@ -3612,7 +3650,7 @@ static void qf_set_cwindow_options(void)
// switch off 'swapfile'
set_option_value("swf", 0L, NULL, OPT_LOCAL);
set_option_value("bt", 0L, "quickfix", OPT_LOCAL);
- set_option_value("bh", 0L, "wipe", OPT_LOCAL);
+ set_option_value("bh", 0L, "hide", OPT_LOCAL);
RESET_BINDING(curwin);
curwin->w_p_diff = false;
set_option_value("fdm", 0L, "manual", OPT_LOCAL);
@@ -3646,22 +3684,13 @@ static int qf_open_new_cwindow(qf_info_T *qi, int height)
if (win_split(height, flags) == FAIL) {
return FAIL; // not enough room for window
}
-
- // User autocommands may have invalidated the previous window after calling
- // win_split, so add a check to ensure that the win is still here
- if (IS_LL_STACK(qi) && !win_valid(win)) {
- // close the window that was supposed to be for the loclist
- win_close(curwin, false, false);
- return FAIL;
- }
-
RESET_BINDING(curwin);
if (IS_LL_STACK(qi)) {
// For the location list window, create a reference to the
- // location list from the window 'win'.
- curwin->w_llist_ref = win->w_llist;
- win->w_llist->qf_refcount++;
+ // location list stack from the window 'win'.
+ curwin->w_llist_ref = qi;
+ qi->qf_refcount++;
}
if (oldwin != curwin) {
@@ -3678,6 +3707,8 @@ static int qf_open_new_cwindow(qf_info_T *qi, int height)
if (do_ecmd(0, NULL, NULL, NULL, ECMD_ONE, ECMD_HIDE + ECMD_NOWINENTER, oldwin) == FAIL) {
return FAIL;
}
+ // save the number of the new buffer
+ qi->qf_bufnr = curbuf->b_fnum;
}
// Set the options for the quickfix buffer/window (if not already done)
@@ -3856,8 +3887,8 @@ static int is_qf_win(const win_T *win, const qf_info_T *qi)
return false;
}
-/// Find a window displaying the quickfix/location stack 'qi'
-/// Only searches in the current tabpage.
+/// Find a window displaying the quickfix/location stack 'qi' in the current tab
+/// page.
static win_T *qf_find_win(const qf_info_T *qi)
FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT
{
@@ -3870,11 +3901,20 @@ static win_T *qf_find_win(const qf_info_T *qi)
return NULL;
}
-// Find a quickfix buffer.
-// Searches in windows opened in all the tabs.
+/// Find a quickfix buffer.
+/// Searches in windows opened in all the tab pages.
static buf_T *qf_find_buf(qf_info_T *qi)
FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT
{
+ if (qi->qf_bufnr != INVALID_QFBUFNR) {
+ buf_T *const qfbuf = buflist_findnr(qi->qf_bufnr);
+ if (qfbuf != NULL) {
+ return qfbuf;
+ }
+ // buffer is no longer present
+ qi->qf_bufnr = INVALID_QFBUFNR;
+ }
+
FOR_ALL_TAB_WINDOWS(tp, win) {
if (is_qf_win(win, qi)) {
return win->w_buffer;
@@ -5979,6 +6019,21 @@ static int qf_winid(qf_info_T *qi)
return 0;
}
+/// Returns the number of the buffer displayed in the quickfix/location list
+/// window. If there is no buffer associated with the list or the buffer is
+/// wiped out, then returns 0.
+static int qf_getprop_qfbufnr(const qf_info_T *qi, dict_T *retdict)
+ FUNC_ATTR_NONNULL_ARG(2)
+{
+ int bufnum = 0;
+
+ if (qi != NULL && buflist_findnr(qi->qf_bufnr) != NULL) {
+ bufnum = qi->qf_bufnr;
+ }
+
+ return tv_dict_add_nr(retdict, S_LEN("qfbufnr"), bufnum);
+}
+
/// Convert the keys in 'what' to quickfix list property flags.
static int qf_getprop_keys2flags(const dict_T *what, bool loclist)
FUNC_ATTR_NONNULL_ALL FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT
@@ -6022,6 +6077,9 @@ static int qf_getprop_keys2flags(const dict_T *what, bool loclist)
if (loclist && tv_dict_find(what, S_LEN("filewinid")) != NULL) {
flags |= QF_GETLIST_FILEWINID;
}
+ if (tv_dict_find(what, S_LEN("qfbufnr")) != NULL) {
+ flags |= QF_GETLIST_QFBUFNR;
+ }
if (tv_dict_find(what, S_LEN("quickfixtextfunc")) != NULL) {
flags |= QF_GETLIST_QFTF;
}
@@ -6113,6 +6171,9 @@ static int qf_getprop_defaults(qf_info_T *qi, int flags, int locstack, dict_T *r
if ((status == OK) && locstack && (flags & QF_GETLIST_FILEWINID)) {
status = tv_dict_add_nr(retdict, S_LEN("filewinid"), 0);
}
+ if ((status == OK) && (flags & QF_GETLIST_QFBUFNR)) {
+ status = qf_getprop_qfbufnr(qi, retdict);
+ }
if ((status == OK) && (flags & QF_GETLIST_QFTF)) {
status = tv_dict_add_str(retdict, S_LEN("quickfixtextfunc"), "");
}
@@ -6282,6 +6343,9 @@ int qf_get_properties(win_T *wp, dict_T *what, dict_T *retdict)
if ((status == OK) && (wp != NULL) && (flags & QF_GETLIST_FILEWINID)) {
status = qf_getprop_filewinid(wp, qi, retdict);
}
+ if ((status == OK) && (flags & QF_GETLIST_QFBUFNR)) {
+ status = qf_getprop_qfbufnr(qi, retdict);
+ }
if ((status == OK) && (flags & QF_GETLIST_QFTF)) {
status = qf_getprop_qftf(qfl, retdict);
}
@@ -6670,20 +6734,6 @@ static int qf_set_properties(qf_info_T *qi, const dict_T *what, int action, char
return retval;
}
-/// Find the non-location list window with the specified location list stack in
-/// the current tabpage.
-static win_T *find_win_with_ll(const qf_info_T *qi)
- FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT
-{
- FOR_ALL_WINDOWS_IN_TAB(wp, curtab) {
- if ((wp->w_llist == qi) && !bt_quickfix(wp->w_buffer)) {
- return wp;
- }
- }
-
- return NULL;
-}
-
// Free the entire quickfix/location list stack.
// If the quickfix/location list window is open, then clear it.
static void qf_free_stack(win_T *wp, qf_info_T *qi)
@@ -6698,12 +6748,10 @@ static void qf_free_stack(win_T *wp, qf_info_T *qi)
qf_update_buffer(qi, NULL);
}
- win_T *llwin = NULL;
- win_T *orig_wp = wp;
if (wp != NULL && IS_LL_WINDOW(wp)) {
// If in the location list window, then use the non-location list
// window with this location list (if present)
- llwin = find_win_with_ll(qi);
+ win_T *const llwin = qf_find_win_with_loclist(qi);
if (llwin != NULL) {
wp = llwin;
}
@@ -6714,16 +6762,17 @@ static void qf_free_stack(win_T *wp, qf_info_T *qi)
// quickfix list
qi->qf_curlist = 0;
qi->qf_listcount = 0;
- } else if (IS_LL_WINDOW(orig_wp)) {
+ } else if (qfwin != NULL) {
// If the location list window is open, then create a new empty location
// list
qf_info_T *new_ll = qf_alloc_stack(QFLT_LOCATION);
+ new_ll->qf_bufnr = qfwin->w_buffer->b_fnum;
// first free the list reference in the location list window
- ll_free_all(&orig_wp->w_llist_ref);
+ ll_free_all(&qfwin->w_llist_ref);
- orig_wp->w_llist_ref = new_ll;
- if (llwin != NULL) {
+ qfwin->w_llist_ref = new_ll;
+ if (wp != qfwin) {
win_set_loclist(wp, new_ll);
}
}
diff --git a/src/nvim/rbuffer.h b/src/nvim/rbuffer.h
index cc690050ab..e86765a4ad 100644
--- a/src/nvim/rbuffer.h
+++ b/src/nvim/rbuffer.h
@@ -38,17 +38,15 @@
// create infinite loops
#define RBUFFER_UNTIL_EMPTY(buf, rptr, rcnt) \
for (size_t rcnt = 0, _r = 1; _r; _r = 0) /* NOLINT(readability/braces) */ \
- for ( /* NOLINT(readability/braces) */ \
- char *rptr = rbuffer_read_ptr(buf, &rcnt); \
- buf->size; \
- rptr = rbuffer_read_ptr(buf, &rcnt))
+ for (char *rptr = rbuffer_read_ptr(buf, &rcnt); /* NOLINT(readability/braces) */ \
+ buf->size; \
+ rptr = rbuffer_read_ptr(buf, &rcnt))
#define RBUFFER_UNTIL_FULL(buf, wptr, wcnt) \
for (size_t wcnt = 0, _r = 1; _r; _r = 0) /* NOLINT(readability/braces) */ \
- for ( /* NOLINT(readability/braces) */ \
- char *wptr = rbuffer_write_ptr(buf, &wcnt); \
- rbuffer_space(buf); \
- wptr = rbuffer_write_ptr(buf, &wcnt))
+ for (char *wptr = rbuffer_write_ptr(buf, &wcnt); /* NOLINT(readability/braces) */ \
+ rbuffer_space(buf); \
+ wptr = rbuffer_write_ptr(buf, &wcnt))
// Iteration
diff --git a/src/nvim/screen.c b/src/nvim/screen.c
index 0a1f388456..bc9c6bbe00 100644
--- a/src/nvim/screen.c
+++ b/src/nvim/screen.c
@@ -88,6 +88,7 @@
#include "nvim/garray.h"
#include "nvim/getchar.h"
#include "nvim/highlight.h"
+#include "nvim/highlight_group.h"
#include "nvim/indent.h"
#include "nvim/lib/kvec.h"
#include "nvim/log.h"
@@ -286,7 +287,8 @@ void update_curbuf(int type)
void redraw_buf_status_later(buf_T *buf)
{
FOR_ALL_WINDOWS_IN_TAB(wp, curtab) {
- if (wp->w_buffer == buf && wp->w_status_height) {
+ if (wp->w_buffer == buf
+ && (wp->w_status_height || (wp == curwin && global_stl_height()))) {
wp->w_redr_status = true;
if (must_redraw < VALID) {
must_redraw = VALID;
@@ -316,6 +318,7 @@ void redraw_win_signcol(win_T *wp)
int update_screen(int type)
{
static bool did_intro = false;
+ bool is_stl_global = global_stl_height() > 0;
// Don't do anything if the screen structures are (not yet) valid.
// A VimResized autocmd can invoke redrawing in the middle of a resize,
@@ -398,10 +401,13 @@ int update_screen(int type)
if (W_ENDROW(wp) > valid) {
wp->w_redr_type = MAX(wp->w_redr_type, NOT_VALID);
}
- if (W_ENDROW(wp) + wp->w_status_height > valid) {
+ if (!is_stl_global && W_ENDROW(wp) + wp->w_status_height > valid) {
wp->w_redr_status = true;
}
}
+ if (is_stl_global && Rows - p_ch - 1 > valid) {
+ curwin->w_redr_status = true;
+ }
}
msg_grid_set_pos(Rows-p_ch, false);
msg_grid_invalid = false;
@@ -423,13 +429,15 @@ int update_screen(int type)
wp->w_redr_type = REDRAW_TOP;
} else {
wp->w_redr_type = NOT_VALID;
- if (W_ENDROW(wp) + wp->w_status_height
- <= msg_scrolled) {
- wp->w_redr_status = TRUE;
+ if (!is_stl_global && W_ENDROW(wp) + wp->w_status_height <= msg_scrolled) {
+ wp->w_redr_status = true;
}
}
}
}
+ if (is_stl_global && Rows - p_ch - 1 <= msg_scrolled) {
+ curwin->w_redr_status = true;
+ }
redraw_cmdline = true;
redraw_tabline = true;
}
@@ -740,8 +748,11 @@ static void win_update(win_T *wp, DecorProviders *providers)
wp->w_lines_valid = 0;
}
- // Window is zero-height: nothing to draw.
+ // Window is zero-height: Only need to draw the separator
if (wp->w_grid.Rows == 0) {
+ // draw the horizontal separator below this window
+ draw_hsep_win(wp);
+ draw_sep_connectors_win(wp);
wp->w_redr_type = 0;
return;
}
@@ -749,7 +760,8 @@ static void win_update(win_T *wp, DecorProviders *providers)
// Window is zero-width: Only need to draw the separator.
if (wp->w_grid.Columns == 0) {
// draw the vertical separator right of this window
- draw_vsep_win(wp, 0);
+ draw_vsep_win(wp);
+ draw_sep_connectors_win(wp);
wp->w_redr_type = 0;
return;
}
@@ -1664,7 +1676,9 @@ static void win_update(win_T *wp, DecorProviders *providers)
kvi_destroy(line_providers);
if (wp->w_redr_type >= REDRAW_TOP) {
- draw_vsep_win(wp, 0);
+ draw_vsep_win(wp);
+ draw_hsep_win(wp);
+ draw_sep_connectors_win(wp);
}
syn_set_timeout(NULL);
@@ -1948,6 +1962,27 @@ static inline void provider_err_virt_text(linenr_T lnum, char *err)
decor_add_ephemeral(lnum-1, 0, lnum-1, 0, &err_decor);
}
+static inline void get_line_number_str(win_T *wp, linenr_T lnum, char_u *buf, size_t buf_len)
+{
+ long num;
+ char *fmt = "%*ld ";
+
+ if (wp->w_p_nu && !wp->w_p_rnu) {
+ // 'number' + 'norelativenumber'
+ num = (long)lnum;
+ } else {
+ // 'relativenumber', don't use negative numbers
+ num = labs((long)get_cursor_rel_lnum(wp, lnum));
+ if (num == 0 && wp->w_p_nu && wp->w_p_rnu) {
+ // 'number' + 'relativenumber'
+ num = lnum;
+ fmt = "%-*ld ";
+ }
+ }
+
+ snprintf((char *)buf, buf_len, fmt, number_width(wp), num);
+}
+
/// Display line "lnum" of window 'wp' on the screen.
/// wp->w_virtcol needs to be valid.
///
@@ -2702,8 +2737,13 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool noc
get_sign_display_info(false, wp, lnum, sattrs, row,
startrow, filler_lines, filler_todo,
&c_extra, &c_final, extra, sizeof(extra),
- &p_extra, &n_extra,
- &char_attr, &draw_state, &sign_idx);
+ &p_extra, &n_extra, &char_attr, sign_idx);
+ sign_idx++;
+ if (sign_idx < wp->w_scwidth) {
+ draw_state = WL_SIGN - 1;
+ } else {
+ sign_idx = 0;
+ }
}
}
@@ -2722,29 +2762,11 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool noc
get_sign_display_info(true, wp, lnum, sattrs, row,
startrow, filler_lines, filler_todo,
&c_extra, &c_final, extra, sizeof(extra),
- &p_extra, &n_extra,
- &char_attr, &draw_state, &sign_idx);
+ &p_extra, &n_extra, &char_attr, sign_idx);
} else {
+ // Draw the line number (empty space after wrapping).
if (row == startrow + filler_lines) {
- // Draw the line number (empty space after wrapping). */
- long num;
- char *fmt = "%*ld ";
-
- if (wp->w_p_nu && !wp->w_p_rnu) {
- // 'number' + 'norelativenumber'
- num = (long)lnum;
- } else {
- // 'relativenumber', don't use negative numbers
- num = labs((long)get_cursor_rel_lnum(wp, lnum));
- if (num == 0 && wp->w_p_nu && wp->w_p_rnu) {
- // 'number' + 'relativenumber'
- num = lnum;
- fmt = "%-*ld ";
- }
- }
-
- snprintf((char *)extra, sizeof(extra),
- fmt, number_width(wp), num);
+ get_line_number_str(wp, lnum, (char_u *)extra, sizeof(extra));
if (wp->w_skipcol > 0) {
for (p_extra = extra; *p_extra == ' '; p_extra++) {
*p_extra = '-';
@@ -2762,41 +2784,12 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool noc
}
p_extra = extra;
c_extra = NUL;
- c_final = NUL;
} else {
c_extra = ' ';
- c_final = NUL;
}
+ c_final = NUL;
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.
- char_attr = num_sattr->sat_numhl;
- } else if (wp->w_p_cul
- && lnum == wp->w_cursor.lnum
- && (wp->w_p_culopt_flags & CULOPT_NBR)
- && (row == startrow + filler_lines
- || (row > startrow + filler_lines
- && wp->w_p_culopt_flags & CULOPT_LINE))) {
- // When 'cursorline' is set highlight the line number of
- // the current line differently.
- // When 'cursorlineopt' has "screenline" only highlight
- // the line number itself.
- // TODO(vim): Can we use CursorLine instead of CursorLineNr
- // when CursorLineNr isn't set?
- char_attr = win_hl_attr(wp, HLF_CLN);
- }
+ char_attr = get_line_number_attr(wp, lnum, row, startrow, filler_lines, sattrs);
}
}
}
@@ -4569,20 +4562,66 @@ static bool use_cursor_line_sign(win_T *wp, linenr_T lnum)
&& (wp->w_p_culopt_flags & CULOPT_NBR);
}
+/// Return true if CursorLineNr highlight is to be used for the number column.
+///
+/// - 'cursorline' must be set
+/// - lnum must be the cursor line
+/// - 'cursorlineopt' has "number"
+/// - don't highlight filler lines (when in diff mode)
+/// - When line is wrapped and 'cursorlineopt' does not have "line", only highlight the line number
+/// itself on the first screenline of the wrapped line, otherwise highlight the number column of
+/// all screenlines of the wrapped line.
+static bool use_cursor_line_nr(win_T *wp, linenr_T lnum, int row, int startrow, int filler_lines)
+{
+ return wp->w_p_cul
+ && lnum == wp->w_cursor.lnum
+ && (wp->w_p_culopt_flags & CULOPT_NBR)
+ && (row == startrow + filler_lines
+ || (row > startrow + filler_lines
+ && (wp->w_p_culopt_flags & CULOPT_LINE)));
+}
+
+static int get_line_number_attr(win_T *wp, linenr_T lnum, int row, int startrow, int filler_lines,
+ sign_attrs_T *sattrs)
+{
+ sign_attrs_T *num_sattr = sign_get_attr(SIGN_NUMHL, sattrs, 0, 1);
+ if (num_sattr != NULL) {
+ // :sign defined with "numhl" highlight.
+ return num_sattr->sat_numhl;
+ }
+
+ if (wp->w_p_rnu) {
+ if (lnum < wp->w_cursor.lnum) {
+ // Use LineNrAbove
+ return win_hl_attr(wp, HLF_LNA);
+ }
+ if (lnum > wp->w_cursor.lnum) {
+ // Use LineNrBelow
+ return win_hl_attr(wp, HLF_LNB);
+ }
+ }
+
+ if (use_cursor_line_nr(wp, lnum, row, startrow, filler_lines)) {
+ // TODO(vim): Can we use CursorLine instead of CursorLineNr
+ // when CursorLineNr isn't set?
+ return win_hl_attr(wp, HLF_CLN);
+ }
+
+ return win_hl_attr(wp, HLF_N);
+}
+
// Get information needed to display the sign in line 'lnum' in window 'wp'.
// If 'nrcol' is TRUE, the sign is going to be displayed in the number column.
// Otherwise the sign is going to be displayed in the sign column.
//
// @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
+// @param sign_idxp Index of the displayed sign
static void get_sign_display_info(bool nrcol, win_T *wp, linenr_T lnum, sign_attrs_T sattrs[],
int row, int startrow, int filler_lines, int filler_todo,
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)
+ char_u **pp_extra, int *n_extrap, int *char_attrp, int sign_idx)
{
- int count = wp->w_scwidth;
// Draw cells with the sign value or blank.
*c_extrap = ' ';
*c_finalp = NUL;
@@ -4598,7 +4637,7 @@ static void get_sign_display_info(bool nrcol, win_T *wp, linenr_T lnum, sign_att
}
if (row == startrow + filler_lines && filler_todo <= 0) {
- sign_attrs_T *sattr = sign_get_attr(SIGN_TEXT, sattrs, *sign_idxp, count);
+ sign_attrs_T *sattr = sign_get_attr(SIGN_TEXT, sattrs, sign_idx, wp->w_scwidth);
if (sattr != NULL) {
*pp_extra = sattr->sat_text;
if (*pp_extra != NULL) {
@@ -4641,13 +4680,6 @@ static void get_sign_display_info(bool nrcol, win_T *wp, linenr_T lnum, sign_att
}
}
}
-
- (*sign_idxp)++;
- if (*sign_idxp < count) {
- *draw_statep = WL_SIGN - 1;
- } else {
- *sign_idxp = 0;
- }
}
@@ -4863,10 +4895,15 @@ 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;
- redraw_later(wp, VALID);
+ if (global_stl_height()) {
+ curwin->w_redr_status = true;
+ redraw_later(curwin, VALID);
+ } else {
+ FOR_ALL_WINDOWS_IN_TAB(wp, curtab) {
+ if (wp->w_status_height) {
+ wp->w_redr_status = true;
+ redraw_later(wp, VALID);
+ }
}
}
}
@@ -4880,10 +4917,15 @@ void status_redraw_curbuf(void)
/// Marks all status lines of the specified buffer for redraw.
void status_redraw_buf(buf_T *buf)
{
- FOR_ALL_WINDOWS_IN_TAB(wp, curtab) {
- if (wp->w_status_height != 0 && wp->w_buffer == buf) {
- wp->w_redr_status = true;
- redraw_later(wp, VALID);
+ if (global_stl_height() != 0 && curwin->w_buffer == buf) {
+ curwin->w_redr_status = true;
+ redraw_later(curwin, VALID);
+ } else {
+ FOR_ALL_WINDOWS_IN_TAB(wp, curtab) {
+ if (wp->w_status_height != 0 && wp->w_buffer == buf) {
+ wp->w_redr_status = true;
+ redraw_later(wp, VALID);
+ }
}
}
}
@@ -4925,10 +4967,8 @@ void win_redraw_last_status(const frame_T *frp)
}
}
-/*
- * Draw the verticap separator right of window "wp" starting with line "row".
- */
-static void draw_vsep_win(win_T *wp, int row)
+/// Draw the vertical separator right of window "wp"
+static void draw_vsep_win(win_T *wp)
{
int hl;
int c;
@@ -4936,15 +4976,97 @@ static void draw_vsep_win(win_T *wp, int row)
if (wp->w_vsep_width) {
// draw the vertical separator right of this window
c = fillchar_vsep(wp, &hl);
- grid_fill(&default_grid, wp->w_winrow + row, W_ENDROW(wp),
+ grid_fill(&default_grid, wp->w_winrow, W_ENDROW(wp),
W_ENDCOL(wp), W_ENDCOL(wp) + 1, c, ' ', hl);
}
}
+/// Draw the horizontal separator below window "wp"
+static void draw_hsep_win(win_T *wp)
+{
+ int hl;
+ int c;
-/*
- * Get the length of an item as it will be shown in the status line.
- */
+ if (wp->w_hsep_height) {
+ // draw the horizontal separator below this window
+ c = fillchar_hsep(wp, &hl);
+ grid_fill(&default_grid, W_ENDROW(wp), W_ENDROW(wp) + 1,
+ wp->w_wincol, W_ENDCOL(wp), c, c, hl);
+ }
+}
+
+/// Get the separator connector for specified window corner of window "wp"
+static int get_corner_sep_connector(win_T *wp, WindowCorner corner)
+{
+ // It's impossible for windows to be connected neither vertically nor horizontally
+ // So if they're not vertically connected, assume they're horizontally connected
+ if (vsep_connected(wp, corner)) {
+ if (hsep_connected(wp, corner)) {
+ return wp->w_p_fcs_chars.verthoriz;
+ } else if (corner == WC_TOP_LEFT || corner == WC_BOTTOM_LEFT) {
+ return wp->w_p_fcs_chars.vertright;
+ } else {
+ return wp->w_p_fcs_chars.vertleft;
+ }
+ } else if (corner == WC_TOP_LEFT || corner == WC_TOP_RIGHT) {
+ return wp->w_p_fcs_chars.horizdown;
+ } else {
+ return wp->w_p_fcs_chars.horizup;
+ }
+}
+
+/// Draw seperator connecting characters on the corners of window "wp"
+static void draw_sep_connectors_win(win_T *wp)
+{
+ // Don't draw separator connectors unless global statusline is enabled and the window has
+ // either a horizontal or vertical separator
+ if (global_stl_height() == 0 || !(wp->w_hsep_height == 1 || wp->w_vsep_width == 1)) {
+ return;
+ }
+
+ int hl = win_hl_attr(wp, HLF_C);
+
+ // Determine which edges of the screen the window is located on so we can avoid drawing separators
+ // on corners contained in those edges
+ bool win_at_top;
+ bool win_at_bottom = wp->w_hsep_height == 0;
+ bool win_at_left;
+ bool win_at_right = wp->w_vsep_width == 0;
+ frame_T *frp;
+
+ for (frp = wp->w_frame; frp->fr_parent != NULL; frp = frp->fr_parent) {
+ if (frp->fr_parent->fr_layout == FR_COL && frp->fr_prev != NULL) {
+ break;
+ }
+ }
+ win_at_top = frp->fr_parent == NULL;
+ for (frp = wp->w_frame; frp->fr_parent != NULL; frp = frp->fr_parent) {
+ if (frp->fr_parent->fr_layout == FR_ROW && frp->fr_prev != NULL) {
+ break;
+ }
+ }
+ win_at_left = frp->fr_parent == NULL;
+
+ // Draw the appropriate separator connector in every corner where drawing them is necessary
+ if (!(win_at_top || win_at_left)) {
+ grid_putchar(&default_grid, get_corner_sep_connector(wp, WC_TOP_LEFT),
+ wp->w_winrow - 1, wp->w_wincol - 1, hl);
+ }
+ if (!(win_at_top || win_at_right)) {
+ grid_putchar(&default_grid, get_corner_sep_connector(wp, WC_TOP_RIGHT),
+ wp->w_winrow - 1, W_ENDCOL(wp), hl);
+ }
+ if (!(win_at_bottom || win_at_left)) {
+ grid_putchar(&default_grid, get_corner_sep_connector(wp, WC_BOTTOM_LEFT),
+ W_ENDROW(wp), wp->w_wincol - 1, hl);
+ }
+ if (!(win_at_bottom || win_at_right)) {
+ grid_putchar(&default_grid, get_corner_sep_connector(wp, WC_BOTTOM_RIGHT),
+ W_ENDROW(wp), W_ENDCOL(wp), hl);
+ }
+}
+
+/// Get the length of an item as it will be shown in the status line.
static int status_match_len(expand_T *xp, char_u *s)
{
int len = 0;
@@ -5145,7 +5267,7 @@ void win_redr_status_matches(expand_T *xp, int num_matches, char_u **matches, in
// Create status line if needed by setting 'laststatus' to 2.
// Set 'winminheight' to zero to avoid that the window is
// resized.
- if (lastwin->w_status_height == 0) {
+ if (lastwin->w_status_height == 0 && global_stl_height() == 0) {
save_p_ls = p_ls;
save_p_wmh = p_wmh;
p_ls = 2;
@@ -5181,12 +5303,15 @@ void win_redr_status_matches(expand_T *xp, int num_matches, char_u **matches, in
static void win_redr_status(win_T *wp)
{
int row;
+ int col;
char_u *p;
int len;
int fillchar;
int attr;
+ int width;
int this_ru_col;
- static int busy = FALSE;
+ bool is_stl_global = global_stl_height() > 0;
+ static int busy = false;
// May get here recursively when 'statusline' (indirectly)
// invokes ":redrawstatus". Simply ignore the call then.
@@ -5197,9 +5322,9 @@ static void win_redr_status(win_T *wp)
}
busy = true;
- wp->w_redr_status = FALSE;
- if (wp->w_status_height == 0) {
- // no status line, can only be last window
+ wp->w_redr_status = false;
+ if (wp->w_status_height == 0 && !(is_stl_global && wp == curwin)) {
+ // no status line, either global statusline is enabled or the window is a last window
redraw_cmdline = true;
} else if (!redrawing()) {
// Don't redraw right now, do it later. Don't update status line when
@@ -5210,6 +5335,7 @@ static void win_redr_status(win_T *wp)
redraw_custom_statusline(wp);
} else {
fillchar = fillchar_status(&attr, wp);
+ width = is_stl_global ? Columns : wp->w_width;
get_trans_bufname(wp->w_buffer);
p = NameBuff;
@@ -5238,9 +5364,9 @@ static void win_redr_status(win_T *wp)
// len += (int)STRLEN(p + len); // dead assignment
}
- this_ru_col = ru_col - (Columns - wp->w_width);
- if (this_ru_col < (wp->w_width + 1) / 2) {
- this_ru_col = (wp->w_width + 1) / 2;
+ this_ru_col = ru_col - (Columns - width);
+ if (this_ru_col < (width + 1) / 2) {
+ this_ru_col = (width + 1) / 2;
}
if (this_ru_col <= 1) {
p = (char_u *)"<"; // No room for file name!
@@ -5265,10 +5391,11 @@ static void win_redr_status(win_T *wp)
}
}
- row = W_ENDROW(wp);
- grid_puts(&default_grid, p, row, wp->w_wincol, attr);
- grid_fill(&default_grid, row, row + 1, len + wp->w_wincol,
- this_ru_col + wp->w_wincol, fillchar, fillchar, attr);
+ row = is_stl_global ? (Rows - p_ch - 1) : W_ENDROW(wp);
+ col = is_stl_global ? 0 : wp->w_wincol;
+ grid_puts(&default_grid, p, row, col, attr);
+ grid_fill(&default_grid, row, row + 1, len + col,
+ this_ru_col + col, fillchar, fillchar, attr);
if (get_keymap_str(wp, (char_u *)"<%s>", NameBuff, MAXPATHL)
&& this_ru_col - len > (int)(STRLEN(NameBuff) + 1)) {
@@ -5347,6 +5474,76 @@ bool stl_connected(win_T *wp)
return false;
}
+/// Check if horizontal separator of window "wp" at specified window corner is connected to the
+/// horizontal separator of another window
+/// Assumes global statusline is enabled
+static bool hsep_connected(win_T *wp, WindowCorner corner)
+{
+ bool before = (corner == WC_TOP_LEFT || corner == WC_BOTTOM_LEFT);
+ int sep_row = (corner == WC_TOP_LEFT || corner == WC_TOP_RIGHT)
+ ? wp->w_winrow - 1 : W_ENDROW(wp);
+ frame_T *fr = wp->w_frame;
+
+ while (fr->fr_parent != NULL) {
+ if (fr->fr_parent->fr_layout == FR_ROW && (before ? fr->fr_prev : fr->fr_next) != NULL) {
+ fr = before ? fr->fr_prev : fr->fr_next;
+ break;
+ }
+ fr = fr->fr_parent;
+ }
+ if (fr->fr_parent == NULL) {
+ return false;
+ }
+ while (fr->fr_layout != FR_LEAF) {
+ fr = fr->fr_child;
+ if (fr->fr_parent->fr_layout == FR_ROW && before) {
+ while (fr->fr_next != NULL) {
+ fr = fr->fr_next;
+ }
+ } else {
+ while (fr->fr_next != NULL && frame2win(fr)->w_winrow + fr->fr_height < sep_row) {
+ fr = fr->fr_next;
+ }
+ }
+ }
+
+ return (sep_row == fr->fr_win->w_winrow - 1 || sep_row == W_ENDROW(fr->fr_win));
+}
+
+/// Check if vertical separator of window "wp" at specified window corner is connected to the
+/// vertical separator of another window
+static bool vsep_connected(win_T *wp, WindowCorner corner)
+{
+ bool before = (corner == WC_TOP_LEFT || corner == WC_TOP_RIGHT);
+ int sep_col = (corner == WC_TOP_LEFT || corner == WC_BOTTOM_LEFT)
+ ? wp->w_wincol - 1 : W_ENDCOL(wp);
+ frame_T *fr = wp->w_frame;
+
+ while (fr->fr_parent != NULL) {
+ if (fr->fr_parent->fr_layout == FR_COL && (before ? fr->fr_prev : fr->fr_next) != NULL) {
+ fr = before ? fr->fr_prev : fr->fr_next;
+ break;
+ }
+ fr = fr->fr_parent;
+ }
+ if (fr->fr_parent == NULL) {
+ return false;
+ }
+ while (fr->fr_layout != FR_LEAF) {
+ fr = fr->fr_child;
+ if (fr->fr_parent->fr_layout == FR_COL && before) {
+ while (fr->fr_next != NULL) {
+ fr = fr->fr_next;
+ }
+ } else {
+ while (fr->fr_next != NULL && frame2win(fr)->w_wincol + fr->fr_width < sep_col) {
+ fr = fr->fr_next;
+ }
+ }
+ }
+
+ return (sep_col == fr->fr_win->w_wincol - 1 || sep_col == W_ENDCOL(fr->fr_win));
+}
/// Get the value to show for the language mappings, active 'keymap'.
///
@@ -5413,6 +5610,7 @@ static void win_redr_custom(win_T *wp, bool draw_ruler)
int use_sandbox = false;
win_T *ewp;
int p_crb_save;
+ bool is_stl_global = global_stl_height() > 0;
ScreenGrid *grid = &default_grid;
@@ -5434,9 +5632,9 @@ static void win_redr_custom(win_T *wp, bool draw_ruler)
maxwidth = Columns;
use_sandbox = was_set_insecurely(wp, "tabline", 0);
} else {
- row = W_ENDROW(wp);
+ row = is_stl_global ? (Rows - p_ch - 1) : W_ENDROW(wp);
fillchar = fillchar_status(&attr, wp);
- maxwidth = wp->w_width;
+ maxwidth = is_stl_global ? Columns : wp->w_width;
if (draw_ruler) {
stl = p_ruf;
@@ -5454,12 +5652,12 @@ static void win_redr_custom(win_T *wp, bool draw_ruler)
stl = p_ruf;
}
}
- col = ru_col - (Columns - wp->w_width);
- if (col < (wp->w_width + 1) / 2) {
- col = (wp->w_width + 1) / 2;
+ col = ru_col - (Columns - maxwidth);
+ if (col < (maxwidth + 1) / 2) {
+ col = (maxwidth + 1) / 2;
}
- maxwidth = wp->w_width - col;
- if (!wp->w_status_height) {
+ maxwidth = maxwidth - col;
+ if (!wp->w_status_height && !is_stl_global) {
grid = &msg_grid_adj;
row = Rows - 1;
maxwidth--; // writing in last column may cause scrolling
@@ -5477,7 +5675,7 @@ static void win_redr_custom(win_T *wp, bool draw_ruler)
use_sandbox = was_set_insecurely(wp, "statusline", *wp->w_p_stl == NUL ? 0 : OPT_LOCAL);
}
- col += wp->w_wincol;
+ col += is_stl_global ? 0 : wp->w_wincol;
}
if (maxwidth <= 0) {
@@ -7059,10 +7257,10 @@ int showmode(void)
clear_showcmd();
}
- // If the last window has no status line, the ruler is after the mode
- // message and must be redrawn
+ // If the last window has no status line and global statusline is disabled,
+ // the ruler is after the mode message and must be redrawn
win_T *last = lastwin_nofloating();
- if (redrawing() && last->w_status_height == 0) {
+ if (redrawing() && last->w_status_height == 0 && global_stl_height() == 0) {
win_redr_ruler(last, true);
}
redraw_cmdline = false;
@@ -7377,16 +7575,22 @@ int fillchar_status(int *attr, win_T *wp)
return '=';
}
-/*
- * Get the character to use in a separator between vertically split windows.
- * Get its attributes in "*attr".
- */
+/// Get the character to use in a separator between vertically split windows.
+/// Get its attributes in "*attr".
static int fillchar_vsep(win_T *wp, int *attr)
{
*attr = win_hl_attr(wp, HLF_C);
return wp->w_p_fcs_chars.vert;
}
+/// Get the character to use in a separator between horizontally split windows.
+/// Get its attributes in "*attr".
+static int fillchar_hsep(win_T *wp, int *attr)
+{
+ *attr = win_hl_attr(wp, HLF_C);
+ return wp->w_p_fcs_chars.horiz;
+}
+
/*
* Return TRUE if redrawing should currently be done.
*/
@@ -7412,7 +7616,8 @@ void showruler(bool always)
if (!always && !redrawing()) {
return;
}
- if ((*p_stl != NUL || *curwin->w_p_stl != NUL) && curwin->w_status_height) {
+ if ((*p_stl != NUL || *curwin->w_p_stl != NUL)
+ && (curwin->w_status_height || global_stl_height())) {
redraw_custom_statusline(curwin);
} else {
win_redr_ruler(curwin, always);
@@ -7431,6 +7636,7 @@ void showruler(bool always)
static void win_redr_ruler(win_T *wp, bool always)
{
+ bool is_stl_global = global_stl_height() > 0;
static bool did_show_ext_ruler = false;
// If 'ruler' off or redrawing disabled, don't do anything
@@ -7448,7 +7654,7 @@ static void win_redr_ruler(win_T *wp, bool always)
// Don't draw the ruler while doing insert-completion, it might overwrite
// the (long) mode message.
- if (wp == lastwin && lastwin->w_status_height == 0) {
+ if (wp == lastwin && lastwin->w_status_height == 0 && !is_stl_global) {
if (edit_submode != NULL) {
return;
}
@@ -7503,6 +7709,12 @@ static void win_redr_ruler(win_T *wp, bool always)
off = wp->w_wincol;
width = wp->w_width;
part_of_status = true;
+ } else if (is_stl_global) {
+ row = Rows - p_ch - 1;
+ fillchar = fillchar_status(&attr, wp);
+ off = 0;
+ width = Columns;
+ part_of_status = true;
} else {
row = Rows - 1;
fillchar = ' ';
@@ -7542,7 +7754,7 @@ static void win_redr_ruler(win_T *wp, bool always)
int i = (int)STRLEN(buffer);
get_rel_pos(wp, buffer + i + 1, RULER_BUF_LEN - i - 1);
int o = i + vim_strsize(buffer + i + 1);
- if (wp->w_status_height == 0) { // can't use last char of screen
+ if (wp->w_status_height == 0 && !is_stl_global) { // can't use last char of screen
o++;
}
int this_ru_col = ru_col - (Columns - width);
diff --git a/src/nvim/screen.h b/src/nvim/screen.h
index d704a6eb8a..d15e4b7e45 100644
--- a/src/nvim/screen.h
+++ b/src/nvim/screen.h
@@ -8,12 +8,10 @@
#include "nvim/pos.h"
#include "nvim/types.h"
-/*
- * flags for update_screen()
- * The higher the value, the higher the priority
- */
-#define VALID 10 /* buffer not changed, or changes marked
- with b_mod_* */
+// flags for update_screen()
+// The higher the value, the higher the priority
+#define VALID 10 // buffer not changed, or changes marked
+ // with b_mod_*
#define INVERTED 20 // redisplay inverted part that changed
#define INVERTED_ALL 25 // redisplay whole inverted part
#define REDRAW_TOP 30 // display first w_upd_rows screen lines
@@ -21,6 +19,14 @@
#define NOT_VALID 40 // buffer needs complete redraw
#define CLEAR 50 // screen messed up, clear it
+/// corner value flags for hsep_connected and vsep_connected
+typedef enum {
+ WC_TOP_LEFT = 0,
+ WC_TOP_RIGHT,
+ WC_BOTTOM_LEFT,
+ WC_BOTTOM_RIGHT
+} WindowCorner;
+
/// By default, all widows are draw on a single rectangular grid, represented by
/// this ScreenGrid instance. In multigrid mode each window will have its own
/// grid, then this is only used for global screen elements that hasn't been
diff --git a/src/nvim/search.c b/src/nvim/search.c
index cc7c2ecf06..a69bd641f8 100644
--- a/src/nvim/search.c
+++ b/src/nvim/search.c
@@ -5689,7 +5689,7 @@ search_line:
// we read a line, set "already" to check this "line" later
// if depth >= 0 we'll increase files[depth].lnum far
- // bellow -- Acevedo
+ // below -- Acevedo
already = aux = p = skipwhite(line);
p = find_word_start(p);
p = find_word_end(p);
diff --git a/src/nvim/sign.c b/src/nvim/sign.c
index 6d0ac30003..50400852b8 100644
--- a/src/nvim/sign.c
+++ b/src/nvim/sign.c
@@ -13,6 +13,7 @@
#include "nvim/edit.h"
#include "nvim/ex_docmd.h"
#include "nvim/fold.h"
+#include "nvim/highlight_group.h"
#include "nvim/move.h"
#include "nvim/option.h"
#include "nvim/screen.h"
@@ -954,7 +955,7 @@ int sign_define_by_name(char_u *name, char_u *icon, char_u *linehl, char_u *text
if (*linehl == NUL) {
sp->sn_line_hl = 0;
} else {
- sp->sn_line_hl = syn_check_group((char *)linehl, (int)STRLEN(linehl));
+ sp->sn_line_hl = syn_check_group((char *)linehl, STRLEN(linehl));
}
}
@@ -962,7 +963,7 @@ int sign_define_by_name(char_u *name, char_u *icon, char_u *linehl, char_u *text
if (*texthl == NUL) {
sp->sn_text_hl = 0;
} else {
- sp->sn_text_hl = syn_check_group((char *)texthl, (int)STRLEN(texthl));
+ sp->sn_text_hl = syn_check_group((char *)texthl, STRLEN(texthl));
}
}
@@ -970,7 +971,7 @@ int sign_define_by_name(char_u *name, char_u *icon, char_u *linehl, char_u *text
if (*culhl == NUL) {
sp->sn_cul_hl = 0;
} else {
- sp->sn_cul_hl = syn_check_group((char *)culhl, (int)STRLEN(culhl));
+ sp->sn_cul_hl = syn_check_group((char *)culhl, STRLEN(culhl));
}
}
@@ -978,7 +979,7 @@ int sign_define_by_name(char_u *name, char_u *icon, char_u *linehl, char_u *text
if (*numhl == NUL) {
sp->sn_num_hl = 0;
} else {
- sp->sn_num_hl = syn_check_group(numhl, (int)STRLEN(numhl));
+ sp->sn_num_hl = syn_check_group(numhl, STRLEN(numhl));
}
}
diff --git a/src/nvim/syntax.c b/src/nvim/syntax.c
index 54fce3d968..f829b6a270 100644
--- a/src/nvim/syntax.c
+++ b/src/nvim/syntax.c
@@ -25,6 +25,7 @@
#include "nvim/garray.h"
#include "nvim/hashtab.h"
#include "nvim/highlight.h"
+#include "nvim/highlight_group.h"
#include "nvim/indent_c.h"
#include "nvim/keymap.h"
#include "nvim/lua/executor.h"
@@ -51,56 +52,6 @@
static bool did_syntax_onoff = false;
-/// Structure that stores information about a highlight group.
-/// The ID of a highlight group is also called group ID. It is the index in
-/// the highlight_ga array PLUS ONE.
-typedef struct hl_group {
- char_u *sg_name; ///< highlight group name
- char *sg_name_u; ///< uppercase of sg_name
- bool sg_cleared; ///< "hi clear" was used
- int sg_attr; ///< Screen attr @see ATTR_ENTRY
- int sg_link; ///< link to this highlight group ID
- int sg_deflink; ///< default link; restored in highlight_clear()
- int sg_set; ///< combination of flags in \ref SG_SET
- sctx_T sg_deflink_sctx; ///< script where the default link was set
- sctx_T sg_script_ctx; ///< script in which the group was last set
- // for terminal UIs
- int sg_cterm; ///< "cterm=" highlighting attr
- ///< (combination of \ref HlAttrFlags)
- int sg_cterm_fg; ///< terminal fg color number + 1
- int sg_cterm_bg; ///< terminal bg color number + 1
- bool sg_cterm_bold; ///< bold attr was set for light color
- // for RGB UIs
- int sg_gui; ///< "gui=" highlighting attributes
- ///< (combination of \ref HlAttrFlags)
- RgbValue sg_rgb_fg; ///< RGB foreground color
- RgbValue sg_rgb_bg; ///< RGB background color
- RgbValue sg_rgb_sp; ///< RGB special color
- char *sg_rgb_fg_name; ///< RGB foreground color name
- char *sg_rgb_bg_name; ///< RGB background color name
- char *sg_rgb_sp_name; ///< RGB special color name
-
- int sg_blend; ///< blend level (0-100 inclusive), -1 if unset
-} HlGroup;
-
-/// \addtogroup SG_SET
-/// @{
-#define SG_CTERM 2 // cterm has been set
-#define SG_GUI 4 // gui has been set
-#define SG_LINK 8 // link has been set
-/// @}
-
-// builtin |highlight-groups|
-static garray_T highlight_ga = GA_EMPTY_INIT_VALUE;
-Map(cstr_t, int) highlight_unames = MAP_INIT;
-
-static inline struct hl_group *HL_TABLE(void)
-{
- return ((struct hl_group *)((highlight_ga.ga_data)));
-}
-
-#define MAX_HL_ID 20000 // maximum value for a highlight ID.
-
// different types of offsets that are possible
#define SPO_MS_OFF 0 // match start offset
#define SPO_ME_OFF 1 // match end offset
@@ -111,22 +62,6 @@ static inline struct hl_group *HL_TABLE(void)
#define SPO_LC_OFF 6 // leading context offset
#define SPO_COUNT 7
-// Flags to indicate an additional string for highlight name completion.
-static int include_none = 0; // when 1 include "nvim/None"
-static int include_default = 0; // when 1 include "nvim/default"
-static int include_link = 0; // when 2 include "nvim/link" and "clear"
-
-#define MAX_SYN_NAME 200
-
-/// The "term", "cterm" and "gui" arguments can be any combination of the
-/// following names, separated by commas (but no spaces!).
-static char *(hl_name_table[]) =
-{ "bold", "standout", "underline", "underlineline", "undercurl", "underdot",
- "underdash", "italic", "reverse", "inverse", "strikethrough", "nocombine", "NONE" };
-static int hl_attr_table[] =
-{ HL_BOLD, HL_STANDOUT, HL_UNDERLINE, HL_UNDERLINELINE, HL_UNDERCURL, HL_UNDERDOT, HL_UNDERDASH,
- HL_ITALIC, HL_INVERSE, HL_INVERSE, HL_STRIKETHROUGH, HL_NOCOMBINE, 0 };
-
static char e_illegal_arg[] = N_("E390: Illegal argument: %s");
// The patterns that are being searched for are stored in a syn_pattern.
@@ -3609,7 +3544,7 @@ static void syn_cmd_list(exarg_T *eap, int syncing)
/*
* No argument: List all group IDs and all syntax clusters.
*/
- for (int id = 1; id <= highlight_ga.ga_len && !got_int; id++) {
+ for (int id = 1; id <= highlight_num_groups() && !got_int; id++) {
syn_list_one(id, syncing, false);
}
for (int id = 0; id < curwin->w_s->b_syn_clusters.ga_len && !got_int; ++id) {
@@ -3767,8 +3702,8 @@ static void syn_list_one(const int id, const bool syncing, const bool link_only)
}
msg_putchar(' ');
if (spp->sp_sync_idx >= 0) {
- msg_outtrans(HL_TABLE()[SYN_ITEMS(curwin->w_s)
- [spp->sp_sync_idx].sp_syn.id - 1].sg_name);
+ msg_outtrans(highlight_group_name(SYN_ITEMS(curwin->w_s)
+ [spp->sp_sync_idx].sp_syn.id - 1));
} else {
msg_puts("NONE");
}
@@ -3777,11 +3712,11 @@ static void syn_list_one(const int id, const bool syncing, const bool link_only)
}
// list the link, if there is one
- if (HL_TABLE()[id - 1].sg_link && (did_header || link_only) && !got_int) {
+ if (highlight_link_id(id - 1) && (did_header || link_only) && !got_int) {
(void)syn_list_header(did_header, 0, id, true);
msg_puts_attr("links to", attr);
msg_putchar(' ');
- msg_outtrans(HL_TABLE()[HL_TABLE()[id - 1].sg_link - 1].sg_name);
+ msg_outtrans(highlight_group_name(highlight_link_id(id - 1) - 1));
}
}
@@ -3845,7 +3780,7 @@ static void put_id_list(const char *const name, const int16_t *const list, const
msg_putchar('@');
msg_outtrans(SYN_CLSTR(curwin->w_s)[scl_id].scl_name);
} else {
- msg_outtrans(HL_TABLE()[*p - 1].sg_name);
+ msg_outtrans(highlight_group_name(*p - 1));
}
if (p[1]) {
msg_putchar(',');
@@ -3867,7 +3802,7 @@ static void put_pattern(const char *const s, const int c, const synpat_T *const
if (last_matchgroup == 0) {
msg_outtrans((char_u *)"NONE");
} else {
- msg_outtrans(HL_TABLE()[last_matchgroup - 1].sg_name);
+ msg_outtrans(highlight_group_name(last_matchgroup - 1));
}
msg_putchar(' ');
}
@@ -5459,8 +5394,8 @@ static int get_id_list(char_u **const arg, const int keylen, int16_t **const lis
regmatch.rm_ic = TRUE;
id = 0;
- for (int i = highlight_ga.ga_len; --i >= 0;) {
- if (vim_regexec(&regmatch, HL_TABLE()[i].sg_name, (colnr_T)0)) {
+ for (int i = highlight_num_groups(); --i >= 0;) {
+ if (vim_regexec(&regmatch, highlight_group_name(i), (colnr_T)0)) {
if (round == 2) {
// Got more items than expected; can happen
// when adding items that match:
@@ -6121,7 +6056,7 @@ static void syntime_report(void)
msg_puts(profile_msg(p->average));
msg_puts(" ");
msg_advance(50);
- msg_outtrans(HL_TABLE()[p->id - 1].sg_name);
+ msg_outtrans(highlight_group_name(p->id - 1));
msg_puts(" ");
msg_advance(69);
@@ -6146,2740 +6081,3 @@ static void syntime_report(void)
msg_puts("\n");
}
}
-
-/**************************************
-* Highlighting stuff *
-**************************************/
-
-// The default highlight groups. These are compiled-in for fast startup and
-// they still work when the runtime files can't be found.
-//
-// When making changes here, also change runtime/colors/default.vim!
-
-static const char *highlight_init_both[] = {
- "Conceal ctermbg=DarkGrey ctermfg=LightGrey guibg=DarkGrey guifg=LightGrey",
- "Cursor guibg=fg guifg=bg",
- "lCursor guibg=fg guifg=bg",
- "DiffText cterm=bold ctermbg=Red gui=bold guibg=Red",
- "ErrorMsg ctermbg=DarkRed ctermfg=White guibg=Red guifg=White",
- "IncSearch cterm=reverse gui=reverse",
- "ModeMsg cterm=bold gui=bold",
- "NonText ctermfg=Blue gui=bold guifg=Blue",
- "Normal cterm=NONE gui=NONE",
- "PmenuSbar ctermbg=Grey guibg=Grey",
- "StatusLine cterm=reverse,bold gui=reverse,bold",
- "StatusLineNC cterm=reverse gui=reverse",
- "TabLineFill cterm=reverse gui=reverse",
- "TabLineSel cterm=bold gui=bold",
- "TermCursor cterm=reverse gui=reverse",
- "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 CursorLineSign SignColumn",
- "default link CursorLineFold FoldColumn",
- "default link Substitute Search",
- "default link Whitespace NonText",
- "default link MsgSeparator StatusLine",
- "default link NormalFloat Pmenu",
- "default link FloatBorder VertSplit",
- "default FloatShadow blend=80 guibg=Black",
- "default FloatShadowThrough blend=100 guibg=Black",
- "RedrawDebugNormal cterm=reverse gui=reverse",
- "RedrawDebugClear ctermbg=Yellow guibg=Yellow",
- "RedrawDebugComposed ctermbg=Green guibg=Green",
- "RedrawDebugRecompose ctermbg=Red guibg=Red",
- "Error term=reverse cterm=NONE ctermfg=White ctermbg=Red gui=NONE guifg=White guibg=Red",
- "Todo term=standout cterm=NONE ctermfg=Black ctermbg=Yellow gui=NONE guifg=Blue guibg=Yellow",
- "default link String Constant",
- "default link Character Constant",
- "default link Number Constant",
- "default link Boolean Constant",
- "default link Float Number",
- "default link Function Identifier",
- "default link Conditional Statement",
- "default link Repeat Statement",
- "default link Label Statement",
- "default link Operator Statement",
- "default link Keyword Statement",
- "default link Exception Statement",
- "default link Include PreProc",
- "default link Define PreProc",
- "default link Macro PreProc",
- "default link PreCondit PreProc",
- "default link StorageClass Type",
- "default link Structure Type",
- "default link Typedef Type",
- "default link Tag Special",
- "default link SpecialChar Special",
- "default link Delimiter Special",
- "default link SpecialComment Special",
- "default link Debug Special",
- "default DiagnosticError ctermfg=1 guifg=Red",
- "default DiagnosticWarn ctermfg=3 guifg=Orange",
- "default DiagnosticInfo ctermfg=4 guifg=LightBlue",
- "default DiagnosticHint ctermfg=7 guifg=LightGrey",
- "default DiagnosticUnderlineError cterm=underline gui=underline guisp=Red",
- "default DiagnosticUnderlineWarn cterm=underline gui=underline guisp=Orange",
- "default DiagnosticUnderlineInfo cterm=underline gui=underline guisp=LightBlue",
- "default DiagnosticUnderlineHint cterm=underline gui=underline guisp=LightGrey",
- "default link DiagnosticVirtualTextError DiagnosticError",
- "default link DiagnosticVirtualTextWarn DiagnosticWarn",
- "default link DiagnosticVirtualTextInfo DiagnosticInfo",
- "default link DiagnosticVirtualTextHint DiagnosticHint",
- "default link DiagnosticFloatingError DiagnosticError",
- "default link DiagnosticFloatingWarn DiagnosticWarn",
- "default link DiagnosticFloatingInfo DiagnosticInfo",
- "default link DiagnosticFloatingHint DiagnosticHint",
- "default link DiagnosticSignError DiagnosticError",
- "default link DiagnosticSignWarn DiagnosticWarn",
- "default link DiagnosticSignInfo DiagnosticInfo",
- "default link DiagnosticSignHint DiagnosticHint",
- NULL
-};
-
-// Default colors only used with a light background.
-static const char *highlight_init_light[] = {
- "ColorColumn ctermbg=LightRed guibg=LightRed",
- "CursorColumn ctermbg=LightGrey guibg=Grey90",
- "CursorLine cterm=underline guibg=Grey90",
- "CursorLineNr cterm=underline ctermfg=Brown gui=bold guifg=Brown",
- "DiffAdd ctermbg=LightBlue guibg=LightBlue",
- "DiffChange ctermbg=LightMagenta guibg=LightMagenta",
- "DiffDelete ctermfg=Blue ctermbg=LightCyan gui=bold guifg=Blue guibg=LightCyan",
- "Directory ctermfg=DarkBlue guifg=Blue",
- "FoldColumn ctermbg=Grey ctermfg=DarkBlue guibg=Grey guifg=DarkBlue",
- "Folded ctermbg=Grey ctermfg=DarkBlue guibg=LightGrey guifg=DarkBlue",
- "LineNr ctermfg=Brown guifg=Brown",
- "MatchParen ctermbg=Cyan guibg=Cyan",
- "MoreMsg ctermfg=DarkGreen gui=bold guifg=SeaGreen",
- "Pmenu ctermbg=LightMagenta ctermfg=Black guibg=LightMagenta",
- "PmenuSel ctermbg=LightGrey ctermfg=Black guibg=Grey",
- "PmenuThumb ctermbg=Black guibg=Black",
- "Question ctermfg=DarkGreen gui=bold guifg=SeaGreen",
- "Search ctermbg=Yellow ctermfg=NONE guibg=Yellow guifg=NONE",
- "SignColumn ctermbg=Grey ctermfg=DarkBlue guibg=Grey guifg=DarkBlue",
- "SpecialKey ctermfg=DarkBlue guifg=Blue",
- "SpellBad ctermbg=LightRed guisp=Red gui=undercurl",
- "SpellCap ctermbg=LightBlue guisp=Blue gui=undercurl",
- "SpellLocal ctermbg=Cyan guisp=DarkCyan gui=undercurl",
- "SpellRare ctermbg=LightMagenta guisp=Magenta gui=undercurl",
- "TabLine cterm=underline ctermfg=black ctermbg=LightGrey gui=underline guibg=LightGrey",
- "Title ctermfg=DarkMagenta gui=bold guifg=Magenta",
- "Visual guibg=LightGrey",
- "WarningMsg ctermfg=DarkRed guifg=Red",
- "Comment term=bold cterm=NONE ctermfg=DarkBlue ctermbg=NONE gui=NONE guifg=Blue guibg=NONE",
- "Constant term=underline cterm=NONE ctermfg=DarkRed ctermbg=NONE gui=NONE guifg=Magenta guibg=NONE",
- "Special term=bold cterm=NONE ctermfg=DarkMagenta ctermbg=NONE gui=NONE guifg=#6a5acd guibg=NONE",
- "Identifier term=underline cterm=NONE ctermfg=DarkCyan ctermbg=NONE gui=NONE guifg=DarkCyan guibg=NONE",
- "Statement term=bold cterm=NONE ctermfg=Brown ctermbg=NONE gui=bold guifg=Brown guibg=NONE",
- "PreProc term=underline cterm=NONE ctermfg=DarkMagenta ctermbg=NONE gui=NONE guifg=#6a0dad guibg=NONE",
- "Type term=underline cterm=NONE ctermfg=DarkGreen ctermbg=NONE gui=bold guifg=SeaGreen guibg=NONE",
- "Underlined term=underline cterm=underline ctermfg=DarkMagenta gui=underline guifg=SlateBlue",
- "Ignore term=NONE cterm=NONE ctermfg=white ctermbg=NONE gui=NONE guifg=bg guibg=NONE",
- NULL
-};
-
-// Default colors only used with a dark background.
-static const char *highlight_init_dark[] = {
- "ColorColumn ctermbg=DarkRed guibg=DarkRed",
- "CursorColumn ctermbg=DarkGrey guibg=Grey40",
- "CursorLine cterm=underline guibg=Grey40",
- "CursorLineNr cterm=underline ctermfg=Yellow gui=bold guifg=Yellow",
- "DiffAdd ctermbg=DarkBlue guibg=DarkBlue",
- "DiffChange ctermbg=DarkMagenta guibg=DarkMagenta",
- "DiffDelete ctermfg=Blue ctermbg=DarkCyan gui=bold guifg=Blue guibg=DarkCyan",
- "Directory ctermfg=LightCyan guifg=Cyan",
- "FoldColumn ctermbg=DarkGrey ctermfg=Cyan guibg=Grey guifg=Cyan",
- "Folded ctermbg=DarkGrey ctermfg=Cyan guibg=DarkGrey guifg=Cyan",
- "LineNr ctermfg=Yellow guifg=Yellow",
- "MatchParen ctermbg=DarkCyan guibg=DarkCyan",
- "MoreMsg ctermfg=LightGreen gui=bold guifg=SeaGreen",
- "Pmenu ctermbg=Magenta ctermfg=Black guibg=Magenta",
- "PmenuSel ctermbg=Black ctermfg=DarkGrey guibg=DarkGrey",
- "PmenuThumb ctermbg=White guibg=White",
- "Question ctermfg=LightGreen gui=bold guifg=Green",
- "Search ctermbg=Yellow ctermfg=Black guibg=Yellow guifg=Black",
- "SignColumn ctermbg=DarkGrey ctermfg=Cyan guibg=Grey guifg=Cyan",
- "SpecialKey ctermfg=LightBlue guifg=Cyan",
- "SpellBad ctermbg=Red guisp=Red gui=undercurl",
- "SpellCap ctermbg=Blue guisp=Blue gui=undercurl",
- "SpellLocal ctermbg=Cyan guisp=Cyan gui=undercurl",
- "SpellRare ctermbg=Magenta guisp=Magenta gui=undercurl",
- "TabLine cterm=underline ctermfg=white ctermbg=DarkGrey gui=underline guibg=DarkGrey",
- "Title ctermfg=LightMagenta gui=bold guifg=Magenta",
- "Visual guibg=DarkGrey",
- "WarningMsg ctermfg=LightRed guifg=Red",
- "Comment term=bold cterm=NONE ctermfg=Cyan ctermbg=NONE gui=NONE guifg=#80a0ff guibg=NONE",
- "Constant term=underline cterm=NONE ctermfg=Magenta ctermbg=NONE gui=NONE guifg=#ffa0a0 guibg=NONE",
- "Special term=bold cterm=NONE ctermfg=LightRed ctermbg=NONE gui=NONE guifg=Orange guibg=NONE",
- "Identifier term=underline cterm=bold ctermfg=Cyan ctermbg=NONE gui=NONE guifg=#40ffff guibg=NONE",
- "Statement term=bold cterm=NONE ctermfg=Yellow ctermbg=NONE gui=bold guifg=#ffff60 guibg=NONE",
- "PreProc term=underline cterm=NONE ctermfg=LightBlue ctermbg=NONE gui=NONE guifg=#ff80ff guibg=NONE",
- "Type term=underline cterm=NONE ctermfg=LightGreen ctermbg=NONE gui=bold guifg=#60ff60 guibg=NONE",
- "Underlined term=underline cterm=underline ctermfg=LightBlue gui=underline guifg=#80a0ff",
- "Ignore term=NONE cterm=NONE ctermfg=black ctermbg=NONE gui=NONE guifg=bg guibg=NONE",
- NULL
-};
-
-const char *const highlight_init_cmdline[] = {
- // XXX When modifying a list modify it in both valid and invalid halves.
- // TODO(ZyX-I): merge valid and invalid groups via a macros.
-
- // NvimInternalError should appear only when highlighter has a bug.
- "NvimInternalError ctermfg=Red ctermbg=Red guifg=Red guibg=Red",
-
- // Highlight groups (links) used by parser:
-
- "default link NvimAssignment Operator",
- "default link NvimPlainAssignment NvimAssignment",
- "default link NvimAugmentedAssignment NvimAssignment",
- "default link NvimAssignmentWithAddition NvimAugmentedAssignment",
- "default link NvimAssignmentWithSubtraction NvimAugmentedAssignment",
- "default link NvimAssignmentWithConcatenation NvimAugmentedAssignment",
-
- "default link NvimOperator Operator",
-
- "default link NvimUnaryOperator NvimOperator",
- "default link NvimUnaryPlus NvimUnaryOperator",
- "default link NvimUnaryMinus NvimUnaryOperator",
- "default link NvimNot NvimUnaryOperator",
-
- "default link NvimBinaryOperator NvimOperator",
- "default link NvimComparison NvimBinaryOperator",
- "default link NvimComparisonModifier NvimComparison",
- "default link NvimBinaryPlus NvimBinaryOperator",
- "default link NvimBinaryMinus NvimBinaryOperator",
- "default link NvimConcat NvimBinaryOperator",
- "default link NvimConcatOrSubscript NvimConcat",
- "default link NvimOr NvimBinaryOperator",
- "default link NvimAnd NvimBinaryOperator",
- "default link NvimMultiplication NvimBinaryOperator",
- "default link NvimDivision NvimBinaryOperator",
- "default link NvimMod NvimBinaryOperator",
-
- "default link NvimTernary NvimOperator",
- "default link NvimTernaryColon NvimTernary",
-
- "default link NvimParenthesis Delimiter",
- "default link NvimLambda NvimParenthesis",
- "default link NvimNestingParenthesis NvimParenthesis",
- "default link NvimCallingParenthesis NvimParenthesis",
-
- "default link NvimSubscript NvimParenthesis",
- "default link NvimSubscriptBracket NvimSubscript",
- "default link NvimSubscriptColon NvimSubscript",
- "default link NvimCurly NvimSubscript",
-
- "default link NvimContainer NvimParenthesis",
- "default link NvimDict NvimContainer",
- "default link NvimList NvimContainer",
-
- "default link NvimIdentifier Identifier",
- "default link NvimIdentifierScope NvimIdentifier",
- "default link NvimIdentifierScopeDelimiter NvimIdentifier",
- "default link NvimIdentifierName NvimIdentifier",
- "default link NvimIdentifierKey NvimIdentifier",
-
- "default link NvimColon Delimiter",
- "default link NvimComma Delimiter",
- "default link NvimArrow Delimiter",
-
- "default link NvimRegister SpecialChar",
- "default link NvimNumber Number",
- "default link NvimFloat NvimNumber",
- "default link NvimNumberPrefix Type",
-
- "default link NvimOptionSigil Type",
- "default link NvimOptionName NvimIdentifier",
- "default link NvimOptionScope NvimIdentifierScope",
- "default link NvimOptionScopeDelimiter NvimIdentifierScopeDelimiter",
-
- "default link NvimEnvironmentSigil NvimOptionSigil",
- "default link NvimEnvironmentName NvimIdentifier",
-
- "default link NvimString String",
- "default link NvimStringBody NvimString",
- "default link NvimStringQuote NvimString",
- "default link NvimStringSpecial SpecialChar",
-
- "default link NvimSingleQuote NvimStringQuote",
- "default link NvimSingleQuotedBody NvimStringBody",
- "default link NvimSingleQuotedQuote NvimStringSpecial",
-
- "default link NvimDoubleQuote NvimStringQuote",
- "default link NvimDoubleQuotedBody NvimStringBody",
- "default link NvimDoubleQuotedEscape NvimStringSpecial",
-
- "default link NvimFigureBrace NvimInternalError",
- "default link NvimSingleQuotedUnknownEscape NvimInternalError",
-
- "default link NvimSpacing Normal",
-
- // NvimInvalid groups:
-
- "default link NvimInvalidSingleQuotedUnknownEscape NvimInternalError",
-
- "default link NvimInvalid Error",
-
- "default link NvimInvalidAssignment NvimInvalid",
- "default link NvimInvalidPlainAssignment NvimInvalidAssignment",
- "default link NvimInvalidAugmentedAssignment NvimInvalidAssignment",
- "default link NvimInvalidAssignmentWithAddition NvimInvalidAugmentedAssignment",
- "default link NvimInvalidAssignmentWithSubtraction NvimInvalidAugmentedAssignment",
- "default link NvimInvalidAssignmentWithConcatenation NvimInvalidAugmentedAssignment",
-
- "default link NvimInvalidOperator NvimInvalid",
-
- "default link NvimInvalidUnaryOperator NvimInvalidOperator",
- "default link NvimInvalidUnaryPlus NvimInvalidUnaryOperator",
- "default link NvimInvalidUnaryMinus NvimInvalidUnaryOperator",
- "default link NvimInvalidNot NvimInvalidUnaryOperator",
-
- "default link NvimInvalidBinaryOperator NvimInvalidOperator",
- "default link NvimInvalidComparison NvimInvalidBinaryOperator",
- "default link NvimInvalidComparisonModifier NvimInvalidComparison",
- "default link NvimInvalidBinaryPlus NvimInvalidBinaryOperator",
- "default link NvimInvalidBinaryMinus NvimInvalidBinaryOperator",
- "default link NvimInvalidConcat NvimInvalidBinaryOperator",
- "default link NvimInvalidConcatOrSubscript NvimInvalidConcat",
- "default link NvimInvalidOr NvimInvalidBinaryOperator",
- "default link NvimInvalidAnd NvimInvalidBinaryOperator",
- "default link NvimInvalidMultiplication NvimInvalidBinaryOperator",
- "default link NvimInvalidDivision NvimInvalidBinaryOperator",
- "default link NvimInvalidMod NvimInvalidBinaryOperator",
-
- "default link NvimInvalidTernary NvimInvalidOperator",
- "default link NvimInvalidTernaryColon NvimInvalidTernary",
-
- "default link NvimInvalidDelimiter NvimInvalid",
-
- "default link NvimInvalidParenthesis NvimInvalidDelimiter",
- "default link NvimInvalidLambda NvimInvalidParenthesis",
- "default link NvimInvalidNestingParenthesis NvimInvalidParenthesis",
- "default link NvimInvalidCallingParenthesis NvimInvalidParenthesis",
-
- "default link NvimInvalidSubscript NvimInvalidParenthesis",
- "default link NvimInvalidSubscriptBracket NvimInvalidSubscript",
- "default link NvimInvalidSubscriptColon NvimInvalidSubscript",
- "default link NvimInvalidCurly NvimInvalidSubscript",
-
- "default link NvimInvalidContainer NvimInvalidParenthesis",
- "default link NvimInvalidDict NvimInvalidContainer",
- "default link NvimInvalidList NvimInvalidContainer",
-
- "default link NvimInvalidValue NvimInvalid",
-
- "default link NvimInvalidIdentifier NvimInvalidValue",
- "default link NvimInvalidIdentifierScope NvimInvalidIdentifier",
- "default link NvimInvalidIdentifierScopeDelimiter NvimInvalidIdentifier",
- "default link NvimInvalidIdentifierName NvimInvalidIdentifier",
- "default link NvimInvalidIdentifierKey NvimInvalidIdentifier",
-
- "default link NvimInvalidColon NvimInvalidDelimiter",
- "default link NvimInvalidComma NvimInvalidDelimiter",
- "default link NvimInvalidArrow NvimInvalidDelimiter",
-
- "default link NvimInvalidRegister NvimInvalidValue",
- "default link NvimInvalidNumber NvimInvalidValue",
- "default link NvimInvalidFloat NvimInvalidNumber",
- "default link NvimInvalidNumberPrefix NvimInvalidNumber",
-
- "default link NvimInvalidOptionSigil NvimInvalidIdentifier",
- "default link NvimInvalidOptionName NvimInvalidIdentifier",
- "default link NvimInvalidOptionScope NvimInvalidIdentifierScope",
- "default link NvimInvalidOptionScopeDelimiter "
- "NvimInvalidIdentifierScopeDelimiter",
-
- "default link NvimInvalidEnvironmentSigil NvimInvalidOptionSigil",
- "default link NvimInvalidEnvironmentName NvimInvalidIdentifier",
-
- // Invalid string bodies and specials are still highlighted as valid ones to
- // minimize the red area.
- "default link NvimInvalidString NvimInvalidValue",
- "default link NvimInvalidStringBody NvimStringBody",
- "default link NvimInvalidStringQuote NvimInvalidString",
- "default link NvimInvalidStringSpecial NvimStringSpecial",
-
- "default link NvimInvalidSingleQuote NvimInvalidStringQuote",
- "default link NvimInvalidSingleQuotedBody NvimInvalidStringBody",
- "default link NvimInvalidSingleQuotedQuote NvimInvalidStringSpecial",
-
- "default link NvimInvalidDoubleQuote NvimInvalidStringQuote",
- "default link NvimInvalidDoubleQuotedBody NvimInvalidStringBody",
- "default link NvimInvalidDoubleQuotedEscape NvimInvalidStringSpecial",
- "default link NvimInvalidDoubleQuotedUnknownEscape NvimInvalidValue",
-
- "default link NvimInvalidFigureBrace NvimInvalidDelimiter",
-
- "default link NvimInvalidSpacing ErrorMsg",
-
- // Not actually invalid, but we highlight user that he is doing something
- // wrong.
- "default link NvimDoubleQuotedUnknownEscape NvimInvalidValue",
- NULL,
-};
-
-/// Create default links for Nvim* highlight groups used for cmdline coloring
-void syn_init_cmdline_highlight(bool reset, bool init)
-{
- for (size_t i = 0; highlight_init_cmdline[i] != NULL; i++) {
- do_highlight(highlight_init_cmdline[i], reset, init);
- }
-}
-
-/// Load colors from a file if "g:colors_name" is set, otherwise load builtin
-/// colors
-///
-/// @param both include groups where 'bg' doesn't matter
-/// @param reset clear groups first
-void init_highlight(bool both, bool reset)
-{
- static int had_both = false;
-
- // Try finding the color scheme file. Used when a color file was loaded
- // and 'background' or 't_Co' is changed.
- char_u *p = get_var_value("g:colors_name");
- if (p != NULL) {
- // Value of g:colors_name could be freed in load_colors() and make
- // p invalid, so copy it.
- char_u *copy_p = vim_strsave(p);
- bool okay = load_colors(copy_p);
- xfree(copy_p);
- if (okay) {
- return;
- }
- }
-
- /*
- * Didn't use a color file, use the compiled-in colors.
- */
- if (both) {
- had_both = true;
- const char *const *const pp = highlight_init_both;
- for (size_t i = 0; pp[i] != NULL; i++) {
- do_highlight(pp[i], reset, true);
- }
- } else if (!had_both) {
- // Don't do anything before the call with both == true from main().
- // Not everything has been setup then, and that call will overrule
- // everything anyway.
- return;
- }
-
- const char *const *const pp = ((*p_bg == 'l')
- ? highlight_init_light
- : highlight_init_dark);
- for (size_t i = 0; pp[i] != NULL; i++) {
- do_highlight(pp[i], reset, true);
- }
-
- /* Reverse looks ugly, but grey may not work for 8 colors. Thus let it
- * depend on the number of colors available.
- * With 8 colors brown is equal to yellow, need to use black for Search fg
- * to avoid Statement highlighted text disappears.
- * Clear the attributes, needed when changing the t_Co value. */
- if (t_colors > 8) {
- do_highlight((*p_bg == 'l'
- ? "Visual cterm=NONE ctermbg=LightGrey"
- : "Visual cterm=NONE ctermbg=DarkGrey"), false, true);
- } else {
- do_highlight("Visual cterm=reverse ctermbg=NONE", false, true);
- if (*p_bg == 'l') {
- do_highlight("Search ctermfg=black", false, true);
- }
- }
-
- syn_init_cmdline_highlight(false, false);
-}
-
-/*
- * Load color file "name".
- * Return OK for success, FAIL for failure.
- */
-int load_colors(char_u *name)
-{
- char_u *buf;
- int retval = FAIL;
- static bool recursive = false;
-
- // When being called recursively, this is probably because setting
- // 'background' caused the highlighting to be reloaded. This means it is
- // working, thus we should return OK.
- if (recursive) {
- return OK;
- }
-
- recursive = true;
- size_t buflen = STRLEN(name) + 12;
- buf = xmalloc(buflen);
- apply_autocmds(EVENT_COLORSCHEMEPRE, name, curbuf->b_fname, false, curbuf);
- snprintf((char *)buf, buflen, "colors/%s.vim", name);
- retval = source_runtime((char *)buf, DIP_START + DIP_OPT);
- if (retval == FAIL) {
- snprintf((char *)buf, buflen, "colors/%s.lua", name);
- retval = source_runtime((char *)buf, DIP_START + DIP_OPT);
- }
- xfree(buf);
- apply_autocmds(EVENT_COLORSCHEME, name, curbuf->b_fname, false, curbuf);
-
- recursive = false;
-
- return retval;
-}
-
-static char *(color_names[28]) = {
- "Black", "DarkBlue", "DarkGreen", "DarkCyan",
- "DarkRed", "DarkMagenta", "Brown", "DarkYellow",
- "Gray", "Grey", "LightGray", "LightGrey",
- "DarkGray", "DarkGrey",
- "Blue", "LightBlue", "Green", "LightGreen",
- "Cyan", "LightCyan", "Red", "LightRed", "Magenta",
- "LightMagenta", "Yellow", "LightYellow", "White", "NONE"
-};
-// indices:
-// 0, 1, 2, 3,
-// 4, 5, 6, 7,
-// 8, 9, 10, 11,
-// 12, 13,
-// 14, 15, 16, 17,
-// 18, 19, 20, 21, 22,
-// 23, 24, 25, 26, 27
-static int color_numbers_16[28] = { 0, 1, 2, 3,
- 4, 5, 6, 6,
- 7, 7, 7, 7,
- 8, 8,
- 9, 9, 10, 10,
- 11, 11, 12, 12, 13,
- 13, 14, 14, 15, -1 };
-// for xterm with 88 colors...
-static int color_numbers_88[28] = { 0, 4, 2, 6,
- 1, 5, 32, 72,
- 84, 84, 7, 7,
- 82, 82,
- 12, 43, 10, 61,
- 14, 63, 9, 74, 13,
- 75, 11, 78, 15, -1 };
-// for xterm with 256 colors...
-static int color_numbers_256[28] = { 0, 4, 2, 6,
- 1, 5, 130, 3,
- 248, 248, 7, 7,
- 242, 242,
- 12, 81, 10, 121,
- 14, 159, 9, 224, 13,
- 225, 11, 229, 15, -1 };
-// for terminals with less than 16 colors...
-static int color_numbers_8[28] = { 0, 4, 2, 6,
- 1, 5, 3, 3,
- 7, 7, 7, 7,
- 0+8, 0+8,
- 4+8, 4+8, 2+8, 2+8,
- 6+8, 6+8, 1+8, 1+8, 5+8,
- 5+8, 3+8, 3+8, 7+8, -1 };
-
-// Lookup the "cterm" value to be used for color with index "idx" in
-// color_names[].
-// "boldp" will be set to TRUE or FALSE for a foreground color when using 8
-// colors, otherwise it will be unchanged.
-int lookup_color(const int idx, const bool foreground, TriState *const boldp)
-{
- int color = color_numbers_16[idx];
-
- // Use the _16 table to check if it's a valid color name.
- if (color < 0) {
- return -1;
- }
-
- if (t_colors == 8) {
- // t_Co is 8: use the 8 colors table
- color = color_numbers_8[idx];
- if (foreground) {
- // set/reset bold attribute to get light foreground
- // colors (on some terminals, e.g. "linux")
- if (color & 8) {
- *boldp = kTrue;
- } else {
- *boldp = kFalse;
- }
- }
- color &= 7; // truncate to 8 colors
- } else if (t_colors == 16) {
- color = color_numbers_8[idx];
- } else if (t_colors == 88) {
- color = color_numbers_88[idx];
- } else if (t_colors >= 256) {
- color = color_numbers_256[idx];
- }
- return color;
-}
-
-void set_hl_group(int id, HlAttrs attrs, Dict(highlight) *dict, int link_id)
-{
- int idx = id - 1; // Index is ID minus one.
-
- bool is_default = attrs.rgb_ae_attr & HL_DEFAULT;
-
- // Return if "default" was used and the group already has settings
- if (is_default && hl_has_settings(idx, true)) {
- return;
- }
-
- HlGroup *g = &HL_TABLE()[idx];
-
- if (link_id > 0) {
- g->sg_cleared = false;
- g->sg_link = link_id;
- g->sg_script_ctx = current_sctx;
- g->sg_script_ctx.sc_lnum += sourcing_lnum;
- g->sg_set |= SG_LINK;
- if (is_default) {
- g->sg_deflink = link_id;
- g->sg_deflink_sctx = current_sctx;
- g->sg_deflink_sctx.sc_lnum += sourcing_lnum;
- }
- return;
- }
-
- g->sg_cleared = false;
- g->sg_link = 0;
- g->sg_gui = attrs.rgb_ae_attr;
-
- g->sg_rgb_fg = attrs.rgb_fg_color;
- g->sg_rgb_bg = attrs.rgb_bg_color;
- g->sg_rgb_sp = attrs.rgb_sp_color;
-
- struct {
- char **dest; RgbValue val; Object name;
- } cattrs[] = {
- { &g->sg_rgb_fg_name, g->sg_rgb_fg, HAS_KEY(dict->fg) ? dict->fg : dict->foreground },
- { &g->sg_rgb_bg_name, g->sg_rgb_bg, HAS_KEY(dict->bg) ? dict->bg : dict->background },
- { &g->sg_rgb_sp_name, g->sg_rgb_sp, HAS_KEY(dict->sp) ? dict->sp : dict->special },
- { NULL, -1, NIL },
- };
-
- char hex_name[8];
- char *name;
-
- for (int j = 0; cattrs[j].dest; j++) {
- if (cattrs[j].val < 0) {
- XFREE_CLEAR(*cattrs[j].dest);
- continue;
- }
-
- if (cattrs[j].name.type == kObjectTypeString && cattrs[j].name.data.string.size) {
- name = cattrs[j].name.data.string.data;
- } else {
- snprintf(hex_name, sizeof(hex_name), "#%06x", cattrs[j].val);
- name = hex_name;
- }
-
- if (!*cattrs[j].dest
- || STRCMP(*cattrs[j].dest, name) != 0) {
- xfree(*cattrs[j].dest);
- *cattrs[j].dest = xstrdup(name);
- }
- }
-
- g->sg_cterm = attrs.cterm_ae_attr;
- g->sg_cterm_bg = attrs.cterm_bg_color;
- g->sg_cterm_fg = attrs.cterm_fg_color;
- g->sg_cterm_bold = g->sg_cterm & HL_BOLD;
- g->sg_blend = attrs.hl_blend;
-
- g->sg_script_ctx = current_sctx;
- g->sg_script_ctx.sc_lnum += sourcing_lnum;
-
- // 'Normal' is special
- if (STRCMP(g->sg_name_u, "NORMAL") == 0) {
- cterm_normal_fg_color = g->sg_cterm_fg;
- cterm_normal_bg_color = g->sg_cterm_bg;
- normal_fg = g->sg_rgb_fg;
- normal_bg = g->sg_rgb_bg;
- normal_sp = g->sg_rgb_sp;
- ui_default_colors_set();
- } else {
- g->sg_attr = hl_get_syn_attr(0, id, attrs);
-
- // a cursor style uses this syn_id, make sure its attribute is updated.
- if (cursor_mode_uses_syn_id(id)) {
- ui_mode_info_set();
- }
- }
-}
-
-
-/// Handle ":highlight" command
-///
-/// When using ":highlight clear" this is called recursively for each group with
-/// forceit and init being both true.
-///
-/// @param[in] line Command arguments.
-/// @param[in] forceit True when bang is given, allows to link group even if
-/// it has its own settings.
-/// @param[in] init True when initializing.
-void do_highlight(const char *line, const bool forceit, const bool init)
- FUNC_ATTR_NONNULL_ALL
-{
- const char *name_end;
- const char *linep;
- const char *key_start;
- const char *arg_start;
- long i;
- int off;
- int len;
- int attr;
- int id;
- int idx;
- struct hl_group item_before;
- bool did_change = false;
- bool dodefault = false;
- bool doclear = false;
- bool dolink = false;
- bool error = false;
- int color;
- bool is_normal_group = false; // "Normal" group
- bool did_highlight_changed = false;
-
- // If no argument, list current highlighting.
- if (ends_excmd((uint8_t)(*line))) {
- for (i = 1; i <= highlight_ga.ga_len && !got_int; i++) {
- // TODO(brammool): only call when the group has attributes set
- highlight_list_one(i);
- }
- return;
- }
-
- // Isolate the name.
- name_end = (const char *)skiptowhite((const char_u *)line);
- linep = (const char *)skipwhite((const char_u *)name_end);
-
- // Check for "default" argument.
- if (strncmp(line, "default", name_end - line) == 0) {
- dodefault = true;
- line = linep;
- name_end = (const char *)skiptowhite((const char_u *)line);
- linep = (const char *)skipwhite((const char_u *)name_end);
- }
-
- // Check for "clear" or "link" argument.
- if (strncmp(line, "clear", name_end - line) == 0) {
- doclear = true;
- } else if (strncmp(line, "link", name_end - line) == 0) {
- dolink = true;
- }
-
- // ":highlight {group-name}": list highlighting for one group.
- if (!doclear && !dolink && ends_excmd((uint8_t)(*linep))) {
- id = syn_name2id_len((const char_u *)line, (int)(name_end - line));
- if (id == 0) {
- semsg(_("E411: highlight group not found: %s"), line);
- } else {
- highlight_list_one(id);
- }
- return;
- }
-
- // Handle ":highlight link {from} {to}" command.
- if (dolink) {
- const char *from_start = linep;
- const char *from_end;
- const char *to_start;
- const char *to_end;
- int from_id;
- int to_id;
- struct hl_group *hlgroup = NULL;
-
- from_end = (const char *)skiptowhite((const char_u *)from_start);
- to_start = (const char *)skipwhite((const char_u *)from_end);
- to_end = (const char *)skiptowhite((const char_u *)to_start);
-
- if (ends_excmd((uint8_t)(*from_start))
- || ends_excmd((uint8_t)(*to_start))) {
- semsg(_("E412: Not enough arguments: \":highlight link %s\""),
- from_start);
- return;
- }
-
- if (!ends_excmd(*skipwhite((const char_u *)to_end))) {
- semsg(_("E413: Too many arguments: \":highlight link %s\""), from_start);
- return;
- }
-
- from_id = syn_check_group(from_start, (int)(from_end - from_start));
- if (strncmp(to_start, "NONE", 4) == 0) {
- to_id = 0;
- } else {
- to_id = syn_check_group(to_start, (int)(to_end - to_start));
- }
-
- if (from_id > 0) {
- hlgroup = &HL_TABLE()[from_id - 1];
- if (dodefault && (forceit || hlgroup->sg_deflink == 0)) {
- hlgroup->sg_deflink = to_id;
- hlgroup->sg_deflink_sctx = current_sctx;
- hlgroup->sg_deflink_sctx.sc_lnum += sourcing_lnum;
- nlua_set_sctx(&hlgroup->sg_deflink_sctx);
- }
- }
-
- if (from_id > 0 && (!init || hlgroup->sg_set == 0)) {
- // Don't allow a link when there already is some highlighting
- // for the group, unless '!' is used
- if (to_id > 0 && !forceit && !init
- && hl_has_settings(from_id - 1, dodefault)) {
- if (sourcing_name == NULL && !dodefault) {
- emsg(_("E414: group has settings, highlight link ignored"));
- }
- } else if (hlgroup->sg_link != to_id
- || hlgroup->sg_script_ctx.sc_sid != current_sctx.sc_sid
- || hlgroup->sg_cleared) {
- if (!init) {
- hlgroup->sg_set |= SG_LINK;
- }
- hlgroup->sg_link = to_id;
- hlgroup->sg_script_ctx = current_sctx;
- hlgroup->sg_script_ctx.sc_lnum += sourcing_lnum;
- nlua_set_sctx(&hlgroup->sg_script_ctx);
- hlgroup->sg_cleared = false;
- redraw_all_later(SOME_VALID);
-
- // Only call highlight changed() once after multiple changes
- need_highlight_changed = true;
- }
- }
-
- return;
- }
-
- if (doclear) {
- // ":highlight clear [group]" command.
- line = linep;
- if (ends_excmd((uint8_t)(*line))) {
- do_unlet(S_LEN("colors_name"), true);
- restore_cterm_colors();
-
- // Clear all default highlight groups and load the defaults.
- for (int j = 0; j < highlight_ga.ga_len; j++) {
- highlight_clear(j);
- }
- init_highlight(true, true);
- highlight_changed();
- redraw_all_later(NOT_VALID);
- return;
- }
- name_end = (const char *)skiptowhite((const char_u *)line);
- linep = (const char *)skipwhite((const char_u *)name_end);
- }
-
- // Find the group name in the table. If it does not exist yet, add it.
- id = syn_check_group(line, (int)(name_end - line));
- if (id == 0) { // Failed (out of memory).
- return;
- }
- idx = id - 1; // Index is ID minus one.
-
- // Return if "default" was used and the group already has settings
- if (dodefault && hl_has_settings(idx, true)) {
- return;
- }
-
- // Make a copy so we can check if any attribute actually changed
- item_before = HL_TABLE()[idx];
- is_normal_group = (STRCMP(HL_TABLE()[idx].sg_name_u, "NORMAL") == 0);
-
- // Clear the highlighting for ":hi clear {group}" and ":hi clear".
- if (doclear || (forceit && init)) {
- highlight_clear(idx);
- if (!doclear) {
- HL_TABLE()[idx].sg_set = 0;
- }
- }
-
- char *key = NULL;
- char *arg = NULL;
- if (!doclear) {
- while (!ends_excmd((uint8_t)(*linep))) {
- key_start = linep;
- if (*linep == '=') {
- semsg(_("E415: unexpected equal sign: %s"), key_start);
- error = true;
- break;
- }
-
- // Isolate the key ("term", "ctermfg", "ctermbg", "font", "guifg",
- // "guibg" or "guisp").
- while (*linep && !ascii_iswhite(*linep) && *linep != '=') {
- linep++;
- }
- xfree(key);
- key = (char *)vim_strnsave_up((const char_u *)key_start,
- linep - key_start);
- linep = (const char *)skipwhite((const char_u *)linep);
-
- if (strcmp(key, "NONE") == 0) {
- if (!init || HL_TABLE()[idx].sg_set == 0) {
- if (!init) {
- HL_TABLE()[idx].sg_set |= SG_CTERM+SG_GUI;
- }
- highlight_clear(idx);
- }
- continue;
- }
-
- // Check for the equal sign.
- if (*linep != '=') {
- semsg(_("E416: missing equal sign: %s"), key_start);
- error = true;
- break;
- }
- linep++;
-
- // Isolate the argument.
- linep = (const char *)skipwhite((const char_u *)linep);
- if (*linep == '\'') { // guifg='color name'
- arg_start = ++linep;
- linep = strchr(linep, '\'');
- if (linep == NULL) {
- semsg(_(e_invarg2), key_start);
- error = true;
- break;
- }
- } else {
- arg_start = linep;
- linep = (const char *)skiptowhite((const char_u *)linep);
- }
- if (linep == arg_start) {
- semsg(_("E417: missing argument: %s"), key_start);
- error = true;
- break;
- }
- xfree(arg);
- arg = xstrndup(arg_start, (size_t)(linep - arg_start));
-
- if (*linep == '\'') {
- linep++;
- }
-
- // Store the argument.
- if (strcmp(key, "TERM") == 0
- || strcmp(key, "CTERM") == 0
- || strcmp(key, "GUI") == 0) {
- attr = 0;
- off = 0;
- while (arg[off] != NUL) {
- for (i = ARRAY_SIZE(hl_attr_table); --i >= 0;) {
- len = (int)STRLEN(hl_name_table[i]);
- if (STRNICMP(arg + off, hl_name_table[i], len) == 0) {
- attr |= hl_attr_table[i];
- off += len;
- break;
- }
- }
- if (i < 0) {
- semsg(_("E418: Illegal value: %s"), arg);
- error = true;
- break;
- }
- if (arg[off] == ',') { // Another one follows.
- off++;
- }
- }
- if (error) {
- break;
- }
- if (*key == 'C') {
- if (!init || !(HL_TABLE()[idx].sg_set & SG_CTERM)) {
- if (!init) {
- HL_TABLE()[idx].sg_set |= SG_CTERM;
- }
- HL_TABLE()[idx].sg_cterm = attr;
- HL_TABLE()[idx].sg_cterm_bold = false;
- }
- } else if (*key == 'G') {
- if (!init || !(HL_TABLE()[idx].sg_set & SG_GUI)) {
- if (!init) {
- HL_TABLE()[idx].sg_set |= SG_GUI;
- }
- HL_TABLE()[idx].sg_gui = attr;
- }
- }
- } else if (STRCMP(key, "FONT") == 0) {
- // in non-GUI fonts are simply ignored
- } else if (STRCMP(key, "CTERMFG") == 0 || STRCMP(key, "CTERMBG") == 0) {
- if (!init || !(HL_TABLE()[idx].sg_set & SG_CTERM)) {
- if (!init) {
- HL_TABLE()[idx].sg_set |= SG_CTERM;
- }
-
- /* When setting the foreground color, and previously the "bold"
- * flag was set for a light color, reset it now */
- if (key[5] == 'F' && HL_TABLE()[idx].sg_cterm_bold) {
- HL_TABLE()[idx].sg_cterm &= ~HL_BOLD;
- HL_TABLE()[idx].sg_cterm_bold = false;
- }
-
- if (ascii_isdigit(*arg)) {
- color = atoi(arg);
- } else if (STRICMP(arg, "fg") == 0) {
- if (cterm_normal_fg_color) {
- color = cterm_normal_fg_color - 1;
- } else {
- emsg(_("E419: FG color unknown"));
- error = true;
- break;
- }
- } else if (STRICMP(arg, "bg") == 0) {
- if (cterm_normal_bg_color > 0) {
- color = cterm_normal_bg_color - 1;
- } else {
- emsg(_("E420: BG color unknown"));
- error = true;
- break;
- }
- } else {
- // Reduce calls to STRICMP a bit, it can be slow.
- off = TOUPPER_ASC(*arg);
- for (i = ARRAY_SIZE(color_names); --i >= 0;) {
- if (off == color_names[i][0]
- && STRICMP(arg + 1, color_names[i] + 1) == 0) {
- break;
- }
- }
- if (i < 0) {
- semsg(_("E421: Color name or number not recognized: %s"),
- key_start);
- error = true;
- break;
- }
-
- TriState bold = kNone;
- color = lookup_color(i, key[5] == 'F', &bold);
-
- // set/reset bold attribute to get light foreground
- // colors (on some terminals, e.g. "linux")
- if (bold == kTrue) {
- HL_TABLE()[idx].sg_cterm |= HL_BOLD;
- HL_TABLE()[idx].sg_cterm_bold = true;
- } else if (bold == kFalse) {
- HL_TABLE()[idx].sg_cterm &= ~HL_BOLD;
- }
- }
- // Add one to the argument, to avoid zero. Zero is used for
- // "NONE", then "color" is -1.
- if (key[5] == 'F') {
- HL_TABLE()[idx].sg_cterm_fg = color + 1;
- if (is_normal_group) {
- cterm_normal_fg_color = color + 1;
- }
- } else {
- HL_TABLE()[idx].sg_cterm_bg = color + 1;
- if (is_normal_group) {
- cterm_normal_bg_color = color + 1;
- if (!ui_rgb_attached()) {
- if (color >= 0) {
- int dark = -1;
-
- if (t_colors < 16) {
- dark = (color == 0 || color == 4);
- } else if (color < 16) {
- // Limit the heuristic to the standard 16 colors
- dark = (color < 7 || color == 8);
- }
- // Set the 'background' option if the value is
- // wrong.
- if (dark != -1
- && dark != (*p_bg == 'd')
- && !option_was_set("bg")) {
- set_option_value("bg", 0L, (dark ? "dark" : "light"), 0);
- reset_option_was_set("bg");
- }
- }
- }
- }
- }
- }
- } else if (strcmp(key, "GUIFG") == 0) {
- char **namep = &HL_TABLE()[idx].sg_rgb_fg_name;
-
- if (!init || !(HL_TABLE()[idx].sg_set & SG_GUI)) {
- if (!init) {
- HL_TABLE()[idx].sg_set |= SG_GUI;
- }
-
- if (*namep == NULL || STRCMP(*namep, arg) != 0) {
- xfree(*namep);
- if (strcmp(arg, "NONE") != 0) {
- *namep = xstrdup(arg);
- HL_TABLE()[idx].sg_rgb_fg = name_to_color(arg);
- } else {
- *namep = NULL;
- HL_TABLE()[idx].sg_rgb_fg = -1;
- }
- did_change = true;
- }
- }
-
- if (is_normal_group) {
- normal_fg = HL_TABLE()[idx].sg_rgb_fg;
- }
- } else if (STRCMP(key, "GUIBG") == 0) {
- char **const namep = &HL_TABLE()[idx].sg_rgb_bg_name;
-
- if (!init || !(HL_TABLE()[idx].sg_set & SG_GUI)) {
- if (!init) {
- HL_TABLE()[idx].sg_set |= SG_GUI;
- }
-
- if (*namep == NULL || STRCMP(*namep, arg) != 0) {
- xfree(*namep);
- if (STRCMP(arg, "NONE") != 0) {
- *namep = xstrdup(arg);
- HL_TABLE()[idx].sg_rgb_bg = name_to_color(arg);
- } else {
- *namep = NULL;
- HL_TABLE()[idx].sg_rgb_bg = -1;
- }
- did_change = true;
- }
- }
-
- if (is_normal_group) {
- normal_bg = HL_TABLE()[idx].sg_rgb_bg;
- }
- } else if (strcmp(key, "GUISP") == 0) {
- char **const namep = &HL_TABLE()[idx].sg_rgb_sp_name;
-
- if (!init || !(HL_TABLE()[idx].sg_set & SG_GUI)) {
- if (!init) {
- HL_TABLE()[idx].sg_set |= SG_GUI;
- }
-
- if (*namep == NULL || STRCMP(*namep, arg) != 0) {
- xfree(*namep);
- if (strcmp(arg, "NONE") != 0) {
- *namep = xstrdup(arg);
- HL_TABLE()[idx].sg_rgb_sp = name_to_color(arg);
- } else {
- *namep = NULL;
- HL_TABLE()[idx].sg_rgb_sp = -1;
- }
- did_change = true;
- }
- }
-
- if (is_normal_group) {
- normal_sp = HL_TABLE()[idx].sg_rgb_sp;
- }
- } else if (strcmp(key, "START") == 0 || strcmp(key, "STOP") == 0) {
- // Ignored for now
- } else if (strcmp(key, "BLEND") == 0) {
- if (strcmp(arg, "NONE") != 0) {
- HL_TABLE()[idx].sg_blend = strtol(arg, NULL, 10);
- } else {
- HL_TABLE()[idx].sg_blend = -1;
- }
- } else {
- semsg(_("E423: Illegal argument: %s"), key_start);
- error = true;
- break;
- }
- HL_TABLE()[idx].sg_cleared = false;
-
- // When highlighting has been given for a group, don't link it.
- if (!init || !(HL_TABLE()[idx].sg_set & SG_LINK)) {
- HL_TABLE()[idx].sg_link = 0;
- }
-
- // Continue with next argument.
- linep = (const char *)skipwhite((const char_u *)linep);
- }
- }
-
- // If there is an error, and it's a new entry, remove it from the table.
- if (error && idx == highlight_ga.ga_len) {
- syn_unadd_group();
- } else {
- if (!error && is_normal_group) {
- // Need to update all groups, because they might be using "bg" and/or
- // "fg", which have been changed now.
- highlight_attr_set_all();
-
- if (!ui_has(kUILinegrid) && starting == 0) {
- // Older UIs assume that we clear the screen after normal group is
- // changed
- ui_refresh();
- } else {
- // TUI and newer UIs will repaint the screen themselves. NOT_VALID
- // redraw below will still handle usages of guibg=fg etc.
- ui_default_colors_set();
- }
- did_highlight_changed = true;
- redraw_all_later(NOT_VALID);
- } else {
- set_hl_attr(idx);
- }
- HL_TABLE()[idx].sg_script_ctx = current_sctx;
- HL_TABLE()[idx].sg_script_ctx.sc_lnum += sourcing_lnum;
- nlua_set_sctx(&HL_TABLE()[idx].sg_script_ctx);
- }
- xfree(key);
- xfree(arg);
-
- // Only call highlight_changed() once, after a sequence of highlight
- // commands, and only if an attribute actually changed
- if ((did_change
- || memcmp(&HL_TABLE()[idx], &item_before, sizeof(item_before)) != 0)
- && !did_highlight_changed) {
- // Do not trigger a redraw when highlighting is changed while
- // redrawing. This may happen when evaluating 'statusline' changes the
- // StatusLine group.
- if (!updating_screen) {
- redraw_all_later(NOT_VALID);
- }
- need_highlight_changed = true;
- }
-}
-
-#if defined(EXITFREE)
-void free_highlight(void)
-{
- for (int i = 0; i < highlight_ga.ga_len; ++i) {
- highlight_clear(i);
- xfree(HL_TABLE()[i].sg_name);
- xfree(HL_TABLE()[i].sg_name_u);
- }
- ga_clear(&highlight_ga);
- map_destroy(cstr_t, int)(&highlight_unames);
-}
-
-#endif
-
-/*
- * Reset the cterm colors to what they were before Vim was started, if
- * possible. Otherwise reset them to zero.
- */
-void restore_cterm_colors(void)
-{
- normal_fg = -1;
- normal_bg = -1;
- normal_sp = -1;
- cterm_normal_fg_color = 0;
- cterm_normal_bg_color = 0;
-}
-
-/// @param check_link if true also check for an existing link.
-///
-/// @return TRUE if highlight group "idx" has any settings.
-static int hl_has_settings(int idx, bool check_link)
-{
- return HL_TABLE()[idx].sg_cleared == 0
- && (HL_TABLE()[idx].sg_attr != 0
- || HL_TABLE()[idx].sg_cterm_fg != 0
- || HL_TABLE()[idx].sg_cterm_bg != 0
- || HL_TABLE()[idx].sg_rgb_fg_name != NULL
- || HL_TABLE()[idx].sg_rgb_bg_name != NULL
- || HL_TABLE()[idx].sg_rgb_sp_name != NULL
- || (check_link && (HL_TABLE()[idx].sg_set & SG_LINK)));
-}
-
-/*
- * Clear highlighting for one group.
- */
-static void highlight_clear(int idx)
-{
- HL_TABLE()[idx].sg_cleared = true;
-
- HL_TABLE()[idx].sg_attr = 0;
- HL_TABLE()[idx].sg_cterm = 0;
- HL_TABLE()[idx].sg_cterm_bold = false;
- HL_TABLE()[idx].sg_cterm_fg = 0;
- HL_TABLE()[idx].sg_cterm_bg = 0;
- HL_TABLE()[idx].sg_gui = 0;
- HL_TABLE()[idx].sg_rgb_fg = -1;
- HL_TABLE()[idx].sg_rgb_bg = -1;
- HL_TABLE()[idx].sg_rgb_sp = -1;
- XFREE_CLEAR(HL_TABLE()[idx].sg_rgb_fg_name);
- XFREE_CLEAR(HL_TABLE()[idx].sg_rgb_bg_name);
- XFREE_CLEAR(HL_TABLE()[idx].sg_rgb_sp_name);
- HL_TABLE()[idx].sg_blend = -1;
- // Restore default link and context if they exist. Otherwise clears.
- HL_TABLE()[idx].sg_link = HL_TABLE()[idx].sg_deflink;
- // Since we set the default link, set the location to where the default
- // link was set.
- HL_TABLE()[idx].sg_script_ctx = HL_TABLE()[idx].sg_deflink_sctx;
-}
-
-
-/// \addtogroup LIST_XXX
-/// @{
-#define LIST_ATTR 1
-#define LIST_STRING 2
-#define LIST_INT 3
-/// @}
-
-static void highlight_list_one(const int id)
-{
- struct hl_group *const sgp = &HL_TABLE()[id - 1]; // index is ID minus one
- bool didh = false;
-
- if (message_filtered(sgp->sg_name)) {
- return;
- }
-
- didh = highlight_list_arg(id, didh, LIST_ATTR,
- sgp->sg_cterm, NULL, "cterm");
- didh = highlight_list_arg(id, didh, LIST_INT,
- sgp->sg_cterm_fg, NULL, "ctermfg");
- didh = highlight_list_arg(id, didh, LIST_INT,
- sgp->sg_cterm_bg, NULL, "ctermbg");
-
- didh = highlight_list_arg(id, didh, LIST_ATTR,
- sgp->sg_gui, NULL, "gui");
- didh = highlight_list_arg(id, didh, LIST_STRING,
- 0, sgp->sg_rgb_fg_name, "guifg");
- didh = highlight_list_arg(id, didh, LIST_STRING,
- 0, sgp->sg_rgb_bg_name, "guibg");
- didh = highlight_list_arg(id, didh, LIST_STRING,
- 0, sgp->sg_rgb_sp_name, "guisp");
-
- didh = highlight_list_arg(id, didh, LIST_INT,
- sgp->sg_blend+1, NULL, "blend");
-
- if (sgp->sg_link && !got_int) {
- (void)syn_list_header(didh, 0, id, true);
- didh = true;
- msg_puts_attr("links to", HL_ATTR(HLF_D));
- msg_putchar(' ');
- msg_outtrans(HL_TABLE()[HL_TABLE()[id - 1].sg_link - 1].sg_name);
- }
-
- if (!didh) {
- highlight_list_arg(id, didh, LIST_STRING, 0, "cleared", "");
- }
- if (p_verbose > 0) {
- last_set_msg(sgp->sg_script_ctx);
- }
-}
-
-Dictionary get_global_hl_defs(void)
-{
- Dictionary rv = ARRAY_DICT_INIT;
- for (int i = 1; i <= highlight_ga.ga_len && !got_int; i++) {
- Dictionary attrs = ARRAY_DICT_INIT;
- struct hl_group *h = &HL_TABLE()[i - 1];
- if (h->sg_attr > 0) {
- attrs = hlattrs2dict(syn_attr2entry(h->sg_attr), true);
- } else if (h->sg_link > 0) {
- const char *link = (const char *)HL_TABLE()[h->sg_link - 1].sg_name;
- PUT(attrs, "link", STRING_OBJ(cstr_to_string(link)));
- }
- PUT(rv, (const char *)h->sg_name, DICTIONARY_OBJ(attrs));
- }
-
- return rv;
-}
-
-/// Outputs a highlight when doing ":hi MyHighlight"
-///
-/// @param type one of \ref LIST_XXX
-/// @param iarg integer argument used if \p type == LIST_INT
-/// @param sarg string used if \p type == LIST_STRING
-static bool highlight_list_arg(const int id, bool didh, const int type, int iarg, char *const sarg,
- const char *const name)
-{
- char buf[100];
-
- if (got_int) {
- return false;
- }
- if (type == LIST_STRING ? (sarg != NULL) : (iarg != 0)) {
- char *ts = buf;
- if (type == LIST_INT) {
- snprintf((char *)buf, sizeof(buf), "%d", iarg - 1);
- } else if (type == LIST_STRING) {
- ts = sarg;
- } else { // type == LIST_ATTR
- buf[0] = NUL;
- for (int i = 0; hl_attr_table[i] != 0; i++) {
- if (iarg & hl_attr_table[i]) {
- if (buf[0] != NUL) {
- xstrlcat(buf, ",", 100);
- }
- xstrlcat(buf, hl_name_table[i], 100);
- iarg &= ~hl_attr_table[i]; // don't want "inverse"
- }
- }
- }
-
- (void)syn_list_header(didh, (int)(vim_strsize((char_u *)ts) + STRLEN(name)
- + 1), id, false);
- didh = true;
- if (!got_int) {
- if (*name != NUL) {
- msg_puts_attr(name, HL_ATTR(HLF_D));
- msg_puts_attr("=", HL_ATTR(HLF_D));
- }
- msg_outtrans((char_u *)ts);
- }
- }
- return didh;
-}
-
-/// Check whether highlight group has attribute
-///
-/// @param[in] id Highlight group to check.
-/// @param[in] flag Attribute to check.
-/// @param[in] modec 'g' for GUI, 'c' for term.
-///
-/// @return "1" if highlight group has attribute, NULL otherwise.
-const char *highlight_has_attr(const int id, const int flag, const int modec)
- FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_PURE
-{
- int attr;
-
- if (id <= 0 || id > highlight_ga.ga_len) {
- return NULL;
- }
-
- if (modec == 'g') {
- attr = HL_TABLE()[id - 1].sg_gui;
- } else {
- attr = HL_TABLE()[id - 1].sg_cterm;
- }
-
- return (attr & flag) ? "1" : NULL;
-}
-
-/// Return color name of the given highlight group
-///
-/// @param[in] id Highlight group to work with.
-/// @param[in] what What to return: one of "font", "fg", "bg", "sp", "fg#",
-/// "bg#" or "sp#".
-/// @param[in] modec 'g' for GUI, 'c' for cterm and 't' for term.
-///
-/// @return color name, possibly in a static buffer. Buffer will be overwritten
-/// on next highlight_color() call. May return NULL.
-const char *highlight_color(const int id, const char *const what, const int modec)
- FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ALL
-{
- static char name[20];
- int n;
- bool fg = false;
- bool sp = false;
- bool font = false;
-
- if (id <= 0 || id > highlight_ga.ga_len) {
- return NULL;
- }
-
- if (TOLOWER_ASC(what[0]) == 'f' && TOLOWER_ASC(what[1]) == 'g') {
- fg = true;
- } else if (TOLOWER_ASC(what[0]) == 'f' && TOLOWER_ASC(what[1]) == 'o'
- && TOLOWER_ASC(what[2]) == 'n' && TOLOWER_ASC(what[3]) == 't') {
- font = true;
- } else if (TOLOWER_ASC(what[0]) == 's' && TOLOWER_ASC(what[1]) == 'p') {
- sp = true;
- } else if (!(TOLOWER_ASC(what[0]) == 'b' && TOLOWER_ASC(what[1]) == 'g')) {
- return NULL;
- }
- if (modec == 'g') {
- if (what[2] == '#' && ui_rgb_attached()) {
- if (fg) {
- n = HL_TABLE()[id - 1].sg_rgb_fg;
- } else if (sp) {
- n = HL_TABLE()[id - 1].sg_rgb_sp;
- } else {
- n = HL_TABLE()[id - 1].sg_rgb_bg;
- }
- if (n < 0 || n > 0xffffff) {
- return NULL;
- }
- snprintf(name, sizeof(name), "#%06x", n);
- return name;
- }
- if (fg) {
- return (const char *)HL_TABLE()[id - 1].sg_rgb_fg_name;
- }
- if (sp) {
- return (const char *)HL_TABLE()[id - 1].sg_rgb_sp_name;
- }
- return (const char *)HL_TABLE()[id - 1].sg_rgb_bg_name;
- }
- if (font || sp) {
- return NULL;
- }
- if (modec == 'c') {
- if (fg) {
- n = HL_TABLE()[id - 1].sg_cterm_fg - 1;
- } else {
- n = HL_TABLE()[id - 1].sg_cterm_bg - 1;
- }
- if (n < 0) {
- return NULL;
- }
- snprintf(name, sizeof(name), "%d", n);
- return name;
- }
- // term doesn't have color.
- return NULL;
-}
-
-/// Output the syntax list header.
-///
-/// @param did_header did header already
-/// @param outlen length of string that comes
-/// @param id highlight group id
-/// @param force_newline always start a new line
-/// @return true when started a new line.
-static bool syn_list_header(const bool did_header, const int outlen, const int id,
- bool force_newline)
-{
- int endcol = 19;
- bool newline = true;
- int name_col = 0;
- bool adjust = true;
-
- if (!did_header) {
- msg_putchar('\n');
- if (got_int) {
- return true;
- }
- msg_outtrans(HL_TABLE()[id - 1].sg_name);
- name_col = msg_col;
- endcol = 15;
- } else if ((ui_has(kUIMessages) || msg_silent) && !force_newline) {
- msg_putchar(' ');
- adjust = false;
- } else if (msg_col + outlen + 1 >= Columns || force_newline) {
- msg_putchar('\n');
- if (got_int) {
- return true;
- }
- } else {
- if (msg_col >= endcol) { // wrap around is like starting a new line
- newline = false;
- }
- }
-
- if (adjust) {
- if (msg_col >= endcol) {
- // output at least one space
- endcol = msg_col + 1;
- }
-
- msg_advance(endcol);
- }
-
- // Show "xxx" with the attributes.
- if (!did_header) {
- if (endcol == Columns - 1 && endcol <= name_col) {
- msg_putchar(' ');
- }
- msg_puts_attr("xxx", syn_id2attr(id));
- msg_putchar(' ');
- }
-
- return newline;
-}
-
-/// Set the attribute numbers for a highlight group.
-/// Called after one of the attributes has changed.
-/// @param idx corrected highlight index
-static void set_hl_attr(int idx)
-{
- HlAttrs at_en = HLATTRS_INIT;
- struct hl_group *sgp = HL_TABLE() + idx;
-
- at_en.cterm_ae_attr = sgp->sg_cterm;
- at_en.cterm_fg_color = sgp->sg_cterm_fg;
- at_en.cterm_bg_color = sgp->sg_cterm_bg;
- at_en.rgb_ae_attr = sgp->sg_gui;
- // FIXME(tarruda): The "unset value" for rgb is -1, but since hlgroup is
- // initialized with 0(by garray functions), check for sg_rgb_{f,b}g_name
- // before setting attr_entry->{f,g}g_color to a other than -1
- at_en.rgb_fg_color = sgp->sg_rgb_fg_name ? sgp->sg_rgb_fg : -1;
- at_en.rgb_bg_color = sgp->sg_rgb_bg_name ? sgp->sg_rgb_bg : -1;
- at_en.rgb_sp_color = sgp->sg_rgb_sp_name ? sgp->sg_rgb_sp : -1;
- at_en.hl_blend = sgp->sg_blend;
-
- sgp->sg_attr = hl_get_syn_attr(0, idx+1, at_en);
-
- // a cursor style uses this syn_id, make sure its attribute is updated.
- if (cursor_mode_uses_syn_id(idx+1)) {
- ui_mode_info_set();
- }
-}
-
-int syn_name2id(const char *name)
- FUNC_ATTR_NONNULL_ALL
-{
- return syn_name2id_len((char_u *)name, STRLEN(name));
-}
-
-/// Lookup a highlight group name and return its ID.
-///
-/// @param highlight name e.g. 'Cursor', 'Normal'
-/// @return the highlight id, else 0 if \p name does not exist
-int syn_name2id_len(const char_u *name, size_t len)
- FUNC_ATTR_NONNULL_ALL
-{
- char name_u[MAX_SYN_NAME + 1];
-
- if (len == 0 || len > MAX_SYN_NAME) {
- return 0;
- }
-
- // Avoid using stricmp() too much, it's slow on some systems */
- // Avoid alloc()/free(), these are slow too.
- memcpy(name_u, name, len);
- name_u[len] = '\0';
- vim_strup((char_u *)name_u);
-
- // map_get(..., int) returns 0 when no key is present, which is
- // the expected value for missing highlight group.
- return map_get(cstr_t, int)(&highlight_unames, name_u);
-}
-
-/// Lookup a highlight group name and return its attributes.
-/// Return zero if not found.
-int syn_name2attr(const char_u *name)
- FUNC_ATTR_NONNULL_ALL
-{
- int id = syn_name2id((char *)name);
-
- if (id != 0) {
- return syn_id2attr(id);
- }
- return 0;
-}
-
-/*
- * Return TRUE if highlight group "name" exists.
- */
-int highlight_exists(const char *name)
-{
- return syn_name2id(name) > 0;
-}
-
-/*
- * Return the name of highlight group "id".
- * When not a valid ID return an empty string.
- */
-char_u *syn_id2name(int id)
-{
- if (id <= 0 || id > highlight_ga.ga_len) {
- return (char_u *)"";
- }
- return HL_TABLE()[id - 1].sg_name;
-}
-
-
-/// Find highlight group name in the table and return its ID.
-/// If it doesn't exist yet, a new entry is created.
-///
-/// @param pp Highlight group name
-/// @param len length of \p pp
-///
-/// @return 0 for failure else the id of the group
-int syn_check_group(const char *name, int len)
-{
- if (len > MAX_SYN_NAME) {
- emsg(_(e_highlight_group_name_too_long));
- return 0;
- }
- int id = syn_name2id_len((char_u *)name, len);
- if (id == 0) { // doesn't exist yet
- return syn_add_group(vim_strnsave((char_u *)name, len));
- }
- return id;
-}
-
-/// Add new highlight group and return its ID.
-///
-/// @param name must be an allocated string, it will be consumed.
-/// @return 0 for failure, else the allocated group id
-/// @see syn_check_group syn_unadd_group
-static int syn_add_group(char_u *name)
-{
- char_u *p;
-
- // Check that the name is ASCII letters, digits and underscore.
- for (p = name; *p != NUL; ++p) {
- if (!vim_isprintc(*p)) {
- emsg(_("E669: Unprintable character in group name"));
- xfree(name);
- return 0;
- } else if (!ASCII_ISALNUM(*p) && *p != '_') {
- /* This is an error, but since there previously was no check only
- * give a warning. */
- msg_source(HL_ATTR(HLF_W));
- msg(_("W18: Invalid character in group name"));
- break;
- }
- }
-
- /*
- * First call for this growarray: init growing array.
- */
- if (highlight_ga.ga_data == NULL) {
- highlight_ga.ga_itemsize = sizeof(struct hl_group);
- ga_set_growsize(&highlight_ga, 10);
- }
-
- if (highlight_ga.ga_len >= MAX_HL_ID) {
- emsg(_("E849: Too many highlight and syntax groups"));
- xfree(name);
- return 0;
- }
-
- char *const name_up = (char *)vim_strsave_up(name);
-
- // Append another syntax_highlight entry.
- struct hl_group *hlgp = GA_APPEND_VIA_PTR(struct hl_group, &highlight_ga);
- memset(hlgp, 0, sizeof(*hlgp));
- hlgp->sg_name = name;
- hlgp->sg_rgb_bg = -1;
- hlgp->sg_rgb_fg = -1;
- hlgp->sg_rgb_sp = -1;
- hlgp->sg_blend = -1;
- hlgp->sg_name_u = name_up;
-
- int id = highlight_ga.ga_len; // ID is index plus one
-
- map_put(cstr_t, int)(&highlight_unames, name_up, id);
-
- return id;
-}
-
-/// When, just after calling syn_add_group(), an error is discovered, this
-/// function deletes the new name.
-static void syn_unadd_group(void)
-{
- highlight_ga.ga_len--;
- HlGroup *item = &HL_TABLE()[highlight_ga.ga_len];
- map_del(cstr_t, int)(&highlight_unames, item->sg_name_u);
- xfree(item->sg_name);
- xfree(item->sg_name_u);
-}
-
-
-/// Translate a group ID to highlight attributes.
-/// @see syn_attr2entry
-int syn_id2attr(int hl_id)
-{
- hl_id = syn_get_final_id(hl_id);
- struct hl_group *sgp = &HL_TABLE()[hl_id - 1]; // index is ID minus one
-
- int attr = ns_get_hl(-1, hl_id, false, sgp->sg_set);
- if (attr >= 0) {
- return attr;
- }
- return sgp->sg_attr;
-}
-
-
-/*
- * Translate a group ID to the final group ID (following links).
- */
-int syn_get_final_id(int hl_id)
-{
- int count;
-
- if (hl_id > highlight_ga.ga_len || hl_id < 1) {
- return 0; // Can be called from eval!!
- }
- /*
- * Follow links until there is no more.
- * Look out for loops! Break after 100 links.
- */
- for (count = 100; --count >= 0;) {
- struct hl_group *sgp = &HL_TABLE()[hl_id - 1]; // index is ID minus one
-
- // ACHTUNG: when using "tmp" attribute (no link) the function might be
- // called twice. it needs be smart enough to remember attr only to
- // syn_id2attr time
- int check = ns_get_hl(-1, hl_id, true, sgp->sg_set);
- if (check == 0) {
- return hl_id; // how dare! it broke the link!
- } else if (check > 0) {
- hl_id = check;
- continue;
- }
-
-
- if (sgp->sg_link == 0 || sgp->sg_link > highlight_ga.ga_len) {
- break;
- }
- hl_id = sgp->sg_link;
- }
-
- return hl_id;
-}
-
-/// Refresh the color attributes of all highlight groups.
-void highlight_attr_set_all(void)
-{
- for (int idx = 0; idx < highlight_ga.ga_len; idx++) {
- struct hl_group *sgp = &HL_TABLE()[idx];
- if (sgp->sg_rgb_bg_name != NULL) {
- sgp->sg_rgb_bg = name_to_color(sgp->sg_rgb_bg_name);
- }
- if (sgp->sg_rgb_fg_name != NULL) {
- sgp->sg_rgb_fg = name_to_color(sgp->sg_rgb_fg_name);
- }
- if (sgp->sg_rgb_sp_name != NULL) {
- sgp->sg_rgb_sp = name_to_color(sgp->sg_rgb_sp_name);
- }
- set_hl_attr(idx);
- }
-}
-
-// Apply difference between User[1-9] and HLF_S to HLF_SNC.
-static void combine_stl_hlt(int id, int id_S, int id_alt, int hlcnt, int i, int hlf, int *table)
- FUNC_ATTR_NONNULL_ALL
-{
- struct hl_group *const hlt = HL_TABLE();
-
- if (id_alt == 0) {
- memset(&hlt[hlcnt + i], 0, sizeof(struct hl_group));
- hlt[hlcnt + i].sg_cterm = highlight_attr[hlf];
- hlt[hlcnt + i].sg_gui = highlight_attr[hlf];
- } else {
- memmove(&hlt[hlcnt + i], &hlt[id_alt - 1], sizeof(struct hl_group));
- }
- hlt[hlcnt + i].sg_link = 0;
-
- hlt[hlcnt + i].sg_cterm ^= hlt[id - 1].sg_cterm ^ hlt[id_S - 1].sg_cterm;
- if (hlt[id - 1].sg_cterm_fg != hlt[id_S - 1].sg_cterm_fg) {
- hlt[hlcnt + i].sg_cterm_fg = hlt[id - 1].sg_cterm_fg;
- }
- if (hlt[id - 1].sg_cterm_bg != hlt[id_S - 1].sg_cterm_bg) {
- hlt[hlcnt + i].sg_cterm_bg = hlt[id - 1].sg_cterm_bg;
- }
- hlt[hlcnt + i].sg_gui ^= hlt[id - 1].sg_gui ^ hlt[id_S - 1].sg_gui;
- if (hlt[id - 1].sg_rgb_fg != hlt[id_S - 1].sg_rgb_fg) {
- hlt[hlcnt + i].sg_rgb_fg = hlt[id - 1].sg_rgb_fg;
- }
- if (hlt[id - 1].sg_rgb_bg != hlt[id_S - 1].sg_rgb_bg) {
- hlt[hlcnt + i].sg_rgb_bg = hlt[id - 1].sg_rgb_bg;
- }
- if (hlt[id - 1].sg_rgb_sp != hlt[id_S - 1].sg_rgb_sp) {
- hlt[hlcnt + i].sg_rgb_sp = hlt[id - 1].sg_rgb_sp;
- }
- highlight_ga.ga_len = hlcnt + i + 1;
- set_hl_attr(hlcnt + i); // At long last we can apply
- table[i] = syn_id2attr(hlcnt + i + 1);
-}
-
-/// Translate highlight groups into attributes in highlight_attr[] and set up
-/// the user highlights User1..9. A set of corresponding highlights to use on
-/// top of HLF_SNC is computed. Called only when nvim starts and upon first
-/// screen redraw after any :highlight command.
-void highlight_changed(void)
-{
- int id;
- char userhl[30]; // use 30 to avoid compiler warning
- int id_S = -1;
- int id_SNC = 0;
- int hlcnt;
-
- need_highlight_changed = false;
-
- /// Translate builtin highlight groups into attributes for quick lookup.
- for (int hlf = 0; hlf < HLF_COUNT; hlf++) {
- id = syn_check_group(hlf_names[hlf], STRLEN(hlf_names[hlf]));
- if (id == 0) {
- abort();
- }
- int final_id = syn_get_final_id(id);
- if (hlf == HLF_SNC) {
- id_SNC = final_id;
- } else if (hlf == HLF_S) {
- id_S = final_id;
- }
-
- highlight_attr[hlf] = hl_get_ui_attr(hlf, final_id,
- hlf == HLF_INACTIVE);
-
- if (highlight_attr[hlf] != highlight_attr_last[hlf]) {
- if (hlf == HLF_MSG) {
- clear_cmdline = true;
- }
- ui_call_hl_group_set(cstr_as_string((char *)hlf_names[hlf]),
- highlight_attr[hlf]);
- highlight_attr_last[hlf] = highlight_attr[hlf];
- }
- }
-
- //
- // Setup the user highlights
- //
- // Temporarily utilize 10 more hl entries:
- // 9 for User1-User9 combined with StatusLineNC
- // 1 for StatusLine default
- // Must to be in there simultaneously in case of table overflows in
- // get_attr_entry()
- ga_grow(&highlight_ga, 10);
- hlcnt = highlight_ga.ga_len;
- if (id_S == -1) {
- // Make sure id_S is always valid to simplify code below. Use the last entry
- memset(&HL_TABLE()[hlcnt + 9], 0, sizeof(struct hl_group));
- id_S = hlcnt + 10;
- }
- for (int i = 0; i < 9; i++) {
- snprintf(userhl, sizeof(userhl), "User%d", i + 1);
- id = syn_name2id(userhl);
- if (id == 0) {
- highlight_user[i] = 0;
- highlight_stlnc[i] = 0;
- } else {
- highlight_user[i] = syn_id2attr(id);
- combine_stl_hlt(id, id_S, id_SNC, hlcnt, i, HLF_SNC, highlight_stlnc);
- }
- }
- highlight_ga.ga_len = hlcnt;
-}
-
-
-/*
- * Handle command line completion for :highlight command.
- */
-void set_context_in_highlight_cmd(expand_T *xp, const char *arg)
-{
- // Default: expand group names.
- xp->xp_context = EXPAND_HIGHLIGHT;
- xp->xp_pattern = (char_u *)arg;
- include_link = 2;
- include_default = 1;
-
- // (part of) subcommand already typed
- if (*arg != NUL) {
- const char *p = (const char *)skiptowhite((const char_u *)arg);
- if (*p != NUL) { // Past "default" or group name.
- include_default = 0;
- if (strncmp("default", arg, p - arg) == 0) {
- arg = (const char *)skipwhite((const char_u *)p);
- xp->xp_pattern = (char_u *)arg;
- p = (const char *)skiptowhite((const char_u *)arg);
- }
- if (*p != NUL) { // past group name
- include_link = 0;
- if (arg[1] == 'i' && arg[0] == 'N') {
- highlight_list();
- }
- if (strncmp("link", arg, p - arg) == 0
- || strncmp("clear", arg, p - arg) == 0) {
- xp->xp_pattern = skipwhite((const char_u *)p);
- p = (const char *)skiptowhite(xp->xp_pattern);
- if (*p != NUL) { // Past first group name.
- xp->xp_pattern = skipwhite((const char_u *)p);
- p = (const char *)skiptowhite(xp->xp_pattern);
- }
- }
- if (*p != NUL) { // Past group name(s).
- xp->xp_context = EXPAND_NOTHING;
- }
- }
- }
- }
-}
-
-/*
- * List highlighting matches in a nice way.
- */
-static void highlight_list(void)
-{
- int i;
-
- for (i = 10; --i >= 0;) {
- highlight_list_two(i, HL_ATTR(HLF_D));
- }
- for (i = 40; --i >= 0;) {
- highlight_list_two(99, 0);
- }
-}
-
-static void highlight_list_two(int cnt, int attr)
-{
- msg_puts_attr(&("N \bI \b! \b"[cnt / 11]), attr);
- msg_clr_eos();
- ui_flush();
- os_delay(cnt == 99 ? 40L : (long)cnt * 50L, false);
-}
-
-
-/// Function given to ExpandGeneric() to obtain the list of group names.
-const char *get_highlight_name(expand_T *const xp, int idx)
- FUNC_ATTR_WARN_UNUSED_RESULT
-{
- return get_highlight_name_ext(xp, idx, true);
-}
-
-
-/// Obtain a highlight group name.
-///
-/// @param skip_cleared if true don't return a cleared entry.
-const char *get_highlight_name_ext(expand_T *xp, int idx, bool skip_cleared)
- FUNC_ATTR_WARN_UNUSED_RESULT
-{
- if (idx < 0) {
- return NULL;
- }
-
- // Items are never removed from the table, skip the ones that were cleared.
- if (skip_cleared && idx < highlight_ga.ga_len && HL_TABLE()[idx].sg_cleared) {
- return "";
- }
-
- if (idx == highlight_ga.ga_len && include_none != 0) {
- return "none";
- } else if (idx == highlight_ga.ga_len + include_none
- && include_default != 0) {
- return "default";
- } else if (idx == highlight_ga.ga_len + include_none + include_default
- && include_link != 0) {
- return "link";
- } else if (idx == highlight_ga.ga_len + include_none + include_default + 1
- && include_link != 0) {
- return "clear";
- } else if (idx >= highlight_ga.ga_len) {
- return NULL;
- }
- return (const char *)HL_TABLE()[idx].sg_name;
-}
-
-color_name_table_T color_name_table[] = {
- // Colors from rgb.txt
- { "AliceBlue", RGB_(0xf0, 0xf8, 0xff) },
- { "AntiqueWhite", RGB_(0xfa, 0xeb, 0xd7) },
- { "AntiqueWhite1", RGB_(0xff, 0xef, 0xdb) },
- { "AntiqueWhite2", RGB_(0xee, 0xdf, 0xcc) },
- { "AntiqueWhite3", RGB_(0xcd, 0xc0, 0xb0) },
- { "AntiqueWhite4", RGB_(0x8b, 0x83, 0x78) },
- { "Aqua", RGB_(0x00, 0xff, 0xff) },
- { "Aquamarine", RGB_(0x7f, 0xff, 0xd4) },
- { "Aquamarine1", RGB_(0x7f, 0xff, 0xd4) },
- { "Aquamarine2", RGB_(0x76, 0xee, 0xc6) },
- { "Aquamarine3", RGB_(0x66, 0xcd, 0xaa) },
- { "Aquamarine4", RGB_(0x45, 0x8b, 0x74) },
- { "Azure", RGB_(0xf0, 0xff, 0xff) },
- { "Azure1", RGB_(0xf0, 0xff, 0xff) },
- { "Azure2", RGB_(0xe0, 0xee, 0xee) },
- { "Azure3", RGB_(0xc1, 0xcd, 0xcd) },
- { "Azure4", RGB_(0x83, 0x8b, 0x8b) },
- { "Beige", RGB_(0xf5, 0xf5, 0xdc) },
- { "Bisque", RGB_(0xff, 0xe4, 0xc4) },
- { "Bisque1", RGB_(0xff, 0xe4, 0xc4) },
- { "Bisque2", RGB_(0xee, 0xd5, 0xb7) },
- { "Bisque3", RGB_(0xcd, 0xb7, 0x9e) },
- { "Bisque4", RGB_(0x8b, 0x7d, 0x6b) },
- { "Black", RGB_(0x00, 0x00, 0x00) },
- { "BlanchedAlmond", RGB_(0xff, 0xeb, 0xcd) },
- { "Blue", RGB_(0x00, 0x00, 0xff) },
- { "Blue1", RGB_(0x0, 0x0, 0xff) },
- { "Blue2", RGB_(0x0, 0x0, 0xee) },
- { "Blue3", RGB_(0x0, 0x0, 0xcd) },
- { "Blue4", RGB_(0x0, 0x0, 0x8b) },
- { "BlueViolet", RGB_(0x8a, 0x2b, 0xe2) },
- { "Brown", RGB_(0xa5, 0x2a, 0x2a) },
- { "Brown1", RGB_(0xff, 0x40, 0x40) },
- { "Brown2", RGB_(0xee, 0x3b, 0x3b) },
- { "Brown3", RGB_(0xcd, 0x33, 0x33) },
- { "Brown4", RGB_(0x8b, 0x23, 0x23) },
- { "BurlyWood", RGB_(0xde, 0xb8, 0x87) },
- { "Burlywood1", RGB_(0xff, 0xd3, 0x9b) },
- { "Burlywood2", RGB_(0xee, 0xc5, 0x91) },
- { "Burlywood3", RGB_(0xcd, 0xaa, 0x7d) },
- { "Burlywood4", RGB_(0x8b, 0x73, 0x55) },
- { "CadetBlue", RGB_(0x5f, 0x9e, 0xa0) },
- { "CadetBlue1", RGB_(0x98, 0xf5, 0xff) },
- { "CadetBlue2", RGB_(0x8e, 0xe5, 0xee) },
- { "CadetBlue3", RGB_(0x7a, 0xc5, 0xcd) },
- { "CadetBlue4", RGB_(0x53, 0x86, 0x8b) },
- { "ChartReuse", RGB_(0x7f, 0xff, 0x00) },
- { "Chartreuse1", RGB_(0x7f, 0xff, 0x0) },
- { "Chartreuse2", RGB_(0x76, 0xee, 0x0) },
- { "Chartreuse3", RGB_(0x66, 0xcd, 0x0) },
- { "Chartreuse4", RGB_(0x45, 0x8b, 0x0) },
- { "Chocolate", RGB_(0xd2, 0x69, 0x1e) },
- { "Chocolate1", RGB_(0xff, 0x7f, 0x24) },
- { "Chocolate2", RGB_(0xee, 0x76, 0x21) },
- { "Chocolate3", RGB_(0xcd, 0x66, 0x1d) },
- { "Chocolate4", RGB_(0x8b, 0x45, 0x13) },
- { "Coral", RGB_(0xff, 0x7f, 0x50) },
- { "Coral1", RGB_(0xff, 0x72, 0x56) },
- { "Coral2", RGB_(0xee, 0x6a, 0x50) },
- { "Coral3", RGB_(0xcd, 0x5b, 0x45) },
- { "Coral4", RGB_(0x8b, 0x3e, 0x2f) },
- { "CornFlowerBlue", RGB_(0x64, 0x95, 0xed) },
- { "Cornsilk", RGB_(0xff, 0xf8, 0xdc) },
- { "Cornsilk1", RGB_(0xff, 0xf8, 0xdc) },
- { "Cornsilk2", RGB_(0xee, 0xe8, 0xcd) },
- { "Cornsilk3", RGB_(0xcd, 0xc8, 0xb1) },
- { "Cornsilk4", RGB_(0x8b, 0x88, 0x78) },
- { "Crimson", RGB_(0xdc, 0x14, 0x3c) },
- { "Cyan", RGB_(0x00, 0xff, 0xff) },
- { "Cyan1", RGB_(0x0, 0xff, 0xff) },
- { "Cyan2", RGB_(0x0, 0xee, 0xee) },
- { "Cyan3", RGB_(0x0, 0xcd, 0xcd) },
- { "Cyan4", RGB_(0x0, 0x8b, 0x8b) },
- { "DarkBlue", RGB_(0x00, 0x00, 0x8b) },
- { "DarkCyan", RGB_(0x00, 0x8b, 0x8b) },
- { "DarkGoldenRod", RGB_(0xb8, 0x86, 0x0b) },
- { "DarkGoldenrod1", RGB_(0xff, 0xb9, 0xf) },
- { "DarkGoldenrod2", RGB_(0xee, 0xad, 0xe) },
- { "DarkGoldenrod3", RGB_(0xcd, 0x95, 0xc) },
- { "DarkGoldenrod4", RGB_(0x8b, 0x65, 0x8) },
- { "DarkGray", RGB_(0xa9, 0xa9, 0xa9) },
- { "DarkGreen", RGB_(0x00, 0x64, 0x00) },
- { "DarkGrey", RGB_(0xa9, 0xa9, 0xa9) },
- { "DarkKhaki", RGB_(0xbd, 0xb7, 0x6b) },
- { "DarkMagenta", RGB_(0x8b, 0x00, 0x8b) },
- { "DarkOliveGreen", RGB_(0x55, 0x6b, 0x2f) },
- { "DarkOliveGreen1", RGB_(0xca, 0xff, 0x70) },
- { "DarkOliveGreen2", RGB_(0xbc, 0xee, 0x68) },
- { "DarkOliveGreen3", RGB_(0xa2, 0xcd, 0x5a) },
- { "DarkOliveGreen4", RGB_(0x6e, 0x8b, 0x3d) },
- { "DarkOrange", RGB_(0xff, 0x8c, 0x00) },
- { "DarkOrange1", RGB_(0xff, 0x7f, 0x0) },
- { "DarkOrange2", RGB_(0xee, 0x76, 0x0) },
- { "DarkOrange3", RGB_(0xcd, 0x66, 0x0) },
- { "DarkOrange4", RGB_(0x8b, 0x45, 0x0) },
- { "DarkOrchid", RGB_(0x99, 0x32, 0xcc) },
- { "DarkOrchid1", RGB_(0xbf, 0x3e, 0xff) },
- { "DarkOrchid2", RGB_(0xb2, 0x3a, 0xee) },
- { "DarkOrchid3", RGB_(0x9a, 0x32, 0xcd) },
- { "DarkOrchid4", RGB_(0x68, 0x22, 0x8b) },
- { "DarkRed", RGB_(0x8b, 0x00, 0x00) },
- { "DarkSalmon", RGB_(0xe9, 0x96, 0x7a) },
- { "DarkSeaGreen", RGB_(0x8f, 0xbc, 0x8f) },
- { "DarkSeaGreen1", RGB_(0xc1, 0xff, 0xc1) },
- { "DarkSeaGreen2", RGB_(0xb4, 0xee, 0xb4) },
- { "DarkSeaGreen3", RGB_(0x9b, 0xcd, 0x9b) },
- { "DarkSeaGreen4", RGB_(0x69, 0x8b, 0x69) },
- { "DarkSlateBlue", RGB_(0x48, 0x3d, 0x8b) },
- { "DarkSlateGray", RGB_(0x2f, 0x4f, 0x4f) },
- { "DarkSlateGray1", RGB_(0x97, 0xff, 0xff) },
- { "DarkSlateGray2", RGB_(0x8d, 0xee, 0xee) },
- { "DarkSlateGray3", RGB_(0x79, 0xcd, 0xcd) },
- { "DarkSlateGray4", RGB_(0x52, 0x8b, 0x8b) },
- { "DarkSlateGrey", RGB_(0x2f, 0x4f, 0x4f) },
- { "DarkTurquoise", RGB_(0x00, 0xce, 0xd1) },
- { "DarkViolet", RGB_(0x94, 0x00, 0xd3) },
- { "DarkYellow", RGB_(0xbb, 0xbb, 0x00) },
- { "DeepPink", RGB_(0xff, 0x14, 0x93) },
- { "DeepPink1", RGB_(0xff, 0x14, 0x93) },
- { "DeepPink2", RGB_(0xee, 0x12, 0x89) },
- { "DeepPink3", RGB_(0xcd, 0x10, 0x76) },
- { "DeepPink4", RGB_(0x8b, 0xa, 0x50) },
- { "DeepSkyBlue", RGB_(0x00, 0xbf, 0xff) },
- { "DeepSkyBlue1", RGB_(0x0, 0xbf, 0xff) },
- { "DeepSkyBlue2", RGB_(0x0, 0xb2, 0xee) },
- { "DeepSkyBlue3", RGB_(0x0, 0x9a, 0xcd) },
- { "DeepSkyBlue4", RGB_(0x0, 0x68, 0x8b) },
- { "DimGray", RGB_(0x69, 0x69, 0x69) },
- { "DimGrey", RGB_(0x69, 0x69, 0x69) },
- { "DodgerBlue", RGB_(0x1e, 0x90, 0xff) },
- { "DodgerBlue1", RGB_(0x1e, 0x90, 0xff) },
- { "DodgerBlue2", RGB_(0x1c, 0x86, 0xee) },
- { "DodgerBlue3", RGB_(0x18, 0x74, 0xcd) },
- { "DodgerBlue4", RGB_(0x10, 0x4e, 0x8b) },
- { "Firebrick", RGB_(0xb2, 0x22, 0x22) },
- { "Firebrick1", RGB_(0xff, 0x30, 0x30) },
- { "Firebrick2", RGB_(0xee, 0x2c, 0x2c) },
- { "Firebrick3", RGB_(0xcd, 0x26, 0x26) },
- { "Firebrick4", RGB_(0x8b, 0x1a, 0x1a) },
- { "FloralWhite", RGB_(0xff, 0xfa, 0xf0) },
- { "ForestGreen", RGB_(0x22, 0x8b, 0x22) },
- { "Fuchsia", RGB_(0xff, 0x00, 0xff) },
- { "Gainsboro", RGB_(0xdc, 0xdc, 0xdc) },
- { "GhostWhite", RGB_(0xf8, 0xf8, 0xff) },
- { "Gold", RGB_(0xff, 0xd7, 0x00) },
- { "Gold1", RGB_(0xff, 0xd7, 0x0) },
- { "Gold2", RGB_(0xee, 0xc9, 0x0) },
- { "Gold3", RGB_(0xcd, 0xad, 0x0) },
- { "Gold4", RGB_(0x8b, 0x75, 0x0) },
- { "GoldenRod", RGB_(0xda, 0xa5, 0x20) },
- { "Goldenrod1", RGB_(0xff, 0xc1, 0x25) },
- { "Goldenrod2", RGB_(0xee, 0xb4, 0x22) },
- { "Goldenrod3", RGB_(0xcd, 0x9b, 0x1d) },
- { "Goldenrod4", RGB_(0x8b, 0x69, 0x14) },
- { "Gray", RGB_(0x80, 0x80, 0x80) },
- { "Gray0", RGB_(0x0, 0x0, 0x0) },
- { "Gray1", RGB_(0x3, 0x3, 0x3) },
- { "Gray10", RGB_(0x1a, 0x1a, 0x1a) },
- { "Gray100", RGB_(0xff, 0xff, 0xff) },
- { "Gray11", RGB_(0x1c, 0x1c, 0x1c) },
- { "Gray12", RGB_(0x1f, 0x1f, 0x1f) },
- { "Gray13", RGB_(0x21, 0x21, 0x21) },
- { "Gray14", RGB_(0x24, 0x24, 0x24) },
- { "Gray15", RGB_(0x26, 0x26, 0x26) },
- { "Gray16", RGB_(0x29, 0x29, 0x29) },
- { "Gray17", RGB_(0x2b, 0x2b, 0x2b) },
- { "Gray18", RGB_(0x2e, 0x2e, 0x2e) },
- { "Gray19", RGB_(0x30, 0x30, 0x30) },
- { "Gray2", RGB_(0x5, 0x5, 0x5) },
- { "Gray20", RGB_(0x33, 0x33, 0x33) },
- { "Gray21", RGB_(0x36, 0x36, 0x36) },
- { "Gray22", RGB_(0x38, 0x38, 0x38) },
- { "Gray23", RGB_(0x3b, 0x3b, 0x3b) },
- { "Gray24", RGB_(0x3d, 0x3d, 0x3d) },
- { "Gray25", RGB_(0x40, 0x40, 0x40) },
- { "Gray26", RGB_(0x42, 0x42, 0x42) },
- { "Gray27", RGB_(0x45, 0x45, 0x45) },
- { "Gray28", RGB_(0x47, 0x47, 0x47) },
- { "Gray29", RGB_(0x4a, 0x4a, 0x4a) },
- { "Gray3", RGB_(0x8, 0x8, 0x8) },
- { "Gray30", RGB_(0x4d, 0x4d, 0x4d) },
- { "Gray31", RGB_(0x4f, 0x4f, 0x4f) },
- { "Gray32", RGB_(0x52, 0x52, 0x52) },
- { "Gray33", RGB_(0x54, 0x54, 0x54) },
- { "Gray34", RGB_(0x57, 0x57, 0x57) },
- { "Gray35", RGB_(0x59, 0x59, 0x59) },
- { "Gray36", RGB_(0x5c, 0x5c, 0x5c) },
- { "Gray37", RGB_(0x5e, 0x5e, 0x5e) },
- { "Gray38", RGB_(0x61, 0x61, 0x61) },
- { "Gray39", RGB_(0x63, 0x63, 0x63) },
- { "Gray4", RGB_(0xa, 0xa, 0xa) },
- { "Gray40", RGB_(0x66, 0x66, 0x66) },
- { "Gray41", RGB_(0x69, 0x69, 0x69) },
- { "Gray42", RGB_(0x6b, 0x6b, 0x6b) },
- { "Gray43", RGB_(0x6e, 0x6e, 0x6e) },
- { "Gray44", RGB_(0x70, 0x70, 0x70) },
- { "Gray45", RGB_(0x73, 0x73, 0x73) },
- { "Gray46", RGB_(0x75, 0x75, 0x75) },
- { "Gray47", RGB_(0x78, 0x78, 0x78) },
- { "Gray48", RGB_(0x7a, 0x7a, 0x7a) },
- { "Gray49", RGB_(0x7d, 0x7d, 0x7d) },
- { "Gray5", RGB_(0xd, 0xd, 0xd) },
- { "Gray50", RGB_(0x7f, 0x7f, 0x7f) },
- { "Gray51", RGB_(0x82, 0x82, 0x82) },
- { "Gray52", RGB_(0x85, 0x85, 0x85) },
- { "Gray53", RGB_(0x87, 0x87, 0x87) },
- { "Gray54", RGB_(0x8a, 0x8a, 0x8a) },
- { "Gray55", RGB_(0x8c, 0x8c, 0x8c) },
- { "Gray56", RGB_(0x8f, 0x8f, 0x8f) },
- { "Gray57", RGB_(0x91, 0x91, 0x91) },
- { "Gray58", RGB_(0x94, 0x94, 0x94) },
- { "Gray59", RGB_(0x96, 0x96, 0x96) },
- { "Gray6", RGB_(0xf, 0xf, 0xf) },
- { "Gray60", RGB_(0x99, 0x99, 0x99) },
- { "Gray61", RGB_(0x9c, 0x9c, 0x9c) },
- { "Gray62", RGB_(0x9e, 0x9e, 0x9e) },
- { "Gray63", RGB_(0xa1, 0xa1, 0xa1) },
- { "Gray64", RGB_(0xa3, 0xa3, 0xa3) },
- { "Gray65", RGB_(0xa6, 0xa6, 0xa6) },
- { "Gray66", RGB_(0xa8, 0xa8, 0xa8) },
- { "Gray67", RGB_(0xab, 0xab, 0xab) },
- { "Gray68", RGB_(0xad, 0xad, 0xad) },
- { "Gray69", RGB_(0xb0, 0xb0, 0xb0) },
- { "Gray7", RGB_(0x12, 0x12, 0x12) },
- { "Gray70", RGB_(0xb3, 0xb3, 0xb3) },
- { "Gray71", RGB_(0xb5, 0xb5, 0xb5) },
- { "Gray72", RGB_(0xb8, 0xb8, 0xb8) },
- { "Gray73", RGB_(0xba, 0xba, 0xba) },
- { "Gray74", RGB_(0xbd, 0xbd, 0xbd) },
- { "Gray75", RGB_(0xbf, 0xbf, 0xbf) },
- { "Gray76", RGB_(0xc2, 0xc2, 0xc2) },
- { "Gray77", RGB_(0xc4, 0xc4, 0xc4) },
- { "Gray78", RGB_(0xc7, 0xc7, 0xc7) },
- { "Gray79", RGB_(0xc9, 0xc9, 0xc9) },
- { "Gray8", RGB_(0x14, 0x14, 0x14) },
- { "Gray80", RGB_(0xcc, 0xcc, 0xcc) },
- { "Gray81", RGB_(0xcf, 0xcf, 0xcf) },
- { "Gray82", RGB_(0xd1, 0xd1, 0xd1) },
- { "Gray83", RGB_(0xd4, 0xd4, 0xd4) },
- { "Gray84", RGB_(0xd6, 0xd6, 0xd6) },
- { "Gray85", RGB_(0xd9, 0xd9, 0xd9) },
- { "Gray86", RGB_(0xdb, 0xdb, 0xdb) },
- { "Gray87", RGB_(0xde, 0xde, 0xde) },
- { "Gray88", RGB_(0xe0, 0xe0, 0xe0) },
- { "Gray89", RGB_(0xe3, 0xe3, 0xe3) },
- { "Gray9", RGB_(0x17, 0x17, 0x17) },
- { "Gray90", RGB_(0xe5, 0xe5, 0xe5) },
- { "Gray91", RGB_(0xe8, 0xe8, 0xe8) },
- { "Gray92", RGB_(0xeb, 0xeb, 0xeb) },
- { "Gray93", RGB_(0xed, 0xed, 0xed) },
- { "Gray94", RGB_(0xf0, 0xf0, 0xf0) },
- { "Gray95", RGB_(0xf2, 0xf2, 0xf2) },
- { "Gray96", RGB_(0xf5, 0xf5, 0xf5) },
- { "Gray97", RGB_(0xf7, 0xf7, 0xf7) },
- { "Gray98", RGB_(0xfa, 0xfa, 0xfa) },
- { "Gray99", RGB_(0xfc, 0xfc, 0xfc) },
- { "Green", RGB_(0x00, 0x80, 0x00) },
- { "Green1", RGB_(0x0, 0xff, 0x0) },
- { "Green2", RGB_(0x0, 0xee, 0x0) },
- { "Green3", RGB_(0x0, 0xcd, 0x0) },
- { "Green4", RGB_(0x0, 0x8b, 0x0) },
- { "GreenYellow", RGB_(0xad, 0xff, 0x2f) },
- { "Grey", RGB_(0x80, 0x80, 0x80) },
- { "Grey0", RGB_(0x0, 0x0, 0x0) },
- { "Grey1", RGB_(0x3, 0x3, 0x3) },
- { "Grey10", RGB_(0x1a, 0x1a, 0x1a) },
- { "Grey100", RGB_(0xff, 0xff, 0xff) },
- { "Grey11", RGB_(0x1c, 0x1c, 0x1c) },
- { "Grey12", RGB_(0x1f, 0x1f, 0x1f) },
- { "Grey13", RGB_(0x21, 0x21, 0x21) },
- { "Grey14", RGB_(0x24, 0x24, 0x24) },
- { "Grey15", RGB_(0x26, 0x26, 0x26) },
- { "Grey16", RGB_(0x29, 0x29, 0x29) },
- { "Grey17", RGB_(0x2b, 0x2b, 0x2b) },
- { "Grey18", RGB_(0x2e, 0x2e, 0x2e) },
- { "Grey19", RGB_(0x30, 0x30, 0x30) },
- { "Grey2", RGB_(0x5, 0x5, 0x5) },
- { "Grey20", RGB_(0x33, 0x33, 0x33) },
- { "Grey21", RGB_(0x36, 0x36, 0x36) },
- { "Grey22", RGB_(0x38, 0x38, 0x38) },
- { "Grey23", RGB_(0x3b, 0x3b, 0x3b) },
- { "Grey24", RGB_(0x3d, 0x3d, 0x3d) },
- { "Grey25", RGB_(0x40, 0x40, 0x40) },
- { "Grey26", RGB_(0x42, 0x42, 0x42) },
- { "Grey27", RGB_(0x45, 0x45, 0x45) },
- { "Grey28", RGB_(0x47, 0x47, 0x47) },
- { "Grey29", RGB_(0x4a, 0x4a, 0x4a) },
- { "Grey3", RGB_(0x8, 0x8, 0x8) },
- { "Grey30", RGB_(0x4d, 0x4d, 0x4d) },
- { "Grey31", RGB_(0x4f, 0x4f, 0x4f) },
- { "Grey32", RGB_(0x52, 0x52, 0x52) },
- { "Grey33", RGB_(0x54, 0x54, 0x54) },
- { "Grey34", RGB_(0x57, 0x57, 0x57) },
- { "Grey35", RGB_(0x59, 0x59, 0x59) },
- { "Grey36", RGB_(0x5c, 0x5c, 0x5c) },
- { "Grey37", RGB_(0x5e, 0x5e, 0x5e) },
- { "Grey38", RGB_(0x61, 0x61, 0x61) },
- { "Grey39", RGB_(0x63, 0x63, 0x63) },
- { "Grey4", RGB_(0xa, 0xa, 0xa) },
- { "Grey40", RGB_(0x66, 0x66, 0x66) },
- { "Grey41", RGB_(0x69, 0x69, 0x69) },
- { "Grey42", RGB_(0x6b, 0x6b, 0x6b) },
- { "Grey43", RGB_(0x6e, 0x6e, 0x6e) },
- { "Grey44", RGB_(0x70, 0x70, 0x70) },
- { "Grey45", RGB_(0x73, 0x73, 0x73) },
- { "Grey46", RGB_(0x75, 0x75, 0x75) },
- { "Grey47", RGB_(0x78, 0x78, 0x78) },
- { "Grey48", RGB_(0x7a, 0x7a, 0x7a) },
- { "Grey49", RGB_(0x7d, 0x7d, 0x7d) },
- { "Grey5", RGB_(0xd, 0xd, 0xd) },
- { "Grey50", RGB_(0x7f, 0x7f, 0x7f) },
- { "Grey51", RGB_(0x82, 0x82, 0x82) },
- { "Grey52", RGB_(0x85, 0x85, 0x85) },
- { "Grey53", RGB_(0x87, 0x87, 0x87) },
- { "Grey54", RGB_(0x8a, 0x8a, 0x8a) },
- { "Grey55", RGB_(0x8c, 0x8c, 0x8c) },
- { "Grey56", RGB_(0x8f, 0x8f, 0x8f) },
- { "Grey57", RGB_(0x91, 0x91, 0x91) },
- { "Grey58", RGB_(0x94, 0x94, 0x94) },
- { "Grey59", RGB_(0x96, 0x96, 0x96) },
- { "Grey6", RGB_(0xf, 0xf, 0xf) },
- { "Grey60", RGB_(0x99, 0x99, 0x99) },
- { "Grey61", RGB_(0x9c, 0x9c, 0x9c) },
- { "Grey62", RGB_(0x9e, 0x9e, 0x9e) },
- { "Grey63", RGB_(0xa1, 0xa1, 0xa1) },
- { "Grey64", RGB_(0xa3, 0xa3, 0xa3) },
- { "Grey65", RGB_(0xa6, 0xa6, 0xa6) },
- { "Grey66", RGB_(0xa8, 0xa8, 0xa8) },
- { "Grey67", RGB_(0xab, 0xab, 0xab) },
- { "Grey68", RGB_(0xad, 0xad, 0xad) },
- { "Grey69", RGB_(0xb0, 0xb0, 0xb0) },
- { "Grey7", RGB_(0x12, 0x12, 0x12) },
- { "Grey70", RGB_(0xb3, 0xb3, 0xb3) },
- { "Grey71", RGB_(0xb5, 0xb5, 0xb5) },
- { "Grey72", RGB_(0xb8, 0xb8, 0xb8) },
- { "Grey73", RGB_(0xba, 0xba, 0xba) },
- { "Grey74", RGB_(0xbd, 0xbd, 0xbd) },
- { "Grey75", RGB_(0xbf, 0xbf, 0xbf) },
- { "Grey76", RGB_(0xc2, 0xc2, 0xc2) },
- { "Grey77", RGB_(0xc4, 0xc4, 0xc4) },
- { "Grey78", RGB_(0xc7, 0xc7, 0xc7) },
- { "Grey79", RGB_(0xc9, 0xc9, 0xc9) },
- { "Grey8", RGB_(0x14, 0x14, 0x14) },
- { "Grey80", RGB_(0xcc, 0xcc, 0xcc) },
- { "Grey81", RGB_(0xcf, 0xcf, 0xcf) },
- { "Grey82", RGB_(0xd1, 0xd1, 0xd1) },
- { "Grey83", RGB_(0xd4, 0xd4, 0xd4) },
- { "Grey84", RGB_(0xd6, 0xd6, 0xd6) },
- { "Grey85", RGB_(0xd9, 0xd9, 0xd9) },
- { "Grey86", RGB_(0xdb, 0xdb, 0xdb) },
- { "Grey87", RGB_(0xde, 0xde, 0xde) },
- { "Grey88", RGB_(0xe0, 0xe0, 0xe0) },
- { "Grey89", RGB_(0xe3, 0xe3, 0xe3) },
- { "Grey9", RGB_(0x17, 0x17, 0x17) },
- { "Grey90", RGB_(0xe5, 0xe5, 0xe5) },
- { "Grey91", RGB_(0xe8, 0xe8, 0xe8) },
- { "Grey92", RGB_(0xeb, 0xeb, 0xeb) },
- { "Grey93", RGB_(0xed, 0xed, 0xed) },
- { "Grey94", RGB_(0xf0, 0xf0, 0xf0) },
- { "Grey95", RGB_(0xf2, 0xf2, 0xf2) },
- { "Grey96", RGB_(0xf5, 0xf5, 0xf5) },
- { "Grey97", RGB_(0xf7, 0xf7, 0xf7) },
- { "Grey98", RGB_(0xfa, 0xfa, 0xfa) },
- { "Grey99", RGB_(0xfc, 0xfc, 0xfc) },
- { "Honeydew", RGB_(0xf0, 0xff, 0xf0) },
- { "Honeydew1", RGB_(0xf0, 0xff, 0xf0) },
- { "Honeydew2", RGB_(0xe0, 0xee, 0xe0) },
- { "Honeydew3", RGB_(0xc1, 0xcd, 0xc1) },
- { "Honeydew4", RGB_(0x83, 0x8b, 0x83) },
- { "HotPink", RGB_(0xff, 0x69, 0xb4) },
- { "HotPink1", RGB_(0xff, 0x6e, 0xb4) },
- { "HotPink2", RGB_(0xee, 0x6a, 0xa7) },
- { "HotPink3", RGB_(0xcd, 0x60, 0x90) },
- { "HotPink4", RGB_(0x8b, 0x3a, 0x62) },
- { "IndianRed", RGB_(0xcd, 0x5c, 0x5c) },
- { "IndianRed1", RGB_(0xff, 0x6a, 0x6a) },
- { "IndianRed2", RGB_(0xee, 0x63, 0x63) },
- { "IndianRed3", RGB_(0xcd, 0x55, 0x55) },
- { "IndianRed4", RGB_(0x8b, 0x3a, 0x3a) },
- { "Indigo", RGB_(0x4b, 0x00, 0x82) },
- { "Ivory", RGB_(0xff, 0xff, 0xf0) },
- { "Ivory1", RGB_(0xff, 0xff, 0xf0) },
- { "Ivory2", RGB_(0xee, 0xee, 0xe0) },
- { "Ivory3", RGB_(0xcd, 0xcd, 0xc1) },
- { "Ivory4", RGB_(0x8b, 0x8b, 0x83) },
- { "Khaki", RGB_(0xf0, 0xe6, 0x8c) },
- { "Khaki1", RGB_(0xff, 0xf6, 0x8f) },
- { "Khaki2", RGB_(0xee, 0xe6, 0x85) },
- { "Khaki3", RGB_(0xcd, 0xc6, 0x73) },
- { "Khaki4", RGB_(0x8b, 0x86, 0x4e) },
- { "Lavender", RGB_(0xe6, 0xe6, 0xfa) },
- { "LavenderBlush", RGB_(0xff, 0xf0, 0xf5) },
- { "LavenderBlush1", RGB_(0xff, 0xf0, 0xf5) },
- { "LavenderBlush2", RGB_(0xee, 0xe0, 0xe5) },
- { "LavenderBlush3", RGB_(0xcd, 0xc1, 0xc5) },
- { "LavenderBlush4", RGB_(0x8b, 0x83, 0x86) },
- { "LawnGreen", RGB_(0x7c, 0xfc, 0x00) },
- { "LemonChiffon", RGB_(0xff, 0xfa, 0xcd) },
- { "LemonChiffon1", RGB_(0xff, 0xfa, 0xcd) },
- { "LemonChiffon2", RGB_(0xee, 0xe9, 0xbf) },
- { "LemonChiffon3", RGB_(0xcd, 0xc9, 0xa5) },
- { "LemonChiffon4", RGB_(0x8b, 0x89, 0x70) },
- { "LightBlue", RGB_(0xad, 0xd8, 0xe6) },
- { "LightBlue1", RGB_(0xbf, 0xef, 0xff) },
- { "LightBlue2", RGB_(0xb2, 0xdf, 0xee) },
- { "LightBlue3", RGB_(0x9a, 0xc0, 0xcd) },
- { "LightBlue4", RGB_(0x68, 0x83, 0x8b) },
- { "LightCoral", RGB_(0xf0, 0x80, 0x80) },
- { "LightCyan", RGB_(0xe0, 0xff, 0xff) },
- { "LightCyan1", RGB_(0xe0, 0xff, 0xff) },
- { "LightCyan2", RGB_(0xd1, 0xee, 0xee) },
- { "LightCyan3", RGB_(0xb4, 0xcd, 0xcd) },
- { "LightCyan4", RGB_(0x7a, 0x8b, 0x8b) },
- { "LightGoldenrod", RGB_(0xee, 0xdd, 0x82) },
- { "LightGoldenrod1", RGB_(0xff, 0xec, 0x8b) },
- { "LightGoldenrod2", RGB_(0xee, 0xdc, 0x82) },
- { "LightGoldenrod3", RGB_(0xcd, 0xbe, 0x70) },
- { "LightGoldenrod4", RGB_(0x8b, 0x81, 0x4c) },
- { "LightGoldenRodYellow", RGB_(0xfa, 0xfa, 0xd2) },
- { "LightGray", RGB_(0xd3, 0xd3, 0xd3) },
- { "LightGreen", RGB_(0x90, 0xee, 0x90) },
- { "LightGrey", RGB_(0xd3, 0xd3, 0xd3) },
- { "LightMagenta", RGB_(0xff, 0xbb, 0xff) },
- { "LightPink", RGB_(0xff, 0xb6, 0xc1) },
- { "LightPink1", RGB_(0xff, 0xae, 0xb9) },
- { "LightPink2", RGB_(0xee, 0xa2, 0xad) },
- { "LightPink3", RGB_(0xcd, 0x8c, 0x95) },
- { "LightPink4", RGB_(0x8b, 0x5f, 0x65) },
- { "LightRed", RGB_(0xff, 0xbb, 0xbb) },
- { "LightSalmon", RGB_(0xff, 0xa0, 0x7a) },
- { "LightSalmon1", RGB_(0xff, 0xa0, 0x7a) },
- { "LightSalmon2", RGB_(0xee, 0x95, 0x72) },
- { "LightSalmon3", RGB_(0xcd, 0x81, 0x62) },
- { "LightSalmon4", RGB_(0x8b, 0x57, 0x42) },
- { "LightSeaGreen", RGB_(0x20, 0xb2, 0xaa) },
- { "LightSkyBlue", RGB_(0x87, 0xce, 0xfa) },
- { "LightSkyBlue1", RGB_(0xb0, 0xe2, 0xff) },
- { "LightSkyBlue2", RGB_(0xa4, 0xd3, 0xee) },
- { "LightSkyBlue3", RGB_(0x8d, 0xb6, 0xcd) },
- { "LightSkyBlue4", RGB_(0x60, 0x7b, 0x8b) },
- { "LightSlateBlue", RGB_(0x84, 0x70, 0xff) },
- { "LightSlateGray", RGB_(0x77, 0x88, 0x99) },
- { "LightSlateGrey", RGB_(0x77, 0x88, 0x99) },
- { "LightSteelBlue", RGB_(0xb0, 0xc4, 0xde) },
- { "LightSteelBlue1", RGB_(0xca, 0xe1, 0xff) },
- { "LightSteelBlue2", RGB_(0xbc, 0xd2, 0xee) },
- { "LightSteelBlue3", RGB_(0xa2, 0xb5, 0xcd) },
- { "LightSteelBlue4", RGB_(0x6e, 0x7b, 0x8b) },
- { "LightYellow", RGB_(0xff, 0xff, 0xe0) },
- { "LightYellow1", RGB_(0xff, 0xff, 0xe0) },
- { "LightYellow2", RGB_(0xee, 0xee, 0xd1) },
- { "LightYellow3", RGB_(0xcd, 0xcd, 0xb4) },
- { "LightYellow4", RGB_(0x8b, 0x8b, 0x7a) },
- { "Lime", RGB_(0x00, 0xff, 0x00) },
- { "LimeGreen", RGB_(0x32, 0xcd, 0x32) },
- { "Linen", RGB_(0xfa, 0xf0, 0xe6) },
- { "Magenta", RGB_(0xff, 0x00, 0xff) },
- { "Magenta1", RGB_(0xff, 0x0, 0xff) },
- { "Magenta2", RGB_(0xee, 0x0, 0xee) },
- { "Magenta3", RGB_(0xcd, 0x0, 0xcd) },
- { "Magenta4", RGB_(0x8b, 0x0, 0x8b) },
- { "Maroon", RGB_(0x80, 0x00, 0x00) },
- { "Maroon1", RGB_(0xff, 0x34, 0xb3) },
- { "Maroon2", RGB_(0xee, 0x30, 0xa7) },
- { "Maroon3", RGB_(0xcd, 0x29, 0x90) },
- { "Maroon4", RGB_(0x8b, 0x1c, 0x62) },
- { "MediumAquamarine", RGB_(0x66, 0xcd, 0xaa) },
- { "MediumBlue", RGB_(0x00, 0x00, 0xcd) },
- { "MediumOrchid", RGB_(0xba, 0x55, 0xd3) },
- { "MediumOrchid1", RGB_(0xe0, 0x66, 0xff) },
- { "MediumOrchid2", RGB_(0xd1, 0x5f, 0xee) },
- { "MediumOrchid3", RGB_(0xb4, 0x52, 0xcd) },
- { "MediumOrchid4", RGB_(0x7a, 0x37, 0x8b) },
- { "MediumPurple", RGB_(0x93, 0x70, 0xdb) },
- { "MediumPurple1", RGB_(0xab, 0x82, 0xff) },
- { "MediumPurple2", RGB_(0x9f, 0x79, 0xee) },
- { "MediumPurple3", RGB_(0x89, 0x68, 0xcd) },
- { "MediumPurple4", RGB_(0x5d, 0x47, 0x8b) },
- { "MediumSeaGreen", RGB_(0x3c, 0xb3, 0x71) },
- { "MediumSlateBlue", RGB_(0x7b, 0x68, 0xee) },
- { "MediumSpringGreen", RGB_(0x00, 0xfa, 0x9a) },
- { "MediumTurquoise", RGB_(0x48, 0xd1, 0xcc) },
- { "MediumVioletRed", RGB_(0xc7, 0x15, 0x85) },
- { "MidnightBlue", RGB_(0x19, 0x19, 0x70) },
- { "MintCream", RGB_(0xf5, 0xff, 0xfa) },
- { "MistyRose", RGB_(0xff, 0xe4, 0xe1) },
- { "MistyRose1", RGB_(0xff, 0xe4, 0xe1) },
- { "MistyRose2", RGB_(0xee, 0xd5, 0xd2) },
- { "MistyRose3", RGB_(0xcd, 0xb7, 0xb5) },
- { "MistyRose4", RGB_(0x8b, 0x7d, 0x7b) },
- { "Moccasin", RGB_(0xff, 0xe4, 0xb5) },
- { "NavajoWhite", RGB_(0xff, 0xde, 0xad) },
- { "NavajoWhite1", RGB_(0xff, 0xde, 0xad) },
- { "NavajoWhite2", RGB_(0xee, 0xcf, 0xa1) },
- { "NavajoWhite3", RGB_(0xcd, 0xb3, 0x8b) },
- { "NavajoWhite4", RGB_(0x8b, 0x79, 0x5e) },
- { "Navy", RGB_(0x00, 0x00, 0x80) },
- { "NavyBlue", RGB_(0x0, 0x0, 0x80) },
- { "OldLace", RGB_(0xfd, 0xf5, 0xe6) },
- { "Olive", RGB_(0x80, 0x80, 0x00) },
- { "OliveDrab", RGB_(0x6b, 0x8e, 0x23) },
- { "OliveDrab1", RGB_(0xc0, 0xff, 0x3e) },
- { "OliveDrab2", RGB_(0xb3, 0xee, 0x3a) },
- { "OliveDrab3", RGB_(0x9a, 0xcd, 0x32) },
- { "OliveDrab4", RGB_(0x69, 0x8b, 0x22) },
- { "Orange", RGB_(0xff, 0xa5, 0x00) },
- { "Orange1", RGB_(0xff, 0xa5, 0x0) },
- { "Orange2", RGB_(0xee, 0x9a, 0x0) },
- { "Orange3", RGB_(0xcd, 0x85, 0x0) },
- { "Orange4", RGB_(0x8b, 0x5a, 0x0) },
- { "OrangeRed", RGB_(0xff, 0x45, 0x00) },
- { "OrangeRed1", RGB_(0xff, 0x45, 0x0) },
- { "OrangeRed2", RGB_(0xee, 0x40, 0x0) },
- { "OrangeRed3", RGB_(0xcd, 0x37, 0x0) },
- { "OrangeRed4", RGB_(0x8b, 0x25, 0x0) },
- { "Orchid", RGB_(0xda, 0x70, 0xd6) },
- { "Orchid1", RGB_(0xff, 0x83, 0xfa) },
- { "Orchid2", RGB_(0xee, 0x7a, 0xe9) },
- { "Orchid3", RGB_(0xcd, 0x69, 0xc9) },
- { "Orchid4", RGB_(0x8b, 0x47, 0x89) },
- { "PaleGoldenRod", RGB_(0xee, 0xe8, 0xaa) },
- { "PaleGreen", RGB_(0x98, 0xfb, 0x98) },
- { "PaleGreen1", RGB_(0x9a, 0xff, 0x9a) },
- { "PaleGreen2", RGB_(0x90, 0xee, 0x90) },
- { "PaleGreen3", RGB_(0x7c, 0xcd, 0x7c) },
- { "PaleGreen4", RGB_(0x54, 0x8b, 0x54) },
- { "PaleTurquoise", RGB_(0xaf, 0xee, 0xee) },
- { "PaleTurquoise1", RGB_(0xbb, 0xff, 0xff) },
- { "PaleTurquoise2", RGB_(0xae, 0xee, 0xee) },
- { "PaleTurquoise3", RGB_(0x96, 0xcd, 0xcd) },
- { "PaleTurquoise4", RGB_(0x66, 0x8b, 0x8b) },
- { "PaleVioletRed", RGB_(0xdb, 0x70, 0x93) },
- { "PaleVioletRed1", RGB_(0xff, 0x82, 0xab) },
- { "PaleVioletRed2", RGB_(0xee, 0x79, 0x9f) },
- { "PaleVioletRed3", RGB_(0xcd, 0x68, 0x89) },
- { "PaleVioletRed4", RGB_(0x8b, 0x47, 0x5d) },
- { "PapayaWhip", RGB_(0xff, 0xef, 0xd5) },
- { "PeachPuff", RGB_(0xff, 0xda, 0xb9) },
- { "PeachPuff1", RGB_(0xff, 0xda, 0xb9) },
- { "PeachPuff2", RGB_(0xee, 0xcb, 0xad) },
- { "PeachPuff3", RGB_(0xcd, 0xaf, 0x95) },
- { "PeachPuff4", RGB_(0x8b, 0x77, 0x65) },
- { "Peru", RGB_(0xcd, 0x85, 0x3f) },
- { "Pink", RGB_(0xff, 0xc0, 0xcb) },
- { "Pink1", RGB_(0xff, 0xb5, 0xc5) },
- { "Pink2", RGB_(0xee, 0xa9, 0xb8) },
- { "Pink3", RGB_(0xcd, 0x91, 0x9e) },
- { "Pink4", RGB_(0x8b, 0x63, 0x6c) },
- { "Plum", RGB_(0xdd, 0xa0, 0xdd) },
- { "Plum1", RGB_(0xff, 0xbb, 0xff) },
- { "Plum2", RGB_(0xee, 0xae, 0xee) },
- { "Plum3", RGB_(0xcd, 0x96, 0xcd) },
- { "Plum4", RGB_(0x8b, 0x66, 0x8b) },
- { "PowderBlue", RGB_(0xb0, 0xe0, 0xe6) },
- { "Purple", RGB_(0x80, 0x00, 0x80) },
- { "Purple1", RGB_(0x9b, 0x30, 0xff) },
- { "Purple2", RGB_(0x91, 0x2c, 0xee) },
- { "Purple3", RGB_(0x7d, 0x26, 0xcd) },
- { "Purple4", RGB_(0x55, 0x1a, 0x8b) },
- { "RebeccaPurple", RGB_(0x66, 0x33, 0x99) },
- { "Red", RGB_(0xff, 0x00, 0x00) },
- { "Red1", RGB_(0xff, 0x0, 0x0) },
- { "Red2", RGB_(0xee, 0x0, 0x0) },
- { "Red3", RGB_(0xcd, 0x0, 0x0) },
- { "Red4", RGB_(0x8b, 0x0, 0x0) },
- { "RosyBrown", RGB_(0xbc, 0x8f, 0x8f) },
- { "RosyBrown1", RGB_(0xff, 0xc1, 0xc1) },
- { "RosyBrown2", RGB_(0xee, 0xb4, 0xb4) },
- { "RosyBrown3", RGB_(0xcd, 0x9b, 0x9b) },
- { "RosyBrown4", RGB_(0x8b, 0x69, 0x69) },
- { "RoyalBlue", RGB_(0x41, 0x69, 0xe1) },
- { "RoyalBlue1", RGB_(0x48, 0x76, 0xff) },
- { "RoyalBlue2", RGB_(0x43, 0x6e, 0xee) },
- { "RoyalBlue3", RGB_(0x3a, 0x5f, 0xcd) },
- { "RoyalBlue4", RGB_(0x27, 0x40, 0x8b) },
- { "SaddleBrown", RGB_(0x8b, 0x45, 0x13) },
- { "Salmon", RGB_(0xfa, 0x80, 0x72) },
- { "Salmon1", RGB_(0xff, 0x8c, 0x69) },
- { "Salmon2", RGB_(0xee, 0x82, 0x62) },
- { "Salmon3", RGB_(0xcd, 0x70, 0x54) },
- { "Salmon4", RGB_(0x8b, 0x4c, 0x39) },
- { "SandyBrown", RGB_(0xf4, 0xa4, 0x60) },
- { "SeaGreen", RGB_(0x2e, 0x8b, 0x57) },
- { "SeaGreen1", RGB_(0x54, 0xff, 0x9f) },
- { "SeaGreen2", RGB_(0x4e, 0xee, 0x94) },
- { "SeaGreen3", RGB_(0x43, 0xcd, 0x80) },
- { "SeaGreen4", RGB_(0x2e, 0x8b, 0x57) },
- { "SeaShell", RGB_(0xff, 0xf5, 0xee) },
- { "Seashell1", RGB_(0xff, 0xf5, 0xee) },
- { "Seashell2", RGB_(0xee, 0xe5, 0xde) },
- { "Seashell3", RGB_(0xcd, 0xc5, 0xbf) },
- { "Seashell4", RGB_(0x8b, 0x86, 0x82) },
- { "Sienna", RGB_(0xa0, 0x52, 0x2d) },
- { "Sienna1", RGB_(0xff, 0x82, 0x47) },
- { "Sienna2", RGB_(0xee, 0x79, 0x42) },
- { "Sienna3", RGB_(0xcd, 0x68, 0x39) },
- { "Sienna4", RGB_(0x8b, 0x47, 0x26) },
- { "Silver", RGB_(0xc0, 0xc0, 0xc0) },
- { "SkyBlue", RGB_(0x87, 0xce, 0xeb) },
- { "SkyBlue1", RGB_(0x87, 0xce, 0xff) },
- { "SkyBlue2", RGB_(0x7e, 0xc0, 0xee) },
- { "SkyBlue3", RGB_(0x6c, 0xa6, 0xcd) },
- { "SkyBlue4", RGB_(0x4a, 0x70, 0x8b) },
- { "SlateBlue", RGB_(0x6a, 0x5a, 0xcd) },
- { "SlateBlue1", RGB_(0x83, 0x6f, 0xff) },
- { "SlateBlue2", RGB_(0x7a, 0x67, 0xee) },
- { "SlateBlue3", RGB_(0x69, 0x59, 0xcd) },
- { "SlateBlue4", RGB_(0x47, 0x3c, 0x8b) },
- { "SlateGray", RGB_(0x70, 0x80, 0x90) },
- { "SlateGray1", RGB_(0xc6, 0xe2, 0xff) },
- { "SlateGray2", RGB_(0xb9, 0xd3, 0xee) },
- { "SlateGray3", RGB_(0x9f, 0xb6, 0xcd) },
- { "SlateGray4", RGB_(0x6c, 0x7b, 0x8b) },
- { "SlateGrey", RGB_(0x70, 0x80, 0x90) },
- { "Snow", RGB_(0xff, 0xfa, 0xfa) },
- { "Snow1", RGB_(0xff, 0xfa, 0xfa) },
- { "Snow2", RGB_(0xee, 0xe9, 0xe9) },
- { "Snow3", RGB_(0xcd, 0xc9, 0xc9) },
- { "Snow4", RGB_(0x8b, 0x89, 0x89) },
- { "SpringGreen", RGB_(0x00, 0xff, 0x7f) },
- { "SpringGreen1", RGB_(0x0, 0xff, 0x7f) },
- { "SpringGreen2", RGB_(0x0, 0xee, 0x76) },
- { "SpringGreen3", RGB_(0x0, 0xcd, 0x66) },
- { "SpringGreen4", RGB_(0x0, 0x8b, 0x45) },
- { "SteelBlue", RGB_(0x46, 0x82, 0xb4) },
- { "SteelBlue1", RGB_(0x63, 0xb8, 0xff) },
- { "SteelBlue2", RGB_(0x5c, 0xac, 0xee) },
- { "SteelBlue3", RGB_(0x4f, 0x94, 0xcd) },
- { "SteelBlue4", RGB_(0x36, 0x64, 0x8b) },
- { "Tan", RGB_(0xd2, 0xb4, 0x8c) },
- { "Tan1", RGB_(0xff, 0xa5, 0x4f) },
- { "Tan2", RGB_(0xee, 0x9a, 0x49) },
- { "Tan3", RGB_(0xcd, 0x85, 0x3f) },
- { "Tan4", RGB_(0x8b, 0x5a, 0x2b) },
- { "Teal", RGB_(0x00, 0x80, 0x80) },
- { "Thistle", RGB_(0xd8, 0xbf, 0xd8) },
- { "Thistle1", RGB_(0xff, 0xe1, 0xff) },
- { "Thistle2", RGB_(0xee, 0xd2, 0xee) },
- { "Thistle3", RGB_(0xcd, 0xb5, 0xcd) },
- { "Thistle4", RGB_(0x8b, 0x7b, 0x8b) },
- { "Tomato", RGB_(0xff, 0x63, 0x47) },
- { "Tomato1", RGB_(0xff, 0x63, 0x47) },
- { "Tomato2", RGB_(0xee, 0x5c, 0x42) },
- { "Tomato3", RGB_(0xcd, 0x4f, 0x39) },
- { "Tomato4", RGB_(0x8b, 0x36, 0x26) },
- { "Turquoise", RGB_(0x40, 0xe0, 0xd0) },
- { "Turquoise1", RGB_(0x0, 0xf5, 0xff) },
- { "Turquoise2", RGB_(0x0, 0xe5, 0xee) },
- { "Turquoise3", RGB_(0x0, 0xc5, 0xcd) },
- { "Turquoise4", RGB_(0x0, 0x86, 0x8b) },
- { "Violet", RGB_(0xee, 0x82, 0xee) },
- { "VioletRed", RGB_(0xd0, 0x20, 0x90) },
- { "VioletRed1", RGB_(0xff, 0x3e, 0x96) },
- { "VioletRed2", RGB_(0xee, 0x3a, 0x8c) },
- { "VioletRed3", RGB_(0xcd, 0x32, 0x78) },
- { "VioletRed4", RGB_(0x8b, 0x22, 0x52) },
- { "WebGray", RGB_(0x80, 0x80, 0x80) },
- { "WebGreen", RGB_(0x0, 0x80, 0x0) },
- { "WebGrey", RGB_(0x80, 0x80, 0x80) },
- { "WebMaroon", RGB_(0x80, 0x0, 0x0) },
- { "WebPurple", RGB_(0x80, 0x0, 0x80) },
- { "Wheat", RGB_(0xf5, 0xde, 0xb3) },
- { "Wheat1", RGB_(0xff, 0xe7, 0xba) },
- { "Wheat2", RGB_(0xee, 0xd8, 0xae) },
- { "Wheat3", RGB_(0xcd, 0xba, 0x96) },
- { "Wheat4", RGB_(0x8b, 0x7e, 0x66) },
- { "White", RGB_(0xff, 0xff, 0xff) },
- { "WhiteSmoke", RGB_(0xf5, 0xf5, 0xf5) },
- { "X11Gray", RGB_(0xbe, 0xbe, 0xbe) },
- { "X11Green", RGB_(0x0, 0xff, 0x0) },
- { "X11Grey", RGB_(0xbe, 0xbe, 0xbe) },
- { "X11Maroon", RGB_(0xb0, 0x30, 0x60) },
- { "X11Purple", RGB_(0xa0, 0x20, 0xf0) },
- { "Yellow", RGB_(0xff, 0xff, 0x00) },
- { "Yellow1", RGB_(0xff, 0xff, 0x0) },
- { "Yellow2", RGB_(0xee, 0xee, 0x0) },
- { "Yellow3", RGB_(0xcd, 0xcd, 0x0) },
- { "Yellow4", RGB_(0x8b, 0x8b, 0x0) },
- { "YellowGreen", RGB_(0x9a, 0xcd, 0x32) },
- { NULL, 0 },
-};
-
-
-/// Translate to RgbValue if \p name is an hex value (e.g. #XXXXXX),
-/// else look into color_name_table to translate a color name to its
-/// hex value
-///
-/// @param[in] name string value to convert to RGB
-/// return the hex value or -1 if could not find a correct value
-RgbValue name_to_color(const char *name)
-{
- if (name[0] == '#' && isxdigit(name[1]) && isxdigit(name[2])
- && isxdigit(name[3]) && isxdigit(name[4]) && isxdigit(name[5])
- && isxdigit(name[6]) && name[7] == NUL) {
- // rgb hex string
- return strtol((char *)(name + 1), NULL, 16);
- } else if (!STRICMP(name, "bg") || !STRICMP(name, "background")) {
- return normal_bg;
- } else if (!STRICMP(name, "fg") || !STRICMP(name, "foreground")) {
- return normal_fg;
- }
-
- for (int i = 0; color_name_table[i].name != NULL; i++) {
- if (!STRICMP(name, color_name_table[i].name)) {
- return color_name_table[i].color;
- }
- }
-
- return -1;
-}
-
-int name_to_ctermcolor(const char *name)
-{
- int i;
- int off = TOUPPER_ASC(*name);
- for (i = ARRAY_SIZE(color_names); --i >= 0;) {
- if (off == color_names[i][0]
- && STRICMP(name+1, color_names[i]+1) == 0) {
- break;
- }
- }
- if (i < 0) {
- return -1;
- }
- TriState bold = kNone;
- return lookup_color(i, false, &bold);
-}
-
-/**************************************
-* End of Highlighting stuff *
-**************************************/
diff --git a/src/nvim/syntax.h b/src/nvim/syntax.h
index 15fc084a0a..0d890314c5 100644
--- a/src/nvim/syntax.h
+++ b/src/nvim/syntax.h
@@ -29,12 +29,6 @@
#define SYN_GROUP_STATIC(s) syn_check_group(S_LEN(s))
-typedef struct {
- char *name;
- RgbValue color;
-} color_name_table_T;
-extern color_name_table_T color_name_table[];
-
/// Array of highlight definitions, used for unit testing
extern const char *const highlight_init_cmdline[];
diff --git a/src/nvim/syntax_defs.h b/src/nvim/syntax_defs.h
index 526be905e9..a005f67209 100644
--- a/src/nvim/syntax_defs.h
+++ b/src/nvim/syntax_defs.h
@@ -21,9 +21,7 @@ struct sp_syn {
int16_t *cont_in_list; // cont.in group IDs, if non-zero
};
-/*
- * Each keyword has one keyentry, which is linked in a hash list.
- */
+// Each keyword has one keyentry, which is linked in a hash list.
typedef struct keyentry keyentry_T;
struct keyentry {
@@ -35,9 +33,7 @@ struct keyentry {
char_u keyword[1]; // actually longer
};
-/*
- * Struct used to store one state of the state stack.
- */
+// Struct used to store one state of the state stack.
typedef struct buf_state {
int bs_idx; // index of pattern
int bs_flags; // flags for pattern
@@ -46,10 +42,8 @@ typedef struct buf_state {
reg_extmatch_T *bs_extmatch; // external matches from start pattern
} bufstate_T;
-/*
- * syn_state contains the syntax state stack for the start of one line.
- * Used by b_sst_array[].
- */
+// syn_state contains the syntax state stack for the start of one line.
+// Used by b_sst_array[].
struct syn_state {
synstate_T *sst_next; // next entry in used or free list
linenr_T sst_lnum; // line number for this state
@@ -66,4 +60,4 @@ struct syn_state {
// may have made the state invalid
};
-#endif // NVIM_SYNTAX_DEFS_H
+#endif // NVIM_SYNTAX_DEFS_H
diff --git a/src/nvim/tag.h b/src/nvim/tag.h
index 64bacceb1b..902fe0c7ba 100644
--- a/src/nvim/tag.h
+++ b/src/nvim/tag.h
@@ -4,9 +4,7 @@
#include "nvim/ex_cmds_defs.h"
#include "nvim/types.h"
-/*
- * Values for do_tag().
- */
+// Values for do_tag().
#define DT_TAG 1 // jump to newer position or same tag again
#define DT_POP 2 // jump to older position
#define DT_NEXT 3 // jump to next match of same tag
@@ -20,9 +18,7 @@
#define DT_LTAG 11 // tag using location list
#define DT_FREE 99 // free cached matches
-//
// flags for find_tags().
-//
#define TAG_HELP 1 // only search for help tags
#define TAG_NAMES 2 // only return name of tag
#define TAG_REGEXP 4 // use tag pattern as regexp
@@ -36,9 +32,7 @@
#define TAG_MANY 300 // When finding many tags (for completion),
// find up to this many tags
-/*
- * Structure used for get_tagfname().
- */
+// Structure used for get_tagfname().
typedef struct {
char_u *tn_tags; // value of 'tags' when starting
char_u *tn_np; // current position in tn_tags
diff --git a/src/nvim/terminal.c b/src/nvim/terminal.c
index 1c26e46a21..5c8789ec37 100644
--- a/src/nvim/terminal.c
+++ b/src/nvim/terminal.c
@@ -55,6 +55,7 @@
#include "nvim/fileio.h"
#include "nvim/getchar.h"
#include "nvim/highlight.h"
+#include "nvim/highlight_group.h"
#include "nvim/keymap.h"
#include "nvim/log.h"
#include "nvim/macros.h"
@@ -70,7 +71,6 @@
#include "nvim/os/input.h"
#include "nvim/screen.h"
#include "nvim/state.h"
-#include "nvim/syntax.h"
#include "nvim/terminal.h"
#include "nvim/ui.h"
#include "nvim/vim.h"
@@ -317,10 +317,14 @@ void terminal_close(Terminal *term, int status)
term->opts.close_cb(term->opts.data);
}
} else if (!only_destroy) {
- // This was called by channel_process_exit_cb() not in process_teardown().
+ // Associated channel has been closed and the editor is not exiting.
// Do not call the close callback now. Wait for the user to press a key.
char msg[sizeof("\r\n[Process exited ]") + NUMBUFLEN];
- snprintf(msg, sizeof msg, "\r\n[Process exited %d]", status);
+ if (((Channel *)term->opts.data)->streamtype == kChannelStreamInternal) {
+ snprintf(msg, sizeof msg, "\r\n[Terminal closed]");
+ } else {
+ snprintf(msg, sizeof msg, "\r\n[Process exited %d]", status);
+ }
terminal_receive(term, msg, strlen(msg));
}
@@ -1284,7 +1288,7 @@ static bool send_mouse_event(Terminal *term, int c)
return mouse_win == curwin;
}
- // ignore left release action if it was not proccessed above
+ // ignore left release action if it was not processed above
// to prevent leaving Terminal mode after entering to it using a mouse
if (c == K_LEFTRELEASE && mouse_win->w_buffer->terminal == term) {
return false;
diff --git a/src/nvim/testdir/check.vim b/src/nvim/testdir/check.vim
index 883f036fe1..8f97d959ce 100644
--- a/src/nvim/testdir/check.vim
+++ b/src/nvim/testdir/check.vim
@@ -137,6 +137,14 @@ func CheckNotMSWindows()
endif
endfunc
+" Command to check for not running under ASAN
+command CheckNotAsan call CheckNotAsan()
+func CheckNotAsan()
+ if execute('version') =~# '-fsanitize=[a-z,]*\<address\>'
+ throw 'Skipped: does not work with ASAN'
+ endif
+endfunc
+
" Command to check for satisfying any of the conditions.
" e.g. CheckAnyOf Feature:bsd Feature:sun Linux
command -nargs=+ CheckAnyOf call CheckAnyOf(<f-args>)
diff --git a/src/nvim/testdir/runnvim.sh b/src/nvim/testdir/runnvim.sh
index 72d88f9f93..322265737a 100755
--- a/src/nvim/testdir/runnvim.sh
+++ b/src/nvim/testdir/runnvim.sh
@@ -38,7 +38,7 @@ main() {(
-S runnvim.vim \
"$tlog" > "out-$tlog" 2> "err-$tlog"
then
- fail "$test_name" F "Nvim exited with non-zero code"
+ fail "$test_name" "Nvim exited with non-zero code"
fi
{
echo "Stdout of :terminal runner"
@@ -53,7 +53,7 @@ main() {(
if test "$oldesttest" = 1 ; then
if ! diff -q test.out "$test_name.ok" > /dev/null 2>&1 ; then
if test -f test.out ; then
- fail "$test_name" F "Oldest test .out file differs from .ok file"
+ fail "$test_name" "Oldest test .out file differs from .ok file"
{
echo "Diff between test.out and $test_name.ok"
echo "$separator"
diff --git a/src/nvim/testdir/test_cmdline.vim b/src/nvim/testdir/test_cmdline.vim
index ff4cbe544c..c589d941da 100644
--- a/src/nvim/testdir/test_cmdline.vim
+++ b/src/nvim/testdir/test_cmdline.vim
@@ -1123,6 +1123,18 @@ func Test_cmdlineclear_tabenter()
call delete('XtestCmdlineClearTabenter')
endfunc
+func Test_cmdwin_tabpage()
+ tabedit
+ " v8.2.1919 isn't ported yet, so E492 is thrown after E11 here.
+ " v8.2.1183 also isn't ported yet, so we also can't assert E11 directly.
+ " For now, assert E11 and E492 seperately. When v8.2.1183 is ported, the
+ " assert for E492 will fail and this workaround should be removed.
+ " call assert_fails("silent norm q/g :I\<Esc>", 'E11:')
+ call assert_fails("silent norm q/g ", 'E11:')
+ call assert_fails("silent norm q/g :I\<Esc>", 'E492:')
+ tabclose!
+endfunc
+
" test that ";" works to find a match at the start of the first line
func Test_zero_line_search()
new
diff --git a/src/nvim/testdir/test_exit.vim b/src/nvim/testdir/test_exit.vim
index bd3e9eb4d4..befcaec2b2 100644
--- a/src/nvim/testdir/test_exit.vim
+++ b/src/nvim/testdir/test_exit.vim
@@ -1,6 +1,7 @@
" Tests for exiting Vim.
source shared.vim
+source check.vim
func Test_exiting()
let after =<< trim [CODE]
@@ -109,4 +110,25 @@ func Test_exit_code()
call delete('Xtestout')
endfunc
+func Test_exit_error_reading_input()
+ throw 'Skipped: Nvim does not exit after stdin is read'
+
+ CheckNotGui
+ CheckNotMSWindows
+ " The early exit causes memory not to be freed somehow
+ CheckNotAsan
+
+ call writefile([":au VimLeave * call writefile(['l = ' .. v:exiting], 'Xtestout')", ":tabnew", "q:"], 'Xscript', 'b')
+
+ " Nvim requires "-s -" to read stdin as Normal mode input
+ " if RunVim([], [], '<Xscript')
+ if RunVim([], [], '-s - <Xscript')
+ call assert_equal(1, v:shell_error)
+ call assert_equal(['l = 1'], readfile('Xtestout'))
+ endif
+ call delete('Xscript')
+ call delete('Xtestout')
+endfun
+
+
" vim: shiftwidth=2 sts=2 expandtab
diff --git a/src/nvim/testdir/test_filetype.vim b/src/nvim/testdir/test_filetype.vim
index 5f4a7dac6e..839d160e39 100644
--- a/src/nvim/testdir/test_filetype.vim
+++ b/src/nvim/testdir/test_filetype.vim
@@ -196,7 +196,7 @@ let s:filename_checks = {
\ 'fstab': ['fstab', 'mtab'],
\ 'fusion': ['file.fusion'],
\ 'fvwm': ['/.fvwm/file', 'any/.fvwm/file'],
- \ 'gdb': ['.gdbinit', 'gdbinit'],
+ \ 'gdb': ['.gdbinit', 'gdbinit', 'file.gdb', '.config/gdbearlyinit', '.gdbearlyinit'],
\ 'gdresource': ['file.tscn', 'file.tres'],
\ 'gdscript': ['file.gd'],
\ 'gdmo': ['file.mo', 'file.gdmo'],
diff --git a/src/nvim/testdir/test_functions.vim b/src/nvim/testdir/test_functions.vim
index 994d74601a..c2b5653a29 100644
--- a/src/nvim/testdir/test_functions.vim
+++ b/src/nvim/testdir/test_functions.vim
@@ -1762,6 +1762,75 @@ func Test_getcurpos_setpos()
call assert_equal([0, 0, 0, 0, 0], getcurpos(1999))
endfunc
+func Test_getmousepos()
+ enew!
+ call setline(1, "\t\t\t1234")
+ " call test_setmouse(1, 1)
+ call nvim_input_mouse('left', 'press', '', 0, 0, 0)
+ call getchar() " wait for and consume the mouse press
+ call assert_equal(#{
+ \ screenrow: 1,
+ \ screencol: 1,
+ \ winid: win_getid(),
+ \ winrow: 1,
+ \ wincol: 1,
+ \ line: 1,
+ \ column: 1,
+ \ }, getmousepos())
+ " call test_setmouse(1, 25)
+ call nvim_input_mouse('left', 'press', '', 0, 0, 24)
+ call getchar() " wait for and consume the mouse press
+ call assert_equal(#{
+ \ screenrow: 1,
+ \ screencol: 25,
+ \ winid: win_getid(),
+ \ winrow: 1,
+ \ wincol: 25,
+ \ line: 1,
+ \ column: 4,
+ \ }, getmousepos())
+ " call test_setmouse(1, 50)
+ call nvim_input_mouse('left', 'press', '', 0, 0, 49)
+ call getchar() " wait for and consume the mouse press
+ call assert_equal(#{
+ \ screenrow: 1,
+ \ screencol: 50,
+ \ winid: win_getid(),
+ \ winrow: 1,
+ \ wincol: 50,
+ \ line: 1,
+ \ column: 8,
+ \ }, getmousepos())
+
+ " If the mouse is positioned past the last buffer line, "line" and "column"
+ " should act like it's positioned on the last buffer line.
+ " call test_setmouse(2, 25)
+ call nvim_input_mouse('left', 'press', '', 0, 1, 24)
+ call getchar() " wait for and consume the mouse press
+ call assert_equal(#{
+ \ screenrow: 2,
+ \ screencol: 25,
+ \ winid: win_getid(),
+ \ winrow: 2,
+ \ wincol: 25,
+ \ line: 1,
+ \ column: 4,
+ \ }, getmousepos())
+ " call test_setmouse(2, 50)
+ call nvim_input_mouse('left', 'press', '', 0, 1, 49)
+ call getchar() " wait for and consume the mouse press
+ call assert_equal(#{
+ \ screenrow: 2,
+ \ screencol: 50,
+ \ winid: win_getid(),
+ \ winrow: 2,
+ \ wincol: 50,
+ \ line: 1,
+ \ column: 8,
+ \ }, getmousepos())
+ bwipe!
+endfunc
+
func HasDefault(msg = 'msg')
return a:msg
endfunc
diff --git a/src/nvim/testdir/test_highlight.vim b/src/nvim/testdir/test_highlight.vim
index 6971ecd357..aa7b3a225b 100644
--- a/src/nvim/testdir/test_highlight.vim
+++ b/src/nvim/testdir/test_highlight.vim
@@ -146,7 +146,7 @@ func Test_highlight_eol_with_cursorline_vertsplit()
" 'abcd |abcd '
" ^^^^ ^^^^^^^^^ no highlight
" ^ 'Search' highlight
- " ^ 'VertSplit' highlight
+ " ^ 'WinSeparator' highlight
let attrs0 = ScreenAttrs(1, 15)[0]
call assert_equal(repeat([attrs0[0]], 4), attrs0[0:3])
call assert_equal(repeat([attrs0[0]], 9), attrs0[6:14])
@@ -160,7 +160,7 @@ func Test_highlight_eol_with_cursorline_vertsplit()
" 'abcd |abcd '
" ^^^^ underline
" ^ 'Search' highlight with underline
- " ^ 'VertSplit' highlight
+ " ^ 'WinSeparator' highlight
" ^^^^^^^^^ no highlight
" underline
diff --git a/src/nvim/testdir/test_mksession.vim b/src/nvim/testdir/test_mksession.vim
index a8e50af510..798cb9e54f 100644
--- a/src/nvim/testdir/test_mksession.vim
+++ b/src/nvim/testdir/test_mksession.vim
@@ -219,6 +219,7 @@ func Test_mksession_one_buffer_two_windows()
let count1 = 0
let count2 = 0
let count2buf = 0
+ let bufexists = 0
for line in lines
if line =~ 'edit \f*Xtest1$'
let count1 += 1
@@ -229,10 +230,14 @@ func Test_mksession_one_buffer_two_windows()
if line =~ 'buffer \f\{-}Xtest2'
let count2buf += 1
endif
+ if line =~ 'bufexists(fnamemodify(.*, ":p")'
+ let bufexists += 1
+ endif
endfor
call assert_equal(1, count1, 'Xtest1 count')
call assert_equal(2, count2, 'Xtest2 count')
call assert_equal(2, count2buf, 'Xtest2 buffer count')
+ call assert_equal(2, bufexists)
close
bwipe!
diff --git a/src/nvim/testdir/test_quickfix.vim b/src/nvim/testdir/test_quickfix.vim
index 6852f53ea8..14d13049d9 100644
--- a/src/nvim/testdir/test_quickfix.vim
+++ b/src/nvim/testdir/test_quickfix.vim
@@ -1,4 +1,4 @@
-" Test for the quickfix commands.
+" Test for the quickfix feature.
source check.vim
CheckFeature quickfix
@@ -169,8 +169,8 @@ func XlistTests(cchar)
\ {'lnum':30,'col':15,'type':'W','filename':'Data/Text.hs','text':'FileWarning','nr':33,'valid':v:true}])
let l = split(execute('Xlist', ""), "\n")
call assert_equal([' 1 Data.Text:10 col 5 warning 11: ModuleWarning',
- \ ' 2 Data.Text:20 col 10 warning 22: ModuleWarning',
- \ ' 3 Data/Text.hs:30 col 15 warning 33: FileWarning'], l)
+ \ ' 2 Data.Text:20 col 10 warning 22: ModuleWarning',
+ \ ' 3 Data/Text.hs:30 col 15 warning 33: FileWarning'], l)
" For help entries in the quickfix list, only the filename without directory
" should be displayed
@@ -1655,7 +1655,7 @@ func XquickfixSetListWithAct(cchar)
\ {'filename': 'fnameD', 'text': 'D'},
\ {'filename': 'fnameE', 'text': 'E'}]
- " {action} is unspecified. Same as specifing ' '.
+ " {action} is unspecified. Same as specifying ' '.
new | only
silent! Xnewer 99
call g:Xsetlist(list1)
@@ -2020,6 +2020,7 @@ func s:test_xgrep(cchar)
enew
set makeef=Temp_File_##
silent Xgrepadd GrepAdd_Test_Text: test_quickfix.vim
+ call assert_true(len(g:Xgetlist()) == 9)
" Try with 'grepprg' set to 'internal'
set grepprg=internal
@@ -2028,12 +2029,12 @@ func s:test_xgrep(cchar)
call assert_true(len(g:Xgetlist()) == 9)
set grepprg&vim
- call writefile(['Vim'], 'XtestTempFile')
- set makeef=XtestTempFile
- silent Xgrep Grep_Test_Text: test_quickfix.vim
- call assert_equal(5, len(g:Xgetlist()))
- call assert_false(filereadable('XtestTempFile'))
- set makeef&vim
+ call writefile(['Vim'], 'XtestTempFile')
+ set makeef=XtestTempFile
+ silent Xgrep Grep_Test_Text: test_quickfix.vim
+ call assert_equal(5, len(g:Xgetlist()))
+ call assert_false(filereadable('XtestTempFile'))
+ set makeef&vim
endfunc
func Test_grep()
@@ -2706,7 +2707,7 @@ func Test_cwindow_jump()
" Open a new window and create a location list
" Open the location list window and close the other window
" Jump to an entry.
- " Should create a new window and jump to the entry. The scrtach buffer
+ " Should create a new window and jump to the entry. The scratch buffer
" should not be used.
enew | only
set buftype=nofile
@@ -2739,6 +2740,25 @@ func Test_cwindow_jump()
call assert_true(winnr('$') == 2)
call assert_true(winnr() == 1)
+ " open the quickfix buffer in two windows and jump to an entry. Should open
+ " the file in the first quickfix window.
+ enew | only
+ copen
+ let bnum = bufnr('')
+ exe 'sbuffer ' . bnum
+ wincmd b
+ cfirst
+ call assert_equal(2, winnr())
+ call assert_equal('F1', bufname(''))
+ enew | only
+ exe 'sb' bnum
+ exe 'botright sb' bnum
+ wincmd t
+ clast
+ call assert_equal(2, winnr())
+ call assert_equal('quickfix', getwinvar(1, '&buftype'))
+ call assert_equal('quickfix', getwinvar(3, '&buftype'))
+
" Jumping to a file from the location list window should find a usable
" window by wrapping around the window list.
enew | only
@@ -3548,20 +3568,21 @@ func Xgetlist_empty_tests(cchar)
call assert_equal(0, g:Xgetlist({'changedtick' : 0}).changedtick)
if a:cchar == 'c'
call assert_equal({'context' : '', 'id' : 0, 'idx' : 0,
- \ 'items' : [], 'nr' : 0, 'size' : 0,
+ \ 'items' : [], 'nr' : 0, 'size' : 0, 'qfbufnr' : 0,
\ 'title' : '', 'winid' : 0, 'changedtick': 0,
\ 'quickfixtextfunc' : ''}, g:Xgetlist({'all' : 0}))
else
call assert_equal({'context' : '', 'id' : 0, 'idx' : 0,
\ 'items' : [], 'nr' : 0, 'size' : 0, 'title' : '',
\ 'winid' : 0, 'changedtick': 0, 'filewinid' : 0,
- \ 'quickfixtextfunc' : ''},
+ \ 'qfbufnr' : 0, 'quickfixtextfunc' : ''},
\ g:Xgetlist({'all' : 0}))
endif
" Quickfix window with empty stack
silent! Xopen
let qfwinid = (a:cchar == 'c') ? win_getid() : 0
+ let qfbufnr = (a:cchar == 'c') ? bufnr('') : 0
call assert_equal(qfwinid, g:Xgetlist({'winid' : 0}).winid)
Xclose
@@ -3593,12 +3614,12 @@ func Xgetlist_empty_tests(cchar)
if a:cchar == 'c'
call assert_equal({'context' : '', 'id' : 0, 'idx' : 0, 'items' : [],
\ 'nr' : 0, 'size' : 0, 'title' : '', 'winid' : 0,
- \ 'quickfixtextfunc' : '',
+ \ 'qfbufnr' : qfbufnr, 'quickfixtextfunc' : '',
\ 'changedtick' : 0}, g:Xgetlist({'id' : qfid, 'all' : 0}))
else
call assert_equal({'context' : '', 'id' : 0, 'idx' : 0, 'items' : [],
\ 'nr' : 0, 'size' : 0, 'title' : '', 'winid' : 0,
- \ 'changedtick' : 0, 'filewinid' : 0,
+ \ 'changedtick' : 0, 'filewinid' : 0, 'qfbufnr' : 0,
\ 'quickfixtextfunc' : ''},
\ g:Xgetlist({'id' : qfid, 'all' : 0}))
endif
@@ -3616,12 +3637,12 @@ func Xgetlist_empty_tests(cchar)
if a:cchar == 'c'
call assert_equal({'context' : '', 'id' : 0, 'idx' : 0, 'items' : [],
\ 'nr' : 0, 'size' : 0, 'title' : '', 'winid' : 0,
- \ 'changedtick' : 0,
+ \ 'changedtick' : 0, 'qfbufnr' : qfbufnr,
\ 'quickfixtextfunc' : ''}, g:Xgetlist({'nr' : 5, 'all' : 0}))
else
call assert_equal({'context' : '', 'id' : 0, 'idx' : 0, 'items' : [],
\ 'nr' : 0, 'size' : 0, 'title' : '', 'winid' : 0,
- \ 'changedtick' : 0, 'filewinid' : 0,
+ \ 'changedtick' : 0, 'filewinid' : 0, 'qfbufnr' : 0,
\ 'quickfixtextfunc' : ''}, g:Xgetlist({'nr' : 5, 'all' : 0}))
endif
endfunc
@@ -4360,7 +4381,7 @@ func Test_splitview()
new | only
" When split opening files from a helpgrep location list window, a new help
- " window should be opend with a copy of the location list.
+ " window should be opened with a copy of the location list.
lhelpgrep window
let locid = getloclist(0, {'id' : 0}).id
lwindow
@@ -4456,11 +4477,19 @@ func Xqfbuf_test(cchar)
Xclose
" Even after the quickfix window is closed, the buffer should be loaded
call assert_true(bufloaded(qfbnum))
+ call assert_true(qfbnum, g:Xgetlist({'qfbufnr' : 0}).qfbufnr)
Xopen
" Buffer should be reused when opening the window again
call assert_equal(qfbnum, bufnr(''))
Xclose
+ " When quickfix buffer is wiped out, getqflist() should return 0
+ %bw!
+ Xexpr ""
+ Xopen
+ bw!
+ call assert_equal(0, g:Xgetlist({'qfbufnr': 0}).qfbufnr)
+
if a:cchar == 'l'
%bwipe
" For a location list, when both the file window and the location list
@@ -4474,7 +4503,7 @@ func Xqfbuf_test(cchar)
close
" When the location list window is closed, the buffer name should not
" change to 'Quickfix List'
- call assert_match(qfbnum . ' h- "\[Location List]"', execute('ls'))
+ call assert_match(qfbnum . 'u h- "\[Location List]"', execute('ls!'))
call assert_true(bufloaded(qfbnum))
" After deleting a location list buffer using ":bdelete", opening the
@@ -4491,6 +4520,7 @@ func Xqfbuf_test(cchar)
" removed
call setloclist(0, [], 'f')
call assert_false(bufexists(qfbnum))
+ call assert_equal(0, getloclist(0, {'qfbufnr' : 0}).qfbufnr)
" When the location list is freed with the location list window open, the
" location list buffer should not be lost. It should be reused when the
@@ -4515,11 +4545,36 @@ func Xqfbuf_test(cchar)
endfunc
func Test_qfbuf()
- throw 'skipped: enable after porting patch 8.1.0877'
call Xqfbuf_test('c')
call Xqfbuf_test('l')
endfunc
+" If there is an autocmd to use only one window, then opening the location
+" list window used to crash Vim.
+func Test_winonly_autocmd()
+ call s:create_test_file('Xtest1')
+ " Autocmd to show only one Vim window at a time
+ autocmd WinEnter * only
+ new
+ " Load the location list
+ lexpr "Xtest1:5:Line5\nXtest1:10:Line10\nXtest1:15:Line15"
+ let loclistid = getloclist(0, {'id' : 0}).id
+ " Open the location list window. Only this window will be shown and the file
+ " window is closed.
+ lopen
+ call assert_equal(loclistid, getloclist(0, {'id' : 0}).id)
+ " Jump to an entry in the location list and make sure that the cursor is
+ " positioned correctly.
+ ll 3
+ call assert_equal(loclistid, getloclist(0, {'id' : 0}).id)
+ call assert_equal('Xtest1', bufname(''))
+ call assert_equal(15, line('.'))
+ " Cleanup
+ autocmd! WinEnter
+ new | only
+ call delete('Xtest1')
+endfunc
+
" Test to make sure that an empty quickfix buffer is not reused for loading
" a normal buffer.
func Test_empty_qfbuf()
@@ -5207,16 +5262,14 @@ func Xtest_qftextfunc(cchar)
" Non-existing function
set quickfixtextfunc=Tabc
- " call assert_fails("Xexpr ['F1:10:2:green', 'F1:20:4:blue']", 'E117:')
- Xexpr ['F1:10:2:green', 'F1:20:4:blue']"
+ call assert_fails("Xexpr ['F1:10:2:green', 'F1:20:4:blue']", 'E117:')
call assert_fails("Xwindow", 'E117:')
Xclose
set quickfixtextfunc&
" set option to a non-function
set quickfixtextfunc=[10,\ 20]
- " call assert_fails("Xexpr ['F1:10:2:green', 'F1:20:4:blue']", 'E117:')
- Xexpr ['F1:10:2:green', 'F1:20:4:blue']"
+ call assert_fails("Xexpr ['F1:10:2:green', 'F1:20:4:blue']", 'E117:')
call assert_fails("Xwindow", 'E117:')
Xclose
set quickfixtextfunc&
@@ -5226,8 +5279,7 @@ func Xtest_qftextfunc(cchar)
return a:a .. a:b .. a:c
endfunc
set quickfixtextfunc=Xqftext
- " call assert_fails("Xexpr ['F1:10:2:green', 'F1:20:4:blue']", 'E119:')
- Xexpr ['F1:10:2:green', 'F1:20:4:blue']"
+ call assert_fails("Xexpr ['F1:10:2:green', 'F1:20:4:blue']", 'E119:')
call assert_fails("Xwindow", 'E119:')
Xclose
@@ -5236,9 +5288,8 @@ func Xtest_qftextfunc(cchar)
return ['one', [], 'two']
endfunc
set quickfixtextfunc=Xqftext2
- " call assert_fails("Xexpr ['F1:10:2:green', 'F1:20:4:blue', 'F1:30:6:red']",
- " \ 'E730:')
- Xexpr ['F1:10:2:green', 'F1:20:4:blue', 'F1:30:6:red']
+ call assert_fails("Xexpr ['F1:10:2:green', 'F1:20:4:blue', 'F1:30:6:red']",
+ \ 'E730:')
call assert_fails('Xwindow', 'E730:')
call assert_equal(['one', 'F1|20 col 4| blue', 'F1|30 col 6| red'],
\ getline(1, '$'))
@@ -5402,4 +5453,40 @@ func Test_win_gettype()
lclose
endfunc
+" Test for opening the quickfix window in two tab pages and then closing one
+" of the quickfix windows. This should not make the quickfix buffer unlisted.
+" (github issue #9300).
+func Test_two_qf_windows()
+ cexpr "F1:1:line1"
+ copen
+ tabnew
+ copen
+ call assert_true(&buflisted)
+ cclose
+ tabfirst
+ call assert_true(&buflisted)
+ let bnum = bufnr()
+ cclose
+ " if all the quickfix windows are closed, then buffer should be unlisted.
+ call assert_false(buflisted(bnum))
+ %bw!
+
+ " Repeat the test for a location list
+ lexpr "F2:2:line2"
+ lopen
+ let bnum = bufnr()
+ tabnew
+ exe "buffer" bnum
+ tabfirst
+ lclose
+ tablast
+ call assert_true(buflisted(bnum))
+ tabclose
+ lopen
+ call assert_true(buflisted(bnum))
+ lclose
+ call assert_false(buflisted(bnum))
+ %bw!
+endfunc
+
" vim: shiftwidth=2 sts=2 expandtab
diff --git a/src/nvim/testdir/test_tabpage.vim b/src/nvim/testdir/test_tabpage.vim
index 9869dc7590..51ab5c1022 100644
--- a/src/nvim/testdir/test_tabpage.vim
+++ b/src/nvim/testdir/test_tabpage.vim
@@ -128,6 +128,8 @@ function Test_tabpage()
1tabmove
call assert_equal(2, tabpagenr())
+ call assert_fails('let t = tabpagenr("@")', 'E15:')
+ call assert_equal(0, tabpagewinnr(-1))
call assert_fails("99tabmove", 'E16:')
call assert_fails("+99tabmove", 'E16:')
call assert_fails("-99tabmove", 'E16:')
@@ -683,4 +685,73 @@ func Test_tabline_tabmenu()
%bw!
endfunc
+" Test for jumping to last accessed tabpage
+func Test_lastused_tabpage()
+ tabonly!
+ call assert_equal(0, tabpagenr('#'))
+ call assert_beeps('call feedkeys("g\<Tab>", "xt")')
+ call assert_beeps('call feedkeys("\<C-Tab>", "xt")')
+ call assert_beeps('call feedkeys("\<C-W>g\<Tab>", "xt")')
+ call assert_fails('tabnext #', 'E475:')
+
+ " open four tab pages
+ tabnew
+ tabnew
+ tabnew
+
+ 2tabnext
+
+ " Test for g<Tab>
+ call assert_equal(4, tabpagenr('#'))
+ call feedkeys("g\<Tab>", "xt")
+ call assert_equal(4, tabpagenr())
+ call assert_equal(2, tabpagenr('#'))
+
+ " Test for <C-Tab>
+ call feedkeys("\<C-Tab>", "xt")
+ call assert_equal(2, tabpagenr())
+ call assert_equal(4, tabpagenr('#'))
+
+ " Test for <C-W>g<Tab>
+ call feedkeys("\<C-W>g\<Tab>", "xt")
+ call assert_equal(4, tabpagenr())
+ call assert_equal(2, tabpagenr('#'))
+
+ " Test for :tabnext #
+ tabnext #
+ call assert_equal(2, tabpagenr())
+ call assert_equal(4, tabpagenr('#'))
+
+ " Try to jump to a closed tab page
+ tabclose #
+ call assert_equal(0, tabpagenr('#'))
+ call feedkeys("g\<Tab>", "xt")
+ call assert_equal(2, tabpagenr())
+ call feedkeys("\<C-Tab>", "xt")
+ call assert_equal(2, tabpagenr())
+ call feedkeys("\<C-W>g\<Tab>", "xt")
+ call assert_equal(2, tabpagenr())
+ call assert_fails('tabnext #', 'E475:')
+ call assert_equal(2, tabpagenr())
+
+ " Test for :tabonly #
+ let wnum = win_getid()
+ $tabnew
+ tabonly #
+ call assert_equal(wnum, win_getid())
+ call assert_equal(1, tabpagenr('$'))
+
+ " Test for :tabmove #
+ tabnew
+ let wnum = win_getid()
+ tabnew
+ tabnew
+ tabnext 2
+ tabmove #
+ call assert_equal(4, tabpagenr())
+ call assert_equal(wnum, win_getid())
+
+ tabonly!
+endfunc
+
" vim: shiftwidth=2 sts=2 expandtab
diff --git a/src/nvim/tui/input.c b/src/nvim/tui/input.c
index b262fc6c54..917847608a 100644
--- a/src/nvim/tui/input.c
+++ b/src/nvim/tui/input.c
@@ -19,6 +19,7 @@
# include "nvim/os/os_win_console.h"
#endif
#include "nvim/event/rstream.h"
+#include "nvim/msgpack_rpc/channel.h"
#define KEY_BUFFER_SIZE 0xfff
@@ -115,6 +116,7 @@ static void tinput_wait_enqueue(void **argv)
{
TermInput *input = argv[0];
if (rbuffer_size(input->key_buffer) == 0 && input->paste == 3) {
+ // End streamed paste with an empty string.
const String keys = { .data = "", .size = 0 };
String copy = copy_string(keys);
multiqueue_put(main_loop.events, tinput_paste_event, 3,
@@ -124,8 +126,16 @@ static void tinput_wait_enqueue(void **argv)
const String keys = { .data = buf, .size = len };
if (input->paste) {
String copy = copy_string(keys);
- multiqueue_put(main_loop.events, tinput_paste_event, 3,
- copy.data, copy.size, (intptr_t)input->paste);
+ if (ui_client_channel_id) {
+ Array args = ARRAY_DICT_INIT;
+ ADD(args, STRING_OBJ(copy_string(keys))); // 'data'
+ ADD(args, BOOLEAN_OBJ(true)); // 'crlf'
+ ADD(args, INTEGER_OBJ(input->paste)); // 'phase'
+ rpc_send_event(ui_client_channel_id, "nvim_paste", args);
+ } else {
+ multiqueue_put(main_loop.events, tinput_paste_event, 3,
+ copy.data, copy.size, (intptr_t)input->paste);
+ }
if (input->paste == 1) {
// Paste phase: "continue"
input->paste = 2;
@@ -133,7 +143,17 @@ static void tinput_wait_enqueue(void **argv)
rbuffer_consumed(input->key_buffer, len);
rbuffer_reset(input->key_buffer);
} else {
- const size_t consumed = input_enqueue(keys);
+ size_t consumed;
+ if (ui_client_channel_id) {
+ Array args = ARRAY_DICT_INIT;
+ Error err = ERROR_INIT;
+ ADD(args, STRING_OBJ(copy_string(keys)));
+ // TODO(bfredl): could be non-blocking now with paste?
+ Object result = rpc_send_call(ui_client_channel_id, "nvim_input", args, &err);
+ consumed = result.type == kObjectTypeInteger ? (size_t)result.data.integer : 0;
+ } else {
+ consumed = input_enqueue(keys);
+ }
if (consumed) {
rbuffer_consumed(input->key_buffer, consumed);
}
diff --git a/src/nvim/ui.c b/src/nvim/ui.c
index 7c67c058b0..da50f068b7 100644
--- a/src/nvim/ui.c
+++ b/src/nvim/ui.c
@@ -12,6 +12,7 @@
#include "nvim/charset.h"
#include "nvim/cursor.h"
#include "nvim/cursor_shape.h"
+#include "nvim/msgpack_rpc/channel.h"
#include "nvim/diff.h"
#include "nvim/event/loop.h"
#include "nvim/ex_cmds2.h"
@@ -224,7 +225,21 @@ void ui_refresh(void)
int save_p_lz = p_lz;
p_lz = false; // convince redrawing() to return true ...
- screen_resize(width, height);
+ if (!ui_client_channel_id) {
+ screen_resize(width, height);
+ } else {
+ Array args = ARRAY_DICT_INIT;
+ Error err = ERROR_INIT;
+ ADD(args, INTEGER_OBJ((int)width));
+ ADD(args, INTEGER_OBJ((int)height));
+ rpc_send_call(ui_client_channel_id, "nvim_ui_try_resize", args, &err);
+
+ if (ERROR_SET(&err)) {
+ ELOG("ui_client resize: %s", err.msg);
+ }
+ api_clear_error(&err);
+ }
+
p_lz = save_p_lz;
if (ext_widgets[kUIMessages]) {
diff --git a/src/nvim/ui_client.c b/src/nvim/ui_client.c
new file mode 100644
index 0000000000..6e45a28e89
--- /dev/null
+++ b/src/nvim/ui_client.c
@@ -0,0 +1,215 @@
+// This is an open source non-commercial project. Dear PVS-Studio, please check
+// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+
+#include <stdbool.h>
+#include <stdint.h>
+#include <assert.h>
+
+#include "nvim/vim.h"
+#include "nvim/log.h"
+#include "nvim/map.h"
+#include "nvim/ui_client.h"
+#include "nvim/api/private/helpers.h"
+#include "nvim/msgpack_rpc/channel.h"
+#include "nvim/api/private/dispatch.h"
+#include "nvim/ui.h"
+#include "nvim/highlight.h"
+#include "nvim/screen.h"
+
+static Map(String, UIClientHandler) ui_client_handlers = MAP_INIT;
+
+// Temporary buffer for converting a single grid_line event
+static size_t buf_size = 0;
+static schar_T *buf_char = NULL;
+static sattr_T *buf_attr = NULL;
+
+static void add_ui_client_event_handler(String method, UIClientHandler handler)
+{
+ map_put(String, UIClientHandler)(&ui_client_handlers, method, handler);
+}
+
+void ui_client_init(uint64_t chan)
+{
+ Array args = ARRAY_DICT_INIT;
+ int width = Columns;
+ int height = Rows;
+ Dictionary opts = ARRAY_DICT_INIT;
+
+ PUT(opts, "rgb", BOOLEAN_OBJ(true));
+ PUT(opts, "ext_linegrid", BOOLEAN_OBJ(true));
+ PUT(opts, "ext_termcolors", BOOLEAN_OBJ(true));
+
+ ADD(args, INTEGER_OBJ((int)width));
+ ADD(args, INTEGER_OBJ((int)height));
+ ADD(args, DICTIONARY_OBJ(opts));
+
+ rpc_send_event(chan, "nvim_ui_attach", args);
+ msgpack_rpc_add_redraw(); // GAME!
+ // TODO(bfredl): use a keyset instead
+ ui_client_methods_table_init();
+ ui_client_channel_id = chan;
+}
+
+/// Handler for "redraw" events sent by the NVIM server
+///
+/// This function will be called by handle_request (in msgpack_rpc/channel.c)
+/// The individual ui_events sent by the server are individually handled
+/// by their respective handlers defined in ui_events_client.generated.h
+///
+/// @note The "flush" event is called only once and only after handling all
+/// the other events
+/// @param channel_id: The id of the rpc channel
+/// @param uidata: The dense array containing the ui_events sent by the server
+/// @param[out] err Error details, if any
+Object ui_client_handle_redraw(uint64_t channel_id, Array args, Error *error)
+{
+ for (size_t i = 0; i < args.size; i++) {
+ Array call = args.items[i].data.array;
+ String name = call.items[0].data.string;
+
+ UIClientHandler handler = map_get(String, UIClientHandler)(&ui_client_handlers, name);
+ if (!handler) {
+ ELOG("No ui client handler for %s", name.size ? name.data : "<empty>");
+ continue;
+ }
+
+ // fprintf(stderr, "%s: %zu\n", name.data, call.size-1);
+ DLOG("Invoke ui client handler for %s", name.data);
+ for (size_t j = 1; j < call.size; j++) {
+ handler(call.items[j].data.array);
+ }
+ }
+
+ return NIL;
+}
+
+/// run the main thread in ui client mode
+///
+/// This is just a stub. the full version will handle input, resizing, etc
+void ui_client_execute(uint64_t chan)
+{
+ while (true) {
+ loop_poll_events(&main_loop, -1);
+ multiqueue_process_events(resize_events);
+ }
+
+ getout(0);
+}
+
+static HlAttrs ui_client_dict2hlattrs(Dictionary d, bool rgb)
+{
+ Error err = ERROR_INIT;
+ Dict(highlight) dict = { 0 };
+ if (!api_dict_to_keydict(&dict, KeyDict_highlight_get_field, d, &err)) {
+ // TODO(bfredl): log "err"
+ return HLATTRS_INIT;
+ }
+ return dict2hlattrs(&dict, true, NULL, &err);
+}
+
+#ifdef INCLUDE_GENERATED_DECLARATIONS
+#include "ui_events_client.generated.h"
+#endif
+
+void ui_client_event_grid_resize(Array args)
+{
+ if (args.size < 3
+ || args.items[0].type != kObjectTypeInteger
+ || args.items[1].type != kObjectTypeInteger
+ || args.items[2].type != kObjectTypeInteger) {
+ ELOG("Error handling ui event 'grid_resize'");
+ return;
+ }
+
+ Integer grid = args.items[0].data.integer;
+ Integer width = args.items[1].data.integer;
+ Integer height = args.items[2].data.integer;
+ ui_call_grid_resize(grid, width, height);
+
+ if (buf_size < (size_t)width) {
+ xfree(buf_char);
+ xfree(buf_attr);
+ buf_size = (size_t)width;
+ buf_char = xmalloc(buf_size * sizeof(schar_T));
+ buf_attr = xmalloc(buf_size * sizeof(sattr_T));
+ }
+}
+
+void ui_client_event_grid_line(Array args)
+{
+ if (args.size < 4
+ || args.items[0].type != kObjectTypeInteger
+ || args.items[1].type != kObjectTypeInteger
+ || args.items[2].type != kObjectTypeInteger
+ || args.items[3].type != kObjectTypeArray) {
+ goto error;
+ }
+
+ Integer grid = args.items[0].data.integer;
+ Integer row = args.items[1].data.integer;
+ Integer startcol = args.items[2].data.integer;
+ Array cells = args.items[3].data.array;
+
+ Integer endcol, clearcol;
+ // TODO(hlpr98): Accomodate other LineFlags when included in grid_line
+ LineFlags lineflags = 0;
+ endcol = startcol;
+
+ size_t j = 0;
+ int cur_attr = 0;
+ int clear_attr = 0;
+ int clear_width = 0;
+ for (size_t i = 0; i < cells.size; i++) {
+ if (cells.items[i].type != kObjectTypeArray) {
+ goto error;
+ }
+ Array cell = cells.items[i].data.array;
+
+ if (cell.size < 1 || cell.items[0].type != kObjectTypeString) {
+ goto error;
+ }
+ String sstring = cell.items[0].data.string;
+
+ char *schar = sstring.data;
+ int repeat = 1;
+ if (cell.size >= 2) {
+ if (cell.items[1].type != kObjectTypeInteger
+ || cell.items[1].data.integer < 0) {
+ goto error;
+ }
+ cur_attr = (int)cell.items[1].data.integer;
+ }
+
+ if (cell.size >= 3) {
+ if (cell.items[2].type != kObjectTypeInteger
+ || cell.items[2].data.integer < 0) {
+ goto error;
+ }
+ repeat = (int)cell.items[2].data.integer;
+ }
+
+ if (i == cells.size - 1 && sstring.size == 1 && sstring.data[0] == ' ' && repeat > 1) {
+ clear_width = repeat;
+ break;
+ }
+
+ for (int r = 0; r < repeat; r++) {
+ if (j >= buf_size) {
+ goto error; // _YIKES_
+ }
+ STRLCPY(buf_char[j], schar, sizeof(schar_T));
+ buf_attr[j++] = cur_attr;
+ }
+ }
+
+ endcol = startcol + (int)j;
+ clearcol = endcol + clear_width;
+ clear_attr = cur_attr;
+
+ ui_call_raw_line(grid, row, startcol, endcol, clearcol, clear_attr, lineflags,
+ (const schar_T *)buf_char, (const sattr_T *)buf_attr);
+ return;
+
+error:
+ ELOG("Error handling ui event 'grid_line'");
+}
diff --git a/src/nvim/ui_client.h b/src/nvim/ui_client.h
new file mode 100644
index 0000000000..253deecc52
--- /dev/null
+++ b/src/nvim/ui_client.h
@@ -0,0 +1,13 @@
+#ifndef NVIM_UI_CLIENT_H
+#define NVIM_UI_CLIENT_H
+
+#include "nvim/api/private/defs.h"
+
+typedef void (*UIClientHandler)(Array args);
+
+#ifdef INCLUDE_GENERATED_DECLARATIONS
+#include "ui_client.h.generated.h"
+#include "ui_events_client.h.generated.h"
+#endif
+
+#endif // NVIM_UI_CLIENT_H
diff --git a/src/nvim/ui_compositor.c b/src/nvim/ui_compositor.c
index d7becb4fd4..e356960cc8 100644
--- a/src/nvim/ui_compositor.c
+++ b/src/nvim/ui_compositor.c
@@ -14,6 +14,7 @@
#include "nvim/api/private/helpers.h"
#include "nvim/ascii.h"
#include "nvim/highlight.h"
+#include "nvim/highlight_group.h"
#include "nvim/lib/kvec.h"
#include "nvim/log.h"
#include "nvim/lua/executor.h"
@@ -23,7 +24,6 @@
#include "nvim/os/os.h"
#include "nvim/popupmnu.h"
#include "nvim/screen.h"
-#include "nvim/syntax.h"
#include "nvim/ugrid.h"
#include "nvim/ui.h"
#include "nvim/ui_compositor.h"
diff --git a/src/nvim/undo_defs.h b/src/nvim/undo_defs.h
index 3267b2f71e..d8470b07b1 100644
--- a/src/nvim/undo_defs.h
+++ b/src/nvim/undo_defs.h
@@ -33,8 +33,8 @@ struct u_entry {
};
struct u_header {
- /* The following have a pointer and a number. The number is used when
- * reading the undo file in u_read_undo() */
+ // The following have a pointer and a number. The number is used when reading
+ // the undo file in u_read_undo()
union {
u_header_T *ptr; // pointer to next undo header in list
long seq;
@@ -80,4 +80,4 @@ typedef struct {
FILE *bi_fp;
} bufinfo_T;
-#endif // NVIM_UNDO_DEFS_H
+#endif // NVIM_UNDO_DEFS_H
diff --git a/src/nvim/viml/parser/parser.h b/src/nvim/viml/parser/parser.h
index b2933c3781..b8835127e7 100644
--- a/src/nvim/viml/parser/parser.h
+++ b/src/nvim/viml/parser/parser.h
@@ -81,10 +81,8 @@ typedef struct {
bool can_continuate;
} ParserState;
-static inline void viml_parser_init(
- ParserState *const ret_pstate,
- const ParserLineGetter get_line, void *const cookie,
- ParserHighlight *const colors)
+static inline void viml_parser_init(ParserState *const ret_pstate, const ParserLineGetter get_line,
+ void *const cookie, ParserHighlight *const colors)
REAL_FATTR_ALWAYS_INLINE REAL_FATTR_NONNULL_ARG(1, 2);
/// Initialize a new parser state instance
diff --git a/src/nvim/window.c b/src/nvim/window.c
index d5299202b0..8b9f1e024d 100644
--- a/src/nvim/window.c
+++ b/src/nvim/window.c
@@ -25,6 +25,7 @@
#include "nvim/getchar.h"
#include "nvim/globals.h"
#include "nvim/hashtab.h"
+#include "nvim/highlight_group.h"
#include "nvim/main.h"
#include "nvim/mark.h"
#include "nvim/memline.h"
@@ -60,7 +61,7 @@
#define NOWIN (win_T *)-1 // non-existing window
-#define ROWS_AVAIL (Rows - p_ch - tabline_height())
+#define ROWS_AVAIL (Rows - p_ch - tabline_height() - global_stl_height())
/// flags for win_enter_ext()
typedef enum {
@@ -73,6 +74,15 @@ typedef enum {
static char *m_onlyone = N_("Already only one window");
+/// @return the current window, unless in the cmdline window and "prevwin" is
+/// set, then return "prevwin".
+win_T *prevwin_curwin(void)
+ FUNC_ATTR_WARN_UNUSED_RESULT
+{
+ // In cmdwin, the alternative buffer should be used.
+ return is_in_cmdwin() && prevwin != NULL ? prevwin : curwin;
+}
+
/// all CTRL-W window commands are handled here, called from normal_cmd().
///
/// @param xchar extra char from ":wincmd gx" or NUL
@@ -521,10 +531,6 @@ wingotofile:
do_nv_ident('g', xchar);
break;
- case TAB:
- goto_tabpage_lastused();
- break;
-
case 'f': // CTRL-W gf: "gf" in a new tab page
case 'F': // CTRL-W gF: "gF" in a new tab page
cmdmod.tab = tabpage_index(curtab) + 1;
@@ -538,6 +544,12 @@ wingotofile:
goto_tabpage(-(int)Prenum1);
break;
+ case TAB: // CTRL-W g<Tab>: go to last used tab page
+ if (!goto_tabpage_lastused()) {
+ beep_flush();
+ }
+ break;
+
case 'e':
if (curwin->w_floating || !ui_has(kUIMultigrid)) {
beep_flush();
@@ -647,6 +659,7 @@ win_T *win_new_float(win_T *wp, FloatConfig fconfig, Error *err)
}
wp->w_floating = 1;
wp->w_status_height = 0;
+ wp->w_hsep_height = 0;
wp->w_vsep_width = 0;
win_config_float(wp, fconfig);
@@ -956,6 +969,7 @@ int win_split_ins(int size, int flags, win_T *new_wp, int dir)
int before;
int minheight;
int wmh1;
+ int hsep_height;
bool did_set_fraction = false;
// aucmd_win should always remain floating
@@ -1068,6 +1082,7 @@ int win_split_ins(int size, int flags, win_T *new_wp, int dir)
}
}
} else {
+ hsep_height = global_stl_height() > 0 ? 1 : STATUS_HEIGHT;
layout = FR_COL;
/*
@@ -1076,7 +1091,7 @@ int win_split_ins(int size, int flags, win_T *new_wp, int dir)
*/
// Current window requires at least 1 space.
wmh1 = p_wmh == 0 ? 1 : p_wmh;
- needed = wmh1 + STATUS_HEIGHT;
+ needed = wmh1 + hsep_height;
if (flags & WSP_ROOM) {
needed += p_wh - wmh1;
}
@@ -1118,15 +1133,15 @@ int win_split_ins(int size, int flags, win_T *new_wp, int dir)
new_size = oldwin_height / 2;
}
- if (new_size > available - minheight - STATUS_HEIGHT) {
- new_size = available - minheight - STATUS_HEIGHT;
+ if (new_size > available - minheight - hsep_height) {
+ new_size = available - minheight - hsep_height;
}
if (new_size < wmh1) {
new_size = wmh1;
}
// if it doesn't fit in the current window, need win_equal()
- if (oldwin_height - new_size - STATUS_HEIGHT < p_wmh) {
+ if (oldwin_height - new_size - hsep_height < p_wmh) {
do_equal = true;
}
@@ -1139,7 +1154,7 @@ int win_split_ins(int size, int flags, win_T *new_wp, int dir)
set_fraction(oldwin);
did_set_fraction = true;
- win_setheight_win(oldwin->w_height + new_size + STATUS_HEIGHT,
+ win_setheight_win(oldwin->w_height + new_size + hsep_height,
oldwin);
oldwin_height = oldwin->w_height;
if (need_status) {
@@ -1156,8 +1171,7 @@ int win_split_ins(int size, int flags, win_T *new_wp, int dir)
while (frp != NULL) {
if (frp->fr_win != oldwin && frp->fr_win != NULL
&& (frp->fr_win->w_height > new_size
- || frp->fr_win->w_height > oldwin_height - new_size
- - STATUS_HEIGHT)) {
+ || frp->fr_win->w_height > oldwin_height - new_size - hsep_height)) {
do_equal = true;
break;
}
@@ -1283,13 +1297,15 @@ int win_split_ins(int size, int flags, win_T *new_wp, int dir)
if (flags & (WSP_TOP | WSP_BOT)) {
// set height and row of new window to full height
wp->w_winrow = tabline_height();
- win_new_height(wp, curfrp->fr_height - (p_ls > 0));
- wp->w_status_height = (p_ls > 0);
+ win_new_height(wp, curfrp->fr_height - (p_ls == 1 || p_ls == 2));
+ wp->w_status_height = (p_ls == 1 || p_ls == 2);
+ wp->w_hsep_height = 0;
} else {
// height and row of new window is same as current window
wp->w_winrow = oldwin->w_winrow;
win_new_height(wp, oldwin->w_height);
wp->w_status_height = oldwin->w_status_height;
+ wp->w_hsep_height = oldwin->w_hsep_height;
}
frp->fr_height = curfrp->fr_height;
@@ -1322,6 +1338,7 @@ int win_split_ins(int size, int flags, win_T *new_wp, int dir)
frame_fix_width(oldwin);
frame_fix_width(wp);
} else {
+ bool is_stl_global = global_stl_height() > 0;
// width and column of new window is same as current window
if (flags & (WSP_TOP | WSP_BOT)) {
wp->w_wincol = 0;
@@ -1337,28 +1354,53 @@ int win_split_ins(int size, int flags, win_T *new_wp, int dir)
// "new_size" of the current window goes to the new window, use
// one row for the status line
win_new_height(wp, new_size);
+ if (before) {
+ wp->w_hsep_height = is_stl_global ? 1 : 0;
+ } else {
+ wp->w_hsep_height = oldwin->w_hsep_height;
+ oldwin->w_hsep_height = is_stl_global ? 1 : 0;
+ }
if (flags & (WSP_TOP | WSP_BOT)) {
int new_fr_height = curfrp->fr_height - new_size;
- if (!((flags & WSP_BOT) && p_ls == 0)) {
+ if (!((flags & WSP_BOT) && p_ls == 0) && global_stl_height() == 0) {
new_fr_height -= STATUS_HEIGHT;
+ } else if (global_stl_height() > 0) {
+ if (flags & WSP_BOT) {
+ frame_add_hsep(curfrp);
+ } else {
+ new_fr_height -= 1;
+ }
}
frame_new_height(curfrp, new_fr_height, flags & WSP_TOP, false);
} else {
- win_new_height(oldwin, oldwin_height - (new_size + STATUS_HEIGHT));
+ win_new_height(oldwin, oldwin_height - (new_size
+ + (global_stl_height() > 0 ? 1 : STATUS_HEIGHT)));
}
+
if (before) { // new window above current one
wp->w_winrow = oldwin->w_winrow;
- wp->w_status_height = STATUS_HEIGHT;
- oldwin->w_winrow += wp->w_height + STATUS_HEIGHT;
+
+ if (is_stl_global) {
+ wp->w_status_height = 0;
+ oldwin->w_winrow += wp->w_height + 1;
+ } else {
+ wp->w_status_height = STATUS_HEIGHT;
+ oldwin->w_winrow += wp->w_height + STATUS_HEIGHT;
+ }
} else { // new window below current one
- wp->w_winrow = oldwin->w_winrow + oldwin->w_height + STATUS_HEIGHT;
- wp->w_status_height = oldwin->w_status_height;
- if (!(flags & WSP_BOT)) {
- oldwin->w_status_height = STATUS_HEIGHT;
+ if (is_stl_global) {
+ wp->w_winrow = oldwin->w_winrow + oldwin->w_height + 1;
+ wp->w_status_height = 0;
+ } else {
+ wp->w_winrow = oldwin->w_winrow + oldwin->w_height + STATUS_HEIGHT;
+ wp->w_status_height = oldwin->w_status_height;
+ if (!(flags & WSP_BOT)) {
+ oldwin->w_status_height = STATUS_HEIGHT;
+ }
}
}
- if (flags & WSP_BOT) {
+ if ((flags & WSP_BOT) && global_stl_height() == 0) {
frame_add_statusline(curfrp);
}
frame_fix_height(wp);
@@ -1420,13 +1462,11 @@ int win_split_ins(int size, int flags, win_T *new_wp, int dir)
p_wh = i;
}
- if (!win_valid(oldwin)) {
- return FAIL;
+ if (win_valid(oldwin)) {
+ // Send the window positions to the UI
+ oldwin->w_pos_changed = true;
}
- // Send the window positions to the UI
- oldwin->w_pos_changed = true;
-
return OK;
}
@@ -1600,10 +1640,10 @@ int make_windows(int count, bool vertical)
maxcount = (curwin->w_width + curwin->w_vsep_width
- (p_wiw - p_wmw)) / (p_wmw + 1);
} else {
- // Each window needs at least 'winminheight' lines and a status line.
- maxcount = (curwin->w_height
- + curwin->w_status_height
- - (p_wh - p_wmh)) / (p_wmh + STATUS_HEIGHT);
+ // Each window needs at least 'winminheight' lines
+ // If statusline isn't global, each window also needs a statusline
+ maxcount = (curwin->w_height + curwin->w_hsep_height + curwin->w_status_height
+ - (p_wh - p_wmh)) / (p_wmh + (global_stl_height() > 0 ? 1 : STATUS_HEIGHT));
}
if (maxcount < 2) {
@@ -1698,7 +1738,7 @@ static void win_exchange(long Prenum)
* if wp != wp2
* 3. remove wp from the list
* 4. insert wp after wp2
- * 5. exchange the status line height and vsep width.
+ * 5. exchange the status line height, hsep height and vsep width.
*/
wp2 = curwin->w_prev;
frp2 = curwin->w_frame->fr_prev;
@@ -1724,6 +1764,9 @@ static void win_exchange(long Prenum)
temp = curwin->w_vsep_width;
curwin->w_vsep_width = wp->w_vsep_width;
wp->w_vsep_width = temp;
+ temp = curwin->w_hsep_height;
+ curwin->w_hsep_height = wp->w_hsep_height;
+ wp->w_hsep_height = temp;
frame_fix_height(curwin);
frame_fix_height(wp);
@@ -1804,10 +1847,13 @@ static void win_rotate(bool upwards, int count)
frame_insert(frp->fr_parent->fr_child, frp);
}
- // exchange status height and vsep width of old and new last window
+ // exchange status height, hsep height and vsep width of old and new last window
n = wp2->w_status_height;
wp2->w_status_height = wp1->w_status_height;
wp1->w_status_height = n;
+ n = wp2->w_hsep_height;
+ wp2->w_hsep_height = wp1->w_hsep_height;
+ wp1->w_hsep_height = n;
frame_fix_height(wp1);
frame_fix_height(wp2);
n = wp2->w_vsep_width;
@@ -1884,11 +1930,16 @@ void win_move_after(win_T *win1, win_T *win2)
// check if there is something to do
if (win2->w_next != win1) {
- // may need move the status line/vertical separator of the last window
+ // may need move the status line, horizontal or vertical separator of the last window
if (win1 == lastwin) {
height = win1->w_prev->w_status_height;
win1->w_prev->w_status_height = win1->w_status_height;
win1->w_status_height = height;
+
+ height = win1->w_prev->w_hsep_height;
+ win1->w_prev->w_hsep_height = win1->w_hsep_height;
+ win1->w_hsep_height = height;
+
if (win1->w_prev->w_vsep_width == 1) {
// Remove the vertical separator from the last-but-one window,
// add it to the last window. Adjust the frame widths.
@@ -1901,6 +1952,11 @@ void win_move_after(win_T *win1, win_T *win2)
height = win1->w_status_height;
win1->w_status_height = win2->w_status_height;
win2->w_status_height = height;
+
+ height = win1->w_hsep_height;
+ win1->w_hsep_height = win2->w_hsep_height;
+ win2->w_hsep_height = height;
+
if (win1->w_vsep_width == 1) {
// Remove the vertical separator from win1, add it to the last
// window, win2. Adjust the frame widths.
@@ -1964,6 +2020,7 @@ static void win_equal_rec(win_T *next_curwin, bool current, frame_T *topfr, int
int room = 0;
int new_size;
int has_next_curwin = 0;
+ int hsep_height;
bool hnc;
if (topfr->fr_layout == FR_LEAF) {
@@ -2109,19 +2166,22 @@ static void win_equal_rec(win_T *next_curwin, bool current, frame_T *topfr, int
totwincount -= wincount;
}
} else { // topfr->fr_layout == FR_COL
+ hsep_height = global_stl_height() > 0 ? 1 : STATUS_HEIGHT;
topfr->fr_width = width;
topfr->fr_height = height;
if (dir != 'h') { // equalize frame heights
// Compute maximum number of windows vertically in this frame.
n = frame_minheight(topfr, NOWIN);
- // add one for the bottom window if it doesn't have a statusline
+ // add one for the bottom window if it doesn't have a statusline or separator
if (row + height == cmdline_row && p_ls == 0) {
+ extra_sep = STATUS_HEIGHT;
+ } else if (global_stl_height() > 0) {
extra_sep = 1;
} else {
extra_sep = 0;
}
- totwincount = (n + extra_sep) / (p_wmh + 1);
+ totwincount = (n + extra_sep) / (p_wmh + hsep_height);
has_next_curwin = frame_has_win(topfr, next_curwin);
/*
@@ -2156,7 +2216,7 @@ static void win_equal_rec(win_T *next_curwin, bool current, frame_T *topfr, int
} else {
// These windows don't use up room.
totwincount -= (n + (fr->fr_next == NULL
- ? extra_sep : 0)) / (p_wmh + 1);
+ ? extra_sep : 0)) / (p_wmh + hsep_height);
}
room -= new_size - n;
if (room < 0) {
@@ -2202,7 +2262,7 @@ static void win_equal_rec(win_T *next_curwin, bool current, frame_T *topfr, int
// Compute the maximum number of windows vert. in "fr".
n = frame_minheight(fr, NOWIN);
wincount = (n + (fr->fr_next == NULL ? extra_sep : 0))
- / (p_wmh + 1);
+ / (p_wmh + hsep_height);
m = frame_minheight(fr, next_curwin);
if (has_next_curwin) {
hnc = frame_has_win(fr, next_curwin);
@@ -2598,6 +2658,13 @@ int win_close(win_T *win, bool free_buf, bool force)
reset_synblock(win);
}
+ // When a quickfix/location list window is closed and the buffer is
+ // displayed in only one window, then unlist the buffer.
+ if (win->w_buffer != NULL && bt_quickfix(win->w_buffer)
+ && win->w_buffer->b_nwindows == 1) {
+ win->w_buffer->b_p_bl = false;
+ }
+
/*
* Close the link to the buffer.
*/
@@ -2890,6 +2957,9 @@ void win_free_all(void)
{
int dummy;
+ // avoid an error for switching tabpage with the cmdline window open
+ cmdwin_type = 0;
+
while (first_tabpage->tp_next != NULL) {
tabpage_close(TRUE);
}
@@ -3148,7 +3218,7 @@ static tabpage_T *alt_tabpage(void)
/*
* Find the left-upper window in frame "frp".
*/
-static win_T *frame2win(frame_T *frp)
+win_T *frame2win(frame_T *frp)
{
while (frp->fr_win == NULL) {
frp = frp->fr_child;
@@ -3175,23 +3245,40 @@ static bool frame_has_win(const frame_T *frp, const win_T *wp)
return false;
}
+/// Check if current window is at the bottom
+/// Returns true if there are no windows below current window
+static bool is_bottom_win(win_T *wp)
+ FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ALL
+{
+ frame_T *frp;
+ for (frp = wp->w_frame; frp->fr_parent != NULL; frp = frp->fr_parent) {
+ if (frp->fr_parent->fr_layout == FR_COL && frp->fr_next != NULL) {
+ return false;
+ }
+ }
+ return true;
+}
/// Set a new height for a frame. Recursively sets the height for contained
/// frames and windows. Caller must take care of positions.
///
/// @param topfirst resize topmost contained frame first.
/// @param wfh obey 'winfixheight' when there is a choice;
/// may cause the height not to be set.
-static void frame_new_height(frame_T *topfrp, int height, bool topfirst, bool wfh)
+void frame_new_height(frame_T *topfrp, int height, bool topfirst, bool wfh)
FUNC_ATTR_NONNULL_ALL
{
frame_T *frp;
int extra_lines;
int h;
+ win_T *wp;
if (topfrp->fr_win != NULL) {
// Simple case: just one window.
- win_new_height(topfrp->fr_win,
- height - topfrp->fr_win->w_status_height);
+ wp = topfrp->fr_win;
+ if (is_bottom_win(wp)) {
+ wp->w_hsep_height = 0;
+ }
+ win_new_height(wp, height - wp->w_hsep_height - wp->w_status_height);
} else if (topfrp->fr_layout == FR_ROW) {
do {
// All frames in this row get the same new height.
@@ -3347,8 +3434,8 @@ static void frame_add_statusline(frame_T *frp)
if (frp->fr_layout == FR_LEAF) {
wp = frp->fr_win;
if (wp->w_status_height == 0) {
- if (wp->w_height > 0) { // don't make it negative
- --wp->w_height;
+ if (wp->w_height - STATUS_HEIGHT >= 0) { // don't make it negative
+ wp->w_height -= STATUS_HEIGHT;
}
wp->w_status_height = STATUS_HEIGHT;
}
@@ -3468,10 +3555,8 @@ static void frame_new_width(frame_T *topfrp, int width, bool leftfirst, bool wfw
topfrp->fr_width = width;
}
-/*
- * Add the vertical separator to windows at the right side of "frp".
- * Note: Does not check if there is room!
- */
+/// Add the vertical separator to windows at the right side of "frp".
+/// Note: Does not check if there is room!
static void frame_add_vsep(const frame_T *frp)
FUNC_ATTR_NONNULL_ARG(1)
{
@@ -3501,6 +3586,37 @@ static void frame_add_vsep(const frame_T *frp)
}
}
+/// Add the horizontal separator to windows at the bottom of "frp".
+/// Note: Does not check if there is room or whether the windows have a statusline!
+static void frame_add_hsep(const frame_T *frp)
+ FUNC_ATTR_NONNULL_ARG(1)
+{
+ win_T *wp;
+
+ if (frp->fr_layout == FR_LEAF) {
+ wp = frp->fr_win;
+ if (wp->w_hsep_height == 0) {
+ if (wp->w_height > 0) { // don't make it negative
+ wp->w_height++;
+ }
+ wp->w_hsep_height = 1;
+ }
+ } else if (frp->fr_layout == FR_ROW) {
+ // Handle all the frames in the row.
+ FOR_ALL_FRAMES(frp, frp->fr_child) {
+ frame_add_hsep(frp);
+ }
+ } else {
+ assert(frp->fr_layout == FR_COL);
+ // Only need to handle the last frame in the column.
+ frp = frp->fr_child;
+ while (frp->fr_next != NULL) {
+ frp = frp->fr_next;
+ }
+ frame_add_hsep(frp);
+ }
+}
+
/*
* Set frame width from the window it contains.
*/
@@ -3515,7 +3631,7 @@ static void frame_fix_width(win_T *wp)
static void frame_fix_height(win_T *wp)
FUNC_ATTR_NONNULL_ALL
{
- wp->w_frame->fr_height = wp->w_height + wp->w_status_height;
+ wp->w_frame->fr_height = wp->w_height + wp->w_hsep_height + wp->w_status_height;
}
/*
@@ -3533,10 +3649,11 @@ static int frame_minheight(frame_T *topfrp, win_T *next_curwin)
if (topfrp->fr_win != NULL) {
if (topfrp->fr_win == next_curwin) {
- m = p_wh + topfrp->fr_win->w_status_height;
+ m = p_wh + topfrp->fr_win->w_hsep_height + topfrp->fr_win->w_status_height;
} else {
- // window: minimal height of the window plus status line
- m = p_wmh + topfrp->fr_win->w_status_height;
+ // window: minimal height of the window plus separator column or status line
+ // depending on whether global statusline is enabled
+ m = p_wmh + topfrp->fr_win->w_hsep_height + topfrp->fr_win->w_status_height;
if (topfrp->fr_win == curwin && next_curwin == NULL) {
// Current window is minimal one line high.
if (p_wmh == 0) {
@@ -3765,7 +3882,7 @@ static int win_alloc_firstwin(win_T *oldwin)
new_frame(curwin);
topframe = curwin->w_frame;
topframe->fr_width = Columns;
- topframe->fr_height = Rows - p_ch;
+ topframe->fr_height = Rows - p_ch - global_stl_height();
return OK;
}
@@ -3852,6 +3969,11 @@ int win_new_tabpage(int after, char_u *filename)
tabpage_T *newtp;
int n;
+ if (cmdwin_type != 0) {
+ emsg(_(e_cmdwin));
+ return FAIL;
+ }
+
newtp = alloc_tabpage();
// Remember the current windows in this Tab page.
@@ -4097,8 +4219,8 @@ static void enter_tabpage(tabpage_T *tp, buf_T *old_curbuf, bool trigger_enter_a
{
int old_off = tp->tp_firstwin->w_winrow;
win_T *next_prevwin = tp->tp_prevwin;
-
tabpage_T *old_curtab = curtab;
+
curtab = tp;
firstwin = tp->tp_firstwin;
lastwin = tp->tp_lastwin;
@@ -4250,6 +4372,10 @@ void goto_tabpage(int n)
/// @param trigger_leave_autocmds when true trigger *Leave autocommands.
void goto_tabpage_tp(tabpage_T *tp, bool trigger_enter_autocmds, bool trigger_leave_autocmds)
{
+ if (trigger_enter_autocmds || trigger_leave_autocmds) {
+ CHECK_CMDWIN;
+ }
+
// Don't repeat a message in another tab page.
set_keep_msg(NULL, 0);
@@ -4265,13 +4391,15 @@ void goto_tabpage_tp(tabpage_T *tp, bool trigger_enter_autocmds, bool trigger_le
}
}
-// Go to the last accessed tab page, if there is one.
-void goto_tabpage_lastused(void)
+/// Go to the last accessed tab page, if there is one.
+/// @return true if the tab page is valid, false otherwise.
+bool goto_tabpage_lastused(void)
{
- int index = tabpage_index(lastused_tabpage);
- if (index < tabpage_index(NULL)) {
- goto_tabpage(index);
+ if (valid_tabpage(lastused_tabpage)) {
+ goto_tabpage_tp(lastused_tabpage, true, true);
+ return true;
}
+ return false;
}
/*
@@ -5170,11 +5298,8 @@ void win_size_restore(garray_T *gap)
}
}
-/*
- * Update the position for all windows, using the width and height of the
- * frames.
- * Returns the row just after the last window.
- */
+// Update the position for all windows, using the width and height of the frames.
+// Returns the row just after the last window and global statusline (if there is one).
int win_comp_pos(void)
{
int row = tabline_height();
@@ -5189,7 +5314,7 @@ int win_comp_pos(void)
}
}
- return row;
+ return row + global_stl_height();
}
void win_reconfig_floats(void)
@@ -5223,7 +5348,7 @@ static void frame_comp_pos(frame_T *topfrp, int *row, int *col)
wp->w_redr_status = true;
wp->w_pos_changed = true;
}
- const int h = wp->w_height + wp->w_status_height;
+ const int h = wp->w_height + wp->w_hsep_height + wp->w_status_height;
*row += h > topfrp->fr_height ? topfrp->fr_height : h;
*col += wp->w_width + wp->w_vsep_width;
} else {
@@ -5272,7 +5397,7 @@ void win_setheight_win(int height, win_T *win)
win_config_float(win, win->w_float_config);
redraw_later(win, NOT_VALID);
} else {
- frame_setheight(win->w_frame, height + win->w_status_height);
+ frame_setheight(win->w_frame, height + win->w_hsep_height + win->w_status_height);
// recompute the window positions
int row = win_comp_pos();
@@ -5363,8 +5488,8 @@ static void frame_setheight(frame_T *curfrp, int height)
room_cmdline = 0;
} else {
win_T *wp = lastwin_nofloating();
- room_cmdline = Rows - p_ch
- - (wp->w_winrow + wp->w_height + wp->w_status_height);
+ room_cmdline = Rows - p_ch - global_stl_height()
+ - (wp->w_winrow + wp->w_height + wp->w_hsep_height + wp->w_status_height);
if (room_cmdline < 0) {
room_cmdline = 0;
}
@@ -5726,7 +5851,7 @@ void win_drag_status_line(win_T *dragwin, int offset)
} else { // drag down
up = false;
// Only dragging the last status line can reduce p_ch.
- room = Rows - cmdline_row;
+ room = Rows - cmdline_row - global_stl_height();
if (curfr->fr_next == NULL) {
room -= 1;
} else {
@@ -6367,72 +6492,104 @@ char_u *file_name_in_line(char_u *line, int col, int options, long count, char_u
return find_file_name_in_path(ptr, len, options, count, rel_fname);
}
-/// Add or remove a status line for the bottom window(s), according to the
+/// Add or remove a status line from window(s), according to the
/// value of 'laststatus'.
///
/// @param morewin pretend there are two or more windows if true.
void last_status(bool morewin)
{
// Don't make a difference between horizontal or vertical split.
- last_status_rec(topframe, (p_ls == 2
- || (p_ls == 1 && (morewin || !one_window()))));
+ last_status_rec(topframe, (p_ls == 2 || (p_ls == 1 && (morewin || !one_window()))),
+ global_stl_height() > 0);
+}
+
+// Look for resizable frames and take lines from them to make room for the statusline
+static void resize_frame_for_status(frame_T *fr, int resize_amount)
+{
+ // Find a frame to take a line from.
+ frame_T *fp = fr;
+ win_T *wp = fr->fr_win;
+ int n;
+
+ while (resize_amount > 0) {
+ while (fp->fr_height <= frame_minheight(fp, NULL)) {
+ if (fp == topframe) {
+ emsg(_(e_noroom));
+ return;
+ }
+ // In a column of frames: go to frame above. If already at
+ // the top or in a row of frames: go to parent.
+ if (fp->fr_parent->fr_layout == FR_COL && fp->fr_prev != NULL) {
+ fp = fp->fr_prev;
+ } else {
+ fp = fp->fr_parent;
+ }
+ }
+ n = MIN(fp->fr_height - frame_minheight(fp, NULL), resize_amount);
+ resize_amount -= n;
+
+ if (fp != fr) {
+ frame_new_height(fp, fp->fr_height - n, false, false);
+ frame_fix_height(wp);
+ (void)win_comp_pos();
+ } else {
+ win_new_height(wp, wp->w_height - n);
+ }
+ }
}
-static void last_status_rec(frame_T *fr, bool statusline)
+static void last_status_rec(frame_T *fr, bool statusline, bool is_stl_global)
{
frame_T *fp;
win_T *wp;
if (fr->fr_layout == FR_LEAF) {
wp = fr->fr_win;
- if (wp->w_status_height != 0 && !statusline) {
- // remove status line
- win_new_height(wp, wp->w_height + 1);
+ bool is_last = is_bottom_win(wp);
+
+ if (is_last) {
+ if (wp->w_status_height != 0 && (!statusline || is_stl_global)) {
+ // Remove status line
+ wp->w_status_height = 0;
+ win_new_height(wp, wp->w_height + STATUS_HEIGHT);
+ comp_col();
+ } else if (wp->w_status_height == 0 && !is_stl_global && statusline) {
+ // Add statusline to window if needed
+ wp->w_status_height = STATUS_HEIGHT;
+ resize_frame_for_status(fr, STATUS_HEIGHT);
+ comp_col();
+ }
+ } else if (wp->w_status_height != 0 && is_stl_global) {
+ // If statusline is global and the window has a statusline, replace it with a horizontal
+ // separator
+ if (STATUS_HEIGHT - 1 != 0) {
+ win_new_height(wp, wp->w_height + STATUS_HEIGHT - 1);
+ }
wp->w_status_height = 0;
+ wp->w_hsep_height = 1;
comp_col();
- } else if (wp->w_status_height == 0 && statusline) {
- // Find a frame to take a line from.
- fp = fr;
- while (fp->fr_height <= frame_minheight(fp, NULL)) {
- if (fp == topframe) {
- emsg(_(e_noroom));
- return;
- }
- // In a column of frames: go to frame above. If already at
- // the top or in a row of frames: go to parent.
- if (fp->fr_parent->fr_layout == FR_COL && fp->fr_prev != NULL) {
- fp = fp->fr_prev;
- } else {
- fp = fp->fr_parent;
- }
- }
- wp->w_status_height = 1;
- if (fp != fr) {
- frame_new_height(fp, fp->fr_height - 1, false, false);
- frame_fix_height(wp);
- (void)win_comp_pos();
- } else {
- win_new_height(wp, wp->w_height - 1);
- }
+ } else if (wp->w_status_height == 0 && !is_stl_global) {
+ // If statusline isn't global and the window doesn't have a statusline, re-add it
+ wp->w_status_height = STATUS_HEIGHT;
+ wp->w_hsep_height = 0;
+ resize_frame_for_status(fr, STATUS_HEIGHT - 1);
comp_col();
- redraw_all_later(SOME_VALID);
}
- } else if (fr->fr_layout == FR_ROW) {
- // vertically split windows, set status line for each one
+ redraw_all_later(SOME_VALID);
+ } else if (fr->fr_layout == FR_COL) {
+ // For a column frame, recursively call this function for all child frames
FOR_ALL_FRAMES(fp, fr->fr_child) {
- last_status_rec(fp, statusline);
+ last_status_rec(fp, statusline, is_stl_global);
}
} else {
- // horizontally split window, set status line for last one
- for (fp = fr->fr_child; fp->fr_next != NULL; fp = fp->fr_next) {
+ // For a row frame, recursively call this function for all child frames
+ FOR_ALL_FRAMES(fp, fr->fr_child) {
+ last_status_rec(fp, statusline, is_stl_global);
}
- last_status_rec(fp, statusline);
}
}
-/*
- * Return the number of lines used by the tab page line.
- */
+/// Return the number of lines used by the tab page line.
int tabline_height(void)
{
if (ui_has(kUITabline)) {
@@ -6448,10 +6605,14 @@ int tabline_height(void)
return 1;
}
-/*
- * Return the minimal number of rows that is needed on the screen to display
- * the current number of windows.
- */
+/// Return the number of lines used by the global statusline
+int global_stl_height(void)
+{
+ return (p_ls == 3) ? STATUS_HEIGHT : 0;
+}
+
+/// Return the minimal number of rows that is needed on the screen to display
+/// the current number of windows.
int min_rows(void)
{
if (firstwin == NULL) { // not initialized yet
@@ -6465,7 +6626,7 @@ int min_rows(void)
total = n;
}
}
- total += tabline_height();
+ total += tabline_height() + global_stl_height();
total += 1; // count the room for the command line
return total;
}
@@ -7197,16 +7358,14 @@ void win_id2tabwin(typval_T *const argvars, typval_T *const rettv)
tv_list_append_number(list, winnr);
}
-win_T *win_id2wp(typval_T *argvars)
+win_T *win_id2wp(int id)
{
- return win_id2wp_tp(argvars, NULL);
+ return win_id2wp_tp(id, NULL);
}
// Return the window and tab pointer of window "id".
-win_T *win_id2wp_tp(typval_T *argvars, tabpage_T **tpp)
+win_T *win_id2wp_tp(int id, tabpage_T **tpp)
{
- int id = tv_get_number(&argvars[0]);
-
FOR_ALL_TAB_WINDOWS(tp, wp) {
if (wp->handle == id) {
if (tpp != NULL) {
diff --git a/src/nvim/window.h b/src/nvim/window.h
index 42701f72b4..b75b8abd9b 100644
--- a/src/nvim/window.h
+++ b/src/nvim/window.h
@@ -12,13 +12,11 @@
#define FNAME_EXP 2 // expand to path
#define FNAME_HYP 4 // check for hypertext link
#define FNAME_INCL 8 // apply 'includeexpr'
-#define FNAME_REL 16 /* ".." and "./" are relative to the (current)
- file instead of the current directory */
+#define FNAME_REL 16 // ".." and "./" are relative to the (current)
+ // file instead of the current directory
#define FNAME_UNESC 32 // remove backslashes used for escaping
-/*
- * arguments for win_split()
- */
+// arguments for win_split()
#define WSP_ROOM 1 // require enough room
#define WSP_VERT 2 // split vertically
#define WSP_TOP 4 // window at top-left of shell
@@ -28,9 +26,7 @@
#define WSP_ABOVE 64 // put new window above/left
#define WSP_NEWLOC 128 // don't copy location list
-/*
- * Minimum screen size
- */
+// Minimum screen size
#define MIN_COLUMNS 12 // minimal columns for screen
#define MIN_LINES 2 // minimal lines for screen
diff --git a/test/functional/api/vim_spec.lua b/test/functional/api/vim_spec.lua
index e945a6c706..af6872760a 100644
--- a/test/functional/api/vim_spec.lua
+++ b/test/functional/api/vim_spec.lua
@@ -636,34 +636,374 @@ describe('API', function()
eq('Invalid phase: 4',
pcall_err(request, 'nvim_paste', 'foo', true, 4))
end)
- it('stream: multiple chunks form one undo-block', function()
- nvim('paste', '1/chunk 1 (start)\n', true, 1)
- nvim('paste', '1/chunk 2 (end)\n', true, 3)
- local expected1 = [[
- 1/chunk 1 (start)
- 1/chunk 2 (end)
- ]]
- expect(expected1)
- nvim('paste', '2/chunk 1 (start)\n', true, 1)
- nvim('paste', '2/chunk 2\n', true, 2)
- expect([[
- 1/chunk 1 (start)
- 1/chunk 2 (end)
- 2/chunk 1 (start)
- 2/chunk 2
- ]])
- nvim('paste', '2/chunk 3\n', true, 2)
- nvim('paste', '2/chunk 4 (end)\n', true, 3)
- expect([[
- 1/chunk 1 (start)
- 1/chunk 2 (end)
- 2/chunk 1 (start)
- 2/chunk 2
- 2/chunk 3
- 2/chunk 4 (end)
- ]])
- feed('u') -- Undo.
- expect(expected1)
+ local function run_streamed_paste_tests()
+ it('stream: multiple chunks form one undo-block', function()
+ nvim('paste', '1/chunk 1 (start)\n', true, 1)
+ nvim('paste', '1/chunk 2 (end)\n', true, 3)
+ local expected1 = [[
+ 1/chunk 1 (start)
+ 1/chunk 2 (end)
+ ]]
+ expect(expected1)
+ nvim('paste', '2/chunk 1 (start)\n', true, 1)
+ nvim('paste', '2/chunk 2\n', true, 2)
+ expect([[
+ 1/chunk 1 (start)
+ 1/chunk 2 (end)
+ 2/chunk 1 (start)
+ 2/chunk 2
+ ]])
+ nvim('paste', '2/chunk 3\n', true, 2)
+ nvim('paste', '2/chunk 4 (end)\n', true, 3)
+ expect([[
+ 1/chunk 1 (start)
+ 1/chunk 2 (end)
+ 2/chunk 1 (start)
+ 2/chunk 2
+ 2/chunk 3
+ 2/chunk 4 (end)
+ ]])
+ feed('u') -- Undo.
+ expect(expected1)
+ end)
+ it('stream: Insert mode', function()
+ -- If nvim_paste() calls :undojoin without making any changes, this makes it an error.
+ feed('afoo<Esc>u')
+ feed('i')
+ nvim('paste', 'aaaaaa', false, 1)
+ nvim('paste', 'bbbbbb', false, 2)
+ nvim('paste', 'cccccc', false, 2)
+ nvim('paste', 'dddddd', false, 3)
+ expect('aaaaaabbbbbbccccccdddddd')
+ feed('<Esc>u')
+ expect('')
+ end)
+ describe('stream: Normal mode', function()
+ describe('on empty line', function()
+ before_each(function()
+ -- If nvim_paste() calls :undojoin without making any changes, this makes it an error.
+ feed('afoo<Esc>u')
+ end)
+ after_each(function()
+ feed('u')
+ expect('')
+ end)
+ it('pasting one line', function()
+ nvim('paste', 'aaaaaa', false, 1)
+ nvim('paste', 'bbbbbb', false, 2)
+ nvim('paste', 'cccccc', false, 2)
+ nvim('paste', 'dddddd', false, 3)
+ expect('aaaaaabbbbbbccccccdddddd')
+ end)
+ it('pasting multiple lines', function()
+ nvim('paste', 'aaaaaa\n', false, 1)
+ nvim('paste', 'bbbbbb\n', false, 2)
+ nvim('paste', 'cccccc\n', false, 2)
+ nvim('paste', 'dddddd', false, 3)
+ expect([[
+ aaaaaa
+ bbbbbb
+ cccccc
+ dddddd]])
+ end)
+ end)
+ describe('not at the end of a line', function()
+ before_each(function()
+ feed('i||<Esc>')
+ -- If nvim_paste() calls :undojoin without making any changes, this makes it an error.
+ feed('afoo<Esc>u')
+ feed('0')
+ end)
+ after_each(function()
+ feed('u')
+ expect('||')
+ end)
+ it('pasting one line', function()
+ nvim('paste', 'aaaaaa', false, 1)
+ nvim('paste', 'bbbbbb', false, 2)
+ nvim('paste', 'cccccc', false, 2)
+ nvim('paste', 'dddddd', false, 3)
+ expect('|aaaaaabbbbbbccccccdddddd|')
+ end)
+ it('pasting multiple lines', function()
+ nvim('paste', 'aaaaaa\n', false, 1)
+ nvim('paste', 'bbbbbb\n', false, 2)
+ nvim('paste', 'cccccc\n', false, 2)
+ nvim('paste', 'dddddd', false, 3)
+ expect([[
+ |aaaaaa
+ bbbbbb
+ cccccc
+ dddddd|]])
+ end)
+ end)
+ describe('at the end of a line', function()
+ before_each(function()
+ feed('i||<Esc>')
+ -- If nvim_paste() calls :undojoin without making any changes, this makes it an error.
+ feed('afoo<Esc>u')
+ feed('2|')
+ end)
+ after_each(function()
+ feed('u')
+ expect('||')
+ end)
+ it('pasting one line', function()
+ nvim('paste', 'aaaaaa', false, 1)
+ nvim('paste', 'bbbbbb', false, 2)
+ nvim('paste', 'cccccc', false, 2)
+ nvim('paste', 'dddddd', false, 3)
+ expect('||aaaaaabbbbbbccccccdddddd')
+ end)
+ it('pasting multiple lines', function()
+ nvim('paste', 'aaaaaa\n', false, 1)
+ nvim('paste', 'bbbbbb\n', false, 2)
+ nvim('paste', 'cccccc\n', false, 2)
+ nvim('paste', 'dddddd', false, 3)
+ expect([[
+ ||aaaaaa
+ bbbbbb
+ cccccc
+ dddddd]])
+ end)
+ end)
+ end)
+ describe('stream: Visual mode', function()
+ describe('neither end at the end of a line', function()
+ before_each(function()
+ feed('i|xxx<CR>xxx|<Esc>')
+ -- If nvim_paste() calls :undojoin without making any changes, this makes it an error.
+ feed('afoo<Esc>u')
+ feed('3|vhk')
+ end)
+ after_each(function()
+ feed('u')
+ expect([[
+ |xxx
+ xxx|]])
+ end)
+ it('with non-empty chunks', function()
+ nvim('paste', 'aaaaaa', false, 1)
+ nvim('paste', 'bbbbbb', false, 2)
+ nvim('paste', 'cccccc', false, 2)
+ nvim('paste', 'dddddd', false, 3)
+ expect('|aaaaaabbbbbbccccccdddddd|')
+ end)
+ it('with empty first chunk', function()
+ nvim('paste', '', false, 1)
+ nvim('paste', 'bbbbbb', false, 2)
+ nvim('paste', 'cccccc', false, 2)
+ nvim('paste', 'dddddd', false, 3)
+ expect('|bbbbbbccccccdddddd|')
+ end)
+ it('with all chunks empty', function()
+ nvim('paste', '', false, 1)
+ nvim('paste', '', false, 2)
+ nvim('paste', '', false, 2)
+ nvim('paste', '', false, 3)
+ expect('||')
+ end)
+ end)
+ describe('cursor at the end of a line', function()
+ before_each(function()
+ feed('i||xxx<CR>xxx<Esc>')
+ -- If nvim_paste() calls :undojoin without making any changes, this makes it an error.
+ feed('afoo<Esc>u')
+ feed('3|vko')
+ end)
+ after_each(function()
+ feed('u')
+ expect([[
+ ||xxx
+ xxx]])
+ end)
+ it('with non-empty chunks', function()
+ nvim('paste', 'aaaaaa', false, 1)
+ nvim('paste', 'bbbbbb', false, 2)
+ nvim('paste', 'cccccc', false, 2)
+ nvim('paste', 'dddddd', false, 3)
+ expect('||aaaaaabbbbbbccccccdddddd')
+ end)
+ it('with empty first chunk', function()
+ nvim('paste', '', false, 1)
+ nvim('paste', 'bbbbbb', false, 2)
+ nvim('paste', 'cccccc', false, 2)
+ nvim('paste', 'dddddd', false, 3)
+ expect('||bbbbbbccccccdddddd')
+ end)
+ end)
+ describe('other end at the end of a line', function()
+ before_each(function()
+ feed('i||xxx<CR>xxx<Esc>')
+ -- If nvim_paste() calls :undojoin without making any changes, this makes it an error.
+ feed('afoo<Esc>u')
+ feed('3|vk')
+ end)
+ after_each(function()
+ feed('u')
+ expect([[
+ ||xxx
+ xxx]])
+ end)
+ it('with non-empty chunks', function()
+ nvim('paste', 'aaaaaa', false, 1)
+ nvim('paste', 'bbbbbb', false, 2)
+ nvim('paste', 'cccccc', false, 2)
+ nvim('paste', 'dddddd', false, 3)
+ expect('||aaaaaabbbbbbccccccdddddd')
+ end)
+ it('with empty first chunk', function()
+ nvim('paste', '', false, 1)
+ nvim('paste', 'bbbbbb', false, 2)
+ nvim('paste', 'cccccc', false, 2)
+ nvim('paste', 'dddddd', false, 3)
+ expect('||bbbbbbccccccdddddd')
+ end)
+ end)
+ end)
+ describe('stream: linewise Visual mode', function()
+ before_each(function()
+ feed('i123456789<CR>987654321<CR>123456789<Esc>')
+ -- If nvim_paste() calls :undojoin without making any changes, this makes it an error.
+ feed('afoo<Esc>u')
+ end)
+ after_each(function()
+ feed('u')
+ expect([[
+ 123456789
+ 987654321
+ 123456789]])
+ end)
+ describe('selecting the start of a file', function()
+ before_each(function()
+ feed('ggV')
+ end)
+ it('pasting text without final new line', function()
+ nvim('paste', 'aaaaaa\n', false, 1)
+ nvim('paste', 'bbbbbb\n', false, 2)
+ nvim('paste', 'cccccc\n', false, 2)
+ nvim('paste', 'dddddd', false, 3)
+ expect([[
+ aaaaaa
+ bbbbbb
+ cccccc
+ dddddd987654321
+ 123456789]])
+ end)
+ it('pasting text with final new line', function()
+ nvim('paste', 'aaaaaa\n', false, 1)
+ nvim('paste', 'bbbbbb\n', false, 2)
+ nvim('paste', 'cccccc\n', false, 2)
+ nvim('paste', 'dddddd\n', false, 3)
+ expect([[
+ aaaaaa
+ bbbbbb
+ cccccc
+ dddddd
+ 987654321
+ 123456789]])
+ end)
+ end)
+ describe('selecting the middle of a file', function()
+ before_each(function()
+ feed('2ggV')
+ end)
+ it('pasting text without final new line', function()
+ nvim('paste', 'aaaaaa\n', false, 1)
+ nvim('paste', 'bbbbbb\n', false, 2)
+ nvim('paste', 'cccccc\n', false, 2)
+ nvim('paste', 'dddddd', false, 3)
+ expect([[
+ 123456789
+ aaaaaa
+ bbbbbb
+ cccccc
+ dddddd123456789]])
+ end)
+ it('pasting text with final new line', function()
+ nvim('paste', 'aaaaaa\n', false, 1)
+ nvim('paste', 'bbbbbb\n', false, 2)
+ nvim('paste', 'cccccc\n', false, 2)
+ nvim('paste', 'dddddd\n', false, 3)
+ expect([[
+ 123456789
+ aaaaaa
+ bbbbbb
+ cccccc
+ dddddd
+ 123456789]])
+ end)
+ end)
+ describe('selecting the end of a file', function()
+ before_each(function()
+ feed('3ggV')
+ end)
+ it('pasting text without final new line', function()
+ nvim('paste', 'aaaaaa\n', false, 1)
+ nvim('paste', 'bbbbbb\n', false, 2)
+ nvim('paste', 'cccccc\n', false, 2)
+ nvim('paste', 'dddddd', false, 3)
+ expect([[
+ 123456789
+ 987654321
+ aaaaaa
+ bbbbbb
+ cccccc
+ dddddd]])
+ end)
+ it('pasting text with final new line', function()
+ nvim('paste', 'aaaaaa\n', false, 1)
+ nvim('paste', 'bbbbbb\n', false, 2)
+ nvim('paste', 'cccccc\n', false, 2)
+ nvim('paste', 'dddddd\n', false, 3)
+ expect([[
+ 123456789
+ 987654321
+ aaaaaa
+ bbbbbb
+ cccccc
+ dddddd
+ ]])
+ end)
+ end)
+ describe('selecting the whole file', function()
+ before_each(function()
+ feed('ggVG')
+ end)
+ it('pasting text without final new line', function()
+ nvim('paste', 'aaaaaa\n', false, 1)
+ nvim('paste', 'bbbbbb\n', false, 2)
+ nvim('paste', 'cccccc\n', false, 2)
+ nvim('paste', 'dddddd', false, 3)
+ expect([[
+ aaaaaa
+ bbbbbb
+ cccccc
+ dddddd]])
+ end)
+ it('pasting text with final new line', function()
+ nvim('paste', 'aaaaaa\n', false, 1)
+ nvim('paste', 'bbbbbb\n', false, 2)
+ nvim('paste', 'cccccc\n', false, 2)
+ nvim('paste', 'dddddd\n', false, 3)
+ expect([[
+ aaaaaa
+ bbbbbb
+ cccccc
+ dddddd
+ ]])
+ end)
+ end)
+ end)
+ end
+ describe('without virtualedit,', function()
+ run_streamed_paste_tests()
+ end)
+ describe('with virtualedit=onemore,', function()
+ before_each(function()
+ command('set virtualedit=onemore')
+ end)
+ run_streamed_paste_tests()
end)
it('non-streaming', function()
-- With final "\n".
@@ -738,6 +1078,37 @@ describe('API', function()
eeffgghh
iijjkkll]])
end)
+ it('when searching in Visual mode', function()
+ feed('v/')
+ nvim('paste', 'aabbccdd', true, -1)
+ eq('aabbccdd', funcs.getcmdline())
+ expect('')
+ end)
+ it('pasting with empty last chunk in Cmdline mode', function()
+ local screen = Screen.new(20, 4)
+ screen:attach()
+ feed(':')
+ nvim('paste', 'Foo', true, 1)
+ nvim('paste', '', true, 3)
+ screen:expect([[
+ |
+ ~ |
+ ~ |
+ :Foo^ |
+ ]])
+ end)
+ it('pasting text with control characters in Cmdline mode', function()
+ local screen = Screen.new(20, 4)
+ screen:attach()
+ feed(':')
+ nvim('paste', 'normal! \023\022\006\027', true, -1)
+ screen:expect([[
+ |
+ ~ |
+ ~ |
+ :normal! ^W^V^F^[^ |
+ ]])
+ end)
it('crlf=false does not break lines at CR, CRLF', function()
nvim('paste', 'line 1\r\n\r\rline 2\nline 3\rline 4\r', false, -1)
expect('line 1\r\n\r\rline 2\nline 3\rline 4\r')
diff --git a/test/functional/core/channels_spec.lua b/test/functional/core/channels_spec.lua
index c28300f0f4..ca52404d3b 100644
--- a/test/functional/core/channels_spec.lua
+++ b/test/functional/core/channels_spec.lua
@@ -10,6 +10,8 @@ local nvim_prog = helpers.nvim_prog
local is_os = helpers.is_os
local retry = helpers.retry
local expect_twostreams = helpers.expect_twostreams
+local assert_alive = helpers.assert_alive
+local pcall_err = helpers.pcall_err
describe('channels', function()
local init = [[
@@ -314,3 +316,22 @@ describe('channels', function()
eq({"notification", "exit", {id, 1, {''}}}, next_msg())
end)
end)
+
+describe('loopback', function()
+ before_each(function()
+ clear()
+ command("let chan = sockconnect('pipe', v:servername, {'rpc': v:true})")
+ end)
+
+ it('does not crash when sending raw data', function()
+ eq("Vim(call):Can't send raw data to rpc channel",
+ pcall_err(command, "call chansend(chan, 'test')"))
+ assert_alive()
+ end)
+
+ it('are released when closed', function()
+ local chans = eval('len(nvim_list_chans())')
+ command('call chanclose(chan)')
+ eq(chans - 1, eval('len(nvim_list_chans())'))
+ end)
+end)
diff --git a/test/functional/lua/overrides_spec.lua b/test/functional/lua/overrides_spec.lua
index b0712ff366..9b51af1eec 100644
--- a/test/functional/lua/overrides_spec.lua
+++ b/test/functional/lua/overrides_spec.lua
@@ -61,6 +61,44 @@ describe('print', function()
eq('Vim(lua):E5108: Error executing lua E5114: Error while converting print argument #2: <Unknown error: lua_tolstring returned NULL for tostring result>',
pcall_err(command, 'lua print("foo", v_tblout, "bar")'))
end)
+ it('coerces error values into strings', function()
+ write_file(fname, [[
+ function string_error() error("my mistake") end
+ function number_error() error(1234) end
+ function nil_error() error(nil) end
+ function table_error() error({message = "my mistake"}) end
+ function custom_error()
+ local err = {message = "my mistake", code = 11234}
+ setmetatable(err, {
+ __tostring = function(t)
+ return "Internal Error [" .. t.code .. "] " .. t.message
+ end
+ })
+ error(err)
+ end
+ function bad_custom_error()
+ local err = {message = "my mistake", code = 11234}
+ setmetatable(err, {
+ -- intentionally not a function, downstream programmer has made an mistake
+ __tostring = "Internal Error [" .. err.code .. "] " .. err.message
+ })
+ error(err)
+ end
+ ]])
+ eq('', exec_capture('luafile ' .. fname))
+ eq('Vim(lua):E5108: Error executing lua Xtest-functional-lua-overrides-luafile:0: my mistake',
+ pcall_err(command, 'lua string_error()'))
+ eq('Vim(lua):E5108: Error executing lua Xtest-functional-lua-overrides-luafile:0: 1234',
+ pcall_err(command, 'lua number_error()'))
+ eq('Vim(lua):E5108: Error executing lua [NULL]',
+ pcall_err(command, 'lua nil_error()'))
+ eq('Vim(lua):E5108: Error executing lua [NULL]',
+ pcall_err(command, 'lua table_error()'))
+ eq('Vim(lua):E5108: Error executing lua Internal Error [11234] my mistake',
+ pcall_err(command, 'lua custom_error()'))
+ eq('Vim(lua):E5108: Error executing lua [NULL]',
+ pcall_err(command, 'lua bad_custom_error()'))
+ end)
it('prints strings with NULs and NLs correctly', function()
meths.set_option('more', true)
eq('abc ^@ def\nghi^@^@^@jkl\nTEST\n\n\nT\n',
diff --git a/test/functional/lua/vim_spec.lua b/test/functional/lua/vim_spec.lua
index e66e08d9d0..5b4daf02ea 100644
--- a/test/functional/lua/vim_spec.lua
+++ b/test/functional/lua/vim_spec.lua
@@ -14,7 +14,7 @@ local feed = helpers.feed
local pcall_err = helpers.pcall_err
local exec_lua = helpers.exec_lua
local matches = helpers.matches
-local source = helpers.source
+local exec = helpers.exec
local NIL = helpers.NIL
local retry = helpers.retry
local next_msg = helpers.next_msg
@@ -743,7 +743,7 @@ describe('lua stdlib', function()
-- compat: nvim_call_function uses "special" value for vimL float
eq(false, exec_lua([[return vim.api.nvim_call_function('sin', {0.0}) == 0.0 ]]))
- source([[
+ exec([[
func! FooFunc(test)
let g:test = a:test
return {}
@@ -771,6 +771,12 @@ describe('lua stdlib', function()
-- error handling
eq({false, 'Vim:E897: List or Blob required'}, exec_lua([[return {pcall(vim.fn.add, "aa", "bb")}]]))
+
+ -- conversion between LuaRef and Vim Funcref
+ eq(true, exec_lua([[
+ local x = vim.fn.VarArg(function() return 'foo' end, function() return 'bar' end)
+ return #x == 2 and x[1]() == 'foo' and x[2]() == 'bar'
+ ]]))
end)
it('vim.fn should error when calling API function', function()
@@ -993,8 +999,11 @@ describe('lua stdlib', function()
exec_lua [[
local counter = 0
- vim.g.AddCounter = function() counter = counter + 1 end
- vim.g.GetCounter = function() return counter end
+ local function add_counter() counter = counter + 1 end
+ local function get_counter() return counter end
+ vim.g.AddCounter = add_counter
+ vim.g.GetCounter = get_counter
+ vim.g.funcs = {add = add_counter, get = get_counter}
]]
eq(0, eval('g:GetCounter()'))
@@ -1006,11 +1015,18 @@ describe('lua stdlib', function()
eq(3, exec_lua([[return vim.g.GetCounter()]]))
exec_lua([[vim.api.nvim_get_var('AddCounter')()]])
eq(4, exec_lua([[return vim.api.nvim_get_var('GetCounter')()]]))
+ exec_lua([[vim.g.funcs.add()]])
+ eq(5, exec_lua([[return vim.g.funcs.get()]]))
+ exec_lua([[vim.api.nvim_get_var('funcs').add()]])
+ eq(6, exec_lua([[return vim.api.nvim_get_var('funcs').get()]]))
exec_lua [[
local counter = 0
- vim.api.nvim_set_var('AddCounter', function() counter = counter + 1 end)
- vim.api.nvim_set_var('GetCounter', function() return counter end)
+ local function add_counter() counter = counter + 1 end
+ local function get_counter() return counter end
+ vim.api.nvim_set_var('AddCounter', add_counter)
+ vim.api.nvim_set_var('GetCounter', get_counter)
+ vim.api.nvim_set_var('funcs', {add = add_counter, get = get_counter})
]]
eq(0, eval('g:GetCounter()'))
@@ -1022,6 +1038,10 @@ describe('lua stdlib', function()
eq(3, exec_lua([[return vim.g.GetCounter()]]))
exec_lua([[vim.api.nvim_get_var('AddCounter')()]])
eq(4, exec_lua([[return vim.api.nvim_get_var('GetCounter')()]]))
+ exec_lua([[vim.g.funcs.add()]])
+ eq(5, exec_lua([[return vim.g.funcs.get()]]))
+ exec_lua([[vim.api.nvim_get_var('funcs').add()]])
+ eq(6, exec_lua([[return vim.api.nvim_get_var('funcs').get()]]))
-- Check if autoload works properly
local pathsep = helpers.get_pathsep()
@@ -1072,8 +1092,11 @@ describe('lua stdlib', function()
exec_lua [[
local counter = 0
- vim.b.AddCounter = function() counter = counter + 1 end
- vim.b.GetCounter = function() return counter end
+ local function add_counter() counter = counter + 1 end
+ local function get_counter() return counter end
+ vim.b.AddCounter = add_counter
+ vim.b.GetCounter = get_counter
+ vim.b.funcs = {add = add_counter, get = get_counter}
]]
eq(0, eval('b:GetCounter()'))
@@ -1085,11 +1108,18 @@ describe('lua stdlib', function()
eq(3, exec_lua([[return vim.b.GetCounter()]]))
exec_lua([[vim.api.nvim_buf_get_var(0, 'AddCounter')()]])
eq(4, exec_lua([[return vim.api.nvim_buf_get_var(0, 'GetCounter')()]]))
+ exec_lua([[vim.b.funcs.add()]])
+ eq(5, exec_lua([[return vim.b.funcs.get()]]))
+ exec_lua([[vim.api.nvim_buf_get_var(0, 'funcs').add()]])
+ eq(6, exec_lua([[return vim.api.nvim_buf_get_var(0, 'funcs').get()]]))
exec_lua [[
local counter = 0
- vim.api.nvim_buf_set_var(0, 'AddCounter', function() counter = counter + 1 end)
- vim.api.nvim_buf_set_var(0, 'GetCounter', function() return counter end)
+ local function add_counter() counter = counter + 1 end
+ local function get_counter() return counter end
+ vim.api.nvim_buf_set_var(0, 'AddCounter', add_counter)
+ vim.api.nvim_buf_set_var(0, 'GetCounter', get_counter)
+ vim.api.nvim_buf_set_var(0, 'funcs', {add = add_counter, get = get_counter})
]]
eq(0, eval('b:GetCounter()'))
@@ -1101,6 +1131,10 @@ describe('lua stdlib', function()
eq(3, exec_lua([[return vim.b.GetCounter()]]))
exec_lua([[vim.api.nvim_buf_get_var(0, 'AddCounter')()]])
eq(4, exec_lua([[return vim.api.nvim_buf_get_var(0, 'GetCounter')()]]))
+ exec_lua([[vim.b.funcs.add()]])
+ eq(5, exec_lua([[return vim.b.funcs.get()]]))
+ exec_lua([[vim.api.nvim_buf_get_var(0, 'funcs').add()]])
+ eq(6, exec_lua([[return vim.api.nvim_buf_get_var(0, 'funcs').get()]]))
exec_lua [[
vim.cmd "vnew"
@@ -1141,8 +1175,11 @@ describe('lua stdlib', function()
exec_lua [[
local counter = 0
- vim.w.AddCounter = function() counter = counter + 1 end
- vim.w.GetCounter = function() return counter end
+ local function add_counter() counter = counter + 1 end
+ local function get_counter() return counter end
+ vim.w.AddCounter = add_counter
+ vim.w.GetCounter = get_counter
+ vim.w.funcs = {add = add_counter, get = get_counter}
]]
eq(0, eval('w:GetCounter()'))
@@ -1154,11 +1191,18 @@ describe('lua stdlib', function()
eq(3, exec_lua([[return vim.w.GetCounter()]]))
exec_lua([[vim.api.nvim_win_get_var(0, 'AddCounter')()]])
eq(4, exec_lua([[return vim.api.nvim_win_get_var(0, 'GetCounter')()]]))
+ exec_lua([[vim.w.funcs.add()]])
+ eq(5, exec_lua([[return vim.w.funcs.get()]]))
+ exec_lua([[vim.api.nvim_win_get_var(0, 'funcs').add()]])
+ eq(6, exec_lua([[return vim.api.nvim_win_get_var(0, 'funcs').get()]]))
exec_lua [[
local counter = 0
- vim.api.nvim_win_set_var(0, 'AddCounter', function() counter = counter + 1 end)
- vim.api.nvim_win_set_var(0, 'GetCounter', function() return counter end)
+ local function add_counter() counter = counter + 1 end
+ local function get_counter() return counter end
+ vim.api.nvim_win_set_var(0, 'AddCounter', add_counter)
+ vim.api.nvim_win_set_var(0, 'GetCounter', get_counter)
+ vim.api.nvim_win_set_var(0, 'funcs', {add = add_counter, get = get_counter})
]]
eq(0, eval('w:GetCounter()'))
@@ -1170,6 +1214,10 @@ describe('lua stdlib', function()
eq(3, exec_lua([[return vim.w.GetCounter()]]))
exec_lua([[vim.api.nvim_win_get_var(0, 'AddCounter')()]])
eq(4, exec_lua([[return vim.api.nvim_win_get_var(0, 'GetCounter')()]]))
+ exec_lua([[vim.w.funcs.add()]])
+ eq(5, exec_lua([[return vim.w.funcs.get()]]))
+ exec_lua([[vim.api.nvim_win_get_var(0, 'funcs').add()]])
+ eq(6, exec_lua([[return vim.api.nvim_win_get_var(0, 'funcs').get()]]))
exec_lua [[
vim.cmd "vnew"
@@ -1205,8 +1253,11 @@ describe('lua stdlib', function()
exec_lua [[
local counter = 0
- vim.t.AddCounter = function() counter = counter + 1 end
- vim.t.GetCounter = function() return counter end
+ local function add_counter() counter = counter + 1 end
+ local function get_counter() return counter end
+ vim.t.AddCounter = add_counter
+ vim.t.GetCounter = get_counter
+ vim.t.funcs = {add = add_counter, get = get_counter}
]]
eq(0, eval('t:GetCounter()'))
@@ -1218,11 +1269,18 @@ describe('lua stdlib', function()
eq(3, exec_lua([[return vim.t.GetCounter()]]))
exec_lua([[vim.api.nvim_tabpage_get_var(0, 'AddCounter')()]])
eq(4, exec_lua([[return vim.api.nvim_tabpage_get_var(0, 'GetCounter')()]]))
+ exec_lua([[vim.t.funcs.add()]])
+ eq(5, exec_lua([[return vim.t.funcs.get()]]))
+ exec_lua([[vim.api.nvim_tabpage_get_var(0, 'funcs').add()]])
+ eq(6, exec_lua([[return vim.api.nvim_tabpage_get_var(0, 'funcs').get()]]))
exec_lua [[
local counter = 0
- vim.api.nvim_tabpage_set_var(0, 'AddCounter', function() counter = counter + 1 end)
- vim.api.nvim_tabpage_set_var(0, 'GetCounter', function() return counter end)
+ local function add_counter() counter = counter + 1 end
+ local function get_counter() return counter end
+ vim.api.nvim_tabpage_set_var(0, 'AddCounter', add_counter)
+ vim.api.nvim_tabpage_set_var(0, 'GetCounter', get_counter)
+ vim.api.nvim_tabpage_set_var(0, 'funcs', {add = add_counter, get = get_counter})
]]
eq(0, eval('t:GetCounter()'))
@@ -1234,6 +1292,10 @@ describe('lua stdlib', function()
eq(3, exec_lua([[return vim.t.GetCounter()]]))
exec_lua([[vim.api.nvim_tabpage_get_var(0, 'AddCounter')()]])
eq(4, exec_lua([[return vim.api.nvim_tabpage_get_var(0, 'GetCounter')()]]))
+ exec_lua([[vim.t.funcs.add()]])
+ eq(5, exec_lua([[return vim.t.funcs.get()]]))
+ exec_lua([[vim.api.nvim_tabpage_get_var(0, 'funcs').add()]])
+ eq(6, exec_lua([[return vim.api.nvim_tabpage_get_var(0, 'funcs').get()]]))
exec_lua [[
vim.cmd "tabnew"
diff --git a/test/functional/provider/python3_spec.lua b/test/functional/provider/python3_spec.lua
index 603f4d91b9..d9c44c3315 100644
--- a/test/functional/provider/python3_spec.lua
+++ b/test/functional/provider/python3_spec.lua
@@ -9,6 +9,7 @@ local missing_provider = helpers.missing_provider
local matches = helpers.matches
local pcall_err = helpers.pcall_err
local funcs = helpers.funcs
+local dedent = helpers.dedent
do
clear()
@@ -49,7 +50,12 @@ describe('python3 provider', function()
local very_long_symbol = string.rep('a', 1200)
feed_command(':silent! py3 print('..very_long_symbol..' b)')
-- Error message will contain this (last) line.
- eq('Error invoking \'python_execute\' on channel 3 (python3-script-host):\n File "<string>", line 1\n print('..very_long_symbol..' b)\n '..string.rep(' ',1200)..' ^\nSyntaxError: invalid syntax', eval('v:errmsg'))
+ matches(string.format(dedent([[
+ ^Error invoking 'python_execute' on channel 3 %%(python3%%-script%%-host%%):
+ File "<string>", line 1
+ print%%(%s b%%)
+ %%C*
+ SyntaxError: invalid syntax%%C*$]]), very_long_symbol), eval('v:errmsg'))
end)
it('python3_execute with nested commands', function()
diff --git a/test/functional/terminal/channel_spec.lua b/test/functional/terminal/channel_spec.lua
index 7223f5ba61..b5f3c2bd31 100644
--- a/test/functional/terminal/channel_spec.lua
+++ b/test/functional/terminal/channel_spec.lua
@@ -1,45 +1,94 @@
local helpers = require('test.functional.helpers')(after_each)
+local Screen = require('test.functional.ui.screen')
local clear = helpers.clear
local eq = helpers.eq
+local eval = helpers.eval
local command = helpers.command
local pcall_err = helpers.pcall_err
local feed = helpers.feed
-local sleep = helpers.sleep
local poke_eventloop = helpers.poke_eventloop
-describe('associated channel is closed and later freed for terminal', function()
- before_each(clear)
+describe('terminal channel is closed and later released if', function()
+ local screen
+
+ before_each(function()
+ clear()
+ screen = Screen.new()
+ screen:attach()
+ end)
it('opened by nvim_open_term() and deleted by :bdelete!', function()
command([[let id = nvim_open_term(0, {})]])
- -- channel hasn't been freed yet
- eq("Vim(call):Can't send data to closed stream", pcall_err(command, [[bdelete! | call chansend(id, 'test')]]))
- -- channel has been freed after one main loop iteration
- eq("Vim(call):E900: Invalid channel id", pcall_err(command, [[call chansend(id, 'test')]]))
+ local chans = eval('len(nvim_list_chans())')
+ -- channel hasn't been released yet
+ eq("Vim(call):Can't send data to closed stream",
+ pcall_err(command, [[bdelete! | call chansend(id, 'test')]]))
+ -- channel has been released after one main loop iteration
+ eq(chans - 1, eval('len(nvim_list_chans())'))
+ end)
+
+ it('opened by nvim_open_term(), closed by chanclose(), and deleted by pressing a key', function()
+ command('let id = nvim_open_term(0, {})')
+ local chans = eval('len(nvim_list_chans())')
+ -- channel has been closed but not released
+ eq("Vim(call):Can't send data to closed stream",
+ pcall_err(command, [[call chanclose(id) | call chansend(id, 'test')]]))
+ screen:expect({any='%[Terminal closed%]'})
+ eq(chans, eval('len(nvim_list_chans())'))
+ -- delete terminal
+ feed('i<CR>')
+ -- need to first process input
+ poke_eventloop()
+ -- channel has been released after another main loop iteration
+ eq(chans - 1, eval('len(nvim_list_chans())'))
+ end)
+
+ it('opened by nvim_open_term(), closed by chanclose(), and deleted by :bdelete', function()
+ command('let id = nvim_open_term(0, {})')
+ local chans = eval('len(nvim_list_chans())')
+ -- channel has been closed but not released
+ eq("Vim(call):Can't send data to closed stream",
+ pcall_err(command, [[call chanclose(id) | call chansend(id, 'test')]]))
+ screen:expect({any='%[Terminal closed%]'})
+ eq(chans, eval('len(nvim_list_chans())'))
+ -- channel still hasn't been released yet
+ eq("Vim(call):Can't send data to closed stream",
+ pcall_err(command, [[bdelete | call chansend(id, 'test')]]))
+ -- channel has been released after one main loop iteration
+ eq(chans - 1, eval('len(nvim_list_chans())'))
end)
it('opened by termopen(), exited, and deleted by pressing a key', function()
command([[let id = termopen('echo')]])
- sleep(500)
- -- process has exited
- eq("Vim(call):Can't send data to closed stream", pcall_err(command, [[call chansend(id, 'test')]]))
+ local chans = eval('len(nvim_list_chans())')
+ -- wait for process to exit
+ screen:expect({any='%[Process exited 0%]'})
+ -- process has exited but channel has't been released
+ eq("Vim(call):Can't send data to closed stream",
+ pcall_err(command, [[call chansend(id, 'test')]]))
+ eq(chans, eval('len(nvim_list_chans())'))
-- delete terminal
feed('i<CR>')
-- need to first process input
poke_eventloop()
- -- channel has been freed after another main loop iteration
- eq("Vim(call):E900: Invalid channel id", pcall_err(command, [[call chansend(id, 'test')]]))
+ -- channel has been released after another main loop iteration
+ eq(chans - 1, eval('len(nvim_list_chans())'))
end)
-- This indirectly covers #16264
it('opened by termopen(), exited, and deleted by :bdelete', function()
command([[let id = termopen('echo')]])
- sleep(500)
- -- process has exited
- eq("Vim(call):Can't send data to closed stream", pcall_err(command, [[call chansend(id, 'test')]]))
- -- channel hasn't been freed yet
- eq("Vim(call):Can't send data to closed stream", pcall_err(command, [[bdelete | call chansend(id, 'test')]]))
- -- channel has been freed after one main loop iteration
- eq("Vim(call):E900: Invalid channel id", pcall_err(command, [[call chansend(id, 'test')]]))
+ local chans = eval('len(nvim_list_chans())')
+ -- wait for process to exit
+ screen:expect({any='%[Process exited 0%]'})
+ -- process has exited but channel hasn't been released
+ eq("Vim(call):Can't send data to closed stream",
+ pcall_err(command, [[call chansend(id, 'test')]]))
+ eq(chans, eval('len(nvim_list_chans())'))
+ -- channel still hasn't been released yet
+ eq("Vim(call):Can't send data to closed stream",
+ pcall_err(command, [[bdelete | call chansend(id, 'test')]]))
+ -- channel has been released after one main loop iteration
+ eq(chans - 1, eval('len(nvim_list_chans())'))
end)
end)
diff --git a/test/functional/terminal/tui_spec.lua b/test/functional/terminal/tui_spec.lua
index faf44fa01d..c37cde06ab 100644
--- a/test/functional/terminal/tui_spec.lua
+++ b/test/functional/terminal/tui_spec.lua
@@ -323,7 +323,7 @@ describe('TUI', function()
feed_data('just paste it™')
feed_data('\027[201~')
screen:expect{grid=[[
- thisjust paste it™{1:3} is here |
+ thisjust paste it{1:™}3 is here |
|
{4:~ }|
{4:~ }|
@@ -379,7 +379,7 @@ describe('TUI', function()
end)
it('paste: normal-mode (+CRLF #10872)', function()
- feed_data(':set ruler')
+ feed_data(':set ruler | echo')
wait_for_mode('c')
feed_data('\n')
wait_for_mode('n')
@@ -423,13 +423,13 @@ describe('TUI', function()
expect_child_buf_lines(expected_crlf)
feed_data('u')
expect_child_buf_lines({''})
+ feed_data(':echo')
+ wait_for_mode('c')
+ feed_data('\n')
+ wait_for_mode('n')
-- CRLF input
feed_data('\027[200~'..table.concat(expected_lf,'\r\n')..'\027[201~')
- screen:expect{
- grid=expected_grid1:gsub(
- ':set ruler *',
- '3 fewer lines; before #1 0 seconds ago '),
- attr_ids=expected_attr}
+ screen:expect{grid=expected_grid1, attr_ids=expected_attr}
expect_child_buf_lines(expected_crlf)
end)
diff --git a/test/functional/ui/cursor_spec.lua b/test/functional/ui/cursor_spec.lua
index 03cd4bfd06..4c51547e2c 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 = 60
+ m.hl_id = 61
m.attr = {background = Screen.colors.DarkGray}
end
- if m.id_lm then m.id_lm = 61 end
+ if m.id_lm then m.id_lm = 62 end
end
-- Assert the new expectation.
diff --git a/test/functional/ui/global_statusline_spec.lua b/test/functional/ui/global_statusline_spec.lua
new file mode 100644
index 0000000000..6b37e5e2f1
--- /dev/null
+++ b/test/functional/ui/global_statusline_spec.lua
@@ -0,0 +1,233 @@
+local helpers = require('test.functional.helpers')(after_each)
+local Screen = require('test.functional.ui.screen')
+local clear, command, feed = helpers.clear, helpers.command, helpers.feed
+
+describe('global statusline', function()
+ local screen
+
+ before_each(function()
+ clear()
+ screen = Screen.new(60, 16)
+ screen:attach()
+ command('set laststatus=3')
+ command('set ruler')
+ end)
+
+ it('works', function()
+ screen:expect{grid=[[
+ ^ |
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {2:[No Name] 0,0-1 All}|
+ |
+ ]], attr_ids={
+ [1] = {bold = true, foreground = Screen.colors.Blue1};
+ [2] = {bold = true, reverse = true};
+ }}
+
+ feed('i<CR><CR>')
+ screen:expect{grid=[[
+ |
+ |
+ ^ |
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {2:[No Name] [+] 3,1 All}|
+ {3:-- INSERT --} |
+ ]], attr_ids={
+ [1] = {bold = true, foreground = Screen.colors.Blue};
+ [2] = {bold = true, reverse = true};
+ [3] = {bold = true};
+ }}
+ end)
+
+ it('works with splits', function()
+ command('vsplit | split | vsplit | vsplit | wincmd l | split | 2wincmd l | split')
+ screen:expect{grid=[[
+ {1:│} {1:│} {1:│}^ |
+ {2:~ }{1:│}{2:~ }{1:│}{2:~}{1:│}{2:~ }|
+ {2:~ }{1:│}{2:~ }{1:│}{2:~}{1:│}{2:~ }|
+ {2:~ }{1:│}{2:~ }{1:│}{2:~}{1:│}{2:~ }|
+ {2:~ }{1:├────────────────┤}{2:~}{1:│}{2:~ }|
+ {2:~ }{1:│} {1:│}{2:~}{1:│}{2:~ }|
+ {2:~ }{1:│}{2:~ }{1:│}{2:~}{1:│}{2:~ }|
+ {2:~ }{1:│}{2:~ }{1:│}{2:~}{1:├────────────────────}|
+ {2:~ }{1:│}{2:~ }{1:│}{2:~}{1:│} |
+ {1:────────────────────┴────────────────┴─┤}{2:~ }|
+ {1:│}{2:~ }|
+ {2:~ }{1:│}{2:~ }|
+ {2:~ }{1:│}{2:~ }|
+ {2:~ }{1:│}{2:~ }|
+ {3:[No Name] 0,0-1 All}|
+ |
+ ]], attr_ids={
+ [1] = {reverse = true};
+ [2] = {bold = true, foreground = Screen.colors.Blue1};
+ [3] = {bold = true, reverse = true};
+ }}
+ end)
+
+ it('works when switching between values of laststatus', function()
+ command('set laststatus=1')
+ screen:expect{grid=[[
+ ^ |
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ 0,0-1 All |
+ ]], attr_ids={
+ [1] = {foreground = Screen.colors.Blue, bold = true};
+ }}
+
+ command('set laststatus=3')
+ screen:expect{grid=[[
+ ^ |
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {2:[No Name] 0,0-1 All}|
+ |
+ ]], attr_ids={
+ [1] = {foreground = Screen.colors.Blue, bold = true};
+ [2] = {reverse = true, bold = true};
+ }}
+
+ command('vsplit | split | vsplit | vsplit | wincmd l | split | 2wincmd l | split')
+ command('set laststatus=2')
+ screen:expect{grid=[[
+ {1:│} {1:│} {1:│}^ |
+ {2:~ }{1:│}{2:~ }{1:│}{2:~}{1:│}{2:~ }|
+ {2:~ }{1:│}{2:~ }{1:│}{2:~}{1:│}{2:~ }|
+ {2:~ }{1:│}{2:~ }{1:│}{2:~}{1:│}{2:~ }|
+ {2:~ }{1:│< Name] 0,0-1 │}{2:~}{1:│}{2:~ }|
+ {2:~ }{1:│} {1:│}{2:~}{1:│}{2:~ }|
+ {2:~ }{1:│}{2:~ }{1:│}{2:~}{1:│}{2:~ }|
+ {2:~ }{1:│}{2:~ }{1:│}{2:~}{1:│}{3:<No Name] 0,0-1 All}|
+ {2:~ }{1:│}{2:~ }{1:│}{2:~}{1:│} |
+ {1:<No Name] 0,0-1 All < Name] 0,0-1 <│}{2:~ }|
+ {1:│}{2:~ }|
+ {2:~ }{1:│}{2:~ }|
+ {2:~ }{1:│}{2:~ }|
+ {2:~ }{1:│}{2:~ }|
+ {1:[No Name] 0,0-1 All <No Name] 0,0-1 All}|
+ |
+ ]], attr_ids={
+ [1] = {reverse = true};
+ [2] = {foreground = Screen.colors.Blue, bold = true};
+ [3] = {reverse = true, bold = true};
+ }}
+
+ command('set laststatus=3')
+ screen:expect{grid=[[
+ {1:│} {1:│} {1:│}^ |
+ {2:~ }{1:│}{2:~ }{1:│}{2:~}{1:│}{2:~ }|
+ {2:~ }{1:│}{2:~ }{1:│}{2:~}{1:│}{2:~ }|
+ {2:~ }{1:│}{2:~ }{1:│}{2:~}{1:│}{2:~ }|
+ {2:~ }{1:├────────────────┤}{2:~}{1:│}{2:~ }|
+ {2:~ }{1:│} {1:│}{2:~}{1:│}{2:~ }|
+ {2:~ }{1:│}{2:~ }{1:│}{2:~}{1:│}{2:~ }|
+ {2:~ }{1:│}{2:~ }{1:│}{2:~}{1:├────────────────────}|
+ {2:~ }{1:│}{2:~ }{1:│}{2:~}{1:│} |
+ {1:────────────────────┴────────────────┴─┤}{2:~ }|
+ {1:│}{2:~ }|
+ {2:~ }{1:│}{2:~ }|
+ {2:~ }{1:│}{2:~ }|
+ {2:~ }{1:│}{2:~ }|
+ {3:[No Name] 0,0-1 All}|
+ |
+ ]], attr_ids={
+ [1] = {reverse = true};
+ [2] = {foreground = Screen.colors.Blue, bold = true};
+ [3] = {reverse = true, bold = true};
+ }}
+
+ command('set laststatus=0')
+ screen:expect{grid=[[
+ {1:│} {1:│} {1:│}^ |
+ {2:~ }{1:│}{2:~ }{1:│}{2:~}{1:│}{2:~ }|
+ {2:~ }{1:│}{2:~ }{1:│}{2:~}{1:│}{2:~ }|
+ {2:~ }{1:│}{2:~ }{1:│}{2:~}{1:│}{2:~ }|
+ {2:~ }{1:│< Name] 0,0-1 │}{2:~}{1:│}{2:~ }|
+ {2:~ }{1:│} {1:│}{2:~}{1:│}{2:~ }|
+ {2:~ }{1:│}{2:~ }{1:│}{2:~}{1:│}{2:~ }|
+ {2:~ }{1:│}{2:~ }{1:│}{2:~}{1:│}{3:<No Name] 0,0-1 All}|
+ {2:~ }{1:│}{2:~ }{1:│}{2:~}{1:│} |
+ {1:<No Name] 0,0-1 All < Name] 0,0-1 <│}{2:~ }|
+ {1:│}{2:~ }|
+ {2:~ }{1:│}{2:~ }|
+ {2:~ }{1:│}{2:~ }|
+ {2:~ }{1:│}{2:~ }|
+ {2:~ }{1:│}{2:~ }|
+ 0,0-1 All |
+ ]], attr_ids={
+ [1] = {reverse = true};
+ [2] = {foreground = Screen.colors.Blue, bold = true};
+ [3] = {reverse = true, bold = true};
+ }}
+
+ command('set laststatus=3')
+ screen:expect{grid=[[
+ {1:│} {1:│} {1:│}^ |
+ {2:~ }{1:│}{2:~ }{1:│}{2:~}{1:│}{2:~ }|
+ {2:~ }{1:│}{2:~ }{1:│}{2:~}{1:│}{2:~ }|
+ {2:~ }{1:│}{2:~ }{1:│}{2:~}{1:│}{2:~ }|
+ {2:~ }{1:├────────────────┤}{2:~}{1:│}{2:~ }|
+ {2:~ }{1:│} {1:│}{2:~}{1:│}{2:~ }|
+ {2:~ }{1:│}{2:~ }{1:│}{2:~}{1:│}{2:~ }|
+ {2:~ }{1:│}{2:~ }{1:│}{2:~}{1:├────────────────────}|
+ {2:~ }{1:│}{2:~ }{1:│}{2:~}{1:│} |
+ {1:────────────────────┴────────────────┴─┤}{2:~ }|
+ {1:│}{2:~ }|
+ {2:~ }{1:│}{2:~ }|
+ {2:~ }{1:│}{2:~ }|
+ {2:~ }{1:│}{2:~ }|
+ {3:[No Name] 0,0-1 All}|
+ |
+ ]], attr_ids={
+ [1] = {reverse = true};
+ [2] = {foreground = Screen.colors.Blue, bold = true};
+ [3] = {reverse = true, bold = true};
+ }}
+ end)
+end)
diff --git a/test/functional/ui/hlstate_spec.lua b/test/functional/ui/hlstate_spec.lua
index 295b70f265..dcea2c76dd 100644
--- a/test/functional/ui/hlstate_spec.lua
+++ b/test/functional/ui/hlstate_spec.lua
@@ -59,7 +59,7 @@ describe('ext_hlstate detailed highlights', function()
it('work with cleared UI highlights', function()
screen:set_default_attr_ids({
- [1] = {{}, {{hi_name = "VertSplit", ui_name = "VertSplit", kind = "ui"}}},
+ [1] = {{}, {{hi_name = "VertSplit", ui_name = "WinSeparator", kind = "ui"}}},
[2] = {{bold = true, foreground = Screen.colors.Blue1},
{{hi_name = "NonText", ui_name = "EndOfBuffer", kind = "ui"}}},
[3] = {{bold = true, reverse = true},
diff --git a/test/unit/viml/expressions/parser_spec.lua b/test/unit/viml/expressions/parser_spec.lua
index 8342044b5e..51a703b593 100644
--- a/test/unit/viml/expressions/parser_spec.lua
+++ b/test/unit/viml/expressions/parser_spec.lua
@@ -48,6 +48,7 @@ local predefined_hl_defs = {
TermCursor=true,
VertSplit=true,
WildMenu=true,
+ WinSeparator=true,
EndOfBuffer=true,
QuickFixLine=true,
Substitute=true,