aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.github/ISSUE_TEMPLATE/bug_report.yml2
-rw-r--r--.github/ISSUE_TEMPLATE/lsp_bug_report.yml2
-rw-r--r--.github/labeler.yml18
-rw-r--r--.github/workflows/labeler.yml3
-rw-r--r--runtime/doc/eval.txt23
-rw-r--r--runtime/doc/lsp.txt16
-rw-r--r--runtime/doc/syntax.txt61
-rw-r--r--runtime/doc/vim_diff.txt8
-rw-r--r--runtime/lua/vim/lsp.lua10
-rw-r--r--runtime/lua/vim/lsp/diagnostic.lua47
-rw-r--r--runtime/syntax/syncolor.vim89
-rw-r--r--runtime/syntax/synload.vim5
-rw-r--r--src/nvim/api/buffer.c87
-rw-r--r--src/nvim/api/deprecated.c82
-rw-r--r--src/nvim/api/private/helpers.c36
-rw-r--r--src/nvim/decoration.c26
-rw-r--r--src/nvim/decoration.h13
-rw-r--r--src/nvim/eval.lua1
-rw-r--r--src/nvim/eval/funcs.c41
-rw-r--r--src/nvim/ex_session.c37
-rw-r--r--src/nvim/extmark.c2
-rw-r--r--src/nvim/globals.h2
-rw-r--r--src/nvim/main.c5
-rw-r--r--src/nvim/normal.c2
-rw-r--r--src/nvim/screen.c128
-rw-r--r--src/nvim/state.c3
-rw-r--r--src/nvim/syntax.c96
-rw-r--r--src/nvim/testdir/test_functions.vim19
-rw-r--r--src/nvim/testdir/test_mksession.vim23
-rw-r--r--test/functional/ex_cmds/mksession_spec.lua9
-rw-r--r--test/functional/ui/bufhl_spec.lua22
-rw-r--r--test/functional/ui/cmdline_spec.lua4
-rw-r--r--test/functional/ui/decorations_spec.lua94
-rw-r--r--test/functional/ui/highlight_spec.lua2
-rw-r--r--test/functional/ui/sign_spec.lua28
-rw-r--r--test/unit/viml/expressions/parser_spec.lua58
36 files changed, 608 insertions, 496 deletions
diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml
index e5530a1511..474fce0167 100644
--- a/.github/ISSUE_TEMPLATE/bug_report.yml
+++ b/.github/ISSUE_TEMPLATE/bug_report.yml
@@ -54,7 +54,7 @@ body:
- type: textarea
attributes:
label: "Expected behavior"
+ description: "A description of the behavior you expected. May optionally include logs, images, or videos."
- type: textarea
attributes:
label: "Actual behavior"
- description: "A description of the behavior you expected. May optionally include logs, images, or videos."
diff --git a/.github/ISSUE_TEMPLATE/lsp_bug_report.yml b/.github/ISSUE_TEMPLATE/lsp_bug_report.yml
index ff25bb0a23..ba1905329b 100644
--- a/.github/ISSUE_TEMPLATE/lsp_bug_report.yml
+++ b/.github/ISSUE_TEMPLATE/lsp_bug_report.yml
@@ -47,10 +47,10 @@ body:
- type: textarea
attributes:
label: "Expected behavior"
+ description: "A description of the behavior you expected. May optionally include logs, images, or videos."
- type: textarea
attributes:
label: "Actual behavior"
- description: "A description of the behavior you expected. May optionally include logs, images, or videos."
- type: markdown
attributes:
diff --git a/.github/labeler.yml b/.github/labeler.yml
index 282c6b1e7c..2de3904314 100644
--- a/.github/labeler.yml
+++ b/.github/labeler.yml
@@ -17,33 +17,33 @@
"dependencies":
- third-party/**/*
-"topic: spell":
+"spell":
- src/nvim/spell*
-"topic: :terminal":
+"terminal":
- src/nvim/terminal.*
-"topic: column":
+"column":
- src/nvim/mark.h
- src/nvim/mark.c
- src/nvim/sign*
-"topic: folds":
+"folds":
- src/nvim/fold*
-"topic: mouse":
+"mouse":
- src/nvim/mouse*
-"topic: documentation":
+"documentation":
- runtime/doc/*
-"topic: clipboard":
+"clipboard":
- runtime/autoload/provider/clipboard.vim
-"topic: diff":
+"diff":
- src/nvim/diff.*
-"topic: build":
+"build":
- CMakeLists.txt
- "**/CMakeLists.txt"
- "**/*.cmake"
diff --git a/.github/workflows/labeler.yml b/.github/workflows/labeler.yml
index 909e197b57..67ad4c0552 100644
--- a/.github/workflows/labeler.yml
+++ b/.github/workflows/labeler.yml
@@ -1,6 +1,7 @@
name: "Pull Request Labeler"
on:
-- pull_request_target
+ pull_request_target:
+ types: opened
jobs:
triage:
runs-on: ubuntu-latest
diff --git a/runtime/doc/eval.txt b/runtime/doc/eval.txt
index e32691dfb4..83e10d649d 100644
--- a/runtime/doc/eval.txt
+++ b/runtime/doc/eval.txt
@@ -2203,9 +2203,11 @@ getbufline({expr}, {lnum} [, {end}])
getbufvar({expr}, {varname} [, {def}])
any variable {varname} in buffer {expr}
getchangelist({expr}) List list of change list items
-getchar([expr]) Number get one character from the user
+getchar([expr]) Number or String
+ get one character from the user
getcharmod() Number modifiers for the last typed character
getcharsearch() Dict last character search
+getcharstr([expr]) String get one character from the user
getcmdline() String return the current command-line
getcmdpos() Number return cursor position in command-line
getcmdtype() String return current command-line type
@@ -4308,6 +4310,7 @@ getchar([expr]) *getchar()*
Return zero otherwise.
If [expr] is 1, only check if a character is available, it is
not consumed. Return zero if no character available.
+ If you prefer always getting a string use |getcharstr()|.
Without [expr] and when [expr] is 0 a whole character or
special key is returned. If it is a single character, the
@@ -4399,6 +4402,20 @@ getcharsearch() *getcharsearch()*
:nnoremap <expr> , getcharsearch().forward ? ',' : ';'
< Also see |setcharsearch()|.
+
+getcharstr([expr]) *getcharstr()*
+ Get a single character from the user or input stream as a
+ string.
+ If [expr] is omitted, wait until a character is available.
+ If [expr] is 0 or false, only get a character when one is
+ available. Return an empty string otherwise.
+ If [expr] is 1 or true, only check if a character is
+ available, it is not consumed. Return an empty string
+ if no character is available.
+ Otherwise this works like |getchar()|, except that a number
+ result is converted to a string.
+
+
getcmdline() *getcmdline()*
Return the current command-line. Only works when the command
line is being edited, thus requires use of |c_CTRL-\_e| or
@@ -6350,6 +6367,10 @@ mode([expr]) Return a string that indicates the current mode.
s Select by character
S Select by line
CTRL-S Select blockwise
+ vs Visual by character using |v_CTRL-O| from
+ Select mode
+ Vs Visual by line using |v_CTRL-O| from Select mode
+ CTRL-Vs Visual blockwise using |v_CTRL-O| from Select mode
i Insert
ic Insert mode completion |compl-generic|
ix Insert mode |i_CTRL-X| completion
diff --git a/runtime/doc/lsp.txt b/runtime/doc/lsp.txt
index c750a65c10..7daab4d6f1 100644
--- a/runtime/doc/lsp.txt
+++ b/runtime/doc/lsp.txt
@@ -1487,6 +1487,22 @@ on_publish_diagnostics({_}, {_}, {params}, {client_id}, {_}, {config})
• Sort diagnostics (and thus signs and virtual
text)
+redraw({bufnr}, {client_id}) *vim.lsp.diagnostic.redraw()*
+ Redraw diagnostics for the given buffer and client
+
+ This calls the "textDocument/publishDiagnostics" handler
+ manually using the cached diagnostics already received from
+ the server. This can be useful for redrawing diagnostics after
+ making changes in diagnostics configuration.
+ |lsp-handler-configuration|
+
+ Parameters: ~
+ {bufnr} (optional, number): Buffer handle, defaults
+ to current
+ {client_id} (optional, number): Redraw diagnostics for
+ the given client. The default is to redraw
+ diagnostics for all attached clients.
+
reset({client_id}, {buffer_client_map}) *vim.lsp.diagnostic.reset()*
Clear diagnotics and diagnostic cache
diff --git a/runtime/doc/syntax.txt b/runtime/doc/syntax.txt
index 6c51f37ae5..bc7a1e34c3 100644
--- a/runtime/doc/syntax.txt
+++ b/runtime/doc/syntax.txt
@@ -25,11 +25,15 @@ In the User Manual:
==============================================================================
1. Quick start *:syn-qstart*
- *:syn-enable* *:syntax-enable*
+ *:syn-enable* *:syntax-enable* *:syn-on* *:syntax-on*
This command switches on syntax highlighting: >
:syntax enable
+Alternatively: >
+
+ :syntax on
+
What this command actually does is to execute the command >
:source $VIMRUNTIME/syntax/syntax.vim
@@ -42,19 +46,11 @@ are in the "/usr/vim/vim82/syntax" directory, set $VIMRUNTIME to
This command also sources the |menu.vim| script when the GUI is running or
will start soon. See |'go-M'| about avoiding that.
- *:syn-on* *:syntax-on*
-The `:syntax enable` command will keep most of your current color settings.
-This allows using `:highlight` commands to set your preferred colors before or
-after using this command. If you want Vim to overrule your settings with the
-defaults, use: >
- :syntax on
-<
*:hi-normal* *:highlight-normal*
If you are running in the GUI, you can get white text on a black background
with: >
:highlight Normal guibg=Black guifg=White
For a color terminal see |:hi-normal-cterm|.
-For setting up your own colors syntax highlighting see |syncolor|.
NOTE: The syntax files on MS-Windows have lines that end in <CR><NL>.
The files for Unix end in <NL>. This means you should use the right type of
@@ -277,12 +273,6 @@ located. This is used here as the variable |$VIMRUNTIME|.
|
+- Source first syntax/synload.vim in 'runtimepath'
| |
- | +- Setup the colors for syntax highlighting. If a color scheme is
- | | defined it is loaded again with ":colors {name}". Otherwise
- | | ":runtime! syntax/syncolor.vim" is used. ":syntax on" overrules
- | | existing colors, ":syntax enable" only sets groups that weren't
- | | set yet.
- | |
| +- Set up syntax autocmds to load the appropriate syntax file when
| | the 'syntax' option is set. *synload-1*
| |
@@ -5271,51 +5261,10 @@ back to their Vim default.
Note that if you are using a color scheme, the colors defined by the color
scheme for syntax highlighting will be lost.
-What this actually does is: >
-
- let g:syntax_cmd = "reset"
- runtime! syntax/syncolor.vim
-
-Note that this uses the 'runtimepath' option.
-
- *syncolor*
-If you want to use different colors for syntax highlighting, you can add a Vim
-script file to set these colors. Put this file in a directory in
-'runtimepath' which comes after $VIMRUNTIME, so that your settings overrule
-the default colors. This way these colors will be used after the ":syntax
-reset" command.
-
-For Unix you can use the file ~/.config/nvim/after/syntax/syncolor.vim.
-Example: >
-
- if &background == "light"
- highlight comment ctermfg=darkgreen guifg=darkgreen
- else
- highlight comment ctermfg=green guifg=green
- endif
-
- *E679*
-Do make sure this syncolor.vim script does not use a "syntax on", set the
-'background' option or uses a "colorscheme" command, because it results in an
-endless loop.
-
Note that when a color scheme is used, there might be some confusion whether
your defined colors are to be used or the colors from the scheme. This
depends on the color scheme file. See |:colorscheme|.
- *syntax_cmd*
-The "syntax_cmd" variable is set to one of these values when the
-syntax/syncolor.vim files are loaded:
- "on" ":syntax on" command. Highlight colors are overruled but
- links are kept
- "enable" ":syntax enable" command. Only define colors for groups that
- don't have highlighting yet. Use ":syntax default".
- "reset" ":syntax reset" command or loading a color scheme. Define all
- the colors.
- "skip" Don't define colors. Used to skip the default settings when a
- syncolor.vim file earlier in 'runtimepath' has already set
- them.
-
==============================================================================
16. Highlighting tags *tag-highlight*
diff --git a/runtime/doc/vim_diff.txt b/runtime/doc/vim_diff.txt
index a259afded0..2c53620049 100644
--- a/runtime/doc/vim_diff.txt
+++ b/runtime/doc/vim_diff.txt
@@ -358,6 +358,14 @@ Startup:
- works by default: "-" file is optional
- works in more cases: |-Es|, file args
+Syntax highlighting:
+ syncolor.vim has been removed. Nvim now sets up default highlighting groups
+ automatically for both light and dark backgrounds, regardless of whether or
+ not syntax highlighting is enabled. This means that |:syntax-on| and
+ |:syntax-enable| are now identical. Users who previously used an
+ after/syntax/syncolor.vim file should transition that file into a
+ colorscheme. |:colorscheme|
+
TUI:
*:set-termcap*
Start Nvim with 'verbose' level 3 to show terminal capabilities: >
diff --git a/runtime/lua/vim/lsp.lua b/runtime/lua/vim/lsp.lua
index f5aefc8260..87ecc3eeea 100644
--- a/runtime/lua/vim/lsp.lua
+++ b/runtime/lua/vim/lsp.lua
@@ -453,15 +453,7 @@ local function text_document_did_open_handler(bufnr, client)
-- Next chance we get, we should re-do the diagnostics
vim.schedule(function()
- vim.lsp.handlers["textDocument/publishDiagnostics"](
- nil,
- "textDocument/publishDiagnostics",
- {
- diagnostics = vim.lsp.diagnostic.get(bufnr, client.id),
- uri = vim.uri_from_bufnr(bufnr),
- },
- client.id
- )
+ vim.lsp.diagnostic.redraw(bufnr, client.id)
end)
end
diff --git a/runtime/lua/vim/lsp/diagnostic.lua b/runtime/lua/vim/lsp/diagnostic.lua
index 246665602d..120320becc 100644
--- a/runtime/lua/vim/lsp/diagnostic.lua
+++ b/runtime/lua/vim/lsp/diagnostic.lua
@@ -1168,6 +1168,40 @@ function M.display(diagnostics, bufnr, client_id, config)
save_extmarks(bufnr, client_id)
end
+--- Redraw diagnostics for the given buffer and client
+---
+--- This calls the "textDocument/publishDiagnostics" handler manually using
+--- the cached diagnostics already received from the server. This can be useful
+--- for redrawing diagnostics after making changes in diagnostics
+--- configuration. |lsp-handler-configuration|
+---
+--- @param bufnr (optional, number): Buffer handle, defaults to current
+--- @param client_id (optional, number): Redraw diagnostics for the given
+--- client. The default is to redraw diagnostics for all attached
+--- clients.
+function M.redraw(bufnr, client_id)
+ bufnr = get_bufnr(bufnr)
+ if not client_id then
+ return vim.lsp.for_each_buffer_client(bufnr, function(client)
+ M.redraw(bufnr, client.id)
+ end)
+ end
+
+ -- We need to invoke the publishDiagnostics handler directly instead of just
+ -- calling M.display so that we can preserve any custom configuration options
+ -- the user may have set with vim.lsp.with.
+ vim.lsp.handlers["textDocument/publishDiagnostics"](
+ nil,
+ "textDocument/publishDiagnostics",
+ {
+ uri = vim.uri_from_bufnr(bufnr),
+ diagnostics = M.get(bufnr, client_id),
+ },
+ client_id,
+ bufnr
+ )
+end
+
-- }}}
-- Diagnostic User Functions {{{
@@ -1361,18 +1395,7 @@ function M.enable(bufnr, client_id)
diagnostic_disabled[bufnr][client_id] = nil
- -- We need to invoke the publishDiagnostics handler directly instead of just
- -- calling M.display so that we can preserve any custom configuration options
- -- the user may have set with vim.lsp.with.
- vim.lsp.handlers["textDocument/publishDiagnostics"](
- nil,
- "textDocument/publishDiagnostics",
- {
- diagnostics = M.get(bufnr, client_id),
- uri = vim.uri_from_bufnr(bufnr),
- },
- client_id
- )
+ M.redraw(bufnr, client_id)
end
-- }}}
diff --git a/runtime/syntax/syncolor.vim b/runtime/syntax/syncolor.vim
deleted file mode 100644
index 27cc3360c4..0000000000
--- a/runtime/syntax/syncolor.vim
+++ /dev/null
@@ -1,89 +0,0 @@
-" Vim syntax support file
-" Maintainer: Bram Moolenaar <Bram@vim.org>
-" Last Change: 2020 Feb 13
-
-" This file sets up the default methods for highlighting.
-" It is loaded from "synload.vim" and from Vim for ":syntax reset".
-" Also used from init_highlight().
-
-if !exists("syntax_cmd") || syntax_cmd == "on"
- " ":syntax on" works like in Vim 5.7: set colors but keep links
- command -nargs=* SynColor hi <args>
- command -nargs=* SynLink hi link <args>
-else
- if syntax_cmd == "enable"
- " ":syntax enable" keeps any existing colors
- command -nargs=* SynColor hi def <args>
- command -nargs=* SynLink hi def link <args>
- elseif syntax_cmd == "reset"
- " ":syntax reset" resets all colors to the default
- command -nargs=* SynColor hi <args>
- command -nargs=* SynLink hi! link <args>
- else
- " User defined syncolor file has already set the colors.
- finish
- endif
-endif
-
-let did_syncolor = 1
-
-" Many terminals can only use six different colors (plus black and white).
-" Therefore the number of colors used is kept low. It doesn't look nice with
-" too many colors anyway.
-" Careful with "cterm=bold", it changes the color to bright for some terminals.
-" There are two sets of defaults: for a dark and a light background.
-if &background == "dark"
- SynColor Comment term=bold cterm=NONE ctermfg=Cyan ctermbg=NONE gui=NONE guifg=#80a0ff guibg=NONE
- SynColor Constant term=underline cterm=NONE ctermfg=Magenta ctermbg=NONE gui=NONE guifg=#ffa0a0 guibg=NONE
- SynColor Special term=bold cterm=NONE ctermfg=LightRed ctermbg=NONE gui=NONE guifg=Orange guibg=NONE
- SynColor Identifier term=underline cterm=bold ctermfg=Cyan ctermbg=NONE gui=NONE guifg=#40ffff guibg=NONE
- SynColor Statement term=bold cterm=NONE ctermfg=Yellow ctermbg=NONE gui=bold guifg=#ffff60 guibg=NONE
- SynColor PreProc term=underline cterm=NONE ctermfg=LightBlue ctermbg=NONE gui=NONE guifg=#ff80ff guibg=NONE
- SynColor Type term=underline cterm=NONE ctermfg=LightGreen ctermbg=NONE gui=bold guifg=#60ff60 guibg=NONE
- SynColor Underlined term=underline cterm=underline ctermfg=LightBlue gui=underline guifg=#80a0ff
- SynColor Ignore term=NONE cterm=NONE ctermfg=black ctermbg=NONE gui=NONE guifg=bg guibg=NONE
-else
- SynColor Comment term=bold cterm=NONE ctermfg=DarkBlue ctermbg=NONE gui=NONE guifg=Blue guibg=NONE
- SynColor Constant term=underline cterm=NONE ctermfg=DarkRed ctermbg=NONE gui=NONE guifg=Magenta guibg=NONE
- " #6a5acd is SlateBlue
- SynColor Special term=bold cterm=NONE ctermfg=DarkMagenta ctermbg=NONE gui=NONE guifg=#6a5acd guibg=NONE
- SynColor Identifier term=underline cterm=NONE ctermfg=DarkCyan ctermbg=NONE gui=NONE guifg=DarkCyan guibg=NONE
- SynColor Statement term=bold cterm=NONE ctermfg=Brown ctermbg=NONE gui=bold guifg=Brown guibg=NONE
- " #6a0dad is Purple
- SynColor PreProc term=underline cterm=NONE ctermfg=DarkMagenta ctermbg=NONE gui=NONE guifg=#6a0dad guibg=NONE
- SynColor Type term=underline cterm=NONE ctermfg=DarkGreen ctermbg=NONE gui=bold guifg=SeaGreen guibg=NONE
- SynColor Underlined term=underline cterm=underline ctermfg=DarkMagenta gui=underline guifg=SlateBlue
- SynColor Ignore term=NONE cterm=NONE ctermfg=white ctermbg=NONE gui=NONE guifg=bg guibg=NONE
-endif
-SynColor Error term=reverse cterm=NONE ctermfg=White ctermbg=Red gui=NONE guifg=White guibg=Red
-SynColor Todo term=standout cterm=NONE ctermfg=Black ctermbg=Yellow gui=NONE guifg=Blue guibg=Yellow
-
-" Common groups that link to default highlighting.
-" You can specify other highlighting easily.
-SynLink String Constant
-SynLink Character Constant
-SynLink Number Constant
-SynLink Boolean Constant
-SynLink Float Number
-SynLink Function Identifier
-SynLink Conditional Statement
-SynLink Repeat Statement
-SynLink Label Statement
-SynLink Operator Statement
-SynLink Keyword Statement
-SynLink Exception Statement
-SynLink Include PreProc
-SynLink Define PreProc
-SynLink Macro PreProc
-SynLink PreCondit PreProc
-SynLink StorageClass Type
-SynLink Structure Type
-SynLink Typedef Type
-SynLink Tag Special
-SynLink SpecialChar Special
-SynLink Delimiter Special
-SynLink SpecialComment Special
-SynLink Debug Special
-
-delcommand SynColor
-delcommand SynLink
diff --git a/runtime/syntax/synload.vim b/runtime/syntax/synload.vim
index aee9ba8b8e..bfcd3b06da 100644
--- a/runtime/syntax/synload.vim
+++ b/runtime/syntax/synload.vim
@@ -14,11 +14,6 @@ endif
" let others know that syntax has been switched on
let syntax_on = 1
-" Set the default highlighting colors
-if !exists("colors_name") && !exists("did_syncolor")
- runtime! syntax/syncolor.vim
-endif
-
" Line continuation is used here, remove 'C' from 'cpoptions'
let s:cpo_save = &cpo
set cpo&vim
diff --git a/src/nvim/api/buffer.c b/src/nvim/api/buffer.c
index 78e36e5ef0..77cff0cb4f 100644
--- a/src/nvim/api/buffer.c
+++ b/src/nvim/api/buffer.c
@@ -1433,8 +1433,14 @@ Array nvim_buf_get_extmarks(Buffer buffer, Integer ns_id,
/// - hl_group : name of the highlight group used to highlight
/// this mark.
/// - virt_text : virtual text to link to this mark.
-/// - virt_text_pos : positioning of virtual text. Possible
-/// values:
+/// A list of [text, highlight] tuples, each representing a
+/// text chunk with specified highlight. `highlight` element
+/// can either be a a single highlight group, or an array of
+/// multiple highlight groups that will be stacked
+/// (highest priority last). A highlight group can be supplied
+/// either as a string or as an integer, the latter which
+/// can be obtained using |nvim_get_hl_id_by_name|.
+/// - virt_text_pos : position of virtual text. Possible values:
/// - "eol": right after eol character (default)
/// - "overlay": display over the specified column, without
/// shifting the underlying text.
@@ -1560,7 +1566,8 @@ Integer nvim_buf_set_extmark(Buffer buffer, Integer ns_id,
"virt_text is not an Array");
goto error;
}
- decor.virt_text = parse_virt_text(v->data.array, err);
+ decor.virt_text = parse_virt_text(v->data.array, err,
+ &decor.virt_text_width);
if (ERROR_SET(err)) {
goto error;
}
@@ -1892,80 +1899,6 @@ void nvim_buf_clear_namespace(Buffer buffer,
(int)line_end-1, MAXCOL);
}
-/// Set the virtual text (annotation) for a buffer line.
-///
-/// By default (and currently the only option) the text will be placed after
-/// the buffer text. Virtual text will never cause reflow, rather virtual
-/// text will be truncated at the end of the screen line. The virtual text will
-/// begin one cell (|lcs-eol| or space) after the ordinary text.
-///
-/// Namespaces are used to support batch deletion/updating of virtual text.
-/// To create a namespace, use |nvim_create_namespace()|. Virtual text is
-/// cleared using |nvim_buf_clear_namespace()|. The same `ns_id` can be used for
-/// both virtual text and highlights added by |nvim_buf_add_highlight()|, both
-/// can then be cleared with a single call to |nvim_buf_clear_namespace()|. If
-/// the virtual text never will be cleared by an API call, pass `ns_id = -1`.
-///
-/// As a shorthand, `ns_id = 0` can be used to create a new namespace for the
-/// virtual text, the allocated id is then returned.
-///
-/// @param buffer Buffer handle, or 0 for current buffer
-/// @param ns_id Namespace to use or 0 to create a namespace,
-/// or -1 for a ungrouped annotation
-/// @param line Line to annotate with virtual text (zero-indexed)
-/// @param chunks A list of [text, hl_group] arrays, each representing a
-/// text chunk with specified highlight. `hl_group` element
-/// can be omitted for no highlight.
-/// @param opts Optional parameters. Currently not used.
-/// @param[out] err Error details, if any
-/// @return The ns_id that was used
-Integer nvim_buf_set_virtual_text(Buffer buffer,
- Integer src_id,
- Integer line,
- Array chunks,
- Dictionary opts,
- Error *err)
- FUNC_API_SINCE(5)
-{
- buf_T *buf = find_buffer_by_handle(buffer, err);
- if (!buf) {
- return 0;
- }
-
- if (line < 0 || line >= MAXLNUM) {
- api_set_error(err, kErrorTypeValidation, "Line number outside range");
- return 0;
- }
-
- if (opts.size > 0) {
- api_set_error(err, kErrorTypeValidation, "opts dict isn't empty");
- return 0;
- }
-
- uint64_t ns_id = src2ns(&src_id);
-
- VirtText virt_text = parse_virt_text(chunks, err);
- if (ERROR_SET(err)) {
- return 0;
- }
-
-
- VirtText *existing = decor_find_virttext(buf, (int)line, ns_id);
-
- if (existing) {
- clear_virttext(existing);
- *existing = virt_text;
- return src_id;
- }
-
- Decoration *decor = xcalloc(1, sizeof(*decor));
- decor->virt_text = virt_text;
-
- extmark_set(buf, ns_id, 0, (int)line, 0, -1, -1, decor, true,
- false, kExtmarkNoUndo);
- return src_id;
-}
-
/// call a function with buffer as temporary current buffer
///
/// This temporarily switches current buffer to "buffer".
diff --git a/src/nvim/api/deprecated.c b/src/nvim/api/deprecated.c
index 3989386bb9..554966e266 100644
--- a/src/nvim/api/deprecated.c
+++ b/src/nvim/api/deprecated.c
@@ -12,6 +12,7 @@
#include "nvim/api/private/helpers.h"
#include "nvim/api/private/defs.h"
#include "nvim/lua/executor.h"
+#include "nvim/extmark.h"
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "api/deprecated.c.generated.h"
@@ -80,6 +81,87 @@ void nvim_buf_clear_highlight(Buffer buffer,
}
+/// Set the virtual text (annotation) for a buffer line.
+///
+/// @deprecated use nvim_buf_set_extmark to use full virtual text
+/// functionality.
+///
+/// The text will be placed after the buffer text. Virtual text will never
+/// cause reflow, rather virtual text will be truncated at the end of the screen
+/// line. The virtual text will begin one cell (|lcs-eol| or space) after the
+/// ordinary text.
+///
+/// Namespaces are used to support batch deletion/updating of virtual text.
+/// To create a namespace, use |nvim_create_namespace()|. Virtual text is
+/// cleared using |nvim_buf_clear_namespace()|. The same `ns_id` can be used for
+/// both virtual text and highlights added by |nvim_buf_add_highlight()|, both
+/// can then be cleared with a single call to |nvim_buf_clear_namespace()|. If
+/// the virtual text never will be cleared by an API call, pass `ns_id = -1`.
+///
+/// As a shorthand, `ns_id = 0` can be used to create a new namespace for the
+/// virtual text, the allocated id is then returned.
+///
+/// @param buffer Buffer handle, or 0 for current buffer
+/// @param ns_id Namespace to use or 0 to create a namespace,
+/// or -1 for a ungrouped annotation
+/// @param line Line to annotate with virtual text (zero-indexed)
+/// @param chunks A list of [text, hl_group] arrays, each representing a
+/// text chunk with specified highlight. `hl_group` element
+/// can be omitted for no highlight.
+/// @param opts Optional parameters. Currently not used.
+/// @param[out] err Error details, if any
+/// @return The ns_id that was used
+Integer nvim_buf_set_virtual_text(Buffer buffer,
+ Integer src_id,
+ Integer line,
+ Array chunks,
+ Dictionary opts,
+ Error *err)
+ FUNC_API_SINCE(5)
+ FUNC_API_DEPRECATED_SINCE(8)
+{
+ buf_T *buf = find_buffer_by_handle(buffer, err);
+ if (!buf) {
+ return 0;
+ }
+
+ if (line < 0 || line >= MAXLNUM) {
+ api_set_error(err, kErrorTypeValidation, "Line number outside range");
+ return 0;
+ }
+
+ if (opts.size > 0) {
+ api_set_error(err, kErrorTypeValidation, "opts dict isn't empty");
+ return 0;
+ }
+
+ uint64_t ns_id = src2ns(&src_id);
+ int width;
+
+ VirtText virt_text = parse_virt_text(chunks, err, &width);
+ if (ERROR_SET(err)) {
+ return 0;
+ }
+
+
+ Decoration *existing = decor_find_virttext(buf, (int)line, ns_id);
+
+ if (existing) {
+ clear_virttext(&existing->virt_text);
+ existing->virt_text = virt_text;
+ existing->virt_text_width = width;
+ return src_id;
+ }
+
+ Decoration *decor = xcalloc(1, sizeof(*decor));
+ decor->virt_text = virt_text;
+ decor->virt_text_width = width;
+
+ extmark_set(buf, ns_id, 0, (int)line, 0, -1, -1, decor, true,
+ false, kExtmarkNoUndo);
+ return src_id;
+}
+
/// Inserts a sequence of lines to a buffer at a certain index
///
/// @deprecated use nvim_buf_set_lines(buffer, lnum, lnum, true, lines)
diff --git a/src/nvim/api/private/helpers.c b/src/nvim/api/private/helpers.c
index 9f2e94f31e..3ec6151090 100644
--- a/src/nvim/api/private/helpers.c
+++ b/src/nvim/api/private/helpers.c
@@ -1592,9 +1592,10 @@ bool extmark_get_index_from_obj(buf_T *buf, Integer ns_id, Object obj, int
}
}
-VirtText parse_virt_text(Array chunks, Error *err)
+VirtText parse_virt_text(Array chunks, Error *err, int *width)
{
VirtText virt_text = KV_INITIAL_VALUE;
+ int w = 0;
for (size_t i = 0; i < chunks.size; i++) {
if (chunks.items[i].type != kObjectTypeArray) {
api_set_error(err, kErrorTypeValidation, "Chunk is not an array");
@@ -1602,26 +1603,44 @@ VirtText parse_virt_text(Array chunks, Error *err)
}
Array chunk = chunks.items[i].data.array;
if (chunk.size == 0 || chunk.size > 2
- || chunk.items[0].type != kObjectTypeString
- || (chunk.size == 2 && chunk.items[1].type != kObjectTypeString)) {
+ || chunk.items[0].type != kObjectTypeString) {
api_set_error(err, kErrorTypeValidation,
"Chunk is not an array with one or two strings");
goto free_exit;
}
String str = chunk.items[0].data.string;
- char *text = transstr(str.size > 0 ? str.data : ""); // allocates
int hl_id = 0;
if (chunk.size == 2) {
- String hl = chunk.items[1].data.string;
- if (hl.size > 0) {
- hl_id = syn_check_group((char_u *)hl.data, (int)hl.size);
+ Object hl = chunk.items[1];
+ if (hl.type == kObjectTypeArray) {
+ Array arr = hl.data.array;
+ for (size_t j = 0; j < arr.size; j++) {
+ hl_id = object_to_hl_id(arr.items[j], "virt_text highlight", err);
+ if (ERROR_SET(err)) {
+ goto free_exit;
+ }
+ if (j < arr.size-1) {
+ kv_push(virt_text, ((VirtTextChunk){ .text = NULL,
+ .hl_id = hl_id }));
+ }
+ }
+ } else {
+ hl_id = object_to_hl_id(hl, "virt_text highlight", err);
+ if (ERROR_SET(err)) {
+ goto free_exit;
+ }
}
}
+
+ char *text = transstr(str.size > 0 ? str.data : ""); // allocates
+ w += (int)mb_string2cells((char_u *)text);
+
kv_push(virt_text, ((VirtTextChunk){ .text = text, .hl_id = hl_id }));
}
+ *width = w;
return virt_text;
free_exit:
@@ -1656,7 +1675,7 @@ int object_to_hl_id(Object obj, const char *what, Error *err)
String str = obj.data.string;
return str.size ? syn_check_group((char_u *)str.data, (int)str.size) : 0;
} else if (obj.type == kObjectTypeInteger) {
- return (int)obj.data.integer;
+ return MAX((int)obj.data.integer, 0);
} else {
api_set_error(err, kErrorTypeValidation,
"%s is not a valid highlight", what);
@@ -1687,6 +1706,7 @@ HlMessage parse_hl_msg(Array chunks, Error *err)
if (chunk.size == 2) {
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((char_u *)hl.data, (int)hl.size);
attr = hl_id > 0 ? syn_id2attr(hl_id) : 0;
}
diff --git a/src/nvim/decoration.c b/src/nvim/decoration.c
index 9d969ada89..74cb9a26b7 100644
--- a/src/nvim/decoration.c
+++ b/src/nvim/decoration.c
@@ -119,7 +119,7 @@ void clear_virttext(VirtText *text)
*text = (VirtText)KV_INITIAL_VALUE;
}
-VirtText *decor_find_virttext(buf_T *buf, int row, uint64_t ns_id)
+Decoration *decor_find_virttext(buf_T *buf, int row, uint64_t ns_id)
{
MarkTreeIter itr[1] = { 0 };
marktree_itr_get(buf->b_marktree, row, 0, itr);
@@ -132,7 +132,7 @@ VirtText *decor_find_virttext(buf_T *buf, int row, uint64_t ns_id)
mark.id, false);
if (item && (ns_id == 0 || ns_id == item->ns_id)
&& item->decor && kv_size(item->decor->virt_text)) {
- return &item->decor->virt_text;
+ return item->decor;
}
marktree_itr_next(buf->b_marktree, itr);
}
@@ -218,6 +218,7 @@ bool decor_redraw_line(buf_T *buf, int row, DecorState *state)
}
state->row = row;
state->col_until = -1;
+ state->eol_col = -1;
return true; // TODO(bfredl): be more precise
}
@@ -230,10 +231,6 @@ static void decor_add(DecorState *state, int start_row, int start_col,
*decor, attr_id,
kv_size(decor->virt_text) && owned, -1 };
- if (decor->virt_text_pos == kVTEndOfLine) {
- range.win_col = -2; // handled separately
- }
-
kv_pushp(state->active);
size_t index;
for (index = kv_size(state->active)-1; index > 0; index--) {
@@ -345,29 +342,22 @@ void decor_redraw_end(DecorState *state)
state->buf = NULL;
}
-VirtText decor_redraw_eol(buf_T *buf, DecorState *state, int *eol_attr,
- bool *aligned)
+bool decor_redraw_eol(buf_T *buf, DecorState *state, int *eol_attr, int eol_col)
{
decor_redraw_col(buf, MAXCOL, MAXCOL, false, state);
- VirtText text = VIRTTEXT_EMPTY;
+ state->eol_col = eol_col;
+ bool has_virttext = false;
for (size_t i = 0; i < kv_size(state->active); i++) {
DecorRange item = kv_A(state->active, i);
if (item.start_row == state->row && kv_size(item.decor.virt_text)) {
- if (!kv_size(text) && item.decor.virt_text_pos == kVTEndOfLine) {
- text = item.decor.virt_text;
- } else if (item.decor.virt_text_pos == kVTRightAlign
- || item.decor.virt_text_pos == kVTWinCol) {
- *aligned = true;
- }
+ has_virttext = true;
}
-
if (item.decor.hl_eol && item.start_row <= state->row) {
*eol_attr = hl_combine_attr(*eol_attr, item.attr_id);
}
}
-
- return text;
+ return has_virttext;
}
void decor_add_ephemeral(int start_row, int start_col, int end_row, int end_col,
diff --git a/src/nvim/decoration.h b/src/nvim/decoration.h
index 4cebc0b731..28dabeeada 100644
--- a/src/nvim/decoration.h
+++ b/src/nvim/decoration.h
@@ -34,19 +34,20 @@ typedef enum {
struct Decoration
{
- int hl_id; // highlight group
VirtText virt_text;
+ int hl_id; // highlight group
VirtTextPos virt_text_pos;
- bool virt_text_hide;
HlMode hl_mode;
+ bool virt_text_hide;
bool hl_eol;
+ bool shared; // shared decoration, don't free
// TODO(bfredl): style, signs, etc
DecorPriority priority;
- bool shared; // shared decoration, don't free
int col; // fixed col value, like win_col
+ int virt_text_width; // width of virt_text
};
-#define DECORATION_INIT { 0, KV_INITIAL_VALUE, kVTEndOfLine, false, \
- kHlModeUnknown, false, DECOR_PRIORITY_BASE, false, 0 }
+#define DECORATION_INIT { KV_INITIAL_VALUE, 0, kVTEndOfLine, kHlModeUnknown, \
+ false, false, false, DECOR_PRIORITY_BASE, 0, 0 }
typedef struct {
int start_row;
@@ -67,6 +68,8 @@ typedef struct {
int row;
int col_until;
int current;
+
+ int eol_col;
VirtText *virt_text;
} DecorState;
diff --git a/src/nvim/eval.lua b/src/nvim/eval.lua
index 33c6fae5cf..eb20cd1bc8 100644
--- a/src/nvim/eval.lua
+++ b/src/nvim/eval.lua
@@ -136,6 +136,7 @@ return {
getchar={args={0, 1}},
getcharmod={},
getcharsearch={},
+ getcharstr={args={0, 1}},
getcmdline={},
getcmdpos={},
getcmdtype={},
diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c
index 3d7a440856..f4735b3751 100644
--- a/src/nvim/eval/funcs.c
+++ b/src/nvim/eval/funcs.c
@@ -3028,10 +3028,9 @@ static void f_getchangelist(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
}
-/*
- * "getchar()" function
- */
-static void f_getchar(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+// "getchar()" and "getcharstr()" functions
+static void getchar_common(typval_T *argvars, typval_T *rettv)
+ FUNC_ATTR_NONNULL_ALL
{
varnumber_T n;
bool error = false;
@@ -3098,6 +3097,7 @@ static void f_getchar(typval_T *argvars, typval_T *rettv, FunPtr fptr)
} else {
i += utf_char2bytes(n, temp + i);
}
+ assert(i < 10);
temp[i++] = NUL;
rettv->v_type = VAR_STRING;
rettv->vval.v_string = vim_strsave(temp);
@@ -3106,15 +3106,14 @@ static void f_getchar(typval_T *argvars, typval_T *rettv, FunPtr fptr)
int row = mouse_row;
int col = mouse_col;
int grid = mouse_grid;
- win_T *win;
linenr_T lnum;
win_T *wp;
int winnr = 1;
if (row >= 0 && col >= 0) {
- /* Find the window at the mouse coordinates and compute the
- * text position. */
- win = mouse_find_win(&grid, &row, &col);
+ // Find the window at the mouse coordinates and compute the
+ // text position.
+ win_T *const win = mouse_find_win(&grid, &row, &col);
if (win == NULL) {
return;
}
@@ -3130,6 +3129,32 @@ static void f_getchar(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
}
+// "getchar()" function
+static void f_getchar(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+{
+ getchar_common(argvars, rettv);
+}
+
+// "getcharstr()" function
+static void f_getcharstr(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+{
+ getchar_common(argvars, rettv);
+
+ if (rettv->v_type == VAR_NUMBER) {
+ char_u temp[7]; // mbyte-char: 6, NUL: 1
+ const varnumber_T n = rettv->vval.v_number;
+ int i = 0;
+
+ if (n != 0) {
+ i += utf_char2bytes(n, temp);
+ }
+ assert(i < 7);
+ temp[i++] = NUL;
+ rettv->v_type = VAR_STRING;
+ rettv->vval.v_string = vim_strsave(temp);
+ }
+}
+
/*
* "getcharmod()" function
*/
diff --git a/src/nvim/ex_session.c b/src/nvim/ex_session.c
index 67b8e7e92f..3038ed3947 100644
--- a/src/nvim/ex_session.c
+++ b/src/nvim/ex_session.c
@@ -583,22 +583,6 @@ static int makeopens(FILE *fd, char_u *dirnow)
return FAIL;
}
- // Now put the other buffers into the buffer list.
- FOR_ALL_BUFFERS(buf) {
- if (!(only_save_windows && buf->b_nwindows == 0)
- && !(buf->b_help && !(ssop_flags & SSOP_HELP))
- && buf->b_fname != NULL
- && buf->b_p_bl) {
- if (fprintf(fd, "badd +%" PRId64 " ",
- buf->b_wininfo == NULL
- ? (int64_t)1L
- : (int64_t)buf->b_wininfo->wi_fpos.lnum) < 0
- || ses_fname(fd, buf, &ssop_flags, true) == FAIL) {
- return FAIL;
- }
- }
- }
-
// the global argument list
if (ses_arglist(fd, "argglobal", &global_alist.al_ga,
!(ssop_flags & SSOP_CURDIR), &ssop_flags) == FAIL) {
@@ -813,12 +797,31 @@ static int makeopens(FILE *fd, char_u *dirnow)
return FAIL;
}
+ // Now put the remaining buffers into the buffer list.
+ // This is near the end, so that when 'hidden' is set we don't create extra
+ // buffers. If the buffer was already created with another command the
+ // ":badd" will have no effect.
+ FOR_ALL_BUFFERS(buf) {
+ if (!(only_save_windows && buf->b_nwindows == 0)
+ && !(buf->b_help && !(ssop_flags & SSOP_HELP))
+ && buf->b_fname != NULL
+ && buf->b_p_bl) {
+ if (fprintf(fd, "badd +%" PRId64 " ",
+ buf->b_wininfo == NULL
+ ? (int64_t)1L
+ : (int64_t)buf->b_wininfo->wi_fpos.lnum) < 0
+ || ses_fname(fd, buf, &ssop_flags, true) == FAIL) {
+ return FAIL;
+ }
+ }
+ }
+
//
// Wipe out an empty unnamed buffer we started in.
//
if (fprintf(fd, "%s",
"if exists('s:wipebuf') "
- "&& len(win_findbuf(s:wipebuf)) == 0"
+ "&& len(win_findbuf(s:wipebuf)) == 0 "
"&& getbufvar(s:wipebuf, '&buftype') isnot# 'terminal'\n"
" silent exe 'bwipe ' . s:wipebuf\n"
"endif\n"
diff --git a/src/nvim/extmark.c b/src/nvim/extmark.c
index 60b7b024f1..4b2dccd8a4 100644
--- a/src/nvim/extmark.c
+++ b/src/nvim/extmark.c
@@ -268,7 +268,7 @@ bool extmark_clear(buf_T *buf, uint64_t ns_id,
}
ExtmarkNs *my_ns = all_ns ? buf_ns_ref(buf, item.ns_id, false) : ns;
map_del(uint64_t, uint64_t)(my_ns->map, item.mark_id);
- map_del(uint64_t, ExtmarkItem)(buf->b_extmark_index, mark.id);
+ map_del(uint64_t, ExtmarkItem)(buf->b_extmark_index, start_id);
marktree_del_itr(buf->b_marktree, itr, false);
} else {
marktree_itr_next(buf->b_marktree, itr);
diff --git a/src/nvim/globals.h b/src/nvim/globals.h
index 13370ff47e..4012cc5897 100644
--- a/src/nvim/globals.h
+++ b/src/nvim/globals.h
@@ -524,6 +524,8 @@ EXTERN pos_T VIsual;
EXTERN int VIsual_active INIT(= false);
/// Whether Select mode is active.
EXTERN int VIsual_select INIT(= false);
+/// Restart Select mode when next cmd finished
+EXTERN int restart_VIsual_select INIT(= 0);
/// Whether to restart the selection after a Select-mode mapping or menu.
EXTERN int VIsual_reselect;
/// Type of Visual mode.
diff --git a/src/nvim/main.c b/src/nvim/main.c
index 25593134fd..252aa81825 100644
--- a/src/nvim/main.c
+++ b/src/nvim/main.c
@@ -372,11 +372,6 @@ int main(int argc, char **argv)
// If using the runtime (-u is not NONE), enable syntax & filetype plugins.
if (params.use_vimrc == NULL || !strequal(params.use_vimrc, "NONE")) {
- // Source syncolor.vim to set up default UI highlights if the user didn't
- // already enable a colorscheme
- if (!get_var_value("g:colors_name")) {
- source_runtime((char_u *)"syntax/syncolor.vim", DIP_ALL);
- }
// Does ":filetype plugin indent on".
filetype_maybe_enable();
// Sources syntax/syntax.vim, which calls `:filetype on`.
diff --git a/src/nvim/normal.c b/src/nvim/normal.c
index 4213e6f946..9185062f94 100644
--- a/src/nvim/normal.c
+++ b/src/nvim/normal.c
@@ -92,8 +92,6 @@ static linenr_T resel_VIsual_line_count; /* number of lines */
static colnr_T resel_VIsual_vcol; /* nr of cols or end col */
static int VIsual_mode_orig = NUL; /* saved Visual mode */
-static int restart_VIsual_select = 0;
-
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "normal.c.generated.h"
diff --git a/src/nvim/screen.c b/src/nvim/screen.c
index b9628385cd..aee10c06ad 100644
--- a/src/nvim/screen.c
+++ b/src/nvim/screen.c
@@ -165,7 +165,7 @@ static bool resizing = false;
#endif
#define SEARCH_HL_PRIORITY 0
-static char * provider_first_error = NULL;
+static char * provider_err = NULL;
static bool provider_invoke(NS ns_id, const char *name, LuaRef ref,
Array args, bool default_true)
@@ -187,10 +187,10 @@ static bool provider_invoke(NS ns_id, const char *name, LuaRef ref,
const char *ns_name = describe_ns(ns_id);
ELOG("error in provider %s:%s: %s", ns_name, name, err.msg);
bool verbose_errs = true; // TODO(bfredl):
- if (verbose_errs && provider_first_error == NULL) {
+ if (verbose_errs && provider_err == NULL) {
static char errbuf[IOSIZE];
snprintf(errbuf, sizeof errbuf, "%s: %s", ns_name, err.msg);
- provider_first_error = xstrdup(errbuf);
+ provider_err = xstrdup(errbuf);
}
}
@@ -2103,7 +2103,6 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow,
bool search_attr_from_match = false; // if search_attr is from :match
bool has_decor = false; // this buffer has decoration
- bool do_virttext = false; // draw virtual text for this line
int win_col_offset = 0; // offset for window columns
char_u buf_fold[FOLD_TEXT_LEN + 1]; // Hold value returned by get_foldtext
@@ -2148,8 +2147,6 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow,
row = startrow;
- char *err_text = NULL;
-
buf_T *buf = wp->w_buffer;
if (!number_only) {
@@ -2194,14 +2191,20 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow,
}
}
- if (has_decor) {
- extra_check = true;
+ if (provider_err) {
+ Decoration err_decor = DECORATION_INIT;
+ int hl_err = syn_check_group((char_u *)S_LEN("ErrorMsg"));
+ kv_push(err_decor.virt_text,
+ ((VirtTextChunk){ .text = provider_err,
+ .hl_id = hl_err }));
+ err_decor.virt_text_width = mb_string2cells((char_u *)provider_err);
+ decor_add_ephemeral(lnum-1, 0, lnum-1, 0, &err_decor);
+ provider_err = NULL;
+ has_decor = true;
}
- if (provider_first_error) {
- err_text = provider_first_error;
- provider_first_error = NULL;
- do_virttext = true;
+ if (has_decor) {
+ extra_check = true;
}
// Check for columns to display for 'colorcolumn'.
@@ -3953,19 +3956,15 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow,
if (draw_color_col)
draw_color_col = advance_color_col(VCOL_HLC, &color_cols);
- VirtText virt_text = KV_INITIAL_VALUE;
- bool has_aligned = false;
- if (err_text) {
- int hl_err = syn_check_group((char_u *)S_LEN("ErrorMsg"));
- kv_push(virt_text, ((VirtTextChunk){ .text = err_text,
- .hl_id = hl_err }));
- do_virttext = true;
- } else if (has_decor) {
- virt_text = decor_redraw_eol(wp->w_buffer, &decor_state, &line_attr,
- &has_aligned);
- if (kv_size(virt_text)) {
- do_virttext = true;
- }
+ bool has_virttext = false;
+ // Make sure alignment is the same regardless
+ // if listchars=eol:X is used or not.
+ int eol_skip = (wp->w_p_lcs_chars.eol == lcs_eol_one && eol_hl_off == 0
+ ? 1 : 0);
+
+ if (has_decor) {
+ has_virttext = decor_redraw_eol(wp->w_buffer, &decor_state, &line_attr,
+ col + eol_skip);
}
if (((wp->w_p_cuc
@@ -3974,20 +3973,10 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow,
grid->Columns * (row - startrow + 1) + v
&& lnum != wp->w_cursor.lnum)
|| draw_color_col || line_attr_lowprio || line_attr
- || diff_hlf != (hlf_T)0 || do_virttext
- || has_aligned)) {
+ || diff_hlf != (hlf_T)0 || has_virttext)) {
int rightmost_vcol = 0;
int i;
- size_t virt_pos = 0;
- LineState s = LINE_STATE("");
- int virt_attr = 0;
-
- // Make sure alignment is the same regardless
- // if listchars=eol:X is used or not.
- bool delay_virttext = wp->w_p_lcs_chars.eol == lcs_eol_one
- && eol_hl_off == 0;
-
if (wp->w_p_cuc) {
rightmost_vcol = wp->w_virtcol;
}
@@ -4013,37 +4002,15 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow,
}
int base_attr = hl_combine_attr(line_attr_lowprio, diff_attr);
- if (base_attr || line_attr || has_aligned) {
+ if (base_attr || line_attr || has_virttext) {
rightmost_vcol = INT_MAX;
}
int col_stride = wp->w_p_rl ? -1 : 1;
while (wp->w_p_rl ? col >= 0 : col < grid->Columns) {
- int cells = -1;
- if (do_virttext && !delay_virttext) {
- if (*s.p == NUL) {
- if (virt_pos < virt_text.size) {
- s.p = kv_A(virt_text, virt_pos).text;
- int hl_id = kv_A(virt_text, virt_pos).hl_id;
- virt_attr = hl_id > 0 ? syn_id2attr(hl_id) : 0;
- virt_pos++;
- } else {
- do_virttext = false;
- }
- }
- if (*s.p != NUL) {
- cells = line_putchar(&s, &linebuf_char[off], grid->Columns - col,
- false);
- }
- }
- delay_virttext = false;
-
- if (cells == -1) {
- schar_from_ascii(linebuf_char[off], ' ');
- cells = 1;
- }
- col += cells * col_stride;
+ schar_from_ascii(linebuf_char[off], ' ');
+ col += col_stride;
if (draw_color_col) {
draw_color_col = advance_color_col(VCOL_HLC, &color_cols);
}
@@ -4056,24 +4023,16 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow,
col_attr = mc_attr;
}
- if (do_virttext) {
- col_attr = hl_combine_attr(col_attr, virt_attr);
- }
-
col_attr = hl_combine_attr(col_attr, line_attr);
linebuf_attr[off] = col_attr;
- if (cells == 2) {
- linebuf_attr[off+1] = col_attr;
- }
- off += cells * col_stride;
+ off += col_stride;
- if (VCOL_HLC >= rightmost_vcol && *s.p == NUL
- && virt_pos >= virt_text.size) {
+ if (VCOL_HLC >= rightmost_vcol) {
break;
}
- vcol += cells;
+ vcol += 1;
}
}
@@ -4392,7 +4351,6 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow,
}
xfree(p_extra_free);
- xfree(err_text);
return row;
}
@@ -4400,13 +4358,17 @@ void draw_virt_text(buf_T *buf, int col_off, int *end_col, int max_col)
{
DecorState *state = &decor_state;
int right_pos = max_col;
+ bool do_eol = state->eol_col > -1;
for (size_t i = 0; i < kv_size(state->active); i++) {
DecorRange *item = &kv_A(state->active, i);
if (item->start_row == state->row && kv_size(item->decor.virt_text)) {
if (item->win_col == -1) {
if (item->decor.virt_text_pos == kVTRightAlign) {
- right_pos -= item->decor.col;
+ right_pos -= item->decor.virt_text_width;
item->win_col = right_pos;
+ } else if (item->decor.virt_text_pos == kVTEndOfLine && do_eol) {
+ item->win_col = state->eol_col;
+ state->eol_col += item->decor.virt_text_width;
} else if (item->decor.virt_text_pos == kVTWinCol) {
item->win_col = MAX(item->decor.col+col_off, 0);
}
@@ -4424,14 +4386,20 @@ void draw_virt_text(buf_T *buf, int col_off, int *end_col, int max_col)
while (col < max_col) {
if (!*s.p) {
- if (virt_pos == kv_size(vt)) {
+ if (virt_pos >= kv_size(vt)) {
+ break;
+ }
+ virt_attr = 0;
+ do {
+ s.p = kv_A(vt, virt_pos).text;
+ int hl_id = kv_A(vt, virt_pos).hl_id;
+ virt_attr = hl_combine_attr(virt_attr,
+ hl_id > 0 ? syn_id2attr(hl_id) : 0);
+ virt_pos++;
+ } while (!s.p && virt_pos < kv_size(vt));
+ if (!s.p) {
break;
}
- s.p = kv_A(vt, virt_pos).text;
- int hl_id = kv_A(vt, virt_pos).hl_id;
- virt_attr = hl_id > 0 ? syn_id2attr(hl_id) : 0;
- virt_pos++;
- continue;
}
int attr;
bool through = false;
diff --git a/src/nvim/state.c b/src/nvim/state.c
index 437cb0db47..02d63d8ab1 100644
--- a/src/nvim/state.c
+++ b/src/nvim/state.c
@@ -144,6 +144,9 @@ char *get_mode(void)
buf[0] = (char)(VIsual_mode + 's' - 'v');
} else {
buf[0] = (char)VIsual_mode;
+ if (restart_VIsual_select) {
+ buf[1] = 's';
+ }
}
} else if (State == HITRETURN || State == ASKMORE || State == SETWSIZE
|| State == CONFIRM) {
diff --git a/src/nvim/syntax.c b/src/nvim/syntax.c
index d20bc6026d..d9089eb821 100644
--- a/src/nvim/syntax.c
+++ b/src/nvim/syntax.c
@@ -3417,16 +3417,6 @@ static void syn_cmd_on(exarg_T *eap, int syncing)
}
/*
- * Handle ":syntax enable" command.
- */
-static void syn_cmd_enable(exarg_T *eap, int syncing)
-{
- set_internal_string_var("syntax_cmd", (char_u *)"enable");
- syn_cmd_onoff(eap, "syntax");
- do_unlet(S_LEN("g:syntax_cmd"), true);
-}
-
-/*
* Handle ":syntax reset" command.
* It actually resets highlighting, not syntax.
*/
@@ -3434,9 +3424,7 @@ static void syn_cmd_reset(exarg_T *eap, int syncing)
{
eap->nextcmd = check_nextcmd(eap->arg);
if (!eap->skip) {
- set_internal_string_var("syntax_cmd", (char_u *)"reset");
- do_cmdline_cmd("runtime! syntax/syncolor.vim");
- do_unlet(S_LEN("g:syntax_cmd"), true);
+ init_highlight(true, true);
}
}
@@ -3475,7 +3463,7 @@ void syn_maybe_enable(void)
exarg_T ea;
ea.arg = (char_u *)"";
ea.skip = false;
- syn_cmd_enable(&ea, false);
+ syn_cmd_on(&ea, false);
}
}
@@ -5534,7 +5522,7 @@ static struct subcommand subcommands[] =
{ "clear", syn_cmd_clear },
{ "cluster", syn_cmd_cluster },
{ "conceal", syn_cmd_conceal },
- { "enable", syn_cmd_enable },
+ { "enable", syn_cmd_on },
{ "foldlevel", syn_cmd_foldlevel },
{ "include", syn_cmd_include },
{ "iskeyword", syn_cmd_iskeyword },
@@ -6057,6 +6045,34 @@ static const char *highlight_init_both[] = {
"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",
NULL
};
@@ -6090,6 +6106,24 @@ static const char *highlight_init_light[] = {
"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
};
@@ -6123,6 +6157,24 @@ static const char *highlight_init_dark[] = {
"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
};
@@ -6398,20 +6450,6 @@ void init_highlight(bool both, bool reset)
}
}
- /*
- * If syntax highlighting is enabled load the highlighting for it.
- */
- if (get_var_value("g:syntax_on") != NULL) {
- static int recursive = 0;
-
- if (recursive >= 5) {
- EMSG(_("E679: recursive loop loading syncolor.vim"));
- } else {
- recursive++;
- (void)source_runtime((char_u *)"syntax/syncolor.vim", DIP_ALL);
- recursive--;
- }
- }
syn_init_cmdline_highlight(false, false);
}
diff --git a/src/nvim/testdir/test_functions.vim b/src/nvim/testdir/test_functions.vim
index 224ca257ab..bcf2edcc93 100644
--- a/src/nvim/testdir/test_functions.vim
+++ b/src/nvim/testdir/test_functions.vim
@@ -534,6 +534,7 @@ func Test_mode()
set complete=.
inoremap <F2> <C-R>=Save_mode()<CR>
+ xnoremap <F2> <Cmd>call Save_mode()<CR>
normal! 3G
exe "normal i\<F2>\<Esc>"
@@ -645,6 +646,14 @@ func Test_mode()
call assert_equal("\<C-S>", mode(1))
call feedkeys("\<Esc>", 'xt')
+ " v_CTRL-O
+ exe "normal gh\<C-O>\<F2>\<Esc>"
+ call assert_equal("v-vs", g:current_modes)
+ exe "normal gH\<C-O>\<F2>\<Esc>"
+ call assert_equal("V-Vs", g:current_modes)
+ exe "normal g\<C-H>\<C-O>\<F2>\<Esc>"
+ call assert_equal("\<C-V>-\<C-V>s", g:current_modes)
+
call feedkeys(":echo \<C-R>=Save_mode()\<C-U>\<CR>", 'xt')
call assert_equal('c-c', g:current_modes)
call feedkeys("gQecho \<C-R>=Save_mode()\<CR>\<CR>vi\<CR>", 'xt')
@@ -653,6 +662,7 @@ func Test_mode()
bwipe!
iunmap <F2>
+ xunmap <F2>
set complete&
endfunc
@@ -1315,7 +1325,15 @@ endfunc
func Test_getchar()
call feedkeys('a', '')
call assert_equal(char2nr('a'), getchar())
+ call assert_equal(0, getchar(0))
+ call assert_equal(0, getchar(1))
+
+ call feedkeys('a', '')
+ call assert_equal('a', getcharstr())
+ call assert_equal('', getcharstr(0))
+ call assert_equal('', getcharstr(1))
+ call setline(1, 'xxxx')
" call test_setmouse(1, 3)
" let v:mouse_win = 9
" let v:mouse_winid = 9
@@ -1328,6 +1346,7 @@ func Test_getchar()
call assert_equal(win_getid(1), v:mouse_winid)
call assert_equal(1, v:mouse_lnum)
call assert_equal(3, v:mouse_col)
+ enew!
endfunc
func Test_libcall_libcallnr()
diff --git a/src/nvim/testdir/test_mksession.vim b/src/nvim/testdir/test_mksession.vim
index 4026f2bf98..fbe764bbf2 100644
--- a/src/nvim/testdir/test_mksession.vim
+++ b/src/nvim/testdir/test_mksession.vim
@@ -287,6 +287,29 @@ func Test_mksession_blank_windows()
call delete('Xtest_mks.out')
endfunc
+func Test_mksession_buffer_count()
+ set hidden
+
+ " Edit exactly three files in the current session.
+ %bwipe!
+ e Xfoo | tabe Xbar | tabe Xbaz
+ tabdo write
+ mksession! Xtest_mks.out
+
+ " Verify that loading the session does not create additional buffers.
+ %bwipe!
+ source Xtest_mks.out
+ call assert_equal(3, len(getbufinfo()))
+
+ " Clean up.
+ call delete('Xfoo')
+ call delete('Xbar')
+ call delete('Xbaz')
+ call delete('Xtest_mks.out')
+ %bwipe!
+ set hidden&
+endfunc
+
if has('extra_search')
func Test_mksession_hlsearch()
diff --git a/test/functional/ex_cmds/mksession_spec.lua b/test/functional/ex_cmds/mksession_spec.lua
index 949724bb53..09eaa36686 100644
--- a/test/functional/ex_cmds/mksession_spec.lua
+++ b/test/functional/ex_cmds/mksession_spec.lua
@@ -43,7 +43,7 @@ describe(':mksession', function()
-- Restore session.
command('source '..session_file)
- eq({3,3,2},
+ eq({2,2,4},
{funcs.winbufnr(1), funcs.winbufnr(2), funcs.winbufnr(3)})
end)
@@ -91,7 +91,12 @@ describe(':mksession', function()
command('tabnext 1')
eq(cwd_dir .. get_pathsep() .. tmpfile_base .. '1', funcs.expand('%:p'))
command('tabnext 2')
- eq(cwd_dir .. get_pathsep() .. tmpfile_base .. '2', funcs.expand('%:p'))
+ -- :mksession stores paths using unix slashes, but Nvim doesn't adjust these
+ -- for absolute paths in all cases yet. Absolute paths are used in the
+ -- session file after :tcd, so we need to expect unix slashes here for now
+ -- eq(cwd_dir .. get_pathsep() .. tmpfile_base .. '2', funcs.expand('%:p'))
+ eq(cwd_dir:gsub([[\]], '/') .. '/' .. tmpfile_base .. '2',
+ funcs.expand('%:p'))
end)
it('restores CWD for :terminal buffers #11288', function()
diff --git a/test/functional/ui/bufhl_spec.lua b/test/functional/ui/bufhl_spec.lua
index af709cd521..16ed3b9486 100644
--- a/test/functional/ui/bufhl_spec.lua
+++ b/test/functional/ui/bufhl_spec.lua
@@ -858,8 +858,8 @@ describe('Buffer highlighting', function()
it('works with cursorline', function()
command("set cursorline")
- screen:expect([[
- {14:^1 + 2 }{15:=}{16: 3}{14: }|
+ screen:expect{grid=[[
+ {14:^1 + 2 }{3:=}{2: 3}{14: }|
3 + {11:ERROR:} invalid syntax |
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5|
, 5, 5, 5, 5, 5, 5, Lorem ipsum dolor s|
@@ -867,32 +867,32 @@ describe('Buffer highlighting', function()
{1:~ }|
{1:~ }|
|
- ]])
+ ]]}
feed('j')
- screen:expect([[
+ screen:expect{grid=[[
1 + 2 {3:=}{2: 3} |
- {14:^3 + }{11:ERROR:}{14: invalid syntax }|
+ {14:^3 + }{11:ERROR:} invalid syntax{14: }|
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5|
, 5, 5, 5, 5, 5, 5, Lorem ipsum dolor s|
x = 4 |
{1:~ }|
{1:~ }|
|
- ]])
+ ]]}
feed('j')
- screen:expect([[
+ screen:expect{grid=[[
1 + 2 {3:=}{2: 3} |
3 + {11:ERROR:} invalid syntax |
{14:^5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5}|
- {14:, 5, 5, 5, 5, 5, 5, Lorem ipsum dolor s}|
+ {14:, 5, 5, 5, 5, 5, 5, }Lorem ipsum dolor s|
x = 4 |
{1:~ }|
{1:~ }|
|
- ]])
+ ]]}
end)
it('works with color column', function()
@@ -910,11 +910,11 @@ describe('Buffer highlighting', function()
command("set colorcolumn=9")
screen:expect{grid=[[
- ^1 + 2 {3:=}{2: }{17:3} |
+ ^1 + 2 {3:=}{2: 3} |
3 + {11:ERROR:} invalid syntax |
5, 5, 5,{18: }5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5|
, 5, 5, 5, 5, 5, 5, Lorem ipsum dolor s|
- x = 4 {12:暗}{19:x}{12:事} |
+ x = 4 {12:暗x事} |
{1:~ }|
{1:~ }|
|
diff --git a/test/functional/ui/cmdline_spec.lua b/test/functional/ui/cmdline_spec.lua
index 0ea8bab957..ad23402ff9 100644
--- a/test/functional/ui/cmdline_spec.lua
+++ b/test/functional/ui/cmdline_spec.lua
@@ -14,6 +14,8 @@ local function new_screen(opt)
[3] = {bold = true, reverse = true},
[4] = {foreground = Screen.colors.Grey100, background = Screen.colors.Red},
[5] = {bold = true, foreground = Screen.colors.SeaGreen4},
+ [6] = {foreground = Screen.colors.Magenta},
+ [7] = {bold = true, foreground = Screen.colors.Brown},
})
return screen
end
@@ -267,7 +269,7 @@ local function test_cmdline(linegrid)
special = {'"', true},
}, {
firstc = "=",
- content = {{"1"}, {"+"}, {"2"}},
+ content = {{"1", 6}, {"+", 7}, {"2", 6}},
pos = 3,
}}
diff --git a/test/functional/ui/decorations_spec.lua b/test/functional/ui/decorations_spec.lua
index 98aafd8757..4373d17890 100644
--- a/test/functional/ui/decorations_spec.lua
+++ b/test/functional/ui/decorations_spec.lua
@@ -562,7 +562,7 @@ end]]
{5:l}{8:blen}{7:dy}{10:e}{7:text}{10:h}{7:-}{10:_}{7:here}ell, count = unpack(item) |
{5:i}{12:c}{11:ombining color} {13:nil} {5:then} |
{11:replacing color}d_cell |
- {5:e}{8:bl}{14:endy}{15:i}{14:text}{15:o}{14:-}{15:o}{14:h}{7:ere} |
+ {5:e}{8:bl}{7:endy}{10: }{7:text}{10: }{7:-}{10: }{7:here} |
{5:f}{12:co}{11:mbini}{16:n}{11:g color}t {5:or} {13:1}) {5:do} |
{11:replacing color} line[colpos] |
cell.text = text |
@@ -697,4 +697,96 @@ end]]
|
]]}
end)
+
+ it('can have virtual text which combines foreground and backround groups', function()
+ screen:set_default_attr_ids {
+ [1] = {bold=true, foreground=Screen.colors.Blue};
+ [2] = {background = tonumber('0x123456'), foreground = tonumber('0xbbbbbb')};
+ [3] = {background = tonumber('0x123456'), foreground = tonumber('0xcccccc')};
+ [4] = {background = tonumber('0x234567'), foreground = tonumber('0xbbbbbb')};
+ [5] = {background = tonumber('0x234567'), foreground = tonumber('0xcccccc')};
+ [6] = {bold = true, foreground = tonumber('0xcccccc'), background = tonumber('0x234567')};
+ }
+
+ exec [[
+ hi BgOne guibg=#123456
+ hi BgTwo guibg=#234567
+ hi FgEin guifg=#bbbbbb
+ hi FgZwei guifg=#cccccc
+ hi VeryBold gui=bold
+ ]]
+
+ meths.buf_set_extmark(0, ns, 0, 0, { virt_text={
+ {'a', {'BgOne', 'FgEin'}};
+ {'b', {'BgOne', 'FgZwei'}};
+ {'c', {'BgTwo', 'FgEin'}};
+ {'d', {'BgTwo', 'FgZwei'}};
+ {'X', {'BgTwo', 'FgZwei', 'VeryBold'}};
+ }})
+
+ screen:expect{grid=[[
+ ^ {2:a}{3:b}{4:c}{5:d}{6:X} |
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ |
+ ]]}
+ end)
+
+ it('does not crash when deleting a cleared buffer #15212', function()
+ exec_lua [[
+ ns = vim.api.nvim_create_namespace("myplugin")
+ vim.api.nvim_buf_set_extmark(0, ns, 0, 0, {virt_text = {{"a"}}, end_col = 0})
+ ]]
+ screen:expect{grid=[[
+ ^ a |
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ |
+ ]]}
+
+ exec_lua [[
+ vim.api.nvim_buf_clear_namespace(0, ns, 0, -1)
+ vim.cmd("bdelete")
+ ]]
+ screen:expect{grid=[[
+ ^ |
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ {1:~ }|
+ |
+ ]]}
+ helpers.assert_alive()
+ end)
end)
diff --git a/test/functional/ui/highlight_spec.lua b/test/functional/ui/highlight_spec.lua
index 8992ee27ce..7471255345 100644
--- a/test/functional/ui/highlight_spec.lua
+++ b/test/functional/ui/highlight_spec.lua
@@ -789,7 +789,7 @@ describe("'listchars' highlight", function()
[0] = {bold=true, foreground=Screen.colors.Blue},
[1] = {background=Screen.colors.Grey90},
[2] = {foreground=Screen.colors.Red},
- [3] = {foreground=Screen.colors.Green1},
+ [3] = {foreground=Screen.colors.X11Green, background=Screen.colors.Red1},
})
feed_command('highlight clear ModeMsg')
feed_command('highlight Whitespace guifg=#FF0000')
diff --git a/test/functional/ui/sign_spec.lua b/test/functional/ui/sign_spec.lua
index 06c92a4b10..741b93043d 100644
--- a/test/functional/ui/sign_spec.lua
+++ b/test/functional/ui/sign_spec.lua
@@ -176,8 +176,8 @@ describe('Signs', function()
command('sign place 5 line=3 name=pietWarn buffer=1')
command('sign place 3 line=3 name=pietError buffer=1')
screen:expect([[
- {1:>>}XX{6: 1 }a |
- XX{1:>>}{6: 2 }b |
+ {1:>>}{8:XX}{6: 1 }a |
+ {8:XX}{1:>>}{6: 2 }b |
{1:>>}WW{6: 3 }c |
{2: }{6: 4 }^ |
{0:~ }|
@@ -194,7 +194,7 @@ describe('Signs', function()
-- With the default setting, we get the sign with the top id.
command('set signcolumn=yes:1')
screen:expect([[
- XX{6: 1 }a |
+ {8:XX}{6: 1 }a |
{1:>>}{6: 2 }b |
WW{6: 3 }c |
{2: }{6: 4 }^ |
@@ -212,9 +212,9 @@ describe('Signs', function()
-- "auto:3" accommodates all the signs we defined so far.
command('set signcolumn=auto:3')
screen:expect([[
- {1:>>}XX{2: }{6: 1 }a |
- XX{1:>>}{2: }{6: 2 }b |
- XX{1:>>}WW{6: 3 }c |
+ {1:>>}{8:XX}{2: }{6: 1 }a |
+ {8:XX}{1:>>}{2: }{6: 2 }b |
+ {8:XX}{1:>>}WW{6: 3 }c |
{2: }{6: 4 }^ |
{0:~ }|
{0:~ }|
@@ -230,9 +230,9 @@ describe('Signs', function()
-- Check "yes:9".
command('set signcolumn=yes:9')
screen:expect([[
- {1:>>}XX{2: }{6: 1 }a |
- XX{1:>>}{2: }{6: 2 }b |
- XX{1:>>}WW{2: }{6: 3 }c |
+ {1:>>}{8:XX}{2: }{6: 1 }a |
+ {8:XX}{1:>>}{2: }{6: 2 }b |
+ {8:XX}{1:>>}WW{2: }{6: 3 }c |
{2: }{6: 4 }^ |
{0:~ }|
{0:~ }|
@@ -249,9 +249,9 @@ describe('Signs', function()
-- a single line (same result as "auto:3").
command('set signcolumn=auto:4')
screen:expect{grid=[[
- {1:>>}XX{2: }{6: 1 }a |
- XX{1:>>}{2: }{6: 2 }b |
- XX{1:>>}WW{6: 3 }c |
+ {1:>>}{8:XX}{2: }{6: 1 }a |
+ {8:XX}{1:>>}{2: }{6: 2 }b |
+ {8:XX}{1:>>}WW{6: 3 }c |
{2: }{6: 4 }^ |
{0:~ }|
{0:~ }|
@@ -267,8 +267,8 @@ describe('Signs', function()
-- line deletion deletes signs.
command('2d')
screen:expect([[
- {1:>>}XX{2: }{6: 1 }a |
- XX{1:>>}WW{6: 2 }^c |
+ {1:>>}{8:XX}{2: }{6: 1 }a |
+ {8:XX}{1:>>}WW{6: 2 }^c |
{2: }{6: 3 } |
{0:~ }|
{0:~ }|
diff --git a/test/unit/viml/expressions/parser_spec.lua b/test/unit/viml/expressions/parser_spec.lua
index 032baf6578..8342044b5e 100644
--- a/test/unit/viml/expressions/parser_spec.lua
+++ b/test/unit/viml/expressions/parser_spec.lua
@@ -52,6 +52,32 @@ local predefined_hl_defs = {
QuickFixLine=true,
Substitute=true,
Whitespace=true,
+ Error=true,
+ Todo=true,
+ String=true,
+ Character=true,
+ Number=true,
+ Boolean=true,
+ Float=true,
+ Function=true,
+ Conditional=true,
+ Repeat=true,
+ Label=true,
+ Operator=true,
+ Keyword=true,
+ Exception=true,
+ Include=true,
+ Define=true,
+ Macro=true,
+ PreCondit=true,
+ StorageClass=true,
+ Structure=true,
+ Typedef=true,
+ Tag=true,
+ SpecialChar=true,
+ Delimiter=true,
+ SpecialComment=true,
+ Debug=true,
-- From highlight_init_(dark|light)
ColorColumn=true,
@@ -83,8 +109,6 @@ local predefined_hl_defs = {
Visual=true,
WarningMsg=true,
Normal=true,
-
- -- From syncolor.vim, if &background
Comment=true,
Constant=true,
Special=true,
@@ -94,36 +118,6 @@ local predefined_hl_defs = {
Type=true,
Underlined=true,
Ignore=true,
-
- -- From syncolor.vim, below if &background
- Error=true,
- Todo=true,
-
- -- From syncolor.vim, links at the bottom
- String=true,
- Character=true,
- Number=true,
- Boolean=true,
- Float=true,
- Function=true,
- Conditional=true,
- Repeat=true,
- Label=true,
- Operator=true,
- Keyword=true,
- Exception=true,
- Include=true,
- Define=true,
- Macro=true,
- PreCondit=true,
- StorageClass=true,
- Structure=true,
- Typedef=true,
- Tag=true,
- SpecialChar=true,
- Delimiter=true,
- SpecialComment=true,
- Debug=true,
}
local nvim_hl_defs = {}