diff options
88 files changed, 1129 insertions, 982 deletions
diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index e6ff09d351..5e6f05d973 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -288,7 +288,7 @@ jobs: run: cmake --build build --config MinSizeRel windows: - runs-on: windows-2019 + runs-on: windows-2022 timeout-minutes: 45 name: windows steps: @@ -348,14 +348,19 @@ jobs: run: cmake --build build --target functionaltest - if: success() || failure() && steps.abort_job.outputs.status == 'success' + uses: msys2/setup-msys2@v2 + with: + update: true + pacboy: >- + make:p gcc:p + release: false + + - if: success() || failure() && steps.abort_job.outputs.status == 'success' name: Run oldtest + shell: msys2 {0} run: | - # Add MSYS to path, required for e.g. `find` used in test scripts. - # But would break functionaltest, where its `more` would be used then. - $OldPath = $env:PATH - $env:PATH = "C:\msys64\usr\bin;$env:PATH" - & "C:\msys64\mingw64\bin\mingw32-make.exe" -C $(Convert-Path test\old\testdir) VERBOSE=1 - $env:PATH = $OldPath + cd test/old/testdir + mingw32-make VERBOSE=1 with-external-deps: runs-on: ubuntu-22.04 diff --git a/CMakePresets.json b/CMakePresets.json index 62abb2697f..22077a64a5 100644 --- a/CMakePresets.json +++ b/CMakePresets.json @@ -1,5 +1,5 @@ { - "version": 6, + "version": 3, "configurePresets": [ { "name": "base", @@ -94,20 +94,5 @@ "name": "iwyu", "configurePreset": "iwyu" } - ], - "workflowPresets": [ - { - "name": "iwyu", - "steps": [ - { - "type": "configure", - "name": "iwyu" - }, - { - "type": "build", - "name": "iwyu" - } - ] - } ] } diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index ca13e1b956..91f2ff64dc 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -253,7 +253,8 @@ For managing includes in C files, use [include-what-you-use]. - [Install include-what-you-use][include-what-you-use-install] - To see which includes needs fixing use the cmake preset `iwyu`: ``` - cmake --workflow --preset iwyu + cmake --preset iwyu + cmake --build --preset iwyu ``` - There's also a make target that automatically fixes the suggestions from IWYU: @@ -137,7 +137,8 @@ generated-sources benchmark uninstall $(FORMAT) $(LINT) $(TEST): | build/.ran-cm test: $(TEST) iwyu: build/.ran-cmake - cmake --workflow --fresh --preset iwyu > build/iwyu.log + cmake --preset iwyu + cmake --build --preset iwyu > build/iwyu.log iwyu-fix-includes --only_re="src/nvim" --ignore_re="src/nvim/(auto|map.h|eval/encode.c)" --safe_headers < build/iwyu.log cmake -B build -U ENABLE_IWYU diff --git a/runtime/doc/autocmd.txt b/runtime/doc/autocmd.txt index e9a4196252..d0713ee18c 100644 --- a/runtime/doc/autocmd.txt +++ b/runtime/doc/autocmd.txt @@ -704,7 +704,6 @@ InsertCharPre When a character is typed in Insert mode, inserted literally. Cannot change the text. |textlock| - Not triggered when 'paste' is set. *InsertEnter* InsertEnter Just before starting Insert mode. Also for Replace mode and Virtual Replace mode. The diff --git a/runtime/doc/change.txt b/runtime/doc/change.txt index 3706612d52..91358a8cdd 100644 --- a/runtime/doc/change.txt +++ b/runtime/doc/change.txt @@ -1725,8 +1725,6 @@ Note that when 'textwidth' is 0, Vim does no automatic formatting anyway (but does insert comment leaders according to the 'comments' option). An exception is when the 'a' flag is present. |auto-format| -Note that when 'paste' is on, Vim does no formatting at all. - Note that 'textwidth' can be non-zero even if Vim never performs auto-wrapping; 'textwidth' is still useful for formatting with "gq". diff --git a/runtime/doc/deprecated.txt b/runtime/doc/deprecated.txt index 3d861b07b3..fe1d6f1645 100644 --- a/runtime/doc/deprecated.txt +++ b/runtime/doc/deprecated.txt @@ -129,6 +129,7 @@ TREESITTER FUNCTIONS LUA - *vim.register_keystroke_callback()* Use |vim.on_key()| instead. +- *vim.pretty_print()* Use |vim.print()| instead. NORMAL COMMANDS - *]f* *[f* Same as "gf". @@ -145,6 +146,27 @@ OPTIONS - 'viewoptions' Flags "unix", "slash" are ignored and always enabled. - *'viminfo'* Deprecated alias to 'shada' option. - *'viminfofile'* Deprecated alias to 'shadafile' option. +- *'paste'* *'nopaste'* This option is obsolete; |paste| is handled automatically. + Enables "paste mode": + - mappings in Insert mode and Command-line mode are + disabled + - abbreviations are disabled + - 'autoindent' is reset + - 'expandtab' is reset + - 'formatoptions' is used like it is empty + - 'revins' is reset + - 'ruler' is reset + - 'showmatch' is reset + - 'smartindent' is reset + - 'smarttab' is reset + - 'softtabstop' is set to 0 + - 'textwidth' is set to 0 + - 'wrapmargin' is set to 0 + These options keep their value, but their effect is + disabled: + - 'cindent' + - 'indentexpr' + - 'lisp' UI EXTENSIONS - *ui-wildmenu* Use |ui-cmdline| with |ui-popupmenu| instead. Enabled diff --git a/runtime/doc/diagnostic.txt b/runtime/doc/diagnostic.txt index cff73ad097..f888bb0991 100644 --- a/runtime/doc/diagnostic.txt +++ b/runtime/doc/diagnostic.txt @@ -325,7 +325,7 @@ Example: >lua vim.api.nvim_create_autocmd('DiagnosticChanged', { callback = function(args) local diagnostics = args.data.diagnostics - vim.pretty_print(diagnostics) + vim.print(diagnostics) end, }) < diff --git a/runtime/doc/lsp.txt b/runtime/doc/lsp.txt index d13dc4a782..ca65251a9f 100644 --- a/runtime/doc/lsp.txt +++ b/runtime/doc/lsp.txt @@ -676,7 +676,7 @@ buf_request_all({bufnr}, {method}, {params}, {callback}) finished. Unlike `buf_request`, this will collect all the responses from each server instead of handling them. A map of client_id:request_result will be provided to the - callback + callback. Return: ~ fun() cancel A function that will cancel all requests @@ -697,9 +697,9 @@ buf_request_sync({bufnr}, {method}, {params}, {timeout_ms}) result. Defaults to 1000 Return: ~ - table<integer, any>|nil result, string|nil err Map of - client_id:request_result. On timeout, cancel or error, returns `(nil, - err)` where `err` is a string describing the failure reason. + (table) result Map of client_id:request_result. + (string|nil) err On timeout, cancel, or error, `err` is a string + describing the failure reason, and `result` is nil. client() *vim.lsp.client* LSP client object. You can get an active client object via diff --git a/runtime/doc/lua-guide.txt b/runtime/doc/lua-guide.txt index 8ea84f8c60..5e2b753645 100644 --- a/runtime/doc/lua-guide.txt +++ b/runtime/doc/lua-guide.txt @@ -10,16 +10,16 @@ ============================================================================== Introduction *lua-guide* -This guide will go through the basics of using Lua in Neovim. It is not meant +This guide will go through the basics of using Lua in Nvim. It is not meant to be a comprehensive encyclopedia of all available features, nor will it detail all intricacies. Think of it as a survival kit -- the bare minimum -needed to know to comfortably get started on using Lua in Neovim. +needed to know to comfortably get started on using Lua in Nvim. An important thing to note is that this isn't a guide to the Lua language -itself. Rather, this is a guide on how to configure and modify Neovim through +itself. Rather, this is a guide on how to configure and modify Nvim through the Lua language and the functions we provide to help with this. Take a look at |luaref| and |lua-concepts| if you'd like to learn more about Lua itself. -Similarly, this guide assumes some familiarity with the basics of Neovim +Similarly, this guide assumes some familiarity with the basics of Nvim (commands, options, mappings, autocommands), which are covered in the |user-manual|. @@ -27,7 +27,7 @@ Similarly, this guide assumes some familiarity with the basics of Neovim Some words on the API *lua-guide-api* The purpose of this guide is to introduce the different ways of interacting -with Neovim through Lua (the "API"). This API consists of three different +with Nvim through Lua (the "API"). This API consists of three different layers: 1. The "Vim API" inherited from Vim: |ex-commands| and |builtin-functions| as @@ -35,14 +35,14 @@ well as |user-function|s in Vimscript. These are accessed through |vim.cmd()| and |vim.fn| respectively, which are discussed under |lua-guide-vimscript| below. -2. The "Neovim API" written in C for use in remote plugins and GUIs; see |api|. +2. The "Nvim API" written in C for use in remote plugins and GUIs; see |api|. These functions are accessed through |vim.api|. 3. The "Lua API" written in and specifically for Lua. These are any other functions accessible through `vim.*` not mentioned already; see |lua-stdlib|. This distinction is important, as API functions inherit behavior from their -original layer: For example, Neovim API functions always need all arguments to +original layer: For example, Nvim API functions always need all arguments to be specified even if Lua itself allows omitting arguments (which are then passed as `nil`); and Vim API functions can use 0-based indexing even if Lua arrays are 1-indexed by default. @@ -58,7 +58,7 @@ convenient to use from Lua. ============================================================================== Using Lua *lua-guide-using-Lua* -To run Lua code from the Neovim command line, use the |:lua| command: +To run Lua code from the Nvim command line, use the |:lua| command: >vim :lua print("Hello!") < @@ -69,10 +69,10 @@ local keyword are not accessible outside of the command. This won't work: :lua print(foo) " prints "nil" instead of "1" < -You can also use `:lua=`, which is the same as `:lua vim.pretty_print(...)`, -to conveniently check the value of a variable or a table: +You can also use `:lua=`, which is equivalent to `:lua vim.print(...)`, to +conveniently check the value of a variable or a table: >vim - :lua=package + :lua =package < To run a Lua script in an external file, you can use the |:source| command exactly like for a Vimscript file: @@ -92,7 +92,7 @@ Finally, you can include Lua code in a Vimscript file by putting it inside a ------------------------------------------------------------------------------ Using Lua files on startup *lua-guide-config* -Neovim supports using `init.vim` or `init.lua` as the configuration file, but +Nvim supports using `init.vim` or `init.lua` as the configuration file, but not both at the same time. This should be placed in your |config| directory, which is typically `~/.config/nvim` for Linux, BSD, or macOS, and `~/AppData/Local/nvim/` for Windows. Note that you can use Lua in `init.vim` @@ -279,7 +279,7 @@ Note that you cannot directly change fields of array variables. This won't work: >lua vim.g.some_global_variable.key2 = 400 - vim.pretty_print(vim.g.some_global_variable) + vim.print(vim.g.some_global_variable) --> { key1 = "value", key2 = 300 } < Instead, you need to create an intermediate Lua table and change this: @@ -287,7 +287,7 @@ Instead, you need to create an intermediate Lua table and change this: local temp_table = vim.g.some_global_variable temp_table.key2 = 400 vim.g.some_global_variable = temp_table - vim.pretty_print(vim.g.some_global_variable) + vim.print(vim.g.some_global_variable) --> { key1 = "value", key2 = 400 } < To delete a variable, simply set it to `nil`: @@ -350,7 +350,7 @@ use |vim.opt:get()|: --> {...} (big table) print(vim.opt.smarttab:get()) --> false - vim.pretty_print(vim.opt.listchars:get()) + vim.print(vim.opt.listchars:get()) --> { space = '_', tab = '>~' } < ------------------------------------------------------------------------------ @@ -488,7 +488,7 @@ Autocommands *lua-guide-autocommands* An |autocommand| is a Vim command or a Lua function that is automatically executed whenever one or more |events| are triggered, e.g., when a file is read or written, or when a window is created. These are accessible from Lua -through the Neovim API. +through the Nvim API. ------------------------------------------------------------------------------ Creating autocommands *lua-guide-autocommand-create* @@ -530,7 +530,7 @@ Examples: }) < -Neovim will always call a Lua function with a single table containing information +Nvim will always call a Lua function with a single table containing information about the triggered autocommand. The most useful keys are • `match`: a string that matched the `pattern` (see |<amatch>|) • `buf`: the number of the buffer the event was triggered in (see |<abuf>|) @@ -667,9 +667,8 @@ cover only the basics of this advanced topic. ------------------------------------------------------------------------------ Creating user commands *lua-guide-commands-create* -User commands can be created through the Neovim API with -`vim.api.`|nvim_create_user_command()|. This function takes three mandatory -arguments: +User commands can be created through with |nvim_create_user_command()|. This +function takes three mandatory arguments: • a string that is the name of the command (which must start with an uppercase letter to distinguish it from builtin commands); • a string containing Vim commands or a Lua function that is executed when the diff --git a/runtime/doc/lua.txt b/runtime/doc/lua.txt index bcd68b7608..81e45ae9bb 100644 --- a/runtime/doc/lua.txt +++ b/runtime/doc/lua.txt @@ -1239,7 +1239,7 @@ which is accessed through |vim.opt:get()|: print(vim.o.wildignore) < In Lua using `vim.opt`: >lua - vim.pretty_print(vim.opt.wildignore:get()) + vim.print(vim.opt.wildignore:get()) < In any of the above examples, to replicate the behavior |:setlocal|, use @@ -1258,7 +1258,7 @@ Option:get() the values as entries in the array: >lua vim.cmd [[set wildignore=*.pyc,*.o]] - vim.pretty_print(vim.opt.wildignore:get()) + vim.print(vim.opt.wildignore:get()) -- { "*.pyc", "*.o", } for _, ignore_pattern in ipairs(vim.opt.wildignore:get()) do @@ -1271,7 +1271,7 @@ Option:get() the names as keys and the values as entries: >lua vim.cmd [[set listchars=space:_,tab:>~]] - vim.pretty_print(vim.opt.listchars:get()) + vim.print(vim.opt.listchars:get()) -- { space = "_", tab = ">~", } for char, representation in pairs(vim.opt.listchars:get()) do @@ -1282,7 +1282,7 @@ Option:get() as keys and `true` as entries. >lua vim.cmd [[set formatoptions=njtcroql]] - vim.pretty_print(vim.opt.formatoptions:get()) + vim.print(vim.opt.formatoptions:get()) -- { n = true, j = true, c = true, ... } local format_opts = vim.opt.formatoptions:get() @@ -1496,10 +1496,11 @@ paste({lines}, {phase}) *vim.paste()* See also: ~ |paste| @alias paste_phase -1 | 1 | 2 | 3 -pretty_print({...}) *vim.pretty_print()* - Prints given arguments in human-readable format. Example: >lua - -- Print highlight group Normal and store it's contents in a variable. - local hl_normal = vim.pretty_print(vim.api.nvim_get_hl_by_name("Normal", true)) +print({...}) *vim.print()* + "Pretty prints" the given arguments and returns them unmodified. + + Example: >lua + local hl_normal = vim.print(vim.api.nvim_get_hl_by_name('Normal', true)) < Return: ~ diff --git a/runtime/doc/map.txt b/runtime/doc/map.txt index 3a5223fa3a..c65007d1a4 100644 --- a/runtime/doc/map.txt +++ b/runtime/doc/map.txt @@ -695,8 +695,7 @@ this (see |<>|). Example: > :map _ls :!ls -l %:S<CR>:echo "the end"<CR> To avoid mapping of the characters you type in insert or Command-line mode, -type a CTRL-V first. The mapping in Insert mode is disabled if the 'paste' -option is on. +type a CTRL-V first. *map-error* Note that when an error is encountered (that causes an error message or might cause a beep) the rest of the mapping is not executed. This is Vi-compatible. @@ -1070,8 +1069,6 @@ Abbreviations are never recursive. You can use ":ab f f-o-o" without any problem. But abbreviations can be mapped. {some versions of Vi support recursive abbreviations, for no apparent reason} -Abbreviations are disabled if the 'paste' option is on. - *:abbreviate-local* *:abbreviate-<buffer>* Just like mappings, abbreviations can be local to a buffer. This is mostly used in a |filetype-plugin| file. Example for a C plugin file: > diff --git a/runtime/doc/news.txt b/runtime/doc/news.txt index da9ebd589f..64cf5d78ba 100644 --- a/runtime/doc/news.txt +++ b/runtime/doc/news.txt @@ -45,11 +45,21 @@ The following changes may require adaptations in user config or plugins. - `printheader` - `printmbcharset` +• 'paste' option is now deprecated and 'pastetoggle' is removed. |paste| works + automatically in GUI and terminal (TUI) Nvim. Just Paste It.™ + • libiconv and intl are now required build dependencies. • Unsaved changes are now preserved rather than discarded when |channel-stdio| is closed. +• Changes to |vim.treesitter.get_node_text()|: + - It now returns `string`, as opposed to `string|string[]|nil`. + - The `concat` option has been removed as it was not consistently applied. + - Invalid ranges now cause an error instead of returning `nil`. + +• Renamed vim.pretty_print to vim.print. |deprecated| + ============================================================================== NEW FEATURES *news-features* @@ -218,6 +228,9 @@ The following changes to existing APIs or features add new behavior. • API calls now show more information about where an exception happened. +• The `win_viewport` UI event now contains information about virtual lines, + meaning that smooth scrolling can now be implemented more consistenlty. + ============================================================================== REMOVED FEATURES *news-removed* diff --git a/runtime/doc/options.txt b/runtime/doc/options.txt index 6c5b168402..9fff5228f2 100644 --- a/runtime/doc/options.txt +++ b/runtime/doc/options.txt @@ -676,8 +676,6 @@ A jump table for the options with a short description can be found at |Q_op|. line. When 'smartindent' or 'cindent' is on the indent is changed in a different way. - The 'autoindent' option is reset when the 'paste' option is set and - restored when 'paste' is reset. {small difference from Vi: After the indent is deleted when typing <Esc> or <CR>, the cursor position when moving up or down is after the deleted indent; Vi puts the cursor somewhere in the deleted indent}. @@ -1266,7 +1264,6 @@ A jump table for the options with a short description can be found at |Q_op|. See |C-indenting|. When you don't like the way 'cindent' works, try the 'smartindent' option or 'indentexpr'. - This option is not used when 'paste' is set. *'cinkeys'* *'cink'* 'cinkeys' 'cink' string (default "0{,0},0),0],:,0#,!^F,o,O,e") @@ -2246,8 +2243,6 @@ A jump table for the options with a short description can be found at |Q_op|. <Tab>. Spaces are used in indents with the '>' and '<' commands and when 'autoindent' is on. To insert a real tab when 'expandtab' is on, use CTRL-V<Tab>. See also |:retab| and |ins-expandtab|. - This option is reset when the 'paste' option is set and restored when - the 'paste' option is reset. *'exrc'* *'ex'* *'noexrc'* *'noex'* 'exrc' 'ex' boolean (default off) @@ -2749,9 +2744,8 @@ A jump table for the options with a short description can be found at |Q_op|. 'formatoptions' 'fo' string (default: "tcqj") local to buffer This is a sequence of letters which describes how automatic - formatting is to be done. See |fo-table|. When the 'paste' option is - on, no formatting is done (like 'formatoptions' is empty). Commas can - be inserted for readability. + formatting is to be done. See |fo-table|. Commas can be inserted for + readability. To avoid problems with flags that are added in the future, use the "+=" and "-=" feature of ":set" |add-option-flags|. @@ -3392,7 +3386,6 @@ A jump table for the options with a short description can be found at |Q_op|. When this option is not empty, it overrules the 'cindent' and 'smartindent' indenting. When 'lisp' is set, this option is is only used when 'lispoptions' contains "expr:1". - When 'paste' is set this option is not used for indenting. The expression is evaluated with |v:lnum| set to the line number for which the indent is to be computed. The cursor is also in this line when the expression is evaluated (but it may be moved around). @@ -3761,7 +3754,6 @@ A jump table for the options with a short description can be found at |Q_op|. The '-' character is included in keyword characters. Redefines the "=" operator to use this same indentation algorithm rather than calling an external program if 'equalprg' is empty. - This option is not used when 'paste' is set. *'lispoptions'* *'lop'* 'lispoptions' 'lop' string (default "") @@ -4474,77 +4466,6 @@ A jump table for the options with a short description can be found at |Q_op|. Specifies the nroff macros that separate paragraphs. These are pairs of two letters (see |object-motions|). - *'paste'* *'nopaste'* -'paste' boolean (default off) - global - This option is obsolete; |bracketed-paste-mode| is built-in. - - Put Vim in Paste mode. This is useful if you want to cut or copy - some text from one window and paste it in Vim. This will avoid - unexpected effects. - Setting this option is useful when using Vim in a terminal, where Vim - cannot distinguish between typed text and pasted text. In the GUI, Vim - knows about pasting and will mostly do the right thing without 'paste' - being set. The same is true for a terminal where Vim handles the - mouse clicks itself. - This option is reset when starting the GUI. Thus if you set it in - your vimrc it will work in a terminal, but not in the GUI. Setting - 'paste' in the GUI has side effects: e.g., the Paste toolbar button - will no longer work in Insert mode, because it uses a mapping. - When the 'paste' option is switched on (also when it was already on): - - mapping in Insert mode and Command-line mode is disabled - - abbreviations are disabled - - 'autoindent' is reset - - 'expandtab' is reset - - 'hkmap' is reset - - 'revins' is reset - - 'ruler' is reset - - 'showmatch' is reset - - 'smarttab' is reset - - 'softtabstop' is set to 0 - - 'textwidth' is set to 0 - - 'wrapmargin' is set to 0 - - 'varsofttabstop' is made empty - These options keep their value, but their effect is disabled: - - 'cindent' - - 'formatoptions' is used like it is empty - - 'indentexpr' - - 'lisp' - - 'smartindent' - NOTE: When you start editing another file while the 'paste' option is - on, settings from the modelines or autocommands may change the - settings again, causing trouble when pasting text. You might want to - set the 'paste' option again. - When the 'paste' option is reset the mentioned options are restored to - the value before the moment 'paste' was switched from off to on. - Resetting 'paste' before ever setting it does not have any effect. - Since mapping doesn't work while 'paste' is active, you need to use - the 'pastetoggle' option to toggle the 'paste' option with some key. - - *'pastetoggle'* *'pt'* -'pastetoggle' 'pt' string (default "") - global - When non-empty, specifies the key sequence that toggles the 'paste' - option. This is like specifying a mapping: > - :map {keys} :set invpaste<CR> -< Where {keys} is the value of 'pastetoggle'. - The difference is that it will work even when 'paste' is set. - 'pastetoggle' works in Insert mode and Normal mode, but not in - Command-line mode. - Mappings are checked first, thus overrule 'pastetoggle'. However, - when 'paste' is on mappings are ignored in Insert mode, thus you can do - this: > - :map <F10> :set paste<CR> - :map <F11> :set nopaste<CR> - :imap <F10> <C-O>:set paste<CR> - :imap <F11> <nop> - :set pastetoggle=<F11> -< This will make <F10> start paste mode and <F11> stop paste mode. - Note that typing <F10> in paste mode inserts "<F10>", since in paste - mode everything is inserted literally, except the 'pastetoggle' key - sequence. - When the value has several bytes 'ttimeoutlen' applies. - *'pex'* *'patchexpr'* 'patchexpr' 'pex' string (default "") global @@ -4827,8 +4748,6 @@ A jump table for the options with a short description can be found at |Q_op|. Inserting characters in Insert mode will work backwards. See "typing backwards" |ins-reverse|. This option can be toggled with the CTRL-_ command in Insert mode, when 'allowrevins' is set. - This option is reset when 'paste' is set and restored when 'paste' is - reset. *'rightleft'* *'rl'* *'norightleft'* *'norl'* 'rightleft' 'rl' boolean (default off) @@ -4877,8 +4796,6 @@ A jump table for the options with a short description can be found at |Q_op|. separated with a dash. For an empty line "0-1" is shown. For an empty buffer the line number will also be zero: "0,0-1". - This option is reset when 'paste' is set and restored when 'paste' is - reset. If you don't want to see the ruler all the time but want to know where you are, use "g CTRL-G" |g_CTRL-G|. @@ -5610,8 +5527,6 @@ A jump table for the options with a short description can be found at |Q_op|. show the match can be set with 'matchtime'. A Beep is given if there is no match (no matter if the match can be seen or not). - This option is reset when 'paste' is set and restored when 'paste' is - reset. When the 'm' flag is not included in 'cpoptions', typing a character will immediately move the cursor back to where it belongs. See the "sm" field in 'guicursor' for setting the cursor shape and @@ -5733,8 +5648,6 @@ A jump table for the options with a short description can be found at |Q_op|. mapping: ":inoremap # X^H#", where ^H is entered with CTRL-V CTRL-H. When using the ">>" command, lines starting with '#' are not shifted right. - This option is reset when 'paste' is set and restored when 'paste' is - reset. *'smarttab'* *'sta'* *'nosmarttab'* *'nosta'* 'smarttab' 'sta' boolean (default on) @@ -5749,8 +5662,6 @@ A jump table for the options with a short description can be found at |Q_op|. What gets inserted (a <Tab> or spaces) depends on the 'expandtab' option. Also see |ins-expandtab|. When 'expandtab' is not set, the number of spaces is minimized by using <Tab>s. - This option is reset when 'paste' is set and restored when 'paste' is - reset. *'softtabstop'* *'sts'* 'softtabstop' 'sts' number (default 0) @@ -5763,8 +5674,6 @@ A jump table for the options with a short description can be found at |Q_op|. commands like "x" still work on the actual characters. When 'sts' is zero, this feature is off. When 'sts' is negative, the value of 'shiftwidth' is used. - 'softtabstop' is set to 0 when the 'paste' option is set and restored - when 'paste' is reset. See also |ins-expandtab|. When 'expandtab' is not set, the number of spaces is minimized by using <Tab>s. The 'L' flag in 'cpoptions' changes how tabs are used when 'list' is @@ -6579,8 +6488,6 @@ A jump table for the options with a short description can be found at |Q_op|. Maximum width of text that is being inserted. A longer line will be broken after white space to get this width. A zero value disables this. - 'textwidth' is set to 0 when the 'paste' option is set and restored - when 'paste' is reset. When 'textwidth' is zero, 'wrapmargin' may be used. See also 'formatoptions' and |ins-textwidth|. When 'formatexpr' is set it will be used to break the line. diff --git a/runtime/doc/quickref.txt b/runtime/doc/quickref.txt index d17df3cd61..952f0064e6 100644 --- a/runtime/doc/quickref.txt +++ b/runtime/doc/quickref.txt @@ -812,8 +812,6 @@ Short explanation of each option: *option-list* 'operatorfunc' 'opfunc' function to be called for |g@| operator 'packpath' 'pp' list of directories used for packages 'paragraphs' 'para' nroff macros that separate paragraphs -'paste' allow pasting text -'pastetoggle' 'pt' key code that causes 'paste' to toggle 'patchexpr' 'pex' expression used to patch a file 'patchmode' 'pm' keep the oldest version of a file 'path' 'pa' list of directories searched with "gf" et.al. diff --git a/runtime/doc/treesitter.txt b/runtime/doc/treesitter.txt index a8f25d2ff9..ddca307e74 100644 --- a/runtime/doc/treesitter.txt +++ b/runtime/doc/treesitter.txt @@ -789,14 +789,12 @@ get_node_text({node}, {source}, {opts}) • {source} (integer|string) Buffer or string from which the {node} is extracted • {opts} (table|nil) Optional parameters. - • concat: (boolean) Concatenate result in a string (default - true) • metadata (table) Metadata of a specific capture. This would be set to `metadata[capture_id]` when using |vim.treesitter.add_directive()|. Return: ~ - (string[]|string|nil) + (string) get_query({lang}, {query_name}) *vim.treesitter.get_query()* Returns the runtime query {query_name} for {lang}. @@ -822,6 +820,19 @@ get_query_files({lang}, {query_name}, {is_included}) string[] query_files List of files to load for given query and language +get_range({node}, {source}, {metadata}) *vim.treesitter.get_range()* + Get the range of a |TSNode|. Can also supply {source} and {metadata} to + get the range with directives applied. + + Parameters: ~ + • {node} |TSNode| + • {source} integer|string|nil Buffer or string from which the {node} + is extracted + • {metadata} TSMetadata|nil + + Return: ~ + (table) + list_directives() *vim.treesitter.list_directives()* Lists the currently available directives to use in queries. @@ -887,7 +898,8 @@ Query:iter_captures({self}, {node}, {source}, {start}, {stop}) • {self} Return: ~ - (fun(): integer, TSNode, TSMetadata ): capture id, capture node, metadata + (fun(): integer, TSNode, TSMetadata): capture id, capture node, + metadata *Query:iter_matches()* Query:iter_matches({self}, {node}, {source}, {start}, {stop}) diff --git a/runtime/doc/ui.txt b/runtime/doc/ui.txt index e706e36374..4ff74714f3 100644 --- a/runtime/doc/ui.txt +++ b/runtime/doc/ui.txt @@ -626,11 +626,15 @@ tabs. When |ui-messages| is active, no message grid is used, and this event will not be sent. -["win_viewport", grid, win, topline, botline, curline, curcol] ~ +["win_viewport", grid, win, topline, botline, curline, curcol, line_count, scroll_delta] ~ Indicates the range of buffer text displayed in the window, as well as the cursor position in the buffer. All positions are zero-based. `botline` is set to one more than the line count of the buffer, if - there are filler lines past the end. + there are filler lines past the end. `scroll_delta` contains how much + the top line of a window moved since `win_viewport` was last emitted. + It is intended to be used to implement smooth scrolling. For this + purpose it only counts "virtual" or "displayed" lines, so folds + only count as one line. ["win_extmark", grid, win, ns_id, mark_id, row, col] ~ Updates the position of an extmark which is currently visible in a diff --git a/runtime/doc/vim_diff.txt b/runtime/doc/vim_diff.txt index 21736059c4..9c01e3dbc7 100644 --- a/runtime/doc/vim_diff.txt +++ b/runtime/doc/vim_diff.txt @@ -623,6 +623,7 @@ Options: 'highlight' (Names of builtin |highlight-groups| cannot be changed.) *'hkmap'* *'hk'* use `set keymap=hebrew` instead. *'hkmapp'* *'hkp'* use `set keymap=hebrewp` instead. + *'pastetoggle'* *'pt'* *'imactivatefunc'* *'imaf'* *'imactivatekey'* *'imak'* diff --git a/runtime/lua/vim/_editor.lua b/runtime/lua/vim/_editor.lua index 9516233b45..5445c4e492 100644 --- a/runtime/lua/vim/_editor.lua +++ b/runtime/lua/vim/_editor.lua @@ -778,22 +778,37 @@ do end end ----Prints given arguments in human-readable format. ----Example: ----<pre>lua ---- -- Print highlight group Normal and store it's contents in a variable. ---- local hl_normal = vim.pretty_print(vim.api.nvim_get_hl_by_name("Normal", true)) ----</pre> ----@see |vim.inspect()| ----@return any # given arguments. +---@private function vim.pretty_print(...) - local objects = {} + vim.deprecate('vim.pretty_print', 'vim.print', '0.10') + return vim.print(...) +end + +--- "Pretty prints" the given arguments and returns them unmodified. +--- +--- Example: +--- <pre>lua +--- local hl_normal = vim.print(vim.api.nvim_get_hl_by_name('Normal', true)) +--- </pre> +--- +--- @see |vim.inspect()| +--- @return any # given arguments. +function vim.print(...) + if vim.in_fast_event() then + print(...) + return ... + end + for i = 1, select('#', ...) do - local v = select(i, ...) - table.insert(objects, vim.inspect(v)) + local o = select(i, ...) + if type(o) == 'string' then + vim.api.nvim_out_write(o) + else + vim.api.nvim_out_write(vim.inspect(o, { newline = '\n', indent = ' ' })) + end + vim.api.nvim_out_write('\n') end - print(table.concat(objects, ' ')) return ... end diff --git a/runtime/lua/vim/lsp.lua b/runtime/lua/vim/lsp.lua index 117b32dc57..39665a3d4f 100644 --- a/runtime/lua/vim/lsp.lua +++ b/runtime/lua/vim/lsp.lua @@ -1,3 +1,4 @@ +---@diagnostic disable: invisible local default_handlers = require('vim.lsp.handlers') local log = require('vim.lsp.log') local lsp_rpc = require('vim.lsp.rpc') @@ -1037,7 +1038,7 @@ function lsp.start_client(config) --- Returns the default handler if the user hasn't set a custom one. --- ---@param method (string) LSP method name - ---@return function|nil The handler for the given method, if defined, or the default from |vim.lsp.handlers| + ---@return lsp-handler|nil The handler for the given method, if defined, or the default from |vim.lsp.handlers| local function resolve_handler(method) return handlers[method] or default_handlers[method] end @@ -1592,6 +1593,11 @@ local function text_document_did_save_handler(bufnr) local name = api.nvim_buf_get_name(bufnr) local old_name = changetracking._get_and_set_name(client, bufnr, name) if old_name and name ~= old_name then + client.notify('textDocument/didClose', { + textDocument = { + uri = vim.uri_from_fname(old_name), + }, + }) client.notify('textDocument/didOpen', { textDocument = { version = 0, @@ -1932,7 +1938,7 @@ api.nvim_create_autocmd('VimLeavePre', { ---@param bufnr (integer) Buffer handle, or 0 for current. ---@param method (string) LSP method name ---@param params table|nil Parameters to send to the server ----@param handler function|nil See |lsp-handler| +---@param handler lsp-handler|nil See |lsp-handler| --- If nil, follows resolution strategy defined in |lsp-handler-configuration| --- ---@return table<integer, integer>, fun() 2-tuple: @@ -1992,9 +1998,10 @@ end ---@param bufnr (integer) Buffer handle, or 0 for current. ---@param method (string) LSP method name ---@param params (table|nil) Parameters to send to the server ----@param callback (function) The callback to call when all requests are finished. +---@param callback fun(request_results: table<integer, {error: lsp.ResponseError, result: any}>) (function) +--- The callback to call when all requests are finished. --- Unlike `buf_request`, this will collect all the responses from each server instead of handling them. ---- A map of client_id:request_result will be provided to the callback +--- A map of client_id:request_result will be provided to the callback. --- ---@return fun() cancel A function that will cancel all requests function lsp.buf_request_all(bufnr, method, params, callback) @@ -2037,9 +2044,8 @@ end ---@param timeout_ms (integer|nil) Maximum time in milliseconds to wait for a --- result. Defaults to 1000 --- ----@return table<integer, any>|nil result, string|nil err Map of client_id:request_result. ---- On timeout, cancel or error, returns `(nil, err)` where `err` is a string describing ---- the failure reason. +---@return table<integer, {err: lsp.ResponseError, result: any}>|nil (table) result Map of client_id:request_result. +---@return string|nil err On timeout, cancel, or error, `err` is a string describing the failure reason, and `result` is nil. function lsp.buf_request_sync(bufnr, method, params, timeout_ms) local request_results diff --git a/runtime/lua/vim/lsp/buf.lua b/runtime/lua/vim/lsp/buf.lua index 6ac885c78f..0e16e8f820 100644 --- a/runtime/lua/vim/lsp/buf.lua +++ b/runtime/lua/vim/lsp/buf.lua @@ -118,8 +118,10 @@ function M.completion(context) end ---@private +---@param bufnr integer +---@param mode "v"|"V" ---@return table {start={row, col}, end={row, col}} using (1, 0) indexing -local function range_from_selection() +local function range_from_selection(bufnr, mode) -- TODO: Use `vim.region()` instead https://github.com/neovim/neovim/pull/13896 -- [bufnum, lnum, col, off]; both row and column 1-indexed @@ -138,6 +140,11 @@ local function range_from_selection() start_row, end_row = end_row, start_row start_col, end_col = end_col, start_col end + if mode == 'V' then + start_col = 1 + local lines = api.nvim_buf_get_lines(bufnr, end_row - 1, end_row, true) + end_col = #lines[1] + end return { ['start'] = { start_row, start_col - 1 }, ['end'] = { end_row, end_col - 1 }, @@ -200,7 +207,7 @@ function M.format(options) local mode = api.nvim_get_mode().mode local range = options.range if not range and mode == 'v' or mode == 'V' then - range = range_from_selection() + range = range_from_selection(bufnr, mode) end local method = range and 'textDocument/rangeFormatting' or 'textDocument/formatting' @@ -772,7 +779,7 @@ function M.code_action(options) local end_ = assert(options.range['end'], 'range must have a `end` property') params = util.make_given_range_params(start, end_) elseif mode == 'v' or mode == 'V' then - local range = range_from_selection() + local range = range_from_selection(0, mode) params = util.make_given_range_params(range.start, range['end']) else params = util.make_range_params() diff --git a/runtime/lua/vim/lsp/protocol.lua b/runtime/lua/vim/lsp/protocol.lua index 27dd68645a..1686e22c48 100644 --- a/runtime/lua/vim/lsp/protocol.lua +++ b/runtime/lua/vim/lsp/protocol.lua @@ -854,7 +854,6 @@ function protocol.make_client_capabilities() } end -local if_nil = vim.F.if_nil --- Creates a normalized object describing LSP server capabilities. ---@param server_capabilities table Table of capabilities supported by the server ---@return table Normalized table of capabilities @@ -892,178 +891,5 @@ function protocol.resolve_capabilities(server_capabilities) return server_capabilities end ----@private ---- Creates a normalized object describing LSP server capabilities. --- @deprecated access resolved_capabilities instead ----@param server_capabilities table Table of capabilities supported by the server ----@return table Normalized table of capabilities -function protocol._resolve_capabilities_compat(server_capabilities) - local general_properties = {} - local text_document_sync_properties - do - local TextDocumentSyncKind = protocol.TextDocumentSyncKind - local textDocumentSync = server_capabilities.textDocumentSync - if textDocumentSync == nil then - -- Defaults if omitted. - text_document_sync_properties = { - text_document_open_close = false, - text_document_did_change = TextDocumentSyncKind.None, - -- text_document_did_change = false; - text_document_will_save = false, - text_document_will_save_wait_until = false, - text_document_save = false, - text_document_save_include_text = false, - } - elseif type(textDocumentSync) == 'number' then - -- Backwards compatibility - if not TextDocumentSyncKind[textDocumentSync] then - return nil, 'Invalid server TextDocumentSyncKind for textDocumentSync' - end - text_document_sync_properties = { - text_document_open_close = true, - text_document_did_change = textDocumentSync, - text_document_will_save = false, - text_document_will_save_wait_until = false, - text_document_save = true, - text_document_save_include_text = false, - } - elseif type(textDocumentSync) == 'table' then - text_document_sync_properties = { - text_document_open_close = if_nil(textDocumentSync.openClose, false), - text_document_did_change = if_nil(textDocumentSync.change, TextDocumentSyncKind.None), - text_document_will_save = if_nil(textDocumentSync.willSave, true), - text_document_will_save_wait_until = if_nil(textDocumentSync.willSaveWaitUntil, true), - text_document_save = if_nil(textDocumentSync.save, false), - text_document_save_include_text = if_nil( - type(textDocumentSync.save) == 'table' and textDocumentSync.save.includeText, - false - ), - } - else - return nil, string.format('Invalid type for textDocumentSync: %q', type(textDocumentSync)) - end - end - general_properties.completion = server_capabilities.completionProvider ~= nil - general_properties.hover = server_capabilities.hoverProvider or false - general_properties.goto_definition = server_capabilities.definitionProvider or false - general_properties.find_references = server_capabilities.referencesProvider or false - general_properties.document_highlight = server_capabilities.documentHighlightProvider or false - general_properties.document_symbol = server_capabilities.documentSymbolProvider or false - general_properties.workspace_symbol = server_capabilities.workspaceSymbolProvider or false - general_properties.document_formatting = server_capabilities.documentFormattingProvider or false - general_properties.document_range_formatting = server_capabilities.documentRangeFormattingProvider - or false - general_properties.call_hierarchy = server_capabilities.callHierarchyProvider or false - general_properties.execute_command = server_capabilities.executeCommandProvider ~= nil - - if server_capabilities.renameProvider == nil then - general_properties.rename = false - elseif type(server_capabilities.renameProvider) == 'boolean' then - general_properties.rename = server_capabilities.renameProvider - else - general_properties.rename = true - end - - if server_capabilities.codeLensProvider == nil then - general_properties.code_lens = false - general_properties.code_lens_resolve = false - elseif type(server_capabilities.codeLensProvider) == 'table' then - general_properties.code_lens = true - general_properties.code_lens_resolve = server_capabilities.codeLensProvider.resolveProvider - or false - else - error('The server sent invalid codeLensProvider') - end - - if server_capabilities.codeActionProvider == nil then - general_properties.code_action = false - elseif - type(server_capabilities.codeActionProvider) == 'boolean' - or type(server_capabilities.codeActionProvider) == 'table' - then - general_properties.code_action = server_capabilities.codeActionProvider - else - error('The server sent invalid codeActionProvider') - end - - if server_capabilities.declarationProvider == nil then - general_properties.declaration = false - elseif type(server_capabilities.declarationProvider) == 'boolean' then - general_properties.declaration = server_capabilities.declarationProvider - elseif type(server_capabilities.declarationProvider) == 'table' then - general_properties.declaration = server_capabilities.declarationProvider - else - error('The server sent invalid declarationProvider') - end - - if server_capabilities.typeDefinitionProvider == nil then - general_properties.type_definition = false - elseif type(server_capabilities.typeDefinitionProvider) == 'boolean' then - general_properties.type_definition = server_capabilities.typeDefinitionProvider - elseif type(server_capabilities.typeDefinitionProvider) == 'table' then - general_properties.type_definition = server_capabilities.typeDefinitionProvider - else - error('The server sent invalid typeDefinitionProvider') - end - - if server_capabilities.implementationProvider == nil then - general_properties.implementation = false - elseif type(server_capabilities.implementationProvider) == 'boolean' then - general_properties.implementation = server_capabilities.implementationProvider - elseif type(server_capabilities.implementationProvider) == 'table' then - general_properties.implementation = server_capabilities.implementationProvider - else - error('The server sent invalid implementationProvider') - end - - local workspace = server_capabilities.workspace - local workspace_properties = {} - if workspace == nil or workspace.workspaceFolders == nil then - -- Defaults if omitted. - workspace_properties = { - workspace_folder_properties = { - supported = false, - changeNotifications = false, - }, - } - elseif type(workspace.workspaceFolders) == 'table' then - workspace_properties = { - workspace_folder_properties = { - supported = if_nil(workspace.workspaceFolders.supported, false), - changeNotifications = if_nil(workspace.workspaceFolders.changeNotifications, false), - }, - } - else - error('The server sent invalid workspace') - end - - local signature_help_properties - if server_capabilities.signatureHelpProvider == nil then - signature_help_properties = { - signature_help = false, - signature_help_trigger_characters = {}, - } - elseif type(server_capabilities.signatureHelpProvider) == 'table' then - signature_help_properties = { - signature_help = true, - -- The characters that trigger signature help automatically. - signature_help_trigger_characters = server_capabilities.signatureHelpProvider.triggerCharacters - or {}, - } - else - error('The server sent invalid signatureHelpProvider') - end - - local capabilities = vim.tbl_extend( - 'error', - text_document_sync_properties, - signature_help_properties, - workspace_properties, - general_properties - ) - - return capabilities -end - return protocol -- vim:sw=2 ts=2 et diff --git a/runtime/lua/vim/treesitter/_fold.lua b/runtime/lua/vim/treesitter/_fold.lua index 435cb9fdb6..90f4394fcc 100644 --- a/runtime/lua/vim/treesitter/_fold.lua +++ b/runtime/lua/vim/treesitter/_fold.lua @@ -1,4 +1,5 @@ local Range = require('vim.treesitter._range') +local Query = require('vim.treesitter.query') local api = vim.api @@ -74,18 +75,6 @@ function FoldInfo:get_stop(lnum) return self.stop_counts[lnum] or 0 end ----@private ---- TODO(lewis6991): copied from languagetree.lua. Consolidate ----@param node TSNode ----@param metadata TSMetadata ----@return Range4 -local function get_range_from_metadata(node, metadata) - if metadata and metadata.range then - return metadata.range --[[@as Range4]] - end - return { node:range() } -end - local function trim_level(level) local max_fold_level = vim.wo.foldnestmax if level > max_fold_level then @@ -118,7 +107,7 @@ local function get_folds_levels(bufnr, info, srow, erow) for id, node, metadata in query:iter_captures(tree:root(), bufnr, srow or 0, q_erow) do if query.captures[id] == 'fold' then - local range = get_range_from_metadata(node, metadata[id]) + local range = Query.get_range(node, bufnr, metadata[id]) local start, _, stop, stop_col = Range.unpack4(range) if stop_col == 0 then @@ -211,8 +200,9 @@ end local function on_bytes(bufnr, foldinfo, start_row, old_row, new_row) local end_row_old = start_row + old_row local end_row_new = start_row + new_row + if new_row < old_row then - foldinfo:remove_range(end_row_old, end_row_new) + foldinfo:remove_range(end_row_new, end_row_old) elseif new_row > old_row then foldinfo:add_range(start_row, end_row_new) vim.schedule(function() diff --git a/runtime/lua/vim/treesitter/_range.lua b/runtime/lua/vim/treesitter/_range.lua index 02918da23f..f4db5016ac 100644 --- a/runtime/lua/vim/treesitter/_range.lua +++ b/runtime/lua/vim/treesitter/_range.lua @@ -2,8 +2,21 @@ local api = vim.api local M = {} ----@alias Range4 {[1]: integer, [2]: integer, [3]: integer, [4]: integer} ----@alias Range6 {[1]: integer, [2]: integer, [3]: integer, [4]: integer, [5]: integer, [6]: integer} +---@class Range4 +---@field [1] integer start row +---@field [2] integer start column +---@field [3] integer end row +---@field [4] integer end column + +---@class Range6 +---@field [1] integer start row +---@field [2] integer start column +---@field [3] integer start bytes +---@field [4] integer end row +---@field [5] integer end column +---@field [6] integer end bytes + +---@alias Range Range4|Range6 ---@private ---@param a_row integer @@ -74,8 +87,8 @@ function M.validate(r) end ---@private ----@param r1 Range4|Range6 ----@param r2 Range4|Range6 +---@param r1 Range +---@param r2 Range ---@return boolean function M.intercepts(r1, r2) local srow_1, scol_1, erow_1, ecol_1 = M.unpack4(r1) @@ -95,7 +108,7 @@ function M.intercepts(r1, r2) end ---@private ----@param r Range4|Range6 +---@param r Range ---@return integer, integer, integer, integer function M.unpack4(r) local off_1 = #r == 6 and 1 or 0 @@ -110,8 +123,8 @@ function M.unpack6(r) end ---@private ----@param r1 Range4|Range6 ----@param r2 Range4|Range6 +---@param r1 Range +---@param r2 Range ---@return boolean whether r1 contains r2 function M.contains(r1, r2) local srow_1, scol_1, erow_1, ecol_1 = M.unpack4(r1) @@ -132,7 +145,7 @@ end ---@private ---@param source integer|string ----@param range Range4|Range6 +---@param range Range ---@return Range6 function M.add_bytes(source, range) if type(range) == 'table' and #range == 6 then diff --git a/runtime/lua/vim/treesitter/languagetree.lua b/runtime/lua/vim/treesitter/languagetree.lua index 26321cd1f4..bdfe281a5b 100644 --- a/runtime/lua/vim/treesitter/languagetree.lua +++ b/runtime/lua/vim/treesitter/languagetree.lua @@ -448,7 +448,7 @@ end --- nodes, which is useful for templating languages like ERB and EJS. --- ---@private ----@param new_regions Range4[][] List of regions this tree should manage and parse. +---@param new_regions Range6[][] List of regions this tree should manage and parse. function LanguageTree:set_included_regions(new_regions) -- Transform the tables from 4 element long to 6 element long (with byte offset) for _, region in ipairs(new_regions) do @@ -478,24 +478,11 @@ end ---@private ---@param node TSNode ----@param source integer|string ----@param metadata TSMetadata ----@return Range6 -local function get_range_from_metadata(node, source, metadata) - if metadata and metadata.range then - return Range.add_bytes(source, metadata.range --[[@as Range4|Range6]]) - end - return { node:range(true) } -end - ----@private ---- TODO(lewis6991): cleanup of the node_range interface ----@param node TSNode ---@param source string|integer ---@param metadata TSMetadata ---@return Range6[] local function get_node_ranges(node, source, metadata, include_children) - local range = get_range_from_metadata(node, source, metadata) + local range = query.get_range(node, source, metadata) if include_children then return { range } @@ -535,7 +522,7 @@ end ---@param pattern integer ---@param lang string ---@param combined boolean ----@param ranges Range4[] +---@param ranges Range6[] local function add_injection(t, tree_index, pattern, lang, combined, ranges) assert(type(lang) == 'string') @@ -559,30 +546,15 @@ local function add_injection(t, tree_index, pattern, lang, combined, ranges) end ---@private ----Get node text ---- ----Note: `query.get_node_text` returns string|string[]|nil so use this simple alias function ----to annotate it returns string. ---- ----TODO(lewis6991): use [at]overload annotations on `query.get_node_text` ----@param node TSNode ----@param source integer|string ----@param metadata table ----@return string -local function get_node_text(node, source, metadata) - return query.get_node_text(node, source, { metadata = metadata }) --[[@as string]] -end - ----@private --- Extract injections according to: --- https://tree-sitter.github.io/tree-sitter/syntax-highlighting#language-injection ---@param match table<integer,TSNode> ----@param metadata table ----@return string, boolean, Range4[] +---@param metadata TSMetadata +---@return string?, boolean, Range6[] function LanguageTree:_get_injection(match, metadata) - local ranges = {} ---@type Range4[] + local ranges = {} ---@type Range6[] local combined = metadata['injection.combined'] ~= nil - local lang = metadata['injection.language'] ---@type string + local lang = metadata['injection.language'] --[[@as string?]] local include_children = metadata['injection.include-children'] ~= nil for id, node in pairs(match) do @@ -590,7 +562,7 @@ function LanguageTree:_get_injection(match, metadata) -- Lang should override any other language tag if name == 'injection.language' then - lang = get_node_text(node, self._source, metadata[id]) + lang = query.get_node_text(node, self._source, { metadata = metadata[id] }) elseif name == 'injection.content' then ranges = get_node_ranges(node, self._source, metadata[id], include_children) end @@ -601,11 +573,11 @@ end ---@private ---@param match table<integer,TSNode> ----@param metadata table ----@return string, boolean, Range4[] +---@param metadata TSMetadata +---@return string, boolean, Range6[] function LanguageTree:_get_injection_deprecated(match, metadata) local lang = nil ---@type string - local ranges = {} ---@type Range4[] + local ranges = {} ---@type Range6[] local combined = metadata.combined ~= nil -- Directives can configure how injections are captured as well as actual node captures. @@ -623,8 +595,10 @@ function LanguageTree:_get_injection_deprecated(match, metadata) end end - if metadata.language then - lang = metadata.language ---@type string + local mlang = metadata.language + if mlang ~= nil then + assert(type(mlang) == 'string') + lang = mlang end -- You can specify the content and language together @@ -635,11 +609,11 @@ function LanguageTree:_get_injection_deprecated(match, metadata) -- Lang should override any other language tag if name == 'language' and not lang then - lang = get_node_text(node, self._source, metadata[id]) + lang = query.get_node_text(node, self._source, { metadata = metadata[id] }) elseif name == 'combined' then combined = true elseif name == 'content' and #ranges == 0 then - ranges[#ranges + 1] = get_range_from_metadata(node, self._source, metadata[id]) + ranges[#ranges + 1] = query.get_range(node, self._source, metadata[id]) -- Ignore any tags that start with "_" -- Allows for other tags to be used in matches elseif string.sub(name, 1, 1) ~= '_' then @@ -648,7 +622,7 @@ function LanguageTree:_get_injection_deprecated(match, metadata) end if #ranges == 0 then - ranges[#ranges + 1] = get_range_from_metadata(node, self._source, metadata[id]) + ranges[#ranges + 1] = query.get_range(node, self._source, metadata[id]) end end end @@ -926,7 +900,7 @@ end ---@private ---@param tree TSTree ----@param range Range4 +---@param range Range ---@return boolean local function tree_contains(tree, range) return Range.contains({ tree:root():range() }, range) diff --git a/runtime/lua/vim/treesitter/query.lua b/runtime/lua/vim/treesitter/query.lua index e7cf42283d..f4e038b2d8 100644 --- a/runtime/lua/vim/treesitter/query.lua +++ b/runtime/lua/vim/treesitter/query.lua @@ -1,6 +1,8 @@ local a = vim.api local language = require('vim.treesitter.language') +local Range = require('vim.treesitter._range') + ---@class Query ---@field captures string[] List of captures used in query ---@field info TSQueryInfo Contains used queries, predicates, directives @@ -56,35 +58,21 @@ local function add_included_lang(base_langs, lang, ilang) end ---@private ----@param buf (integer) ----@param range (table) ----@param concat (boolean) ----@returns (string[]|string|nil) -local function buf_range_get_text(buf, range, concat) - local lines - local start_row, start_col, end_row, end_col = unpack(range) - local eof_row = a.nvim_buf_line_count(buf) - if start_row >= eof_row then - return nil - end - +---@param buf integer +---@param range Range +---@returns string +local function buf_range_get_text(buf, range) + local start_row, start_col, end_row, end_col = Range.unpack4(range) if end_col == 0 then - lines = a.nvim_buf_get_lines(buf, start_row, end_row, true) - end_col = -1 - else - lines = a.nvim_buf_get_lines(buf, start_row, end_row + 1, true) - end - - if #lines > 0 then - if #lines == 1 then - lines[1] = string.sub(lines[1], start_col + 1, end_col) - else - lines[1] = string.sub(lines[1], start_col + 1) - lines[#lines] = string.sub(lines[#lines], 1, end_col) + if start_row == end_row then + start_col = -1 + start_row = start_row - 1 end + end_col = -1 + end_row = end_row - 1 end - - return concat and table.concat(lines, '\n') or lines + local lines = a.nvim_buf_get_text(buf, start_row, start_col, end_row, end_col, {}) + return table.concat(lines, '\n') end --- Gets the list of files used to make up a query @@ -256,14 +244,28 @@ function M.parse_query(lang, query) local cached = query_cache[lang][query] if cached then return cached - else - local self = setmetatable({}, Query) - self.query = vim._ts_parse_query(lang, query) - self.info = self.query:inspect() - self.captures = self.info.captures - query_cache[lang][query] = self - return self end + + local self = setmetatable({}, Query) + self.query = vim._ts_parse_query(lang, query) + self.info = self.query:inspect() + self.captures = self.info.captures + query_cache[lang][query] = self + return self +end + +---Get the range of a |TSNode|. Can also supply {source} and {metadata} +---to get the range with directives applied. +---@param node TSNode +---@param source integer|string|nil Buffer or string from which the {node} is extracted +---@param metadata TSMetadata|nil +---@return Range6 +function M.get_range(node, source, metadata) + if metadata and metadata.range then + assert(source) + return Range.add_bytes(source, metadata.range) + end + return { node:range(true) } end --- Gets the text corresponding to a given node @@ -271,24 +273,22 @@ end ---@param node TSNode ---@param source (integer|string) Buffer or string from which the {node} is extracted ---@param opts (table|nil) Optional parameters. ---- - concat: (boolean) Concatenate result in a string (default true) --- - metadata (table) Metadata of a specific capture. This would be --- set to `metadata[capture_id]` when using |vim.treesitter.add_directive()|. ----@return (string[]|string|nil) +---@return string function M.get_node_text(node, source, opts) opts = opts or {} - -- TODO(lewis6991): concat only works when source is number. - local concat = vim.F.if_nil(opts.concat, true) local metadata = opts.metadata or {} if metadata.text then return metadata.text elseif type(source) == 'number' then - return metadata.range and buf_range_get_text(source, metadata.range, concat) - or buf_range_get_text(source, { node:range() }, concat) - elseif type(source) == 'string' then - return source:sub(select(3, node:start()) + 1, select(3, node:end_())) + local range = M.get_range(node, source, metadata) + return buf_range_get_text(source, range) end + + ---@cast source string + return source:sub(select(3, node:start()) + 1, select(3, node:end_())) end ---@alias TSMatch table<integer,TSNode> @@ -312,7 +312,7 @@ local predicate_handlers = { str = predicate[3] else -- (#eq? @aa @bb) - str = M.get_node_text(match[predicate[3]], source) --[[@as string]] + str = M.get_node_text(match[predicate[3]], source) end if node_text ~= str or str == nil then @@ -328,7 +328,7 @@ local predicate_handlers = { return true end local regex = predicate[3] - return string.find(M.get_node_text(node, source) --[[@as string]], regex) ~= nil + return string.find(M.get_node_text(node, source), regex) ~= nil end, ['match?'] = (function() @@ -366,7 +366,7 @@ local predicate_handlers = { if not node then return true end - local node_text = M.get_node_text(node, source) --[[@as string]] + local node_text = M.get_node_text(node, source) for i = 3, #predicate do if string.find(node_text, predicate[i], 1, true) then @@ -404,9 +404,9 @@ local predicate_handlers = { predicate_handlers['vim-match?'] = predicate_handlers['match?'] ---@class TSMetadata +---@field range Range ---@field [integer] TSMetadata ---@field [string] integer|string ----@field range Range4 ---@alias TSDirective fun(match: TSMatch, _, _, predicate: (string|integer)[], metadata: TSMetadata) @@ -465,13 +465,20 @@ local directive_handlers = { assert(#pred == 4) local id = pred[2] + assert(type(id) == 'number') + local node = match[id] local text = M.get_node_text(node, bufnr, { metadata = metadata[id] }) or '' if not metadata[id] then metadata[id] = {} end - metadata[id].text = text:gsub(pred[3], pred[4]) + + local pattern, replacement = pred[3], pred[3] + assert(type(pattern) == 'string') + assert(type(replacement) == 'string') + + metadata[id].text = text:gsub(pattern, replacement) end, } diff --git a/runtime/optwin.vim b/runtime/optwin.vim index 200254321e..0d10ac4758 100644 --- a/runtime/optwin.vim +++ b/runtime/optwin.vim @@ -106,11 +106,7 @@ func <SID>Update(lnum, line, local, thiswin) else let name = substitute(a:line, '^ \tset \(no\)\=\([a-z]*\).*', '\2', "") endif - if name == "pt" && &pt =~ "\x80" - let val = <SID>PTvalue() - else - let val = escape(eval('&' . name), " \t\\\"|") - endif + let val = escape(eval('&' . name), " \t\\\"|") if a:local exe a:thiswin . "wincmd w" endif @@ -211,14 +207,6 @@ func <SID>Header(text) let s:lnum = s:lnum + 1 endfunc -" Get the value of 'pastetoggle'. It could be a special key. -func <SID>PTvalue() - redir @a - silent set pt - redir END - return substitute(@a, '[^=]*=\(.*\)', '\1', "") -endfunc - " Restore the previous value of 'cpoptions' here, it's used below. let &cpo = s:cpo_save @@ -232,12 +220,6 @@ call <SID>AddOption("cpoptions", gettext("list of flags to specify Vi compatibil call <SID>OptionG("cpo", &cpo) call <SID>AddOption("paste", gettext("paste mode, insert typed text literally")) call <SID>BinOptionG("paste", &paste) -call <SID>AddOption("pastetoggle", gettext("key sequence to toggle paste mode")) -if &pt =~ "\x80" - call append("$", " \tset pt=" . <SID>PTvalue()) -else - call <SID>OptionG("pt", &pt) -endif call <SID>AddOption("runtimepath", gettext("list of directories used for runtime files and plugins")) call <SID>OptionG("rtp", &rtp) call <SID>AddOption("packpath", gettext("list of directories used for plugin packages")) diff --git a/runtime/plugin/nvim.lua b/runtime/plugin/nvim.lua index 762e9519db..e4b099f7ad 100644 --- a/runtime/plugin/nvim.lua +++ b/runtime/plugin/nvim.lua @@ -1,6 +1,6 @@ vim.api.nvim_create_user_command('Inspect', function(cmd) if cmd.bang then - vim.pretty_print(vim.inspect_pos()) + vim.print(vim.inspect_pos()) else vim.show_pos() end diff --git a/scripts/lua2dox.lua b/scripts/lua2dox.lua index b99cd955f4..de9f2926f2 100644 --- a/scripts/lua2dox.lua +++ b/scripts/lua2dox.lua @@ -302,7 +302,7 @@ local types = { 'integer', 'number', 'string', 'table', 'list', 'boolean', 'func local tagged_types = { 'TSNode', 'LanguageTree' } -- Document these as 'table' -local alias_types = { 'Range4', 'Range6' } +local alias_types = { 'Range', 'Range4', 'Range6', 'TSMetadata' } -- Processes the file and writes filtered output to stdout. function TLua2DoX_filter.filter(this, AppStamp, Filename) diff --git a/src/nvim/api/command.c b/src/nvim/api/command.c index 32378ed244..de766c14b9 100644 --- a/src/nvim/api/command.c +++ b/src/nvim/api/command.c @@ -938,10 +938,11 @@ static void build_cmdline_str(char **cmdlinep, exarg_T *eap, CmdParseInfo *cmdin /// - force: (boolean, default true) Override any previous definition. /// - preview: (function) Preview callback for 'inccommand' |:command-preview| /// @param[out] err Error details, if any. -void nvim_create_user_command(String name, Object command, Dict(user_command) *opts, Error *err) +void nvim_create_user_command(uint64_t channel_id, String name, Object command, + Dict(user_command) *opts, Error *err) FUNC_API_SINCE(9) { - create_user_command(name, command, opts, 0, err); + create_user_command(channel_id, name, command, opts, 0, err); } /// Delete a user-defined command. @@ -959,7 +960,7 @@ void nvim_del_user_command(String name, Error *err) /// @param buffer Buffer handle, or 0 for current buffer. /// @param[out] err Error details, if any. /// @see nvim_create_user_command -void nvim_buf_create_user_command(Buffer buffer, String name, Object command, +void nvim_buf_create_user_command(uint64_t channel_id, Buffer buffer, String name, Object command, Dict(user_command) *opts, Error *err) FUNC_API_SINCE(9) { @@ -970,7 +971,7 @@ void nvim_buf_create_user_command(Buffer buffer, String name, Object command, buf_T *save_curbuf = curbuf; curbuf = target_buf; - create_user_command(name, command, opts, UC_BUFFER, err); + create_user_command(channel_id, name, command, opts, UC_BUFFER, err); curbuf = save_curbuf; } @@ -1011,8 +1012,8 @@ void nvim_buf_del_user_command(Buffer buffer, String name, Error *err) api_set_error(err, kErrorTypeException, "Invalid command (not found): %s", name.data); } -void create_user_command(String name, Object command, Dict(user_command) *opts, int flags, - Error *err) +void create_user_command(uint64_t channel_id, String name, Object command, Dict(user_command) *opts, + int flags, Error *err) { uint32_t argt = 0; int64_t def = -1; @@ -1205,11 +1206,13 @@ void create_user_command(String name, Object command, Dict(user_command) *opts, }); } - if (uc_add_command(name.data, name.size, rep, argt, def, flags, compl, compl_arg, compl_luaref, - preview_luaref, addr_type_arg, luaref, force) != OK) { - api_set_error(err, kErrorTypeException, "Failed to create user command"); - // Do not goto err, since uc_add_command now owns luaref, compl_luaref, and compl_arg - } + WITH_SCRIPT_CONTEXT(channel_id, { + if (uc_add_command(name.data, name.size, rep, argt, def, flags, compl, compl_arg, compl_luaref, + preview_luaref, addr_type_arg, luaref, force) != OK) { + api_set_error(err, kErrorTypeException, "Failed to create user command"); + // Do not goto err, since uc_add_command now owns luaref, compl_luaref, and compl_arg + } + }); return; diff --git a/src/nvim/api/options.c b/src/nvim/api/options.c index ddaed3a254..2d9ffcba06 100644 --- a/src/nvim/api/options.c +++ b/src/nvim/api/options.c @@ -157,7 +157,8 @@ Object nvim_get_option_value(String name, Dict(option) *opts, Error *err) /// - win: |window-ID|. Used for setting window local option. /// - buf: Buffer number. Used for setting buffer local option. /// @param[out] err Error details, if any -void nvim_set_option_value(String name, Object value, Dict(option) *opts, Error *err) +void nvim_set_option_value(uint64_t channel_id, String name, Object value, Dict(option) *opts, + Error *err) FUNC_API_SINCE(9) { int scope = 0; @@ -202,7 +203,9 @@ void nvim_set_option_value(String name, Object value, Dict(option) *opts, Error }); } - access_option_value_for(name.data, &numval, &stringval, scope, opt_type, to, false, err); + WITH_SCRIPT_CONTEXT(channel_id, { + access_option_value_for(name.data, &numval, &stringval, scope, opt_type, to, false, err); + }); } /// Gets the option information for all options. diff --git a/src/nvim/api/ui_events.in.h b/src/nvim/api/ui_events.in.h index a08e8dbfeb..b93f521ca3 100644 --- a/src/nvim/api/ui_events.in.h +++ b/src/nvim/api/ui_events.in.h @@ -114,7 +114,7 @@ void msg_set_pos(Integer grid, Integer row, Boolean scrolled, String sep_char) FUNC_API_SINCE(6) FUNC_API_COMPOSITOR_IMPL FUNC_API_CLIENT_IGNORE; void win_viewport(Integer grid, Window win, Integer topline, Integer botline, Integer curline, - Integer curcol, Integer line_count) + Integer curcol, Integer line_count, Integer scroll_delta) FUNC_API_SINCE(7) FUNC_API_CLIENT_IGNORE; void win_extmark(Integer grid, Window win, Integer ns_id, Integer mark_id, Integer row, Integer col) diff --git a/src/nvim/api/vim.c b/src/nvim/api/vim.c index 0f27040fd3..315ccd13e6 100644 --- a/src/nvim/api/vim.c +++ b/src/nvim/api/vim.c @@ -579,7 +579,7 @@ ArrayOf(String) nvim__get_runtime(Array pat, Boolean all, Dict(runtime) *opts, E if (source) { for (size_t i = 0; i < res.size; i++) { String name = res.items[i].data.string; - (void)do_source(name.data, false, DOSO_NONE); + (void)do_source(name.data, false, DOSO_NONE, NULL); } } diff --git a/src/nvim/buffer_defs.h b/src/nvim/buffer_defs.h index 6122136a75..4bdf5aac64 100644 --- a/src/nvim/buffer_defs.h +++ b/src/nvim/buffer_defs.h @@ -1222,6 +1222,7 @@ struct window_S { colnr_T w_valid_leftcol; // last known w_leftcol bool w_viewport_invalid; + linenr_T w_viewport_last_topline; // topline when the viewport was last updated // w_cline_height is the number of physical lines taken by the buffer line // that the cursor is on. We use this to avoid extra calls to plines_win(). diff --git a/src/nvim/diff.c b/src/nvim/diff.c index 289939b2ca..52c5732f23 100644 --- a/src/nvim/diff.c +++ b/src/nvim/diff.c @@ -3136,7 +3136,7 @@ static void diffgetput(const int addr_count, const int idx_cur, const int idx_fr if (added != 0) { // Adjust marks. This will change the following entries! - mark_adjust(lnum, lnum + count - 1, (long)MAXLNUM, added, kExtmarkUndo); + mark_adjust(lnum, lnum + count - 1, (long)MAXLNUM, added, kExtmarkNOOP); if (curwin->w_cursor.lnum >= lnum) { // Adjust the cursor position if it's in/after the changed // lines. diff --git a/src/nvim/drawscreen.c b/src/nvim/drawscreen.c index 384dbf82f9..d8c9da870a 100644 --- a/src/nvim/drawscreen.c +++ b/src/nvim/drawscreen.c @@ -728,19 +728,15 @@ static void win_redr_border(win_T *wp) /// Show current cursor info in ruler and various other places /// /// @param always if false, only show ruler if position has changed. -void show_cursor_info(bool always) +void show_cursor_info_later(bool force) { - if (!always && !redrawing()) { - return; - } - int state = get_real_state(); int empty_line = (State & MODE_INSERT) == 0 && *ml_get_buf(curwin->w_buffer, curwin->w_cursor.lnum, false) == NUL; // Only draw when something changed. validate_virtcol_win(curwin); - if (always + if (force || curwin->w_cursor.lnum != curwin->w_stl_cursor.lnum || curwin->w_cursor.col != curwin->w_stl_cursor.col || curwin->w_virtcol != curwin->w_stl_virtcol @@ -750,27 +746,19 @@ void show_cursor_info(bool always) || curwin->w_topfill != curwin->w_stl_topfill || empty_line != curwin->w_stl_empty || state != curwin->w_stl_state) { - win_check_ns_hl(curwin); - if ((*p_stl != NUL || *curwin->w_p_stl != NUL) - && (curwin->w_status_height || global_stl_height())) { - redraw_custom_statusline(curwin); + if ((curwin->w_status_height || global_stl_height())) { + curwin->w_redr_status = true; } else { - win_redr_ruler(curwin); + redraw_cmdline = true; } + if (*p_wbr != NUL || *curwin->w_p_wbr != NUL) { - win_redr_winbar(curwin); + curwin->w_redr_status = true; } - if (need_maketitle - || (p_icon && (stl_syntax & STL_IN_ICON)) + if ((p_icon && (stl_syntax & STL_IN_ICON)) || (p_title && (stl_syntax & STL_IN_TITLE))) { - maketitle(); - } - - win_check_ns_hl(NULL); - // Redraw the tab pages line if needed. - if (redraw_tabline) { - draw_tabline(); + need_maketitle = true; } } @@ -2136,7 +2124,7 @@ void status_redraw_all(void) bool is_stl_global = global_stl_height() != 0; FOR_ALL_WINDOWS_IN_TAB(wp, curtab) { - if ((!is_stl_global && wp->w_status_height) || (is_stl_global && wp == curwin) + if ((!is_stl_global && wp->w_status_height) || wp == curwin || wp->w_winbar_height) { wp->w_redr_status = true; redraw_later(wp, UPD_VALID); diff --git a/src/nvim/edit.c b/src/nvim/edit.c index 9eb4802d97..48ba93e666 100644 --- a/src/nvim/edit.c +++ b/src/nvim/edit.c @@ -1350,12 +1350,15 @@ void ins_redraw(bool ready) } pum_check_clear(); + show_cursor_info_later(false); if (must_redraw) { update_screen(); - } else if (clear_cmdline || redraw_cmdline) { - showmode(); // clear cmdline and show mode + } else { + redraw_statuslines(); + if (clear_cmdline || redraw_cmdline || redraw_mode) { + showmode(); // clear cmdline and show mode + } } - show_cursor_info(false); setcursor(); emsg_on_display = false; // may remove error message now } @@ -1510,14 +1513,14 @@ bool prompt_curpos_editable(void) // Undo the previous edit_putchar(). void edit_unputchar(void) { - if (pc_status != PC_STATUS_UNSET && pc_row >= msg_scrolled) { + if (pc_status != PC_STATUS_UNSET) { if (pc_status == PC_STATUS_RIGHT) { curwin->w_wcol++; } if (pc_status == PC_STATUS_RIGHT || pc_status == PC_STATUS_LEFT) { redrawWinline(curwin, curwin->w_cursor.lnum); } else { - grid_puts(&curwin->w_grid, pc_bytes, pc_row - msg_scrolled, pc_col, pc_attr); + grid_puts(&curwin->w_grid, pc_bytes, pc_row, pc_col, pc_attr); } } } diff --git a/src/nvim/eval.c b/src/nvim/eval.c index 384e088bcf..14f2379504 100644 --- a/src/nvim/eval.c +++ b/src/nvim/eval.c @@ -6951,14 +6951,12 @@ int handle_subscript(const char **const arg, typval_T *rettv, int evaluate, int tv_dict_unref(selfdict); selfdict = NULL; } else if (**arg == '-') { - if (ret == OK) { - if ((*arg)[2] == '{') { - // expr->{lambda}() - ret = eval_lambda((char **)arg, rettv, evaluate, verbose); - } else { - // expr->name() - ret = eval_method((char **)arg, rettv, evaluate, verbose); - } + if ((*arg)[2] == '{') { + // expr->{lambda}() + ret = eval_lambda((char **)arg, rettv, evaluate, verbose); + } else { + // expr->name() + ret = eval_method((char **)arg, rettv, evaluate, verbose); } } else { // **arg == '[' || **arg == '.' tv_dict_unref(selfdict); diff --git a/src/nvim/ex_cmds.c b/src/nvim/ex_cmds.c index a12c2a15b4..d398d3e06e 100644 --- a/src/nvim/ex_cmds.c +++ b/src/nvim/ex_cmds.c @@ -3747,6 +3747,7 @@ static int do_sub(exarg_T *eap, proftime_T timeout, long cmdpreview_ns, handle_T update_topline(curwin); validate_cursor(); redraw_later(curwin, UPD_SOME_VALID); + show_cursor_info_later(true); update_screen(); highlight_match = false; redraw_later(curwin, UPD_SOME_VALID); @@ -3765,7 +3766,6 @@ static int do_sub(exarg_T *eap, proftime_T timeout, long cmdpreview_ns, handle_T _("replace with %s (y/n/a/q/l/^E/^Y)?"), sub); msg_no_more = false; msg_scroll = (int)i; - show_cursor_info(true); if (!ui_has(kUIMessages)) { ui_cursor_goto(msg_row, msg_col); } diff --git a/src/nvim/ex_docmd.c b/src/nvim/ex_docmd.c index f460b4b93f..49f6d24c89 100644 --- a/src/nvim/ex_docmd.c +++ b/src/nvim/ex_docmd.c @@ -5666,10 +5666,7 @@ static void ex_equal(exarg_T *eap) static void ex_sleep(exarg_T *eap) { if (cursor_valid()) { - int n = curwin->w_winrow + curwin->w_wrow - msg_scrolled; - if (n >= 0) { - ui_cursor_goto(n, curwin->w_wincol + curwin->w_wcol); - } + setcursor_mayforce(true); } long len = eap->line2; diff --git a/src/nvim/ex_session.c b/src/nvim/ex_session.c index 8e3e68d9b7..855a5f7538 100644 --- a/src/nvim/ex_session.c +++ b/src/nvim/ex_session.c @@ -909,7 +909,7 @@ void ex_loadview(exarg_T *eap) return; } - if (do_source(fname, false, DOSO_NONE) == FAIL) { + if (do_source(fname, false, DOSO_NONE, NULL) == FAIL) { semsg(_(e_notopen), fname); } xfree(fname); diff --git a/src/nvim/getchar.c b/src/nvim/getchar.c index ea541dbca4..605705e0e3 100644 --- a/src/nvim/getchar.c +++ b/src/nvim/getchar.c @@ -2073,39 +2073,6 @@ static int handle_mapping(int *keylenp, const bool *timedout, int *mapdepth) } } - // Check for match with 'pastetoggle' - if (*p_pt != NUL && mp == NULL && (State & (MODE_INSERT | MODE_NORMAL))) { - bool match = typebuf_match_len((uint8_t *)p_pt, &mlen); - if (match) { - // write chars to script file(s) - if (mlen > typebuf.tb_maplen) { - gotchars(typebuf.tb_buf + typebuf.tb_off + typebuf.tb_maplen, - (size_t)(mlen - typebuf.tb_maplen)); - } - - del_typebuf(mlen, 0); // remove the chars - set_option_value_give_err("paste", !p_paste, NULL, 0); - if (!(State & MODE_INSERT)) { - msg_col = 0; - msg_row = Rows - 1; - msg_clr_eos(); // clear ruler - } - status_redraw_all(); - redraw_statuslines(); - showmode(); - setcursor(); - *keylenp = keylen; - return map_result_retry; - } - // Need more chars for partly match. - if (mlen == typebuf.tb_len) { - keylen = KEYLEN_PART_KEY; - } else if (max_mlen < mlen) { - // no match, may have to check for termcode at next character - max_mlen = mlen + 1; - } - } - if ((mp == NULL || max_mlen > mp_match_len) && keylen != KEYLEN_PART_MAP) { // When no matching mapping found or found a non-matching mapping that // matches at least what the matching mapping matched: @@ -2116,13 +2083,6 @@ static int handle_mapping(int *keylenp, const bool *timedout, int *mapdepth) || (typebuf.tb_buf[typebuf.tb_off + 1] == KS_MODIFIER && typebuf.tb_len < 4))) { // Incomplete modifier sequence: cannot decide whether to simplify yet. keylen = KEYLEN_PART_KEY; - } else if (keylen == KEYLEN_PART_KEY && !*timedout) { - // If 'pastetoggle' matched partially, don't simplify. - // When the last characters were not typed, don't wait for a typed character to - // complete 'pastetoggle'. - if (typebuf.tb_len == typebuf.tb_maplen) { - keylen = 0; - } } else { // Try to include the modifier into the key. keylen = check_simplify_modifier(max_mlen + 1); @@ -2923,18 +2883,6 @@ int fix_input_buffer(uint8_t *buf, int len) return len; } -static bool typebuf_match_len(const uint8_t *str, int *mlen) -{ - int i; - for (i = 0; i < typebuf.tb_len && str[i]; i++) { - if (str[i] != typebuf.tb_buf[typebuf.tb_off + i]) { - break; - } - } - *mlen = i; - return str[i] == NUL; // matched the whole string -} - /// Get command argument for <Cmd> key char *getcmdkeycmd(int promptc, void *cookie, int indent, bool do_concat) { diff --git a/src/nvim/grid.c b/src/nvim/grid.c index efbeac4f3f..cd70e98047 100644 --- a/src/nvim/grid.c +++ b/src/nvim/grid.c @@ -549,9 +549,9 @@ void grid_put_linebuf(ScreenGrid *grid, int row, int coloff, int endcol, int cle } if (bg_attr) { + assert(off_from == (size_t)col); for (int c = col; c < endcol; c++) { - linebuf_attr[off_from + (size_t)c] = - hl_combine_attr(bg_attr, linebuf_attr[off_from + (size_t)c]); + linebuf_attr[c] = hl_combine_attr(bg_attr, linebuf_attr[c]); } } diff --git a/src/nvim/lua/executor.c b/src/nvim/lua/executor.c index 078bc4fea9..819e3cccff 100644 --- a/src/nvim/lua/executor.c +++ b/src/nvim/lua/executor.c @@ -1623,12 +1623,12 @@ void ex_lua(exarg_T *const eap) } // When =expr is used transform it to print(vim.inspect(expr)) if (code[0] == '=') { - len += sizeof("vim.pretty_print()") - sizeof("="); + len += sizeof("vim.print()") - sizeof("="); // code_buf needs to be 1 char larger then len for null byte in the end. // lua nlua_typval_exec doesn't expect null terminated string so len // needs to end before null byte. char *code_buf = xmallocz(len); - vim_snprintf(code_buf, len + 1, "vim.pretty_print(%s)", code + 1); + vim_snprintf(code_buf, len + 1, "vim.print(%s)", code + 1); xfree(code); code = code_buf; } @@ -2061,10 +2061,15 @@ void nlua_set_sctx(sctx_T *current) break; } char *source_path = fix_fname(info->source + 1); - get_current_script_id(&source_path, current); - xfree(source_path); - current->sc_lnum = info->currentline; + int sid = find_script_by_name(source_path); + if (sid > 0) { + xfree(source_path); + } else { + new_script_item(source_path, &sid); + } + current->sc_sid = sid; current->sc_seq = -1; + current->sc_lnum = info->currentline; cleanup: xfree(info); diff --git a/src/nvim/main.c b/src/nvim/main.c index be1714b207..ea5f511fc6 100644 --- a/src/nvim/main.c +++ b/src/nvim/main.c @@ -1937,7 +1937,7 @@ static void do_system_initialization(void) dir_len += 1; } memcpy(vimrc + dir_len, path_tail, sizeof(path_tail)); - if (do_source(vimrc, false, DOSO_NONE) != FAIL) { + if (do_source(vimrc, false, DOSO_NONE, NULL) != FAIL) { xfree(vimrc); xfree(config_dirs); return; @@ -1949,7 +1949,7 @@ static void do_system_initialization(void) #ifdef SYS_VIMRC_FILE // Get system wide defaults, if the file name is defined. - (void)do_source(SYS_VIMRC_FILE, false, DOSO_NONE); + (void)do_source(SYS_VIMRC_FILE, false, DOSO_NONE, NULL); #endif } @@ -1978,7 +1978,7 @@ static bool do_user_initialization(void) // init.lua if (os_path_exists(init_lua_path) - && do_source(init_lua_path, true, DOSO_VIMRC)) { + && do_source(init_lua_path, true, DOSO_VIMRC, NULL)) { if (os_path_exists(user_vimrc)) { semsg(_("E5422: Conflicting configs: \"%s\" \"%s\""), init_lua_path, user_vimrc); @@ -1992,7 +1992,7 @@ static bool do_user_initialization(void) xfree(init_lua_path); // init.vim - if (do_source(user_vimrc, true, DOSO_VIMRC) != FAIL) { + if (do_source(user_vimrc, true, DOSO_VIMRC, NULL) != FAIL) { do_exrc = p_exrc; if (do_exrc) { do_exrc = (path_full_compare(VIMRC_FILE, user_vimrc, false, true) != kEqualFiles); @@ -2018,7 +2018,7 @@ static bool do_user_initialization(void) memmove(vimrc, dir, dir_len); vimrc[dir_len] = PATHSEP; memmove(vimrc + dir_len + 1, path_tail, sizeof(path_tail)); - if (do_source(vimrc, true, DOSO_VIMRC) != FAIL) { + if (do_source(vimrc, true, DOSO_VIMRC, NULL) != FAIL) { do_exrc = p_exrc; if (do_exrc) { do_exrc = (path_full_compare(VIMRC_FILE, vimrc, false, true) != kEqualFiles); @@ -2084,7 +2084,7 @@ static void source_startup_scripts(const mparm_T *const parmp) || strequal(parmp->use_vimrc, "NORC")) { // Do nothing. } else { - if (do_source(parmp->use_vimrc, false, DOSO_NONE) != OK) { + if (do_source(parmp->use_vimrc, false, DOSO_NONE, NULL) != OK) { semsg(_("E282: Cannot read from \"%s\""), parmp->use_vimrc); } } diff --git a/src/nvim/move.c b/src/nvim/move.c index 8fda73cbec..6d55955927 100644 --- a/src/nvim/move.c +++ b/src/nvim/move.c @@ -512,8 +512,7 @@ void approximate_botline_win(win_T *wp) int cursor_valid(void) { check_cursor_moved(curwin); - return (curwin->w_valid & (VALID_WROW|VALID_WCOL)) == - (VALID_WROW|VALID_WCOL); + return (curwin->w_valid & (VALID_WROW|VALID_WCOL)) == (VALID_WROW|VALID_WCOL); } // Validate cursor position. Makes sure w_wrow and w_wcol are valid. diff --git a/src/nvim/normal.c b/src/nvim/normal.c index 890215e754..2a8fbbb962 100644 --- a/src/nvim/normal.c +++ b/src/nvim/normal.c @@ -1306,16 +1306,20 @@ static void normal_redraw(NormalState *s) update_topline(curwin); validate_cursor(); + show_cursor_info_later(false); + if (VIsual_active) { redraw_curbuf_later(UPD_INVERTED); // update inverted part - update_screen(); - } else if (must_redraw) { - update_screen(); - } else if (redraw_cmdline || clear_cmdline || redraw_mode) { - showmode(); } - redraw_statuslines(); + if (must_redraw) { + update_screen(); + } else { + redraw_statuslines(); + if (redraw_cmdline || clear_cmdline || redraw_mode) { + showmode(); + } + } if (need_maketitle) { maketitle(); @@ -1348,7 +1352,6 @@ static void normal_redraw(NormalState *s) did_emsg = false; msg_didany = false; // reset lines_left in msg_start() may_clear_sb_text(); // clear scroll-back text on next msg - show_cursor_info(false); setcursor(); } diff --git a/src/nvim/option.c b/src/nvim/option.c index 4e0fbc20f8..f9b7aa9f99 100644 --- a/src/nvim/option.c +++ b/src/nvim/option.c @@ -2255,9 +2255,6 @@ static char *set_bool_option(const int opt_idx, char *const varp, const int valu if ((int *)varp == &p_ru || (int *)varp == &p_sc) { // in case 'ruler' or 'showcmd' changed comp_col(); - if ((int *)varp == &p_ru) { - win_redr_ruler(curwin); - } } if (curwin->w_curswant != MAXCOL && (options[opt_idx].flags & (P_CURSWANT | P_RALL)) != 0) { @@ -2921,11 +2918,7 @@ getoption_T get_option_value(const char *name, long *numval, char **stringval, u return gov_hidden_string; } if (stringval != NULL) { - if ((char **)varp == &p_pt) { // 'pastetoggle' - *stringval = str2special_save(*(char **)(varp), false, false); - } else { - *stringval = xstrdup(*(char **)(varp)); - } + *stringval = xstrdup(*(char **)(varp)); } return gov_string; } @@ -3535,17 +3528,7 @@ static int put_setstring(FILE *fd, char *cmd, char *name, char **valuep, uint64_ char_u *part = NULL; if (*valuep != NULL) { - // Output 'pastetoggle' as key names. For other - // options some characters have to be escaped with - // CTRL-V or backslash - if (valuep == &p_pt) { - char_u *s = (char_u *)(*valuep); - while (*s != NUL) { - if (put_escstr(fd, (char *)str2special((const char **)&s, false, false), 2) == FAIL) { - return FAIL; - } - } - } else if ((flags & P_EXPAND) != 0) { + if ((flags & P_EXPAND) != 0) { size_t size = (size_t)strlen(*valuep) + 1; // replace home directory in the whole option value into "buf" @@ -4993,9 +4976,6 @@ static void option_value2string(vimoption_T *opp, int scope) NameBuff[0] = NUL; } else if (opp->flags & P_EXPAND) { home_replace(NULL, varp, NameBuff, MAXPATHL, false); - // Translate 'pastetoggle' into special key names. - } else if ((char **)opp->var == &p_pt) { - str2specialbuf((const char *)p_pt, NameBuff, MAXPATHL); } else { xstrlcpy(NameBuff, varp, MAXPATHL); } diff --git a/src/nvim/option_defs.h b/src/nvim/option_defs.h index 470eae2090..de289fe54e 100644 --- a/src/nvim/option_defs.h +++ b/src/nvim/option_defs.h @@ -613,7 +613,6 @@ EXTERN char *p_nf; ///< 'nrformats' EXTERN char *p_opfunc; // 'operatorfunc' EXTERN char *p_para; // 'paragraphs' EXTERN int p_paste; // 'paste' -EXTERN char *p_pt; // 'pastetoggle' EXTERN char *p_pex; // 'patchexpr' EXTERN char *p_pm; // 'patchmode' EXTERN char *p_path; // 'path' diff --git a/src/nvim/options.lua b/src/nvim/options.lua index a4ee114f39..bb673a2c58 100644 --- a/src/nvim/options.lua +++ b/src/nvim/options.lua @@ -1685,9 +1685,8 @@ return { }, { full_name='pastetoggle', abbreviation='pt', - short_desc=N_("key code that causes 'paste' to toggle"), + short_desc=N_("No description"), type='string', scope={'global'}, - varname='p_pt', defaults={if_true=""} }, { diff --git a/src/nvim/optionstr.c b/src/nvim/optionstr.c index 0774baf2d8..cba95377a2 100644 --- a/src/nvim/optionstr.c +++ b/src/nvim/optionstr.c @@ -1221,7 +1221,6 @@ static void did_set_statusline(win_T *win, char **varp, char **gvarp, char **err } if (varp == &p_ruf && *errmsg == NULL) { comp_col(); - win_redr_ruler(curwin); } // add / remove window bars for 'winbar' if (gvarp == &p_wbr) { @@ -1307,22 +1306,6 @@ static void did_set_foldcolumn(char **varp, char **errmsg) } } -static void did_set_pastetoggle(void) -{ - // 'pastetoggle': translate key codes like in a mapping - if (*p_pt) { - char *p = NULL; - (void)replace_termcodes(p_pt, - strlen(p_pt), - &p, REPTERM_FROM_PART | REPTERM_DO_LT, NULL, - CPO_TO_CPO_FLAGS); - if (p != NULL) { - free_string_option(p_pt); - p_pt = p; - } - } -} - static void did_set_backspace(char **errmsg) { if (ascii_isdigit(*p_bs)) { @@ -1779,8 +1762,6 @@ static char *did_set_string_option_for(buf_T *buf, win_T *win, int opt_idx, char did_set_opt_strings(*varp, p_sloc_values, false, &errmsg); } else if (gvarp == &win->w_allbuf_opt.wo_fdc) { // 'foldcolumn' did_set_foldcolumn(varp, &errmsg); - } else if (varp == &p_pt) { // 'pastetoggle' - did_set_pastetoggle(); } else if (varp == &p_bs) { // 'backspace' did_set_backspace(&errmsg); } else if (varp == &p_bo) { diff --git a/src/nvim/runtime.c b/src/nvim/runtime.c index c316b61082..c9667d58ed 100644 --- a/src/nvim/runtime.c +++ b/src/nvim/runtime.c @@ -78,6 +78,8 @@ garray_T script_items = { 0, 0, sizeof(scriptitem_T *), 20, NULL }; /// The names of packages that once were loaded are remembered. static garray_T ga_loaded = { 0, 0, sizeof(char *), 4, NULL }; +static int last_current_SID_seq = 0; + /// Initialize the execution stack. void estack_init(void) { @@ -266,7 +268,7 @@ void set_context_in_runtime_cmd(expand_T *xp, const char *arg) static void source_callback(char *fname, void *cookie) { - (void)do_source(fname, false, DOSO_NONE); + (void)do_source(fname, false, DOSO_NONE, cookie); } /// Find the file "name" in all directories in "path" and invoke @@ -855,7 +857,7 @@ static void source_all_matches(char *pat) } for (int i = 0; i < num_files; i++) { - (void)do_source(files[i], false, DOSO_NONE); + (void)do_source(files[i], false, DOSO_NONE, NULL); } FreeWild(num_files, files); } @@ -1701,7 +1703,7 @@ static void cmd_source(char *fname, exarg_T *eap) || eap->cstack->cs_idx >= 0); // ":source" read ex commands - } else if (do_source(fname, false, DOSO_NONE) == FAIL) { + } else if (do_source(fname, false, DOSO_NONE, NULL) == FAIL) { semsg(_(e_notopen), fname); } } @@ -1954,9 +1956,12 @@ int do_source_str(const char *cmd, const char *traceback_name) /// @param fname /// @param check_other check for .vimrc and _vimrc /// @param is_vimrc DOSO_ value +/// @param ret_sid if not NULL and we loaded the script before, don't load it again /// /// @return FAIL if file could not be opened, OK otherwise -int do_source(char *fname, int check_other, int is_vimrc) +/// +/// If a scriptitem_T was found or created "*ret_sid" is set to the SID. +int do_source(char *fname, int check_other, int is_vimrc, int *ret_sid) { struct source_cookie cookie; char *p; @@ -1982,6 +1987,15 @@ int do_source(char *fname, int check_other, int is_vimrc) goto theend; } + // See if we loaded this script before. + int sid = find_script_by_name(fname_exp); + if (sid > 0 && ret_sid != NULL) { + // Already loaded and no need to load again, return here. + *ret_sid = sid; + retval = OK; + goto theend; + } + // Apply SourceCmd autocommands, they should get the file and source it. if (has_autocmd(EVENT_SOURCECMD, fname_exp, NULL) && apply_autocmds(EVENT_SOURCECMD, fname_exp, fname_exp, @@ -2080,7 +2094,24 @@ int do_source(char *fname, int check_other, int is_vimrc) save_funccal(&funccalp_entry); const sctx_T save_current_sctx = current_sctx; - si = get_current_script_id(&fname_exp, ¤t_sctx); + + current_sctx.sc_lnum = 0; + + // Always use a new sequence number. + current_sctx.sc_seq = ++last_current_SID_seq; + + if (sid > 0) { + // loading the same script again + si = SCRIPT_ITEM(sid); + } else { + // It's new, generate a new SID. + si = new_script_item(fname_exp, &sid); + fname_exp = xstrdup(si->sn_name); // used for autocmd + if (ret_sid != NULL) { + *ret_sid = sid; + } + } + current_sctx.sc_sid = sid; // Keep the sourcing name/lnum, for recursive calls. estack_push(ETYPE_SCRIPT, si->sn_name, 0); @@ -2192,7 +2223,7 @@ theend: /// Find an already loaded script "name". /// If found returns its script ID. If not found returns -1. -static int find_script_by_name(char *name) +int find_script_by_name(char *name) { assert(script_items.ga_len >= 0); for (int sid = script_items.ga_len; sid > 0; sid--) { @@ -2209,35 +2240,6 @@ static int find_script_by_name(char *name) return -1; } -/// Check if fname was sourced before to finds its SID. -/// If it's new, generate a new SID. -/// -/// @param[in,out] fnamep pointer to file path of script -/// @param[out] ret_sctx sctx of this script -scriptitem_T *get_current_script_id(char **fnamep, sctx_T *ret_sctx) -{ - static int last_current_SID_seq = 0; - - scriptitem_T *si; - int sid = find_script_by_name(*fnamep); - if (sid > 0) { - si = SCRIPT_ITEM(sid); - } else { - si = new_script_item(*fnamep, &sid); - *fnamep = xstrdup(si->sn_name); - } - - sctx_T script_sctx = { .sc_seq = ++last_current_SID_seq, - .sc_lnum = 0, - .sc_sid = sid }; - - if (ret_sctx != NULL) { - *ret_sctx = script_sctx; - } - - return si; -} - /// ":scriptnames" void ex_scriptnames(exarg_T *eap) { @@ -2704,7 +2706,9 @@ bool script_autoload(const char *const name, const size_t name_len, const bool r } // Try loading the package from $VIMRUNTIME/autoload/<name>.vim - if (source_runtime(scriptname, 0) == OK) { + // Use "ret_sid" to avoid loading the same script again. + int ret_sid; + if (do_in_runtimepath(scriptname, 0, source_callback, &ret_sid) == OK) { ret = true; } } diff --git a/src/nvim/screen.c b/src/nvim/screen.c index 43c7866180..8b0f8b58a7 100644 --- a/src/nvim/screen.c +++ b/src/nvim/screen.c @@ -111,14 +111,14 @@ static int win_fill_end(win_T *wp, int c1, int c2, int off, int width, int row, int attr) { int nn = off + width; + const int endcol = wp->w_grid.cols; - if (nn > wp->w_grid.cols) { - nn = wp->w_grid.cols; + if (nn > endcol) { + nn = endcol; } if (wp->w_p_rl) { - grid_fill(&wp->w_grid, row, endrow, W_ENDCOL(wp) - nn, W_ENDCOL(wp) - off, - c1, c2, attr); + grid_fill(&wp->w_grid, row, endrow, endcol - nn, endcol - off, c1, c2, attr); } else { grid_fill(&wp->w_grid, row, endrow, off, nn, c1, c2, attr); } @@ -156,13 +156,12 @@ void win_draw_end(win_T *wp, int c1, int c2, bool draw_margin, int row, int endr int attr = hl_combine_attr(win_bg_attr(wp), win_hl_attr(wp, (int)hl)); + const int endcol = wp->w_grid.cols; if (wp->w_p_rl) { - grid_fill(&wp->w_grid, row, endrow, wp->w_wincol, W_ENDCOL(wp) - 1 - n, - c2, c2, attr); - grid_fill(&wp->w_grid, row, endrow, W_ENDCOL(wp) - 1 - n, W_ENDCOL(wp) - n, - c1, c2, attr); + grid_fill(&wp->w_grid, row, endrow, 0, endcol - 1 - n, c2, c2, attr); + grid_fill(&wp->w_grid, row, endrow, endcol - 1 - n, endcol - n, c1, c2, attr); } else { - grid_fill(&wp->w_grid, row, endrow, n, wp->w_grid.cols, c1, c2, attr); + grid_fill(&wp->w_grid, row, endrow, n, endcol, c1, c2, attr); } } diff --git a/src/nvim/search.c b/src/nvim/search.c index e5a456161f..782f60f11f 100644 --- a/src/nvim/search.c +++ b/src/nvim/search.c @@ -2340,7 +2340,6 @@ void showmatch(int c) dollar_vcol = -1; } curwin->w_virtcol++; // do display ')' just before "$" - update_screen(); // show the new char first colnr_T save_dollar_vcol = dollar_vcol; int save_state = State; @@ -2349,7 +2348,8 @@ void showmatch(int c) curwin->w_cursor = mpos; // move to matching char *so = 0; // don't use 'scrolloff' here *siso = 0; // don't use 'sidescrolloff' here - show_cursor_info(false); + show_cursor_info_later(false); + update_screen(); // show the new char setcursor(); ui_flush(); // Restore dollar_vcol(), because setcursor() may call curs_rows() diff --git a/src/nvim/syntax.c b/src/nvim/syntax.c index d4161b9ca2..14fef19399 100644 --- a/src/nvim/syntax.c +++ b/src/nvim/syntax.c @@ -4026,7 +4026,7 @@ static void syn_cmd_include(exarg_T *eap, int syncing) prev_toplvl_grp = curwin->w_s->b_syn_topgrp; curwin->w_s->b_syn_topgrp = sgl_id; if (source - ? do_source(eap->arg, false, DOSO_NONE) == FAIL + ? do_source(eap->arg, false, DOSO_NONE, NULL) == FAIL : source_runtime(eap->arg, DIP_ALL) == FAIL) { semsg(_(e_notopen), eap->arg); } diff --git a/src/nvim/window.c b/src/nvim/window.c index 38b7326363..39e9efbabb 100644 --- a/src/nvim/window.c +++ b/src/nvim/window.c @@ -993,10 +993,22 @@ void ui_ext_win_viewport(win_T *wp) // interact with incomplete final line? Diff filler lines? botline = wp->w_buffer->b_ml.ml_line_count; } + int scroll_delta = 0; + if (wp->w_viewport_last_topline > line_count) { + scroll_delta -= wp->w_viewport_last_topline - line_count; + wp->w_viewport_last_topline = line_count; + } + if (wp->w_topline < wp->w_viewport_last_topline) { + scroll_delta -= plines_m_win(wp, wp->w_topline, wp->w_viewport_last_topline - 1); + } else if (wp->w_topline > wp->w_viewport_last_topline + && wp->w_topline <= line_count) { + scroll_delta += plines_m_win(wp, wp->w_viewport_last_topline, wp->w_topline - 1); + } ui_call_win_viewport(wp->w_grid_alloc.handle, wp->handle, wp->w_topline - 1, botline, wp->w_cursor.lnum - 1, wp->w_cursor.col, - line_count); + line_count, scroll_delta); wp->w_viewport_invalid = false; + wp->w_viewport_last_topline = wp->w_topline; } } @@ -5038,6 +5050,7 @@ static win_T *win_alloc(win_T *after, bool hidden) new_wp->w_floating = 0; new_wp->w_float_config = FLOAT_CONFIG_INIT; new_wp->w_viewport_invalid = true; + new_wp->w_viewport_last_topline = 1; new_wp->w_ns_hl = -1; diff --git a/test/functional/api/vim_spec.lua b/test/functional/api/vim_spec.lua index 08abf82f47..2af041c706 100644 --- a/test/functional/api/vim_spec.lua +++ b/test/functional/api/vim_spec.lua @@ -2832,6 +2832,24 @@ describe('API', function() type = "boolean", was_set = true }, meths.get_option_info'showcmd') + + meths.set_option_value('showcmd', true, {}) + + eq({ + allows_duplicates = true, + commalist = false, + default = true, + flaglist = false, + global_local = false, + last_set_chan = 1, + last_set_linenr = 0, + last_set_sid = -9, + name = "showcmd", + scope = "global", + shortname = "sc", + type = "boolean", + was_set = true + }, meths.get_option_info'showcmd') end) end) @@ -4024,7 +4042,7 @@ describe('API', function() it('splits arguments correctly for Lua callback', function() meths.exec_lua([[ local function FooFunc(opts) - vim.pretty_print(opts.fargs) + vim.print(opts.fargs) end vim.api.nvim_create_user_command("Foo", FooFunc, { nargs = '+' }) diff --git a/test/functional/autocmd/termxx_spec.lua b/test/functional/autocmd/termxx_spec.lua index 63b5617eef..a9980dda04 100644 --- a/test/functional/autocmd/termxx_spec.lua +++ b/test/functional/autocmd/termxx_spec.lua @@ -50,6 +50,7 @@ describe('autocmd TermClose', function() end) it('triggers when long-running terminal job gets stopped', function() + skip(is_os('win')) nvim('set_option', 'shell', is_os('win') and 'cmd.exe' or 'sh') command('autocmd TermClose * let g:test_termclose = 23') command('terminal') diff --git a/test/functional/core/job_spec.lua b/test/functional/core/job_spec.lua index 1bae626b98..613dff577a 100644 --- a/test/functional/core/job_spec.lua +++ b/test/functional/core/job_spec.lua @@ -88,7 +88,6 @@ describe('jobs', function() end) it('append environment with pty #env', function() - skip(is_os('win')) nvim('command', "let $VAR = 'abc'") nvim('command', "let $TOTO = 'goodbye world'") nvim('command', "let g:job_opts.pty = v:true") @@ -806,7 +805,6 @@ describe('jobs', function() end) it('can be called recursively', function() - skip(is_os('win'), "TODO: Need `cat`") source([[ let g:opts = {} let g:counter = 0 diff --git a/test/functional/editor/mode_insert_spec.lua b/test/functional/editor/mode_insert_spec.lua index cd51a65be3..b00661ac3a 100644 --- a/test/functional/editor/mode_insert_spec.lua +++ b/test/functional/editor/mode_insert_spec.lua @@ -1,6 +1,7 @@ -- Insert-mode tests. local helpers = require('test.functional.helpers')(after_each) +local Screen = require('test.functional.ui.screen') local clear, feed, insert = helpers.clear, helpers.feed, helpers.insert local expect = helpers.expect local command = helpers.command @@ -48,6 +49,48 @@ describe('insert-mode', function() feed('i<C-r>"') expect('påskägg') end) + + it('double quote is removed after hit-enter prompt #22609', function() + local screen = Screen.new(60, 6) + screen:set_default_attr_ids({ + [0] = {bold = true, foreground = Screen.colors.Blue}, + [1] = {foreground = Screen.colors.Blue}, + [2] = {foreground = Screen.colors.SlateBlue}, + [3] = {bold = true}, + [4] = {reverse = true, bold = true}, + [5] = {background = Screen.colors.Red, foreground = Screen.colors.Red}, + [6] = {background = Screen.colors.Red, foreground = Screen.colors.White}, + [7] = {foreground = Screen.colors.SeaGreen, bold = true}, + }) + screen:attach() + feed('i<C-R>') + screen:expect([[ + {1:^"} | + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {3:-- INSERT --} | + ]]) + feed('={}<CR>') + screen:expect([[ + {1:"} | + {0:~ }| + {4: }| + ={5:{}{2:}} | + {6:E731: using Dictionary as a String} | + {7:Press ENTER or type command to continue}^ | + ]]) + feed('<CR>') + screen:expect([[ + ^ | + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {3:-- INSERT --} | + ]]) + end) end) describe('Ctrl-O', function() diff --git a/test/functional/ex_cmds/map_spec.lua b/test/functional/ex_cmds/map_spec.lua index ec912053b2..a197b81cc5 100644 --- a/test/functional/ex_cmds/map_spec.lua +++ b/test/functional/ex_cmds/map_spec.lua @@ -152,7 +152,7 @@ describe('Screen', function() ~ | ~ | ~ | - > | + -- INSERT -- | ]]) end) diff --git a/test/functional/ex_cmds/mksession_spec.lua b/test/functional/ex_cmds/mksession_spec.lua index 0a0c7ca410..0a1cdd93aa 100644 --- a/test/functional/ex_cmds/mksession_spec.lua +++ b/test/functional/ex_cmds/mksession_spec.lua @@ -18,6 +18,8 @@ local is_os = helpers.is_os local file_prefix = 'Xtest-functional-ex_cmds-mksession_spec' +if helpers.skip(helpers.is_os('win')) then return end + describe(':mksession', function() local session_file = file_prefix .. '.vim' local tab_dir = file_prefix .. '.d' diff --git a/test/functional/ex_cmds/verbose_spec.lua b/test/functional/ex_cmds/verbose_spec.lua index 000e746f1c..e55372e993 100644 --- a/test/functional/ex_cmds/verbose_spec.lua +++ b/test/functional/ex_cmds/verbose_spec.lua @@ -7,7 +7,7 @@ local exec_capture = helpers.exec_capture local write_file = helpers.write_file local call_viml_function = helpers.meths.call_function -describe('lua :verbose', function() +local function last_set_tests(cmd) local script_location, script_file -- All test cases below use the same nvim instance. setup(function() @@ -46,7 +46,7 @@ endfunction\ let &tw = s:return80()\ ", true) ]]) - exec(':source '..script_file) + exec(cmd .. ' ' .. script_file) end) teardown(function() @@ -106,6 +106,9 @@ test_group FileType end) it('"Last set" for command defined by nvim_command', function() + if cmd == 'luafile' then + pending('nvim_command does not set the script context') + end local result = exec_capture(':verbose command Bdelete') eq(string.format([[ Name Args Address Complete Definition @@ -123,7 +126,7 @@ test_group FileType script_location), result) end) - it('"Last set for function', function() + it('"Last set" for function', function() local result = exec_capture(':verbose function Close_Window') eq(string.format([[ function Close_Window() abort @@ -140,6 +143,14 @@ test_group FileType Last set from %s line 22]], script_location), result) end) +end + +describe('lua :verbose when using :source', function() + last_set_tests('source') +end) + +describe('lua :verbose when using :luafile', function() + last_set_tests('luafile') end) describe('lua verbose:', function() diff --git a/test/functional/fixtures/fake-lsp-server.lua b/test/functional/fixtures/fake-lsp-server.lua index 5fb86d029d..001cd5770a 100644 --- a/test/functional/fixtures/fake-lsp-server.lua +++ b/test/functional/fixtures/fake-lsp-server.lua @@ -272,6 +272,7 @@ function tests.text_document_save_did_open() end; body = function() notify('start') + expect_notification('textDocument/didClose') expect_notification('textDocument/didOpen') expect_notification('textDocument/didSave') notify('shutdown') diff --git a/test/functional/lua/buffer_updates_spec.lua b/test/functional/lua/buffer_updates_spec.lua index b1b39501f7..2cd3123dcd 100644 --- a/test/functional/lua/buffer_updates_spec.lua +++ b/test/functional/lua/buffer_updates_spec.lua @@ -1171,6 +1171,25 @@ describe('lua: nvim_buf_attach on_bytes', function() } end) + it('works with :diffput and :diffget', function() + local check_events = setup_eventcheck(verify, {"AAA"}) + command('diffthis') + command('new') + command('diffthis') + meths.buf_set_lines(0, 0, -1, true, {"AAA", "BBB"}) + feed('G') + command('diffput') + check_events { + { "test1", "bytes", 1, 3, 1, 0, 4, 0, 0, 0, 1, 0, 4 }; + } + meths.buf_set_lines(0, 0, -1, true, {"AAA", "CCC"}) + feed('<C-w>pG') + command('diffget') + check_events { + { "test1", "bytes", 1, 4, 1, 0, 4, 1, 0, 4, 1, 0, 4 }; + } + end) + local function test_lockmarks(mode) local description = (mode ~= "") and mode or "(baseline)" it("test_lockmarks " .. description .. " %delete _", function() diff --git a/test/functional/lua/commands_spec.lua b/test/functional/lua/commands_spec.lua index b8346df290..943095c51e 100644 --- a/test/functional/lua/commands_spec.lua +++ b/test/functional/lua/commands_spec.lua @@ -8,6 +8,8 @@ local eval = helpers.eval local feed = helpers.feed local clear = helpers.clear local meths = helpers.meths +local exec_lua = helpers.exec_lua +local exec_capture = helpers.exec_capture local funcs = helpers.funcs local source = helpers.source local dedent = helpers.dedent @@ -15,7 +17,6 @@ local command = helpers.command local exc_exec = helpers.exc_exec local pcall_err = helpers.pcall_err local write_file = helpers.write_file -local exec_capture = helpers.exec_capture local curbufmeths = helpers.curbufmeths local remove_trace = helpers.remove_trace @@ -142,22 +143,29 @@ describe(':lua command', function() ]]} end) - it('Can print results of =expr', function() - helpers.exec_lua("x = 5") - eq("5", helpers.exec_capture(':lua =x')) - helpers.exec_lua("function x() return 'hello' end") - eq([["hello"]], helpers.exec_capture(':lua = x()')) - helpers.exec_lua("x = {a = 1, b = 2}") - eq("{\n a = 1,\n b = 2\n}", helpers.exec_capture(':lua =x')) - helpers.exec_lua([[function x(success) + it('prints result of =expr', function() + exec_lua("x = 5") + eq("5", exec_capture(':lua =x')) + exec_lua("function x() return 'hello' end") + eq('hello', exec_capture(':lua = x()')) + exec_lua("x = {a = 1, b = 2}") + eq("{\n a = 1,\n b = 2\n}", exec_capture(':lua =x')) + exec_lua([[function x(success) if success then return true, "Return value" else return false, nil, "Error message" end end]]) - eq([[true "Return value"]], helpers.exec_capture(':lua =x(true)')) - eq([[false nil "Error message"]], helpers.exec_capture(':lua =x(false)')) + eq(dedent[[ + true + Return value]], + exec_capture(':lua =x(true)')) + eq(dedent[[ + false + nil + Error message]], + exec_capture(':lua =x(false)')) end) end) diff --git a/test/functional/lua/vim_spec.lua b/test/functional/lua/vim_spec.lua index 77628487ca..470102df5e 100644 --- a/test/functional/lua/vim_spec.lua +++ b/test/functional/lua/vim_spec.lua @@ -6,6 +6,7 @@ local nvim_prog = helpers.nvim_prog local funcs = helpers.funcs local meths = helpers.meths local command = helpers.command +local dedent = helpers.dedent local insert = helpers.insert local clear = helpers.clear local eq = helpers.eq @@ -2269,7 +2270,7 @@ describe('lua stdlib', function() describe('vim.region', function() it('charwise', function() - insert(helpers.dedent( [[ + insert(dedent( [[ text tααt tααt text text tαxt txtα tex text tαxt tαxt @@ -2923,6 +2924,24 @@ describe('lua stdlib', function() {4:-- Omni completion (^O^N^P) }{5:match 1 of 2} | ]]} end) + + it('vim.print', function() + -- vim.print() returns its args. + eq({42, 'abc', { a = { b = 77 }}}, + exec_lua[[return {vim.print(42, 'abc', { a = { b = 77 }})}]]) + + -- vim.print() pretty-prints the args. + eq(dedent[[ + + 42 + abc + { + a = { + b = 77 + } + }]], + eval[[execute('lua vim.print(42, "abc", { a = { b = 77 }})')]]) + end) end) describe('lua: builtin modules', function() diff --git a/test/functional/options/pastetoggle_spec.lua b/test/functional/options/pastetoggle_spec.lua deleted file mode 100644 index 40c14fa187..0000000000 --- a/test/functional/options/pastetoggle_spec.lua +++ /dev/null @@ -1,90 +0,0 @@ -local helpers = require('test.functional.helpers')(after_each) - -local clear = helpers.clear -local feed = helpers.feed -local command = helpers.command -local eq = helpers.eq -local expect = helpers.expect -local eval = helpers.eval -local insert = helpers.insert -local meths = helpers.meths -local sleep = helpers.sleep - -describe("'pastetoggle' option", function() - before_each(clear) - it("toggles 'paste'", function() - command('set pastetoggle=a') - eq(0, eval('&paste')) - feed('a') - -- Need another key so that the vgetorpeek() function returns. - feed('j') - eq(1, eval('&paste')) - end) - describe("multiple key 'pastetoggle'", function() - before_each(function() - eq(0, eval('&paste')) - command('set timeoutlen=1 ttimeoutlen=10000') - end) - it('is waited for when chars are typed', function() - local pastetoggle = 'lllll' - command('set pastetoggle=' .. pastetoggle) - feed(pastetoggle:sub(0, 2)) - -- sleep() for long enough that vgetorpeek() is gotten into, but short - -- enough that ttimeoutlen is not reached. - sleep(200) - feed(pastetoggle:sub(3, -1)) - -- Need another key so that the vgetorpeek() function returns. - feed('j') - eq(1, eval('&paste')) - end) - - it('is not waited for when there are no typed chars after mapped chars', function() - command('set pastetoggle=abc') - command('imap d a') - meths.feedkeys('id', 't', true) - -- sleep() for long enough that vgetorpeek() is gotten into, but short - -- enough that ttimeoutlen is not reached. - sleep(200) - feed('bc') - -- Need another key so that the vgetorpeek() function returns. - feed('j') - -- 'ttimeoutlen' should NOT apply - eq(0, eval('&paste')) - end) - - it('is waited for when there are typed chars after mapped chars', function() - command('set pastetoggle=abc') - command('imap d a') - meths.feedkeys('idb', 't', true) - -- sleep() for long enough that vgetorpeek() is gotten into, but short - -- enough that ttimeoutlen is not reached. - sleep(200) - feed('c') - -- Need another key so that the vgetorpeek() function returns. - feed('j') - -- 'ttimeoutlen' should apply - eq(1, eval('&paste')) - end) - - it('is waited for when there are typed chars after noremapped chars', function() - command('set pastetoggle=abc') - command('inoremap d a') - meths.feedkeys('idb', 't', true) - -- sleep() for long enough that vgetorpeek() is gotten into, but short - -- enough that ttimeoutlen is not reached. - sleep(200) - feed('c') - -- Need another key so that the vgetorpeek() function returns. - feed('j') - -- 'ttimeoutlen' should apply - eq(1, eval('&paste')) - end) - end) - it('does not interfere with character-find', function() - insert('foo,bar') - feed('0') - command('set pastetoggle=,sp') - feed('dt,') - expect(',bar') - end) -end) diff --git a/test/functional/plugin/lsp_spec.lua b/test/functional/plugin/lsp_spec.lua index c621a5eae2..a6e50ac82c 100644 --- a/test/functional/plugin/lsp_spec.lua +++ b/test/functional/plugin/lsp_spec.lua @@ -3554,6 +3554,7 @@ describe('LSP', function() vim.cmd.normal('v') vim.api.nvim_win_set_cursor(0, { 2, 3 }) vim.lsp.buf.format({ bufnr = bufnr, false }) + vim.lsp.stop_client(client_id) return server.messages ]]) eq("textDocument/rangeFormatting", result[3].method) @@ -3563,6 +3564,52 @@ describe('LSP', function() } eq(expected_range, result[3].params.range) end) + it('format formats range in visual line mode', function() + exec_lua(create_server_definition) + local result = exec_lua([[ + local server = _create_server({ capabilities = { + documentFormattingProvider = true, + documentRangeFormattingProvider = true, + }}) + local bufnr = vim.api.nvim_get_current_buf() + local client_id = vim.lsp.start({ name = 'dummy', cmd = server.cmd }) + vim.api.nvim_win_set_buf(0, bufnr) + vim.api.nvim_buf_set_lines(bufnr, 0, -1, true, {'foo', 'bar baz'}) + vim.api.nvim_win_set_cursor(0, { 1, 2 }) + vim.cmd.normal('V') + vim.api.nvim_win_set_cursor(0, { 2, 1 }) + vim.lsp.buf.format({ bufnr = bufnr, false }) + + -- Format again with visual lines going from bottom to top + -- Must result in same formatting + vim.cmd.normal("<ESC>") + vim.api.nvim_win_set_cursor(0, { 2, 1 }) + vim.cmd.normal('V') + vim.api.nvim_win_set_cursor(0, { 1, 2 }) + vim.lsp.buf.format({ bufnr = bufnr, false }) + + vim.lsp.stop_client(client_id) + return server.messages + ]]) + local expected_methods = { + "initialize", + "initialized", + "textDocument/rangeFormatting", + "$/cancelRequest", + "textDocument/rangeFormatting", + "$/cancelRequest", + "shutdown", + "exit", + } + eq(expected_methods, vim.tbl_map(function(x) return x.method end, result)) + -- uses first column of start line and last column of end line + local expected_range = { + start = { line = 0, character = 0 }, + ['end'] = { line = 1, character = 7 }, + } + eq(expected_range, result[3].params.range) + eq(expected_range, result[5].params.range) + end) it('Aborts with notify if no clients support requested method', function() exec_lua(create_server_definition) exec_lua([[ diff --git a/test/functional/terminal/mouse_spec.lua b/test/functional/terminal/mouse_spec.lua index 50c8f5e7df..ac76217023 100644 --- a/test/functional/terminal/mouse_spec.lua +++ b/test/functional/terminal/mouse_spec.lua @@ -68,7 +68,6 @@ describe(':terminal mouse', function() end) it('does not leave terminal mode on left-release', function() - skip(is_os('win')) feed('<LeftRelease>') eq('t', eval('mode(1)')) end) @@ -232,7 +231,6 @@ describe(':terminal mouse', function() end) describe('with a split window and other buffer', function() - skip(is_os('win')) before_each(function() feed('<c-\\><c-n>:vsp<cr>') screen:expect([[ diff --git a/test/functional/terminal/scrollback_spec.lua b/test/functional/terminal/scrollback_spec.lua index a4899c8219..00a35a5c6c 100644 --- a/test/functional/terminal/scrollback_spec.lua +++ b/test/functional/terminal/scrollback_spec.lua @@ -140,7 +140,6 @@ describe(':terminal scrollback', function() describe('and height decreased by 1', function() - if skip(is_os('win')) then return end local function will_hide_top_line() feed([[<C-\><C-N>]]) screen:try_resize(screen._width - 2, screen._height - 1) @@ -347,7 +346,6 @@ end) describe(':terminal prints more lines than the screen height and exits', function() it('will push extra lines to scrollback', function() - skip(is_os('win')) clear() local screen = Screen.new(30, 7) screen:attach({rgb=false}) diff --git a/test/functional/treesitter/parser_spec.lua b/test/functional/treesitter/parser_spec.lua index 0f00fcfe0d..e872861d2a 100644 --- a/test/functional/treesitter/parser_spec.lua +++ b/test/functional/treesitter/parser_spec.lua @@ -7,7 +7,6 @@ local exec_lua = helpers.exec_lua local pcall_err = helpers.pcall_err local feed = helpers.feed local is_os = helpers.is_os -local skip = helpers.skip before_each(clear) @@ -196,7 +195,7 @@ void ui_refresh(void) local manyruns = q(100) -- First run should be at least 400x slower than an 100 subsequent runs. - local factor = is_os('win') and 300 or 400 + local factor = is_os('win') and 200 or 400 assert(factor * manyruns < firstrun, ('firstrun: %f ms, manyruns: %f ms'):format(firstrun / 1e6, manyruns / 1e6)) end) @@ -277,13 +276,13 @@ void ui_refresh(void) eq('void', res2) end) - it('support getting text where start of node is past EOF', function() + it('support getting text where start of node is one past EOF', function() local text = [[ def run a = <<~E end]] insert(text) - local result = exec_lua([[ + eq('', exec_lua[[ local fake_node = {} function fake_node:start() return 3, 0, 23 @@ -291,12 +290,14 @@ end]] function fake_node:end_() return 3, 0, 23 end - function fake_node:range() + function fake_node:range(bytes) + if bytes then + return 3, 0, 23, 3, 0, 23 + end return 3, 0, 3, 0 end - return vim.treesitter.get_node_text(fake_node, 0) == nil + return vim.treesitter.get_node_text(fake_node, 0) ]]) - eq(true, result) end) it('support getting empty text if node range is zero width', function() @@ -739,7 +740,6 @@ int x = INT_MAX; end) it("should not inject bad languages", function() - skip(is_os('win')) exec_lua([=[ vim.treesitter.add_directive("inject-bad!", function(match, _, _, pred, metadata) metadata.language = "{" diff --git a/test/functional/ui/cmdline_spec.lua b/test/functional/ui/cmdline_spec.lua index 1c9ac7f7ba..a9469bdf2d 100644 --- a/test/functional/ui/cmdline_spec.lua +++ b/test/functional/ui/cmdline_spec.lua @@ -1241,7 +1241,7 @@ describe('cmdheight=0', function() {1:~ }| ## grid 3 ]], win_viewport={ - [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1}; + [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0}; }} feed '/p' @@ -1261,7 +1261,7 @@ describe('cmdheight=0', function() ## grid 3 /p^ | ]], win_viewport={ - [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1}; + [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0}; }} end) diff --git a/test/functional/ui/float_spec.lua b/test/functional/ui/float_spec.lua index 6759510ad1..bae83537e5 100644 --- a/test/functional/ui/float_spec.lua +++ b/test/functional/ui/float_spec.lua @@ -1433,8 +1433,8 @@ describe('float window', function() ]], float_pos={ [5] = { { id = 1002 }, "NW", 1, 2, 5, true } }, win_viewport={ - [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1}; - [5] = {win = {id = 1002}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 2}; + [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0}; + [5] = {win = {id = 1002}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 2, sum_scroll_delta = 0}; }} else screen:expect{grid=[[ @@ -1476,8 +1476,8 @@ describe('float window', function() ]], float_pos={ [5] = { { id = 1002 }, "NW", 1, 2, 5, true } }, win_viewport={ - [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1}; - [5] = {win = {id = 1002}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 2}; + [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0}; + [5] = {win = {id = 1002}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 2, sum_scroll_delta = 0}; }} else screen:expect{grid=[[ @@ -1519,8 +1519,8 @@ describe('float window', function() ]], float_pos={ [5] = { { id = 1002 }, "NW", 1, 2, 5, true } }, win_viewport={ - [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1}; - [5] = {win = {id = 1002}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 2}; + [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0}; + [5] = {win = {id = 1002}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 2, sum_scroll_delta = 0}; }} else screen:expect{grid=[[ @@ -1562,8 +1562,8 @@ describe('float window', function() ]], float_pos={ [5] = { { id = 1002 }, "NW", 1, 2, 5, true } }, win_viewport={ - [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1}; - [5] = {win = {id = 1002}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 2}; + [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0}; + [5] = {win = {id = 1002}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 2, sum_scroll_delta = 0}; }} else screen:expect{grid=[[ @@ -1606,8 +1606,8 @@ describe('float window', function() ]], float_pos={ [5] = { { id = 1002 }, "NW", 1, 2, 5, true } }, win_viewport={ - [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1}; - [5] = {win = {id = 1002}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 2}; + [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0}; + [5] = {win = {id = 1002}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 2, sum_scroll_delta = 0}; }} else screen:expect{grid=[[ @@ -1647,8 +1647,8 @@ describe('float window', function() ]], float_pos={ [5] = { { id = 1002 }, "NW", 1, 2, 5, true } }, win_viewport={ - [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1}; - [5] = {win = {id = 1002}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 2}; + [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0}; + [5] = {win = {id = 1002}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 2, sum_scroll_delta = 0}; }} else screen:expect{grid=[[ @@ -1688,8 +1688,8 @@ describe('float window', function() ]], float_pos={ [5] = { { id = 1002 }, "NW", 1, 2, 5, true } }, win_viewport={ - [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1}; - [5] = {win = {id = 1002}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 2}; + [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0}; + [5] = {win = {id = 1002}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 2, sum_scroll_delta = 0}; }} else screen:expect{grid=[[ @@ -1731,8 +1731,8 @@ describe('float window', function() ]], float_pos={ [5] = { { id = 1002 }, "NW", 1, 2, 5, true } }, win_viewport={ - [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1}; - [5] = {win = {id = 1002}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 2}; + [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0}; + [5] = {win = {id = 1002}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 2, sum_scroll_delta = 0}; }} else screen:expect{grid=[[ @@ -1781,8 +1781,8 @@ describe('float window', function() ]], float_pos={ [5] = { { id = 1002 }, "NW", 1, 2, 5, true } }, win_viewport={ - [2] = {win = {id = 1000}, topline = 0, botline = 6, curline = 5, curcol = 0, linecount = 6}; - [5] = {win = {id = 1002}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 2}; + [2] = {win = {id = 1000}, topline = 0, botline = 6, curline = 5, curcol = 0, linecount = 6, sum_scroll_delta = 0}; + [5] = {win = {id = 1002}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 2, sum_scroll_delta = 0}; }} else screen:expect{grid=[[ @@ -1868,8 +1868,8 @@ describe('float window', function() ]], float_pos={ [5] = { { id = 1002 }, "NW", 1, 2, 5, true } }, win_viewport={ - [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1}; - [5] = {win = {id = 1002}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 2}; + [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0}; + [5] = {win = {id = 1002}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 2, sum_scroll_delta = 0}; }} else screen:expect{grid=[[ @@ -1911,8 +1911,8 @@ describe('float window', function() ]], float_pos={ [5] = { { id = 1002 }, "NW", 1, 2, 5, true } }, win_viewport={ - [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1}; - [5] = {win = {id = 1002}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 2}; + [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0}; + [5] = {win = {id = 1002}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 2, sum_scroll_delta = 0}; }} else screen:expect{grid=[[ @@ -1954,8 +1954,8 @@ describe('float window', function() ]], float_pos={ [5] = { { id = 1002 }, "NW", 1, 2, 5, true } }, win_viewport={ - [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1}; - [5] = {win = {id = 1002}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 2}; + [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0}; + [5] = {win = {id = 1002}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 2, sum_scroll_delta = 0}; }} else screen:expect{grid=[[ @@ -1997,8 +1997,8 @@ describe('float window', function() ]], float_pos={ [5] = { { id = 1002 }, "NW", 1, 2, 5, true } }, win_viewport={ - [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1}; - [5] = {win = {id = 1002}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 2}; + [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0}; + [5] = {win = {id = 1002}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 2, sum_scroll_delta = 0}; }} else screen:expect{grid=[[ @@ -2048,8 +2048,8 @@ describe('float window', function() ]], float_pos={ [4] = { { id = 1001 }, "NW", 1, 0, 0, true } }, win_viewport={ - [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1}; - [4] = {win = {id = 1001}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1}; + [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0}; + [4] = {win = {id = 1001}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0}; }} else screen:expect{grid=[[ @@ -2106,8 +2106,8 @@ describe('float window', function() ]], float_pos={ [5] = { { id = 1002 }, "NW", 1, 0, 5, true } }, win_viewport={ - [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1}; - [5] = {win = {id = 1002}, topline = 0, botline = 3, curline = 2, curcol = 0, linecount = 3}; + [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0}; + [5] = {win = {id = 1002}, topline = 0, botline = 3, curline = 2, curcol = 0, linecount = 3, sum_scroll_delta = 0}; }} else screen:expect{grid=[[ @@ -2165,8 +2165,8 @@ describe('float window', function() [5] = { { id = 1002 }, "NW", 1, 0, 5, true, 50 }, [6] = { { id = -1 }, "NW", 5, 4, 0, false, 100 } }, win_viewport={ - [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount=1}; - [5] = {win = {id = 1002}, topline = 0, botline = 3, curline = 2, curcol = 3, linecount=3}; + [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount=1, sum_scroll_delta = 0}; + [5] = {win = {id = 1002}, topline = 0, botline = 3, curline = 2, curcol = 3, linecount=3, sum_scroll_delta = 0}; }} else screen:expect{grid=[[ @@ -2618,7 +2618,8 @@ describe('float window', function() curline = 0, curcol = 3, linecount = 2, - win = { id = 1000 } + sum_scroll_delta = 0, + win = { id = 1000 }, }, [4] = { topline = 0, @@ -2626,6 +2627,7 @@ describe('float window', function() curline = 0, curcol = 3, linecount = 2, + sum_scroll_delta = 0, win = { id = 1001 } }, [5] = { @@ -2634,6 +2636,7 @@ describe('float window', function() curline = 0, curcol = 0, linecount = 1, + sum_scroll_delta = 0, win = { id = 1002 } } }} @@ -7149,8 +7152,8 @@ describe('float window', function() ]], float_pos={ [5] = {{id = 1002}, "NW", 1, 2, 5, true, 50}; }, win_viewport={ - [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1}; - [5] = {win = {id = 1002}, topline = 0, botline = 3, curline = 0, curcol = 0, linecount = 3}; + [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0}; + [5] = {win = {id = 1002}, topline = 0, botline = 3, curline = 0, curcol = 0, linecount = 3, sum_scroll_delta = 0}; }} meths.input_mouse('left', 'press', '', 5, 0, 0) @@ -7179,8 +7182,8 @@ describe('float window', function() ]], float_pos={ [5] = {{id = 1002}, "NW", 1, 2, 5, true, 50}; }, win_viewport={ - [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1}; - [5] = {win = {id = 1002}, topline = 0, botline = 3, curline = 0, curcol = 0, linecount = 3}; + [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0}; + [5] = {win = {id = 1002}, topline = 0, botline = 3, curline = 0, curcol = 0, linecount = 3, sum_scroll_delta = 0}; }} meths.input_mouse('left', 'drag', '', 5, 1, 2) @@ -7209,8 +7212,8 @@ describe('float window', function() ]], float_pos={ [5] = {{id = 1002}, "NW", 1, 2, 5, true, 50}; }, win_viewport={ - [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1}; - [5] = {win = {id = 1002}, topline = 0, botline = 3, curline = 1, curcol = 2, linecount = 3}; + [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0}; + [5] = {win = {id = 1002}, topline = 0, botline = 3, curline = 1, curcol = 2, linecount = 3, sum_scroll_delta = 0}; }} else screen:expect{grid=[[ @@ -7279,8 +7282,8 @@ describe('float window', function() ]], float_pos={ [5] = {{id = 1002}, "NW", 1, 0, 5, true, 50}; }, win_viewport={ - [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1}; - [5] = {win = {id = 1002}, topline = 0, botline = 3, curline = 0, curcol = 0, linecount = 3}; + [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0}; + [5] = {win = {id = 1002}, topline = 0, botline = 3, curline = 0, curcol = 0, linecount = 3, sum_scroll_delta = 0}; }} meths.input_mouse('left', 'press', '', 5, 1, 1) @@ -7311,8 +7314,8 @@ describe('float window', function() ]], float_pos={ [5] = {{id = 1002}, "NW", 1, 0, 5, true, 50}; }, win_viewport={ - [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1}; - [5] = {win = {id = 1002}, topline = 0, botline = 3, curline = 0, curcol = 0, linecount = 3}; + [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0}; + [5] = {win = {id = 1002}, topline = 0, botline = 3, curline = 0, curcol = 0, linecount = 3, sum_scroll_delta = 0}; }} meths.input_mouse('left', 'drag', '', 5, 2, 3) @@ -7343,8 +7346,8 @@ describe('float window', function() ]], float_pos={ [5] = {{id = 1002}, "NW", 1, 0, 5, true, 50}; }, win_viewport={ - [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1}; - [5] = {win = {id = 1002}, topline = 0, botline = 3, curline = 1, curcol = 2, linecount = 3}; + [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0}; + [5] = {win = {id = 1002}, topline = 0, botline = 3, curline = 1, curcol = 2, linecount = 3, sum_scroll_delta = 0}; }} else screen:expect{grid=[[ @@ -7413,8 +7416,8 @@ describe('float window', function() ]], float_pos={ [5] = {{id = 1002}, "NW", 1, 1, 5, true, 50}; }, win_viewport={ - [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1}; - [5] = {win = {id = 1002}, topline = 0, botline = 3, curline = 0, curcol = 0, linecount = 3}; + [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0}; + [5] = {win = {id = 1002}, topline = 0, botline = 3, curline = 0, curcol = 0, linecount = 3, sum_scroll_delta = 0}; }} meths.input_mouse('left', 'press', '', 5, 1, 0) @@ -7444,8 +7447,8 @@ describe('float window', function() ]], float_pos={ [5] = {{id = 1002}, "NW", 1, 1, 5, true, 50}; }, win_viewport={ - [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1}; - [5] = {win = {id = 1002}, topline = 0, botline = 3, curline = 0, curcol = 0, linecount = 3}; + [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0}; + [5] = {win = {id = 1002}, topline = 0, botline = 3, curline = 0, curcol = 0, linecount = 3, sum_scroll_delta = 0}; }} meths.input_mouse('left', 'drag', '', 5, 2, 2) @@ -7475,8 +7478,8 @@ describe('float window', function() ]], float_pos={ [5] = {{id = 1002}, "NW", 1, 1, 5, true, 50}; }, win_viewport={ - [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1}; - [5] = {win = {id = 1002}, topline = 0, botline = 3, curline = 1, curcol = 2, linecount = 3}; + [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0}; + [5] = {win = {id = 1002}, topline = 0, botline = 3, curline = 1, curcol = 2, linecount = 3, sum_scroll_delta = 0}; }} else screen:expect{grid=[[ @@ -8228,8 +8231,8 @@ describe('float window', function() ]], float_pos={ [4] = { { id = 1001 }, "NW", 1, 2, 5, true }; }, win_viewport={ - [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1}; - [4] = {win = {id = 1001}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1}; + [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0}; + [4] = {win = {id = 1001}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0}; }} else screen:expect{grid=[[ @@ -8285,10 +8288,10 @@ describe('float window', function() [5] = { { id = 1002 }, "NW", 1, 3, 8, true }; [6] = { { id = 1003 }, "NW", 1, 4, 10, true }; }, win_viewport={ - [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount=1}; - [4] = {win = {id = 1001}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount=1}; - [5] = {win = {id = 1002}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount=1}; - [6] = {win = {id = 1003}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount=1}; + [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount=1, sum_scroll_delta = 0}; + [4] = {win = {id = 1001}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount=1, sum_scroll_delta = 0}; + [5] = {win = {id = 1002}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount=1, sum_scroll_delta = 0}; + [6] = {win = {id = 1003}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount=1, sum_scroll_delta = 0}; }} else screen:expect{grid=[[ @@ -8333,8 +8336,8 @@ describe('float window', function() ]], float_pos={ [4] = { { id = 1001 }, "NW", 1, 2, 5, true }; }, win_viewport={ - [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1}; - [4] = {win = {id = 1001}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1}; + [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0}; + [4] = {win = {id = 1001}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0}; }} else screen:expect{grid=[[ @@ -8390,10 +8393,10 @@ describe('float window', function() [5] = { { id = 1002 }, "NW", 1, 4, 10, true }; [6] = { { id = 1003 }, "NW", 1, 3, 8, true }; }, win_viewport={ - [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1}; - [4] = {win = {id = 1001}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1}; - [5] = {win = {id = 1002}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1}; - [6] = {win = {id = 1003}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1}; + [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0}; + [4] = {win = {id = 1001}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0}; + [5] = {win = {id = 1002}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0}; + [6] = {win = {id = 1003}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0}; }} else screen:expect{grid=[[ @@ -8453,10 +8456,10 @@ describe('float window', function() [5] = {{id = 1002}, "NW", 1, 2, 6, true, 50}; [6] = {{id = 1003}, "NW", 1, 3, 7, true, 40}; }, win_viewport={ - [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1}; - [4] = {win = {id = 1001}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1}; - [5] = {win = {id = 1002}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1}; - [6] = {win = {id = 1003}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1}; + [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0}; + [4] = {win = {id = 1001}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0}; + [5] = {win = {id = 1002}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0}; + [6] = {win = {id = 1003}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0}; }} else screen:expect{grid=[[ @@ -8502,8 +8505,8 @@ describe('float window', function() ]], float_pos={ [4] = {{id = 1001}, "NW", 1, 1, 5, true, 50}; }, win_viewport={ - [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1}; - [4] = {win = {id = 1001}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1}; + [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0}; + [4] = {win = {id = 1001}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0}; }} else screen:expect{grid=[[ @@ -8549,8 +8552,8 @@ describe('float window', function() ]], float_pos={ [4] = {{id = 1001}, "NW", 1, 0, 4, true, 50}; }, win_viewport={ - [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1}; - [4] = {win = {id = 1001}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1}; + [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0}; + [4] = {win = {id = 1001}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0}; }} else screen:expect{grid=[[ @@ -8604,8 +8607,8 @@ describe('float window', function() ]], float_pos={ [5] = {{id = 1002}, "SW", 1, 9, 0, true, 50}; }, win_viewport={ - [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1}; - [5] = {win = {id = 1002}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1}; + [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0}; + [5] = {win = {id = 1002}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0}; }} else screen:expect{grid=[[ @@ -8658,8 +8661,8 @@ describe('float window', function() ]], float_pos={ [5] = {{id = 1002}, "SW", 1, 9, 0, true, 50}; }, win_viewport={ - [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1}; - [5] = {win = {id = 1002}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1}; + [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0}; + [5] = {win = {id = 1002}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0}; }} else screen:expect{grid=[[ @@ -8701,7 +8704,7 @@ describe('float window', function() {0:~ }| ## grid 3 ]], win_viewport={ - [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1}; + [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0}; }} else screen:expect{grid=[[ @@ -8756,8 +8759,8 @@ describe('float window', function() ]], float_pos={ [5] = {{id = 1002}, "SW", 1, 8, 0, true, 50}; }, win_viewport={ - [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1}; - [5] = {win = {id = 1002}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1}; + [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0}; + [5] = {win = {id = 1002}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0}; }} else screen:expect{grid=[[ @@ -8816,8 +8819,8 @@ describe('float window', function() ]], float_pos={ [5] = {{id = 1002}, "SW", 1, 8, 0, true, 50}; }, win_viewport={ - [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1}; - [5] = {win = {id = 1002}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1}; + [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0}; + [5] = {win = {id = 1002}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0}; }} else screen:expect{grid=[[ @@ -8865,8 +8868,8 @@ describe('float window', function() ]], float_pos={ [5] = {{id = 1002}, "SW", 1, 8, 0, true, 50}; }, win_viewport={ - [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1}; - [5] = {win = {id = 1002}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1}; + [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0}; + [5] = {win = {id = 1002}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0}; }} else screen:expect{grid=[[ @@ -8907,9 +8910,8 @@ describe('float window', function() ## grid 3 | ]], win_viewport={ - [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1}; + [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0}; }} - else screen:expect{grid=[[ ^ | @@ -8952,6 +8954,328 @@ describe('float window', function() test_float_move_close('autocmd BufWinLeave * ++once redraw') end) end) + + it(':sleep cursor placement #22639', function() + local float_opts = {relative = 'editor', row = 1, col = 1, width = 4, height = 3} + local win = meths.open_win(meths.create_buf(false, false), true, float_opts) + feed('iab<CR>cd<Esc>') + feed(':sleep 100') + if multigrid then + screen:expect{grid=[[ + ## grid 1 + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [3:----------------------------------------]| + ## grid 2 + | + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + ## grid 3 + :sleep 100^ | + ## grid 4 + {1:ab }| + {1:cd }| + {2:~ }| + ]], float_pos={ + [4] = {{id = 1001}, "NW", 1, 1, 1, true, 50}; + }, win_viewport={ + [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0}; + [4] = {win = {id = 1001}, topline = 0, botline = 3, curline = 1, curcol = 1, linecount = 2, sum_scroll_delta = 0}; + }} + else + screen:expect{grid=[[ + | + {0:~}{1:ab }{0: }| + {0:~}{1:cd }{0: }| + {0:~}{2:~ }{0: }| + {0:~ }| + {0:~ }| + :sleep 100^ | + ]]} + end + + feed('<CR>') + if multigrid then + screen:expect{grid=[[ + ## grid 1 + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [3:----------------------------------------]| + ## grid 2 + | + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + ## grid 3 + :sleep 100 | + ## grid 4 + {1:ab }| + {1:c^d }| + {2:~ }| + ]], float_pos={ + [4] = {{id = 1001}, "NW", 1, 1, 1, true, 50}; + }, win_viewport={ + [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0}; + [4] = {win = {id = 1001}, topline = 0, botline = 3, curline = 1, curcol = 1, linecount = 2, sum_scroll_delta = 0}; + }} + else + screen:expect{grid=[[ + | + {0:~}{1:ab }{0: }| + {0:~}{1:c^d }{0: }| + {0:~}{2:~ }{0: }| + {0:~ }| + {0:~ }| + :sleep 100 | + ]]} + end + feed('<C-C>') + screen:expect_unchanged() + + meths.win_set_config(win, {border = 'single'}) + feed(':sleep 100') + if multigrid then + screen:expect{grid=[[ + ## grid 1 + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [3:----------------------------------------]| + ## grid 2 + | + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + ## grid 3 + :sleep 100^ | + ## grid 4 + {5:┌────┐}| + {5:│}{1:ab }{5:│}| + {5:│}{1:cd }{5:│}| + {5:│}{2:~ }{5:│}| + {5:└────┘}| + ]], float_pos={ + [4] = {{id = 1001}, "NW", 1, 1, 1, true, 50}; + }, win_viewport={ + [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0}; + [4] = {win = {id = 1001}, topline = 0, botline = 3, curline = 1, curcol = 1, linecount = 2, sum_scroll_delta = 0}; + }} + else + screen:expect{grid=[[ + | + {0:~}{5:┌────┐}{0: }| + {0:~}{5:│}{1:ab }{5:│}{0: }| + {0:~}{5:│}{1:cd }{5:│}{0: }| + {0:~}{5:│}{2:~ }{5:│}{0: }| + {0:~}{5:└────┘}{0: }| + :sleep 100^ | + ]]} + end + + feed('<CR>') + if multigrid then + screen:expect{grid=[[ + ## grid 1 + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [3:----------------------------------------]| + ## grid 2 + | + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + ## grid 3 + :sleep 100 | + ## grid 4 + {5:┌────┐}| + {5:│}{1:ab }{5:│}| + {5:│}{1:c^d }{5:│}| + {5:│}{2:~ }{5:│}| + {5:└────┘}| + ]], float_pos={ + [4] = {{id = 1001}, "NW", 1, 1, 1, true, 50}; + }, win_viewport={ + [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0}; + [4] = {win = {id = 1001}, topline = 0, botline = 3, curline = 1, curcol = 1, linecount = 2, sum_scroll_delta = 0}; + }} + else + screen:expect{grid=[[ + | + {0:~}{5:┌────┐}{0: }| + {0:~}{5:│}{1:ab }{5:│}{0: }| + {0:~}{5:│}{1:c^d }{5:│}{0: }| + {0:~}{5:│}{2:~ }{5:│}{0: }| + {0:~}{5:└────┘}{0: }| + :sleep 100 | + ]]} + end + feed('<C-C>') + screen:expect_unchanged() + + command('setlocal winbar=foo') + feed(':sleep 100') + if multigrid then + screen:expect{grid=[[ + ## grid 1 + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [3:----------------------------------------]| + ## grid 2 + | + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + ## grid 3 + :sleep 100^ | + ## grid 4 + {5:┌────┐}| + {5:│}{3:foo }{5:│}| + {5:│}{1:ab }{5:│}| + {5:│}{1:cd }{5:│}| + {5:└────┘}| + ]], float_pos={ + [4] = {{id = 1001}, "NW", 1, 1, 1, true, 50}; + }, win_viewport={ + [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0}; + [4] = {win = {id = 1001}, topline = 0, botline = 2, curline = 1, curcol = 1, linecount = 2, sum_scroll_delta = 0}; + }} + else + screen:expect{grid=[[ + | + {0:~}{5:┌────┐}{0: }| + {0:~}{5:│}{3:foo }{5:│}{0: }| + {0:~}{5:│}{1:ab }{5:│}{0: }| + {0:~}{5:│}{1:cd }{5:│}{0: }| + {0:~}{5:└────┘}{0: }| + :sleep 100^ | + ]]} + end + + feed('<CR>') + if multigrid then + screen:expect{grid=[[ + ## grid 1 + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [3:----------------------------------------]| + ## grid 2 + | + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + ## grid 3 + :sleep 100 | + ## grid 4 + {5:┌────┐}| + {5:│}{3:foo }{5:│}| + {5:│}{1:ab }{5:│}| + {5:│}{1:c^d }{5:│}| + {5:└────┘}| + ]], float_pos={ + [4] = {{id = 1001}, "NW", 1, 1, 1, true, 50}; + }, win_viewport={ + [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0}; + [4] = {win = {id = 1001}, topline = 0, botline = 2, curline = 1, curcol = 1, linecount = 2, sum_scroll_delta = 0}; + }} + else + screen:expect{grid=[[ + | + {0:~}{5:┌────┐}{0: }| + {0:~}{5:│}{3:foo }{5:│}{0: }| + {0:~}{5:│}{1:ab }{5:│}{0: }| + {0:~}{5:│}{1:c^d }{5:│}{0: }| + {0:~}{5:└────┘}{0: }| + :sleep 100 | + ]]} + end + feed('<C-C>') + screen:expect_unchanged() + end) + + it('with rightleft and border #22640', function() + local float_opts = {relative='editor', width=5, height=3, row=1, col=1, border='single'} + meths.open_win(meths.create_buf(false, false), true, float_opts) + command('setlocal rightleft') + feed('iabc<CR>def<Esc>') + if multigrid then + screen:expect{grid=[[ + ## grid 1 + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [2:----------------------------------------]| + [3:----------------------------------------]| + ## grid 2 + | + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + ## grid 3 + | + ## grid 4 + {5:┌─────┐}| + {5:│}{1: cba}{5:│}| + {5:│}{1: ^fed}{5:│}| + {5:│}{2: ~}{5:│}| + {5:└─────┘}| + ]], float_pos={ + [4] = {{id = 1001}, "NW", 1, 1, 1, true, 50}; + }, win_viewport={ + [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0}; + [4] = {win = {id = 1001}, topline = 0, botline = 3, curline = 1, curcol = 2, linecount = 2, sum_scroll_delta = 0}; + }} + else + screen:expect{grid=[[ + | + {0:~}{5:┌─────┐}{0: }| + {0:~}{5:│}{1: cba}{5:│}{0: }| + {0:~}{5:│}{1: ^fed}{5:│}{0: }| + {0:~}{5:│}{2: ~}{5:│}{0: }| + {0:~}{5:└─────┘}{0: }| + | + ]]} + end + end) end describe('with ext_multigrid', function() diff --git a/test/functional/ui/highlight_spec.lua b/test/functional/ui/highlight_spec.lua index 288c2a214f..d5e0eefb41 100644 --- a/test/functional/ui/highlight_spec.lua +++ b/test/functional/ui/highlight_spec.lua @@ -1812,6 +1812,31 @@ describe("'winhighlight' highlight", function() ]]) end) + it('works for background color in rightleft window #22640', function() + -- Use a wide screen to also check that this doesn't overflow linebuf_attr. + screen:try_resize(80, 6) + insert('aa') + command('setlocal rightleft') + command('setlocal winhl=Normal:Background1') + screen:expect([[ + {1: ^aa}| + {2: ~}| + {2: ~}| + {2: ~}| + {2: ~}| + | + ]]) + command('botright vsplit') + screen:expect([[ + {1: aa│ ^aa}| + {2: ~}{1:│}{2: ~}| + {2: ~}{1:│}{2: ~}| + {2: ~}{1:│}{2: ~}| + {4:[No Name] [+] }{3:[No Name] [+] }| + | + ]]) + end) + it('handles undefined groups', function() command("set winhl=Normal:Background1") screen:expect([[ diff --git a/test/functional/ui/messages_spec.lua b/test/functional/ui/messages_spec.lua index 212d3aee7d..db45e80dae 100644 --- a/test/functional/ui/messages_spec.lua +++ b/test/functional/ui/messages_spec.lua @@ -474,8 +474,7 @@ describe('ui/ext_messages', function() ]], msg_history={{ content = {{ "stuff" }}, kind = "echomsg", - }}, showmode={{ "-- INSERT --", 3 }}, - messages={{ + }}, messages={{ content = {{ "Press ENTER or type command to continue", 4}}, kind = "return_prompt" }}} diff --git a/test/functional/ui/multigrid_spec.lua b/test/functional/ui/multigrid_spec.lua index 71adeb42a4..2525314b8e 100644 --- a/test/functional/ui/multigrid_spec.lua +++ b/test/functional/ui/multigrid_spec.lua @@ -2127,7 +2127,7 @@ describe('ext_multigrid', function() ## grid 3 | ]], win_viewport={ - [2] = {win = { id = 1000 }, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1} + [2] = {win = { id = 1000 }, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0} }} insert([[ Lorem ipsum dolor sit amet, consectetur @@ -2162,7 +2162,7 @@ describe('ext_multigrid', function() ## grid 3 | ]], win_viewport={ - [2] = {win = {id = 1000}, topline = 5, botline = 11, curline = 10, curcol = 7, linecount = 11}, + [2] = {win = {id = 1000}, topline = 5, botline = 11, curline = 10, curcol = 7, linecount = 11, sum_scroll_delta = 5}, }} @@ -2187,7 +2187,7 @@ describe('ext_multigrid', function() ## grid 3 | ]], win_viewport={ - [2] = {win = {id = 1000}, topline = 2, botline = 9, curline = 7, curcol = 0, linecount = 11}, + [2] = {win = {id = 1000}, topline = 2, botline = 9, curline = 7, curcol = 0, linecount = 11, sum_scroll_delta = 2}, }} command("split") @@ -2211,8 +2211,8 @@ describe('ext_multigrid', function() reprehenderit in voluptate velit esse cillum | ^dolore eu fugiat nulla pariatur. Excepteur sint | ]], win_viewport={ - [2] = {win = {id = 1000}, topline = 6, botline = 9, curline = 7, curcol = 0, linecount = 11}, - [4] = {win = {id = 1001}, topline = 5, botline = 9, curline = 7, curcol = 0, linecount = 11}, + [2] = {win = {id = 1000}, topline = 6, botline = 9, curline = 7, curcol = 0, linecount = 11, sum_scroll_delta = 6}, + [4] = {win = {id = 1001}, topline = 5, botline = 9, curline = 7, curcol = 0, linecount = 11, sum_scroll_delta = 5}, }} feed("b") @@ -2236,8 +2236,8 @@ describe('ext_multigrid', function() reprehenderit in voluptate velit esse ^cillum | dolore eu fugiat nulla pariatur. Excepteur sint | ]], win_viewport={ - [2] = {win = {id = 1000}, topline = 6, botline = 9, curline = 7, curcol = 0, linecount = 11}, - [4] = {win = {id = 1001}, topline = 5, botline = 9, curline = 6, curcol = 38, linecount = 11}, + [2] = {win = {id = 1000}, topline = 6, botline = 9, curline = 7, curcol = 0, linecount = 11, sum_scroll_delta = 6}, + [4] = {win = {id = 1001}, topline = 5, botline = 9, curline = 6, curcol = 38, linecount = 11, sum_scroll_delta = 5}, }} feed("2k") @@ -2261,8 +2261,8 @@ describe('ext_multigrid', function() ea commodo consequat. Duis aute irure dolor in | reprehenderit in voluptate velit esse cillum | ]], win_viewport={ - [2] = {win = {id = 1000}, topline = 6, botline = 9, curline = 7, curcol = 0, linecount = 11}, - [4] = {win = {id = 1001}, topline = 4, botline = 8, curline = 4, curcol = 38, linecount = 11}, + [2] = {win = {id = 1000}, topline = 6, botline = 9, curline = 7, curcol = 0, linecount = 11, sum_scroll_delta = 6}, + [4] = {win = {id = 1001}, topline = 4, botline = 8, curline = 4, curcol = 38, linecount = 11, sum_scroll_delta = 4}, }} -- handles non-current window @@ -2287,8 +2287,59 @@ describe('ext_multigrid', function() ea commodo consequat. Duis aute irure dolor in | reprehenderit in voluptate velit esse cillum | ]], win_viewport={ - [2] = {win = {id = 1000}, topline = 0, botline = 3, curline = 0, curcol = 10, linecount = 11}, - [4] = {win = {id = 1001}, topline = 4, botline = 8, curline = 4, curcol = 38, linecount = 11}, + [2] = {win = {id = 1000}, topline = 0, botline = 3, curline = 0, curcol = 10, linecount = 11, sum_scroll_delta = 0}, + [4] = {win = {id = 1001}, topline = 4, botline = 8, curline = 4, curcol = 38, linecount = 11, sum_scroll_delta = 4}, + }} + + -- sum_scroll_delta works with folds + feed('zfj') + screen:expect{grid=[[ + ## grid 1 + [4:------------------------------------------------]| + [4:------------------------------------------------]| + [4:------------------------------------------------]| + {11:[No Name] [+] }| + [2:------------------------------------------------]| + [2:------------------------------------------------]| + {12:[No Name] [+] }| + [3:------------------------------------------------]| + ## grid 2 + Lorem ipsum dolor sit amet, consectetur | + adipisicing elit, sed do eiusmod tempor | + ## grid 3 + | + ## grid 4 + {13:^+-- 2 lines: exercitation ullamco laboris nisi }| + reprehenderit in voluptate velit esse cillum | + dolore eu fugiat nulla pariatur. Excepteur sint | + ]], win_viewport={ + [2] = {win = {id = 1000}, topline = 0, botline = 3, curline = 0, curcol = 10, linecount = 11, sum_scroll_delta = 0}, + [4] = {win = {id = 1001}, topline = 4, botline = 9, curline = 4, curcol = 38, linecount = 11, sum_scroll_delta = 4}, + }} + + feed('<c-e>') + screen:expect{grid=[[ + ## grid 1 + [4:------------------------------------------------]| + [4:------------------------------------------------]| + [4:------------------------------------------------]| + {11:[No Name] [+] }| + [2:------------------------------------------------]| + [2:------------------------------------------------]| + {12:[No Name] [+] }| + [3:------------------------------------------------]| + ## grid 2 + Lorem ipsum dolor sit amet, consectetur | + adipisicing elit, sed do eiusmod tempor | + ## grid 3 + | + ## grid 4 + ^reprehenderit in voluptate velit esse cillum | + dolore eu fugiat nulla pariatur. Excepteur sint | + occaecat cupidatat non proident, sunt in culpa | + ]], win_viewport={ + [2] = {win = {id = 1000}, topline = 0, botline = 3, curline = 0, curcol = 10, linecount = 11, sum_scroll_delta = 0}, + [4] = {win = {id = 1001}, topline = 6, botline = 10, curline = 6, curcol = 0, linecount = 11, sum_scroll_delta = 5}, }} end) @@ -2314,7 +2365,7 @@ describe('ext_multigrid', function() ## grid 3 | ]], win_viewport={ - [2] = {win = { id = 1000 }, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1} + [2] = {win = { id = 1000 }, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0} }} insert([[ Lorem ipsum dolor sit amet, consectetur @@ -2349,7 +2400,7 @@ describe('ext_multigrid', function() ## grid 3 | ]], win_viewport={ - [2] = {win = {id = 1000}, topline = 5, botline = 11, curline = 10, curcol = 7, linecount = 11}, + [2] = {win = {id = 1000}, topline = 5, botline = 11, curline = 10, curcol = 7, linecount = 11, sum_scroll_delta = 5}, }} meths.input_mouse('left', 'press', '', 1,5, 1) @@ -2376,7 +2427,7 @@ describe('ext_multigrid', function() ## grid 3 {7:-- VISUAL --} | ]], win_viewport={ - [2] = {win = {id = 1000}, topline = 6, botline = 12, curline = 10, curcol = 1, linecount = 11}, + [2] = {win = {id = 1000}, topline = 6, botline = 12, curline = 10, curcol = 1, linecount = 11, sum_scroll_delta = 6}, }} end) @@ -2414,8 +2465,8 @@ describe('ext_multigrid', function() {1:~ }| {1:~ }| ]], win_viewport={ - [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1}; - [4] = {win = {id = 1001}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1}; + [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0}; + [4] = {win = {id = 1001}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0}; }} -- XXX: hack to get notifications. Could use next_msg() also. @@ -2459,8 +2510,8 @@ describe('ext_multigrid', function() {1:~ }| {1:~ }| ]], win_viewport={ - [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1}; - [4] = {win = {id = 1001}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1}; + [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0}; + [4] = {win = {id = 1001}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0}; }} eq({}, win_pos) @@ -2497,8 +2548,8 @@ describe('ext_multigrid', function() {1:~ }| {1:~ }| ]], win_viewport={ - [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1}; - [4] = {win = {id = 1001}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1}; + [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0}; + [4] = {win = {id = 1001}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0}; }} eq({}, win_pos) end) diff --git a/test/functional/ui/output_spec.lua b/test/functional/ui/output_spec.lua index 223844405e..954431d689 100644 --- a/test/functional/ui/output_spec.lua +++ b/test/functional/ui/output_spec.lua @@ -54,6 +54,7 @@ describe("shell command :!", function() it("throttles shell-command output greater than ~10KB", function() skip(is_os('openbsd'), 'FIXME #10804') + skip(is_os('win')) child_session.feed_data((":!%s REP 30001 foo\n"):format(testprg('shell-test'))) -- If we observe any line starting with a dot, then throttling occurred. diff --git a/test/functional/ui/screen.lua b/test/functional/ui/screen.lua index e5a449fa66..f5ae9c8e89 100644 --- a/test/functional/ui/screen.lua +++ b/test/functional/ui/screen.lua @@ -803,14 +803,17 @@ function Screen:_handle_win_pos(grid, win, startrow, startcol, width, height) self.float_pos[grid] = nil end -function Screen:_handle_win_viewport(grid, win, topline, botline, curline, curcol, linecount) +function Screen:_handle_win_viewport(grid, win, topline, botline, curline, curcol, linecount, scroll_delta) + -- accumulate scroll delta + local last_scroll_delta = self.win_viewport[grid] and self.win_viewport[grid].sum_scroll_delta or 0 self.win_viewport[grid] = { win = win, topline = topline, botline = botline, curline = curline, curcol = curcol, - linecount = linecount + linecount = linecount, + sum_scroll_delta = scroll_delta + last_scroll_delta } end @@ -1348,7 +1351,7 @@ local function fmt_ext_state(name, state) for k,v in pairs(state) do str = (str.." ["..k.."] = {win = {id = "..v.win.id.."}, topline = " ..v.topline..", botline = "..v.botline..", curline = "..v.curline - ..", curcol = "..v.curcol..", linecount = "..v.linecount.."};\n") + ..", curcol = "..v.curcol..", linecount = "..v.linecount..", scroll_delta = "..v.scroll_delta.."};\n") end return str .. "}" elseif name == "float_pos" then diff --git a/test/functional/ui/searchhl_spec.lua b/test/functional/ui/searchhl_spec.lua index 916a5eb537..3c8dceb8cb 100644 --- a/test/functional/ui/searchhl_spec.lua +++ b/test/functional/ui/searchhl_spec.lua @@ -52,7 +52,7 @@ describe('search highlighting', function() {1:~ }| /text^ | ]], win_viewport={ - [2] = {win = {id = 1000}, topline = 0, botline = 3, curline = 0, curcol = 9, linecount = 2}; + [2] = {win = {id = 1000}, topline = 0, botline = 3, curline = 0, curcol = 9, linecount = 2, sum_scroll_delta = 0}; }} end) @@ -616,7 +616,7 @@ describe('search highlighting', function() {1:~ }| {4:search hit BOTTOM, continuing at TOP} | ]], win_viewport={ - [2] = {win = {id = 1000}, topline = 0, botline = 3, curline = 0, curcol = 11, linecount = 2}; + [2] = {win = {id = 1000}, topline = 0, botline = 3, curline = 0, curcol = 11, linecount = 2, sum_scroll_delta = 0}; }} -- check highlights work also in folds diff --git a/test/old/testdir/runnvim.vim b/test/old/testdir/runnvim.vim index a46e2d3fc0..2db60d05b3 100644 --- a/test/old/testdir/runnvim.vim +++ b/test/old/testdir/runnvim.vim @@ -23,11 +23,13 @@ function Main() set lines=25 set columns=80 enew - let job = termopen(args, s:logger) + " FIXME: using termopen() hangs on Windows CI + let job = has('win32') ? jobstart(args, s:logger) : termopen(args, s:logger) let results = jobwait([job], 5 * 60 * 1000) " TODO(ZyX-I): Get colors let screen = getline(1, '$') - bwipeout! " kills the job always. + call jobstop(job) " kills the job always. + bwipeout! let stringified_events = map(s:logger.d_events, \'v:val[0] . ": " . ' . \'join(map(v:val[1], '. diff --git a/test/old/testdir/sautest/autoload/sourced.vim b/test/old/testdir/sautest/autoload/sourced.vim index f69f00cb53..aac96b11ce 100644 --- a/test/old/testdir/sautest/autoload/sourced.vim +++ b/test/old/testdir/sautest/autoload/sourced.vim @@ -1,3 +1,4 @@ let g:loaded_sourced_vim += 1 -func! sourced#something() +func sourced#something() endfunc +call sourced#something() diff --git a/test/old/testdir/test_excmd.vim b/test/old/testdir/test_excmd.vim index 44bed890f5..15c83709ad 100644 --- a/test/old/testdir/test_excmd.vim +++ b/test/old/testdir/test_excmd.vim @@ -237,7 +237,6 @@ endfunc " Test for the :language command func Test_language_cmd() - CheckNotMSWindows " FIXME: why does this fail on Windows CI? CheckFeature multi_lang call assert_fails('language ctype non_existing_lang', 'E197:') diff --git a/test/old/testdir/test_mksession.vim b/test/old/testdir/test_mksession.vim index 972397cb91..f60d89faae 100644 --- a/test/old/testdir/test_mksession.vim +++ b/test/old/testdir/test_mksession.vim @@ -943,15 +943,16 @@ func Test_mkvimrc() " the 'pastetoggle', 'wildchar' and 'wildcharm' option values should be " stored as key names in the vimrc file - set pastetoggle=<F5> + " set pastetoggle=<F5> set wildchar=<F6> set wildcharm=<F7> call assert_fails('mkvimrc Xtestvimrc') mkvimrc! Xtestvimrc - call assert_notequal(-1, index(readfile('Xtestvimrc'), 'set pastetoggle=<F5>')) + " call assert_notequal(-1, index(readfile('Xtestvimrc'), 'set pastetoggle=<F5>')) call assert_notequal(-1, index(readfile('Xtestvimrc'), 'set wildchar=<F6>')) call assert_notequal(-1, index(readfile('Xtestvimrc'), 'set wildcharm=<F7>')) - set pastetoggle& wildchar& wildcharm& + " set pastetoggle& wildchar& wildcharm& + set wildchar& wildcharm& call delete('Xtestvimrc') endfunc diff --git a/test/old/testdir/test_options.vim b/test/old/testdir/test_options.vim index b6b982e92e..d18802adc1 100644 --- a/test/old/testdir/test_options.vim +++ b/test/old/testdir/test_options.vim @@ -49,6 +49,7 @@ endfunc " Test for getting the value of 'pastetoggle' func Test_pastetoggle() + throw "Skipped: 'pastetoggle' is removed from Nvim" " character with K_SPECIAL byte let &pastetoggle = '…' call assert_equal('…', &pastetoggle) diff --git a/test/old/testdir/test_paste.vim b/test/old/testdir/test_paste.vim index 923f4f42a6..9ed3adca9b 100644 --- a/test/old/testdir/test_paste.vim +++ b/test/old/testdir/test_paste.vim @@ -1,21 +1,4 @@ -" Test for 'pastetoggle' -func Test_pastetoggle() - new - set pastetoggle=<F4> - set nopaste - call feedkeys("iHello\<F4>", 'xt') - call assert_true(&paste) - call feedkeys("i\<F4>", 'xt') - call assert_false(&paste) - call assert_equal('Hello', getline(1)) - " command-line completion for 'pastetoggle' value - call feedkeys(":set pastetoggle=\<Tab>\<C-B>\"\<CR>", 'xt') - call assert_equal('"set pastetoggle=<F4>', @:) - set pastetoggle& - bwipe! -endfunc - " Test for restoring option values when 'paste' is disabled func Test_paste_opt_restore() set autoindent expandtab ruler showmatch diff --git a/test/old/testdir/test_sort.vim b/test/old/testdir/test_sort.vim index 534393b724..94a35e3cb5 100644 --- a/test/old/testdir/test_sort.vim +++ b/test/old/testdir/test_sort.vim @@ -12,7 +12,6 @@ func Compare2(a, b) abort endfunc func Test_sort_strings() - CheckNotMSWindows " FIXME: Why does this fail with MSVC? " numbers compared as strings call assert_equal([1, 2, 3], sort([3, 2, 1])) call assert_equal([13, 28, 3], sort([3, 28, 13])) diff --git a/test/old/testdir/test_spell_utf8.vim b/test/old/testdir/test_spell_utf8.vim index 7c588d736a..91ada1ed38 100644 --- a/test/old/testdir/test_spell_utf8.vim +++ b/test/old/testdir/test_spell_utf8.vim @@ -624,7 +624,6 @@ endfunc " Test affix flags with two characters func Test_spell_affix() - CheckNotMSWindows " FIXME: Why does this fail with MSVC? call LoadAffAndDic(g:test_data_aff5, g:test_data_dic5) call RunGoodBad("fooa1 fooa\u00E9 bar prebar barbork prebarbork startprebar start end startend startmiddleend nouend", \ "bad: foo fooa2 prabar probarbirk middle startmiddle middleend endstart startprobar startnouend", |