diff options
96 files changed, 2622 insertions, 1614 deletions
diff --git a/.github/workflows/backport.yml b/.github/workflows/backport.yml index 9fbe837106..16ed889841 100644 --- a/.github/workflows/backport.yml +++ b/.github/workflows/backport.yml @@ -14,15 +14,10 @@ jobs: - uses: actions/checkout@v4 - name: Create backport PR id: backport - uses: korthout/backport-action@v2 + uses: korthout/backport-action@v3 with: pull_title: "${pull_title}" label_pattern: "^ci:backport ([^ ]+)$" - # https://github.com/korthout/backport-action/pull/399 - experimental: > - { - "detect_merge_method": true - } - if: ${{steps.backport.outputs.was_successful == 'true'}} uses: actions/github-script@v7 diff --git a/cmake.deps/deps.txt b/cmake.deps/deps.txt index 6b72ed5b52..f76a6a1b70 100644 --- a/cmake.deps/deps.txt +++ b/cmake.deps/deps.txt @@ -4,8 +4,8 @@ LIBUV_SHA256 8c253adb0f800926a6cbd1c6576abae0bc8eb86a4f891049b72f9e5b7dc58f33 MSGPACK_URL https://github.com/msgpack/msgpack-c/archive/c-6.0.1.tar.gz MSGPACK_SHA256 58d5fe49d0ee2b374d60a61aabf8028b2c92004e6f11bff04e74b639fc8ad541 -LUAJIT_URL https://github.com/LuaJIT/LuaJIT/archive/75e92777988017fe47c5eb290998021bbf972d1f.tar.gz -LUAJIT_SHA256 0f69288190024d732c67645e40ed5b137d67aa950fedf0f44a9ad0f3dba6d5d2 +LUAJIT_URL https://github.com/LuaJIT/LuaJIT/archive/93e87998b24021b94de8d1c8db244444c46fb6e9.tar.gz +LUAJIT_SHA256 026eb4531cddff20acc72ec97378ccfc30326173c491d6c01834b48b42a80518 LUA_URL https://www.lua.org/ftp/lua-5.1.5.tar.gz LUA_SHA256 2640fc56a795f29d28ef15e13c34a47e223960b0240e8cb0a82d9b0738695333 @@ -41,16 +41,16 @@ GETTEXT_SHA256 66415634c6e8c3fa8b71362879ec7575e27da43da562c798a8a2f223e6e47f5c LIBICONV_URL https://github.com/neovim/deps/raw/b9bf36eb31f27e8136d907da38fa23518927737e/opt/libiconv-1.17.tar.gz LIBICONV_SHA256 8f74213b56238c85a50a5329f77e06198771e70dd9a739779f4c02f65d971313 -TREESITTER_C_URL https://github.com/tree-sitter/tree-sitter-c/archive/v0.21.0.tar.gz -TREESITTER_C_SHA256 6f0f5d1b71cf8ffd8a37fb638c6022fa1245bd630150b538547d52128ce0ea7e +TREESITTER_C_URL https://github.com/tree-sitter/tree-sitter-c/archive/v0.21.3.tar.gz +TREESITTER_C_SHA256 75a3780df6114cd37496761c4a7c9fd900c78bee3a2707f590d78c0ca3a24368 TREESITTER_LUA_URL https://github.com/tree-sitter-grammars/tree-sitter-lua/archive/v0.1.0.tar.gz TREESITTER_LUA_SHA256 230cfcbfa74ed1f7b8149e9a1f34c2efc4c589a71fe0f5dc8560622f8020d722 TREESITTER_VIM_URL https://github.com/neovim/tree-sitter-vim/archive/v0.4.0.tar.gz TREESITTER_VIM_SHA256 9f856f8b4a10ab43348550fa2d3cb2846ae3d8e60f45887200549c051c66f9d5 TREESITTER_VIMDOC_URL https://github.com/neovim/tree-sitter-vimdoc/archive/v2.5.1.tar.gz TREESITTER_VIMDOC_SHA256 063645096504b21603585507c41c6d8718ff3c11b2150c5bfc31e8f3ee9afea3 -TREESITTER_QUERY_URL https://github.com/tree-sitter-grammars/tree-sitter-query/archive/v0.3.0.tar.gz -TREESITTER_QUERY_SHA256 f878ff37abcb83250e31a6569e997546f3dbab74dcb26683cb2d613f7568cfc0 +TREESITTER_QUERY_URL https://github.com/tree-sitter-grammars/tree-sitter-query/archive/v0.4.0.tar.gz +TREESITTER_QUERY_SHA256 d3a423ab66dc62b2969625e280116678a8a22582b5ff087795222108db2f6a6e TREESITTER_PYTHON_URL https://github.com/tree-sitter/tree-sitter-python/archive/v0.21.0.tar.gz TREESITTER_PYTHON_SHA256 720304a603271fa89e4430a14d6a81a023d6d7d1171b1533e49c0ab44f1e1c13 TREESITTER_BASH_URL https://github.com/tree-sitter/tree-sitter-bash/archive/v0.21.0.tar.gz diff --git a/runtime/autoload/hare.vim b/runtime/autoload/hare.vim new file mode 100644 index 0000000000..c4581fccf9 --- /dev/null +++ b/runtime/autoload/hare.vim @@ -0,0 +1,26 @@ +" Vim autoload file. +" Language: Hare +" Maintainer: Amelia Clarke <selene@perilune.dev> +" Last Updated: 2024-05-10 +" Upstream: https://git.sr.ht/~sircmpwn/hare.vim + +" Attempt to find the directory for a given Hare module. +function hare#FindModule(str) + let path = substitute(trim(a:str, ':', 2), '::', '/', 'g') + let dir = finddir(path) + while !empty(path) && empty(dir) + let path = substitute(path, '/\?\h\w*$', '', '') + let dir = finddir(path) + endwhile + return dir +endfunction + +" Return the value of HAREPATH if it exists. Otherwise use a reasonable default. +function hare#GetPath() + if empty($HAREPATH) + return '/usr/src/hare/stdlib,/usr/src/hare/third-party' + endif + return substitute($HAREPATH, ':', ',', 'g') +endfunction + +" vim: et sts=2 sw=2 ts=8 diff --git a/runtime/compiler/hare.vim b/runtime/compiler/hare.vim index c98bbb9c63..33edb3a281 100644 --- a/runtime/compiler/hare.vim +++ b/runtime/compiler/hare.vim @@ -1,28 +1,29 @@ -" Vim compiler file -" Compiler: Hare Compiler -" Maintainer: Amelia Clarke <me@rsaihe.dev> -" Last Change: 2022-09-21 -" 2024 Apr 05 by The Vim Project (removed :CompilerSet definition) +" Vim compiler file. +" Compiler: Hare +" Maintainer: Amelia Clarke <selene@perilune.dev> +" Last Change: 2024-05-23 +" Upstream: https://git.sr.ht/~sircmpwn/hare.vim -if exists("g:current_compiler") +if exists('current_compiler') finish endif -let g:current_compiler = "hare" +let current_compiler = 'hare' let s:cpo_save = &cpo set cpo&vim -if filereadable("Makefile") || filereadable("makefile") +if filereadable('Makefile') || filereadable('makefile') CompilerSet makeprg=make else CompilerSet makeprg=hare\ build endif CompilerSet errorformat= - \Error\ %f:%l:%c:\ %m, - \Syntax\ error:\ %.%#\ at\ %f:%l:%c\\,\ %m, + \%f:%l:%c:\ syntax\ error:\ %m, + \%f:%l:%c:\ error:\ %m, \%-G%.%# let &cpo = s:cpo_save unlet s:cpo_save -" vim: tabstop=2 shiftwidth=2 expandtab + +" vim: et sts=2 sw=2 ts=8 diff --git a/runtime/doc/api.txt b/runtime/doc/api.txt index 2aa147770d..38960e1bc2 100644 --- a/runtime/doc/api.txt +++ b/runtime/doc/api.txt @@ -3259,13 +3259,15 @@ nvim_open_win({buffer}, {enter}, {config}) *nvim_open_win()* < • title: Title (optional) in window border, string or list. List should consist of `[text, highlight]` tuples. If - string, the default highlight group is `FloatTitle`. + string, or a tuple lacks a highlight, the default + highlight group is `FloatTitle`. • title_pos: Title position. Must be set with `title` option. Value can be one of "left", "center", or "right". Default is `"left"`. • footer: Footer (optional) in window border, string or list. List should consist of `[text, highlight]` tuples. - If string, the default highlight group is `FloatFooter`. + If string, or a tuple lacks a highlight, the default + highlight group is `FloatFooter`. • footer_pos: Footer position. Must be set with `footer` option. Value can be one of "left", "center", or "right". Default is `"left"`. diff --git a/runtime/doc/builtin.txt b/runtime/doc/builtin.txt index ff7d5f9ce8..1a762c6ec0 100644 --- a/runtime/doc/builtin.txt +++ b/runtime/doc/builtin.txt @@ -2930,14 +2930,14 @@ getregion({pos1}, {pos2} [, {opts}]) *getregion()* The optional argument {opts} is a Dict and supports the following items: - type Specify the region's selection type - (default: "v"): - "v" for |charwise| mode - "V" for |linewise| mode - "<CTRL-V>" for |blockwise-visual| mode + type Specify the region's selection type. + See |getregtype()| for possible values, + except that the width can be omitted + and an empty string cannot be used. + (default: "v") exclusive If |TRUE|, use exclusive selection - for the end position + for the end position. (default: follow 'selection') You can get the last selection type by |visualmode()|. diff --git a/runtime/doc/deprecated.txt b/runtime/doc/deprecated.txt index 646ba72bd8..6c6585d76e 100644 --- a/runtime/doc/deprecated.txt +++ b/runtime/doc/deprecated.txt @@ -19,6 +19,22 @@ API - nvim_subscribe() Plugins must maintain their own "multicast" channels list. - nvim_unsubscribe() Plugins must maintain their own "multicast" channels list. +LUA +- vim.region() Use |getregionpos()| instead. + +DIAGNOSTICS +- *vim.diagnostic.goto_next()* Use |vim.diagnostic.jump()| with `{count = 1}` instead. +- *vim.diagnostic.goto_prev()* Use |vim.diagnostic.jump()| with `{count = -1}` instead. +- *vim.diagnostic.get_next_pos()* + Use the "lnum" and "col" fields from the return value of + |vim.diagnostic.get_next()| instead. +- *vim.diagnostic.get_prev_pos()* + Use the "lnum" and "col" fields from the return value of + |vim.diagnostic.get_prev()| instead. +- The "win_id" parameter used by various functions is deprecated in favor of + "winid" |winid| +- The "cursor_position" parameter of |vim.diagnostic.JumpOpts| is renamed to + "pos" ------------------------------------------------------------------------------ DEPRECATED IN 0.10 *deprecated-0.10* @@ -202,9 +218,6 @@ internally and are no longer exposed as part of the API. Instead, use - *vim.lsp.diagnostic.set_underline()* - *vim.lsp.diagnostic.set_virtual_text()* -Configuring |diagnostic-signs| with |:sign-define| or |sign_define()| is no -longer supported. Use the "signs" key of |vim.diagnostic.config()| instead. - LSP FUNCTIONS - *vim.lsp.buf.server_ready()* Use |LspAttach| instead, depending on your use-case. "Server ready" is not diff --git a/runtime/doc/diagnostic.txt b/runtime/doc/diagnostic.txt index 36616b9a0d..be9e54d6cd 100644 --- a/runtime/doc/diagnostic.txt +++ b/runtime/doc/diagnostic.txt @@ -378,28 +378,37 @@ Lua module: vim.diagnostic *diagnostic-api* • {severity}? (`vim.diagnostic.SeverityFilter`) See |diagnostic-severity|. -*vim.diagnostic.GotoOpts* +*vim.diagnostic.JumpOpts* Extends: |vim.diagnostic.GetOpts| Configuration table with the following keys: Fields: ~ - • {cursor_position}? (`{[1]:integer,[2]:integer}`, default: current cursor position) - Cursor position as a `(row, col)` tuple. See - |nvim_win_get_cursor()|. - • {wrap}? (`boolean`, default: `true`) Whether to loop - around file or not. Similar to 'wrapscan'. - • {severity}? (`vim.diagnostic.SeverityFilter`) See - |diagnostic-severity|. - • {float}? (`boolean|vim.diagnostic.Opts.Float`, default: - `true`) If `true`, call - |vim.diagnostic.open_float()| after moving. If a - table, pass the table as the {opts} parameter to - |vim.diagnostic.open_float()|. Unless overridden, - the float will show diagnostics at the new cursor - position (as if "cursor" were passed to the - "scope" option). - • {win_id}? (`integer`, default: `0`) Window ID + • {diagnostic}? (`vim.Diagnostic`) The diagnostic to jump to. Mutually + exclusive with {count}, {namespace}, and {severity}. + See |vim.Diagnostic|. + • {count}? (`integer`) The number of diagnostics to move by, + starting from {pos}. A positive integer moves forward + by {count} diagnostics, while a negative integer moves + backward by {count} diagnostics. Mutually exclusive + with {diagnostic}. + • {pos}? (`{[1]:integer,[2]:integer}`) Cursor position as a + `(row, col)` tuple. See |nvim_win_get_cursor()|. Used + to find the nearest diagnostic when {count} is used. + Only used when {count} is non-nil. Default is the + current cursor position. + • {wrap}? (`boolean`, default: `true`) Whether to loop around + file or not. Similar to 'wrapscan'. + • {severity}? (`vim.diagnostic.SeverityFilter`) See + |diagnostic-severity|. + • {float}? (`boolean|vim.diagnostic.Opts.Float`, default: `true`) + If `true`, call |vim.diagnostic.open_float()| after + moving. If a table, pass the table as the {opts} + parameter to |vim.diagnostic.open_float()|. Unless + overridden, the float will show diagnostics at the new + cursor position (as if "cursor" were passed to the + "scope" option). + • {winid}? (`integer`, default: `0`) Window ID *vim.diagnostic.NS* @@ -678,52 +687,20 @@ get_next({opts}) *vim.diagnostic.get_next()* Get the next diagnostic closest to the cursor position. Parameters: ~ - • {opts} (`vim.diagnostic.GotoOpts?`) See |vim.diagnostic.GotoOpts|. + • {opts} (`vim.diagnostic.JumpOpts?`) See |vim.diagnostic.JumpOpts|. Return: ~ (`vim.Diagnostic?`) Next diagnostic. See |vim.Diagnostic|. -get_next_pos({opts}) *vim.diagnostic.get_next_pos()* - Return the position of the next diagnostic in the current buffer. - - Parameters: ~ - • {opts} (`vim.diagnostic.GotoOpts?`) See |vim.diagnostic.GotoOpts|. - - Return: ~ - (`table|false`) Next diagnostic position as a `(row, col)` tuple or - false if no next diagnostic. - get_prev({opts}) *vim.diagnostic.get_prev()* Get the previous diagnostic closest to the cursor position. Parameters: ~ - • {opts} (`vim.diagnostic.GotoOpts?`) See |vim.diagnostic.GotoOpts|. + • {opts} (`vim.diagnostic.JumpOpts?`) See |vim.diagnostic.JumpOpts|. Return: ~ (`vim.Diagnostic?`) Previous diagnostic. See |vim.Diagnostic|. -get_prev_pos({opts}) *vim.diagnostic.get_prev_pos()* - Return the position of the previous diagnostic in the current buffer. - - Parameters: ~ - • {opts} (`vim.diagnostic.GotoOpts?`) See |vim.diagnostic.GotoOpts|. - - Return: ~ - (`table|false`) Previous diagnostic position as a `(row, col)` tuple - or `false` if there is no prior diagnostic. - -goto_next({opts}) *vim.diagnostic.goto_next()* - Move to the next diagnostic. - - Parameters: ~ - • {opts} (`vim.diagnostic.GotoOpts?`) See |vim.diagnostic.GotoOpts|. - -goto_prev({opts}) *vim.diagnostic.goto_prev()* - Move to the previous diagnostic in the current buffer. - - Parameters: ~ - • {opts} (`vim.diagnostic.GotoOpts?`) See |vim.diagnostic.GotoOpts|. - hide({namespace}, {bufnr}) *vim.diagnostic.hide()* Hide currently displayed diagnostics. @@ -753,6 +730,16 @@ is_enabled({filter}) *vim.diagnostic.is_enabled()* Return: ~ (`boolean`) +jump({opts}) *vim.diagnostic.jump()* + Move to a diagnostic. + + Parameters: ~ + • {opts} (`vim.diagnostic.JumpOpts`) See |vim.diagnostic.JumpOpts|. + + Return: ~ + (`vim.Diagnostic?`) The diagnostic that was moved to. See + |vim.Diagnostic|. + *vim.diagnostic.match()* match({str}, {pat}, {groups}, {severity_map}, {defaults}) Parse a diagnostic from a string. @@ -792,7 +779,7 @@ open_float({opts}) *vim.diagnostic.open_float()* Return (multiple): ~ (`integer?`) float_bufnr - (`integer?`) win_id + (`integer?`) winid reset({namespace}, {bufnr}) *vim.diagnostic.reset()* Remove all diagnostics from the given namespace. diff --git a/runtime/doc/filetype.txt b/runtime/doc/filetype.txt index 5eae78744c..eddf14014a 100644 --- a/runtime/doc/filetype.txt +++ b/runtime/doc/filetype.txt @@ -602,6 +602,12 @@ The mapping can be disabled with: > let g:no_gprof_maps = 1 +HARE *ft-hare* + +Since the text for this plugin is rather long it has been put in a separate +file: |ft_hare.txt|. + + JAVA *ft-java-plugin* Whenever the variable "g:ftplugin_java_source_path" is defined and its value diff --git a/runtime/doc/ft_hare.txt b/runtime/doc/ft_hare.txt new file mode 100644 index 0000000000..937c5e0961 --- /dev/null +++ b/runtime/doc/ft_hare.txt @@ -0,0 +1,77 @@ +*ft_hare.txt* Support for the Hare programming language + +============================================================================== +CONTENTS *hare* + +1. Introduction |hare-intro| +2. Filetype plugin |hare-plugin| +3. Settings |hare-settings| + +============================================================================== +INTRODUCTION *hare-intro* + +This plugin provides syntax highlighting, indentation, and other functionality +for the Hare programming language. Support is also provided for README files +inside Hare modules, but this must be enabled by setting |g:filetype_haredoc|. + +============================================================================== +FILETYPE PLUGIN *hare-plugin* + +This plugin automatically sets the value of 'path' to include the contents of +the HAREPATH environment variable, allowing commands such as |gf| to directly +open standard library or third-party modules. If HAREPATH is not set, it +defaults to the recommended paths for most Unix-like filesystems, namely +/usr/src/hare/stdlib and /usr/src/hare/third-party. + +============================================================================== +SETTINGS *hare-settings* + +This plugin provides a small number of variables that you can define in your +vimrc to configure its behavior. + + *g:filetype_haredoc* +This plugin is able to automatically detect Hare modules and set the "haredoc" +filetype for any README files. As the recursive directory search used as a +heuristic has a minor performance impact, this feature is disabled by default +and must be specifically opted into: > + let g:filetype_haredoc = 1 +< +See |g:haredoc_search_depth| for ways to tweak the searching behavior. + + *g:hare_recommended_style* +The following options are set by default, in accordance with the official Hare +style guide: > + setlocal noexpandtab + setlocal shiftwidth=0 + setlocal softtabstop=0 + setlocal tabstop=8 + setlocal textwidth=80 +< +To disable this behavior: > + let g:hare_recommended_style = 0 +< + *g:hare_space_error* +By default, trailing whitespace and tabs preceded by space characters are +highlighted as errors. This is automatically turned off when in insert mode. +To disable this highlighting completely: > + let g:hare_space_error = 0 +< + *g:haredoc_search_depth* +By default, when |g:filetype_haredoc| is enabled, only the current directory +and its immediate subdirectories are searched for Hare files. The maximum +search depth may be adjusted with: > + let g:haredoc_search_depth = 2 +< + Value Effect~ + 0 Only search the current directory. + 1 Search the current directory and immediate + subdirectories. + 2 Search the current directory and two levels of + subdirectories. + +The maximum search depth can be set to any integer, but using values higher +than 2 is not recommended, and will likely provide no tangible benefit in most +situations. + +============================================================================== + vim:tw=78:ts=8:noet:ft=help:norl: diff --git a/runtime/doc/lsp.txt b/runtime/doc/lsp.txt index 0e165e6f54..a78a16968f 100644 --- a/runtime/doc/lsp.txt +++ b/runtime/doc/lsp.txt @@ -996,7 +996,7 @@ Lua module: vim.lsp.client *lsp-client* if the client supports workspace folders. It can be `null` if the client supports workspace folders but none are configured. - • {root_dir} (`string`) + • {root_dir} (`string?`) • {attached_buffers} (`table<integer,true>`) • {commands} (`table<string,fun(command: lsp.Command, ctx: table)>`) Table of command name to function which is diff --git a/runtime/doc/lua.txt b/runtime/doc/lua.txt index 3d8453c5a2..36d6e0d41e 100644 --- a/runtime/doc/lua.txt +++ b/runtime/doc/lua.txt @@ -646,8 +646,8 @@ vim.highlight.range({bufnr}, {ns}, {higroup}, {start}, {finish}, {opts}) • {finish} (`integer[]|string`) End of region as a (line, column) tuple or string accepted by |getpos()| • {opts} (`table?`) A table with the following fields: - • {regtype}? (`string`, default: `'charwise'`) Type of - range. See |setreg()| + • {regtype}? (`string`, default: `'v'` i.e. charwise) Type + of range. See |getregtype()| • {inclusive}? (`boolean`, default: `false`) Indicates whether the range is end-inclusive • {priority}? (`integer`, default: @@ -1708,30 +1708,6 @@ vim.print({...}) *vim.print()* • |vim.inspect()| • |:=| - *vim.region()* -vim.region({bufnr}, {pos1}, {pos2}, {regtype}, {inclusive}) - Gets a dict of line segment ("chunk") positions for the region from `pos1` - to `pos2`. - - Input and output positions are byte positions, (0,0)-indexed. "End of - line" column position (for example, |linewise| visual selection) is - returned as |v:maxcol| (big number). - - Parameters: ~ - • {bufnr} (`integer`) Buffer number, or 0 for current buffer - • {pos1} (`integer[]|string`) Start of region as a (line, column) - tuple or |getpos()|-compatible string - • {pos2} (`integer[]|string`) End of region as a (line, column) - tuple or |getpos()|-compatible string - • {regtype} (`string`) |setreg()|-style selection type - • {inclusive} (`boolean`) Controls whether the ending column is - inclusive (see also 'selection'). - - Return: ~ - (`table`) region Dict of the form `{linenr = {startcol,endcol}}`. - `endcol` is exclusive, and whole lines are returned as - `{startcol,endcol} = {0,-1}`. - vim.schedule_wrap({fn}) *vim.schedule_wrap()* Returns a function which calls {fn} via |vim.schedule()|. @@ -2366,7 +2342,26 @@ vim.trim({s}) *vim.trim()* • https://www.lua.org/pil/20.2.html vim.validate({opt}) *vim.validate()* - Validates a parameter specification (types and values). Specs are + Validate function arguments. + + This function has two valid forms: + 1. vim.validate(name: str, value: any, type: string, optional?: bool) + 2. vim.validate(spec: table) + + Form 1 validates that argument {name} with value {value} has the type + {type}. {type} must be a value returned by |lua-type()|. If {optional} is + true, then {value} may be null. This form is significantly faster and + should be preferred for simple cases. + + Example: >lua + function vim.startswith(s, prefix) + vim.validate('s', s, 'string') + vim.validate('prefix', prefix, 'string') + ... + end +< + + Form 2 validates a parameter specification (types and values). Specs are evaluated in alphanumeric order, until the first failure. Usage example: >lua diff --git a/runtime/doc/news-0.10.txt b/runtime/doc/news-0.10.txt index 8a0e7e92e7..d611eee242 100644 --- a/runtime/doc/news-0.10.txt +++ b/runtime/doc/news-0.10.txt @@ -307,7 +307,7 @@ The following new features were added. a predicate function that is checked for each value. (Use |vim.list_contains()| for checking list-like tables (integer keys without gaps) for literal values.) - • |vim.region()| can use a string accepted by |getpos()| as position. + • vim.region() can use a string accepted by |getpos()| as position. • Options: • 'winfixbuf' keeps a window focused onto a specific buffer diff --git a/runtime/doc/news.txt b/runtime/doc/news.txt index f1b402c92e..b5ba2921e6 100644 --- a/runtime/doc/news.txt +++ b/runtime/doc/news.txt @@ -93,7 +93,9 @@ DEFAULTS EDITOR -• TODO +* On Windows, filename arguments on the command-line prefixed with "~\" or + "~/" are now expanded to the user's profile directory, not a relative path + to a literal "~" directory. EVENTS diff --git a/runtime/doc/syntax.txt b/runtime/doc/syntax.txt index 7893822a66..06d7ad8f7e 100644 --- a/runtime/doc/syntax.txt +++ b/runtime/doc/syntax.txt @@ -3289,6 +3289,19 @@ set "tf_minlines" to the value you desire. Example: > :let tf_minlines = your choice < +TYPESCRIPT *typescript.vim* *ft-typescript-syntax* + *typescriptreact.vim* *ft-typescriptreact-syntax* + +There is one option to control the TypeScript syntax highlighting. + + *g:typescript_host_keyword* +When this variable is set to 1, host-specific APIs such as `addEventListener` +are highlighted. To disable set it to zero in your .vimrc: > + + let g:typescript_host_keyword = 0 +< +The default value is 1. + VIM *vim.vim* *ft-vim-syntax* *g:vimsyn_minlines* *g:vimsyn_maxlines* There is a trade-off between more accurate syntax highlighting versus screen diff --git a/runtime/ftplugin/cpp.vim b/runtime/ftplugin/cpp.vim index d4931a2533..5cdad8fdc8 100644 --- a/runtime/ftplugin/cpp.vim +++ b/runtime/ftplugin/cpp.vim @@ -10,7 +10,8 @@ if exists("b:did_ftplugin") endif " Behaves mostly just like C -runtime! ftplugin/c.{vim,lua} ftplugin/c_*.{vim,lua} ftplugin/c/*.{vim,lua} +" XXX: "[.]" in the first pattern makes it a wildcard on Windows +runtime! ftplugin/c[.]{vim,lua} ftplugin/c_*.{vim,lua} ftplugin/c/*.{vim,lua} " C++ uses templates with <things> " Disabled, because it gives an error for typing an unmatched ">". diff --git a/runtime/ftplugin/deb822sources.vim b/runtime/ftplugin/deb822sources.vim index 4936f42bf9..31c81b1a5d 100644 --- a/runtime/ftplugin/deb822sources.vim +++ b/runtime/ftplugin/deb822sources.vim @@ -1,6 +1,6 @@ " Language: Debian sources.list " Maintainer: Debian Vim Maintainers <team+vim@tracker.debian.org> -" Last Change: 2024 Mar 20 +" Last Change: 2024 May 25 " License: Vim License " URL: https://salsa.debian.org/vim-team/vim-debian/blob/main/ftplugin/deb822sources.vim @@ -10,7 +10,7 @@ endif let b:did_ftplugin=1 setlocal comments=:# -setlocal commentstring=#%s +setlocal commentstring=#\ %s setlocal formatoptions-=t let b:undo_ftplugin = 'setlocal comments< commentstring< formatoptions<' diff --git a/runtime/ftplugin/debcontrol.vim b/runtime/ftplugin/debcontrol.vim index bb710e597c..5b8292ba6e 100644 --- a/runtime/ftplugin/debcontrol.vim +++ b/runtime/ftplugin/debcontrol.vim @@ -2,7 +2,7 @@ " Language: Debian control files " Maintainer: Debian Vim Maintainers " Former Maintainer: Pierre Habouzit <madcoder@debian.org> -" Last Change: 2023 Jan 16 +" Last Change: 2024 May 25 " URL: https://salsa.debian.org/vim-team/vim-debian/blob/main/ftplugin/debcontrol.vim " Do these settings once per buffer @@ -19,8 +19,11 @@ if exists('g:debcontrol_fold_enable') endif setlocal textwidth=0 +setlocal comments=:# +setlocal commentstring=#\ %s + " Clean unloading -let b:undo_ftplugin = 'setlocal tw< foldmethod< foldexpr< foldtext<' +let b:undo_ftplugin = 'setlocal tw< foldmethod< foldexpr< foldtext< comments< commentstring<' " }}}1 diff --git a/runtime/ftplugin/debsources.vim b/runtime/ftplugin/debsources.vim index cbb4fafd22..2c5ea3599f 100644 --- a/runtime/ftplugin/debsources.vim +++ b/runtime/ftplugin/debsources.vim @@ -1,6 +1,6 @@ " Language: Debian sources.list " Maintainer: Debian Vim Maintainers <team+vim@tracker.debian.org> -" Last Change: 2023 Aug 30 +" Last Change: 2024 May 25 " License: Vim License " URL: https://salsa.debian.org/vim-team/vim-debian/blob/main/ftplugin/debsources.vim @@ -10,7 +10,7 @@ endif let b:did_ftplugin=1 setlocal comments=:# -setlocal commentstring=#%s +setlocal commentstring=#\ %s setlocal formatoptions-=t let b:undo_ftplugin = 'setlocal comments< commentstring< formatoptions<' diff --git a/runtime/ftplugin/hare.vim b/runtime/ftplugin/hare.vim index 0200ba5913..422bb7b4e8 100644 --- a/runtime/ftplugin/hare.vim +++ b/runtime/ftplugin/hare.vim @@ -1,35 +1,59 @@ -" Vim filetype plugin -" Language: Hare -" Maintainer: Amelia Clarke <me@rsaihe.dev> -" Previous Maintainer: Drew DeVault <sir@cmpwn.com> -" Last Updated: 2022-09-28 -" 2023 Aug 28 by Vim Project (undo_ftplugin) +" Vim filetype plugin. +" Language: Hare +" Maintainer: Amelia Clarke <selene@perilune.dev> +" Last Updated: 2024-05-10 +" Upstream: https://git.sr.ht/~sircmpwn/hare.vim if exists('b:did_ftplugin') finish endif let b:did_ftplugin = 1 -" Formatting settings. -setlocal formatoptions-=t formatoptions+=croql/ +let s:cpo_save = &cpo +set cpo&vim + +" Set the default compiler. +compiler hare -" Miscellaneous. +" Formatting settings. setlocal comments=:// setlocal commentstring=//\ %s +setlocal formatlistpat=^\ \\?-\ +setlocal formatoptions+=croqnlj/ formatoptions-=t + +" Search for Hare modules. +setlocal include=^\\s*use\\> +setlocal includeexpr=hare#FindModule(v:fname) +setlocal isfname+=: setlocal suffixesadd=.ha -let b:undo_ftplugin = "setl cms< com< fo< sua<" +" Add HAREPATH to the default search paths. +setlocal path-=/usr/include,, +let &l:path .= ',' .. hare#GetPath() .. ',,' -" Hare recommended style. -if get(g:, "hare_recommended_style", 1) +let b:undo_ftplugin = 'setl cms< com< flp< fo< inc< inex< isf< pa< sua< mp<' + +" Follow the Hare style guide by default. +if get(g:, 'hare_recommended_style', 1) setlocal noexpandtab - setlocal shiftwidth=8 + setlocal shiftwidth=0 setlocal softtabstop=0 setlocal tabstop=8 setlocal textwidth=80 - let b:undo_ftplugin ..= " | setl et< sts< sw< ts< tw<" + let b:undo_ftplugin .= ' et< sts< sw< ts< tw<' endif -compiler hare +augroup hare.vim + autocmd! + + " Highlight whitespace errors by default. + if get(g:, 'hare_space_error', 1) + autocmd InsertEnter * hi link hareSpaceError NONE + autocmd InsertLeave * hi link hareSpaceError Error + endif +augroup END + +let &cpo = s:cpo_save +unlet s:cpo_save -" vim: et sw=2 sts=2 ts=8 +" vim: et sts=2 sw=2 ts=8 diff --git a/runtime/ftplugin/haredoc.vim b/runtime/ftplugin/haredoc.vim new file mode 100644 index 0000000000..69030b47ba --- /dev/null +++ b/runtime/ftplugin/haredoc.vim @@ -0,0 +1,44 @@ +" Vim filetype plugin. +" Language: Haredoc (Hare documentation format) +" Maintainer: Amelia Clarke <selene@perilune.dev> +" Last Updated: 2024-05-02 +" Upstream: https://git.sr.ht/~selene/hare.vim + +if exists('b:did_ftplugin') + finish +endif +let b:did_ftplugin = 1 + +let s:cpo_save = &cpo +set cpo&vim + +" Formatting settings. +setlocal comments=:\ +setlocal formatlistpat=^\ \\?-\ +setlocal formatoptions+=tnlj formatoptions-=c formatoptions-=q + +" Search for Hare modules. +setlocal includeexpr=hare#FindModule(v:fname) +setlocal isfname+=: +setlocal suffixesadd=.ha + +" Add HAREPATH to the default search paths. +setlocal path-=/usr/include,, +let &l:path .= ',' .. hare#GetPath() .. ',,' + +let b:undo_ftplugin = 'setl com< flp< fo< inex< isf< pa< sua<' + +" Follow the Hare style guide by default. +if get(g:, 'hare_recommended_style', 1) + setlocal noexpandtab + setlocal shiftwidth=0 + setlocal softtabstop=0 + setlocal tabstop=8 + setlocal textwidth=80 + let b:undo_ftplugin .= ' et< sts< sw< ts< tw<' +endif + +let &cpo = s:cpo_save +unlet s:cpo_save + +" vim: et sts=2 sw=2 ts=8 diff --git a/runtime/indent/asm.vim b/runtime/indent/asm.vim deleted file mode 100644 index 054612b9d6..0000000000 --- a/runtime/indent/asm.vim +++ /dev/null @@ -1,29 +0,0 @@ -" Vim indent file -" Language: asm -" Maintainer: Philip Jones <philj56@gmail.com> -" Upstream: https://github.com/philj56/vim-asm-indent -" Last Change: 2017-Jul-01 -" 2024 Apr 25 by Vim Project (undo_indent) - -if exists("b:did_indent") - finish -endif -let b:did_indent = 1 - -setlocal indentexpr=s:getAsmIndent() -setlocal indentkeys=<:>,!^F,o,O - -let b:undo_indent = "setlocal indentexpr< indentkeys<" - -function! s:getAsmIndent() - let line = getline(v:lnum) - let ind = shiftwidth() - - " If the line is a label (starts with ':' terminated keyword), - " then don't indent - if line =~ '^\s*\k\+:' - let ind = 0 - endif - - return ind -endfunction diff --git a/runtime/indent/hare.vim b/runtime/indent/hare.vim index 0a9d8dafd8..1b51d1e80a 100644 --- a/runtime/indent/hare.vim +++ b/runtime/indent/hare.vim @@ -1,19 +1,16 @@ " Vim indent file -" Language: Hare -" Maintainer: Amelia Clarke <me@rsaihe.dev> -" Last Change: 2022 Sep 22 -" 2023 Aug 28 by Vim Project (undo_indent) +" Language: Hare +" Maintainer: Amelia Clarke <selene@perilune.dev> +" Last Change: 2024-04-14 +" Upstream: https://git.sr.ht/~sircmpwn/hare.vim -if exists("b:did_indent") +if exists('b:did_indent') finish endif let b:did_indent = 1 -if !has("cindent") || !has("eval") - finish -endif - -setlocal cindent +let s:cpo_save = &cpo +set cpo&vim " L0 -> don't deindent labels " (s -> use one indent after a trailing ( @@ -41,7 +38,11 @@ setlocal cinwords=if,else,for,switch,match setlocal indentexpr=GetHareIndent() -let b:undo_indent = "setl cin< cino< cinw< inde< indk<" +let b:undo_indent = 'setl cino< cinw< inde< indk<' + +if exists('*GetHareIndent()') + finish +endif function! FloorCindent(lnum) return cindent(a:lnum) / shiftwidth() * shiftwidth() @@ -122,7 +123,8 @@ function! GetHareIndent() " Indent the body of a case. " If the previous line ended in a semicolon and the line before that was a " case, don't do any special indenting. - if prevline =~# '\v;\s*(//.*)?$' && prevprevline =~# '\v\=\>\s*(//.*)?$' && line !~# '\v^\s*}' + if prevline =~# '\v;\s*(//.*)?$' && prevprevline =~# '\v\=\>\s*(//.*)?$' + \ && line !~# '\v^\s*}' return indent(prevlnum) endif @@ -138,4 +140,7 @@ function! GetHareIndent() return l:indent endfunction -" vim: tabstop=2 shiftwidth=2 expandtab +let &cpo = s:cpo_save +unlet s:cpo_save + +" vim: et sw=2 sts=2 ts=8 diff --git a/runtime/lua/tohtml.lua b/runtime/lua/tohtml.lua index 505de720ba..120247ed4e 100644 --- a/runtime/lua/tohtml.lua +++ b/runtime/lua/tohtml.lua @@ -57,6 +57,24 @@ --- @field [3] any[][] virt_text --- @field [4] any[][] overlay_text +--- @type string[] +local notifications = {} + +---@param msg string +local function notify(msg) + if #notifications == 0 then + vim.schedule(function() + if #notifications > 1 then + vim.notify(('TOhtml: %s (+ %d more warnings)'):format(notifications[1], #notifications - 1)) + elseif #notifications == 1 then + vim.notify('TOhtml: ' .. notifications[1]) + end + notifications = {} + end) + end + table.insert(notifications, msg) +end + local HIDE_ID = -1 -- stylua: ignore start local cterm_8_to_hex={ @@ -168,6 +186,8 @@ local background_color_cache = nil --- @type string? local foreground_color_cache = nil +local len = vim.api.nvim_strwidth + --- @see https://invisible-island.net/xterm/ctlseqs/ctlseqs.html#h3-Operating-System-Commands --- @param color "background"|"foreground"|integer --- @return string? @@ -215,7 +235,7 @@ local function cterm_to_hex(colorstr) if hex then cterm_color_cache[color] = hex else - vim.notify_once("Info(TOhtml): Couldn't get terminal colors, using fallback") + notify("Couldn't get terminal colors, using fallback") local t_Co = tonumber(vim.api.nvim_eval('&t_Co')) if t_Co <= 8 then cterm_color_cache = cterm_8_to_hex @@ -241,7 +261,7 @@ local function get_background_color() end local hex = try_query_terminal_color('background') if not hex or not hex:match('#%x%x%x%x%x%x') then - vim.notify_once("Info(TOhtml): Couldn't get terminal background colors, using fallback") + notify("Couldn't get terminal background colors, using fallback") hex = vim.o.background == 'light' and '#ffffff' or '#000000' end background_color_cache = hex @@ -259,7 +279,7 @@ local function get_foreground_color() end local hex = try_query_terminal_color('foreground') if not hex or not hex:match('#%x%x%x%x%x%x') then - vim.notify_once("Info(TOhtml): Couldn't get terminal foreground colors, using fallback") + notify("Couldn't get terminal foreground colors, using fallback") hex = vim.o.background == 'light' and '#000000' or '#ffffff' end foreground_color_cache = hex @@ -292,9 +312,12 @@ local function style_line_insert_virt_text(style_line, col, val) end --- @param state vim.tohtml.state ---- @param hl string|integer|nil +--- @param hl string|integer|string[]|integer[]? --- @return nil|integer local function register_hl(state, hl) + if type(hl) == 'table' then + hl = hl[#hl] + end if type(hl) == 'nil' then return elseif type(hl) == 'string' then @@ -467,7 +490,7 @@ local function _styletable_extmarks_highlight(state, extmark, namespaces) ---TODO(altermo) LSP semantic tokens (and some other extmarks) are only ---generated in visible lines, and not in the whole buffer. if (namespaces[extmark[4].ns_id] or ''):find('vim_lsp_semantic_tokens') then - vim.notify_once('Info(TOhtml): lsp semantic tokens are not supported, HTML may be incorrect') + notify('lsp semantic tokens are not supported, HTML may be incorrect') return end local srow, scol, erow, ecol = @@ -481,10 +504,17 @@ end --- @param state vim.tohtml.state --- @param extmark {[1]:integer,[2]:integer,[3]:integer,[4]:vim.api.keyset.set_extmark|any} -local function _styletable_extmarks_virt_text(state, extmark) +--- @param namespaces table<integer,string> +local function _styletable_extmarks_virt_text(state, extmark, namespaces) if not extmark[4].virt_text then return end + ---TODO(altermo) LSP semantic tokens (and some other extmarks) are only + ---generated in visible lines, and not in the whole buffer. + if (namespaces[extmark[4].ns_id] or ''):find('vim_lsp_inlayhint') then + notify('lsp inlay hints are not supported, HTML may be incorrect') + return + end local styletable = state.style --- @type integer,integer local row, col = extmark[2], extmark[3] @@ -510,7 +540,7 @@ local function _styletable_extmarks_virt_text(state, extmark) else style_line_insert_virt_text(styletable[row + 1], col + 1, { i[1], hlid }) end - virt_text_len = virt_text_len + #i[1] + virt_text_len = virt_text_len + len(i[1]) end if extmark[4].virt_text_pos == 'overlay' then styletable_insert_range(state, row + 1, col + 1, row + 1, col + virt_text_len + 1, HIDE_ID) @@ -521,11 +551,9 @@ local function _styletable_extmarks_virt_text(state, extmark) hl_mode = 'blend', hl_group = 'combine', } - for opt, val in ipairs(not_supported) do + for opt, val in pairs(not_supported) do if extmark[4][opt] == val then - vim.notify_once( - ('Info(TOhtml): extmark.%s="%s" is not supported, HTML may be incorrect'):format(opt, val) - ) + notify(('extmark.%s="%s" is not supported, HTML may be incorrect'):format(opt, val)) end end end @@ -586,7 +614,7 @@ local function styletable_extmarks(state) _styletable_extmarks_conceal(state, v) end for _, v in ipairs(extmarks) do - _styletable_extmarks_virt_text(state, v) + _styletable_extmarks_virt_text(state, v, namespaces) end for _, v in ipairs(extmarks) do _styletable_extmarks_virt_lines(state, v) @@ -611,9 +639,7 @@ local function styletable_folds(state) end end if has_folded and type(({ pcall(vim.api.nvim_eval, vim.o.foldtext) })[2]) == 'table' then - vim.notify_once( - 'Info(TOhtml): foldtext returning a table is half supported, HTML may be incorrect' - ) + notify('foldtext returning a table with highlights is not supported, HTML may be incorrect') end end @@ -759,7 +785,7 @@ local function styletable_statuscolumn(state) statuscolumn, { winid = state.winid, use_statuscol_lnum = row, highlights = true } ) - local width = vim.api.nvim_strwidth(status.str) + local width = len(status.str) if width > minwidth then minwidth = width end @@ -774,7 +800,7 @@ local function styletable_statuscolumn(state) for k, v in ipairs(hls) do local text = str:sub(v.start + 1, hls[k + 1] and hls[k + 1].start or nil) if k == #hls then - text = text .. (' '):rep(minwidth - vim.api.nvim_strwidth(str)) + text = text .. (' '):rep(minwidth - len(str)) end if text ~= '' then local hlid = register_hl(state, v.group) @@ -794,7 +820,6 @@ local function styletable_listchars(state) local function utf8_sub(str, i, j) return vim.fn.strcharpart(str, i - 1, j and j - i + 1 or nil) end - local len = vim.api.nvim_strwidth --- @type table<string,string> local listchars = vim.opt_local.listchars:get() local ids = setmetatable({}, { diff --git a/runtime/lua/vim/_editor.lua b/runtime/lua/vim/_editor.lua index 5e9be509c8..9f952db4fc 100644 --- a/runtime/lua/vim/_editor.lua +++ b/runtime/lua/vim/_editor.lua @@ -494,6 +494,7 @@ do vim.t = make_dict_accessor('t') end +--- @deprecated --- Gets a dict of line segment ("chunk") positions for the region from `pos1` to `pos2`. --- --- Input and output positions are byte positions, (0,0)-indexed. "End of line" column @@ -507,6 +508,8 @@ end ---@return table region Dict of the form `{linenr = {startcol,endcol}}`. `endcol` is exclusive, and ---whole lines are returned as `{startcol,endcol} = {0,-1}`. function vim.region(bufnr, pos1, pos2, regtype, inclusive) + vim.deprecate('vim.region', 'vim.fn.getregionpos()', '0.13') + if not vim.api.nvim_buf_is_loaded(bufnr) then vim.fn.bufload(bufnr) end diff --git a/runtime/lua/vim/_meta.lua b/runtime/lua/vim/_meta.lua index 731dd5b923..c9f207cb20 100644 --- a/runtime/lua/vim/_meta.lua +++ b/runtime/lua/vim/_meta.lua @@ -34,3 +34,5 @@ vim.uri_from_fname = uri.uri_from_fname vim.uri_from_bufnr = uri.uri_from_bufnr vim.uri_to_fname = uri.uri_to_fname vim.uri_to_bufnr = uri.uri_to_bufnr + +vim.provider = require('vim.provider') diff --git a/runtime/lua/vim/_meta/api.lua b/runtime/lua/vim/_meta/api.lua index 6edf2a5a96..c99eefa4f6 100644 --- a/runtime/lua/vim/_meta/api.lua +++ b/runtime/lua/vim/_meta/api.lua @@ -1761,13 +1761,15 @@ function vim.api.nvim_open_term(buffer, opts) end --- --- • title: Title (optional) in window border, string or list. --- List should consist of `[text, highlight]` tuples. If ---- string, the default highlight group is `FloatTitle`. +--- string, or a tuple lacks a highlight, the default +--- highlight group is `FloatTitle`. --- • title_pos: Title position. Must be set with `title` --- option. Value can be one of "left", "center", or "right". --- Default is `"left"`. --- • footer: Footer (optional) in window border, string or --- list. List should consist of `[text, highlight]` tuples. ---- If string, the default highlight group is `FloatFooter`. +--- If string, or a tuple lacks a highlight, the default +--- highlight group is `FloatFooter`. --- • footer_pos: Footer position. Must be set with `footer` --- option. Value can be one of "left", "center", or "right". --- Default is `"left"`. diff --git a/runtime/lua/vim/_meta/vimfn.lua b/runtime/lua/vim/_meta/vimfn.lua index f4daacfb7d..84bb26a135 100644 --- a/runtime/lua/vim/_meta/vimfn.lua +++ b/runtime/lua/vim/_meta/vimfn.lua @@ -1642,7 +1642,7 @@ function vim.fn.execute(command, silent) end --- If {expr} starts with "./" the |current-directory| is used. --- --- @param expr any ---- @return any +--- @return string function vim.fn.exepath(expr) end --- The result is a Number, which is |TRUE| if {expr} is @@ -3536,14 +3536,14 @@ function vim.fn.getreginfo(regname) end --- The optional argument {opts} is a Dict and supports the --- following items: --- ---- type Specify the region's selection type ---- (default: "v"): ---- "v" for |charwise| mode ---- "V" for |linewise| mode ---- "<CTRL-V>" for |blockwise-visual| mode +--- type Specify the region's selection type. +--- See |getregtype()| for possible values, +--- except that the width can be omitted +--- and an empty string cannot be used. +--- (default: "v") --- --- exclusive If |TRUE|, use exclusive selection ---- for the end position +--- for the end position. --- (default: follow 'selection') --- --- You can get the last selection type by |visualmode()|. diff --git a/runtime/lua/vim/deprecated/health.lua b/runtime/lua/vim/deprecated/health.lua index 0f6b1f578c..64a755b248 100644 --- a/runtime/lua/vim/deprecated/health.lua +++ b/runtime/lua/vim/deprecated/health.lua @@ -1,7 +1,7 @@ local M = {} local health = vim.health -local deprecated = {} +local deprecated = {} ---@type {[1]: string, [2]: table, [3]: string}[] function M.check() if next(deprecated) == nil then diff --git a/runtime/lua/vim/diagnostic.lua b/runtime/lua/vim/diagnostic.lua index 348204abb7..8e68e9608a 100644 --- a/runtime/lua/vim/diagnostic.lua +++ b/runtime/lua/vim/diagnostic.lua @@ -835,21 +835,36 @@ local function filter_highest(diagnostics) end end ---- @param position {[1]: integer, [2]: integer} --- @param search_forward boolean ---- @param bufnr integer ---- @param opts vim.diagnostic.GotoOpts ---- @param namespace integer[]|integer +--- @param opts vim.diagnostic.JumpOpts? --- @return vim.Diagnostic? -local function next_diagnostic(position, search_forward, bufnr, opts, namespace) +local function next_diagnostic(search_forward, opts) + opts = opts or {} + + -- Support deprecated win_id alias + if opts.win_id then + vim.deprecate('opts.win_id', 'opts.winid', '0.13') + opts.winid = opts.win_id + opts.win_id = nil + end + + -- Support deprecated cursor_position alias + if opts.cursor_position then + vim.deprecate('opts.cursor_position', 'opts.pos', '0.13') + opts.pos = opts.cursor_position + opts.cursor_position = nil + end + + local winid = opts.winid or api.nvim_get_current_win() + local bufnr = api.nvim_win_get_buf(winid) + local position = opts.pos or api.nvim_win_get_cursor(winid) + + -- Adjust row to be 0-indexed position[1] = position[1] - 1 - bufnr = get_bufnr(bufnr) - local wrap = if_nil(opts.wrap, true) - local get_opts = vim.deepcopy(opts) - get_opts.namespace = get_opts.namespace or namespace + local wrap = if_nil(opts.wrap, true) - local diagnostics = get_diagnostics(bufnr, get_opts, true) + local diagnostics = get_diagnostics(bufnr, opts, true) if opts._highest then filter_highest(diagnostics) @@ -902,32 +917,41 @@ local function next_diagnostic(position, search_forward, bufnr, opts, namespace) end end ---- @param opts vim.diagnostic.GotoOpts? ---- @param pos {[1]:integer,[2]:integer}|false -local function diagnostic_move_pos(opts, pos) - opts = opts or {} - - local float = if_nil(opts.float, true) - local win_id = opts.win_id or api.nvim_get_current_win() - - if not pos then +--- Move the cursor to the given diagnostic. +--- +--- @param diagnostic vim.Diagnostic? +--- @param opts vim.diagnostic.JumpOpts? +local function goto_diagnostic(diagnostic, opts) + if not diagnostic then api.nvim_echo({ { 'No more valid diagnostics to move to', 'WarningMsg' } }, true, {}) return end - api.nvim_win_call(win_id, function() + opts = opts or {} + + -- Support deprecated win_id alias + if opts.win_id then + vim.deprecate('opts.win_id', 'opts.winid', '0.13') + opts.winid = opts.win_id + opts.win_id = nil + end + + local winid = opts.winid or api.nvim_get_current_win() + + api.nvim_win_call(winid, function() -- Save position in the window's jumplist vim.cmd("normal! m'") - api.nvim_win_set_cursor(win_id, { pos[1] + 1, pos[2] }) + api.nvim_win_set_cursor(winid, { diagnostic.lnum + 1, diagnostic.col }) -- Open folds under the cursor vim.cmd('normal! zv') end) + local float = if_nil(opts.float, true) if float then local float_opts = type(float) == 'table' and float or {} vim.schedule(function() M.open_float(vim.tbl_extend('keep', float_opts, { - bufnr = api.nvim_win_get_buf(win_id), + bufnr = api.nvim_win_get_buf(winid), scope = 'cursor', focus = false, })) @@ -1114,24 +1138,24 @@ end --- Get the previous diagnostic closest to the cursor position. --- ----@param opts? vim.diagnostic.GotoOpts +---@param opts? vim.diagnostic.JumpOpts ---@return vim.Diagnostic? : Previous diagnostic function M.get_prev(opts) - opts = opts or {} - - local win_id = opts.win_id or api.nvim_get_current_win() - local bufnr = api.nvim_win_get_buf(win_id) - local cursor_position = opts.cursor_position or api.nvim_win_get_cursor(win_id) - - return next_diagnostic(cursor_position, false, bufnr, opts, opts.namespace) + return next_diagnostic(false, opts) end --- Return the position of the previous diagnostic in the current buffer. --- ----@param opts? vim.diagnostic.GotoOpts +---@param opts? vim.diagnostic.JumpOpts ---@return table|false: Previous diagnostic position as a `(row, col)` tuple --- or `false` if there is no prior diagnostic. +---@deprecated function M.get_prev_pos(opts) + vim.deprecate( + 'vim.diagnostic.get_prev_pos()', + 'access the lnum and col fields from get_prev() instead', + '0.13' + ) local prev = M.get_prev(opts) if not prev then return false @@ -1141,31 +1165,33 @@ function M.get_prev_pos(opts) end --- Move to the previous diagnostic in the current buffer. ----@param opts? vim.diagnostic.GotoOpts +---@param opts? vim.diagnostic.JumpOpts +---@deprecated function M.goto_prev(opts) - return diagnostic_move_pos(opts, M.get_prev_pos(opts)) + vim.deprecate('vim.diagnostic.goto_prev()', 'vim.diagnostic.jump()', '0.13') + goto_diagnostic(M.get_prev(opts), opts) end --- Get the next diagnostic closest to the cursor position. --- ----@param opts? vim.diagnostic.GotoOpts +---@param opts? vim.diagnostic.JumpOpts ---@return vim.Diagnostic? : Next diagnostic function M.get_next(opts) - opts = opts or {} - - local win_id = opts.win_id or api.nvim_get_current_win() - local bufnr = api.nvim_win_get_buf(win_id) - local cursor_position = opts.cursor_position or api.nvim_win_get_cursor(win_id) - - return next_diagnostic(cursor_position, true, bufnr, opts, opts.namespace) + return next_diagnostic(true, opts) end --- Return the position of the next diagnostic in the current buffer. --- ----@param opts? vim.diagnostic.GotoOpts +---@param opts? vim.diagnostic.JumpOpts ---@return table|false : Next diagnostic position as a `(row, col)` tuple or false if no next --- diagnostic. +---@deprecated function M.get_next_pos(opts) + vim.deprecate( + 'vim.diagnostic.get_next_pos()', + 'access the lnum and col fields from get_next() instead', + '0.13' + ) local next = M.get_next(opts) if not next then return false @@ -1187,12 +1213,21 @@ end --- @field severity? vim.diagnostic.SeverityFilter --- Configuration table with the following keys: ---- @class vim.diagnostic.GotoOpts : vim.diagnostic.GetOpts +--- @class vim.diagnostic.JumpOpts : vim.diagnostic.GetOpts +--- +--- The diagnostic to jump to. Mutually exclusive with {count}, {namespace}, +--- and {severity}. +--- @field diagnostic? vim.Diagnostic +--- +--- The number of diagnostics to move by, starting from {pos}. A positive +--- integer moves forward by {count} diagnostics, while a negative integer moves +--- backward by {count} diagnostics. Mutually exclusive with {diagnostic}. +--- @field count? integer --- ---- Cursor position as a `(row, col)` tuple. ---- See |nvim_win_get_cursor()|. ---- (default: current cursor position) ---- @field cursor_position? {[1]:integer,[2]:integer} +--- Cursor position as a `(row, col)` tuple. See |nvim_win_get_cursor()|. Used +--- to find the nearest diagnostic when {count} is used. Only used when {count} +--- is non-nil. Default is the current cursor position. +--- @field pos? {[1]:integer,[2]:integer} --- --- Whether to loop around file or not. Similar to 'wrapscan'. --- (default: `true`) @@ -1214,13 +1249,69 @@ end --- --- Window ID --- (default: `0`) ---- @field win_id? integer +--- @field winid? integer + +--- Move to a diagnostic. +--- +--- @param opts vim.diagnostic.JumpOpts +--- @return vim.Diagnostic? # The diagnostic that was moved to. +function M.jump(opts) + -- One of "diagnostic" or "count" must be provided + assert( + opts.diagnostic or opts.count, + 'One of "diagnostic" or "count" must be specified in the options to vim.diagnostic.jump()' + ) + + if opts.diagnostic then + goto_diagnostic(opts.diagnostic, opts) + return opts.diagnostic + end + + local count = opts.count + if count == 0 then + return nil + end + + -- Support deprecated cursor_position alias + if opts.cursor_position then + vim.deprecate('opts.cursor_position', 'opts.pos', '0.13') + opts.pos = opts.cursor_position + opts.cursor_position = nil + end + + -- Copy the opts table so that we can modify it + local opts_ = vim.deepcopy(opts, true) + + local diag = nil + while count ~= 0 do + local next = next_diagnostic(count > 0, opts_) + if not next then + break + end + + -- Update cursor position + opts_.pos = { next.lnum + 1, next.col } + + if count > 0 then + count = count - 1 + else + count = count + 1 + end + diag = next + end + + goto_diagnostic(diag, opts) + + return diag +end --- Move to the next diagnostic. --- ----@param opts? vim.diagnostic.GotoOpts +---@param opts? vim.diagnostic.JumpOpts +---@deprecated function M.goto_next(opts) - diagnostic_move_pos(opts, M.get_next_pos(opts)) + vim.deprecate('vim.diagnostic.goto_next()', 'vim.diagnostic.jump()', '0.13') + goto_diagnostic(M.get_next(opts), opts) end M.handlers.signs = { @@ -1688,7 +1779,7 @@ end --- ---@param opts vim.diagnostic.Opts.Float? ---@return integer? float_bufnr ----@return integer? win_id +---@return integer? winid function M.open_float(opts, ...) -- Support old (bufnr, opts) signature local bufnr --- @type integer? diff --git a/runtime/lua/vim/filetype.lua b/runtime/lua/vim/filetype.lua index d1fdd0aa16..2ab6cc6059 100644 --- a/runtime/lua/vim/filetype.lua +++ b/runtime/lua/vim/filetype.lua @@ -1637,7 +1637,7 @@ local filename = { ['.xsdbcmdhistory'] = 'tcl', ['texmf.cnf'] = 'texmf', COPYING = 'text', - README = 'text', + README = detect_seq(detect.haredoc, 'text'), LICENSE = 'text', AUTHORS = 'text', tfrc = 'tf', diff --git a/runtime/lua/vim/filetype/detect.lua b/runtime/lua/vim/filetype/detect.lua index ba86d8de5a..58d2666564 100644 --- a/runtime/lua/vim/filetype/detect.lua +++ b/runtime/lua/vim/filetype/detect.lua @@ -650,6 +650,30 @@ function M.header(_, bufnr) end end +--- Recursively search for Hare source files in a directory and any +--- subdirectories, up to a given depth. +--- @param dir string +--- @param depth number +--- @return boolean +local function is_hare_module(dir, depth) + depth = math.max(depth, 0) + for name, _ in vim.fs.dir(dir, { depth = depth + 1 }) do + if name:find('%.ha$') then + return true + end + end + return false +end + +--- @type vim.filetype.mapfn +function M.haredoc(path, _) + if vim.g.filetype_haredoc then + if is_hare_module(vim.fs.dirname(path), vim.g.haredoc_search_depth or 1) then + return 'haredoc' + end + end +end + --- @type vim.filetype.mapfn function M.html(_, bufnr) for _, line in ipairs(getlines(bufnr, 1, 10)) do diff --git a/runtime/lua/vim/health.lua b/runtime/lua/vim/health.lua index f40f04a064..236f9da752 100644 --- a/runtime/lua/vim/health.lua +++ b/runtime/lua/vim/health.lua @@ -104,10 +104,10 @@ local function filepath_to_healthcheck(path) local subpath = path:gsub('.*lua/', '') if vim.fs.basename(subpath) == 'health.lua' then -- */health.lua - name = assert(vim.fs.dirname(subpath)) + name = vim.fs.dirname(subpath) else -- */health/init.lua - name = assert(vim.fs.dirname(assert(vim.fs.dirname(subpath)))) + name = vim.fs.dirname(vim.fs.dirname(subpath)) end name = name:gsub('/', '.') @@ -275,114 +275,6 @@ function M.error(msg, ...) collect_output(input) end -function M._provider_disabled(provider) - local loaded_var = 'loaded_' .. provider .. '_provider' - local v = vim.g[loaded_var] - if v == 0 then - M.info('Disabled (' .. loaded_var .. '=' .. v .. ').') - return true - end - return false -end - --- Handler for s:system() function. -local function system_handler(self, _, data, event) - if event == 'stderr' then - if self.add_stderr_to_output then - self.output = self.output .. table.concat(data, '') - else - self.stderr = self.stderr .. table.concat(data, '') - end - elseif event == 'stdout' then - self.output = self.output .. table.concat(data, '') - end -end - --- Attempts to construct a shell command from an args list. --- Only for display, to help users debug a failed command. -local function shellify(cmd) - if type(cmd) ~= 'table' then - return cmd - end - local escaped = {} - for i, v in ipairs(cmd) do - if v:match('[^A-Za-z_/.-]') then - escaped[i] = vim.fn.shellescape(v) - else - escaped[i] = v - end - end - return table.concat(escaped, ' ') -end - -function M._cmd_ok(cmd) - local out = vim.fn.system(cmd) - return vim.v.shell_error == 0, out -end - ---- Run a system command and timeout after 30 seconds. ---- ---- @param cmd table List of command arguments to execute ---- @param args? table Optional arguments: ---- - stdin (string): Data to write to the job's stdin ---- - stderr (boolean): Append stderr to stdout ---- - ignore_error (boolean): If true, ignore error output ---- - timeout (number): Number of seconds to wait before timing out (default 30) -function M._system(cmd, args) - args = args or {} - local stdin = args.stdin or '' - local stderr = vim.F.if_nil(args.stderr, false) - local ignore_error = vim.F.if_nil(args.ignore_error, false) - - local shell_error_code = 0 - local opts = { - add_stderr_to_output = stderr, - output = '', - stderr = '', - on_stdout = system_handler, - on_stderr = system_handler, - on_exit = function(_, data) - shell_error_code = data - end, - } - local jobid = vim.fn.jobstart(cmd, opts) - - if jobid < 1 then - local message = - string.format('Command error (job=%d): %s (in %s)', jobid, shellify(cmd), vim.uv.cwd()) - error(message) - return opts.output, 1 - end - - if stdin:find('^%s$') then - vim.fn.chansend(jobid, stdin) - end - - local res = vim.fn.jobwait({ jobid }, vim.F.if_nil(args.timeout, 30) * 1000) - if res[1] == -1 then - error('Command timed out: ' .. shellify(cmd)) - vim.fn.jobstop(jobid) - elseif shell_error_code ~= 0 and not ignore_error then - local emsg = string.format( - 'Command error (job=%d, exit code %d): %s (in %s)', - jobid, - shell_error_code, - shellify(cmd), - vim.uv.cwd() - ) - if opts.output:find('%S') then - emsg = string.format('%s\noutput: %s', emsg, opts.output) - end - if opts.stderr:find('%S') then - emsg = string.format('%s\nstderr: %s', emsg, opts.stderr) - end - error(emsg) - end - - -- return opts.output - return vim.trim(vim.fn.system(cmd)), shell_error_code -end - local path2name = function(path) if path:match('%.lua$') then -- Lua: transform "../lua/vim/lsp/health.lua" into "vim.lsp" @@ -409,11 +301,13 @@ end local PATTERNS = { '/autoload/health/*.vim', '/lua/**/**/health.lua', '/lua/**/**/health/init.lua' } --- :checkhealth completion function used by cmdexpand.c get_healthcheck_names() M._complete = function() - local unique = vim + local unique = vim ---@type table<string,boolean> + ---@param pattern string .iter(vim.tbl_map(function(pattern) return vim.tbl_map(path2name, vim.api.nvim_get_runtime_file(pattern, true)) end, PATTERNS)) :flatten() + ---@param t table<string,boolean> :fold({}, function(t, name) t[name] = true -- Remove duplicates return t @@ -472,7 +366,7 @@ function M._check(mods, plugin_names) vim.fn.call(func, {}) else local f = assert(loadstring(func)) - local ok, output = pcall(f) + local ok, output = pcall(f) ---@type boolean, string if not ok then M.error( string.format('Failed to run healthcheck for "%s" plugin. Exception:\n%s\n', name, output) @@ -499,7 +393,7 @@ function M._check(mods, plugin_names) end s_output[#s_output + 1] = '' s_output = vim.list_extend(header, s_output) - vim.fn.append('$', s_output) + vim.fn.append(vim.fn.line('$'), s_output) vim.cmd.redraw() end diff --git a/runtime/lua/vim/health/health.lua b/runtime/lua/vim/health/health.lua index 5bc03199ee..235dacb82a 100644 --- a/runtime/lua/vim/health/health.lua +++ b/runtime/lua/vim/health/health.lua @@ -239,6 +239,7 @@ local function check_tmux() return end + ---@param option string local get_tmux_option = function(option) local cmd = 'tmux show-option -qvg ' .. option -- try global scope local out = vim.fn.system(vim.fn.split(cmd)) @@ -378,7 +379,7 @@ local function check_terminal() 'SSH_TTY', }) do if vim.env[env_var] then - health.info(vim.fn.printf('$%s="%s"', env_var, vim.env[env_var])) + health.info(string.format('$%s="%s"', env_var, vim.env[env_var])) end end end diff --git a/runtime/lua/vim/highlight.lua b/runtime/lua/vim/highlight.lua index f278bd357f..89298ce568 100644 --- a/runtime/lua/vim/highlight.lua +++ b/runtime/lua/vim/highlight.lua @@ -20,8 +20,8 @@ M.priorities = { --- @class vim.highlight.range.Opts --- @inlinedoc --- ---- Type of range. See [setreg()] ---- (default: `'charwise'`) +--- Type of range. See [getregtype()] +--- (default: `'v'` i.e. charwise) --- @field regtype? string --- --- Indicates whether the range is end-inclusive @@ -49,20 +49,49 @@ function M.range(bufnr, ns, higroup, start, finish, opts) local priority = opts.priority or M.priorities.user local scoped = opts._scoped or false - -- TODO: in case of 'v', 'V' (not block), this should calculate equivalent - -- bounds (row, col, end_row, end_col) as multiline regions are natively - -- supported now - local region = vim.region(bufnr, start, finish, regtype, inclusive) - for linenr, cols in pairs(region) do - local end_row - if cols[2] == -1 then - end_row = linenr + 1 - cols[2] = 0 + local pos1 = type(start) == 'string' and vim.fn.getpos(start) + or { bufnr, start[1] + 1, start[2] + 1, 0 } + local pos2 = type(finish) == 'string' and vim.fn.getpos(finish) + or { bufnr, finish[1] + 1, finish[2] + 1, 0 } + + local buf_line_count = vim.api.nvim_buf_line_count(bufnr) + pos1[2] = math.min(pos1[2], buf_line_count) + pos2[2] = math.min(pos2[2], buf_line_count) + + if pos1[2] <= 0 or pos1[3] <= 0 or pos2[2] <= 0 or pos2[3] <= 0 then + return + end + + vim.api.nvim_buf_call(bufnr, function() + local max_col1 = vim.fn.col({ pos1[2], '$' }) + pos1[3] = math.min(pos1[3], max_col1) + local max_col2 = vim.fn.col({ pos2[2], '$' }) + pos2[3] = math.min(pos2[3], max_col2) + end) + + local region = vim.fn.getregionpos(pos1, pos2, { + type = regtype, + exclusive = not inclusive, + eol = true, + }) + -- For non-blockwise selection, use a single extmark. + if regtype == 'v' or regtype == 'V' then + region = { { region[1][1], region[#region][2] } } + end + + for _, res in ipairs(region) do + local start_row = res[1][2] - 1 + local start_col = res[1][3] - 1 + local end_row = res[2][2] - 1 + local end_col = res[2][3] + if regtype == 'V' then + end_row = end_row + 1 + end_col = 0 end - api.nvim_buf_set_extmark(bufnr, ns, linenr, cols[1], { + api.nvim_buf_set_extmark(bufnr, ns, start_row, start_col, { hl_group = higroup, end_row = end_row, - end_col = cols[2], + end_col = end_col, priority = priority, strict = false, scoped = scoped, diff --git a/runtime/lua/vim/lsp.lua b/runtime/lua/vim/lsp.lua index da3d4d91f2..94c31359da 100644 --- a/runtime/lua/vim/lsp.lua +++ b/runtime/lua/vim/lsp.lua @@ -577,7 +577,8 @@ local function buf_attach(bufnr) api.nvim_buf_attach(bufnr, false, { on_lines = function(_, _, changedtick, firstline, lastline, new_lastline) if #lsp.get_clients({ bufnr = bufnr }) == 0 then - return true -- detach + -- detach if there are no clients + return #lsp.get_clients({ bufnr = bufnr, _uninitialized = true }) == 0 end util.buf_versions[bufnr] = changedtick changetracking.send_changes(bufnr, firstline, lastline, new_lastline) diff --git a/runtime/lua/vim/lsp/buf.lua b/runtime/lua/vim/lsp/buf.lua index 49833eaeec..299b68e134 100644 --- a/runtime/lua/vim/lsp/buf.lua +++ b/runtime/lua/vim/lsp/buf.lua @@ -135,7 +135,7 @@ end ---@param mode "v"|"V" ---@return table {start={row,col}, end={row,col}} using (1, 0) indexing local function range_from_selection(bufnr, mode) - -- TODO: Use `vim.region()` instead https://github.com/neovim/neovim/pull/13896 + -- TODO: Use `vim.fn.getregionpos()` instead. -- [bufnum, lnum, col, off]; both row and column 1-indexed local start = vim.fn.getpos('v') diff --git a/runtime/lua/vim/lsp/client.lua b/runtime/lua/vim/lsp/client.lua index c8616bf728..327cd19125 100644 --- a/runtime/lua/vim/lsp/client.lua +++ b/runtime/lua/vim/lsp/client.lua @@ -182,7 +182,7 @@ local validate = vim.validate --- It can be `null` if the client supports workspace folders but none are --- configured. --- @field workspace_folders lsp.WorkspaceFolder[]? ---- @field root_dir string +--- @field root_dir string? --- --- @field attached_buffers table<integer,true> --- @@ -470,7 +470,6 @@ function Client.create(config) _on_exit_cbs = ensure_list(config.on_exit), _on_attach_cbs = ensure_list(config.on_attach), _on_error_cb = config.on_error, - _root_dir = config.root_dir, _trace = get_trace(config.trace), --- Contains $/progress report messages. diff --git a/runtime/lua/vim/lsp/health.lua b/runtime/lua/vim/lsp/health.lua index a79ae76eb9..ffe595ab37 100644 --- a/runtime/lua/vim/lsp/health.lua +++ b/runtime/lua/vim/lsp/health.lua @@ -33,16 +33,25 @@ local function check_active_clients() local clients = vim.lsp.get_clients() if next(clients) then for _, client in pairs(clients) do - local attached_to = table.concat(vim.tbl_keys(client.attached_buffers or {}), ',') - report_info( + local cmd ---@type string + if type(client.config.cmd) == 'table' then + cmd = table.concat(client.config.cmd --[[@as table]], ' ') + elseif type(client.config.cmd) == 'function' then + cmd = tostring(client.config.cmd) + end + report_info(table.concat({ + string.format('%s (id: %d)', client.name, client.id), string.format( - '%s (id=%s, root_dir=%s, attached_to=[%s])', - client.name, - client.id, - vim.fn.fnamemodify(client.root_dir, ':~'), - attached_to - ) - ) + ' Root directory: %s', + client.root_dir and vim.fn.fnamemodify(client.root_dir, ':~') or nil + ), + string.format(' Command: %s', cmd), + string.format(' Settings: %s', vim.inspect(client.settings, { newline = '\n ' })), + string.format( + ' Attached buffers: %s', + vim.iter(pairs(client.attached_buffers)):map(tostring):join(', ') + ), + }, '\n')) end else report_info('No active clients') @@ -50,7 +59,7 @@ local function check_active_clients() end local function check_watcher() - vim.health.start('vim.lsp: File watcher') + vim.health.start('vim.lsp: File Watcher') -- Only run the check if file watching has been enabled by a client. local clients = vim.lsp.get_clients() @@ -94,11 +103,68 @@ local function check_watcher() end end +local function check_position_encodings() + vim.health.start('vim.lsp: Position Encodings') + local clients = vim.lsp.get_clients() + if next(clients) then + local position_encodings = {} ---@type table<integer, table<string, integer[]>> + for _, client in pairs(clients) do + for bufnr in pairs(client.attached_buffers) do + if not position_encodings[bufnr] then + position_encodings[bufnr] = {} + end + if not position_encodings[bufnr][client.offset_encoding] then + position_encodings[bufnr][client.offset_encoding] = {} + end + table.insert(position_encodings[bufnr][client.offset_encoding], client.id) + end + end + + -- Check if any buffers are attached to multiple clients with different position encodings + local buffers = {} ---@type integer[] + for bufnr, encodings in pairs(position_encodings) do + local list = {} ---@type string[] + for k in pairs(encodings) do + list[#list + 1] = k + end + + if #list > 1 then + buffers[#buffers + 1] = bufnr + end + end + + if #buffers > 0 then + local lines = + { 'Found buffers attached to multiple clients with different position encodings.' } + for _, bufnr in ipairs(buffers) do + local encodings = position_encodings[bufnr] + local parts = {} + for encoding, client_ids in pairs(encodings) do + table.insert( + parts, + string.format('%s (client id(s): %s)', encoding:upper(), table.concat(client_ids, ', ')) + ) + end + table.insert(lines, string.format('- Buffer %d: %s', bufnr, table.concat(parts, ', '))) + end + report_warn( + table.concat(lines, '\n'), + 'Use the positionEncodings client capability to ensure all clients use the same position encoding' + ) + else + report_info('No buffers contain mixed position encodings') + end + else + report_info('No active clients') + end +end + --- Performs a healthcheck for LSP function M.check() check_log() check_active_clients() check_watcher() + check_position_encodings() end return M diff --git a/runtime/lua/vim/lsp/util.lua b/runtime/lua/vim/lsp/util.lua index 5a229a1169..0099e82f52 100644 --- a/runtime/lua/vim/lsp/util.lua +++ b/runtime/lua/vim/lsp/util.lua @@ -616,7 +616,7 @@ function M.rename(old_fname, new_fname, opts) buf_rename[b] = { from = old_bname, to = new_bname } end - local newdir = assert(vim.fs.dirname(new_fname)) + local newdir = vim.fs.dirname(new_fname) vim.fn.mkdir(newdir, 'p') local ok, err = os.rename(old_fname_full, new_fname) @@ -625,7 +625,7 @@ function M.rename(old_fname, new_fname, opts) local old_undofile = vim.fn.undofile(old_fname_full) if uv.fs_stat(old_undofile) ~= nil then local new_undofile = vim.fn.undofile(new_fname) - vim.fn.mkdir(assert(vim.fs.dirname(new_undofile)), 'p') + vim.fn.mkdir(vim.fs.dirname(new_undofile), 'p') os.rename(old_undofile, new_undofile) end diff --git a/runtime/lua/vim/provider/health.lua b/runtime/lua/vim/provider/health.lua index 63e0da448a..fa2c452268 100644 --- a/runtime/lua/vim/provider/health.lua +++ b/runtime/lua/vim/provider/health.lua @@ -3,6 +3,112 @@ local iswin = vim.uv.os_uname().sysname == 'Windows_NT' local M = {} +local function cmd_ok(cmd) + local out = vim.fn.system(cmd) + return vim.v.shell_error == 0, out +end + +-- Attempts to construct a shell command from an args list. +-- Only for display, to help users debug a failed command. +local function shellify(cmd) + if type(cmd) ~= 'table' then + return cmd + end + local escaped = {} + for i, v in ipairs(cmd) do + if v:match('[^A-Za-z_/.-]') then + escaped[i] = vim.fn.shellescape(v) + else + escaped[i] = v + end + end + return table.concat(escaped, ' ') +end + +-- Handler for s:system() function. +local function system_handler(self, _, data, event) + if event == 'stderr' then + if self.add_stderr_to_output then + self.output = self.output .. table.concat(data, '') + else + self.stderr = self.stderr .. table.concat(data, '') + end + elseif event == 'stdout' then + self.output = self.output .. table.concat(data, '') + end +end + +--- @param cmd table List of command arguments to execute +--- @param args? table Optional arguments: +--- - stdin (string): Data to write to the job's stdin +--- - stderr (boolean): Append stderr to stdout +--- - ignore_error (boolean): If true, ignore error output +--- - timeout (number): Number of seconds to wait before timing out (default 30) +local function system(cmd, args) + args = args or {} + local stdin = args.stdin or '' + local stderr = vim.F.if_nil(args.stderr, false) + local ignore_error = vim.F.if_nil(args.ignore_error, false) + + local shell_error_code = 0 + local opts = { + add_stderr_to_output = stderr, + output = '', + stderr = '', + on_stdout = system_handler, + on_stderr = system_handler, + on_exit = function(_, data) + shell_error_code = data + end, + } + local jobid = vim.fn.jobstart(cmd, opts) + + if jobid < 1 then + local message = + string.format('Command error (job=%d): %s (in %s)', jobid, shellify(cmd), vim.uv.cwd()) + error(message) + return opts.output, 1 + end + + if stdin:find('^%s$') then + vim.fn.chansend(jobid, stdin) + end + + local res = vim.fn.jobwait({ jobid }, vim.F.if_nil(args.timeout, 30) * 1000) + if res[1] == -1 then + error('Command timed out: ' .. shellify(cmd)) + vim.fn.jobstop(jobid) + elseif shell_error_code ~= 0 and not ignore_error then + local emsg = string.format( + 'Command error (job=%d, exit code %d): %s (in %s)', + jobid, + shell_error_code, + shellify(cmd), + vim.uv.cwd() + ) + if opts.output:find('%S') then + emsg = string.format('%s\noutput: %s', emsg, opts.output) + end + if opts.stderr:find('%S') then + emsg = string.format('%s\nstderr: %s', emsg, opts.stderr) + end + error(emsg) + end + + return vim.trim(vim.fn.system(cmd)), shell_error_code +end + +---@param provider string +local function provider_disabled(provider) + local loaded_var = 'loaded_' .. provider .. '_provider' + local v = vim.g[loaded_var] + if v == 0 then + health.info('Disabled (' .. loaded_var .. '=' .. v .. ').') + return true + end + return false +end + local function clipboard() health.start('Clipboard (optional)') @@ -10,7 +116,7 @@ local function clipboard() os.getenv('TMUX') and vim.fn.executable('tmux') == 1 and vim.fn.executable('pbpaste') == 1 - and not health._cmd_ok('pbpaste') + and not cmd_ok('pbpaste') then local tmux_version = string.match(vim.fn.system('tmux -V'), '%d+%.%d+') local advice = { @@ -20,9 +126,9 @@ local function clipboard() health.error('pbcopy does not work with tmux version: ' .. tmux_version, advice) end - local clipboard_tool = vim.fn['provider#clipboard#Executable']() + local clipboard_tool = vim.fn['provider#clipboard#Executable']() ---@type string if vim.g.clipboard ~= nil and clipboard_tool == '' then - local error_message = vim.fn['provider#clipboard#Error']() + local error_message = vim.fn['provider#clipboard#Error']() ---@type string health.error( error_message, "Use the example in :help g:clipboard as a template, or don't set g:clipboard at all." @@ -40,7 +146,7 @@ end local function node() health.start('Node.js provider (optional)') - if health._provider_disabled('node') then + if provider_disabled('node') then return end @@ -60,7 +166,7 @@ local function node() end -- local node_v = vim.fn.split(system({'node', '-v'}), "\n")[1] or '' - local ok, node_v = health._cmd_ok({ 'node', '-v' }) + local ok, node_v = cmd_ok({ 'node', '-v' }) health.info('Node.js: ' .. node_v) if not ok or vim.version.lt(node_v, '6.0.0') then health.warn('Nvim node.js host does not support Node ' .. node_v) @@ -73,7 +179,7 @@ local function node() ) end - local node_detect_table = vim.fn['provider#node#Detect']() + local node_detect_table = vim.fn['provider#node#Detect']() ---@type string[] local host = node_detect_table[1] if host:find('^%s*$') then health.warn('Missing "neovim" npm (or yarn, pnpm) package.', { @@ -97,7 +203,7 @@ local function node() iswin and 'cmd /c ' .. manager .. ' info neovim --json' or manager .. ' info neovim --json' ) local latest_npm - ok, latest_npm = health._cmd_ok(vim.split(latest_npm_cmd, ' ')) + ok, latest_npm = cmd_ok(vim.split(latest_npm_cmd, ' ')) if not ok or latest_npm:find('^%s$') then health.error( 'Failed to run: ' .. latest_npm_cmd, @@ -115,7 +221,7 @@ local function node() local current_npm_cmd = { 'node', host, '--version' } local current_npm - ok, current_npm = health._cmd_ok(current_npm_cmd) + ok, current_npm = cmd_ok(current_npm_cmd) if not ok then health.error( 'Failed to run: ' .. table.concat(current_npm_cmd, ' '), @@ -143,7 +249,7 @@ end local function perl() health.start('Perl provider (optional)') - if health._provider_disabled('perl') then + if provider_disabled('perl') then return end @@ -162,7 +268,7 @@ local function perl() -- we cannot use cpanm that is on the path, as it may not be for the perl -- set with g:perl_host_prog - local ok = health._cmd_ok({ perl_exec, '-W', '-MApp::cpanminus', '-e', '' }) + local ok = cmd_ok({ perl_exec, '-W', '-MApp::cpanminus', '-e', '' }) if not ok then return { perl_exec, '"App::cpanminus" module is not installed' } end @@ -174,7 +280,7 @@ local function perl() 'my $app = App::cpanminus::script->new; $app->parse_options ("--info", "-q", "Neovim::Ext"); exit $app->doit', } local latest_cpan - ok, latest_cpan = health._cmd_ok(latest_cpan_cmd) + ok, latest_cpan = cmd_ok(latest_cpan_cmd) if not ok or latest_cpan:find('^%s*$') then health.error( 'Failed to run: ' .. table.concat(latest_cpan_cmd, ' '), @@ -184,7 +290,7 @@ local function perl() elseif latest_cpan[1] == '!' then local cpanm_errs = vim.split(latest_cpan, '!') if cpanm_errs[1]:find("Can't write to ") then - local advice = {} + local advice = {} ---@type string[] for i = 2, #cpanm_errs do advice[#advice + 1] = cpanm_errs[i] end @@ -197,7 +303,7 @@ local function perl() return end end - latest_cpan = vim.fn.matchstr(latest_cpan, [[\(\.\?\d\)\+]]) + latest_cpan = tostring(vim.fn.matchstr(latest_cpan, [[\(\.\?\d\)\+]])) if latest_cpan:find('^%s*$') then health.error('Cannot parse version number from cpanm output: ' .. latest_cpan) return @@ -205,7 +311,7 @@ local function perl() local current_cpan_cmd = { perl_exec, '-W', '-MNeovim::Ext', '-e', 'print $Neovim::Ext::VERSION' } local current_cpan - ok, current_cpan = health._cmd_ok(current_cpan_cmd) + ok, current_cpan = cmd_ok(current_cpan_cmd) if not ok then health.error( 'Failed to run: ' .. table.concat(current_cpan_cmd, ' '), @@ -243,9 +349,11 @@ local function python_exepath(invocation) return vim.fs.normalize(vim.trim(p.stdout)) end --- Check if pyenv is available and a valid pyenv root can be found, then return --- their respective paths. If either of those is invalid, return two empty --- strings, effectively ignoring pyenv. +--- Check if pyenv is available and a valid pyenv root can be found, then return +--- their respective paths. If either of those is invalid, return two empty +--- strings, effectively ignoring pyenv. +--- +--- @return {[1]: string, [2]: string} local function check_for_pyenv() local pyenv_path = vim.fn.resolve(vim.fn.exepath('pyenv')) @@ -288,11 +396,13 @@ local function check_bin(bin) return true end --- Fetch the contents of a URL. +--- Fetch the contents of a URL. +--- +--- @param url string local function download(url) local has_curl = vim.fn.executable('curl') == 1 if has_curl and vim.fn.system({ 'curl', '-V' }):find('Protocols:.*https') then - local out, rc = health._system({ 'curl', '-sL', url }, { stderr = true, ignore_error = true }) + local out, rc = system({ 'curl', '-sL', url }, { stderr = true, ignore_error = true }) if rc ~= 0 then return 'curl error with ' .. url .. ': ' .. rc else @@ -305,7 +415,7 @@ local function download(url) from urllib2 import urlopen\n\ response = urlopen('" .. url .. "')\n\ print(response.read().decode('utf8'))\n" - local out, rc = health._system({ 'python', '-c', script }) + local out, rc = system({ 'python', '-c', script }) if out == '' and rc ~= 0 then return 'python urllib.request error: ' .. rc else @@ -323,25 +433,24 @@ local function download(url) return message end --- Get the latest Nvim Python client (pynvim) version from PyPI. +--- Get the latest Nvim Python client (pynvim) version from PyPI. local function latest_pypi_version() local pypi_version = 'unable to get pypi response' local pypi_response = download('https://pypi.python.org/pypi/pynvim/json') if pypi_response ~= '' then local pcall_ok, output = pcall(vim.fn.json_decode, pypi_response) - local pypi_data - if pcall_ok then - pypi_data = output - else + if not pcall_ok then return 'error: ' .. pypi_response end + local pypi_data = output local pypi_element = pypi_data['info'] or {} pypi_version = pypi_element['version'] or 'unable to parse' end return pypi_version end +--- @param s string local function is_bad_response(s) local lower = s:lower() return vim.startswith(lower, 'unable') @@ -349,20 +458,22 @@ local function is_bad_response(s) or vim.startswith(lower, 'outdated') end --- Get version information using the specified interpreter. The interpreter is --- used directly in case breaking changes were introduced since the last time --- Nvim's Python client was updated. --- --- Returns: { --- {python executable version}, --- {current nvim version}, --- {current pypi nvim status}, --- {installed version status} --- } +--- Get version information using the specified interpreter. The interpreter is +--- used directly in case breaking changes were introduced since the last time +--- Nvim's Python client was updated. +--- +--- @param python string +--- +--- Returns: { +--- {python executable version}, +--- {current nvim version}, +--- {current pypi nvim status}, +--- {installed version status} +--- } local function version_info(python) local pypi_version = latest_pypi_version() - local python_version, rc = health._system({ + local python_version, rc = system({ python, '-c', 'import sys; print(".".join(str(x) for x in sys.version_info[:3]))', @@ -373,7 +484,7 @@ local function version_info(python) end local nvim_path - nvim_path, rc = health._system({ + nvim_path, rc = system({ python, '-c', 'import sys; sys.path = [p for p in sys.path if p != ""]; import neovim; print(neovim.__file__)', @@ -398,7 +509,7 @@ local function version_info(python) -- Try to get neovim.VERSION (added in 0.1.11dev). local nvim_version - nvim_version, rc = health._system({ + nvim_version, rc = system({ python, '-c', 'from neovim import VERSION as v; print("{}.{}.{}{}".format(v.major, v.minor, v.patch, v.prerelease))', @@ -406,9 +517,9 @@ local function version_info(python) if rc ~= 0 or nvim_version == '' then nvim_version = 'unable to find pynvim module version' local base = vim.fs.basename(nvim_path) - local metas = vim.fn.glob(base .. '-*/METADATA', 1, 1) - vim.list_extend(metas, vim.fn.glob(base .. '-*/PKG-INFO', 1, 1)) - vim.list_extend(metas, vim.fn.glob(base .. '.egg-info/PKG-INFO', 1, 1)) + local metas = vim.fn.glob(base .. '-*/METADATA', true, 1) + vim.list_extend(metas, vim.fn.glob(base .. '-*/PKG-INFO', true, 1)) + vim.list_extend(metas, vim.fn.glob(base .. '.egg-info/PKG-INFO', true, 1)) metas = table.sort(metas, compare) if metas and next(metas) ~= nil then @@ -438,14 +549,13 @@ end local function python() health.start('Python 3 provider (optional)') - local pyname = 'python3' ---@type string? local python_exe = '' local virtual_env = os.getenv('VIRTUAL_ENV') local venv = virtual_env and vim.fn.resolve(virtual_env) or '' - local host_prog_var = pyname .. '_host_prog' - local python_multiple = {} + local host_prog_var = 'python3_host_prog' + local python_multiple = {} ---@type string[] - if health._provider_disabled(pyname) then + if provider_disabled('python3') then return end @@ -458,8 +568,7 @@ local function python() health.info(message) end - local pythonx_warnings - pyname, pythonx_warnings = vim.provider.python.detect_by_module('neovim') + local pyname, pythonx_warnings = vim.provider.python.detect_by_module('neovim') if not pyname then health.warn( @@ -487,7 +596,7 @@ local function python() end if pyenv ~= '' then - python_exe = health._system({ pyenv, 'which', pyname }, { stderr = true }) + python_exe = system({ pyenv, 'which', pyname }, { stderr = true }) if python_exe == '' then health.warn('pyenv could not find ' .. pyname .. '.') end @@ -547,12 +656,7 @@ local function python() ) health.warn('pyenv is not set up optimally.', advice) elseif venv ~= '' then - local venv_root - if pyenv_root ~= '' then - venv_root = pyenv_root - else - venv_root = vim.fs.dirname(venv) - end + local venv_root = pyenv_root ~= '' and pyenv_root or vim.fs.dirname(venv) if vim.startswith(vim.fn.resolve(python_exe), venv_root .. '/') then local advice = string.format( @@ -637,9 +741,9 @@ local function python() health.ok('no $VIRTUAL_ENV') return end - local errors = {} + local errors = {} ---@type string[] -- Keep hints as dict keys in order to discard duplicates. - local hints = {} + local hints = {} ---@type table<string, boolean> -- The virtualenv should contain some Python executables, and those -- executables should be first both on Nvim's $PATH and the $PATH of -- subshells launched from Nvim. @@ -710,9 +814,7 @@ local function python() health.info(msg) health.info( 'Python version: ' - .. health._system( - 'python -c "import platform, sys; sys.stdout.write(platform.python_version())"' - ) + .. system('python -c "import platform, sys; sys.stdout.write(platform.python_version())"') ) health.ok('$VIRTUAL_ENV provides :!python.') end @@ -721,7 +823,7 @@ end local function ruby() health.start('Ruby provider (optional)') - if health._provider_disabled('ruby') then + if provider_disabled('ruby') then return end @@ -732,7 +834,7 @@ local function ruby() ) return end - health.info('Ruby: ' .. health._system({ 'ruby', '-v' })) + health.info('Ruby: ' .. system({ 'ruby', '-v' })) local host, _ = vim.provider.ruby.detect() if (not host) or host:find('^%s*$') then @@ -748,7 +850,7 @@ local function ruby() health.info('Host: ' .. host) local latest_gem_cmd = (iswin and 'cmd /c gem list -ra "^^neovim$"' or 'gem list -ra ^neovim$') - local ok, latest_gem = health._cmd_ok(vim.split(latest_gem_cmd, ' ')) + local ok, latest_gem = cmd_ok(vim.split(latest_gem_cmd, ' ')) if not ok or latest_gem:find('^%s*$') then health.error( 'Failed to run: ' .. latest_gem_cmd, @@ -761,7 +863,7 @@ local function ruby() local current_gem_cmd = { host, '--version' } local current_gem - ok, current_gem = health._cmd_ok(current_gem_cmd) + ok, current_gem = cmd_ok(current_gem_cmd) if not ok then health.error( 'Failed to run: ' .. table.concat(current_gem_cmd, ' '), diff --git a/runtime/lua/vim/shared.lua b/runtime/lua/vim/shared.lua index e9e4326057..2641d1feb0 100644 --- a/runtime/lua/vim/shared.lua +++ b/runtime/lua/vim/shared.lua @@ -214,7 +214,7 @@ end ---@param t table<T, any> (table) Table ---@return T[] : List of keys function vim.tbl_keys(t) - vim.validate({ t = { t, 't' } }) + vim.validate('t', t, 'table') --- @cast t table<any,any> local keys = {} @@ -231,7 +231,7 @@ end ---@param t table<any, T> (table) Table ---@return T[] : List of values function vim.tbl_values(t) - vim.validate({ t = { t, 't' } }) + vim.validate('t', t, 'table') local values = {} for _, v in @@ -332,7 +332,7 @@ end ---@param value any Value to compare ---@return boolean `true` if `t` contains `value` function vim.list_contains(t, value) - vim.validate({ t = { t, 't' } }) + vim.validate('t', t, 'table') --- @cast t table<any,any> for _, v in ipairs(t) do @@ -350,7 +350,7 @@ end ---@param t table Table to check ---@return boolean `true` if `t` is empty function vim.tbl_isempty(t) - vim.validate({ t = { t, 't' } }) + vim.validate('t', t, 'table') return next(t) == nil end @@ -580,7 +580,7 @@ end ---@return fun(table: table<K, V>, index?: K):K, V # |for-in| iterator over sorted keys and their values ---@return T function vim.spairs(t) - assert(type(t) == 'table', ('expected table, got %s'):format(type(t))) + vim.validate('t', t, 'table') --- @cast t table<any,any> -- collect the keys @@ -691,7 +691,7 @@ end ---@param t table Table ---@return integer : Number of non-nil values in table function vim.tbl_count(t) - vim.validate({ t = { t, 't' } }) + vim.validate('t', t, 'table') --- @cast t table<any,any> local count = 0 @@ -723,7 +723,7 @@ end ---@param s string String to trim ---@return string String with whitespace removed from its beginning and end function vim.trim(s) - vim.validate({ s = { s, 's' } }) + vim.validate('s', s, 'string') return s:match('^%s*(.*%S)') or '' end @@ -733,7 +733,7 @@ end ---@param s string String to escape ---@return string %-escaped pattern string function vim.pesc(s) - vim.validate({ s = { s, 's' } }) + vim.validate('s', s, 'string') return (s:gsub('[%(%)%.%%%+%-%*%?%[%]%^%$]', '%%%1')) end @@ -743,7 +743,8 @@ end ---@param prefix string Prefix to match ---@return boolean `true` if `prefix` is a prefix of `s` function vim.startswith(s, prefix) - vim.validate({ s = { s, 's' }, prefix = { prefix, 's' } }) + vim.validate('s', s, 'string') + vim.validate('prefix', prefix, 'string') return s:sub(1, #prefix) == prefix end @@ -753,7 +754,8 @@ end ---@param suffix string Suffix to match ---@return boolean `true` if `suffix` is a suffix of `s` function vim.endswith(s, suffix) - vim.validate({ s = { s, 's' }, suffix = { suffix, 's' } }) + vim.validate('s', s, 'string') + vim.validate('suffix', suffix, 'string') return #suffix == 0 or s:sub(-#suffix) == suffix end @@ -877,8 +879,30 @@ do return true end - --- Validates a parameter specification (types and values). Specs are evaluated in alphanumeric - --- order, until the first failure. + --- Validate function arguments. + --- + --- This function has two valid forms: + --- + --- 1. vim.validate(name: str, value: any, type: string, optional?: bool) + --- 2. vim.validate(spec: table) + --- + --- Form 1 validates that argument {name} with value {value} has the type + --- {type}. {type} must be a value returned by |lua-type()|. If {optional} is + --- true, then {value} may be null. This form is significantly faster and + --- should be preferred for simple cases. + --- + --- Example: + --- + --- ```lua + --- function vim.startswith(s, prefix) + --- vim.validate('s', s, 'string') + --- vim.validate('prefix', prefix, 'string') + --- ... + --- end + --- ``` + --- + --- Form 2 validates a parameter specification (types and values). Specs are + --- evaluated in alphanumeric order, until the first failure. --- --- Usage example: --- @@ -930,8 +954,32 @@ do --- only if the argument is valid. Can optionally return an additional --- informative error message as the second returned value. --- - msg: (optional) error string if validation fails - function vim.validate(opt) - local ok, err_msg = is_valid(opt) + --- @overload fun(name: string, val: any, expected: string, optional?: boolean) + function vim.validate(opt, ...) + local ok = false + local err_msg ---@type string? + local narg = select('#', ...) + if narg == 0 then + ok, err_msg = is_valid(opt) + elseif narg >= 2 then + -- Overloaded signature for fast/simple cases + local name = opt --[[@as string]] + local v, expected, optional = ... ---@type string, string, boolean? + local actual = type(v) + + ok = (actual == expected) or (v == nil and optional == true) + if not ok then + err_msg = ('%s: expected %s, got %s%s'):format( + name, + expected, + actual, + v and (' (%s)'):format(v) or '' + ) + end + else + error('invalid arguments') + end + if not ok then error(err_msg, 2) end diff --git a/runtime/lua/vim/snippet.lua b/runtime/lua/vim/snippet.lua index 1ec5235d7b..8cd454b908 100644 --- a/runtime/lua/vim/snippet.lua +++ b/runtime/lua/vim/snippet.lua @@ -376,7 +376,7 @@ local function select_tabstop(tabstop) move_cursor_to(range[1] + 1, range[2] + 1) feedkeys('v') move_cursor_to(range[3] + 1, range[4]) - feedkeys('o<c-g>') + feedkeys('o<c-g><c-r>_') end end @@ -456,6 +456,15 @@ local function setup_autocmds(bufnr) end end, }) + + vim.api.nvim_create_autocmd('BufLeave', { + group = snippet_group, + desc = 'Stop the snippet session when leaving the buffer', + buffer = bufnr, + callback = function() + M.stop() + end, + }) end --- Expands the given snippet text. diff --git a/runtime/lua/vim/treesitter/dev.lua b/runtime/lua/vim/treesitter/dev.lua index 5c91f101c0..ca8cf85eda 100644 --- a/runtime/lua/vim/treesitter/dev.lua +++ b/runtime/lua/vim/treesitter/dev.lua @@ -325,7 +325,10 @@ function M.inspect_tree(opts) opts = opts or {} + -- source buffer local buf = api.nvim_get_current_buf() + + -- window id for source buffer local win = api.nvim_get_current_win() local treeview = assert(TSTreeView:new(buf, opts.lang)) @@ -334,12 +337,14 @@ function M.inspect_tree(opts) close_win(vim.b[buf].dev_inspect) end + -- window id for tree buffer local w = opts.winid if not w then vim.cmd(opts.command or '60vnew') w = api.nvim_get_current_win() end + -- tree buffer local b = opts.bufnr if b then api.nvim_win_set_buf(w, b) @@ -375,6 +380,12 @@ function M.inspect_tree(opts) callback = function() local row = api.nvim_win_get_cursor(w)[1] local lnum, col = treeview:get(row).node:start() + + -- update source window if original was closed + if not api.nvim_win_is_valid(win) then + win = vim.fn.win_findbuf(buf)[1] + end + api.nvim_set_current_win(win) api.nvim_win_set_cursor(win, { lnum + 1, col }) end, @@ -432,6 +443,7 @@ function M.inspect_tree(opts) return true end + w = api.nvim_get_current_win() api.nvim_buf_clear_namespace(buf, treeview.ns, 0, -1) local row = api.nvim_win_get_cursor(w)[1] local lnum, col, end_lnum, end_col = treeview:get(row).node:range() @@ -441,6 +453,11 @@ function M.inspect_tree(opts) hl_group = 'Visual', }) + -- update source window if original was closed + if not api.nvim_win_is_valid(win) then + win = vim.fn.win_findbuf(buf)[1] + end + local topline, botline = vim.fn.line('w0', win), vim.fn.line('w$', win) -- Move the cursor if highlighted range is completely out of view @@ -506,7 +523,10 @@ function M.inspect_tree(opts) buffer = buf, once = true, callback = function() - close_win(w) + -- close all tree windows + for _, window in pairs(vim.fn.win_findbuf(b)) do + close_win(window) + end end, }) end diff --git a/runtime/queries/query/highlights.scm b/runtime/queries/query/highlights.scm index 210d03dc33..c02ee3f2a0 100644 --- a/runtime/queries/query/highlights.scm +++ b/runtime/queries/query/highlights.scm @@ -5,9 +5,6 @@ (capture (identifier) @type) -(anonymous_node - (identifier) @string) - (predicate name: (identifier) @function.call) diff --git a/runtime/syntax/hare.vim b/runtime/syntax/hare.vim index 07cf33fb11..4c7ae92486 100644 --- a/runtime/syntax/hare.vim +++ b/runtime/syntax/hare.vim @@ -1,119 +1,142 @@ -" PRELUDE {{{1 -" Vim syntax file -" Language: Hare -" Maintainer: Amelia Clarke <me@rsaihe.dev> -" Last Change: 2022-09-21 +" Vim syntax file. +" Language: Hare +" Maintainer: Amelia Clarke <selene@perilune.dev> +" Last Change: 2024-05-10 +" Upstream: https://git.sr.ht/~sircmpwn/hare.vim -if exists("b:current_syntax") +if exists('b:current_syntax') finish endif -let b:current_syntax = "hare" +syn include @haredoc syntax/haredoc.vim +let b:current_syntax = 'hare' -" SYNTAX {{{1 +" Syntax {{{1 syn case match +syn iskeyword @,48-57,@-@,_ -" KEYWORDS {{{2 -syn keyword hareConditional if else match switch +" Keywords {{{2 +syn keyword hareConditional else if match switch +syn keyword hareDefine def +syn keyword hareInclude use syn keyword hareKeyword break continue return yield +syn keyword hareKeyword case +syn keyword hareKeyword const let syn keyword hareKeyword defer +syn keyword hareKeyword export static syn keyword hareKeyword fn -syn keyword hareKeyword let -syn keyword hareLabel case syn keyword hareOperator as is syn keyword hareRepeat for -syn keyword hareStorageClass const def export nullable static -syn keyword hareStructure enum struct union syn keyword hareTypedef type -" C ABI. -syn keyword hareKeyword vastart vaarg vaend - -" BUILTINS {{{2 -syn keyword hareBuiltin abort +" Attributes. +syn keyword hareAttribute @fini @init @test +syn keyword hareAttribute @offset @packed +syn keyword hareAttribute @symbol +syn keyword hareAttribute @threadlocal + +" Builtins. +syn keyword hareBuiltin abort assert +syn keyword hareBuiltin align len offset syn keyword hareBuiltin alloc free syn keyword hareBuiltin append delete insert -syn keyword hareBuiltin assert -syn keyword hareBuiltin len offset +syn keyword hareBuiltin vaarg vaend vastart -" TYPES {{{2 +" Types {{{2 syn keyword hareType bool -syn keyword hareType char str +syn keyword hareType done syn keyword hareType f32 f64 -syn keyword hareType u8 u16 u32 u64 i8 i16 i32 i64 -syn keyword hareType uint int -syn keyword hareType rune +syn keyword hareType i8 i16 i32 i64 int +syn keyword hareType never +syn keyword hareType opaque +syn keyword hareType rune str +syn keyword hareType u8 u16 u32 u64 uint syn keyword hareType uintptr +syn keyword hareType valist syn keyword hareType void -" C ABI. -syn keyword hareType valist +" Other types. +syn keyword hareStorageClass nullable +syn keyword hareStructure enum struct union -" LITERALS {{{2 -syn keyword hareBoolean true false -syn keyword hareNull null - -" Number literals. -syn match hareNumber "\v(\.@1<!|\.\.)\zs<\d+([Ee][+-]?\d+)?(z|[iu](8|16|32|64)?)?>" display -syn match hareNumber "\v(\.@1<!|\.\.)\zs<0b[01]+(z|[iu](8|16|32|64)?)?>" display -syn match hareNumber "\v(\.@1<!|\.\.)\zs<0o\o+(z|[iu](8|16|32|64)?)?>" display -syn match hareNumber "\v(\.@1<!|\.\.)\zs<0x\x+(z|[iu](8|16|32|64)?)?>" display - -" Floating-point number literals. -syn match hareFloat "\v<\d+\.\d+([Ee][+-]?\d+)?(f32|f64)?>" display -syn match hareFloat "\v<\d+([Ee][+-]?\d+)?(f32|f64)>" display - -" String and rune literals. -syn match hareEscape "\\[\\'"0abfnrtv]" contained display -syn match hareEscape "\v\\(x\x{2}|u\x{4}|U\x{8})" contained display -syn match hareFormat "\v\{\d*(\%\d*|(:[ 0+-]?\d*(\.\d+)?[Xbox]?))?}" contained display -syn match hareFormat "\({{\|}}\)" contained display -syn region hareRune start="'" end="'\|$" skip="\\'" contains=hareEscape display extend -syn region hareString start=+"+ end=+"\|$+ skip=+\\"+ contains=hareEscape,hareFormat display extend -syn region hareString start="`" end="`\|$" contains=hareFormat display - -" MISCELLANEOUS {{{2 -syn keyword hareTodo FIXME TODO XXX contained +" Literals {{{2 +syn keyword hareBoolean false true +syn keyword hareConstant null -" Attributes. -syn match hareAttribute "@[a-z]*" +" Integer literals. +syn match hareNumber '\v<%(0|[1-9]%(_?\d)*)%([Ee]\+?\d+)?%([iu]%(8|16|32|64)?|z)?>' display +syn match hareNumber '\v<0b[01]%(_?[01])*%([iu]%(8|16|32|64)?|z)?>' display +syn match hareNumber '\v<0o\o%(_?\o)*%([iu]%(8|16|32|64)?|z)?>' display +syn match hareNumber '\v<0x\x%(_?\x)*%([iu]%(8|16|32|64)?|z)?>' display -" Blocks. -syn region hareBlock start="{" end="}" fold transparent +" Floating-point literals. +syn match hareFloat '\v<%(0|[1-9]%(_?\d)*)\.\d%(_?\d)*%([Ee][+-]?\d+)?%(f32|f64)?>' display +syn match hareFloat '\v<%(0|[1-9]%(_?\d)*)%([Ee][+-]?\d+)?%(f32|f64)>' display +syn match hareFloat '\v<0x\x%(_?\x)*%(\.\x%(_?\x)*)?[Pp][+-]?\d+%(f32|f64)?>' display + +" Rune and string literals. +syn region hareRune start="'" skip="\\'" end="'" contains=hareEscape +syn region hareString start='"' skip='\\"' end='"' contains=hareEscape,hareFormat +syn region hareString start='`' end='`' contains=hareFormat + +" Escape sequences. +syn match hareEscape '\\[0abfnrtv\\'"]' contained +syn match hareEscape '\v\\%(x\x{2}|u\x{4}|U\x{8})' contained display + +" Format sequences. +syn match hareFormat '\v\{\d*%(:%(\.?\d+|[ +\-=Xbefgox]|F[.2ESUs]|_%(.|\\%([0abfnrtv\\'"]|x\x{2}|u\x{4}|U\x{8})))*)?}' contained contains=hareEscape display +syn match hareFormat '{\d*%\d*}' contained display +syn match hareFormat '{{\|}}' contained display + +" Miscellaneous {{{2 " Comments. -syn region hareComment start="//" end="$" contains=hareCommentDoc,hareTodo,@Spell display keepend -syn region hareCommentDoc start="\[\[" end="]]\|\ze\_s" contained display +syn region hareComment start='//' end='$' contains=hareTodo,@haredoc,@Spell display +syn keyword hareTodo FIXME TODO XXX contained + +" Identifiers. +syn match hareDelimiter '::' display +syn match hareName '\<\h\w*\>' nextgroup=@harePostfix skipempty skipwhite transparent -" The size keyword can be either a builtin or a type. -syn match hareBuiltin "\v<size>\ze(\_s*//.*\_$)*\_s*\(" contains=hareComment -syn match hareType "\v<size>((\_s*//.*\_$)*\_s*\()@!" contains=hareComment +" Labels. +syn match hareLabel ':\h\w*\>' display -" Trailing whitespace. -syn match hareSpaceError "\v\s+$" display excludenl -syn match hareSpaceError "\v\zs +\ze\t" display +" Match `size` as a type unless it is followed by an open paren. +syn match hareType '\<size\>' display +syn match hareBuiltin '\<size\ze(' display -" Use statement. -syn region hareUse start="\v^\s*\zsuse>" end=";" contains=hareComment display +" Postfix expressions. +syn cluster harePostfix contains=hareErrorTest,hareField,hareIndex,hareParens +syn match hareErrorTest '!=\@!' contained nextgroup=@harePostfix skipempty skipwhite +syn match hareErrorTest '?' nextgroup=@harePostfix skipempty skipwhite +syn match hareField '\.\w*\>'hs=s+1 contained contains=hareNumber nextgroup=@harePostfix skipempty skipwhite +syn region hareIndex start='\[' end=']' contained nextgroup=@harePostfix skipempty skipwhite transparent +syn region hareParens start='(' end=')' nextgroup=@harePostfix skipempty skipwhite transparent -syn match hareErrorAssertion "\v(^([^/]|//@!)*\)\_s*)@<=!\=@!" -syn match hareQuestionMark "?" +" Whitespace errors. +syn match hareSpaceError '^ \+\ze\t' display +syn match hareSpaceError excludenl '\s\+$' containedin=ALL display -" DEFAULT HIGHLIGHTING {{{1 -hi def link hareAttribute Keyword +" Folding {{{3 +syn region hareBlock start='{' end='}' fold transparent + +" Default highlighting {{{1 +hi def link hareAttribute PreProc hi def link hareBoolean Boolean -hi def link hareBuiltin Function +hi def link hareBuiltin Operator hi def link hareComment Comment -hi def link hareCommentDoc SpecialComment hi def link hareConditional Conditional +hi def link hareConstant Constant +hi def link hareDefine Define +hi def link hareDelimiter Delimiter +hi def link hareErrorTest Special hi def link hareEscape SpecialChar hi def link hareFloat Float hi def link hareFormat SpecialChar +hi def link hareInclude Include hi def link hareKeyword Keyword -hi def link hareLabel Label -hi def link hareNull Constant +hi def link hareLabel Special hi def link hareNumber Number hi def link hareOperator Operator -hi def link hareQuestionMark Special hi def link hareRepeat Repeat hi def link hareRune Character hi def link hareStorageClass StorageClass @@ -122,12 +145,13 @@ hi def link hareStructure Structure hi def link hareTodo Todo hi def link hareType Type hi def link hareTypedef Typedef -hi def link hareUse PreProc -hi def link hareSpaceError Error -autocmd InsertEnter * hi link hareSpaceError NONE -autocmd InsertLeave * hi link hareSpaceError Error +" Highlight embedded haredoc references. +hi! def link haredocRefValid SpecialComment -hi def hareErrorAssertion ctermfg=red cterm=bold guifg=red gui=bold +" Highlight whitespace errors by default. +if get(g:, 'hare_space_error', 1) + hi def link hareSpaceError Error +endif -" vim: tabstop=8 shiftwidth=2 expandtab +" vim: et sts=2 sw=2 ts=8 diff --git a/runtime/syntax/haredoc.vim b/runtime/syntax/haredoc.vim new file mode 100644 index 0000000000..09c99c1d56 --- /dev/null +++ b/runtime/syntax/haredoc.vim @@ -0,0 +1,32 @@ +" Vim syntax file. +" Language: Haredoc (Hare documentation format) +" Maintainer: Amelia Clarke <selene@perilune.dev> +" Last Change: 2024-05-10 +" Upstream: https://git.sr.ht/~selene/hare.vim + +if exists('b:current_syntax') + finish +endif +let b:current_syntax = 'haredoc' + +" Syntax {{{1 +syn case match +syn iskeyword @,48-57,_ + +" Code samples. +syn region haredocCodeSample excludenl start='\t\zs' end='$' contains=@NoSpell display + +" References to other declarations and modules. +syn region haredocRef start='\[\[' end=']]' contains=haredocRefValid,@NoSpell display keepend oneline +syn match haredocRefValid '\v\[\[\h\w*%(::\h\w*)*%(::)?]]' contained contains=@NoSpell display + +" Miscellaneous. +syn keyword haredocTodo FIXME TODO XXX + +" Default highlighting {{{1 +hi def link haredocCodeSample Comment +hi def link haredocRef Error +hi def link haredocRefValid Special +hi def link haredocTodo Todo + +" vim: et sts=2 sw=2 ts=8 diff --git a/runtime/syntax/i3config.vim b/runtime/syntax/i3config.vim index f4d789e418..c95cb879ad 100644 --- a/runtime/syntax/i3config.vim +++ b/runtime/syntax/i3config.vim @@ -2,8 +2,8 @@ " Language: i3 config file " Original Author: Josef Litos (JosefLitos/i3config.vim) " Maintainer: Quentin Hibon (github user hiqua) -" Version: 1.2.3 -" Last Change: 2024-05-23 +" Version: 1.2.4 +" Last Change: 2024-05-24 " References: " http://i3wm.org/docs/userguide.html#configuring @@ -67,7 +67,7 @@ syn keyword i3ConfigBindKeyword bindsym bindcode contained skipwhite nextgroup=i syn region i3ConfigModeBlock matchgroup=i3ConfigKeyword start=/mode\ze\( --pango_markup\)\? \([^'" {]\+\|'[^']\+'\|".\+"\)\s\+{$/ end=/^}\zs$/ contained contains=i3ConfigShParam,@i3ConfigStrVar,i3ConfigBindKeyword,i3ConfigComment,i3ConfigParen fold keepend extend " 4.7 Floating modifier -syn match i3ConfigKeyword /^floating_modifier [$0-9A-Za-z]*$/ contains=i3ConfigVariable,i3ConfigBindModkey +syn match i3ConfigKeyword /floating_modifier [$A-Z][0-9A-Za-z]*$/ contained contains=i3ConfigVariable,i3ConfigBindModkey " 4.8 Floating window size syn keyword i3ConfigSizeSpecial x contained diff --git a/runtime/syntax/shared/debversions.vim b/runtime/syntax/shared/debversions.vim index e18eca96b1..56f18b969a 100644 --- a/runtime/syntax/shared/debversions.vim +++ b/runtime/syntax/shared/debversions.vim @@ -1,7 +1,7 @@ " Vim syntax file " Language: Debian version information " Maintainer: Debian Vim Maintainers -" Last Change: 2024 Apr 27 +" Last Change: 2024 May 25 " URL: https://salsa.debian.org/vim-team/vim-debian/blob/main/syntax/shared/debversions.vim let s:cpo = &cpo @@ -11,7 +11,7 @@ let g:debSharedSupportedVersions = [ \ 'oldstable', 'stable', 'testing', 'unstable', 'experimental', 'sid', 'rc-buggy', \ 'bullseye', 'bookworm', 'trixie', 'forky', \ - \ 'trusty', 'xenial', 'bionic', 'focal', 'jammy', 'mantic', 'noble', 'oracular', + \ 'focal', 'jammy', 'mantic', 'noble', 'oracular', \ 'devel' \ ] let g:debSharedUnsupportedVersions = [ @@ -22,8 +22,9 @@ let g:debSharedUnsupportedVersions = [ \ 'warty', 'hoary', 'breezy', 'dapper', 'edgy', 'feisty', \ 'gutsy', 'hardy', 'intrepid', 'jaunty', 'karmic', 'lucid', \ 'maverick', 'natty', 'oneiric', 'precise', 'quantal', 'raring', 'saucy', - \ 'utopic', 'vivid', 'wily', 'yakkety', 'zesty', 'artful', 'cosmic', - \ 'disco', 'eoan', 'hirsute', 'impish', 'kinetic', 'lunar', 'groovy' + \ 'trusty', 'utopic', 'vivid', 'wily', 'xenial', 'yakkety', 'zesty', + \ 'artful', 'bionic', 'cosmic', 'disco', 'eoan', 'hirsute', + \ 'impish', 'kinetic', 'lunar', 'groovy' \ ] let &cpo=s:cpo diff --git a/runtime/syntax/shared/typescriptcommon.vim b/runtime/syntax/shared/typescriptcommon.vim index d06525115e..3af79a38fb 100644 --- a/runtime/syntax/shared/typescriptcommon.vim +++ b/runtime/syntax/shared/typescriptcommon.vim @@ -1,7 +1,7 @@ " Vim syntax file " Language: TypeScript and TypeScriptReact " Maintainer: Herrington Darkholme -" Last Change: 2023 Aug 24 +" Last Change: 2024 May 24 " Based On: Herrington Darkholme's yats.vim " Changes: See https://github.com/HerringtonDarkholme/yats.vim " Credits: See yats.vim on github @@ -49,13 +49,13 @@ syntax match typescriptProp contained /\K\k*!\?/ \ nextgroup=@afterIdentifier \ skipwhite skipempty -syntax region typescriptIndexExpr contained matchgroup=typescriptProperty start=/\[/rs=s+1 end=/]/he=e-1 contains=@typescriptValue nextgroup=@typescriptSymbols,typescriptDotNotation,typescriptFuncCallArg skipwhite skipempty +syntax region typescriptIndexExpr contained matchgroup=typescriptProperty start=/\[/ end=/]/ contains=@typescriptValue,typescriptCastKeyword nextgroup=@typescriptSymbols,typescriptDotNotation,typescriptFuncCallArg skipwhite skipempty syntax match typescriptDotNotation /\.\|?\.\|!\./ nextgroup=typescriptProp skipnl syntax match typescriptDotStyleNotation /\.style\./ nextgroup=typescriptDOMStyle transparent " syntax match typescriptFuncCall contained /[a-zA-Z]\k*\ze(/ nextgroup=typescriptFuncCallArg syntax region typescriptParenExp matchgroup=typescriptParens start=/(/ end=/)/ contains=@typescriptComments,@typescriptValue,typescriptCastKeyword nextgroup=@typescriptSymbols skipwhite skipempty -syntax region typescriptFuncCallArg contained matchgroup=typescriptParens start=/(/ end=/)/ contains=@typescriptValue,@typescriptComments nextgroup=@typescriptSymbols,typescriptDotNotation skipwhite skipempty skipnl +syntax region typescriptFuncCallArg contained matchgroup=typescriptParens start=/(/ end=/)/ contains=@typescriptValue,@typescriptComments,typescriptCastKeyword nextgroup=@typescriptSymbols,typescriptDotNotation skipwhite skipempty skipnl syntax region typescriptEventFuncCallArg contained matchgroup=typescriptParens start=/(/ end=/)/ contains=@typescriptEventExpression syntax region typescriptEventString contained start=/\z(["']\)/ skip=/\\\\\|\\\z1\|\\\n/ end=/\z1\|$/ contains=typescriptASCII,@events @@ -116,20 +116,33 @@ syntax match typescriptASCII contained /\\\d\d\d/ syntax region typescriptTemplateSubstitution matchgroup=typescriptTemplateSB \ start=/\${/ end=/}/ - \ contains=@typescriptValue + \ contains=@typescriptValue,typescriptCastKeyword \ contained -syntax region typescriptString +syntax region typescriptString \ start=+\z(["']\)+ skip=+\\\%(\z1\|$\)+ end=+\z1+ end=+$+ \ contains=typescriptSpecial,@Spell + \ nextgroup=@typescriptSymbols + \ skipwhite skipempty \ extend syntax match typescriptSpecial contained "\v\\%(x\x\x|u%(\x{4}|\{\x{1,6}})|c\u|.)" -" From vim runtime -" <https://github.com/vim/vim/blob/master/runtime/syntax/javascript.vim#L48> -syntax region typescriptRegexpString start=+/[^/*]+me=e-1 skip=+\\\\\|\\/+ end=+/[gimuy]\{0,5\}\s*$+ end=+/[gimuy]\{0,5\}\s*[;.,)\]}:]+me=e-1 nextgroup=typescriptDotNotation oneline +" From pangloss/vim-javascript +" <https://github.com/pangloss/vim-javascript/blob/d6e137563c47fb59f26ed25d044c0c7532304f18/syntax/javascript.vim#L64-L72> +syntax region typescriptRegexpCharClass contained start=+\[+ skip=+\\.+ end=+\]+ contains=typescriptSpecial extend +syntax match typescriptRegexpBoundary contained "\v\c[$^]|\\b" +syntax match typescriptRegexpBackRef contained "\v\\[1-9]\d*" +syntax match typescriptRegexpQuantifier contained "\v[^\\]%([?*+]|\{\d+%(,\d*)?})\??"lc=1 +syntax match typescriptRegexpOr contained "|" +syntax match typescriptRegexpMod contained "\v\(\?[:=!>]"lc=1 +syntax region typescriptRegexpGroup contained start="[^\\]("lc=1 skip="\\.\|\[\(\\.\|[^]]\+\)\]" end=")" contains=typescriptRegexpCharClass,@typescriptRegexpSpecial keepend +syntax region typescriptRegexpString + \ start=+\%(\%(\<return\|\<typeof\|\_[^)\]'"[:blank:][:alnum:]_$]\)\s*\)\@<=/\ze[^*/]+ skip=+\\.\|\[[^]]\{1,}\]+ end=+/[gimyus]\{,6}+ + \ contains=typescriptRegexpCharClass,typescriptRegexpGroup,@typescriptRegexpSpecial + \ oneline keepend extend +syntax cluster typescriptRegexpSpecial contains=typescriptSpecial,typescriptRegexpBoundary,typescriptRegexpBackRef,typescriptRegexpQuantifier,typescriptRegexpOr,typescriptRegexpMod syntax region typescriptTemplate \ start=/`/ skip=/\\\\\|\\`\|\n/ end=/`\|$/ @@ -140,7 +153,7 @@ syntax region typescriptTemplate "Array syntax region typescriptArray matchgroup=typescriptBraces \ start=/\[/ end=/]/ - \ contains=@typescriptValue,@typescriptComments + \ contains=@typescriptValue,@typescriptComments,typescriptCastKeyword \ nextgroup=@typescriptSymbols,typescriptDotNotation \ skipwhite skipempty fold @@ -153,7 +166,7 @@ syntax match typescriptNumber /\<\%(\d[0-9_]*\%(\.\d[0-9_]*\)\=\|\.\d[0-9_]*\)\% syntax region typescriptObjectLiteral matchgroup=typescriptBraces \ start=/{/ end=/}/ - \ contains=@typescriptComments,typescriptObjectLabel,typescriptStringProperty,typescriptComputedPropertyName,typescriptObjectAsyncKeyword + \ contains=@typescriptComments,typescriptObjectLabel,typescriptStringProperty,typescriptComputedPropertyName,typescriptObjectAsyncKeyword,typescriptTernary,typescriptCastKeyword \ fold contained syntax keyword typescriptObjectAsyncKeyword async contained @@ -223,11 +236,11 @@ syntax match typescriptBinaryOp contained /\*\*=\?/ nextgroup=@typescriptValue syntax cluster typescriptSymbols contains=typescriptBinaryOp,typescriptKeywordOp,typescriptTernary,typescriptAssign,typescriptCastKeyword -" runtime syntax/basic/reserved.vim +" runtime syntax/ts-common/reserved.vim "Import syntax keyword typescriptImport from as syntax keyword typescriptImport import - \ nextgroup=typescriptImportType + \ nextgroup=typescriptImportType,typescriptTypeBlock,typescriptDefaultImportName \ skipwhite syntax keyword typescriptImportType type \ contained @@ -238,20 +251,11 @@ syntax match typescriptExportType /\<type\s*{\@=/ \ contained skipwhite skipempty skipnl syntax keyword typescriptModule namespace module -"this - -"JavaScript Prototype -syntax keyword typescriptPrototype prototype - \ nextgroup=@afterIdentifier -syntax keyword typescriptCastKeyword as +syntax keyword typescriptCastKeyword as satisfies \ nextgroup=@typescriptType \ skipwhite -"Program Keywords -syntax keyword typescriptIdentifier arguments this super - \ nextgroup=@afterIdentifier - syntax keyword typescriptVariable let var \ nextgroup=@typescriptVariableDeclarations \ skipwhite skipempty @@ -260,6 +264,10 @@ syntax keyword typescriptVariable const \ nextgroup=typescriptEnum,@typescriptVariableDeclarations \ skipwhite skipempty +syntax keyword typescriptUsing using + \ nextgroup=@typescriptVariableDeclarations + \ skipwhite skipempty + syntax region typescriptEnum matchgroup=typescriptEnumKeyword start=/enum / end=/\ze{/ \ nextgroup=typescriptBlock \ skipwhite @@ -272,7 +280,6 @@ syntax keyword typescriptOperator delete new typeof void syntax keyword typescriptForOperator contained in of syntax keyword typescriptBoolean true false nextgroup=@typescriptSymbols skipwhite skipempty -syntax keyword typescriptNull null undefined nextgroup=@typescriptSymbols skipwhite skipempty syntax keyword typescriptMessage alert confirm prompt status \ nextgroup=typescriptDotNotation,typescriptFuncCallArg syntax keyword typescriptGlobal self top parent @@ -290,10 +297,10 @@ syntax keyword typescriptCase case nextgroup=@typescriptPrimiti syntax keyword typescriptDefault default containedin=typescriptBlock nextgroup=@typescriptValue,typescriptClassKeyword,typescriptInterfaceKeyword skipwhite oneline syntax keyword typescriptStatementKeyword with syntax keyword typescriptStatementKeyword yield skipwhite nextgroup=@typescriptValue containedin=typescriptBlock -syntax keyword typescriptStatementKeyword return skipwhite contained nextgroup=@typescriptValue containedin=typescriptBlock syntax keyword typescriptTry try -syntax keyword typescriptExceptions catch throw finally +syntax keyword typescriptExceptions throw finally +syntax keyword typescriptExceptions catch nextgroup=typescriptCall skipwhite skipempty oneline syntax keyword typescriptDebugger debugger syntax keyword typescriptAsyncFor await nextgroup=typescriptLoopParen skipwhite skipempty contained @@ -321,6 +328,24 @@ syntax cluster typescriptAmbients contains= \ typescriptEnumKeyword,typescriptEnum, \ typescriptModule +syntax keyword typescriptIdentifier arguments nextgroup=@afterIdentifier +syntax match typescriptDefaultImportName /\v\h\k*( |,)/ + \ contained + \ nextgroup=typescriptTypeBlock + \ skipwhite skipempty + +syntax region typescriptTypeBlock + \ matchgroup=typescriptBraces + \ start=/{/ end=/}/ + \ contained + \ contains=typescriptIdentifierName,typescriptImportType + \ fold + +"Program Keywords +syntax keyword typescriptNull null undefined nextgroup=@typescriptSymbols skipwhite skipempty +syntax keyword typescriptIdentifier this super prototype nextgroup=@afterIdentifier +syntax keyword typescriptStatementKeyword return skipwhite contained nextgroup=@typescriptValue containedin=typescriptBlock + "Syntax coloring for Node.js shebang line syntax match shellbang "^#!.*node\>" syntax match shellbang "^#!.*iojs\>" @@ -536,7 +561,7 @@ syntax region typescriptGenericFunc matchgroup=typescriptTypeBrackets \ contained skipwhite skipnl syntax region typescriptFuncType matchgroup=typescriptParens - \ start=/(/ end=/)\s*=>/me=e-2 + \ start=/(\(\k\+:\|)\)\@=/ end=/)\s*=>/me=e-2 \ contains=@typescriptParameterList \ nextgroup=typescriptFuncTypeArrow \ contained skipwhite skipnl oneline @@ -546,7 +571,6 @@ syntax match typescriptFuncTypeArrow /=>/ \ containedin=typescriptFuncType \ contained skipwhite skipnl - syntax keyword typescriptConstructorType new \ nextgroup=@typescriptFunctionType \ contained skipwhite skipnl @@ -623,25 +647,24 @@ syntax keyword typescriptReadonlyArrayKeyword readonly " extension -if get(g:, 'yats_host_keyword', 1) - syntax keyword typescriptGlobal containedin=typescriptIdentifierName Function Boolean - " use of nextgroup Suggested by Doug Kearns +if get(g:, 'typescript_host_keyword', 1) + syntax keyword typescriptGlobal containedin=typescriptIdentifierName Function Boolean nextgroup=typescriptFuncCallArg syntax keyword typescriptGlobal containedin=typescriptIdentifierName Error EvalError nextgroup=typescriptFuncCallArg - syntax keyword typescriptGlobal containedin=typescriptIdentifierName InternalError - syntax keyword typescriptGlobal containedin=typescriptIdentifierName RangeError ReferenceError - syntax keyword typescriptGlobal containedin=typescriptIdentifierName StopIteration - syntax keyword typescriptGlobal containedin=typescriptIdentifierName SyntaxError TypeError - syntax keyword typescriptGlobal containedin=typescriptIdentifierName URIError Date - syntax keyword typescriptGlobal containedin=typescriptIdentifierName Float32Array - syntax keyword typescriptGlobal containedin=typescriptIdentifierName Float64Array - syntax keyword typescriptGlobal containedin=typescriptIdentifierName Int16Array Int32Array - syntax keyword typescriptGlobal containedin=typescriptIdentifierName Int8Array Uint16Array - syntax keyword typescriptGlobal containedin=typescriptIdentifierName Uint32Array Uint8Array - syntax keyword typescriptGlobal containedin=typescriptIdentifierName Uint8ClampedArray - syntax keyword typescriptGlobal containedin=typescriptIdentifierName ParallelArray - syntax keyword typescriptGlobal containedin=typescriptIdentifierName ArrayBuffer DataView - syntax keyword typescriptGlobal containedin=typescriptIdentifierName Iterator Generator - syntax keyword typescriptGlobal containedin=typescriptIdentifierName Reflect Proxy + syntax keyword typescriptGlobal containedin=typescriptIdentifierName InternalError nextgroup=typescriptFuncCallArg + syntax keyword typescriptGlobal containedin=typescriptIdentifierName RangeError ReferenceError nextgroup=typescriptFuncCallArg + syntax keyword typescriptGlobal containedin=typescriptIdentifierName StopIteration nextgroup=typescriptFuncCallArg + syntax keyword typescriptGlobal containedin=typescriptIdentifierName SyntaxError TypeError nextgroup=typescriptFuncCallArg + syntax keyword typescriptGlobal containedin=typescriptIdentifierName URIError Date nextgroup=typescriptFuncCallArg + syntax keyword typescriptGlobal containedin=typescriptIdentifierName Float32Array nextgroup=typescriptFuncCallArg + syntax keyword typescriptGlobal containedin=typescriptIdentifierName Float64Array nextgroup=typescriptFuncCallArg + syntax keyword typescriptGlobal containedin=typescriptIdentifierName Int16Array Int32Array nextgroup=typescriptFuncCallArg + syntax keyword typescriptGlobal containedin=typescriptIdentifierName Int8Array Uint16Array nextgroup=typescriptFuncCallArg + syntax keyword typescriptGlobal containedin=typescriptIdentifierName Uint32Array Uint8Array nextgroup=typescriptFuncCallArg + syntax keyword typescriptGlobal containedin=typescriptIdentifierName Uint8ClampedArray nextgroup=typescriptFuncCallArg + syntax keyword typescriptGlobal containedin=typescriptIdentifierName ParallelArray nextgroup=typescriptFuncCallArg + syntax keyword typescriptGlobal containedin=typescriptIdentifierName ArrayBuffer DataView nextgroup=typescriptFuncCallArg + syntax keyword typescriptGlobal containedin=typescriptIdentifierName Iterator Generator nextgroup=typescriptFuncCallArg + syntax keyword typescriptGlobal containedin=typescriptIdentifierName Reflect Proxy nextgroup=typescriptFuncCallArg syntax keyword typescriptGlobal containedin=typescriptIdentifierName arguments hi def link typescriptGlobal Structure syntax keyword typescriptGlobalMethod containedin=typescriptIdentifierName eval uneval nextgroup=typescriptFuncCallArg @@ -675,12 +698,12 @@ if get(g:, 'yats_host_keyword', 1) hi def link typescriptStringStaticMethod Keyword syntax keyword typescriptStringMethod contained anchor charAt charCodeAt codePointAt nextgroup=typescriptFuncCallArg syntax keyword typescriptStringMethod contained concat endsWith includes indexOf lastIndexOf nextgroup=typescriptFuncCallArg - syntax keyword typescriptStringMethod contained link localeCompare match normalize nextgroup=typescriptFuncCallArg - syntax keyword typescriptStringMethod contained padStart padEnd repeat replace search nextgroup=typescriptFuncCallArg + syntax keyword typescriptStringMethod contained link localeCompare match matchAll normalize nextgroup=typescriptFuncCallArg + syntax keyword typescriptStringMethod contained padStart padEnd repeat replace replaceAll search nextgroup=typescriptFuncCallArg syntax keyword typescriptStringMethod contained slice split startsWith substr substring nextgroup=typescriptFuncCallArg syntax keyword typescriptStringMethod contained toLocaleLowerCase toLocaleUpperCase nextgroup=typescriptFuncCallArg syntax keyword typescriptStringMethod contained toLowerCase toString toUpperCase trim nextgroup=typescriptFuncCallArg - syntax keyword typescriptStringMethod contained valueOf nextgroup=typescriptFuncCallArg + syntax keyword typescriptStringMethod contained trimEnd trimStart valueOf nextgroup=typescriptFuncCallArg syntax cluster props add=typescriptStringMethod hi def link typescriptStringMethod Keyword @@ -689,18 +712,18 @@ if get(g:, 'yats_host_keyword', 1) syntax keyword typescriptArrayStaticMethod contained from isArray of nextgroup=typescriptFuncCallArg hi def link typescriptArrayStaticMethod Keyword syntax keyword typescriptArrayMethod contained concat copyWithin entries every fill nextgroup=typescriptFuncCallArg - syntax keyword typescriptArrayMethod contained filter find findIndex forEach indexOf nextgroup=typescriptFuncCallArg - syntax keyword typescriptArrayMethod contained includes join keys lastIndexOf map nextgroup=typescriptFuncCallArg + syntax keyword typescriptArrayMethod contained filter find findIndex flat flatMap forEach nextgroup=typescriptFuncCallArg + syntax keyword typescriptArrayMethod contained includes indexOf join keys lastIndexOf map nextgroup=typescriptFuncCallArg syntax keyword typescriptArrayMethod contained pop push reduce reduceRight reverse nextgroup=typescriptFuncCallArg syntax keyword typescriptArrayMethod contained shift slice some sort splice toLocaleString nextgroup=typescriptFuncCallArg - syntax keyword typescriptArrayMethod contained toSource toString unshift nextgroup=typescriptFuncCallArg + syntax keyword typescriptArrayMethod contained toSource toString unshift values nextgroup=typescriptFuncCallArg syntax cluster props add=typescriptArrayMethod hi def link typescriptArrayMethod Keyword syntax keyword typescriptGlobal containedin=typescriptIdentifierName Object nextgroup=typescriptGlobalObjectDot,typescriptFuncCallArg syntax match typescriptGlobalObjectDot /\./ contained nextgroup=typescriptObjectStaticMethod,typescriptProp syntax keyword typescriptObjectStaticMethod contained create defineProperties defineProperty nextgroup=typescriptFuncCallArg - syntax keyword typescriptObjectStaticMethod contained entries freeze getOwnPropertyDescriptors nextgroup=typescriptFuncCallArg + syntax keyword typescriptObjectStaticMethod contained entries freeze fromEntries getOwnPropertyDescriptors nextgroup=typescriptFuncCallArg syntax keyword typescriptObjectStaticMethod contained getOwnPropertyDescriptor getOwnPropertyNames nextgroup=typescriptFuncCallArg syntax keyword typescriptObjectStaticMethod contained getOwnPropertySymbols getPrototypeOf nextgroup=typescriptFuncCallArg syntax keyword typescriptObjectStaticMethod contained is isExtensible isFrozen isSealed nextgroup=typescriptFuncCallArg @@ -715,7 +738,7 @@ if get(g:, 'yats_host_keyword', 1) syntax keyword typescriptGlobal containedin=typescriptIdentifierName Symbol nextgroup=typescriptGlobalSymbolDot,typescriptFuncCallArg syntax match typescriptGlobalSymbolDot /\./ contained nextgroup=typescriptSymbolStaticProp,typescriptSymbolStaticMethod,typescriptProp - syntax keyword typescriptSymbolStaticProp contained length iterator match replace + syntax keyword typescriptSymbolStaticProp contained description length iterator match matchAll replace syntax keyword typescriptSymbolStaticProp contained search split hasInstance isConcatSpreadable syntax keyword typescriptSymbolStaticProp contained unscopables species toPrimitive syntax keyword typescriptSymbolStaticProp contained toStringTag @@ -771,7 +794,7 @@ if get(g:, 'yats_host_keyword', 1) syntax match typescriptGlobalRegExpDot /\./ contained nextgroup=typescriptRegExpStaticProp,typescriptProp syntax keyword typescriptRegExpStaticProp contained lastIndex hi def link typescriptRegExpStaticProp Keyword - syntax keyword typescriptRegExpProp contained global ignoreCase multiline source sticky + syntax keyword typescriptRegExpProp contained dotAll global ignoreCase multiline source sticky syntax cluster props add=typescriptRegExpProp hi def link typescriptRegExpProp Keyword syntax keyword typescriptRegExpMethod contained exec test nextgroup=typescriptFuncCallArg @@ -805,7 +828,7 @@ if get(g:, 'yats_host_keyword', 1) syntax keyword typescriptGlobal containedin=typescriptIdentifierName Promise nextgroup=typescriptGlobalPromiseDot,typescriptFuncCallArg syntax match typescriptGlobalPromiseDot /\./ contained nextgroup=typescriptPromiseStaticMethod,typescriptProp - syntax keyword typescriptPromiseStaticMethod contained resolve reject all race nextgroup=typescriptFuncCallArg + syntax keyword typescriptPromiseStaticMethod contained all allSettled any race reject resolve nextgroup=typescriptFuncCallArg hi def link typescriptPromiseStaticMethod Keyword syntax keyword typescriptPromiseMethod contained then catch finally nextgroup=typescriptFuncCallArg syntax cluster props add=typescriptPromiseMethod @@ -1232,7 +1255,8 @@ if get(g:, 'yats_host_keyword', 1) syntax cluster props add=typescriptBOMHistoryMethod hi def link typescriptBOMHistoryMethod Keyword - syntax keyword typescriptGlobal containedin=typescriptIdentifierName console + syntax keyword typescriptGlobal containedin=typescriptIdentifierName console nextgroup=typescriptGlobalConsoleDot + syntax match typescriptGlobalConsoleDot /\./ contained nextgroup=typescriptConsoleMethod,typescriptProp syntax keyword typescriptConsoleMethod contained count dir error group groupCollapsed nextgroup=typescriptFuncCallArg syntax keyword typescriptConsoleMethod contained groupEnd info log time timeEnd trace nextgroup=typescriptFuncCallArg syntax keyword typescriptConsoleMethod contained warn nextgroup=typescriptFuncCallArg @@ -1735,8 +1759,6 @@ if get(g:, 'yats_host_keyword', 1) syntax keyword typescriptServiceWorkerEvent contained install activate fetch syntax cluster events add=typescriptServiceWorkerEvent hi def link typescriptServiceWorkerEvent Title - - endif " patch @@ -1764,6 +1786,7 @@ syntax cluster typescriptPropertyMemberDeclaration contains= \ typescriptClassStatic, \ typescriptAccessibilityModifier, \ typescriptReadonlyModifier, + \ typescriptAutoAccessor, \ typescriptMethodAccessor, \ @typescriptMembers " \ typescriptMemberVariableDeclaration @@ -1780,7 +1803,9 @@ syntax keyword typescriptClassStatic static syntax keyword typescriptAccessibilityModifier public private protected contained -syntax keyword typescriptReadonlyModifier readonly contained +syntax keyword typescriptReadonlyModifier readonly override contained + +syntax keyword typescriptAutoAccessor accessor contained syntax region typescriptStringMember contained \ start=/\z(["']\)/ skip=/\\\\\|\\\z1\|\\\n/ end=/\z1/ @@ -1789,7 +1814,7 @@ syntax region typescriptStringMember contained syntax region typescriptComputedMember contained matchgroup=typescriptProperty \ start=/\[/rs=s+1 end=/]/ - \ contains=@typescriptValue,typescriptMember,typescriptMappedIn + \ contains=@typescriptValue,typescriptMember,typescriptMappedIn,typescriptCastKeyword \ nextgroup=@memberNextGroup \ skipwhite skipempty @@ -1861,7 +1886,7 @@ syntax match typescriptInterfaceComma /,/ contained nextgroup=typescriptInterfac "Block VariableStatement EmptyStatement ExpressionStatement IfStatement IterationStatement ContinueStatement BreakStatement ReturnStatement WithStatement LabelledStatement SwitchStatement ThrowStatement TryStatement DebuggerStatement syntax cluster typescriptStatement - \ contains=typescriptBlock,typescriptVariable, + \ contains=typescriptBlock,typescriptVariable,typescriptUsing, \ @typescriptTopExpression,typescriptAssign, \ typescriptConditional,typescriptRepeat,typescriptBranch, \ typescriptLabel,typescriptStatementKeyword, @@ -1899,16 +1924,14 @@ syntax cluster typescriptValue syntax cluster typescriptEventExpression contains=typescriptArrowFuncDef,typescriptParenExp,@typescriptValue,typescriptRegexpString,@typescriptEventTypes,typescriptOperator,typescriptGlobal,jsxRegion syntax keyword typescriptAsyncFuncKeyword async - \ nextgroup=typescriptFuncKeyword,typescriptArrowFuncDef + \ nextgroup=typescriptFuncKeyword,typescriptArrowFuncDef,typescriptArrowFuncTypeParameter \ skipwhite syntax keyword typescriptAsyncFuncKeyword await - \ nextgroup=@typescriptValue + \ nextgroup=@typescriptValue,typescriptUsing \ skipwhite -syntax keyword typescriptFuncKeyword function - \ nextgroup=typescriptAsyncFunc,typescriptFuncName,@typescriptCallSignature - \ skipwhite skipempty +syntax keyword typescriptFuncKeyword function nextgroup=typescriptAsyncFunc,typescriptFuncName,@typescriptCallSignature skipwhite skipempty syntax match typescriptAsyncFunc contained /*/ \ nextgroup=typescriptFuncName,@typescriptCallSignature @@ -1918,39 +1941,33 @@ syntax match typescriptFuncName contained /\K\k*/ \ nextgroup=@typescriptCallSignature \ skipwhite -" destructuring ({ a: ee }) => -syntax match typescriptArrowFuncDef contained /(\(\s*\({\_[^}]*}\|\k\+\)\(:\_[^)]\)\?,\?\)\+)\s*=>/ - \ contains=typescriptArrowFuncArg,typescriptArrowFunc - \ nextgroup=@typescriptExpression,typescriptBlock - \ skipwhite skipempty - -" matches `(a) =>` or `([a]) =>` or -" `( -" a) =>` -syntax match typescriptArrowFuncDef contained /(\(\_s*[a-zA-Z\$_\[.]\_[^)]*\)*)\s*=>/ +syntax match typescriptArrowFuncDef contained /\K\k*\s*=>/ \ contains=typescriptArrowFuncArg,typescriptArrowFunc \ nextgroup=@typescriptExpression,typescriptBlock \ skipwhite skipempty -syntax match typescriptArrowFuncDef contained /\K\k*\s*=>/ - \ contains=typescriptArrowFuncArg,typescriptArrowFunc +syntax match typescriptArrowFuncDef contained /(\%(\_[^()]\+\|(\_[^()]*)\)*)\_s*=>/ + \ contains=typescriptArrowFuncArg,typescriptArrowFunc,@typescriptCallSignature \ nextgroup=@typescriptExpression,typescriptBlock \ skipwhite skipempty -" TODO: optimize this pattern -syntax region typescriptArrowFuncDef contained start=/(\_[^(^)]*):/ end=/=>/ - \ contains=typescriptArrowFuncArg,typescriptArrowFunc,typescriptTypeAnnotation +syntax region typescriptArrowFuncDef contained start=/(\%(\_[^()]\+\|(\_[^()]*)\)*):/ matchgroup=typescriptArrowFunc end=/=>/ + \ contains=typescriptArrowFuncArg,typescriptTypeAnnotation,@typescriptCallSignature \ nextgroup=@typescriptExpression,typescriptBlock \ skipwhite skipempty keepend +syntax region typescriptArrowFuncTypeParameter start=/</ end=/>/ + \ contains=@typescriptTypeParameterCluster + \ nextgroup=typescriptArrowFuncDef + \ contained skipwhite skipnl + syntax match typescriptArrowFunc /=>/ syntax match typescriptArrowFuncArg contained /\K\k*/ -syntax region typescriptArrowFuncArg contained start=/<\|(/ end=/\ze=>/ contains=@typescriptCallSignature syntax region typescriptReturnAnnotation contained start=/:/ end=/{/me=e-1 contains=@typescriptType nextgroup=typescriptBlock -syntax region typescriptFuncImpl contained start=/function\>/ end=/{/me=e-1 +syntax region typescriptFuncImpl contained start=/function\>/ end=/{\|;\|\n/me=e-1 \ contains=typescriptFuncKeyword \ nextgroup=typescriptBlock @@ -1970,7 +1987,7 @@ syntax match typescriptDecorator /@\([_$a-zA-Z][_$a-zA-Z0-9]*\.\)*[_$a-zA-Z][_$a \ nextgroup=typescriptFuncCallArg,typescriptTypeArguments \ contains=@_semantic,typescriptDotNotation -" Define the default highlighting. + hi def link typescriptReserved Error hi def link typescriptEndColons Exception @@ -2013,6 +2030,7 @@ hi def link typescriptDefault typescriptCase hi def link typescriptBranch Conditional hi def link typescriptIdentifier Structure hi def link typescriptVariable Identifier +hi def link typescriptUsing Identifier hi def link typescriptDestructureVariable PreProc hi def link typescriptEnumKeyword Identifier hi def link typescriptRepeat Repeat @@ -2050,16 +2068,13 @@ hi def link typescriptFuncKeyword Keyword hi def link typescriptAsyncFunc Keyword hi def link typescriptArrowFunc Type hi def link typescriptFuncName Function -hi def link typescriptFuncArg PreProc +hi def link typescriptFuncCallArg PreProc hi def link typescriptArrowFuncArg PreProc hi def link typescriptFuncComma Operator hi def link typescriptClassKeyword Keyword hi def link typescriptClassExtends Keyword -" hi def link typescriptClassName Function hi def link typescriptAbstract Special -" hi def link typescriptClassHeritage Function -" hi def link typescriptInterfaceHeritage Function hi def link typescriptClassStatic StorageClass hi def link typescriptReadonlyModifier Keyword hi def link typescriptInterfaceKeyword Keyword @@ -2077,6 +2092,7 @@ hi def link typescriptFuncTypeArrow Function hi def link typescriptConstructorType Function hi def link typescriptTypeQuery Keyword hi def link typescriptAccessibilityModifier Keyword +hi def link typescriptAutoAccessor Keyword hi def link typescriptOptionalMark PreProc hi def link typescriptFuncType Special hi def link typescriptMappedIn Special diff --git a/runtime/syntax/stylus.vim b/runtime/syntax/stylus.vim index fd0f33b65a..d8bf641e60 100644 --- a/runtime/syntax/stylus.vim +++ b/runtime/syntax/stylus.vim @@ -4,17 +4,7 @@ " Filenames: *.styl, *.stylus " Based On: Tim Pope (sass.vim) " Created: Dec 14, 2011 -" Modified: Apr 29, 2024 - -if main_syntax == "css" - syn sync minlines=10 -endif - -" let b:current_syntax = "css" -" -if main_syntax == 'css' - unlet main_syntax -endif +" Modified: May 28, 2024 syn case ignore diff --git a/runtime/syntax/swayconfig.vim b/runtime/syntax/swayconfig.vim index 401412adfd..d09d476a5a 100644 --- a/runtime/syntax/swayconfig.vim +++ b/runtime/syntax/swayconfig.vim @@ -2,8 +2,8 @@ " Language: sway config file " Original Author: Josef Litos (JosefLitos/i3config.vim) " Maintainer: James Eapen <james.eapen@vai.org> -" Version: 1.2.3 -" Last Change: 2024-05-23 +" Version: 1.2.4 +" Last Change: 2024-05-24 " References: " http://i3wm.org/docs/userguide.html#configuring @@ -34,12 +34,12 @@ syn region i3ConfigBindArgument start=/--input-device=['"]/ end=/\s/ contained c syn region i3ConfigBindCombo matchgroup=i3ConfigParen start=/{$/ end=/^\s*}$/ contained contains=i3ConfigBindArgument,i3ConfigBindCombo,i3ConfigComment fold keepend extend " hack for blocks with start outside parsing range -syn region swayConfigBlockOrphan start=/^\s\+\(--[a-z-]\+ \)*\([A-Z$][$a-zA-Z0-9_+]\+\|[a-z]\) [a-z[]/ skip=/\\$\|$\n^\s*}$/ end=/$/ contains=i3ConfigBindArgument,i3ConfigBindCombo,i3ConfigParen keepend extend +syn region swayConfigBlockOrphan start=/^\s\+\(--[a-z-]\+ \)*\([$A-Z][$0-9A-Za-z_+]\+\|[a-z]\) [a-z[]/ skip=/\\$\|$\n^\s*}$/ end=/$/ contains=i3ConfigBindArgument,i3ConfigBindCombo,i3ConfigParen keepend extend syn region i3ConfigExec start=/ {$/ end=/^\s*}$/ contained contains=i3ConfigExecAction,@i3ConfigSh,i3ConfigComment fold keepend extend syn keyword swayConfigFloatingModifierOpts normal inverse none contained -syn match i3ConfigKeyword /floating_modifier \(none\|[$a-zA-Z0-9+]\+ \(normal\|inverse\)\)$/ contained contains=i3ConfigVariable,i3ConfigBindModkey,swayConfigFloatingModifierOpts +syn match i3ConfigKeyword /floating_modifier \(none\|[$A-Z][0-9A-Za-z]\+ \(normal\|inverse\)\)$/ contained contains=i3ConfigVariable,i3ConfigBindModkey,swayConfigFloatingModifierOpts syn match swayConfigI3Param /--i3/ contains=i3ConfigShParam skipwhite nextgroup=i3ConfigEdgeOpts syn keyword i3ConfigKeyword hide_edge_borders contained skipwhite nextgroup=swayConfigI3Param,i3ConfigEdgeOpts @@ -71,7 +71,7 @@ syn keyword i3ConfigBindKeyword bindswitch contained skipwhite nextgroup=swayCon syn region swayConfigBlockOrphan start=/^\s\+\(lid\|tablet\):/ skip=/\\$\|$\n^\s*}$/ end=/$/ contains=swayConfigBindswitchArgument,swayConfigBindswitchType,i3ConfigParen keepend extend " Bindgesture -syn match swayConfigBindgestureArgument /--\(exact\|input-device=[:0-9a-zA-Z_/-]\+\|no-warn\) / contained nextgroup=swayConfigBindgestureArgument,swayConfigBindgestureCombo +syn match swayConfigBindgestureArgument /--\(exact\|input-device=[:0-9A-Za-z_/-]\+\|no-warn\) / contained nextgroup=swayConfigBindgestureArgument,swayConfigBindgestureCombo syn keyword swayConfigBindgestureType hold swipe pinch contained syn keyword swayConfigBindgestureDir up down left right inward outward clockwise counterclockwise contained syn match swayConfigBindgestureCombo /\(hold\(:[1-5]\)\?\|swipe\(:[3-5]\)\?\(:up\|:down\|:left\|:right\)\?\|pinch\(:[2-5]\)\?:\(+\?\(inward\|outward\|clockwise\|counterclockwise\|up\|down\|left\|right\)\)\+\) / contained contains=i3ConfigNumber,swayConfigBindgestureType,i3ConfigColonOperator,swayConfigBindgestureDir,i3ConfigBindModifier nextgroup=swayConfigBindgestureCombo,i3ConfigBind diff --git a/runtime/syntax/typescript.vim b/runtime/syntax/typescript.vim index 5389c21497..03520fd56a 100644 --- a/runtime/syntax/typescript.vim +++ b/runtime/syntax/typescript.vim @@ -1,7 +1,7 @@ " Vim syntax file " Language: TypeScript " Maintainer: Herrington Darkholme -" Last Change: 2023 Aug 13 +" Last Change: 2024 May 24 " Based On: Herrington Darkholme's yats.vim " Changes: Go to https://github.com/HerringtonDarkholme/yats.vim for recent changes. " Origin: https://github.com/othree/yajs diff --git a/runtime/syntax/typescriptreact.vim b/runtime/syntax/typescriptreact.vim index 1c510459f5..061ec4d81e 100644 --- a/runtime/syntax/typescriptreact.vim +++ b/runtime/syntax/typescriptreact.vim @@ -1,7 +1,7 @@ " Vim syntax file " Language: TypeScript with React (JSX) " Maintainer: The Vim Project <https://github.com/vim/vim> -" Last Change: 2023 Aug 13 +" Last Change: 2024 May 26 " Based On: Herrington Darkholme's yats.vim " Changes: See https://github.com/HerringtonDarkholme/yats.vim " Credits: See yats.vim on github @@ -118,13 +118,14 @@ syntax match tsxEqual +=+ display contained " <tag id="sample"> " s~~~~~~e -syntax region tsxString contained start=+"+ end=+"+ contains=tsxEntity,@Spell display +syntax region tsxString contained start=+"+ skip=+\\"+ end=+"+ contains=tsxEntity,@Spell display +syntax region tsxString contained start=+'+ skip=+\\'+ end=+'+ contains=tsxEntity,@Spell display " <tag key={this.props.key}> " s~~~~~~~~~~~~~~e syntax region tsxEscJs \ contained - \ contains=@typescriptValue,@tsxComment + \ contains=@typescriptValue,@tsxComment,typescriptObjectSpread \ matchgroup=typescriptBraces \ start=+{+ \ end=+}+ diff --git a/runtime/syntax/vim.vim b/runtime/syntax/vim.vim index 4fc640bab1..22c1e16a30 100644 --- a/runtime/syntax/vim.vim +++ b/runtime/syntax/vim.vim @@ -60,7 +60,8 @@ syn case ignore syn keyword vimGroup contained Comment Constant String Character Number Boolean Float Identifier Function Statement Conditional Repeat Label Operator Keyword Exception PreProc Include Define Macro PreCondit Type StorageClass Structure Typedef Special SpecialChar Tag Delimiter SpecialComment Debug Underlined Ignore Error Todo " Default highlighting groups {{{2 -syn keyword vimHLGroup contained ErrorMsg IncSearch ModeMsg NonText StatusLine StatusLineNC EndOfBuffer VertSplit DiffText PmenuSbar TabLineSel TabLineFill Cursor lCursor QuickFixLine CursorLineSign CursorLineFold CurSearch PmenuKind PmenuKindSel PmenuExtra PmenuExtraSel Normal Directory LineNr CursorLineNr MoreMsg Question Search SpellBad SpellCap SpellRare SpellLocal PmenuThumb Pmenu PmenuSel SpecialKey Title WarningMsg WildMenu Folded FoldColumn SignColumn Visual DiffAdd DiffChange DiffDelete TabLine CursorColumn CursorLine ColorColumn Conceal MatchParen CursorIM LineNrAbove LineNrBelow +syn keyword vimHLGroup contained ErrorMsg IncSearch ModeMsg NonText StatusLine StatusLineNC EndOfBuffer VertSplit DiffText PmenuSbar TabLineSel TabLineFill Cursor lCursor QuickFixLine CursorLineSign CursorLineFold CurSearch PmenuKind PmenuKindSel PmenuExtra PmenuExtraSel Normal Directory LineNr CursorLineNr MoreMsg Question Search SpellBad SpellCap SpellRare SpellLocal PmenuThumb Pmenu PmenuSel SpecialKey Title WarningMsg WildMenu Folded FoldColumn SignColumn Visual DiffAdd DiffChange DiffDelete TabLine CursorColumn CursorLine ColorColumn MatchParen CursorIM LineNrAbove LineNrBelow +syn match vimHLGroup contained "\<Conceal\>" syn keyword vimOnlyHLGroup contained Menu Scrollbar StatusLineTerm StatusLineTermNC ToolbarButton ToolbarLine Tooltip VisualNOS syn keyword nvimHLGroup contained FloatBorder FloatFooter FloatTitle MsgSeparator NormalFloat NormalNC Substitute TermCursor TermCursorNC VisualNC Whitespace WinBar WinBarNC WinSeparator "}}}2 diff --git a/scripts/gen_help_html.lua b/scripts/gen_help_html.lua index cdfb85bde6..722efc489f 100644 --- a/scripts/gen_help_html.lua +++ b/scripts/gen_help_html.lua @@ -1372,7 +1372,7 @@ function M.validate(help_dir, include, parser_path) parser_path = parser_path and vim.fn.expand(parser_path) or nil for _, f in ipairs(helpfiles) do - local helpfile = assert(vim.fs.basename(f)) + local helpfile = vim.fs.basename(f) local rv = validate_one(f, parser_path) print(('validated (%-4s errors): %s'):format(#rv.parse_errors, helpfile)) if #rv.parse_errors > 0 then @@ -1430,16 +1430,14 @@ end --- :help files, we can be precise about the tolerances here. --- @param help_dir? string e.g. '$VIMRUNTIME/doc' or './runtime/doc' function M.test_gen(help_dir) - local tmpdir = assert(vim.fs.dirname(vim.fn.tempname())) + local tmpdir = vim.fs.dirname(vim.fn.tempname()) help_dir = vim.fn.expand(help_dir or '$VIMRUNTIME/doc') print('doc path = ' .. vim.uv.fs_realpath(help_dir)) - local rv = M.gen( - help_dir, - tmpdir, - -- Because gen() is slow (~30s), this test is limited to a few files. - { 'help.txt', 'index.txt', 'nvim.txt' } - ) + -- Because gen() is slow (~30s), this test is limited to a few files. + local input = { 'help.txt', 'index.txt', 'nvim.txt' } + local rv = M.gen(help_dir, tmpdir, input) + eq(#input, #rv.helpfiles) eq(0, rv.err_count, 'parse errors in :help docs') eq({}, rv.invalid_links, 'invalid tags in :help docs') end diff --git a/scripts/gen_vimdoc.lua b/scripts/gen_vimdoc.lua index d85089116e..dac6c6f461 100755 --- a/scripts/gen_vimdoc.lua +++ b/scripts/gen_vimdoc.lua @@ -814,7 +814,7 @@ local function get_script_path() end local script_path = get_script_path() -local base_dir = vim.fs.dirname(assert(vim.fs.dirname(script_path))) +local base_dir = vim.fs.dirname(vim.fs.dirname(script_path)) local function delete_lines_below(doc_file, tokenstr) local lines = {} --- @type string[] @@ -966,7 +966,7 @@ local function gen_target(cfg) end end -- FIXME: Using f_base will confuse `_meta/protocol.lua` with `protocol.lua` - local f_base = assert(vim.fs.basename(f)) + local f_base = vim.fs.basename(f) sections[f_base] = make_section(f_base, cfg, briefs_txt, funs_txt) end diff --git a/scripts/luacats_parser.lua b/scripts/luacats_parser.lua index cb301b32e4..66fe8ed616 100644 --- a/scripts/luacats_parser.lua +++ b/scripts/luacats_parser.lua @@ -458,7 +458,7 @@ local function dump_uncommitted(filename, uncommitted) local out_path = 'luacats-uncommited/' .. filename:gsub('/', '%%') .. '.txt' if #uncommitted > 0 then print(string.format('Could not commit %d objects in %s', #uncommitted, filename)) - vim.fn.mkdir(assert(vim.fs.dirname(out_path)), 'p') + vim.fn.mkdir(vim.fs.dirname(out_path), 'p') local f = assert(io.open(out_path, 'w')) for i, x in ipairs(uncommitted) do f:write(i) diff --git a/src/nvim/api/vim.c b/src/nvim/api/vim.c index fc780e1248..52ab18cbff 100644 --- a/src/nvim/api/vim.c +++ b/src/nvim/api/vim.c @@ -2354,8 +2354,8 @@ void nvim__redraw(Dict(redraw) *opts, Error *err) } } - int count = (win != NULL) + (buf != NULL); - VALIDATE(popcount(opts->is_set__redraw_) > count, "%s", "at least one action required", { + unsigned count = (win != NULL) + (buf != NULL); + VALIDATE(xpopcount(opts->is_set__redraw_) > count, "%s", "at least one action required", { return; }); diff --git a/src/nvim/api/win_config.c b/src/nvim/api/win_config.c index 3a9986a7d1..70235d8db6 100644 --- a/src/nvim/api/win_config.c +++ b/src/nvim/api/win_config.c @@ -189,13 +189,13 @@ /// ``` /// - title: Title (optional) in window border, string or list. /// List should consist of `[text, highlight]` tuples. -/// If string, the default highlight group is `FloatTitle`. +/// If string, or a tuple lacks a highlight, the default highlight group is `FloatTitle`. /// - title_pos: Title position. Must be set with `title` option. /// Value can be one of "left", "center", or "right". /// Default is `"left"`. /// - footer: Footer (optional) in window border, string or list. /// List should consist of `[text, highlight]` tuples. -/// If string, the default highlight group is `FloatFooter`. +/// If string, or a tuple lacks a highlight, the default highlight group is `FloatFooter`. /// - footer_pos: Footer position. Must be set with `footer` option. /// Value can be one of "left", "center", or "right". /// Default is `"left"`. @@ -851,7 +851,6 @@ static void parse_bordertext(Object bordertext, BorderTextType bordertext_type, bool *is_present; VirtText *chunks; int *width; - int default_hl_id; switch (bordertext_type) { case kBorderTextTitle: if (fconfig->title) { @@ -861,7 +860,6 @@ static void parse_bordertext(Object bordertext, BorderTextType bordertext_type, is_present = &fconfig->title; chunks = &fconfig->title_chunks; width = &fconfig->title_width; - default_hl_id = syn_check_group(S_LEN("FloatTitle")); break; case kBorderTextFooter: if (fconfig->footer) { @@ -871,7 +869,6 @@ static void parse_bordertext(Object bordertext, BorderTextType bordertext_type, is_present = &fconfig->footer; chunks = &fconfig->footer_chunks; width = &fconfig->footer_width; - default_hl_id = syn_check_group(S_LEN("FloatFooter")); break; } @@ -881,7 +878,7 @@ static void parse_bordertext(Object bordertext, BorderTextType bordertext_type, return; } kv_push(*chunks, ((VirtTextChunk){ .text = xstrdup(bordertext.data.string.data), - .hl_id = default_hl_id })); + .hl_id = -1 })); *width = (int)mb_string2cells(bordertext.data.string.data); *is_present = true; return; diff --git a/src/nvim/drawline.c b/src/nvim/drawline.c index 07944081da..4d534d78a2 100644 --- a/src/nvim/drawline.c +++ b/src/nvim/drawline.c @@ -1596,6 +1596,10 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, int col_rows, s // hide virt_text on text hidden by 'nowrap' or 'smoothscroll' decor_redraw_col(wp, (colnr_T)(ptr - line) - 1, wlv.off, true, &decor_state); } + if (wlv.col >= grid->cols) { + wlv.col = wlv.off = grid->cols; + goto end_check; + } } if (cul_screenline && wlv.filler_todo <= 0 @@ -2650,13 +2654,6 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, int col_rows, s conceal_cursor_used = conceal_cursor_line(curwin); } - // When the window is too narrow draw all "@" lines. - if (leftcols_width >= wp->w_grid.cols && is_wrapped) { - win_draw_end(wp, schar_from_ascii('@'), true, wlv.row, wp->w_grid.rows, HLF_AT); - set_empty_rows(wp, wlv.row); - wlv.row = endrow; - } - break; } @@ -2844,10 +2841,12 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, int col_rows, s } } +end_check: // At end of screen line and there is more to come: Display the line // so far. If there is no more to display it is caught above. if (wlv.col >= grid->cols && (!has_foldtext || virt_line_offset >= 0) - && (*ptr != NUL + && (wlv.col <= leftcols_width + || *ptr != NUL || wlv.filler_todo > 0 || (wp->w_p_list && wp->w_p_lcs_chars.eol != NUL && lcs_eol_todo) || (wlv.n_extra != 0 && (wlv.sc_extra != NUL || *wlv.p_extra != NUL)) diff --git a/src/nvim/drawscreen.c b/src/nvim/drawscreen.c index bda0ccc870..039bbd219c 100644 --- a/src/nvim/drawscreen.c +++ b/src/nvim/drawscreen.c @@ -65,6 +65,7 @@ #include "nvim/autocmd.h" #include "nvim/autocmd_defs.h" #include "nvim/buffer.h" +#include "nvim/buffer_defs.h" #include "nvim/charset.h" #include "nvim/cmdexpand.h" #include "nvim/cursor.h" @@ -715,14 +716,17 @@ void end_search_hl(void) screen_search_hl.rm.regprog = NULL; } -static void win_redr_bordertext(win_T *wp, VirtText vt, int col) +static void win_redr_bordertext(win_T *wp, VirtText vt, int col, BorderTextType bt) { for (size_t i = 0; i < kv_size(vt);) { - int attr = 0; + int attr = -1; char *text = next_virt_text_chunk(vt, &i, &attr); if (text == NULL) { break; } + if (attr == -1) { // No highlight specified. + attr = wp->w_ns_hl_attr[bt == kBorderTextTitle ? HLF_BTITLE : HLF_BFOOTER]; + } attr = hl_apply_winblend(wp, attr); col += grid_line_puts(col, text, -1, attr); } @@ -773,7 +777,7 @@ static void win_redr_border(win_T *wp) if (wp->w_config.title) { int title_col = win_get_bordertext_col(icol, wp->w_config.title_width, wp->w_config.title_pos); - win_redr_bordertext(wp, wp->w_config.title_chunks, title_col); + win_redr_bordertext(wp, wp->w_config.title_chunks, title_col, kBorderTextTitle); } if (adj[1]) { grid_line_put_schar(icol + adj[3], chars[2], attrs[2]); @@ -809,7 +813,7 @@ static void win_redr_border(win_T *wp) if (wp->w_config.footer) { int footer_col = win_get_bordertext_col(icol, wp->w_config.footer_width, wp->w_config.footer_pos); - win_redr_bordertext(wp, wp->w_config.footer_chunks, footer_col); + win_redr_bordertext(wp, wp->w_config.footer_chunks, footer_col, kBorderTextFooter); } if (adj[1]) { grid_line_put_schar(icol + adj[3], chars[4], attrs[4]); diff --git a/src/nvim/eval.lua b/src/nvim/eval.lua index 7d4438ded6..ceaba11f41 100644 --- a/src/nvim/eval.lua +++ b/src/nvim/eval.lua @@ -2133,6 +2133,7 @@ M.funcs = { name = 'exepath', params = { { 'expr', 'any' } }, signature = 'exepath({expr})', + returns = 'string', }, exists = { args = 1, @@ -4370,14 +4371,14 @@ M.funcs = { The optional argument {opts} is a Dict and supports the following items: - type Specify the region's selection type - (default: "v"): - "v" for |charwise| mode - "V" for |linewise| mode - "<CTRL-V>" for |blockwise-visual| mode + type Specify the region's selection type. + See |getregtype()| for possible values, + except that the width can be omitted + and an empty string cannot be used. + (default: "v") exclusive If |TRUE|, use exclusive selection - for the end position + for the end position. (default: follow 'selection') You can get the last selection type by |visualmode()|. diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index e4cb63eb8e..8b22c7a797 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -2824,7 +2824,7 @@ static char *block_def2str(struct block_def *bd) } static int getregionpos(typval_T *argvars, typval_T *rettv, pos_T *p1, pos_T *p2, - bool *const inclusive, MotionType *region_type, oparg_T *oa) + bool *const inclusive, MotionType *region_type, oparg_T *oap) FUNC_ATTR_NONNULL_ALL { tv_list_alloc_ret(rettv, kListLenMayKnow); @@ -2858,11 +2858,17 @@ static int getregionpos(typval_T *argvars, typval_T *rettv, pos_T *p1, pos_T *p2 type = default_type; } + int block_width = 0; if (type[0] == 'v' && type[1] == NUL) { *region_type = kMTCharWise; } else if (type[0] == 'V' && type[1] == NUL) { *region_type = kMTLineWise; - } else if (type[0] == Ctrl_V && type[1] == NUL) { + } else if (type[0] == Ctrl_V) { + char *p = type + 1; + if (*p != NUL && ((block_width = getdigits_int(&p, false, 0)) <= 0 || *p != NUL)) { + semsg(_(e_invargNval), "type", type); + return FAIL; + } *region_type = kMTBlockWise; } else { semsg(_(e_invargNval), "type", type); @@ -2926,16 +2932,18 @@ static int getregionpos(typval_T *argvars, typval_T *rettv, pos_T *p1, pos_T *p2 colnr_T sc1, ec1, sc2, ec2; getvvcol(curwin, p1, &sc1, NULL, &ec1); getvvcol(curwin, p2, &sc2, NULL, &ec2); - oa->motion_type = kMTBlockWise; - oa->inclusive = true; - oa->op_type = OP_NOP; - oa->start = *p1; - oa->end = *p2; - oa->start_vcol = MIN(sc1, sc2); - if (is_select_exclusive && ec1 < sc2 && 0 < sc2 && ec2 > ec1) { - oa->end_vcol = sc2 - 1; + oap->motion_type = kMTBlockWise; + oap->inclusive = true; + oap->op_type = OP_NOP; + oap->start = *p1; + oap->end = *p2; + oap->start_vcol = MIN(sc1, sc2); + if (block_width > 0) { + oap->end_vcol = oap->start_vcol + block_width - 1; + } else if (is_select_exclusive && ec1 < sc2 && 0 < sc2 && ec2 > ec1) { + oap->end_vcol = sc2 - 1; } else { - oa->end_vcol = MAX(ec1, ec2); + oap->end_vcol = MAX(ec1, ec2); } } @@ -3034,6 +3042,7 @@ static void f_getregionpos(typval_T *argvars, typval_T *rettv, EvalFuncData fptr for (linenr_T lnum = p1.lnum; lnum <= p2.lnum; lnum++) { pos_T ret_p1, ret_p2; + char *line = ml_get(lnum); colnr_T line_len = ml_get_len(lnum); if (region_type == kMTLineWise) { @@ -3052,7 +3061,7 @@ static void f_getregionpos(typval_T *argvars, typval_T *rettv, EvalFuncData fptr if (bd.is_oneChar) { // selection entirely inside one char if (region_type == kMTBlockWise) { - ret_p1.col = bd.textcol; + ret_p1.col = (colnr_T)(mb_prevptr(line, bd.textstart) - line) + 1; ret_p1.coladd = bd.start_char_vcols - (bd.start_vcol - oa.start_vcol); } else { ret_p1.col = p1.col + 1; @@ -3064,7 +3073,7 @@ static void f_getregionpos(typval_T *argvars, typval_T *rettv, EvalFuncData fptr ret_p1.coladd = oa.start_vcol - bd.start_vcol; bd.is_oneChar = true; } else if (bd.startspaces > 0) { - ret_p1.col = bd.textcol; + ret_p1.col = (colnr_T)(mb_prevptr(line, bd.textstart) - line) + 1; ret_p1.coladd = bd.start_char_vcols - bd.startspaces; } else { ret_p1.col = bd.textcol + 1; diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c index f18dc0f747..cc2608433d 100644 --- a/src/nvim/ex_getln.c +++ b/src/nvim/ex_getln.c @@ -2532,6 +2532,10 @@ static bool cmdpreview_may_show(CommandLineState *s) goto end; } + // Flush now: external cmdline may itself wish to update the screen which is + // currently disallowed during cmdpreview(no longer needed in case that changes). + cmdline_ui_flush(); + // Swap invalid command range if needed if ((ea.argt & EX_RANGE) && ea.line1 > ea.line2) { linenr_T lnum = ea.line1; diff --git a/src/nvim/extmark.c b/src/nvim/extmark.c index 3236590010..4e47fa76fe 100644 --- a/src/nvim/extmark.c +++ b/src/nvim/extmark.c @@ -117,9 +117,16 @@ static void extmark_setraw(buf_T *buf, uint64_t mark, int row, colnr_T col, bool MarkTreeIter itr[1] = { 0 }; MTKey key = marktree_lookup(buf->b_marktree, mark, itr); if (key.pos.row < 0 || (key.pos.row == row && key.pos.col == col)) { + // Does this hold? If it doesn't, we should still revalidate. + assert(!invalid || !mt_invalid(key)); return; } + // Key already revalidated(how?) Avoid adding to decor again. + if (invalid && !mt_invalid(key)) { + invalid = false; + } + // Only the position before undo needs to be redrawn here, // as the position after undo should be marked as changed. if (!invalid && mt_decor_any(key) && key.pos.row != row) { @@ -140,8 +147,8 @@ static void extmark_setraw(buf_T *buf, uint64_t mark, int row, colnr_T col, bool marktree_move(buf->b_marktree, itr, row, col); if (invalid) { - MTPos end = marktree_get_altpos(buf->b_marktree, key, NULL); - buf_put_decor(buf, mt_decor(key), row, end.row); + row2 = mt_paired(key) ? marktree_get_altpos(buf->b_marktree, key, NULL).row : row; + buf_put_decor(buf, mt_decor(key), row, row2); } else if (key.flags & MT_FLAG_DECOR_SIGNTEXT && buf->b_signcols.autom) { buf_signcols_count_range(buf, row1, row2, 0, kNone); } diff --git a/src/nvim/insexpand.c b/src/nvim/insexpand.c index b557b9802e..8b1c09b32f 100644 --- a/src/nvim/insexpand.c +++ b/src/nvim/insexpand.c @@ -1198,6 +1198,10 @@ static int ins_compl_build_pum(void) // match after it, don't highlight anything. bool shown_match_ok = match_at_original_text(compl_shown_match); + if (strequal(compl_leader, compl_orig_text) && !shown_match_ok) { + compl_shown_match = compl_no_select ? compl_first_match : compl_first_match->cp_next; + } + compl_T *shown_compl = NULL; bool did_find_shown_match = false; int cur = -1; diff --git a/src/nvim/main.c b/src/nvim/main.c index 30b6b6e86b..17a0bbf082 100644 --- a/src/nvim/main.c +++ b/src/nvim/main.c @@ -1444,6 +1444,19 @@ scripterror: ga_grow(&global_alist.al_ga, 1); char *p = xstrdup(argv[0]); + // On Windows expand "~\" or "~/" prefix in file names to profile directory. +#ifdef MSWIN + if (*p == '~' && (p[1] == '\\' || p[1] == '/')) { + char *profile_dir = vim_getenv("HOME"); + size_t size = strlen(profile_dir) + strlen(p); + char *tilde_expanded = xmalloc(size); + snprintf(tilde_expanded, size, "%s%s", profile_dir, p + 1); + xfree(p); + xfree(profile_dir); + p = tilde_expanded; + } +#endif + if (parmp->diff_mode && os_isdir(p) && GARGCOUNT > 0 && !os_isdir(alist_name(&GARGLIST[0]))) { char *r = concat_fnames(p, path_tail(alist_name(&GARGLIST[0])), true); diff --git a/src/nvim/math.c b/src/nvim/math.c index 1ccf4d7806..4ca212413b 100644 --- a/src/nvim/math.c +++ b/src/nvim/math.c @@ -78,13 +78,15 @@ int xctz(uint64_t x) } /// Count number of set bits in bit field. -int popcount(uint64_t x) +unsigned xpopcount(uint64_t x) { // Use compiler builtin if possible. -#if defined(__clang__) || defined(__GNUC__) - return __builtin_popcountll(x); +#if defined(__NetBSD__) + return popcount64(x); +#elif defined(__clang__) || defined(__GNUC__) + return (unsigned)__builtin_popcountll(x); #else - int count = 0; + unsigned count = 0; for (; x != 0; x >>= 1) { if (x & 1) { count++; diff --git a/src/nvim/tui/tui.c b/src/nvim/tui/tui.c index 2a9530defb..dc8c8def5b 100644 --- a/src/nvim/tui/tui.c +++ b/src/nvim/tui/tui.c @@ -115,6 +115,7 @@ struct TUIData { kvec_t(HlAttrs) attrs; int print_attr_id; bool default_attr; + bool set_default_colors; bool can_clear_attr; ModeShape showing_mode; Integer verbose; @@ -166,14 +167,6 @@ void tui_start(TUIData **tui_p, int *width, int *height, char **term, bool *rgb) tui->seen_error_exit = 0; tui->loop = &main_loop; tui->url = -1; - // Because setting the default colors is delayed until after startup to avoid - // flickering with the default colorscheme background, any flush that happens - // during startup in turn would result in clearing invalidated regions with - // uninitialized attrs(black). Instead initialize clear_attrs with current - // terminal background so that it is at least not perceived as flickering, even - // though it may be different from the colorscheme that is set during startup. - tui->clear_attrs.rgb_bg_color = normal_bg; - tui->clear_attrs.cterm_bg_color = (int16_t)cterm_normal_bg_color; kv_init(tui->invalid_regions); kv_init(tui->urlbuf); @@ -1016,7 +1009,16 @@ static void clear_region(TUIData *tui, int top, int bot, int left, int right, in { UGrid *grid = &tui->grid; - update_attrs(tui, attr_id); + // Setting the default colors is delayed until after startup to avoid flickering + // with the default colorscheme background. Consequently, any flush that happens + // during startup would result in clearing invalidated regions with zeroed + // clear_attrs, perceived as a black flicker. Reset attributes to clear with + // current terminal background instead(#28667, #28668). + if (tui->set_default_colors) { + update_attrs(tui, attr_id); + } else { + unibi_out(tui, unibi_exit_attribute_mode); + } // Background is set to the default color and the right edge matches the // screen end, try to use terminal codes for clearing the requested area. @@ -1419,6 +1421,7 @@ void tui_default_colors_set(TUIData *tui, Integer rgb_fg, Integer rgb_bg, Intege tui->clear_attrs.cterm_bg_color = (int16_t)cterm_bg; tui->print_attr_id = -1; + tui->set_default_colors = true; invalidate(tui, 0, tui->grid.height, 0, tui->grid.width); } diff --git a/test/functional/api/buffer_spec.lua b/test/functional/api/buffer_spec.lua index cf69958fd8..f836c1c540 100644 --- a/test/functional/api/buffer_spec.lua +++ b/test/functional/api/buffer_spec.lua @@ -125,11 +125,6 @@ describe('api/buf', function() it('cursor position is maintained consistently with viewport', function() local screen = Screen.new(20, 12) - screen:set_default_attr_ids { - [1] = { bold = true, foreground = Screen.colors.Blue1 }, - [2] = { reverse = true, bold = true }, - [3] = { reverse = true }, - } screen:attach() local lines = { 'line1', 'line2', 'line3', 'line4', 'line5', 'line6' } @@ -143,11 +138,11 @@ describe('api/buf', function() grid = [[ ^ | {1:~ }|*4 - {2:[No Name] }| + {3:[No Name] }| line5 | line6 | {1:~ }|*2 - {3:[No Name] [+] }| + {2:[No Name] [+] }| | ]], } @@ -158,11 +153,11 @@ describe('api/buf', function() grid = [[ ^ | {1:~ }|*4 - {2:[No Name] }| + {3:[No Name] }| boogalo 5 | line6 | {1:~ }|*2 - {3:[No Name] [+] }| + {2:[No Name] [+] }| | ]], } @@ -172,11 +167,11 @@ describe('api/buf', function() grid = [[ | {1:~ }|*4 - {3:[No Name] }| + {2:[No Name] }| boogalo 5 | ^line6 | {1:~ }|*2 - {2:[No Name] [+] }| + {3:[No Name] [+] }| | ]], } @@ -216,11 +211,6 @@ describe('api/buf', function() local screen before_each(function() screen = Screen.new(20, 12) - screen:set_default_attr_ids { - [1] = { bold = true, foreground = Screen.colors.Blue1 }, - [2] = { reverse = true, bold = true }, - [3] = { reverse = true }, - } screen:attach() api.nvim_buf_set_lines( 0, @@ -243,12 +233,12 @@ describe('api/buf', function() grid = [[ | {1:~ }|*4 - {3:[No Name] }| + {2:[No Name] }| www | xxx | yyy | ^zzz | - {2:[No Name] }| + {3:[No Name] }| | ]], } @@ -258,12 +248,12 @@ describe('api/buf', function() grid = [[ | {1:~ }|*4 - {3:[No Name] }| + {2:[No Name] }| www | xxx | yyy | ^zzz | - {2:[No Name] [+] }| + {3:[No Name] [+] }| | ]], } @@ -274,12 +264,12 @@ describe('api/buf', function() grid = [[ | {1:~ }|*4 - {3:[No Name] }| + {2:[No Name] }| wwweeee | xxx | yyy | ^zzz | - {2:[No Name] [+] }| + {3:[No Name] [+] }| | ]], } @@ -290,12 +280,12 @@ describe('api/buf', function() grid = [[ | {1:~ }|*4 - {3:[No Name] }| + {2:[No Name] }| wwweeee | xxx | yyy | ^zzz | - {2:[No Name] [+] }| + {3:[No Name] [+] }| | ]], unchanged = true, @@ -306,12 +296,12 @@ describe('api/buf', function() grid = [[ | {1:~ }|*4 - {3:[No Name] }| + {2:[No Name] }| wwweeee | xxx | ^yyy | zzz | - {2:[No Name] [+] }| + {3:[No Name] [+] }| | ]], } @@ -321,12 +311,12 @@ describe('api/buf', function() grid = [[ | {1:~ }|*4 - {3:[No Name] }| + {2:[No Name] }| mmmeeeee | wwweeee | xxx | ^yyy | - {2:[No Name] [+] }| + {3:[No Name] [+] }| | ]], } @@ -343,12 +333,12 @@ describe('api/buf', function() grid = [[ ^ | {1:~ }|*4 - {2:[No Name] }| + {3:[No Name] }| www | xxx | yyy | zzz | - {3:[No Name] }| + {2:[No Name] }| | ]], } @@ -358,12 +348,12 @@ describe('api/buf', function() grid = [[ ^ | {1:~ }|*4 - {2:[No Name] }| + {3:[No Name] }| www | xxx | yyy | zzz | - {3:[No Name] [+] }| + {2:[No Name] [+] }| | ]], } @@ -374,12 +364,12 @@ describe('api/buf', function() grid = [[ ^ | {1:~ }|*4 - {2:[No Name] }| + {3:[No Name] }| wwweeee | xxx | yyy | zzz | - {3:[No Name] [+] }| + {2:[No Name] [+] }| | ]], } @@ -389,12 +379,12 @@ describe('api/buf', function() grid = [[ ^ | {1:~ }|*4 - {2:[No Name] }| + {3:[No Name] }| wwweeee | xxx | yyy | zzz | - {3:[No Name] [+] }| + {2:[No Name] [+] }| | ]], unchanged = true, @@ -416,12 +406,12 @@ describe('api/buf', function() ccc | ddd | www | - {2:[No Name] }| + {3:[No Name] }| www | xxx | yyy | zzz | - {3:[No Name] }| + {2:[No Name] }| | ]], } @@ -434,12 +424,12 @@ describe('api/buf', function() ddd | www | xxx | - {2:[No Name] [+] }| + {3:[No Name] [+] }| www | xxx | yyy | zzz | - {3:[No Name] [+] }| + {2:[No Name] [+] }| | ]], } @@ -453,12 +443,12 @@ describe('api/buf', function() ddd | wwweeee | xxx | - {2:[No Name] [+] }| + {3:[No Name] [+] }| wwweeee | xxx | yyy | zzz | - {3:[No Name] [+] }| + {2:[No Name] [+] }| | ]], } @@ -471,12 +461,12 @@ describe('api/buf', function() ddd | mmm | wwweeee | - {2:[No Name] [+] }| + {3:[No Name] [+] }| wwweeee | xxx | yyy | zzz | - {3:[No Name] [+] }| + {2:[No Name] [+] }| | ]], } @@ -745,10 +735,6 @@ describe('api/buf', function() it("set_lines of invisible buffer doesn't move cursor in current window", function() local screen = Screen.new(20, 5) - screen:set_default_attr_ids({ - [1] = { bold = true, foreground = Screen.colors.Blue1 }, - [2] = { bold = true }, - }) screen:attach() insert([[ @@ -771,7 +757,7 @@ describe('api/buf', function() A real window | with proper tex^t | {1:~ }| - {2:-- INSERT --} | + {5:-- INSERT --} | ]]) end) @@ -1756,11 +1742,6 @@ describe('api/buf', function() local screen before_each(function() screen = Screen.new(20, 12) - screen:set_default_attr_ids { - [1] = { bold = true, foreground = Screen.colors.Blue1 }, - [2] = { reverse = true, bold = true }, - [3] = { reverse = true }, - } screen:attach() api.nvim_buf_set_lines( 0, @@ -1783,12 +1764,12 @@ describe('api/buf', function() grid = [[ | {1:~ }|*4 - {3:[No Name] }| + {2:[No Name] }| www | xxx | yyy | ^zzz | - {2:[No Name] }| + {3:[No Name] }| | ]], } @@ -1798,12 +1779,12 @@ describe('api/buf', function() grid = [[ | {1:~ }|*4 - {3:[No Name] }| + {2:[No Name] }| www | xxx | yyy | ^zzz | - {2:[No Name] [+] }| + {3:[No Name] [+] }| | ]], } @@ -1820,12 +1801,12 @@ describe('api/buf', function() grid = [[ ^ | {1:~ }|*4 - {2:[No Name] }| + {3:[No Name] }| www | xxx | yyy | zzz | - {3:[No Name] }| + {2:[No Name] }| | ]], } @@ -1835,12 +1816,12 @@ describe('api/buf', function() grid = [[ ^ | {1:~ }|*4 - {2:[No Name] }| + {3:[No Name] }| www | xxx | yyy | zzz | - {3:[No Name] [+] }| + {2:[No Name] [+] }| | ]], } @@ -1861,12 +1842,12 @@ describe('api/buf', function() ccc | ddd | www | - {2:[No Name] }| + {3:[No Name] }| www | xxx | yyy | zzz | - {3:[No Name] }| + {2:[No Name] }| | ]], } @@ -1879,12 +1860,12 @@ describe('api/buf', function() ddd | www | xxx | - {2:[No Name] [+] }| + {3:[No Name] [+] }| www | xxx | yyy | zzz | - {3:[No Name] [+] }| + {2:[No Name] [+] }| | ]], } diff --git a/test/functional/api/vim_spec.lua b/test/functional/api/vim_spec.lua index fd0535aa51..b32f2b1cb2 100644 --- a/test/functional/api/vim_spec.lua +++ b/test/functional/api/vim_spec.lua @@ -367,14 +367,11 @@ describe('API', function() it('displays messages when opts.output=false', function() local screen = Screen.new(40, 8) screen:attach() - screen:set_default_attr_ids({ - [0] = { bold = true, foreground = Screen.colors.Blue }, - }) api.nvim_exec2("echo 'hello'", { output = false }) screen:expect { grid = [[ ^ | - {0:~ }|*6 + {1:~ }|*6 hello | ]], } @@ -383,14 +380,11 @@ describe('API', function() it("doesn't display messages when output=true", function() local screen = Screen.new(40, 6) screen:attach() - screen:set_default_attr_ids({ - [0] = { bold = true, foreground = Screen.colors.Blue }, - }) api.nvim_exec2("echo 'hello'", { output = true }) screen:expect { grid = [[ ^ | - {0:~ }|*4 + {1:~ }|*4 | ]], } @@ -403,7 +397,7 @@ describe('API', function() screen:expect { grid = [[ ^ | - {0:~ }|*4 + {1:~ }|*4 15 | ]], } @@ -1533,16 +1527,12 @@ describe('API', function() eq({ 1, 5 }, api.nvim_win_get_cursor(0)) local screen = Screen.new(60, 3) - screen:set_default_attr_ids({ - [0] = { bold = true, foreground = Screen.colors.Blue }, - [1] = { background = Screen.colors.Yellow }, - }) screen:attach() eq(1, eval('v:hlsearch')) screen:expect { grid = [[ - {1:foo} {1:^foo} {1:foo} | - {0:~ }| + {10:foo} {10:^foo} {10:foo} | + {1:~ }| | ]], } @@ -1551,7 +1541,7 @@ describe('API', function() screen:expect { grid = [[ foo ^foo foo | - {0:~ }| + {1:~ }| | ]], } @@ -1559,8 +1549,8 @@ describe('API', function() eq(1, eval('v:hlsearch')) screen:expect { grid = [[ - {1:foo} {1:^foo} {1:foo} | - {0:~ }| + {10:foo} {10:^foo} {10:foo} | + {1:~ }| | ]], } @@ -2254,12 +2244,6 @@ describe('API', function() before_each(function() screen = Screen.new(40, 8) screen:attach() - screen:set_default_attr_ids({ - [0] = { bold = true, foreground = Screen.colors.Blue }, - [1] = { bold = true, foreground = Screen.colors.SeaGreen }, - [2] = { bold = true, reverse = true }, - [3] = { foreground = Screen.colors.Blue }, - }) end) it('prints long messages correctly #20534', function() @@ -2287,11 +2271,11 @@ describe('API', function() screen:expect { grid = [[ | - {0:~ }|*3 - {2: }| + {1:~ }|*3 + {3: }| | a | - {1:Press ENTER or type command to continue}^ | + {6:Press ENTER or type command to continue}^ | ]], } feed('<CR>') @@ -2299,12 +2283,12 @@ describe('API', function() screen:expect { grid = [[ | - {0:~ }|*2 - {2: }| + {1:~ }|*2 + {3: }| b | | c | - {1:Press ENTER or type command to continue}^ | + {6:Press ENTER or type command to continue}^ | ]], } end) @@ -2314,11 +2298,11 @@ describe('API', function() screen:expect { grid = [[ | - {0:~ }|*3 - {2: }| - aaa{3:^@}bbb{3:^@^@}ccc | - ddd{3:^@^@^@}eee | - {1:Press ENTER or type command to continue}^ | + {1:~ }|*3 + {3: }| + aaa{18:^@}bbb{18:^@^@}ccc | + ddd{18:^@^@^@}eee | + {6:Press ENTER or type command to continue}^ | ]], } end) @@ -2330,20 +2314,14 @@ describe('API', function() before_each(function() screen = Screen.new(40, 8) screen:attach() - screen:set_default_attr_ids({ - [0] = { bold = true, foreground = Screen.colors.Blue }, - [1] = { foreground = Screen.colors.White, background = Screen.colors.Red }, - [2] = { bold = true, foreground = Screen.colors.SeaGreen }, - [3] = { bold = true, reverse = true }, - }) end) it('can show one line', function() async_meths.nvim_err_write('has bork\n') screen:expect([[ ^ | - {0:~ }|*6 - {1:has bork} | + {1:~ }|*6 + {9:has bork} | ]]) end) @@ -2351,11 +2329,11 @@ describe('API', function() async_meths.nvim_err_write('something happened\nvery bad\n') screen:expect([[ | - {0:~ }|*3 + {1:~ }|*3 {3: }| - {1:something happened} | - {1:very bad} | - {2:Press ENTER or type command to continue}^ | + {9:something happened} | + {9:very bad} | + {6:Press ENTER or type command to continue}^ | ]]) end) @@ -2363,13 +2341,13 @@ describe('API', function() async_meths.nvim_err_write('FAILURE\nERROR\nEXCEPTION\nTRACEBACK\n') screen:expect([[ | - {0:~ }| + {1:~ }| {3: }| - {1:FAILURE} | - {1:ERROR} | - {1:EXCEPTION} | - {1:TRACEBACK} | - {2:Press ENTER or type command to continue}^ | + {9:FAILURE} | + {9:ERROR} | + {9:EXCEPTION} | + {9:TRACEBACK} | + {6:Press ENTER or type command to continue}^ | ]]) end) @@ -2379,8 +2357,8 @@ describe('API', function() async_meths.nvim_err_write('fail\n') screen:expect([[ ^ | - {0:~ }|*6 - {1:very fail} | + {1:~ }|*6 + {9:very fail} | ]]) n.poke_eventloop() @@ -2388,11 +2366,11 @@ describe('API', function() async_meths.nvim_err_write('more fail\ntoo fail\n') screen:expect([[ | - {0:~ }|*3 + {1:~ }|*3 {3: }| - {1:more fail} | - {1:too fail} | - {2:Press ENTER or type command to continue}^ | + {9:more fail} | + {9:too fail} | + {6:Press ENTER or type command to continue}^ | ]]) feed('<cr>') -- exit the press ENTER screen end) @@ -2402,11 +2380,11 @@ describe('API', function() screen:expect { grid = [[ | - {0:~ }|*3 + {1:~ }|*3 {3: }| - {1:aaa^@bbb^@^@ccc} | - {1:ddd^@^@^@eee} | - {2:Press ENTER or type command to continue}^ | + {9:aaa^@bbb^@^@ccc} | + {9:ddd^@^@^@eee} | + {6:Press ENTER or type command to continue}^ | ]], } end) @@ -2418,30 +2396,24 @@ describe('API', function() before_each(function() screen = Screen.new(40, 8) screen:attach() - screen:set_default_attr_ids({ - [0] = { bold = true, foreground = Screen.colors.Blue }, - [1] = { foreground = Screen.colors.White, background = Screen.colors.Red }, - [2] = { bold = true, foreground = Screen.colors.SeaGreen }, - [3] = { bold = true, reverse = true }, - }) end) it('shows only one return prompt after all lines are shown', function() async_meths.nvim_err_writeln('FAILURE\nERROR\nEXCEPTION\nTRACEBACK') screen:expect([[ | - {0:~ }| + {1:~ }| {3: }| - {1:FAILURE} | - {1:ERROR} | - {1:EXCEPTION} | - {1:TRACEBACK} | - {2:Press ENTER or type command to continue}^ | + {9:FAILURE} | + {9:ERROR} | + {9:EXCEPTION} | + {9:TRACEBACK} | + {6:Press ENTER or type command to continue}^ | ]]) feed('<CR>') screen:expect([[ ^ | - {0:~ }|*6 + {1:~ }|*6 | ]]) end) @@ -3102,9 +3074,6 @@ describe('API', function() eq(1, api.nvim_get_current_buf()) local screen = Screen.new(20, 4) - screen:set_default_attr_ids({ - [1] = { bold = true, foreground = Screen.colors.Blue1 }, - }) screen:attach() -- @@ -3458,13 +3427,6 @@ describe('API', function() before_each(function() screen = Screen.new(40, 8) screen:attach() - screen:set_default_attr_ids({ - [0] = { bold = true, foreground = Screen.colors.Blue }, - [1] = { bold = true, foreground = Screen.colors.SeaGreen }, - [2] = { bold = true, reverse = true }, - [3] = { foreground = Screen.colors.Brown, bold = true }, -- Statement - [4] = { foreground = Screen.colors.SlateBlue }, -- Special - }) command('highlight Statement gui=bold guifg=Brown') command('highlight Special guifg=SlateBlue') end) @@ -3474,7 +3436,7 @@ describe('API', function() screen:expect { grid = [[ ^ | - {0:~ }|*6 + {1:~ }|*6 msg | ]], } @@ -3489,8 +3451,8 @@ describe('API', function() screen:expect { grid = [[ ^ | - {0:~ }|*6 - msg_a{3:msg_b}{4:msg_c} | + {1:~ }|*6 + msg_a{15:msg_b}{16:msg_c} | ]], } end) @@ -3500,11 +3462,11 @@ describe('API', function() screen:expect { grid = [[ | - {0:~ }|*3 - {2: }| - {3:msg_a} | - {3:msg_a}{4:msg_b} | - {1:Press ENTER or type command to continue}^ | + {1:~ }|*3 + {3: }| + {15:msg_a} | + {15:msg_a}{16:msg_b} | + {6:Press ENTER or type command to continue}^ | ]], } end) @@ -3528,24 +3490,16 @@ describe('API', function() before_each(function() screen = Screen.new(100, 35) screen:attach() - screen:set_default_attr_ids({ - [0] = { bold = true, foreground = Screen.colors.Blue }, - [1] = { background = Screen.colors.Plum1 }, - [2] = { background = tonumber('0xffff40'), bg_indexed = true }, - [3] = { - background = Screen.colors.Plum1, - fg_indexed = true, - foreground = tonumber('0x00e000'), - }, - [4] = { bold = true, reverse = true, background = Screen.colors.Plum1 }, - [5] = { - foreground = Screen.colors.Blue, + screen:add_extra_attr_ids { + [100] = { background = tonumber('0xffff40'), bg_indexed = true }, + [101] = { background = Screen.colors.LightMagenta, - bold = true, + foreground = tonumber('0x00e000'), + fg_indexed = true, }, - [6] = { bold = true }, - [7] = { reverse = true, background = Screen.colors.LightMagenta }, - }) + [102] = { background = Screen.colors.LightMagenta, reverse = true }, + [103] = { background = Screen.colors.LightMagenta, bold = true, reverse = true }, + } end) it('can batch process sequences', function() @@ -3561,38 +3515,38 @@ describe('API', function() screen:expect { grid = [[ ^ | - {0:~}{1::smile }{0: }| - {0:~}{1: }{2:oooo$$$$$$$$$$$$oooo}{1: }{0: }| - {0:~}{1: }{2:oo$$$$$$$$$$$$$$$$$$$$$$$$o}{1: }{0: }| - {0:~}{1: }{2:oo$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$o}{1: }{2:o$}{1: }{2:$$}{1: }{2:o$}{1: }{0: }| - {0:~}{1: }{2:o}{1: }{2:$}{1: }{2:oo}{1: }{2:o$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$o}{1: }{2:$$}{1: }{2:$$}{1: }{2:$$o$}{1: }{0: }| - {0:~}{1: }{2:oo}{1: }{2:$}{1: }{2:$}{1: "}{2:$}{1: }{2:o$$$$$$$$$}{1: }{2:$$$$$$$$$$$$$}{1: }{2:$$$$$$$$$o}{1: }{2:$$$o$$o$}{1: }{0: }| - {0:~}{1: "}{2:$$$$$$o$}{1: }{2:o$$$$$$$$$}{1: }{2:$$$$$$$$$$$}{1: }{2:$$$$$$$$$$o}{1: }{2:$$$$$$$$}{1: }{0: }| - {0:~}{1: }{2:$$$$$$$}{1: }{2:$$$$$$$$$$$}{1: }{2:$$$$$$$$$$$}{1: }{2:$$$$$$$$$$$$$$$$$$$$$$$}{1: }{0: }| - {0:~}{1: }{2:$$$$$$$$$$$$$$$$$$$$$$$}{1: }{2:$$$$$$$$$$$$$}{1: }{2:$$$$$$$$$$$$$$}{1: """}{2:$$$}{1: }{0: }| - {0:~}{1: "}{2:$$$}{1:""""}{2:$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$}{1: "}{2:$$$}{1: }{0: }| - {0:~}{1: }{2:$$$}{1: }{2:o$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$}{1: "}{2:$$$o}{1: }{0: }| - {0:~}{1: }{2:o$$}{1:" }{2:$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$}{1: }{2:$$$o}{1: }{0: }| - {0:~}{1: }{2:$$$}{1: }{2:$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$}{1:" "}{2:$$$$$$ooooo$$$$o}{1: }{0: }| - {0:~}{1: }{2:o$$$oooo$$$$$}{1: }{2:$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$}{1: }{2:o$$$$$$$$$$$$$$$$$}{1: }{0: }| - {0:~}{1: }{2:$$$$$$$$}{1:"}{2:$$$$}{1: }{2:$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$}{1: }{2:$$$$}{1:"""""""" }{0: }| - {0:~}{1: """" }{2:$$$$}{1: "}{2:$$$$$$$$$$$$$$$$$$$$$$$$$$$$}{1:" }{2:o$$$}{1: }{0: }| - {0:~}{1: "}{2:$$$o}{1: """}{2:$$$$$$$$$$$$$$$$$$}{1:"}{2:$$}{1:" }{2:$$$}{1: }{0: }| - {0:~}{1: }{2:$$$o}{1: "}{2:$$}{1:""}{2:$$$$$$}{1:"""" }{2:o$$$}{1: }{0: }| - {0:~}{1: }{2:$$$$o}{1: }{2:o$$$}{1:" }{0: }| - {0:~}{1: "}{2:$$$$o}{1: }{2:o$$$$$$o}{1:"}{2:$$$$o}{1: }{2:o$$$$}{1: }{0: }| - {0:~}{1: "}{2:$$$$$oo}{1: ""}{2:$$$$o$$$$$o}{1: }{2:o$$$$}{1:"" }{0: }| - {0:~}{1: ""}{2:$$$$$oooo}{1: "}{2:$$$o$$$$$$$$$}{1:""" }{0: }| - {0:~}{1: ""}{2:$$$$$$$oo}{1: }{2:$$$$$$$$$$}{1: }{0: }| - {0:~}{1: """"}{2:$$$$$$$$$$$}{1: }{0: }| - {0:~}{1: }{2:$$$$$$$$$$$$}{1: }{0: }| - {0:~}{1: }{2:$$$$$$$$$$}{1:" }{0: }| - {0:~}{1: "}{2:$$$}{1:"""" }{0: }| - {0:~}{1: }{0: }| - {0:~}{3:Press ENTER or type command to continue}{1: }{0: }| - {0:~}{4:term://~/config2/docs/pres//32693:vim --clean +smile 29,39 All}{0: }| - {0:~}{1::call nvim__screenshot("smile2.cat") }{0: }| - {0:~ }|*2 + {1:~}{4::smile }{1: }| + {1:~}{4: }{100:oooo$$$$$$$$$$$$oooo}{4: }{1: }| + {1:~}{4: }{100:oo$$$$$$$$$$$$$$$$$$$$$$$$o}{4: }{1: }| + {1:~}{4: }{100:oo$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$o}{4: }{100:o$}{4: }{100:$$}{4: }{100:o$}{4: }{1: }| + {1:~}{4: }{100:o}{4: }{100:$}{4: }{100:oo}{4: }{100:o$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$o}{4: }{100:$$}{4: }{100:$$}{4: }{100:$$o$}{4: }{1: }| + {1:~}{4: }{100:oo}{4: }{100:$}{4: }{100:$}{4: "}{100:$}{4: }{100:o$$$$$$$$$}{4: }{100:$$$$$$$$$$$$$}{4: }{100:$$$$$$$$$o}{4: }{100:$$$o$$o$}{4: }{1: }| + {1:~}{4: "}{100:$$$$$$o$}{4: }{100:o$$$$$$$$$}{4: }{100:$$$$$$$$$$$}{4: }{100:$$$$$$$$$$o}{4: }{100:$$$$$$$$}{4: }{1: }| + {1:~}{4: }{100:$$$$$$$}{4: }{100:$$$$$$$$$$$}{4: }{100:$$$$$$$$$$$}{4: }{100:$$$$$$$$$$$$$$$$$$$$$$$}{4: }{1: }| + {1:~}{4: }{100:$$$$$$$$$$$$$$$$$$$$$$$}{4: }{100:$$$$$$$$$$$$$}{4: }{100:$$$$$$$$$$$$$$}{4: """}{100:$$$}{4: }{1: }| + {1:~}{4: "}{100:$$$}{4:""""}{100:$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$}{4: "}{100:$$$}{4: }{1: }| + {1:~}{4: }{100:$$$}{4: }{100:o$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$}{4: "}{100:$$$o}{4: }{1: }| + {1:~}{4: }{100:o$$}{4:" }{100:$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$}{4: }{100:$$$o}{4: }{1: }| + {1:~}{4: }{100:$$$}{4: }{100:$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$}{4:" "}{100:$$$$$$ooooo$$$$o}{4: }{1: }| + {1:~}{4: }{100:o$$$oooo$$$$$}{4: }{100:$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$}{4: }{100:o$$$$$$$$$$$$$$$$$}{4: }{1: }| + {1:~}{4: }{100:$$$$$$$$}{4:"}{100:$$$$}{4: }{100:$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$}{4: }{100:$$$$}{4:"""""""" }{1: }| + {1:~}{4: """" }{100:$$$$}{4: "}{100:$$$$$$$$$$$$$$$$$$$$$$$$$$$$}{4:" }{100:o$$$}{4: }{1: }| + {1:~}{4: "}{100:$$$o}{4: """}{100:$$$$$$$$$$$$$$$$$$}{4:"}{100:$$}{4:" }{100:$$$}{4: }{1: }| + {1:~}{4: }{100:$$$o}{4: "}{100:$$}{4:""}{100:$$$$$$}{4:"""" }{100:o$$$}{4: }{1: }| + {1:~}{4: }{100:$$$$o}{4: }{100:o$$$}{4:" }{1: }| + {1:~}{4: "}{100:$$$$o}{4: }{100:o$$$$$$o}{4:"}{100:$$$$o}{4: }{100:o$$$$}{4: }{1: }| + {1:~}{4: "}{100:$$$$$oo}{4: ""}{100:$$$$o$$$$$o}{4: }{100:o$$$$}{4:"" }{1: }| + {1:~}{4: ""}{100:$$$$$oooo}{4: "}{100:$$$o$$$$$$$$$}{4:""" }{1: }| + {1:~}{4: ""}{100:$$$$$$$oo}{4: }{100:$$$$$$$$$$}{4: }{1: }| + {1:~}{4: """"}{100:$$$$$$$$$$$}{4: }{1: }| + {1:~}{4: }{100:$$$$$$$$$$$$}{4: }{1: }| + {1:~}{4: }{100:$$$$$$$$$$}{4:" }{1: }| + {1:~}{4: "}{100:$$$}{4:"""" }{1: }| + {1:~}{4: }{1: }| + {1:~}{101:Press ENTER or type command to continue}{4: }{1: }| + {1:~}{103:term://~/config2/docs/pres//32693:vim --clean +smile 29,39 All}{1: }| + {1:~}{4::call nvim__screenshot("smile2.cat") }{1: }| + {1:~ }|*2 | ]], } @@ -3624,9 +3578,9 @@ describe('API', function() screen:expect { grid = [[ | - {0:~}{1:^ }{0: }| - {0:~}{1: }{0: }|*4 - {0:~ }|*3 + {1:~}{4:^ }{1: }| + {1:~}{4: }{1: }|*4 + {1:~ }|*3 | ]], } @@ -3635,10 +3589,10 @@ describe('API', function() screen:expect { grid = [[ | - {0:~}{7: }{1: }{0: }| - {0:~}{1: }{0: }|*4 - {0:~ }|*3 - {6:-- TERMINAL --} | + {1:~}{102: }{4: }{1: }| + {1:~}{4: }{1: }|*4 + {1:~ }|*3 + {5:-- TERMINAL --} | ]], } @@ -3651,10 +3605,10 @@ describe('API', function() screen:expect { grid = [[ | - {0:~}{1:herrejösses!}{7: }{1: }{0: }| - {0:~}{1: }{0: }|*4 - {0:~ }|*3 - {6:-- TERMINAL --} | + {1:~}{4:herrejösses!}{102: }{4: }{1: }| + {1:~}{4: }{1: }|*4 + {1:~ }|*3 + {5:-- TERMINAL --} | ]], } eq('ba\024blaherrejösses!', exec_lua [[ return stream ]]) @@ -4472,10 +4426,6 @@ describe('API', function() end) it('does not interfere with printing line in Ex mode #19400', function() local screen = Screen.new(60, 7) - screen:set_default_attr_ids({ - [0] = { bold = true, foreground = Screen.colors.Blue }, -- NonText - [1] = { bold = true, reverse = true }, -- MsgSeparator - }) screen:attach() insert([[ foo @@ -4484,8 +4434,8 @@ describe('API', function() screen:expect([[ foo | bar | - {0:~ }|*2 - {1: }| + {1:~ }|*2 + {3: }| Entering Ex mode. Type "visual" to go to Normal mode. | :1^ | ]]) @@ -4494,7 +4444,7 @@ describe('API', function() screen:expect([[ foo | bar | - {1: }| + {3: }| Entering Ex mode. Type "visual" to go to Normal mode. | :1 | foo | @@ -4934,14 +4884,11 @@ describe('API', function() it("doesn't display messages when output=true", function() local screen = Screen.new(40, 6) screen:attach() - screen:set_default_attr_ids({ - [0] = { bold = true, foreground = Screen.colors.Blue }, - }) api.nvim_cmd({ cmd = 'echo', args = { [['hello']] } }, { output = true }) screen:expect { grid = [[ ^ | - {0:~ }|*4 + {1:~ }|*4 | ]], } @@ -4954,7 +4901,7 @@ describe('API', function() screen:expect { grid = [[ ^ | - {0:~ }|*4 + {1:~ }|*4 15 | ]], } diff --git a/test/functional/api/window_spec.lua b/test/functional/api/window_spec.lua index 15b9b0945c..77611cc750 100644 --- a/test/functional/api/window_spec.lua +++ b/test/functional/api/window_spec.lua @@ -170,11 +170,6 @@ describe('API/win', function() it('updates the screen, and also when the window is unfocused', function() local screen = Screen.new(30, 9) - screen:set_default_attr_ids({ - [1] = { bold = true, foreground = Screen.colors.Blue }, - [2] = { bold = true, reverse = true }, - [3] = { reverse = true }, - }) screen:attach() insert('prologue') @@ -221,10 +216,10 @@ describe('API/win', function() grid = [[ ^ | {1:~ }|*2 - {2:[No Name] }| + {3:[No Name] }| prologue | |*2 - {3:[No Name] [+] }| + {2:[No Name] [+] }| | ]], } @@ -235,10 +230,10 @@ describe('API/win', function() grid = [[ ^ | {1:~ }|*2 - {2:[No Name] }| + {3:[No Name] }| |*2 epilogue | - {3:[No Name] [+] }| + {2:[No Name] [+] }| | ]], } @@ -249,10 +244,10 @@ describe('API/win', function() grid = [[ ^ | {1:~ }|*2 - {2:[No Name] }| + {3:[No Name] }| prologue | |*2 - {3:[No Name] [+] }| + {2:[No Name] [+] }| | ]], } @@ -286,12 +281,6 @@ describe('API/win', function() it('updates cursorline and statusline ruler in non-current window', function() local screen = Screen.new(60, 8) - screen:set_default_attr_ids({ - [1] = { bold = true, foreground = Screen.colors.Blue }, -- NonText - [2] = { background = Screen.colors.Grey90 }, -- CursorLine - [3] = { bold = true, reverse = true }, -- StatusLine - [4] = { reverse = true }, -- StatusLineNC - }) screen:attach() command('set ruler') command('set cursorline') @@ -306,31 +295,25 @@ describe('API/win', function() aaa │aaa | bbb │bbb | ccc │ccc | - {2:dd^d }│{2:ddd }| + {21:dd^d }│{21:ddd }| {1:~ }│{1:~ }|*2 - {3:[No Name] [+] 4,3 All }{4:[No Name] [+] 4,3 All}| + {3:[No Name] [+] 4,3 All }{2:[No Name] [+] 4,3 All}| | ]]) api.nvim_win_set_cursor(oldwin, { 1, 0 }) screen:expect([[ - aaa │{2:aaa }| + aaa │{21:aaa }| bbb │bbb | ccc │ccc | - {2:dd^d }│ddd | + {21:dd^d }│ddd | {1:~ }│{1:~ }|*2 - {3:[No Name] [+] 4,3 All }{4:[No Name] [+] 1,1 All}| + {3:[No Name] [+] 4,3 All }{2:[No Name] [+] 1,1 All}| | ]]) end) it('updates cursorcolumn in non-current window', function() local screen = Screen.new(60, 8) - screen:set_default_attr_ids({ - [1] = { bold = true, foreground = Screen.colors.Blue }, -- NonText - [2] = { background = Screen.colors.Grey90 }, -- CursorColumn - [3] = { bold = true, reverse = true }, -- StatusLine - [4] = { reverse = true }, -- StatusLineNC - }) screen:attach() command('set cursorcolumn') insert([[ @@ -341,22 +324,22 @@ describe('API/win', function() local oldwin = curwin() command('vsplit') screen:expect([[ - aa{2:a} │aa{2:a} | - bb{2:b} │bb{2:b} | - cc{2:c} │cc{2:c} | + aa{21:a} │aa{21:a} | + bb{21:b} │bb{21:b} | + cc{21:c} │cc{21:c} | dd^d │ddd | {1:~ }│{1:~ }|*2 - {3:[No Name] [+] }{4:[No Name] [+] }| + {3:[No Name] [+] }{2:[No Name] [+] }| | ]]) api.nvim_win_set_cursor(oldwin, { 2, 0 }) screen:expect([[ - aa{2:a} │{2:a}aa | - bb{2:b} │bbb | - cc{2:c} │{2:c}cc | - dd^d │{2:d}dd | + aa{21:a} │{21:a}aa | + bb{21:b} │bbb | + cc{21:c} │{21:c}cc | + dd^d │{21:d}dd | {1:~ }│{1:~ }|*2 - {3:[No Name] [+] }{4:[No Name] [+] }| + {3:[No Name] [+] }{2:[No Name] [+] }| | ]]) end) @@ -874,22 +857,6 @@ describe('API/win', function() it('with two diff windows', function() local X = api.nvim_get_vvar('maxcol') local screen = Screen.new(45, 22) - screen:set_default_attr_ids({ - [0] = { foreground = Screen.colors.Blue1, bold = true }, - [1] = { foreground = Screen.colors.Blue4, background = Screen.colors.Grey }, - [2] = { foreground = Screen.colors.Brown }, - [3] = { - foreground = Screen.colors.Blue1, - background = Screen.colors.LightCyan1, - bold = true, - }, - [4] = { background = Screen.colors.LightBlue }, - [5] = { foreground = Screen.colors.Blue4, background = Screen.colors.LightGrey }, - [6] = { background = Screen.colors.Plum1 }, - [7] = { background = Screen.colors.Red, bold = true }, - [8] = { reverse = true }, - [9] = { bold = true, reverse = true }, - }) screen:attach() exec([[ set diffopt+=context:2 number @@ -902,35 +869,35 @@ describe('API/win', function() feed('24gg') screen:expect { grid = [[ - {1: }{2: }{3:----------------}│{1: }{2: 1 }{4:00000001! }| - {1: }{2: }{3:----------------}│{1: }{2: 2 }{4:00000002!! }| - {1: }{2: 1 }00000003!!! │{1: }{2: 3 }00000003!!! | - {1: }{2: 2 }00000004!!!! │{1: }{2: 4 }00000004!!!! | - {1:+ }{2: 3 }{5:+-- 14 lines: 00}│{1:+ }{2: 5 }{5:+-- 14 lines: 00}| - {1: }{2: 17 }00000019!!!!!!!!│{1: }{2: 19 }00000019!!!!!!!!| - {1: }{2: 18 }00000020!!!!!!!!│{1: }{2: 20 }00000020!!!!!!!!| - {1: }{2: }{3:----------------}│{1: }{2: 21 }{4:00000025!!!!!!!!}| - {1: }{2: }{3:----------------}│{1: }{2: 22 }{4:00000026!!!!!!!!}| - {1: }{2: }{3:----------------}│{1: }{2: 23 }{4:00000027!!!!!!!!}| - {1: }{2: 19 }00000028!!!!!!!!│{1: }{2: 24 }^00000028!!!!!!!!| - {1: }{2: 20 }00000029!!!!!!!!│{1: }{2: 25 }00000029!!!!!!!!| - {1:+ }{2: 21 }{5:+-- 14 lines: 00}│{1:+ }{2: 26 }{5:+-- 14 lines: 00}| - {1: }{2: 35 }00000044!!!!!!!!│{1: }{2: 40 }00000044!!!!!!!!| - {1: }{2: 36 }00000045!!!!!!!!│{1: }{2: 41 }00000045!!!!!!!!| - {1: }{2: 37 }{4:00000046!!!!!!!!}│{1: }{2: }{3:----------------}| - {1: }{2: 38 }{4:00000047!!!!!!!!}│{1: }{2: }{3:----------------}| - {1: }{2: 39 }{4:00000048!!!!!!!!}│{1: }{2: }{3:----------------}| - {1: }{2: 40 }{4:00000049!!!!!!!!}│{1: }{2: }{3:----------------}| - {1: }{2: 41 }{4:00000050!!!!!!!!}│{1: }{2: }{3:----------------}| - {8:[No Name] [+] }{9:[No Name] [+] }| + {7: }{8: }{23:----------------}│{7: }{8: 1 }{22:00000001! }| + {7: }{8: }{23:----------------}│{7: }{8: 2 }{22:00000002!! }| + {7: }{8: 1 }00000003!!! │{7: }{8: 3 }00000003!!! | + {7: }{8: 2 }00000004!!!! │{7: }{8: 4 }00000004!!!! | + {7:+ }{8: 3 }{13:+-- 14 lines: 00}│{7:+ }{8: 5 }{13:+-- 14 lines: 00}| + {7: }{8: 17 }00000019!!!!!!!!│{7: }{8: 19 }00000019!!!!!!!!| + {7: }{8: 18 }00000020!!!!!!!!│{7: }{8: 20 }00000020!!!!!!!!| + {7: }{8: }{23:----------------}│{7: }{8: 21 }{22:00000025!!!!!!!!}| + {7: }{8: }{23:----------------}│{7: }{8: 22 }{22:00000026!!!!!!!!}| + {7: }{8: }{23:----------------}│{7: }{8: 23 }{22:00000027!!!!!!!!}| + {7: }{8: 19 }00000028!!!!!!!!│{7: }{8: 24 }^00000028!!!!!!!!| + {7: }{8: 20 }00000029!!!!!!!!│{7: }{8: 25 }00000029!!!!!!!!| + {7:+ }{8: 21 }{13:+-- 14 lines: 00}│{7:+ }{8: 26 }{13:+-- 14 lines: 00}| + {7: }{8: 35 }00000044!!!!!!!!│{7: }{8: 40 }00000044!!!!!!!!| + {7: }{8: 36 }00000045!!!!!!!!│{7: }{8: 41 }00000045!!!!!!!!| + {7: }{8: 37 }{22:00000046!!!!!!!!}│{7: }{8: }{23:----------------}| + {7: }{8: 38 }{22:00000047!!!!!!!!}│{7: }{8: }{23:----------------}| + {7: }{8: 39 }{22:00000048!!!!!!!!}│{7: }{8: }{23:----------------}| + {7: }{8: 40 }{22:00000049!!!!!!!!}│{7: }{8: }{23:----------------}| + {7: }{8: 41 }{22:00000050!!!!!!!!}│{7: }{8: }{23:----------------}| + {2:[No Name] [+] }{3:[No Name] [+] }| | ]], } screen:try_resize(45, 3) screen:expect { grid = [[ - {1: }{2: 19 }00000028!!!!!!!!│{1: }{2: 24 }^00000028!!!!!!!!| - {8:[No Name] [+] }{9:[No Name] [+] }| + {7: }{8: 19 }00000028!!!!!!!!│{7: }{8: 24 }^00000028!!!!!!!!| + {2:[No Name] [+] }{3:[No Name] [+] }| | ]], } @@ -1008,11 +975,6 @@ describe('API/win', function() it('with wrapped lines', function() local X = api.nvim_get_vvar('maxcol') local screen = Screen.new(45, 22) - screen:set_default_attr_ids({ - [0] = { foreground = Screen.colors.Blue1, bold = true }, - [1] = { foreground = Screen.colors.Brown }, - [2] = { background = Screen.colors.Yellow }, - }) screen:attach() exec([[ set number cpoptions+=n @@ -1035,26 +997,26 @@ describe('API/win', function() ) screen:expect { grid = [[ - {1: 1 }^foobar-foobar-foobar-foobar-foobar-foobar| + {8: 1 }^foobar-foobar-foobar-foobar-foobar-foobar| -foobar-foobar-foobar-foobar-foobar-foobar-fo| obar-foobar-foobar-foobar-foobar-foobar-fooba| r-foobar-foobar-foobar-foobar-foobar-foobar-f| oobar-foobar-foobar-foobar-foobar-foobar-foob| ar-foobar-foobar-foobar-foobar- | - {1: 2 }foobar-foobar-foobar-foobar-foobar-foobar| + {8: 2 }foobar-foobar-foobar-foobar-foobar-foobar| -foobar-foobar-foobar-foobar-foobar-foobar-fo| - obar-foobar-fo{2:???????????????}obar-foobar-foob| + obar-foobar-fo{10:???????????????}obar-foobar-foob| ar-foobar-foobar-foobar-foobar-foobar-foobar-| foobar-foobar-foobar-foobar-foobar-foobar-foo| bar-foobar-foobar-foobar-foobar-foobar-foobar| - | - {1: 3 }foobar-foobar-foobar-foobar-foobar-foobar| + {8: 3 }foobar-foobar-foobar-foobar-foobar-foobar| -foobar-foobar-foobar-foobar-foobar-foobar-fo| obar-foobar-foobar-foobar-foobar-foobar-fooba| r-foobar-foobar-foobar-foobar-foobar-foobar-f| - oobar-foobar-foobar-foob{2:!!!!!!!!!!!!!!!!!!!!!}| - {2:!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!}| - {2:!!!!!!!!!}ar-foobar-foobar-foobar-foobar-fooba| + oobar-foobar-foobar-foob{10:!!!!!!!!!!!!!!!!!!!!!}| + {10:!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!}| + {10:!!!!!!!!!}ar-foobar-foobar-foobar-foobar-fooba| r-foobar-foobar- | | ]], @@ -1062,7 +1024,7 @@ describe('API/win', function() screen:try_resize(45, 2) screen:expect { grid = [[ - {1: 1 }^foobar-foobar-foobar-foobar-foobar-foobar| + {8: 1 }^foobar-foobar-foobar-foobar-foobar-foobar| | ]], } @@ -2563,10 +2525,6 @@ describe('API/win', function() it('updates statusline when moving bottom split', function() local screen = Screen.new(10, 10) - screen:set_default_attr_ids({ - [0] = { bold = true, foreground = Screen.colors.Blue }, -- NonText - [1] = { bold = true, reverse = true }, -- StatusLine - }) screen:attach() exec([[ set laststatus=0 @@ -2575,10 +2533,10 @@ describe('API/win', function() ]]) screen:expect([[ ^ | - {0:~ }|*3 - {1:[No Name] }| + {1:~ }|*3 + {3:[No Name] }| | - {0:~ }|*3 + {1:~ }|*3 | ]]) end) diff --git a/test/functional/core/fileio_spec.lua b/test/functional/core/fileio_spec.lua index 5b0be1e83c..1c4f42eb43 100644 --- a/test/functional/core/fileio_spec.lua +++ b/test/functional/core/fileio_spec.lua @@ -276,11 +276,6 @@ describe('fileio', function() write_file('Xtest-overwrite-forced', 'foobar') command('set nofixendofline') local screen = Screen.new(40, 4) - screen:set_default_attr_ids({ - [1] = { bold = true, foreground = Screen.colors.Blue1 }, - [2] = { foreground = Screen.colors.Grey100, background = Screen.colors.Red }, - [3] = { bold = true, foreground = Screen.colors.SeaGreen4 }, - }) screen:attach() command('set shortmess-=F') @@ -300,9 +295,9 @@ describe('fileio', function() -- use async feed_command because nvim basically hangs on the prompt feed_command('w') screen:expect([[ - {2:WARNING: The file has been changed since}| - {2: reading it!!!} | - {3:Do you really want to write to it (y/n)?}| + {9:WARNING: The file has been changed since}| + {9: reading it!!!} | + {6:Do you really want to write to it (y/n)?}| ^ | ]]) diff --git a/test/functional/core/job_spec.lua b/test/functional/core/job_spec.lua index e1efc07452..bf10033f53 100644 --- a/test/functional/core/job_spec.lua +++ b/test/functional/core/job_spec.lua @@ -910,11 +910,6 @@ describe('jobs', function() it('hides cursor and flushes messages before blocking', function() local screen = Screen.new(50, 6) - screen:set_default_attr_ids({ - [0] = { foreground = Screen.colors.Blue, bold = true }, -- NonText - [1] = { bold = true, reverse = true }, -- MsgSeparator - [2] = { bold = true, foreground = Screen.colors.SeaGreen }, -- MoreMsg - }) screen:attach() command([[let g:id = jobstart([v:progpath, '--clean', '--headless'])]]) source([[ @@ -928,8 +923,8 @@ describe('jobs', function() screen:expect { grid = [[ | - {0:~ }|*2 - {1: }| + {1:~ }|*2 + {3: }| aaa | bbb | ]], @@ -938,11 +933,11 @@ describe('jobs', function() screen:expect { grid = [[ | - {1: }| + {3: }| aaa | bbb | ccc | - {2:Press ENTER or type command to continue}^ | + {6:Press ENTER or type command to continue}^ | ]], } feed('<CR>') diff --git a/test/functional/editor/completion_spec.lua b/test/functional/editor/completion_spec.lua index 62bb7e19f3..a28e449f49 100644 --- a/test/functional/editor/completion_spec.lua +++ b/test/functional/editor/completion_spec.lua @@ -18,19 +18,10 @@ describe('completion', function() clear() screen = Screen.new(60, 8) screen:attach() - screen:set_default_attr_ids({ - [0] = { bold = true, foreground = Screen.colors.Blue }, - [1] = { background = Screen.colors.LightMagenta }, - [2] = { background = Screen.colors.Grey }, - [3] = { bold = true }, - [4] = { bold = true, foreground = Screen.colors.SeaGreen }, - [5] = { foreground = Screen.colors.Red }, - [6] = { background = Screen.colors.Black }, - [7] = { foreground = Screen.colors.White, background = Screen.colors.Red }, - [8] = { reverse = true }, - [9] = { bold = true, reverse = true }, - [10] = { foreground = Screen.colors.Grey0, background = Screen.colors.Yellow }, - }) + screen:add_extra_attr_ids { + [100] = { foreground = Screen.colors.Gray0, background = Screen.colors.Yellow }, + [101] = { background = Screen.colors.Gray0 }, + } end) describe('v:completed_item', function() @@ -42,15 +33,15 @@ describe('completion', function() screen:expect([[ foo | foo^ | - {0:~ }|*5 - {3:-- Keyword Local completion (^N^P) The only match} | + {1:~ }|*5 + {5:-- Keyword Local completion (^N^P) The only match} | ]]) feed('<C-e>') screen:expect([[ foo | ^ | - {0:~ }|*5 - {3:-- INSERT --} | + {1:~ }|*5 + {5:-- INSERT --} | ]]) feed('<ESC>') eq({}, eval('v:completed_item')) @@ -104,10 +95,10 @@ describe('completion', function() eq('foo', eval('getline(1)')) screen:expect([[ foo^ | - {2:bar foobaz baz }{0: }| - {1:abbr kind menu }{0: }| - {0:~ }|*4 - {3:-- Omni completion (^O^N^P) }{4:match 1 of 2} | + {12:bar foobaz baz }{1: }| + {4:abbr kind menu }{1: }| + {1:~ }|*4 + {5:-- Omni completion (^O^N^P) }{6:match 1 of 2} | ]]) eq({ word = 'foo', @@ -136,24 +127,24 @@ describe('completion', function() screen:expect([[ foo | ^ | - {0:~ }|*5 - {3:-- INSERT --} | + {1:~ }|*5 + {5:-- INSERT --} | ]]) feed('<C-x>') -- the ^X prompt, only test this once screen:expect([[ foo | ^ | - {0:~ }|*5 - {3:-- ^X mode (^]^D^E^F^I^K^L^N^O^Ps^U^V^Y)} | + {1:~ }|*5 + {5:-- ^X mode (^]^D^E^F^I^K^L^N^O^Ps^U^V^Y)} | ]]) feed('<C-n>') screen:expect([[ foo | foo^ | - {2:foo }{0: }| - {0:~ }|*4 - {3:-- Keyword Local completion (^N^P) The only match} | + {12:foo }{1: }| + {1:~ }|*4 + {5:-- Keyword Local completion (^N^P) The only match} | ]]) feed('bar<ESC>') eq('foobar', eval('getline(2)')) @@ -162,9 +153,9 @@ describe('completion', function() foo | foobar | foo^ | - {2:foo }{0: }| - {0:~ }|*3 - {3:-- INSERT --} | + {12:foo }{1: }| + {1:~ }|*3 + {5:-- INSERT --} | ]]) eq('foo', eval('getline(3)')) end) @@ -174,16 +165,16 @@ describe('completion', function() screen:expect([[ foo | ^ | - {2:foo }{0: }| - {0:~ }|*4 - {3:-- Keyword Local completion (^N^P) The only match} | + {12:foo }{1: }| + {1:~ }|*4 + {5:-- Keyword Local completion (^N^P) The only match} | ]]) feed('<C-y>') screen:expect([[ foo | foo^ | - {0:~ }|*5 - {3:-- INSERT --} | + {1:~ }|*5 + {5:-- INSERT --} | ]]) feed('<ESC>') eq('foo', eval('getline(2)')) @@ -191,9 +182,9 @@ describe('completion', function() screen:expect([[ foo |*2 ^ | - {2:foo }{0: }| - {0:~ }|*3 - {3:-- INSERT --} | + {12:foo }{1: }| + {1:~ }|*3 + {5:-- INSERT --} | ]]) feed('<C-y><ESC>') eq('foo', eval('getline(3)')) @@ -204,16 +195,16 @@ describe('completion', function() screen:expect([[ foo | ^ | - {1:foo }{0: }| - {0:~ }|*4 - {3:-- Keyword Local completion (^N^P) }{5:Back at original} | + {4:foo }{1: }| + {1:~ }|*4 + {5:-- Keyword Local completion (^N^P) }{19:Back at original} | ]]) feed('b') screen:expect([[ foo | b^ | - {0:~ }|*5 - {3:-- Keyword Local completion (^N^P) }{5:Back at original} | + {1:~ }|*5 + {5:-- Keyword Local completion (^N^P) }{19:Back at original} | ]]) feed('ar<ESC>') eq('bar', eval('getline(2)')) @@ -222,9 +213,9 @@ describe('completion', function() foo | bar | ^ | - {1:foo }{0: }| - {0:~ }|*3 - {3:-- INSERT --} | + {4:foo }{1: }| + {1:~ }|*3 + {5:-- INSERT --} | ]]) feed('bar<ESC>') eq('bar', eval('getline(3)')) @@ -235,15 +226,15 @@ describe('completion', function() screen:expect([[ foo | ^ | - {1:foo }{0: }| - {0:~ }|*4 - {3:-- Keyword Local completion (^N^P) }{5:Back at original} | + {4:foo }{1: }| + {1:~ }|*4 + {5:-- Keyword Local completion (^N^P) }{19:Back at original} | ]]) feed('<ESC>') screen:expect([[ foo | ^ | - {0:~ }|*5 + {1:~ }|*5 | ]]) eq('', eval('getline(2)')) @@ -252,16 +243,16 @@ describe('completion', function() foo | | ^ | - {1:foo }{0: }| - {0:~ }|*3 - {3:-- INSERT --} | + {4:foo }{1: }| + {1:~ }|*3 + {5:-- INSERT --} | ]]) feed('<ESC>') screen:expect([[ foo | | ^ | - {0:~ }|*4 + {1:~ }|*4 | ]]) eq('', eval('getline(3)')) @@ -367,44 +358,44 @@ describe('completion', function() feed('i<C-x><C-u>') screen:expect([[ ^ | - {1:January }{6: }{0: }| - {1:February }{6: }{0: }| - {1:March }{6: }{0: }| - {1:April }{2: }{0: }| - {1:May }{2: }{0: }| - {1:June }{2: }{0: }| - {3:-- User defined completion (^U^N^P) }{5:Back at original} | + {4:January }{101: }{1: }| + {4:February }{101: }{1: }| + {4:March }{101: }{1: }| + {4:April }{12: }{1: }| + {4:May }{12: }{1: }| + {4:June }{12: }{1: }| + {5:-- User defined completion (^U^N^P) }{19:Back at original} | ]]) feed('u') screen:expect([[ u^ | - {1:January }{0: }| - {1:February }{0: }| - {1:June }{0: }| - {1:July }{0: }| - {1:August }{0: }| - {0:~ }| - {3:-- User defined completion (^U^N^P) }{5:Back at original} | + {4:January }{1: }| + {4:February }{1: }| + {4:June }{1: }| + {4:July }{1: }| + {4:August }{1: }| + {1:~ }| + {5:-- User defined completion (^U^N^P) }{19:Back at original} | ]]) feed('g') screen:expect([[ ug^ | - {1:August }{0: }| - {0:~ }|*5 - {3:-- User defined completion (^U^N^P) }{5:Back at original} | + {4:August }{1: }| + {1:~ }|*5 + {5:-- User defined completion (^U^N^P) }{19:Back at original} | ]]) feed('<Down>') screen:expect([[ ug^ | - {2:August }{0: }| - {0:~ }|*5 - {3:-- User defined completion (^U^N^P) The only match} | + {12:August }{1: }| + {1:~ }|*5 + {5:-- User defined completion (^U^N^P) The only match} | ]]) feed('<C-y>') screen:expect([[ August^ | - {0:~ }|*6 - {3:-- INSERT --} | + {1:~ }|*6 + {5:-- INSERT --} | ]]) expect('August') end) @@ -414,45 +405,45 @@ describe('completion', function() screen:expect([[ | Ja^ | - {1:January }{0: }| - {0:~ }|*4 - {3:-- User defined completion (^U^N^P) }{5:Back at original} | + {4:January }{1: }| + {1:~ }|*4 + {5:-- User defined completion (^U^N^P) }{19:Back at original} | ]]) feed('<BS>') screen:expect([[ | J^ | - {1:January }{0: }| - {1:June }{0: }| - {1:July }{0: }| - {0:~ }|*2 - {3:-- User defined completion (^U^N^P) }{5:Back at original} | + {4:January }{1: }| + {4:June }{1: }| + {4:July }{1: }| + {1:~ }|*2 + {5:-- User defined completion (^U^N^P) }{19:Back at original} | ]]) feed('<C-n>') screen:expect([[ | January^ | - {2:January }{0: }| - {1:June }{0: }| - {1:July }{0: }| - {0:~ }|*2 - {3:-- User defined completion (^U^N^P) }{4:match 1 of 3} | + {12:January }{1: }| + {4:June }{1: }| + {4:July }{1: }| + {1:~ }|*2 + {5:-- User defined completion (^U^N^P) }{6:match 1 of 3} | ]]) feed('<C-n>') screen:expect([[ | June^ | - {1:January }{0: }| - {2:June }{0: }| - {1:July }{0: }| - {0:~ }|*2 - {3:-- User defined completion (^U^N^P) }{4:match 2 of 3} | + {4:January }{1: }| + {12:June }{1: }| + {4:July }{1: }| + {1:~ }|*2 + {5:-- User defined completion (^U^N^P) }{6:match 2 of 3} | ]]) feed('<Esc>') screen:expect([[ | Jun^e | - {0:~ }|*5 + {1:~ }|*5 | ]]) feed('.') @@ -460,7 +451,7 @@ describe('completion', function() | June | Jun^e | - {0:~ }|*4 + {1:~ }|*4 | ]]) expect([[ @@ -485,46 +476,46 @@ describe('completion', function() feed('i<C-r>=TestComplete()<CR>') screen:expect([[ ^ | - {1:0 }{6: }{0: }| - {1:1 }{2: }{0: }| - {1:2 }{2: }{0: }| - {1:3 }{2: }{0: }| - {1:4 }{2: }{0: }| - {1:5 }{2: }{0: }| - {3:-- INSERT --} | + {4:0 }{101: }{1: }| + {4:1 }{12: }{1: }| + {4:2 }{12: }{1: }| + {4:3 }{12: }{1: }| + {4:4 }{12: }{1: }| + {4:5 }{12: }{1: }| + {5:-- INSERT --} | ]]) feed('7') screen:expect([[ 7^ | - {1:7 }{6: }{0: }| - {1:70 }{6: }{0: }| - {1:71 }{6: }{0: }| - {1:72 }{2: }{0: }| - {1:73 }{2: }{0: }| - {1:74 }{2: }{0: }| - {3:-- INSERT --} | + {4:7 }{101: }{1: }| + {4:70 }{101: }{1: }| + {4:71 }{101: }{1: }| + {4:72 }{12: }{1: }| + {4:73 }{12: }{1: }| + {4:74 }{12: }{1: }| + {5:-- INSERT --} | ]]) feed('<c-n>') screen:expect([[ 7^ | - {2:7 }{6: }{0: }| - {1:70 }{6: }{0: }| - {1:71 }{6: }{0: }| - {1:72 }{2: }{0: }| - {1:73 }{2: }{0: }| - {1:74 }{2: }{0: }| - {3:-- INSERT --} | + {12:7 }{101: }{1: }| + {4:70 }{101: }{1: }| + {4:71 }{101: }{1: }| + {4:72 }{12: }{1: }| + {4:73 }{12: }{1: }| + {4:74 }{12: }{1: }| + {5:-- INSERT --} | ]]) feed('<c-n>') screen:expect([[ 70^ | - {1:7 }{6: }{0: }| - {2:70 }{6: }{0: }| - {1:71 }{6: }{0: }| - {1:72 }{2: }{0: }| - {1:73 }{2: }{0: }| - {1:74 }{2: }{0: }| - {3:-- INSERT --} | + {4:7 }{101: }{1: }| + {12:70 }{101: }{1: }| + {4:71 }{101: }{1: }| + {4:72 }{12: }{1: }| + {4:73 }{12: }{1: }| + {4:74 }{12: }{1: }| + {5:-- INSERT --} | ]]) end) @@ -532,107 +523,107 @@ describe('completion', function() feed('i<C-r>=TestComplete()<CR>') screen:expect([[ ^ | - {1:0 }{6: }{0: }| - {1:1 }{2: }{0: }| - {1:2 }{2: }{0: }| - {1:3 }{2: }{0: }| - {1:4 }{2: }{0: }| - {1:5 }{2: }{0: }| - {3:-- INSERT --} | + {4:0 }{101: }{1: }| + {4:1 }{12: }{1: }| + {4:2 }{12: }{1: }| + {4:3 }{12: }{1: }| + {4:4 }{12: }{1: }| + {4:5 }{12: }{1: }| + {5:-- INSERT --} | ]]) feed('<PageDown>') screen:expect([[ ^ | - {1:0 }{6: }{0: }| - {1:1 }{2: }{0: }| - {1:2 }{2: }{0: }| - {2:3 }{0: }| - {1:4 }{2: }{0: }| - {1:5 }{2: }{0: }| - {3:-- INSERT --} | + {4:0 }{101: }{1: }| + {4:1 }{12: }{1: }| + {4:2 }{12: }{1: }| + {12:3 }{1: }| + {4:4 }{12: }{1: }| + {4:5 }{12: }{1: }| + {5:-- INSERT --} | ]]) feed('<PageDown>') screen:expect([[ ^ | - {1:5 }{6: }{0: }| - {1:6 }{2: }{0: }| - {2:7 }{0: }| - {1:8 }{2: }{0: }| - {1:9 }{2: }{0: }| - {1:10 }{2: }{0: }| - {3:-- INSERT --} | + {4:5 }{101: }{1: }| + {4:6 }{12: }{1: }| + {12:7 }{1: }| + {4:8 }{12: }{1: }| + {4:9 }{12: }{1: }| + {4:10 }{12: }{1: }| + {5:-- INSERT --} | ]]) feed('<Down>') screen:expect([[ ^ | - {1:5 }{6: }{0: }| - {1:6 }{2: }{0: }| - {1:7 }{2: }{0: }| - {2:8 }{0: }| - {1:9 }{2: }{0: }| - {1:10 }{2: }{0: }| - {3:-- INSERT --} | + {4:5 }{101: }{1: }| + {4:6 }{12: }{1: }| + {4:7 }{12: }{1: }| + {12:8 }{1: }| + {4:9 }{12: }{1: }| + {4:10 }{12: }{1: }| + {5:-- INSERT --} | ]]) feed('<PageUp>') screen:expect([[ ^ | - {1:2 }{6: }{0: }| - {1:3 }{2: }{0: }| - {2:4 }{0: }| - {1:5 }{2: }{0: }| - {1:6 }{2: }{0: }| - {1:7 }{2: }{0: }| - {3:-- INSERT --} | + {4:2 }{101: }{1: }| + {4:3 }{12: }{1: }| + {12:4 }{1: }| + {4:5 }{12: }{1: }| + {4:6 }{12: }{1: }| + {4:7 }{12: }{1: }| + {5:-- INSERT --} | ]]) feed('<PageUp>') -- stop on first item screen:expect([[ ^ | - {2:0 }{6: }{0: }| - {1:1 }{2: }{0: }| - {1:2 }{2: }{0: }| - {1:3 }{2: }{0: }| - {1:4 }{2: }{0: }| - {1:5 }{2: }{0: }| - {3:-- INSERT --} | + {12:0 }{101: }{1: }| + {4:1 }{12: }{1: }| + {4:2 }{12: }{1: }| + {4:3 }{12: }{1: }| + {4:4 }{12: }{1: }| + {4:5 }{12: }{1: }| + {5:-- INSERT --} | ]]) feed('<PageUp>') -- when on first item, unselect screen:expect([[ ^ | - {1:0 }{6: }{0: }| - {1:1 }{2: }{0: }| - {1:2 }{2: }{0: }| - {1:3 }{2: }{0: }| - {1:4 }{2: }{0: }| - {1:5 }{2: }{0: }| - {3:-- INSERT --} | + {4:0 }{101: }{1: }| + {4:1 }{12: }{1: }| + {4:2 }{12: }{1: }| + {4:3 }{12: }{1: }| + {4:4 }{12: }{1: }| + {4:5 }{12: }{1: }| + {5:-- INSERT --} | ]]) feed('<PageUp>') -- when unselected, select last item screen:expect([[ ^ | - {1:95 }{2: }{0: }| - {1:96 }{2: }{0: }| - {1:97 }{2: }{0: }| - {1:98 }{2: }{0: }| - {1:99 }{2: }{0: }| - {2:100 }{6: }{0: }| - {3:-- INSERT --} | + {4:95 }{12: }{1: }| + {4:96 }{12: }{1: }| + {4:97 }{12: }{1: }| + {4:98 }{12: }{1: }| + {4:99 }{12: }{1: }| + {12:100 }{101: }{1: }| + {5:-- INSERT --} | ]]) feed('<PageUp>') screen:expect([[ ^ | - {1:94 }{2: }{0: }| - {1:95 }{2: }{0: }| - {2:96 }{0: }| - {1:97 }{2: }{0: }| - {1:98 }{2: }{0: }| - {1:99 }{6: }{0: }| - {3:-- INSERT --} | + {4:94 }{12: }{1: }| + {4:95 }{12: }{1: }| + {12:96 }{1: }| + {4:97 }{12: }{1: }| + {4:98 }{12: }{1: }| + {4:99 }{101: }{1: }| + {5:-- INSERT --} | ]]) feed('<cr>') screen:expect([[ 96^ | - {0:~ }|*6 - {3:-- INSERT --} | + {1:~ }|*6 + {5:-- INSERT --} | ]]) end) end) @@ -668,9 +659,9 @@ describe('completion', function() screen:expect([[ inc uninc indent unindent | ind^ | - {2:indent }{0: }| - {0:~ }|*4 - {3:-- Keyword Local completion (^N^P) }{4:match 1 of 2} | + {12:indent }{1: }| + {1:~ }|*4 + {5:-- Keyword Local completion (^N^P) }{6:match 1 of 2} | ]]) -- Indents when the item is selected @@ -678,8 +669,8 @@ describe('completion', function() screen:expect([[ inc uninc indent unindent | indent^ | - {0:~ }|*5 - {3:-- INSERT --} | + {1:~ }|*5 + {5:-- INSERT --} | ]]) -- Indents when completion is exited using ESC. feed('<CR>in<C-N><BS>d<Esc>') @@ -687,7 +678,7 @@ describe('completion', function() inc uninc indent unindent | indent | in^d | - {0:~ }|*4 + {1:~ }|*4 | ]]) -- Works for unindenting too. @@ -699,9 +690,9 @@ describe('completion', function() indent | ind | unind^ | - {0:~ }{2: unindent }{0: }| - {0:~ }|*2 - {3:-- Keyword Local completion (^N^P) }{4:match 1 of 2} | + {1:~ }{12: unindent }{1: }| + {1:~ }|*2 + {5:-- Keyword Local completion (^N^P) }{6:match 1 of 2} | ]]) -- Works when going back and forth. feed('<BS>c') @@ -710,9 +701,9 @@ describe('completion', function() indent | ind | uninc^ | - {0:~ }{2: uninc }{0: }| - {0:~ }|*2 - {3:-- Keyword Local completion (^N^P) }{4:match 1 of 2} | + {1:~ }{12: uninc }{1: }| + {1:~ }|*2 + {5:-- Keyword Local completion (^N^P) }{6:match 1 of 2} | ]]) feed('<BS>d') screen:expect([[ @@ -720,9 +711,9 @@ describe('completion', function() indent | ind | unind^ | - {0:~ }{2: unindent }{0: }| - {0:~ }|*2 - {3:-- Keyword Local completion (^N^P) }{4:match 1 of 2} | + {1:~ }{12: unindent }{1: }| + {1:~ }|*2 + {5:-- Keyword Local completion (^N^P) }{6:match 1 of 2} | ]]) feed('<C-N><C-N><C-Y><Esc>') screen:expect([[ @@ -730,7 +721,7 @@ describe('completion', function() indent | ind | uninden^t | - {0:~ }|*3 + {1:~ }|*3 | ]]) end) @@ -741,15 +732,15 @@ describe('completion', function() screen:expect([[ ^foo | bar | - {0:~ }|*5 + {1:~ }|*5 | ]]) feed('A<C-x><C-l>') screen:expect([[ foo^ | bar | - {0:~ }|*5 - {3:-- Whole line completion (^L^N^P) }{7:Pattern not found} | + {1:~ }|*5 + {5:-- Whole line completion (^L^N^P) }{9:Pattern not found} | ]]) eq(-1, eval('foldclosed(1)')) end) @@ -761,10 +752,10 @@ describe('completion', function() screen:expect([[ foobar fooegg | fooegg^ | - {1:foobar }{0: }| - {2:fooegg }{0: }| - {0:~ }|*3 - {3:-- Keyword completion (^N^P) }{4:match 1 of 2} | + {4:foobar }{1: }| + {12:fooegg }{1: }| + {1:~ }|*3 + {5:-- Keyword completion (^N^P) }{6:match 1 of 2} | ]]) assert_alive() @@ -773,10 +764,10 @@ describe('completion', function() grid = [[ foobar fooegg | fooegg^ | - {1:foobar }{0: }| - {2:fooegg }{0: }| - {0:~ }|*3 - {3:-- Keyword completion (^N^P) }{4:match 1 of 2} | + {4:foobar }{1: }| + {12:fooegg }{1: }| + {1:~ }|*3 + {5:-- Keyword completion (^N^P) }{6:match 1 of 2} | ]], unchanged = true, } @@ -786,10 +777,10 @@ describe('completion', function() screen:expect([[ foobar fooegg | foobar^ | - {2:foobar }{0: }| - {1:fooegg }{0: }| - {0:~ }|*3 - {3:-- Keyword completion (^N^P) }{4:match 2 of 2} | + {12:foobar }{1: }| + {4:fooegg }{1: }| + {1:~ }|*3 + {5:-- Keyword completion (^N^P) }{6:match 2 of 2} | ]]) end) @@ -800,7 +791,7 @@ describe('completion', function() screen:expect { grid = [[ | - {0:~ }|*6 + {1:~ }|*6 :lua CURRENT_TESTING_VAR^ | ]], } @@ -813,8 +804,8 @@ describe('completion', function() screen:expect { grid = [[ | - {0:~ }|*5 - {10:CURRENT_TESTING_BAR}{9: CURRENT_TESTING_FOO }| + {1:~ }|*5 + {100:CURRENT_TESTING_BAR}{3: CURRENT_TESTING_FOO }| :lua CURRENT_TESTING_BAR^ | ]], unchanged = true, @@ -847,30 +838,30 @@ describe('completion', function() feed('ifoo faa fee f') screen:expect([[ | - {8:[No Name] }| - {0::}foo faa fee f^ | - {0:~ }|*3 - {9:[Command Line] }| - {3:-- INSERT --} | + {2:[No Name] }| + {1::}foo faa fee f^ | + {1:~ }|*3 + {3:[Command Line] }| + {5:-- INSERT --} | ]]) feed('<c-x><c-n>') screen:expect([[ | - {8:[No Name] }| - {0::}foo faa fee foo^ | - {0:~ }{2: foo }{0: }| - {0:~ }{1: faa }{0: }| - {0:~ }{1: fee }{0: }| - {9:[Command Line] }| - {3:-- Keyword Local completion (^N^P) }{4:match 1 of 3} | + {2:[No Name] }| + {1::}foo faa fee foo^ | + {1:~ }{12: foo }{1: }| + {1:~ }{4: faa }{1: }| + {1:~ }{4: fee }{1: }| + {3:[Command Line] }| + {5:-- Keyword Local completion (^N^P) }{6:match 1 of 3} | ]]) feed('<c-c>') screen:expect([[ | - {8:[No Name] }| - {0::}foo faa fee foo | - {0:~ }|*3 - {9:[Command Line] }| + {2:[No Name] }| + {1::}foo faa fee foo | + {1:~ }|*3 + {3:[Command Line] }| :foo faa fee foo^ | ]]) end) @@ -903,9 +894,9 @@ describe('completion', function() feed('i<C-r>=TestComplete()<CR>') screen:expect([[ ^ | - {1:1 3 2 }{0: }| - {0:~ }|*5 - {3:-- INSERT --} | + {4:1 3 2 }{1: }| + {1:~ }|*5 + {5:-- INSERT --} | ]]) end) end) @@ -918,12 +909,12 @@ describe('completion', function() grid = [[ *backers.txt* Nvim | Xnull^ | - {2:Xnull }{6: } | - {1:Xoxomoon }{6: } | - {1:Xu }{6: } NVIM REFERENCE MANUAL | - {1:Xpayn }{2: } | - {1:Xinity }{2: } | - {3:-- Keyword Local completion (^N^P) }{4:match 1 of 7} | + {12:Xnull }{101: } | + {4:Xoxomoon }{101: } | + {4:Xu }{101: } NVIM REFERENCE MANUAL | + {4:Xpayn }{12: } | + {4:Xinity }{12: } | + {5:-- Keyword Local completion (^N^P) }{6:match 1 of 7} | ]], } end) @@ -950,8 +941,8 @@ describe('completion', function() bar | foobar | f^ | - {0:~ }|*3 - {3:-- Keyword completion (^N^P) }{5:Back at original} | + {1:~ }|*3 + {5:-- Keyword completion (^N^P) }{19:Back at original} | ]], popupmenu = { anchor = { 1, 3, 0 }, @@ -970,8 +961,8 @@ describe('completion', function() bar | foobar | foob^ | - {0:~ }|*3 - {3:-- Keyword completion (^N^P) }{5:Back at original} | + {1:~ }|*3 + {5:-- Keyword completion (^N^P) }{19:Back at original} | ]], popupmenu = { anchor = { 1, 3, 0 }, @@ -992,10 +983,10 @@ describe('completion', function() bar | foobar | f^ | - {1:foo }{0: }| - {1:foobar }{0: }| - {0:~ }| - {3:-- Keyword completion (^N^P) }{5:Back at original} | + {4:foo }{1: }| + {4:foobar }{1: }| + {1:~ }| + {5:-- Keyword completion (^N^P) }{19:Back at original} | ]]) eq( { completed_item = {}, width = 15, height = 2, size = 2, col = 0, row = 4, scrollbar = false }, @@ -1007,10 +998,10 @@ describe('completion', function() bar | foobar | foo^ | - {2:foo }{0: }| - {1:foobar }{0: }| - {0:~ }| - {3:-- Keyword completion (^N^P) }{4:match 1 of 2} | + {12:foo }{1: }| + {4:foobar }{1: }| + {1:~ }| + {5:-- Keyword completion (^N^P) }{6:match 1 of 2} | ]]) eq('foo', eval('g:word')) feed('<C-N>') @@ -1019,10 +1010,10 @@ describe('completion', function() bar | foobar | foobar^ | - {1:foo }{0: }| - {2:foobar }{0: }| - {0:~ }| - {3:-- Keyword completion (^N^P) }{4:match 2 of 2} | + {4:foo }{1: }| + {12:foobar }{1: }| + {1:~ }| + {5:-- Keyword completion (^N^P) }{6:match 2 of 2} | ]]) eq('foobar', eval('g:word')) feed('<up>') @@ -1031,10 +1022,10 @@ describe('completion', function() bar | foobar | foobar^ | - {2:foo }{0: }| - {1:foobar }{0: }| - {0:~ }| - {3:-- Keyword completion (^N^P) }{4:match 1 of 2} | + {12:foo }{1: }| + {4:foobar }{1: }| + {1:~ }| + {5:-- Keyword completion (^N^P) }{6:match 1 of 2} | ]]) eq('foo', eval('g:word')) feed('<down>') @@ -1043,10 +1034,10 @@ describe('completion', function() bar | foobar | foobar^ | - {1:foo }{0: }| - {2:foobar }{0: }| - {0:~ }| - {3:-- Keyword completion (^N^P) }{4:match 2 of 2} | + {4:foo }{1: }| + {12:foobar }{1: }| + {1:~ }| + {5:-- Keyword completion (^N^P) }{6:match 2 of 2} | ]]) eq('foobar', eval('g:word')) feed('<esc>') @@ -1061,11 +1052,11 @@ describe('completion', function() hullo | heeee | hello^ | - {2:hello }{0: }| - {1:hullo }{0: }| - {1:heeee }{0: }| - {0:~ }|*6 - {3:-- }{4:match 1 of 3} | + {12:hello }{1: }| + {4:hullo }{1: }| + {4:heeee }{1: }| + {1:~ }|*6 + {5:-- }{6:match 1 of 3} | ]]) command([[call timer_start(100, { -> execute('stopinsert') })]]) vim.uv.sleep(200) @@ -1075,7 +1066,7 @@ describe('completion', function() hullo | heee^e | hello | - {0:~ }|*9 + {1:~ }|*9 | ]]) end) @@ -1090,9 +1081,9 @@ describe('completion', function() screen:expect([[ ii | ii^ | - {2:ii }{0: }| - {0:~ }|*4 - {3:-- Keyword completion (^N^P) The only match} | + {12:ii }{1: }| + {1:~ }|*4 + {5:-- Keyword completion (^N^P) The only match} | ]]) assert_alive() end) @@ -1129,22 +1120,22 @@ describe('completion', function() screen:expect { grid = [[ foo^ | - {2:foo }{0: }| - {1:bar }{0: }| - {1:foa }{0: }| - {1:.hidden }{0: }| - {0:~ }|*3 - {3:-- }{4:match 1 of 4} | + {12:foo }{1: }| + {4:bar }{1: }| + {4:foa }{1: }| + {4:.hidden }{1: }| + {1:~ }|*3 + {5:-- }{6:match 1 of 4} | ]], } feed('<Esc>ccf<C-n>') screen:expect { grid = [[ foo^ | - {2:foo }{0: }| - {1:foa }{0: }| - {0:~ }|*5 - {3:-- }{4:match 1 of 2} | + {12:foo }{1: }| + {4:foa }{1: }| + {1:~ }|*5 + {5:-- }{6:match 1 of 2} | ]], } end) @@ -1168,10 +1159,10 @@ describe('completion', function() eq(eval('mark'), eval("nvim_buf_get_extmark_by_id(0, ns_id, mark_id, { 'details':1 })")) feed('<Esc>0Yppia<Esc>ggI<C-N>') screen:expect([[ - aaaa{7:^aa}aa | - {2:aaaa } | - {1:aaaaa } | - {3:-- Keyword completion (^N^P) }{4:match 1 of 2} | + aaaa{9:^aa}aa | + {12:aaaa } | + {4:aaaaa } | + {5:-- Keyword completion (^N^P) }{6:match 1 of 2} | ]]) feed('<C-N><C-N><Esc>') eq(eval('mark'), eval("nvim_buf_get_extmark_by_id(0, ns_id, mark_id, { 'details':1 })")) @@ -1180,16 +1171,16 @@ describe('completion', function() feed('<C-N>') screen:expect([[ aaaaa^ | - {1:aaaa } | - {2:aaaaa } | - {3:-- Keyword completion (^N^P) }{4:match 2 of 2} | + {4:aaaa } | + {12:aaaaa } | + {5:-- Keyword completion (^N^P) }{6:match 2 of 2} | ]]) feed('<C-E>') screen:expect([[ - {7:aa}aa^ | + {9:aa}aa^ | aaaa | aaaaa | - {3:-- INSERT --} | + {5:-- INSERT --} | ]]) end) end) diff --git a/test/functional/editor/mode_cmdline_spec.lua b/test/functional/editor/mode_cmdline_spec.lua index 70bdc5d4c2..efd7a37c0b 100644 --- a/test/functional/editor/mode_cmdline_spec.lua +++ b/test/functional/editor/mode_cmdline_spec.lua @@ -48,18 +48,14 @@ describe('cmdline', function() it('redraws statusline when toggling overstrike', function() local screen = Screen.new(60, 4) - screen:set_default_attr_ids({ - [0] = { bold = true, foreground = Screen.colors.Blue }, -- NonText - [1] = { reverse = true, bold = true }, -- StatusLine - }) screen:attach() command('set laststatus=2 statusline=%!mode(1)') feed(':') screen:expect { grid = [[ | - {0:~ }| - {1:c }| + {1:~ }| + {3:c }| :^ | ]], } @@ -67,8 +63,8 @@ describe('cmdline', function() screen:expect { grid = [[ | - {0:~ }| - {1:cr }| + {1:~ }| + {3:cr }| :^ | ]], } diff --git a/test/functional/editor/mode_insert_spec.lua b/test/functional/editor/mode_insert_spec.lua index fb3dda4bf4..fc1e6c4ee4 100644 --- a/test/functional/editor/mode_insert_spec.lua +++ b/test/functional/editor/mode_insert_spec.lua @@ -180,12 +180,6 @@ describe('insert-mode', function() it('multi-char mapping updates screen properly #25626', function() local screen = Screen.new(60, 6) - screen:set_default_attr_ids({ - [0] = { bold = true, foreground = Screen.colors.Blue }, -- NonText - [1] = { bold = true, reverse = true }, -- StatusLine - [2] = { reverse = true }, -- StatusLineNC - [3] = { bold = true }, -- ModeMsg - }) screen:attach() command('vnew') insert('foo\nfoo\nfoo') @@ -197,10 +191,10 @@ describe('insert-mode', function() grid = [[ foo │ | foo │β^jβ | - foo │{0:~ }| - {0:~ }│{0:~ }| - {2:[No Name] [+] }{1:[No Name] [+] }| - {3:-- INSERT --} | + foo │{1:~ }| + {1:~ }│{1:~ }| + {2:[No Name] [+] }{3:[No Name] [+] }| + {5:-- INSERT --} | ]], } feed('k') @@ -208,9 +202,9 @@ describe('insert-mode', function() grid = [[ foo │ | foo │^βββ | - foo │{0:~ }| - {0:~ }│{0:~ }| - {2:[No Name] [+] }{1:[No Name] [+] }| + foo │{1:~ }| + {1:~ }│{1:~ }| + {2:[No Name] [+] }{3:[No Name] [+] }| | ]], } diff --git a/test/functional/editor/tabpage_spec.lua b/test/functional/editor/tabpage_spec.lua index 0b26494436..c20a6e5cb5 100644 --- a/test/functional/editor/tabpage_spec.lua +++ b/test/functional/editor/tabpage_spec.lua @@ -102,14 +102,9 @@ describe('tabpage', function() it('switching tabpage after setting laststatus=3 #19591', function() local screen = Screen.new(40, 8) - screen:set_default_attr_ids({ - [0] = { bold = true, foreground = Screen.colors.Blue }, - [1] = { bold = true, reverse = true }, -- StatusLine - [2] = { reverse = true }, -- TabLineFill - [3] = { bold = true }, -- TabLineSel - [4] = { background = Screen.colors.LightGrey, underline = true }, -- TabLine - [5] = { bold = true, foreground = Screen.colors.Magenta }, - }) + screen:add_extra_attr_ids { + [100] = { bold = true, foreground = Screen.colors.Fuchsia }, + } screen:attach() command('tabnew') @@ -118,18 +113,18 @@ describe('tabpage', function() command('tabnext') feed('<C-G>') screen:expect([[ - {4: [No Name] }{3: [No Name] }{2: }{4:X}| + {24: [No Name] }{5: [No Name] }{2: }{24:X}| ^ | - {0:~ }|*4 - {1:[No Name] }| + {1:~ }|*4 + {3:[No Name] }| "[No Name]" --No lines in buffer-- | ]]) command('vnew') screen:expect([[ - {4: [No Name] }{3: }{5:2}{3: [No Name] }{2: }{4:X}| + {24: [No Name] }{5: }{100:2}{5: [No Name] }{2: }{24:X}| ^ │ | - {0:~ }│{0:~ }|*4 - {1:[No Name] }| + {1:~ }│{1:~ }|*4 + {3:[No Name] }| "[No Name]" --No lines in buffer-- | ]]) end) diff --git a/test/functional/lua/diagnostic_spec.lua b/test/functional/lua/diagnostic_spec.lua index 05082bc132..76246fc2d1 100644 --- a/test/functional/lua/diagnostic_spec.lua +++ b/test/functional/lua/diagnostic_spec.lua @@ -843,17 +843,18 @@ describe('vim.diagnostic', function() end) end) - describe('get_next_pos()', function() + describe('get_next()', function() it('can find the next pos with only one namespace', function() eq( { 1, 1 }, exec_lua [[ - vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, { - make_error('Diagnostic #1', 1, 1, 1, 1), - }) - vim.api.nvim_win_set_buf(0, diagnostic_bufnr) - return vim.diagnostic.get_next_pos() - ]] + vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, { + make_error('Diagnostic #1', 1, 1, 1, 1), + }) + vim.api.nvim_win_set_buf(0, diagnostic_bufnr) + local next = vim.diagnostic.get_next() + return { next.lnum, next.col } + ]] ) end) @@ -861,14 +862,15 @@ describe('vim.diagnostic', function() eq( { 4, 4 }, exec_lua [[ - vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, { - make_error('Diagnostic #1', 1, 1, 1, 1), - make_error('Diagnostic #2', 4, 4, 4, 4), - }) - vim.api.nvim_win_set_buf(0, diagnostic_bufnr) - vim.api.nvim_win_set_cursor(0, {3, 1}) - return vim.diagnostic.get_next_pos { namespace = diagnostic_ns } - ]] + vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, { + make_error('Diagnostic #1', 1, 1, 1, 1), + make_error('Diagnostic #2', 4, 4, 4, 4), + }) + vim.api.nvim_win_set_buf(0, diagnostic_bufnr) + vim.api.nvim_win_set_cursor(0, {3, 1}) + local next = vim.diagnostic.get_next({ namespace = diagnostic_ns }) + return { next.lnum, next.col } + ]] ) end) @@ -876,27 +878,29 @@ describe('vim.diagnostic', function() eq( { 1, 1 }, exec_lua [[ - vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, { - make_error('Diagnostic #1', 1, 1, 1, 1), - }) - vim.api.nvim_win_set_buf(0, diagnostic_bufnr) - vim.api.nvim_win_set_cursor(0, {3, 1}) - return vim.diagnostic.get_next_pos { namespace = diagnostic_ns } - ]] + vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, { + make_error('Diagnostic #1', 1, 1, 1, 1), + }) + vim.api.nvim_win_set_buf(0, diagnostic_bufnr) + vim.api.nvim_win_set_cursor(0, {3, 1}) + local next = vim.diagnostic.get_next({ namespace = diagnostic_ns }) + return { next.lnum, next.col } + ]] ) end) it('will not cycle when wrap is off', function() eq( - false, + vim.NIL, exec_lua [[ - vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, { - make_error('Diagnostic #1', 1, 1, 1, 1), - }) - vim.api.nvim_win_set_buf(0, diagnostic_bufnr) - vim.api.nvim_win_set_cursor(0, {3, 1}) - return vim.diagnostic.get_next_pos { namespace = diagnostic_ns, wrap = false } - ]] + vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, { + make_error('Diagnostic #1', 1, 1, 1, 1), + }) + vim.api.nvim_win_set_buf(0, diagnostic_bufnr) + vim.api.nvim_win_set_cursor(0, {3, 1}) + local next = vim.diagnostic.get_next({ namespace = diagnostic_ns, wrap = false }) + return next + ]] ) end) @@ -904,13 +908,14 @@ describe('vim.diagnostic', function() eq( { 4, 4 }, exec_lua [[ - vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, { - make_error('Diagnostic #2', 4, 4, 4, 4), - }) - vim.api.nvim_win_set_buf(0, diagnostic_bufnr) - vim.api.nvim_win_set_cursor(0, {vim.api.nvim_buf_line_count(0), 1}) - return vim.diagnostic.get_prev_pos { namespace = diagnostic_ns } - ]] + vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, { + make_error('Diagnostic #2', 4, 4, 4, 4), + }) + vim.api.nvim_win_set_buf(0, diagnostic_bufnr) + vim.api.nvim_win_set_cursor(0, {vim.api.nvim_buf_line_count(0), 1}) + local prev = vim.diagnostic.get_prev({ namespace = diagnostic_ns }) + return { prev.lnum, prev.col } + ]] ) end) @@ -918,15 +923,16 @@ describe('vim.diagnostic', function() eq( { 4, 0 }, exec_lua [[ - vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, { - make_error('Diagnostic #1', 3, 9001, 3, 9001), - make_error('Diagnostic #2', 4, 0, 4, 0), - }) - vim.api.nvim_win_set_buf(0, diagnostic_bufnr) - vim.api.nvim_win_set_cursor(0, {1, 1}) - vim.diagnostic.goto_next { float = false } - return vim.diagnostic.get_next_pos { namespace = diagnostic_ns } - ]] + vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, { + make_error('Diagnostic #1', 3, 9001, 3, 9001), + make_error('Diagnostic #2', 4, 0, 4, 0), + }) + vim.api.nvim_win_set_buf(0, diagnostic_bufnr) + vim.api.nvim_win_set_cursor(0, {1, 1}) + vim.diagnostic.jump({ count = 1, float = false }) + local next = vim.diagnostic.get_next({ namespace = diagnostic_ns }) + return { next.lnum, next.col } + ]] ) end) @@ -935,13 +941,14 @@ describe('vim.diagnostic', function() { 4, 0 }, exec_lua [[ vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, { - make_error('Diagnostic #1', 3, 9001, 3, 9001), - make_error('Diagnostic #2', 4, -1, 4, -1), + make_error('Diagnostic #1', 3, 9001, 3, 9001), + make_error('Diagnostic #2', 4, -1, 4, -1), }) vim.api.nvim_win_set_buf(0, diagnostic_bufnr) vim.api.nvim_win_set_cursor(0, {1, 1}) - vim.diagnostic.goto_next { float = false } - return vim.diagnostic.get_next_pos { namespace = diagnostic_ns } + vim.diagnostic.jump({ count = 1, float = false }) + local next = vim.diagnostic.get_next({ namespace = diagnostic_ns }) + return { next.lnum, next.col } ]] ) end) @@ -1044,33 +1051,35 @@ describe('vim.diagnostic', function() end) end) - describe('get_prev_pos()', function() - it('can find the prev pos with only one namespace', function() + describe('get_prev()', function() + it('can find the previous diagnostic with only one namespace', function() eq( { 1, 1 }, exec_lua [[ - vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, { - make_error('Diagnostic #1', 1, 1, 1, 1), - }) - vim.api.nvim_win_set_buf(0, diagnostic_bufnr) - vim.api.nvim_win_set_cursor(0, {3, 1}) - return vim.diagnostic.get_prev_pos() - ]] + vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, { + make_error('Diagnostic #1', 1, 1, 1, 1), + }) + vim.api.nvim_win_set_buf(0, diagnostic_bufnr) + vim.api.nvim_win_set_cursor(0, {3, 1}) + local prev = vim.diagnostic.get_prev() + return { prev.lnum, prev.col } + ]] ) end) - it('can find prev pos with two errors', function() + it('can find the previous diagnostic with two errors', function() eq( { 1, 1 }, exec_lua [[ - vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, { - make_error('Diagnostic #1', 1, 1, 1, 1), - make_error('Diagnostic #2', 4, 4, 4, 4), - }) - vim.api.nvim_win_set_buf(0, diagnostic_bufnr) - vim.api.nvim_win_set_cursor(0, {3, 1}) - return vim.diagnostic.get_prev_pos { namespace = diagnostic_ns } - ]] + vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, { + make_error('Diagnostic #1', 1, 1, 1, 1), + make_error('Diagnostic #2', 4, 4, 4, 4), + }) + vim.api.nvim_win_set_buf(0, diagnostic_bufnr) + vim.api.nvim_win_set_cursor(0, {3, 1}) + local prev = vim.diagnostic.get_prev({ namespace = diagnostic_ns }) + return { prev.lnum, prev.col } + ]] ) end) @@ -1078,27 +1087,29 @@ describe('vim.diagnostic', function() eq( { 4, 4 }, exec_lua [[ - vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, { - make_error('Diagnostic #2', 4, 4, 4, 4), - }) - vim.api.nvim_win_set_buf(0, diagnostic_bufnr) - vim.api.nvim_win_set_cursor(0, {3, 1}) - return vim.diagnostic.get_prev_pos { namespace = diagnostic_ns } - ]] + vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, { + make_error('Diagnostic #2', 4, 4, 4, 4), + }) + vim.api.nvim_win_set_buf(0, diagnostic_bufnr) + vim.api.nvim_win_set_cursor(0, {3, 1}) + local prev = vim.diagnostic.get_prev({ namespace = diagnostic_ns }) + return { prev.lnum, prev.col } + ]] ) end) it('respects wrap parameter', function() eq( - false, + vim.NIL, exec_lua [[ - vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, { - make_error('Diagnostic #2', 4, 4, 4, 4), - }) - vim.api.nvim_win_set_buf(0, diagnostic_bufnr) - vim.api.nvim_win_set_cursor(0, {3, 1}) - return vim.diagnostic.get_prev_pos { namespace = diagnostic_ns, wrap = false} - ]] + vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, { + make_error('Diagnostic #2', 4, 4, 4, 4), + }) + vim.api.nvim_win_set_buf(0, diagnostic_bufnr) + vim.api.nvim_win_set_cursor(0, {3, 1}) + local prev = vim.diagnostic.get_prev({ namespace = diagnostic_ns, wrap = false}) + return prev + ]] ) end) @@ -1126,6 +1137,118 @@ describe('vim.diagnostic', function() end) end) + describe('jump()', function() + before_each(function() + exec_lua([[ + vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, { + make_error('Diagnostic #1', 0, 0, 0, 2), + make_error('Diagnostic #2', 1, 1, 1, 4), + make_warning('Diagnostic #3', 2, -1, 2, -1), + make_info('Diagnostic #4', 3, 0, 3, 3), + }) + vim.api.nvim_win_set_buf(0, diagnostic_bufnr) + ]]) + end) + + it('can move forward', function() + eq( + { 2, 1 }, + exec_lua([[ + vim.api.nvim_win_set_cursor(0, { 1, 0 }) + vim.diagnostic.jump({ count = 1 }) + return vim.api.nvim_win_get_cursor(0) + ]]) + ) + + eq( + { 4, 0 }, + exec_lua([[ + vim.api.nvim_win_set_cursor(0, { 1, 0 }) + vim.diagnostic.jump({ count = 3 }) + return vim.api.nvim_win_get_cursor(0) + ]]) + ) + + eq( + { 4, 0 }, + exec_lua([[ + vim.api.nvim_win_set_cursor(0, { 1, 0 }) + vim.diagnostic.jump({ count = math.huge, wrap = false }) + return vim.api.nvim_win_get_cursor(0) + ]]) + ) + end) + + it('can move backward', function() + eq( + { 3, 0 }, + exec_lua([[ + vim.api.nvim_win_set_cursor(0, { 4, 0 }) + vim.diagnostic.jump({ count = -1 }) + return vim.api.nvim_win_get_cursor(0) + ]]) + ) + + eq( + { 1, 0 }, + exec_lua([[ + vim.api.nvim_win_set_cursor(0, { 4, 0 }) + vim.diagnostic.jump({ count = -3 }) + return vim.api.nvim_win_get_cursor(0) + ]]) + ) + + eq( + { 1, 0 }, + exec_lua([[ + vim.api.nvim_win_set_cursor(0, { 4, 0 }) + vim.diagnostic.jump({ count = -math.huge, wrap = false }) + return vim.api.nvim_win_get_cursor(0) + ]]) + ) + end) + + it('can filter by severity', function() + eq( + { 3, 0 }, + exec_lua([[ + vim.api.nvim_win_set_cursor(0, { 1, 0 }) + vim.diagnostic.jump({ count = 1, severity = vim.diagnostic.severity.WARN }) + return vim.api.nvim_win_get_cursor(0) + ]]) + ) + + eq( + { 3, 0 }, + exec_lua([[ + vim.api.nvim_win_set_cursor(0, { 1, 0 }) + vim.diagnostic.jump({ count = 9999, severity = vim.diagnostic.severity.WARN }) + return vim.api.nvim_win_get_cursor(0) + ]]) + ) + end) + + it('can wrap', function() + eq( + { 1, 0 }, + exec_lua([[ + vim.api.nvim_win_set_cursor(0, { 4, 0 }) + vim.diagnostic.jump({ count = 1, wrap = true }) + return vim.api.nvim_win_get_cursor(0) + ]]) + ) + + eq( + { 4, 0 }, + exec_lua([[ + vim.api.nvim_win_set_cursor(0, { 1, 0 }) + vim.diagnostic.jump({ count = -1, wrap = true }) + return vim.api.nvim_win_get_cursor(0) + ]]) + ) + end) + end) + describe('get()', function() it('returns an empty table when no diagnostics are present', function() eq({}, exec_lua [[return vim.diagnostic.get(diagnostic_bufnr, {namespace=diagnostic_ns})]]) diff --git a/test/functional/lua/highlight_spec.lua b/test/functional/lua/highlight_spec.lua index c9f2d0a47f..8f099ac233 100644 --- a/test/functional/lua/highlight_spec.lua +++ b/test/functional/lua/highlight_spec.lua @@ -1,5 +1,6 @@ local t = require('test.testutil') local n = require('test.functional.testnvim')() +local Screen = require('test.functional.ui.screen') local exec_lua = n.exec_lua local eq = t.eq @@ -9,6 +10,88 @@ local command = n.command local clear = n.clear local api = n.api +describe('vim.highlight.range', function() + local screen + + before_each(function() + clear() + screen = Screen.new(60, 6) + screen:add_extra_attr_ids({ + [100] = { foreground = Screen.colors.Blue, background = Screen.colors.Yellow, bold = true }, + }) + screen:attach() + api.nvim_set_option_value('list', true, {}) + api.nvim_set_option_value('listchars', 'eol:$', {}) + api.nvim_buf_set_lines(0, 0, -1, true, { + 'asdfghjkl', + '«口=口»', + 'qwertyuiop', + '口口=口口', + 'zxcvbnm', + }) + end) + + it('works with charwise selection', function() + exec_lua([[ + local ns = vim.api.nvim_create_namespace('') + vim.highlight.range(0, ns, 'Search', { 1, 5 }, { 3, 10 }) + ]]) + screen:expect([[ + ^asdfghjkl{1:$} | + «口{10:=口»}{100:$} | + {10:qwertyuiop}{100:$} | + {10:口口=口}口{1:$} | + zxcvbnm{1:$} | + | + ]]) + end) + + it('works with linewise selection', function() + exec_lua([[ + local ns = vim.api.nvim_create_namespace('') + vim.highlight.range(0, ns, 'Search', { 0, 0 }, { 4, 0 }, { regtype = 'V' }) + ]]) + screen:expect([[ + {10:^asdfghjkl}{100:$} | + {10:«口=口»}{100:$} | + {10:qwertyuiop}{100:$} | + {10:口口=口口}{100:$} | + {10:zxcvbnm}{100:$} | + | + ]]) + end) + + it('works with blockwise selection', function() + exec_lua([[ + local ns = vim.api.nvim_create_namespace('') + vim.highlight.range(0, ns, 'Search', { 0, 0 }, { 4, 4 }, { regtype = '\022' }) + ]]) + screen:expect([[ + {10:^asdf}ghjkl{1:$} | + {10:«口=}口»{1:$} | + {10:qwer}tyuiop{1:$} | + {10:口口}=口口{1:$} | + {10:zxcv}bnm{1:$} | + | + ]]) + end) + + it('works with blockwise selection with width', function() + exec_lua([[ + local ns = vim.api.nvim_create_namespace('') + vim.highlight.range(0, ns, 'Search', { 0, 4 }, { 4, 7 }, { regtype = '\0226' }) + ]]) + screen:expect([[ + ^asdf{10:ghjkl}{1:$} | + «口={10:口»}{1:$} | + qwer{10:tyuiop}{1:$} | + 口口{10:=口口}{1:$} | + zxcv{10:bnm}{1:$} | + | + ]]) + end) +end) + describe('vim.highlight.on_yank', function() before_each(function() clear() diff --git a/test/functional/lua/runtime_spec.lua b/test/functional/lua/runtime_spec.lua index 4adce42c3e..c6b0577ebe 100644 --- a/test/functional/lua/runtime_spec.lua +++ b/test/functional/lua/runtime_spec.lua @@ -401,4 +401,12 @@ describe('runtime:', function() eq('ABab', eval('g:seq')) end) end) + + it('cpp ftplugin loads c ftplugin #29053', function() + eq('', eval('&commentstring')) + eq('', eval('&omnifunc')) + exec('edit file.cpp') + eq('/*%s*/', eval('&commentstring')) + eq('ccomplete#Complete', eval('&omnifunc')) + end) end) diff --git a/test/functional/lua/ui_event_spec.lua b/test/functional/lua/ui_event_spec.lua index 1e80c88403..0a6deaa41c 100644 --- a/test/functional/lua/ui_event_spec.lua +++ b/test/functional/lua/ui_event_spec.lua @@ -37,6 +37,9 @@ describe('vim.ui_attach', function() [2] = { bold = true }, [3] = { background = Screen.colors.Grey }, [4] = { background = Screen.colors.LightMagenta }, + [5] = { reverse = true }, + [6] = { reverse = true, bold = true }, + [7] = { background = Screen.colors.Yellow1 }, }) screen:attach() end) @@ -188,6 +191,56 @@ describe('vim.ui_attach', function() feed('version<CR><CR>v<Esc>') n.assert_alive() end) + + it("preserved 'incsearch/command' screen state after :redraw from ext_cmdline", function() + exec_lua([[ + vim.cmd.norm('ifoobar') + vim.cmd('1split cmdline') + local buf = vim.api.nvim_get_current_buf() + vim.cmd.wincmd('p') + vim.ui_attach(ns, { ext_cmdline = true }, function(event, ...) + if event == 'cmdline_show' then + local content = select(1, ...) + vim.api.nvim_buf_set_lines(buf, -2, -1, false, {content[1][2]}) + vim.cmd('redraw') + end + return true + end) + ]]) + -- Updates a cmdline window + feed(':cmdline') + screen:expect({ + grid = [[ + cmdline | + {5:cmdline [+] }| + fooba^r | + {6:[No Name] [+] }| + | + ]], + }) + -- Does not clear 'incsearch' highlighting + feed('<Esc>/foo') + screen:expect({ + grid = [[ + foo | + {5:cmdline [+] }| + {5:foo}ba^r | + {6:[No Name] [+] }| + | + ]], + }) + -- Shows new cmdline state during 'inccommand' + feed('<Esc>:%s/bar/baz') + screen:expect({ + grid = [[ + %s/bar/baz | + {5:cmdline [+] }| + foo{7:ba^z} | + {6:[No Name] [+] }| + | + ]], + }) + end) end) describe('vim.ui_attach', function() diff --git a/test/functional/lua/vim_spec.lua b/test/functional/lua/vim_spec.lua index c8f94c6ffa..d50b646085 100644 --- a/test/functional/lua/vim_spec.lua +++ b/test/functional/lua/vim_spec.lua @@ -1408,7 +1408,25 @@ describe('lua stdlib', function() exec_lua("vim.validate{arg1={{}, 't' }, arg2={ 'foo', 's' }}") exec_lua("vim.validate{arg1={2, function(a) return (a % 2) == 0 end, 'even number' }}") exec_lua("vim.validate{arg1={5, {'n', 's'} }, arg2={ 'foo', {'n', 's'} }}") - + vim.validate('arg1', 5, 'number') + vim.validate('arg1', '5', 'string') + vim.validate('arg1', { 5 }, 'table') + vim.validate('arg1', function() + return 5 + end, 'function') + vim.validate('arg1', nil, 'number', true) + vim.validate('arg1', nil, 'string', true) + vim.validate('arg1', nil, 'table', true) + vim.validate('arg1', nil, 'function', true) + + matches('arg1: expected number, got nil', pcall_err(vim.validate, 'arg1', nil, 'number')) + matches('arg1: expected string, got nil', pcall_err(vim.validate, 'arg1', nil, 'string')) + matches('arg1: expected table, got nil', pcall_err(vim.validate, 'arg1', nil, 'table')) + matches('arg1: expected function, got nil', pcall_err(vim.validate, 'arg1', nil, 'function')) + matches('arg1: expected string, got number', pcall_err(vim.validate, 'arg1', 5, 'string')) + matches('arg1: expected table, got number', pcall_err(vim.validate, 'arg1', 5, 'table')) + matches('arg1: expected function, got number', pcall_err(vim.validate, 'arg1', 5, 'function')) + matches('arg1: expected number, got string', pcall_err(vim.validate, 'arg1', '5', 'number')) matches('expected table, got number', pcall_err(exec_lua, "vim.validate{ 1, 'x' }")) matches('invalid type name: x', pcall_err(exec_lua, "vim.validate{ arg1={ 1, 'x' }}")) matches('invalid type name: 1', pcall_err(exec_lua, 'vim.validate{ arg1={ 1, 1 }}')) diff --git a/test/functional/plugin/lsp_spec.lua b/test/functional/plugin/lsp_spec.lua index c95a96baca..0cf84b50c2 100644 --- a/test/functional/plugin/lsp_spec.lua +++ b/test/functional/plugin/lsp_spec.lua @@ -530,6 +530,34 @@ describe('LSP', function() ]]) end) + it('should allow on_lines + nvim_buf_delete during LSP initialization #28575', function() + clear() + exec_lua(create_server_definition) + exec_lua([[ + local initialized = false + local server = _create_server({ + handlers = { + initialize = function(method, params, callback) + vim.schedule(function() + callback(nil, { capabilities = {} }) + initialized = true + end) + end + } + }) + local bufnr = vim.api.nvim_create_buf(false, true) + vim.api.nvim_set_current_buf(bufnr) + local client_id = vim.lsp.start({ + name = 'detach-dummy', + cmd = server.cmd, + }) + vim.api.nvim_buf_set_lines(bufnr, 0, -1, false, {"hello"}) + vim.api.nvim_buf_delete(bufnr, {}) + local ok = vim.wait(1000, function() return initialized end) + assert(ok, "lsp did not initialize") + ]]) + end) + it('client should return settings via workspace/configuration handler', function() local expected_handlers = { { NIL, {}, { method = 'shutdown', client_id = 1 } }, diff --git a/test/functional/plugin/tohtml_spec.lua b/test/functional/plugin/tohtml_spec.lua index 200a5f34b2..be5bada901 100644 --- a/test/functional/plugin/tohtml_spec.lua +++ b/test/functional/plugin/tohtml_spec.lua @@ -287,7 +287,13 @@ describe(':TOhtml', function() 0, { virt_text = { { 'foo' } }, virt_text_pos = 'overlay' } ) - api.nvim_buf_set_extmark(0, ns, 2, 0, { virt_text = { { 'foo' } }, virt_text_pos = 'inline' }) + api.nvim_buf_set_extmark( + 0, + ns, + 2, + 0, + { virt_text = { { 'fo┊o', { 'Conceal', 'Comment' } } }, virt_text_pos = 'inline' } + ) --api.nvim_buf_set_extmark(0,ns,3,0,{virt_text={{'foo'}},virt_text_pos='right_align'}) run_tohtml_and_assert(screen) end) diff --git a/test/functional/terminal/tui_spec.lua b/test/functional/terminal/tui_spec.lua index d4628ea626..efa65b7441 100644 --- a/test/functional/terminal/tui_spec.lua +++ b/test/functional/terminal/tui_spec.lua @@ -2003,38 +2003,39 @@ describe('TUI', function() ]]) end) - it('invalidated regions are cleared with terminal background attr', function() - local screen = Screen.new(50, 10) - screen:set_default_attr_ids({ [1] = { foreground = Screen.colors.Black } }) - screen:attach() - fn.termopen({ - nvim_prog, - '--clean', - '--cmd', - 'set termguicolors', - '--cmd', - 'sleep 10', - }, { - env = { - VIMRUNTIME = os.getenv('VIMRUNTIME'), - }, - }) - screen:expect({ - grid = [[ - {1:^ }| - {1: }|*8 - | - ]], - }) - screen:try_resize(51, 11) - screen:expect({ - grid = [[ - {1:^ }| - {1: }|*9 - | - ]], - }) - end) + -- #28667, #28668 + for _, guicolors in ipairs({ 'notermguicolors', 'termguicolors' }) do + it('has no black flicker when clearing regions during startup with ' .. guicolors, function() + local screen = Screen.new(50, 10) + screen:attach() + fn.termopen({ + nvim_prog, + '--clean', + '--cmd', + 'set ' .. guicolors, + '--cmd', + 'sleep 10', + }, { + env = { + VIMRUNTIME = os.getenv('VIMRUNTIME'), + }, + }) + screen:expect({ + grid = [[ + ^ | + |*9 + ]], + intermediate = true, + }) + screen:try_resize(51, 11) + screen:expect({ + grid = [[ + ^ | + |*10 + ]], + }) + end) + end it('argv[0] can be overridden #23953', function() if not exec_lua('return pcall(require, "ffi")') then diff --git a/test/functional/treesitter/inspect_tree_spec.lua b/test/functional/treesitter/inspect_tree_spec.lua index f5acfe7c4a..b403cca735 100644 --- a/test/functional/treesitter/inspect_tree_spec.lua +++ b/test/functional/treesitter/inspect_tree_spec.lua @@ -114,4 +114,57 @@ describe('vim.treesitter.inspect_tree', function() (fenced_code_block_delimiter)))) ; [2, 0] - [2, 3] markdown ]] end) + + it('updates source and tree buffer windows and closes them correctly', function() + insert([[ + print() + ]]) + + -- setup two windows for the source buffer + exec_lua([[ + source_win = vim.api.nvim_get_current_win() + vim.api.nvim_open_win(0, false, { + win = 0, + split = 'left' + }) + ]]) + + -- setup three windows for the tree buffer + exec_lua([[ + vim.treesitter.start(0, 'lua') + vim.treesitter.inspect_tree() + tree_win = vim.api.nvim_get_current_win() + tree_win_copy_1 = vim.api.nvim_open_win(0, false, { + win = 0, + split = 'left' + }) + tree_win_copy_2 = vim.api.nvim_open_win(0, false, { + win = 0, + split = 'left' + }) + ]]) + + -- close original source window + exec_lua('vim.api.nvim_win_close(source_win, false)') + + -- navigates correctly to the remaining source buffer window + feed('<CR>') + eq('', n.api.nvim_get_vvar('errmsg')) + + -- close original tree window + exec_lua([[ + vim.api.nvim_set_current_win(tree_win_copy_1) + vim.api.nvim_win_close(tree_win, false) + ]]) + + -- navigates correctly to the remaining source buffer window + feed('<CR>') + eq('', n.api.nvim_get_vvar('errmsg')) + + -- close source buffer window and all remaining tree windows + t.pcall_err(exec_lua, 'vim.api.nvim_win_close(0, false)') + + eq(false, exec_lua('return vim.api.nvim_win_is_valid(tree_win_copy_1)')) + eq(false, exec_lua('return vim.api.nvim_win_is_valid(tree_win_copy_2)')) + end) end) diff --git a/test/functional/ui/float_spec.lua b/test/functional/ui/float_spec.lua index 248220e28b..cdaae6cfee 100644 --- a/test/functional/ui/float_spec.lua +++ b/test/functional/ui/float_spec.lua @@ -2127,7 +2127,7 @@ describe('float window', function() ## grid 3 | ## grid 4 - {5:╔═════}🦄BB{5:╗}| + {5:╔═════}{11:🦄BB}{5:╗}| {5:║}{1: halloj! }{5:║}| {5:║}{1: BORDAA }{5:║}| {5:╚═════════╝}| @@ -2141,7 +2141,7 @@ describe('float window', function() screen:expect{grid=[[ ^ | {0:~ }| - {0:~ }{5:╔═════}🦄BB{5:╗}{0: }| + {0:~ }{5:╔═════}{11:🦄BB}{5:╗}{0: }| {0:~ }{5:║}{1: halloj! }{5:║}{0: }| {0:~ }{5:║}{1: BORDAA }{5:║}{0: }| {0:~ }{5:╚═════════╝}{0: }| @@ -2275,7 +2275,7 @@ describe('float window', function() {5:╔═════════╗}| {5:║}{1: halloj! }{5:║}| {5:║}{1: BORDAA }{5:║}| - {5:╚═════}🦄BB{5:╝}| + {5:╚═════}{11:🦄BB}{5:╝}| ]], float_pos={ [4] = { 1001, "NW", 1, 2, 5, true } }, win_viewport={ @@ -2289,7 +2289,7 @@ describe('float window', function() {0:~ }{5:╔═════════╗}{0: }| {0:~ }{5:║}{1: halloj! }{5:║}{0: }| {0:~ }{5:║}{1: BORDAA }{5:║}{0: }| - {0:~ }{5:╚═════}🦄BB{5:╝}{0: }| + {0:~ }{5:╚═════}{11:🦄BB}{5:╝}{0: }| | ]]} end @@ -2423,10 +2423,10 @@ describe('float window', function() ## grid 3 | ## grid 4 - {5:╔═════}🦄{7:BB}{5:╗}| + {5:╔═════}{11:🦄}{7:BB}{5:╗}| {5:║}{1: halloj! }{5:║}| {5:║}{1: BORDAA }{5:║}| - {5:╚═════}🦄{7:BB}{5:╝}| + {5:╚═════}{11:🦄}{7:BB}{5:╝}| ]], float_pos={ [4] = { 1001, "NW", 1, 2, 5, true } }, win_viewport={ @@ -2437,10 +2437,10 @@ describe('float window', function() screen:expect{grid=[[ ^ | {0:~ }| - {0:~ }{5:╔═════}🦄{7:BB}{5:╗}{0: }| + {0:~ }{5:╔═════}{11:🦄}{7:BB}{5:╗}{0: }| {0:~ }{5:║}{1: halloj! }{5:║}{0: }| {0:~ }{5:║}{1: BORDAA }{5:║}{0: }| - {0:~ }{5:╚═════}🦄{7:BB}{5:╝}{0: }| + {0:~ }{5:╚═════}{11:🦄}{7:BB}{5:╝}{0: }| | ]]} end diff --git a/test/functional/ui/screen.lua b/test/functional/ui/screen.lua index 4625ce8553..f8e95f7d88 100644 --- a/test/functional/ui/screen.lua +++ b/test/functional/ui/screen.lua @@ -255,6 +255,7 @@ end function Screen:set_default_attr_ids(attr_ids) self._default_attr_ids = attr_ids + self._attrs_overridden = true end function Screen:add_extra_attr_ids(extra_attr_ids) @@ -699,9 +700,9 @@ screen:redraw_debug() to show all intermediate screen states.]] end, expected) end -function Screen:expect_unchanged(intermediate, waittime_ms, ignore_attrs) +function Screen:expect_unchanged(intermediate, waittime_ms) -- Collect the current screen state. - local kwargs = self:get_snapshot(nil, ignore_attrs) + local kwargs = self:get_snapshot() if intermediate then kwargs.intermediate = true @@ -1536,13 +1537,14 @@ end -- Use snapshot_util({}) to generate a text-only (no attributes) test. -- -- @see Screen:redraw_debug() -function Screen:snapshot_util(attrs, ignore, request_cb) +function Screen:snapshot_util(request_cb) + -- TODO: simplify this later when existing tests have been updated self:sleep(250, request_cb) - self:print_snapshot(attrs, ignore) + self:print_snapshot() end -function Screen:redraw_debug(attrs, ignore, timeout) - self:print_snapshot(attrs, ignore) +function Screen:redraw_debug(timeout) + self:print_snapshot() local function notification_cb(method, args) assert(method == 'redraw') for _, update in ipairs(args) do @@ -1552,7 +1554,7 @@ function Screen:redraw_debug(attrs, ignore, timeout) end end self:_redraw(args) - self:print_snapshot(attrs, ignore) + self:print_snapshot() return true end if timeout == nil then @@ -1596,23 +1598,12 @@ end -- Returns the current screen state in the form of a screen:expect() -- keyword-args map. -function Screen:get_snapshot(attrs, ignore) - if ignore == nil then - ignore = self._default_attr_ignore - end +function Screen:get_snapshot() local attr_state = { ids = {}, - ignore = ignore, mutable = true, -- allow _row_repr to add missing highlights } - if attrs == nil then - attrs = self._default_attr_ids - elseif isempty(attrs) then - attrs = nil - attr_state.ids = nil - else - attr_state.modified = true - end + local attrs = self._default_attr_ids if attrs ~= nil then for i, a in pairs(attrs) do @@ -1708,9 +1699,10 @@ local function fmt_ext_state(name, state) end end -function Screen:_print_snapshot(attrs, ignore) - local kwargs, ext_state, attr_state = self:get_snapshot(attrs, ignore) +function Screen:_print_snapshot() + local kwargs, ext_state, attr_state = self:get_snapshot() local attrstr = '' + local modify_attrs = not self._attrs_overridden if attr_state.modified then local attrstrs = {} for i, a in pairs(attr_state.ids) do @@ -1721,16 +1713,20 @@ function Screen:_print_snapshot(attrs, ignore) dict = '{ ' .. self:_pprint_attrs(a) .. ' }' end local keyval = (type(i) == 'number') and '[' .. tostring(i) .. ']' or i - table.insert(attrstrs, ' ' .. keyval .. ' = ' .. dict .. ',') + if not (type(i) == 'number' and modify_attrs and i <= 30) then + table.insert(attrstrs, ' ' .. keyval .. ' = ' .. dict .. ',') + end + if modify_attrs then + self._default_attr_ids = attr_state.ids + end end - attrstr = (',\n attr_ids = {\n ' .. table.concat(attrstrs, '\n ') .. '\n },') - elseif isempty(attrs) then - attrstr = ',\n attr_ids = {},' + local fn_name = modify_attrs and 'add_extra_attr_ids' or 'set_default_attr_ids' + attrstr = ('screen:' .. fn_name .. ' {\n' .. table.concat(attrstrs, '\n') .. '\n}\n\n') end - local result = ('screen:expect({\n grid = [[\n %s\n ]]%s'):format( - kwargs.grid:gsub('\n', '\n '), - attrstr + local result = ('%sscreen:expect({\n grid = [[\n %s\n ]]'):format( + attrstr, + kwargs.grid:gsub('\n', '\n ') ) for _, k in ipairs(ext_keys) do if ext_state[k] ~= nil and not (k == 'win_viewport' and not self.options.ext_multigrid) then @@ -1742,8 +1738,8 @@ function Screen:_print_snapshot(attrs, ignore) return result end -function Screen:print_snapshot(attrs, ignore) - print('\n' .. self:_print_snapshot(attrs, ignore) .. '\n') +function Screen:print_snapshot() + print('\n' .. self:_print_snapshot() .. '\n') io.stdout:flush() end diff --git a/test/functional/ui/screen_basic_spec.lua b/test/functional/ui/screen_basic_spec.lua index 54580bf47c..85a653df36 100644 --- a/test/functional/ui/screen_basic_spec.lua +++ b/test/functional/ui/screen_basic_spec.lua @@ -4,6 +4,7 @@ local Screen = require('test.functional.ui.screen') local spawn, set_session, clear = n.spawn, n.set_session, n.clear local feed, command = n.feed, n.command +local exec = n.exec local insert = n.insert local eq = t.eq local fn, api = n.fn, n.api @@ -819,3 +820,39 @@ it("showcmd doesn't cause empty grid_line with redrawdebug=compositor #22593", f ]], } end) + +it("scrolling in narrow window doesn't draw over separator #29033", function() + clear() + local screen = Screen.new(60, 8) + screen:attach() + feed('100Oa<Esc>gg') + exec([[ + set number nowrap + vsplit + set scrollbind + wincmd l + set scrollbind + wincmd | + ]]) + screen:expect([[ + {8: }│{8: 1 }^a | + {8: }│{8: 2 }a | + {8: }│{8: 3 }a | + {8: }│{8: 4 }a | + {8: }│{8: 5 }a | + {8: }│{8: 6 }a | + {2:< }{3:[No Name] [+] }| + | + ]]) + feed('<C-F>') + screen:expect([[ + {8: }│{8: 5 }^a | + {8: }│{8: 6 }a | + {8: }│{8: 7 }a | + {8: }│{8: 8 }a | + {8: }│{8: 9 }a | + {8: }│{8: 10 }a | + {2:< }{3:[No Name] [+] }| + | + ]]) +end) diff --git a/test/old/testdir/test_filetype.vim b/test/old/testdir/test_filetype.vim index 34fe93fd55..16125559cf 100644 --- a/test/old/testdir/test_filetype.vim +++ b/test/old/testdir/test_filetype.vim @@ -1511,6 +1511,41 @@ func Test_git_file() filetype off endfunc +func Test_haredoc_file() + filetype on + call assert_true(mkdir('foo/bar', 'pR')) + + call writefile([], 'README', 'D') + split README + call assert_notequal('haredoc', &filetype) + bwipe! + + let g:filetype_haredoc = 1 + split README + call assert_notequal('haredoc', &filetype) + bwipe! + + call writefile([], 'foo/quux.ha') + split README + call assert_equal('haredoc', &filetype) + bwipe! + call delete('foo/quux.ha') + + call writefile([], 'foo/bar/baz.ha', 'D') + split README + call assert_notequal('haredoc', &filetype) + bwipe! + + let g:haredoc_search_depth = 2 + split README + call assert_equal('haredoc', &filetype) + bwipe! + unlet g:filetype_haredoc + unlet g:haredoc_search_depth + + filetype off +endfunc + func Test_hook_file() filetype on diff --git a/test/old/testdir/test_ins_complete.vim b/test/old/testdir/test_ins_complete.vim index 3f67a06999..45db2a7364 100644 --- a/test/old/testdir/test_ins_complete.vim +++ b/test/old/testdir/test_ins_complete.vim @@ -700,14 +700,14 @@ func Test_pum_with_preview_win() CheckScreendump let lines =<< trim END - funct Omni_test(findstart, base) - if a:findstart - return col(".") - 1 - endif - return [#{word: "one", info: "1info"}, #{word: "two", info: "2info"}, #{word: "three", info: "3info"}] - endfunc - set omnifunc=Omni_test - set completeopt+=longest + funct Omni_test(findstart, base) + if a:findstart + return col(".") - 1 + endif + return [#{word: "one", info: "1info"}, #{word: "two", info: "2info"}, #{word: "three", info: "3info"}] + endfunc + set omnifunc=Omni_test + set completeopt+=longest END call writefile(lines, 'Xpreviewscript') diff --git a/test/old/testdir/test_popup.vim b/test/old/testdir/test_popup.vim index 56c881b958..5ae2ed5ed5 100644 --- a/test/old/testdir/test_popup.vim +++ b/test/old/testdir/test_popup.vim @@ -1178,6 +1178,8 @@ func Test_CompleteChanged() set completeopt=menu,menuone call feedkeys("i\<C-X>\<C-O>\<BS>\<BS>\<BS>f", 'tx') call assert_equal('five', g:word) + call feedkeys("i\<C-X>\<C-O>\<BS>\<BS>\<BS>f\<BS>", 'tx') + call assert_equal('one', g:word) autocmd! AAAAA_Group set complete& completeopt& diff --git a/test/old/testdir/test_visual.vim b/test/old/testdir/test_visual.vim index b7b5f611c4..0b840944bf 100644 --- a/test/old/testdir/test_visual.vim +++ b/test/old/testdir/test_visual.vim @@ -1968,6 +1968,14 @@ func Test_visual_getregion() #" using invalid value for "type" call assert_fails("call getregion(getpos('.'), getpos('.'), {'type': '' })", 'E475:') call assert_fails("call getregionpos(getpos('.'), getpos('.'), {'type': '' })", 'E475:') + call assert_fails("call getregion(getpos('.'), getpos('.'), {'type': 'v0' })", 'E475:') + call assert_fails("call getregionpos(getpos('.'), getpos('.'), {'type': 'v0' })", 'E475:') + call assert_fails("call getregion(getpos('.'), getpos('.'), {'type': 'V0' })", 'E475:') + call assert_fails("call getregionpos(getpos('.'), getpos('.'), {'type': 'V0' })", 'E475:') + call assert_fails("call getregion(getpos('.'), getpos('.'), {'type': '\<C-v>0' })", 'E475:') + call assert_fails("call getregionpos(getpos('.'), getpos('.'), {'type': '\<C-v>0' })", 'E475:') + call assert_fails("call getregion(getpos('.'), getpos('.'), {'type': '\<C-v>1:' })", 'E475:') + call assert_fails("call getregionpos(getpos('.'), getpos('.'), {'type': '\<C-v>1:' })", 'E475:') #" using a mark from another buffer to current buffer new @@ -2069,10 +2077,12 @@ func Test_visual_getregion() \ getregion(getpos('v'), getpos('.'), {'type': "\<C-v>" })) call assert_equal([ \ [[bufnr('%'), 1, 5, 0], [bufnr('%'), 1, 5, 0]], - \ [[bufnr('%'), 2, 10, 1], [bufnr('%'), 2, 10, 2]], + \ [[bufnr('%'), 2, 7, 1], [bufnr('%'), 2, 7, 2]], \ [[bufnr('%'), 3, 5, 0], [bufnr('%'), 3, 5, 0]], \ ], \ getregionpos(getpos('v'), getpos('.'), {'type': "\<C-v>" })) + call assert_equal(['efghijk«', '🇦«🇧«🇨«🇩', '12345'], + \ getregion(getpos('v'), getpos('.'), {'type': 'v' })) call assert_equal([ \ [[bufnr('%'), 1, 5, 0], [bufnr('%'), 1, 13, 0]], \ [[bufnr('%'), 2, 1, 0], [bufnr('%'), 2, 22, 0]], @@ -2080,6 +2090,28 @@ func Test_visual_getregion() \ ], \ getregionpos(getpos('v'), getpos('.'), {'type': 'v' })) + call cursor(1, 5) + call feedkeys("\<Esc>\<C-v>5l2j", 'xt') + call assert_equal(['efghij', ' «🇨« ', '567890'], + \ getregion(getpos('v'), getpos('.'), {'type': "\<C-v>" })) + call assert_equal([ + \ [[bufnr('%'), 1, 5, 0], [bufnr('%'), 1, 10, 0]], + \ [[bufnr('%'), 2, 7, 1], [bufnr('%'), 2, 19, 1]], + \ [[bufnr('%'), 3, 5, 0], [bufnr('%'), 3, 10, 0]], + \ ], + \ getregionpos(getpos('v'), getpos('.'), {'type': "\<C-v>" })) + + call cursor(1, 4) + call feedkeys("\<Esc>\<C-v>02j", 'xt') + call assert_equal(['abcd', '🇦« ', '1234'], + \ getregion(getpos('v'), getpos('.'), {'type': "\<C-v>" })) + call assert_equal([ + \ [[bufnr('%'), 1, 1, 0], [bufnr('%'), 1, 4, 0]], + \ [[bufnr('%'), 2, 1, 0], [bufnr('%'), 2, 7, 1]], + \ [[bufnr('%'), 3, 1, 0], [bufnr('%'), 3, 4, 0]], + \ ], + \ getregionpos(getpos('v'), getpos('.'), {'type': "\<C-v>" })) + #" characterwise selection with multibyte chars call cursor(1, 1) call feedkeys("\<Esc>vj", 'xt') @@ -2546,30 +2578,127 @@ func Test_getregion_invalid_buf() bwipe! endfunc -func Test_getregion_maxcol() - new +func Test_getregion_after_yank() + func! Check_Results(type) + call assert_equal(g:expected_region, + \ getregion(getpos("'["), getpos("']"), #{ type: a:type })) + call assert_equal(g:expected_regionpos, + \ getregionpos(getpos("'["), getpos("']"), #{ type: a:type })) + call assert_equal(g:expected_region, + \ getregion(getpos("']"), getpos("'["), #{ type: a:type })) + call assert_equal(g:expected_regionpos, + \ getregionpos(getpos("']"), getpos("'["), #{ type: a:type })) + let g:checked = 1 + endfunc + autocmd TextYankPost * \ : if v:event.operator ==? 'y' - \ | call assert_equal([ - \ [[bufnr('%'), 1, 1, 0], [bufnr('%'), 1, 4, 0]], - \ ], - \ getregionpos(getpos("'["), getpos("']"), - \ #{ mode: visualmode() })) - \ | call assert_equal(['abcd'], - \ getregion(getpos("'["), getpos("']"), - \ #{ mode: visualmode() })) - \ | call assert_equal([ - \ [[bufnr('%'), 1, 1, 0], [bufnr('%'), 1, 4, 0]], - \ ], - \ getregionpos(getpos("']"), getpos("'["), - \ #{ mode: visualmode() })) - \ | call assert_equal(['abcd'], - \ getregion(getpos("']"), getpos("'["), - \ #{ mode: visualmode() })) + \ | call Check_Results(v:event.regtype) \ | endif - call setline(1, ['abcd', 'efghij']) + + new + call setline(1, ['abcd', 'efghijk', 'lmn']) + + let g:expected_region = ['abcd'] + let g:expected_regionpos = [ + \ [[bufnr('%'), 1, 1, 0], [bufnr('%'), 1, 4, 0]], + \ ] + let g:checked = 0 normal yy + call assert_equal(1, g:checked) + call Check_Results(getregtype('"')) + + let g:expected_region = ['cd', 'ghijk', 'n'] + let g:expected_regionpos = [ + \ [[bufnr('%'), 1, 3, 0], [bufnr('%'), 1, 4, 0]], + \ [[bufnr('%'), 2, 3, 0], [bufnr('%'), 2, 7, 0]], + \ [[bufnr('%'), 3, 3, 0], [bufnr('%'), 3, 3, 0]], + \ ] + let g:checked = 0 + call feedkeys("gg0ll\<C-V>jj$y", 'tx') + call assert_equal(1, g:checked) + call Check_Results(getregtype('"')) + call assert_equal(g:expected_region, getreg('"', v:true, v:true)) + + let g:expected_region = ['bc', 'fg', 'mn'] + let g:expected_regionpos = [ + \ [[bufnr('%'), 1, 2, 0], [bufnr('%'), 1, 3, 0]], + \ [[bufnr('%'), 2, 2, 0], [bufnr('%'), 2, 3, 0]], + \ [[bufnr('%'), 3, 2, 0], [bufnr('%'), 3, 3, 0]], + \ ] + let g:checked = 0 + call feedkeys("gg0l\<C-V>jjly", 'tx') + call assert_equal(1, g:checked) + call Check_Results(getregtype('"')) + call assert_equal(g:expected_region, getreg('"', v:true, v:true)) + bwipe! + + new + let lines = ['asdfghjkl', '«口=口»', 'qwertyuiop', '口口=口口', 'zxcvbnm'] + call setline(1, lines) + + let g:expected_region = lines + let g:expected_regionpos = [ + \ [[bufnr('%'), 1, 1, 0], [bufnr('%'), 1, 9, 0]], + \ [[bufnr('%'), 2, 1, 0], [bufnr('%'), 2, 11, 0]], + \ [[bufnr('%'), 3, 1, 0], [bufnr('%'), 3, 10, 0]], + \ [[bufnr('%'), 4, 1, 0], [bufnr('%'), 4, 13, 0]], + \ [[bufnr('%'), 5, 1, 0], [bufnr('%'), 5, 7, 0]], + \ ] + let g:checked = 0 + call feedkeys('ggyG', 'tx') + call assert_equal(1, g:checked) + call Check_Results(getregtype('"')) + call assert_equal(g:expected_region, getreg('"', v:true, v:true)) + + let g:expected_region = ['=口»', 'qwertyuiop', '口口=口'] + let g:expected_regionpos = [ + \ [[bufnr('%'), 2, 6, 0], [bufnr('%'), 2, 11, 0]], + \ [[bufnr('%'), 3, 1, 0], [bufnr('%'), 3, 10, 0]], + \ [[bufnr('%'), 4, 1, 0], [bufnr('%'), 4, 10, 0]], + \ ] + let g:checked = 0 + call feedkeys('2gg02lv2j2ly', 'tx') + call assert_equal(1, g:checked) + call Check_Results(getregtype('"')) + call assert_equal(g:expected_region, getreg('"', v:true, v:true)) + + let g:expected_region = ['asdf', '«口=', 'qwer', '口口', 'zxcv'] + let g:expected_regionpos = [ + \ [[bufnr('%'), 1, 1, 0], [bufnr('%'), 1, 4, 0]], + \ [[bufnr('%'), 2, 1, 0], [bufnr('%'), 2, 6, 0]], + \ [[bufnr('%'), 3, 1, 0], [bufnr('%'), 3, 4, 0]], + \ [[bufnr('%'), 4, 1, 0], [bufnr('%'), 4, 6, 0]], + \ [[bufnr('%'), 5, 1, 0], [bufnr('%'), 5, 4, 0]], + \ ] + let g:checked = 0 + call feedkeys("G0\<C-V>3l4ky", 'tx') + call assert_equal(1, g:checked) + call Check_Results(getregtype('"')) + call assert_equal(g:expected_region, getreg('"', v:true, v:true)) + + let g:expected_region = ['ghjkl', '口»', 'tyuiop', '=口口', 'bnm'] + let g:expected_regionpos = [ + \ [[bufnr('%'), 1, 5, 0], [bufnr('%'), 1, 9, 0]], + \ [[bufnr('%'), 2, 7, 0], [bufnr('%'), 2, 11, 0]], + \ [[bufnr('%'), 3, 5, 0], [bufnr('%'), 3, 10, 0]], + \ [[bufnr('%'), 4, 7, 0], [bufnr('%'), 4, 13, 0]], + \ [[bufnr('%'), 5, 5, 0], [bufnr('%'), 5, 7, 0]], + \ ] + let g:checked = 0 + call feedkeys("G04l\<C-V>$4ky", 'tx') + call assert_equal(1, g:checked) + call Check_Results(getregtype('"')) + call assert_equal(g:expected_region, getreg('"', v:true, v:true)) + + bwipe! + + unlet g:expected_region + unlet g:expected_regionpos + unlet g:checked + autocmd! TextYankPost + delfunc Check_Results endfunc func Test_visual_block_cursor_delete() diff --git a/test/unit/eval/typval_spec.lua b/test/unit/eval/typval_spec.lua index c69c9b0fae..4e3b461396 100644 --- a/test/unit/eval/typval_spec.lua +++ b/test/unit/eval/typval_spec.lua @@ -2326,7 +2326,7 @@ describe('typval.c', function() return lib.tv_dict_extend(d1, d2, action) end, emsg) end - itp('works', function() + pending('works (skip due to flakiness)', function() local d1 = dict() alloc_log:check({ a.dict(d1) }) eq({}, dct2tbl(d1)) |